| #region License |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #endregion |
| |
| using System; |
| using System.Collections.Generic; |
| using System.Numerics; |
| using Gremlin.Net.Process.Traversal; |
| using Gremlin.Net.Process.Traversal.Strategy.Decoration; |
| using Gremlin.Net.Structure; |
| using Gremlin.Net.Structure.IO.GraphSON; |
| using Moq; |
| using Xunit; |
| |
| namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON |
| { |
| public class GraphSONWriterTests |
| { |
| /// <summary> |
| /// Parameters for each test supporting multiple versions of GraphSON |
| /// </summary> |
| public static IEnumerable<object[]> Versions => new [] |
| { |
| new object[] { 2 }, |
| new object[] { 3 } |
| }; |
| |
| /// <summary> |
| /// Parameters for each collections test supporting multiple versions of GraphSON |
| /// </summary> |
| public static IEnumerable<object[]> VersionsSupportingCollections => new [] |
| { |
| new object[] { 3 } |
| }; |
| |
| /// <summary> |
| /// Parameters for each collections test supporting multiple versions of GraphSON |
| /// </summary> |
| public static IEnumerable<object[]> VersionsNotSupportingCollections => new [] |
| { |
| new object[] { 2 } |
| }; |
| |
| private GraphSONWriter CreateGraphSONWriter(int version) |
| { |
| if (version == 3) |
| { |
| return new GraphSON3Writer(); |
| } |
| return new GraphSON2Writer(); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeInt(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject(1); |
| |
| Assert.Equal("{\"@type\":\"g:Int32\",\"@value\":1}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeLong(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject((long) 2); |
| |
| Assert.Equal("{\"@type\":\"g:Int64\",\"@value\":2}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeFloat(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject((float) 3.2); |
| |
| Assert.Equal("{\"@type\":\"g:Float\",\"@value\":3.2}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeDouble(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject(3.2); |
| |
| Assert.Equal("{\"@type\":\"g:Double\",\"@value\":3.2}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeNaN(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject(Double.NaN); |
| |
| Assert.Equal("{\"@type\":\"g:Double\",\"@value\":\"NaN\"}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializePositiveInfinity(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject(Double.PositiveInfinity); |
| |
| Assert.Equal("{\"@type\":\"g:Double\",\"@value\":\"Infinity\"}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeNegativeInfinity(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject(Double.NegativeInfinity); |
| |
| Assert.Equal("{\"@type\":\"g:Double\",\"@value\":\"-Infinity\"}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeDecimal(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject(6.5M); |
| |
| Assert.Equal("{\"@type\":\"gx:BigDecimal\",\"@value\":\"6.5\"}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeBoolean(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject(true); |
| |
| Assert.Equal("true", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeArray(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var array = new[] {5, 6}; |
| |
| var serializedGraphSON = writer.WriteObject(array); |
| |
| var expectedGraphSON = "[{\"@type\":\"g:Int32\",\"@value\":5},{\"@type\":\"g:Int32\",\"@value\":6}]"; |
| Assert.Equal(expectedGraphSON, serializedGraphSON); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeBinding(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var binding = new Binding("theKey", 123); |
| |
| var graphSon = writer.WriteObject(binding); |
| |
| const string expected = |
| "{\"@type\":\"g:Binding\",\"@value\":{\"value\":{\"@type\":\"g:Int32\",\"@value\":123},\"key\":\"theKey\"}}"; |
| Assert.Equal(expected, graphSon); |
| } |
| |
| [Fact] |
| public void ShouldSerializeWithCustomSerializerForNewType() |
| { |
| var customSerializerByType = new Dictionary<Type, IGraphSONSerializer> |
| { |
| {typeof(TestClass), new TestGraphSONSerializer {TestNamespace = "NS"}} |
| }; |
| var writer = new GraphSON2Writer(customSerializerByType); |
| var testObj = new TestClass {Value = "test"}; |
| |
| var serialized = writer.WriteObject(testObj); |
| |
| Assert.Equal("{\"@type\":\"NS:TestClass\",\"@value\":\"test\"}", serialized); |
| } |
| |
| [Fact] |
| public void ShouldSerializeWithCustomSerializerForCommonType() |
| { |
| var customSerializerMock = new Mock<IGraphSONSerializer>(); |
| var customSerializerByType = new Dictionary<Type, IGraphSONSerializer> |
| { |
| {typeof(int), customSerializerMock.Object} |
| }; |
| var writer = new GraphSON2Writer(customSerializerByType); |
| |
| writer.WriteObject(12); |
| |
| customSerializerMock.Verify(m => m.Dictify(It.Is<int>(v => v == 12), It.IsAny<GraphSONWriter>())); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeDateTimeOffset(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var dateTimeOffset = TestUtils.FromJavaTime(1475583442552); |
| |
| var graphSon = writer.WriteObject(dateTimeOffset); |
| |
| const string expected = "{\"@type\":\"g:Date\",\"@value\":1475583442552}"; |
| Assert.Equal(expected, graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeDictionary(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var dictionary = new Dictionary<string, dynamic> |
| { |
| {"age", new List<int> {29}}, |
| {"name", new List<string> {"marko"}} |
| }; |
| |
| var serializedDict = writer.WriteObject(dictionary); |
| |
| var expectedGraphSON = "{\"age\":[{\"@type\":\"g:Int32\",\"@value\":29}],\"name\":[\"marko\"]}"; |
| Assert.Equal(expectedGraphSON, serializedDict); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeEdge(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var edge = new Edge(7, new Vertex(0, "person"), "knows", new Vertex(1, "dog")); |
| |
| var graphSON = writer.WriteObject(edge); |
| |
| const string expected = |
| "{\"@type\":\"g:Edge\",\"@value\":{\"id\":{\"@type\":\"g:Int32\",\"@value\":7},\"outV\":{\"@type\":\"g:Int32\",\"@value\":0},\"outVLabel\":\"person\",\"label\":\"knows\",\"inV\":{\"@type\":\"g:Int32\",\"@value\":1},\"inVLabel\":\"dog\"}}"; |
| Assert.Equal(expected, graphSON); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeEnum(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var serializedEnum = writer.WriteObject(Direction.Both); |
| |
| var expectedGraphSON = "{\"@type\":\"g:Direction\",\"@value\":\"BOTH\"}"; |
| Assert.Equal(expectedGraphSON, serializedEnum); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeList(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var list = new List<int> {5, 6}; |
| |
| var serializedGraphSON = writer.WriteObject(list.ToArray()); |
| |
| var expectedGraphSON = "[{\"@type\":\"g:Int32\",\"@value\":5},{\"@type\":\"g:Int32\",\"@value\":6}]"; |
| Assert.Equal(expectedGraphSON, serializedGraphSON); |
| } |
| |
| [Theory, MemberData(nameof(VersionsSupportingCollections))] |
| public void ShouldSerializeGList(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var list = new List<object> {5, 6}; |
| |
| var serializedGraphSON = writer.WriteObject(list); |
| |
| var expectedGraphSON = "{\"@type\":\"g:List\",\"@value\":[{\"@type\":\"g:Int32\",\"@value\":5}," + |
| "{\"@type\":\"g:Int32\",\"@value\":6}]}"; |
| Assert.Equal(expectedGraphSON, serializedGraphSON); |
| } |
| |
| [Theory, MemberData(nameof(VersionsSupportingCollections))] |
| public void ShouldSerializeGSet(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| ISet<object> set = new HashSet<object> {600L, 700L}; |
| |
| var serializedGraphSON = writer.WriteObject(set); |
| |
| var expectedGraphSON = "{\"@type\":\"g:Set\",\"@value\":[{\"@type\":\"g:Int64\",\"@value\":600}," + |
| "{\"@type\":\"g:Int64\",\"@value\":700}]}"; |
| Assert.Equal(expectedGraphSON, serializedGraphSON); |
| } |
| |
| [Theory, MemberData(nameof(VersionsSupportingCollections))] |
| public void ShouldSerializeGMap(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| IDictionary<object, object> map = new Dictionary<object, object> { { 1L, "a"}, { 200L, "b"}}; |
| |
| var serializedGraphSON = writer.WriteObject(map); |
| |
| var expectedGraphSON = "{\"@type\":\"g:Map\",\"@value\":[{\"@type\":\"g:Int64\",\"@value\":1},\"a\"," + |
| "{\"@type\":\"g:Int64\",\"@value\":200},\"b\"]}"; |
| Assert.Equal(expectedGraphSON, serializedGraphSON); |
| } |
| |
| [Theory, MemberData(nameof(VersionsNotSupportingCollections))] |
| public void ShouldSerializePredicateWithMultipleValuesAsJSONArray(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var predicate = new P("within", new List<int> {1, 2}); |
| |
| var serializedPredicate = writer.WriteObject(predicate); |
| |
| var expectedGraphSON = |
| "{\"@type\":\"g:P\",\"@value\":{\"predicate\":\"within\",\"value\":[{\"@type\":\"g:Int32\",\"@value\":1},{\"@type\":\"g:Int32\",\"@value\":2}]}}"; |
| Assert.Equal(expectedGraphSON, serializedPredicate); |
| |
| predicate = P.Within(1, 2); |
| |
| serializedPredicate = writer.WriteObject(predicate); |
| |
| Assert.Equal(expectedGraphSON, serializedPredicate); |
| } |
| |
| [Theory, MemberData(nameof(VersionsSupportingCollections))] |
| public void ShouldSerializePredicateWithMultipleValues(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var predicate = P.Within(new List<int> {1, 2}); |
| |
| var serializedPredicate = writer.WriteObject(predicate); |
| |
| var expectedGraphSON = |
| "{\"@type\":\"g:P\",\"@value\":{\"predicate\":\"within\",\"value\":{\"@type\":\"g:List\",\"@value\":[{\"@type\":\"g:Int32\",\"@value\":1},{\"@type\":\"g:Int32\",\"@value\":2}]}}}"; |
| Assert.Equal(expectedGraphSON, serializedPredicate); |
| |
| predicate = P.Within(1, 2); |
| |
| serializedPredicate = writer.WriteObject(predicate); |
| |
| Assert.Equal(expectedGraphSON, serializedPredicate); |
| |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializePredicateWithSingleValue(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var predicate = new P("lt", 5); |
| |
| var serializedPredicate = writer.WriteObject(predicate); |
| |
| var expectedGraphSON = |
| "{\"@type\":\"g:P\",\"@value\":{\"predicate\":\"lt\",\"value\":{\"@type\":\"g:Int32\",\"@value\":5}}}"; |
| Assert.Equal(expectedGraphSON, serializedPredicate); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializePropertyWithEdgeElement(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var property = new Property("aKey", "aValue", new Edge("anId", new Vertex(1), "edgeLabel", new Vertex(2))); |
| |
| var graphSON = writer.WriteObject(property); |
| |
| const string expected = |
| "{\"@type\":\"g:Property\",\"@value\":{\"key\":\"aKey\",\"value\":\"aValue\",\"element\":{\"@type\":\"g:Edge\",\"@value\":{\"id\":\"anId\",\"outV\":{\"@type\":\"g:Int32\",\"@value\":1},\"label\":\"edgeLabel\",\"inV\":{\"@type\":\"g:Int32\",\"@value\":2}}}}}"; |
| Assert.Equal(expected, graphSON); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializePropertyWithVertexPropertyElement(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var property = new Property("name", "marko", |
| new VertexProperty("anId", "aKey", 21345, new Vertex("vertexId"))); |
| |
| var graphSON = writer.WriteObject(property); |
| |
| const string expected = |
| "{\"@type\":\"g:Property\",\"@value\":{\"key\":\"name\",\"value\":\"marko\",\"element\":{\"@type\":\"g:VertexProperty\",\"@value\":{\"id\":\"anId\",\"label\":\"aKey\",\"vertex\":\"vertexId\"}}}}"; |
| Assert.Equal(expected, graphSON); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeVertexProperty(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var vertexProperty = new VertexProperty("blah", "keyA", true, new Vertex("stephen")); |
| |
| var graphSON = writer.WriteObject(vertexProperty); |
| |
| const string expected = |
| "{\"@type\":\"g:VertexProperty\",\"@value\":{\"id\":\"blah\",\"label\":\"keyA\",\"value\":true,\"vertex\":\"stephen\"}}"; |
| Assert.Equal(expected, graphSON); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeGuid(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var guid = Guid.Parse("41d2e28a-20a4-4ab0-b379-d810dede3786"); |
| |
| var graphSon = writer.WriteObject(guid); |
| |
| const string expected = "{\"@type\":\"g:UUID\",\"@value\":\"41d2e28a-20a4-4ab0-b379-d810dede3786\"}"; |
| Assert.Equal(expected, graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeVertex(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var vertex = new Vertex(45.23f); |
| |
| var graphSON = writer.WriteObject(vertex); |
| |
| const string expected = |
| "{\"@type\":\"g:Vertex\",\"@value\":{\"id\":{\"@type\":\"g:Float\",\"@value\":45.23},\"label\":\"vertex\"}}"; |
| Assert.Equal(expected, graphSON); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeVertexWithLabel(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var vertex = new Vertex((long) 123, "project"); |
| |
| var graphSON = writer.WriteObject(vertex); |
| |
| const string expected = |
| "{\"@type\":\"g:Vertex\",\"@value\":{\"id\":{\"@type\":\"g:Int64\",\"@value\":123},\"label\":\"project\"}}"; |
| Assert.Equal(expected, graphSON); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeTypeToItsObject(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var type = typeof(SubgraphStrategy); |
| |
| var graphSon = writer.WriteObject(type); |
| |
| const string expected = "{\"@type\":\"g:SubgraphStrategy\",\"@value\":{}}"; |
| Assert.Equal(expected, graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeLambda(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var lambda = Lambda.Groovy("{ it.get() }"); |
| |
| var graphSon = writer.WriteObject(lambda); |
| |
| const string expected = |
| "{\"@type\":\"g:Lambda\",\"@value\":{\"script\":\"{ it.get() }\",\"language\":\"gremlin-groovy\",\"arguments\":-1}}"; |
| Assert.Equal(expected, graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeTimeSpan(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var timeSpan = new TimeSpan(5, 4, 3, 2, 1); |
| |
| var graphSon = writer.WriteObject(timeSpan); |
| |
| const string expected = "{\"@type\":\"gx:Duration\",\"@value\":\"P5DT4H3M2.001S\"}"; |
| Assert.Equal(expected, graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeBigInteger(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| var bigInteger = BigInteger.Parse("123456789987654321123456789987654321"); |
| |
| var graphSon = writer.WriteObject(bigInteger); |
| |
| const string expected = "{\"@type\":\"gx:BigInteger\",\"@value\":\"123456789987654321123456789987654321\"}"; |
| Assert.Equal(expected, graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeByte(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject((byte)1); |
| |
| Assert.Equal("{\"@type\":\"gx:Byte\",\"@value\":1}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeByteBuffer(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject(Convert.FromBase64String("c29tZSBieXRlcyBmb3IgeW91")); |
| |
| Assert.Equal("{\"@type\":\"gx:ByteBuffer\",\"@value\":\"c29tZSBieXRlcyBmb3IgeW91\"}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeChar(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject('x'); |
| |
| Assert.Equal("{\"@type\":\"gx:Char\",\"@value\":\"x\"}", graphSon); |
| } |
| |
| [Theory, MemberData(nameof(Versions))] |
| public void ShouldSerializeInt16(int version) |
| { |
| var writer = CreateGraphSONWriter(version); |
| |
| var graphSon = writer.WriteObject((short)100); |
| |
| Assert.Equal("{\"@type\":\"gx:Int16\",\"@value\":100}", graphSon); |
| } |
| } |
| |
| internal class TestGraphSONSerializer : IGraphSONSerializer |
| { |
| public string TestNamespace { get; set; } |
| |
| public Dictionary<string, dynamic> Dictify(dynamic objectData, GraphSONWriter writer) |
| { |
| return GraphSONUtil.ToTypedValue(nameof(TestClass), objectData.Value, TestNamespace); |
| } |
| } |
| } |