Merge branch 'tp32' Conflicts: gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/a7d01e2e Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/a7d01e2e Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/a7d01e2e Branch: refs/heads/master Commit: a7d01e2e2ff0b958e11662998b901633a6a88a8a Parents: 1967409 6e60a29 Author: Jorge Bay Gondra <jorgebaygon...@gmail.com> Authored: Tue Dec 5 14:49:08 2017 +0100 Committer: Jorge Bay Gondra <jorgebaygon...@gmail.com> Committed: Tue Dec 5 14:49:08 2017 +0100 ---------------------------------------------------------------------- .../src/Gremlin.Net/Driver/GremlinClient.cs | 5 + .../Process/Traversal/DefaultTraversal.cs | 5 + .../Gremlin.Net/Process/Traversal/ITraversal.cs | 11 +- .../Process/Traversal/Instruction.cs | 2 +- .../Structure/IO/GraphSON/DecimalConverter.cs | 35 ++ .../Structure/IO/GraphSON/GraphSONReader.cs | 21 +- .../Structure/IO/GraphSON/GraphSONWriter.cs | 1 + .../Structure/IO/GraphSON/NumberConverter.cs | 9 +- .../Gherkin/Attributes/BddAttribute.cs | 37 ++ .../Gherkin/Attributes/GivenAttribute.cs | 33 ++ .../Gherkin/Attributes/ThenAttribute.cs | 33 ++ .../Gherkin/Attributes/WhenAttribute.cs | 33 ++ .../Gherkin/CommonSteps.cs | 321 +++++++++++++ .../Gherkin/GherkinTestRunner.cs | 381 +++++++++++++++ .../Gherkin/IgnoreException.cs | 55 +++ .../Gherkin/ScenarioData.cs | 168 +++++++ .../Gherkin/StepDefinition.cs | 39 ++ .../ContextBasedParameter.cs | 83 ++++ .../TraversalEvaluation/ITokenParameter.cs | 46 ++ .../TraversalEvaluation/LiteralParameter.cs | 87 ++++ .../ModernGraphTypeInformation.cs | 89 ++++ .../StaticTraversalParameter.cs | 77 +++ .../TraversalEvaluation/StringParameter.cs | 85 ++++ .../Gherkin/TraversalEvaluation/Token.cs | 92 ++++ .../TraversalEnumParameter.cs | 103 ++++ .../TraversalEvaluationTests.cs | 114 +++++ .../TraversalEvaluation/TraversalParser.cs | 474 +++++++++++++++++++ .../TraversalPredicateParameter.cs | 93 ++++ .../Gremlin.Net.IntegrationTest.csproj | 12 +- .../GraphTraversalTests.cs | 17 - .../RemoteConnectionFactory.cs | 22 +- .../DriverRemoteConnection/SideEffectTests.cs | 57 --- .../IO/GraphSON/GraphSONReaderTests.cs | 24 + .../IO/GraphSON/GraphSONWriterTests.cs | 10 + gremlin-test/features/branch/Local.feature | 149 +----- gremlin-test/features/map/Match.feature | 12 +- gremlin-test/features/sideEffect/Group.feature | 2 +- 37 files changed, 2587 insertions(+), 250 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs ---------------------------------------------------------------------- diff --cc gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs index a251ab7,46dd8a6..2b47cbc --- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs @@@ -34,11 -34,6 +34,16 @@@ namespace Gremlin.Net.Drive /// </summary> public class GremlinClient : IGremlinClient { + /// <summary> + /// Defines the default mime type to use. + /// </summary> + public const string DefaultMimeType = "application/vnd.gremlin-v3.0+json"; ++ ++ /// <summary> ++ /// The GraphSON2 mime type to use. ++ /// </summary> ++ public const string GraphSON2MimeType = "application/vnd.gremlin-v2.0+json"; + private readonly ConnectionPool _connectionPool; /// <summary> http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs ---------------------------------------------------------------------- diff --cc gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs index ffe9266,db03dd4..fbec67d --- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs @@@ -89,12 -87,20 +90,20 @@@ namespace Gremlin.Net.Structure.IO.Grap /// </summary> /// <param name="jToken">The GraphSON to deserialize.</param> /// <returns>The deserialized object.</returns> - public dynamic ToObject(JToken jToken) + public virtual dynamic ToObject(JToken jToken) { if (jToken is JArray) + { return jToken.Select(t => ToObject(t)); - if (!jToken.HasValues) return ((JValue) jToken).Value; - if (!HasTypeKey(jToken)) return ReadDictionary(jToken); + } + if (jToken is JValue jValue) + { + return jValue.Value; + } + if (!HasTypeKey(jToken)) + { + return ReadDictionary(jToken); + } return ReadTypedValue(jToken); } @@@ -107,7 -113,11 +116,11 @@@ private dynamic ReadTypedValue(JToken typedValue) { var graphSONType = (string) typedValue[GraphSONTokens.TypeKey]; - return Deserializers[graphSONType].Objectify(typedValue[GraphSONTokens.ValueKey], this); - if (!_deserializerByGraphSONType.TryGetValue(graphSONType, out var deserializer)) ++ if (!Deserializers.TryGetValue(graphSONType, out var deserializer)) + { + throw new InvalidOperationException($"Deserializer for \"{graphSONType}\" not found"); + } + return deserializer.Objectify(typedValue[GraphSONTokens.ValueKey], this); } private dynamic ReadDictionary(JToken jtokenDict) http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs ---------------------------------------------------------------------- diff --cc gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs index 0000000,0abc247..9caca1f mode 000000,100644..100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs @@@ -1,0 -1,321 +1,321 @@@ + #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; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Text.RegularExpressions; + using Gherkin.Ast; + using Gremlin.Net.IntegrationTest.Gherkin.Attributes; + using Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation; + using Gremlin.Net.Process.Traversal; + using Gremlin.Net.Structure; + using Newtonsoft.Json.Linq; + using Xunit; + + namespace Gremlin.Net.IntegrationTest.Gherkin + { + internal class CommonSteps : StepDefinition + { + private GraphTraversalSource _g; + private string _graphName; + private readonly IDictionary<string, object> _parameters = new Dictionary<string, object>(); + private ITraversal _traversal; + private object[] _result; + + private static readonly IDictionary<Regex, Func<string, string, object>> Parsers = + new Dictionary<string, Func<string, string, object>> + { + {@"d\[([\d.]+)\]\.([ilfdm])", ToNumber}, + {@"v\[(.+)\]", ToVertex}, + {@"v\[(.+)\]\.id", (x, graphName) => ToVertex(x, graphName).Id}, + {@"v\[(.+)\]\.sid", (x, graphName) => ToVertex(x, graphName).Id.ToString()}, + {@"e\[(.+)\]", ToEdge}, + {@"e\[(.+)\].id", (x, graphName) => ToEdge(x, graphName).Id}, + {@"e\[(.+)\].sid", (x, graphName) => ToEdge(x, graphName).Id.ToString()}, + {@"p\[(.+)\]", ToPath}, + {@"l\[(.*)\]", ToList}, + {@"s\[(.*)\]", ToSet}, + {@"m\[(.+)\]", ToMap}, + {@"c\[(.+)\]", ToLambda} + }.ToDictionary(kv => new Regex("^" + kv.Key + "$", RegexOptions.Compiled), kv => kv.Value); + + private static readonly IDictionary<char, Func<string, object>> NumericParsers = + new Dictionary<char, Func<string, object>> + { + { 'i', s => Convert.ToInt32(s) }, + { 'l', s => Convert.ToInt64(s) }, + { 'f', s => Convert.ToSingle(s, CultureInfo.InvariantCulture) }, + { 'd', s => Convert.ToDouble(s, CultureInfo.InvariantCulture) }, + { 'm', s => Convert.ToDecimal(s, CultureInfo.InvariantCulture) } + }; + + [Given("the (\\w+) graph")] + public void ChooseModernGraph(string graphName) + { + if (graphName == "empty") + { + ScenarioData.CleanEmptyData(); + } + var data = ScenarioData.GetByGraphName(graphName); + _graphName = graphName; + _g = new Graph().Traversal().WithRemote(data.Connection); + } + + [Given("using the parameter (\\w+) defined as \"(.*)\"")] + public void UsingParameter(string name, string value) + { + var parsedValue = ParseValue(value, _graphName); + _parameters.Add(name, parsedValue); + } + + [Given("the traversal of")] + public void TranslateTraversal(string traversalText) + { + if (_g == null) + { + throw new InvalidOperationException("g should be a traversal source"); + } + _traversal = TraversalParser.GetTraversal(traversalText, _g, _parameters); + } + + [Given("the graph initializer of")] + public void InitTraversal(string traversalText) + { + var traversal = TraversalParser.GetTraversal(traversalText, _g, _parameters); + traversal.Iterate(); + + // We may have modified the so-called `empty` graph + if (_graphName == "empty") + { + ScenarioData.ReloadEmptyData(); + } + } + + [Given("an unsupported test")] + public void UnsupportedTest() + { + + } + + [When("iterated to list")] + public void IterateToList() + { + if (_traversal == null) + { + throw new InvalidOperationException("Traversal should be set before iterating"); + } + ITraversal t = _traversal; + var list = new List<object>(); + while (t.MoveNext()) + { + list.Add(t.Current); + } + _result = list.ToArray(); + } + + [When("iterated next")] + public void IterateNext() + { + if (_traversal == null) + { + throw new InvalidOperationException("Traversal should be set before iterating"); + } + _traversal.MoveNext(); + var result = _traversal.Current; + switch (result) + { + case null: + _result = null; + return; + case object[] arrayResult: + _result = arrayResult; + return; + case IEnumerable enumerableResult: + _result = enumerableResult.Cast<object>().ToArray(); + return; + } + throw new InvalidCastException($"Can not convert instance of {result.GetType()} to object[]"); + } + + [Then("the result should be (\\w+)")] + public void AssertResult(string characterizedAs, DataTable table = null) + { + var ordered = characterizedAs == "ordered"; + switch (characterizedAs) + { + case "empty": + Assert.Equal(0, _result.Length); + return; + case "ordered": + case "unordered": + case "of": + Assert.NotNull(table); + var rows = table.Rows.ToArray(); + Assert.Equal("result", rows[0].Cells.First().Value); + var expected = rows.Skip(1).Select(x => ParseValue(x.Cells.First().Value, _graphName)); + if (ordered) + { + Assert.Equal(expected, _result); + } + else + { + var expectedArray = expected.ToArray(); + foreach (var resultItem in _result) + { + Assert.Contains(resultItem, expectedArray); + } + if (characterizedAs != "of") + { + Assert.Equal(expectedArray.Length, _result.Length); + } + } + break; + default: + throw new NotSupportedException($"Result as '{characterizedAs}' not supported"); + } + } + + [Then("the result should have a count of (\\d+)")] + public void AssertCount(int count) + { + Assert.Equal(count, _result.Length); + } + + [Then("the graph should return (\\d+) for count of (.+)")] + public void AssertTraversalCount(int expectedCount, string traversalText) + { + if (traversalText.StartsWith("\"")) + { + traversalText = traversalText.Substring(1, traversalText.Length - 2); + } + var traversal = TraversalParser.GetTraversal(traversalText, _g, _parameters); + var count = 0; + while (traversal.MoveNext()) + { + count++; + } + Assert.Equal(expectedCount, count); + } + + [Then("nothing should happen because")] + public void AssertNothing(string reason) + { + + } + + private static object ToMap(string stringMap, string graphName) + { + return ParseMapValue(JObject.Parse(stringMap), graphName); + } + + private static object ToLambda(string stringLambda, string graphName) + { + throw new IgnoreException(IgnoreReason.LambdaNotSupported); + } + + private static object ToNumber(string stringNumber, string graphName) + { + return NumericParsers[stringNumber[stringNumber.Length - 1]]( + stringNumber.Substring(0, stringNumber.Length - 1)); + } + + private static object ParseMapValue(JToken value, string graphName) + { + if (value.Type == JTokenType.Object) + { + IDictionary<string, JToken> jsonMap = (JObject)value; + return jsonMap.ToDictionary(kv => kv.Key, kv => ParseMapValue(kv.Value, graphName)); + } + if (value.Type == JTokenType.Array) + { + return value.Select(v => ParseMapValue(v, graphName)).ToArray(); + } + var objValue = value.ToObject<object>(); + if (objValue is long longValue) + { + // JSON Numeric values converted to int64 by default + return Convert.ToInt32(longValue); + } + if (objValue is string stringValue) + { + return ParseValue(stringValue, graphName); + } + return objValue; + } + + private static ISet<object> ToSet(string stringSet, string graphName) + { + return new HashSet<object>(ToList(stringSet, graphName)); + } + + private static IList<object> ToList(string stringList, string graphName) + { + if (stringList == "") + { + return new List<object>(0); + } + return stringList.Split(',').Select(x => ParseValue(x, graphName)).ToList(); + } + + private static Vertex ToVertex(string name, string graphName) + { + return ScenarioData.GetByGraphName(graphName).Vertices[name]; + } + + private static Edge ToEdge(string name, string graphName) + { + return ScenarioData.GetByGraphName(graphName).Edges[name]; + } + + private static Path ToPath(string value, string graphName) + { - return new Path(new List<List<string>>(0), value.Split(',').Select(x => ParseValue(x, graphName)).ToList()); ++ return new Path(new List<ISet<string>>(0), value.Split(',').Select(x => ParseValue(x, graphName)).ToList()); + } + + private static object ParseValue(string stringValue, string graphName) + { + // Parser issue: quotes are not normalized + stringValue = stringValue.Replace("\\\"", "\""); + Func<string, string, object> parser = null; + string extractedValue = null; + foreach (var kv in Parsers) + { + var match = kv.Key.Match(stringValue); + if (match.Success) + { + parser = kv.Value; + extractedValue = match.Groups[1].Value; + if (match.Groups.Count > 2) + { + extractedValue += match.Groups[2].Value; + } + break; + } + } + return parser != null ? parser(extractedValue, graphName) : stringValue; + } + } + } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/RemoteConnectionFactory.cs ---------------------------------------------------------------------- diff --cc gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/RemoteConnectionFactory.cs index 47d4f06,249db60..276340d --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/RemoteConnectionFactory.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/RemoteConnectionFactory.cs @@@ -22,8 -22,10 +22,11 @@@ #endregion using System; + using System.Collections.Generic; using Gremlin.Net.Driver; using Gremlin.Net.Process.Remote; ++using Gremlin.Net.Structure.IO.GraphSON; + using DriverRemoteConnectionImpl = Gremlin.Net.Driver.Remote.DriverRemoteConnection; namespace Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection { @@@ -40,8 -44,18 +45,19 @@@ public IRemoteConnection CreateRemoteConnection(string traversalSource) { - return new Net.Driver.Remote.DriverRemoteConnection( - new GremlinClient(new GremlinServer(TestHost, TestPort)), traversalSource); + var c = new DriverRemoteConnectionImpl( - new GremlinClient(new GremlinServer(TestHost, TestPort)), traversalSource); ++ new GremlinClient(new GremlinServer(TestHost, TestPort), new GraphSON2Reader(), new GraphSON2Writer(), ++ GremlinClient.GraphSON2MimeType), traversalSource); + _connections.Add(c); + return c; + } + + public void Dispose() + { + foreach (var connection in _connections) + { + connection.Dispose(); + } } } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/SideEffectTests.cs ---------------------------------------------------------------------- diff --cc gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/SideEffectTests.cs index 1ffb924,f100e04..b86615e --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/SideEffectTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/SideEffectTests.cs @@@ -76,46 -74,38 +76,6 @@@ namespace Gremlin.Net.IntegrationTest.P } [Fact] -- public void ShouldReturnSideEffectValueWhenGetIsCalledForGroupCountTraversal() -- { -- var graph = new Graph(); -- var connection = _connectionFactory.CreateRemoteConnection(); -- var g = graph.Traversal().WithRemote(connection); -- var t = g.V().Out("created").GroupCount("m").By("name").Iterate(); -- t.SideEffects.Keys(); - var m = (IList) t.SideEffects.Get("m"); - - var m = t.SideEffects.Get("m") as Dictionary<string, dynamic>; -- -- Assert.Equal(2, m.Count); - var result = new Dictionary<object, object>(); - - foreach (IDictionary map in m) - { - foreach (var key in map.Keys) - { - result.Add(key, map[key]); - } - } - Assert.Equal((long) 3, result["lop"]); - Assert.Equal((long) 1, result["ripple"]); - Assert.Equal((long) 3, m["lop"]); - Assert.Equal((long) 1, m["ripple"]); -- } -- -- [Fact] -- public void ShouldReturnSideEffectValueWhenGetIsCalledOnATraversalWithSideEffect() -- { -- var graph = new Graph(); -- var connection = _connectionFactory.CreateRemoteConnection(); -- var g = graph.Traversal().WithRemote(connection); -- var t = g.WithSideEffect("a", new List<string> {"first", "second"}).V().Iterate(); -- t.SideEffects.Keys(); -- -- var a = t.SideEffects.Get("a") as List<object>; -- -- Assert.Equal(2, a.Count); -- Assert.Equal("first", a[0]); -- Assert.Equal("second", a[1]); -- } -- -- [Fact] public void ShouldThrowWhenGetIsCalledWithAnUnknownKey() { var graph = new Graph(); @@@ -127,23 -117,25 +87,6 @@@ } [Fact] -- public void ShouldReturnBothSideEffectForTraversalWithTwoSideEffects_() -- { -- var graph = new Graph(); -- var connection = _connectionFactory.CreateRemoteConnection(); -- var g = graph.Traversal().WithRemote(connection); -- -- var t = g.V().Out("created").GroupCount("m").By("name").Values<string>("name").Aggregate("n").Iterate(); -- -- var keys = t.SideEffects.Keys().ToList(); -- Assert.Equal(2, keys.Count); -- Assert.Contains("m", keys); -- Assert.Contains("n", keys); - var n = (IList<object>) t.SideEffects.Get("n"); - Assert.Equal(new[] {"lop", "ripple"}, n.Select(tr => ((Traverser)tr).Object)); - var n = (Dictionary<object, long>) t.SideEffects.Get("n"); - Assert.Equal(2, n.Count); - Assert.Equal(3, n["lop"]); - Assert.Equal(1, n["ripple"]); -- } -- -- [Fact] public void ShouldReturnAnEmptyCollectionWhenKeysIsCalledForTraversalWithoutSideEffect() { var graph = new Graph(); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs ---------------------------------------------------------------------- diff --cc gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs index 3a2e21f,d2ce40b..ae4392b --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs @@@ -184,11 -163,35 +184,35 @@@ namespace Gremlin.Net.UnitTest.Structur Assert.Equal(31.2, deserializedValue); } - [Fact] - public void ShouldDeserializeDecimal() + [Theory, MemberData(nameof(Versions))] ++ public void ShouldDeserializeDecimal(int version) + { + var serializedValue = "{\"@type\":\"gx:BigDecimal\",\"@value\":-8.201}"; - var reader = CreateStandardGraphSONReader(); ++ var reader = CreateStandardGraphSONReader(version); + + var jObject = JObject.Parse(serializedValue); + decimal deserializedValue = reader.ToObject(jObject); + + Assert.Equal(-8.201M, deserializedValue); + } + - [Fact] - public void ShouldDeserializeDecimalValueAsString() ++ [Theory, MemberData(nameof(Versions))] ++ public void ShouldDeserializeDecimalValueAsString(int version) + { + var serializedValue = "{\"@type\":\"gx:BigDecimal\",\"@value\":\"7.50\"}"; - var reader = CreateStandardGraphSONReader(); ++ var reader = CreateStandardGraphSONReader(version); + + var jObject = JObject.Parse(serializedValue); + decimal deserializedValue = reader.ToObject(jObject); + + Assert.Equal(7.5M, deserializedValue); + } - - [Fact] - public void ShouldDeserializeList() ++ ++ [Theory, MemberData(nameof(Versions))] + public void ShouldDeserializeList(int version) { var serializedValue = "[{\"@type\":\"g:Int32\",\"@value\":5},{\"@type\":\"g:Int32\",\"@value\":6}]"; - var reader = CreateStandardGraphSONReader(); + var reader = CreateStandardGraphSONReader(version); var jObject = JArray.Parse(serializedValue); var deserializedValue = reader.ToObject(jObject); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs ---------------------------------------------------------------------- diff --cc gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs index 4b347fe,3d02533..beb514e --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONWriterTests.cs @@@ -100,10 -79,20 +100,20 @@@ namespace Gremlin.Net.UnitTest.Structur Assert.Equal("{\"@type\":\"g:Double\",\"@value\":3.2}", graphSon); } - [Fact] - public void ShouldSerializeDecimal() + [Theory, MemberData(nameof(Versions))] ++ public void ShouldSerializeDecimal(int version) + { - var writer = CreateStandardGraphSONWriter(); ++ var writer = CreateGraphSONWriter(version); + + var graphSon = writer.WriteObject(6.5M); + + Assert.Equal("{\"@type\":\"gx:BigDecimal\",\"@value\":\"6.5\"}", graphSon); + } + - [Fact] - public void ShouldSerializeBoolean() ++ [Theory, MemberData(nameof(Versions))] + public void ShouldSerializeBoolean(int version) { - var writer = CreateStandardGraphSONWriter(); + var writer = CreateGraphSONWriter(version); var graphSon = writer.WriteObject(true); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a7d01e2e/gremlin-test/features/branch/Local.feature ---------------------------------------------------------------------- diff --cc gremlin-test/features/branch/Local.feature index 9efe921,9efe921..0711b3c --- a/gremlin-test/features/branch/Local.feature +++ b/gremlin-test/features/branch/Local.feature @@@ -33,151 -33,151 +33,4 @@@ Feature: Step - local( | baltimore | | bremen | | aachen | -- | kaiserslautern | -- -- Scenario: g_V_hasXlabel_personX_asXaX_localXoutXcreatedX_asXbXX_selectXa_bX_byXnameX_byXidX -- Given the modern graph -- And the traversal of -- """ -- g.V().has(T.label, "person").as("a").local(__.out("created").as("b")).select("a", "b").by("name").by(T.id) -- """ -- When iterated to list -- Then the result should be unordered -- | result | -- | m[{"a":"marko","b":"d[3].i"}] | -- | m[{"a":"josh","b":"d[5].i"}] | -- | m[{"a":"josh","b":"d[3].i"}] | -- | m[{"a":"peter","b":"d[3].i"}] | -- -- Scenario: g_V_localXoutE_countX -- Given the modern graph -- And the traversal of -- """ -- g.V().local(__.outE().count()) -- """ -- When iterated to list -- Then the result should be unordered -- | result | -- | d[3].l | -- | d[0].l | -- | d[0].l | -- | d[2].l | -- | d[0].l | -- | d[1].l | -- -- Scenario: g_VX1X_localXoutEXknowsX_limitX1XX_inV_name -- Given the modern graph -- And using the parameter v1Id defined as "v[marko].id" -- And the traversal of -- """ -- g.V(v1Id).local(__.outE("knows").limit(1)).inV().values("name") -- """ -- When iterated to list -- Then the result should be of -- | result | -- | vadas | -- | josh | -- And the result should have a count of 1 -- -- Scenario: g_V_localXbothEXcreatedX_limitX1XX_otherV_name -- Given the modern graph -- And the traversal of -- """ -- g.V().local(__.bothE("created").limit(1)).otherV().values("name") -- """ -- When iterated to list -- Then the result should be of -- | result | -- | marko | -- | lop | -- | ripple | -- | josh | -- | peter | -- And the result should have a count of 5 -- -- Scenario: g_VX4X_localXbothEX1_createdX_limitX1XX -- Given the modern graph -- And using the parameter v4Id defined as "v[josh].id" -- And the traversal of -- """ -- g.V(v4Id).local(__.bothE("created").limit(1)) -- """ -- When iterated to list -- Then the result should be of -- | result | -- | e[josh-created->lop] | -- | e[josh-created->ripple] | -- And the result should have a count of 1 -- -- Scenario: g_VX4X_localXbothEXknows_createdX_limitX1XX -- Given the modern graph -- And using the parameter v4Id defined as "v[josh].id" -- And the traversal of -- """ -- g.V(v4Id).local(__.bothE("knows", "created").limit(1)) -- """ -- When iterated to list -- Then the result should be of -- | result | -- | e[marko-knows->josh] | -- | e[josh-created->lop] | -- | e[josh-created->ripple] | -- And the result should have a count of 1 -- -- Scenario: g_VX4X_localXbothE_limitX1XX_otherV_name -- Given the modern graph -- And using the parameter v4Id defined as "v[josh].id" -- And the traversal of -- """ -- g.V(v4Id).local(__.bothE().limit(1)).otherV().values("name") -- """ -- When iterated to list -- Then the result should be of -- | result | -- | marko | -- | ripple | -- | lop | -- And the result should have a count of 1 -- -- Scenario: g_VX4X_localXbothE_limitX2XX_otherV_name -- Given the modern graph -- And using the parameter v4Id defined as "v[josh].id" -- And the traversal of -- """ -- g.V(v4Id).local(__.bothE().limit(2)).otherV().values("name") -- """ -- When iterated to list -- Then the result should be of -- | result | -- | marko | -- | ripple | -- | lop | -- And the result should have a count of 2 -- -- Scenario: g_V_localXinEXknowsX_limitX2XX_outV_name -- Given the modern graph -- And the traversal of -- """ -- g.V().local(__.inE("knows").limit(2)).outV().values("name") -- """ -- When iterated to list -- Then the result should be unordered -- | result | -- | marko | -- | marko | -- -- Scenario: g_V_localXmatchXproject__created_person__person_name_nameX_selectXname_projectX_by_byXnameX -- Given the modern graph -- And the traversal of -- """ -- g.V().local(__.match( -- __.as("project").in("created").as("person"), -- __.as("person").values("name").as("name"))).select("name", "project").by().by("name") -- """ -- When iterated to list -- Then the result should be unordered -- | result | -- | m[{"name":"marko","project":"lop"}] | -- | m[{"name":"josh","project":"lop"}] | -- | m[{"name":"peter","project":"lop"}] | -- | m[{"name":"josh","project":"ripple"}] | ++ | kaiserslautern |