Add support for more steps
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/bfb9df39 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/bfb9df39 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/bfb9df39 Branch: refs/heads/master Commit: bfb9df397dd47b5ac2ffaf52d5c452213c5319e0 Parents: 4b86d19 Author: Jorge Bay Gondra <jorgebaygon...@gmail.com> Authored: Thu Nov 16 09:26:38 2017 +0100 Committer: Jorge Bay Gondra <jorgebaygon...@gmail.com> Committed: Thu Nov 30 10:00:09 2017 +0100 ---------------------------------------------------------------------- .../Process/Traversal/DefaultTraversal.cs | 5 + .../Gremlin.Net/Process/Traversal/ITraversal.cs | 11 +- .../Gherkin/CommonSteps.cs | 153 +++++++++++-------- .../Gherkin/GherkinTestRunner.cs | 43 +++++- .../Gherkin/ScenarioData.cs | 96 ++++++++++-- .../ModernGraphTypeInformation.cs | 11 +- .../TraversalEvaluation/StringParameter.cs | 4 +- .../TraversalEvaluationTests.cs | 4 +- .../TraversalEvaluation/TraversalParser.cs | 8 +- .../GraphTraversalTests.cs | 17 --- 10 files changed, 240 insertions(+), 112 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs index 180054e..58c3428 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs @@ -51,6 +51,11 @@ namespace Gremlin.Net.Process.Traversal /// </summary> public IEnumerable<Traverser> Traversers { get; set; } + ITraversal ITraversal.Iterate() + { + return Iterate(); + } + /// <summary> /// Gets or sets the <see cref="ITraversalStrategy" /> strategies of this traversal. /// </summary> http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs index c519ee6..498ef7f 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs @@ -22,6 +22,7 @@ #endregion using System; +using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; @@ -31,7 +32,7 @@ namespace Gremlin.Net.Process.Traversal /// Represents the basic information for a walk over a graph. /// </summary> /// <seealso cref="ITraversal{SType, EType}"/> - public interface ITraversal + public interface ITraversal: IEnumerator { /// <summary> /// Gets the <see cref="Bytecode" /> representation of this traversal. @@ -47,6 +48,12 @@ namespace Gremlin.Net.Process.Traversal /// Gets or sets the <see cref="Traverser" />'s of this traversal that hold the results of the traversal. /// </summary> IEnumerable<Traverser> Traversers { get; set; } + + /// <summary> + /// Iterates all <see cref="Traverser" /> instances in the traversal. + /// </summary> + /// <returns>The fully drained traversal.</returns> + ITraversal Iterate(); } /// <summary> @@ -71,7 +78,7 @@ namespace Gremlin.Net.Process.Traversal /// Iterates all <see cref="Traverser" /> instances in the traversal. /// </summary> /// <returns>The fully drained traversal.</returns> - ITraversal<S, E> Iterate(); + new ITraversal<S, E> Iterate(); /// <summary> /// Gets the next <see cref="Traverser" />. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs index 4a4d18e..1ccf01d 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs @@ -31,47 +31,53 @@ using Gremlin.Net.IntegrationTest.Gherkin.Attributes; using Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation; using Gremlin.Net.Process.Traversal; using Gremlin.Net.Structure; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Xunit; namespace Gremlin.Net.IntegrationTest.Gherkin { - internal class GeneralDefinitions : StepDefinition + internal class CommonSteps : StepDefinition { private GraphTraversalSource _g; + private string _graphName; private readonly IDictionary<string, object> _parameters = new Dictionary<string, object>(); private dynamic _traversal; private object[] _result; - private static readonly IDictionary<Regex, Func<string, object>> Parsers = - new Dictionary<string, Func<string, object>> + private static readonly IDictionary<Regex, Func<string, string, object>> Parsers = + new Dictionary<string, Func<string, string, object>> { - {@"d\[(\d+)\]", x => Convert.ToInt64(x)}, - {@"d\[(\d+(?:\.\d+)?)\]", x => Convert.ToDouble(x)}, + {@"d\[(\d+)\]", (x, _) => Convert.ToInt32(x)}, + {@"d\[(\d+(?:\.\d+)?)\]", (x, _) => Convert.ToDouble(x)}, {@"v\[(.+)\]", ToVertex}, - {@"v\[(.+)\]\.id", x => ToVertex(x).Id}, - {@"v\[(.+)\]\.sid", x => ToVertex(x).Id.ToString()}, + {@"v\[(.+)\]\.id", (x, graphName) => ToVertex(x, graphName).Id}, + {@"v\[(.+)\]\.sid", (x, graphName) => ToVertex(x, graphName).Id.ToString()}, {@"e\[(.+)\]", ToEdge}, - {@"e\[(.+)\].id", s => ToEdge(s).Id}, - {@"e\[(.+)\].sid", s => ToEdge(s).Id.ToString()}, + {@"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}, + {@"m\[(.+)\]", ToMap} }.ToDictionary(kv => new Regex("^" + kv.Key + "$", RegexOptions.Compiled), kv => kv.Value); - - [Given("the modern graph")] - public void ChooseModernGraph() + + [Given("the (\\w+) graph")] + public void ChooseModernGraph(string graphName) { - var connection = ConnectionFactory.CreateRemoteConnection(); - _g = new Graph().Traversal().WithRemote(connection); + 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) { - _parameters.Add(name, ParseValue(value)); + var parsedValue = ParseValue(value, _graphName); + _parameters.Add(name, parsedValue); } [Given("the traversal of")] @@ -84,6 +90,25 @@ namespace Gremlin.Net.IntegrationTest.Gherkin _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() { @@ -106,36 +131,29 @@ namespace Gremlin.Net.IntegrationTest.Gherkin } [Then("the result should be (\\w+)")] - public void AssertResult(string characterizedAs, DataTable table) + public void AssertResult(string characterizedAs, DataTable table = null) { - TableRow[] rows; + var ordered = characterizedAs == "ordered"; switch (characterizedAs) { case "empty": Assert.Equal(0, _result.Length); return; case "ordered": - rows = table.Rows.ToArray(); - Assert.Equal(rows.Length, _result.Length); - for (var i = 0; i < rows.Length; i++) + case "unordered": + 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) { - var row = rows[i]; - var cells = row.Cells.ToArray(); - var expectedValue = ParseValue(cells[0].Value); - var resultItem = ConvertResultItem(null, _result[i]); - Assert.Equal(expectedValue, resultItem); + Assert.Equal(expected, _result); } - break; - case "unordered": - rows = table.Rows.ToArray(); - Assert.Equal(rows.Length, _result.Length); - foreach (var row in rows) + else { - var cells = row.Cells.ToArray(); - var expectedValue = ParseValue(cells[0].Value); - // Convert all the values in the result to the type - var convertedResult = _result.Select(item => ConvertResultItem(null, item)); - Assert.Contains(expectedValue, convertedResult); + var expectedArray = expected.OrderBy(x => x).ToArray(); + var resultArray = _result.OrderBy(x => x).ToArray(); + Assert.Equal(expectedArray, resultArray); } break; default: @@ -143,61 +161,68 @@ namespace Gremlin.Net.IntegrationTest.Gherkin } } - private object ConvertResultItem(string typeName, object value) + [Then("the result should have a count of (\\d+)")] + public void AssertCount(int count) { - if (typeName == "map") - { - // We need to convert the original typed value into IDictionary<string, string> - return StringMap( - Assert.IsAssignableFrom<IDictionary>(value)); - } - return value; + Assert.Equal(count, _result.Length); } - private IDictionary<string, string> StringMap(IDictionary originalMap) + [Then("the graph should return (\\d+) for count of (.+)")] + public void AssertTraversalCount(int expectedCount, string traversalText) { - var result = new Dictionary<string, string>(originalMap.Count); - foreach (var key in originalMap.Keys) + if (traversalText.StartsWith("\"")) { - result.Add(key.ToString(), originalMap[key]?.ToString()); + traversalText = traversalText.Substring(1, traversalText.Length - 2); } - return result; + 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 IDictionary ToMap(string stringMap) + private static IDictionary ToMap(string stringMap, string graphName) { var jsonMap = JObject.Parse(stringMap); return (IDictionary) jsonMap.ToObject<IDictionary<string, object>>(); } - private static ISet<object> ToSet(string stringSet) + private static ISet<object> ToSet(string stringSet, string graphName) { - return new HashSet<object>(ToList(stringSet)); + return new HashSet<object>(ToList(stringSet, graphName)); } - private static IList<object> ToList(string stringList) + private static IList<object> ToList(string stringList, string graphName) { - return stringList.Split(',').Select(ParseValue).ToArray(); + return stringList.Split(',').Select(x => ParseValue(x, graphName)).ToArray(); } - private static Vertex ToVertex(string name) + private static Vertex ToVertex(string name, string graphName) { - return ScenarioData.Instance.ModernVertices[name]; + return ScenarioData.GetByGraphName(graphName).Vertices[name]; } - private static Edge ToEdge(string name) + private static Edge ToEdge(string name, string graphName) { - return ScenarioData.Instance.ModernEdges[name]; + return ScenarioData.GetByGraphName(graphName).Edges[name]; } - private static Path ToPath(string value) + private static Path ToPath(string value, string graphName) { - return new Path(new List<List<string>>(0), value.Split(',').Select(ParseValue).ToList()); + return new Path(new List<List<string>>(0), value.Split(',').Select(x => ParseValue(x, graphName)).ToList()); } - private static object ParseValue(string stringValue) + private static object ParseValue(string stringValue, string graphName) { - Func<string, object> parser = null; + Func<string, string, object> parser = null; string extractedValue = null; foreach (var kv in Parsers) { @@ -209,7 +234,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin break; } } - return parser != null ? parser(extractedValue) : stringValue; + return parser != null ? parser(extractedValue, graphName) : stringValue; } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs index d850d08..fdee536 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs @@ -111,6 +111,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin } OutputResults(results); Console.WriteLine("Finished Gherkin-based tests"); + ScenarioData.Shutdown(); } private void WriteOutput(string line) @@ -122,8 +123,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin { var totalScenarios = results.Sum(f => f.Scenarios.Count); var totalFailedScenarios = results.Sum(f => f.Scenarios.Count(s => s.Value.Count > 0)); - WriteOutput("Gherkin tests summary"); - WriteOutput($"Total scenarios: {totalScenarios}. " + + Console.WriteLine("Gherkin tests summary"); + Console.WriteLine($"Total scenarios: {totalScenarios}. " + $"Passed: {totalScenarios-totalFailedScenarios}. Failed: {totalFailedScenarios}."); if (totalFailedScenarios == 0) { @@ -188,6 +189,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin .Select(m => { var attr = (BddAttribute) m.GetCustomAttribute(attribute); + if (attr == null) { return null; @@ -210,7 +212,18 @@ namespace Gremlin.Net.IntegrationTest.Gherkin { parameters.Add(step.Argument); } - if (m.GetParameters().Length != parameters.Count) + var methodParameters = m.GetParameters(); + for (var i = parameters.Count; i < methodParameters.Length; i++) + { + // Try to complete with default parameter values + var paramInfo = methodParameters[i]; + if (!paramInfo.HasDefaultValue) + { + break; + } + parameters.Add(paramInfo.DefaultValue); + } + if (methodParameters.Length != parameters.Count) { return null; } @@ -224,7 +237,19 @@ namespace Gremlin.Net.IntegrationTest.Gherkin } try { - methodAndParameters.Item1.Invoke(instance, methodAndParameters.Item2); + var method = methodAndParameters.Item1; + var parameters = methodAndParameters.Item2; + var parameterInfos = method.GetParameters(); + for (var i = 0; i < parameterInfos.Length; i++) + { + var paramInfo = parameterInfos[i]; + // Do some minimal conversion => regex capturing groups to int + if (paramInfo.ParameterType == typeof(int)) + { + parameters[i] = Convert.ToInt32(parameters[i]); + } + } + method.Invoke(instance, parameters); } catch (TargetInvocationException ex) { @@ -300,8 +325,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin WriteOutput(path); WriteOutput("------"); - var files = new [] {"/Users/jorge/workspace/temp/count.feature"}; - //var files = Directory.GetFiles(path, "*.feature", SearchOption.AllDirectories); + var files = new [] + { + "/Users/jorge/workspace/tinkerpop/gremlin-test/features/map/Sum.feature", +// "/Users/jorge/workspace/tinkerpop/gremlin-test/features/map/Coalesce.feature", + "/Users/jorge/workspace/tinkerpop/gremlin-test/features/map/AddEdge.feature" + }; +// var files = new [] {"/Users/jorge/workspace/temp/count.feature"}; +// var files = Directory.GetFiles(path, "*.feature", SearchOption.AllDirectories); foreach (var gherkinFile in files) { var parser = new Parser(); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs index d9f66ff..919da0b 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs @@ -26,45 +26,91 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection; +using Gremlin.Net.Process.Remote; using Gremlin.Net.Process.Traversal; using Gremlin.Net.Structure; namespace Gremlin.Net.IntegrationTest.Gherkin { - public class ScenarioData + internal class ScenarioData { private static readonly Lazy<ScenarioData> Lazy = new Lazy<ScenarioData>(Load); - public static ScenarioData Instance => Lazy.Value; - private static readonly Regex EdgeORegex = new Regex("o=(.+?)[,}]", RegexOptions.Compiled); private static readonly Regex EdgeLRegex = new Regex("l=(.+?)[,}]", RegexOptions.Compiled); private static readonly Regex EdgeIRegex = new Regex("i=(.+?)[,}]", RegexOptions.Compiled); - - public IDictionary<string, Vertex> ModernVertices { get; } - public IDictionary<string, Edge> ModernEdges { get; } + private static readonly string[] GraphNames = {"modern", "classic", "crew", "grateful"}; + + private static readonly RemoteConnectionFactory ConnectionFactory = new RemoteConnectionFactory(); + + public static ScenarioDataPerGraph GetByGraphName(string name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name), "Graph name can not be empty"); + } + var dataPerGraph = Lazy.Value._dataPerGraph; + if (!dataPerGraph.TryGetValue(name, out var data)) + { + throw new KeyNotFoundException($"Graph data with key '{name}' not found"); + } + return data; + } + + public static void Shutdown() + { + ConnectionFactory.Dispose(); + } + + public static void CleanEmptyData() + { + var g = new Graph().Traversal().WithRemote(GetByGraphName("empty").Connection); + g.V().Drop().Iterate(); + } + + public static void ReloadEmptyData() + { + var graphData = Lazy.Value._dataPerGraph["empty"]; + var g = new Graph().Traversal().WithRemote(graphData.Connection); + graphData.Vertices = GetVertices(g); + graphData.Edges = GetEdges(g); + } + + private readonly IDictionary<string, ScenarioDataPerGraph> _dataPerGraph; - private ScenarioData(IDictionary<string, Vertex> modernVertices, IDictionary<string, Edge> modernEdges) + private ScenarioData(IDictionary<string, ScenarioDataPerGraph> dataPerGraph) { - ModernVertices = modernVertices; - ModernEdges = modernEdges; + _dataPerGraph = new Dictionary<string, ScenarioDataPerGraph>(dataPerGraph); + var empty = new ScenarioDataPerGraph("empty", ConnectionFactory.CreateRemoteConnection("ggraph"), + new Dictionary<string, Vertex>(0), new Dictionary<string, Edge>()); + _dataPerGraph.Add("empty", empty); } private static ScenarioData Load() { - var connectionFactory = new RemoteConnectionFactory(); - var g = new Graph().Traversal().WithRemote(connectionFactory.CreateRemoteConnection()); - var vertices = g.V().Group<string, object>().By("name").By(__.Tail<Vertex>()).Next() + return new ScenarioData(GraphNames.Select(name => + { + var connection = ConnectionFactory.CreateRemoteConnection($"g{name}"); + var g = new Graph().Traversal().WithRemote(connection); + return new ScenarioDataPerGraph(name, connection, GetVertices(g), GetEdges(g)); + }).ToDictionary(x => x.Name)); + } + + private static IDictionary<string, Vertex> GetVertices(GraphTraversalSource g) + { + return g.V().Group<string, object>().By("name").By(__.Tail<Vertex>()).Next() .ToDictionary(kv => kv.Key, kv => (Vertex)kv.Value); - var edges = g.E().Group<string, object>() + } + + private static IDictionary<string, Edge> GetEdges(GraphTraversalSource g) + { + return g.E().Group<string, object>() .By(__.Project<Edge>("o", "l", "i") .By(__.OutV().Values<string>("name")).By(__.Label()).By(__.InV().Values<string>("name"))) .By(__.Tail<object>()) .Next() .ToDictionary(kv => GetEdgeKey(kv.Key), kv => (Edge)kv.Value); - connectionFactory.Dispose(); - return new ScenarioData(vertices, edges); } private static string GetEdgeKey(string key) @@ -75,4 +121,24 @@ namespace Gremlin.Net.IntegrationTest.Gherkin return o + "-" + l + "->" + i; } } + + internal class ScenarioDataPerGraph + { + public ScenarioDataPerGraph(string name, IRemoteConnection connection, IDictionary<string, Vertex> vertices, + IDictionary<string, Edge> edges) + { + Name = name; + Connection = connection; + Vertices = vertices; + Edges = edges; + } + + public string Name { get; } + + public IRemoteConnection Connection { get; } + + public IDictionary<string, Vertex> Vertices { get; set; } + + public IDictionary<string, Edge> Edges { get; set; } + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ModernGraphTypeInformation.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ModernGraphTypeInformation.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ModernGraphTypeInformation.cs index 10d316d..a467519 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ModernGraphTypeInformation.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ModernGraphTypeInformation.cs @@ -43,7 +43,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation /// <summary> /// Gets the type argument information based on the modern graph. /// </summary>s - public static Type GetTypeArguments(MethodInfo method, object[] parameterValues) + public static Type GetTypeArguments(MethodInfo method, object[] parameterValues, int genericTypeIndex) { switch (method.Name) { @@ -56,12 +56,19 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation return types[0]; } return typeof(object); + case nameof(GraphTraversal<object,object>.Group) when genericTypeIndex == 0: + // Use IDictionary<string, object> for Group + return typeof(string); case nameof(GraphTraversal<object,object>.ValueMap): case nameof(GraphTraversal<object,object>.Select): - // Use IDictionary<string, object> for value maps + case nameof(GraphTraversal<object,object>.Group): + case nameof(GraphTraversal<object,object>.Unfold): + // default to object for this methods return typeof(object); case nameof(GraphTraversal<object,object>.Limit): case nameof(GraphTraversal<object,object>.Optional): + case nameof(GraphTraversal<object,object>.Sum): + case nameof(GraphTraversal<object,object>.Coalesce): // Maintain the same type return method.DeclaringType.GetGenericArguments()[1]; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs index 716a2ce..7cb9c95 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs @@ -53,10 +53,10 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation Value = value; } - public static StringParameter Parse(string text, ref int i) + public static StringParameter Parse(string text, char quoteChar, ref int i) { i++; - var endIndex = text.IndexOf('"', i); + var endIndex = text.IndexOf(quoteChar, i); var result = new StringParameter(text.Substring(i, endIndex - i)); i = endIndex; return result; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs index ade895c..a2dd888 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs @@ -86,7 +86,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation Tuple.Create("g.V().count(Scope.local)", 2), Tuple.Create("g.V().values(\"age\").is(P.lte(30))", 3), Tuple.Create("g.V().optional(__.out().optional(__.out())).path().limit(1)", 4), - Tuple.Create("g.V(1).as(\"a\").out(\"knows\").as(\"b\").\n select(\"a\", \"b\").by(\"name\")", 6) + Tuple.Create("g.V(1).as(\"a\").out(\"knows\").as(\"b\").\n select(\"a\", \"b\").by(\"name\")", 6), + Tuple.Create( + "g.V().hasLabel(\"software\").group().by(\"name\").by(__.bothE().values(\"weight\").sum())", 5) }; var g = new Graph().Traversal(); foreach (var tuple in traversalTexts) http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs index 1f17ec8..d557c49 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs @@ -209,7 +209,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation if (!genericParameters.TryGetValue(name, out type)) { // Try to infer it from the name based on modern graph - type = ModernGraphTypeInformation.GetTypeArguments(method, parameterValues); + type = ModernGraphTypeInformation.GetTypeArguments(method, parameterValues, i); } if (type == null) { @@ -295,6 +295,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation private static IList<Token> ParseTokens(string text, ref int i) { + // Parser issue: quotes are not normalized + text = text.Replace("\\\"", "\""); var result = new List<Token>(); var startIndex = i; var parsing = ParsingPart.Name; @@ -379,9 +381,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation { return null; } - if (firstChar == '"') + if (firstChar == '"' || firstChar == '\'') { - return StringParameter.Parse(text, ref i); + return StringParameter.Parse(text, firstChar, ref i); } if (char.IsDigit(firstChar)) { http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bfb9df39/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs index 8118209..454ac68 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs @@ -96,23 +96,6 @@ namespace Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection } [Fact] - public void g_V_HasXname_markoX_ValueMap_Next() - { - var graph = new Graph(); - var connection = _connectionFactory.CreateRemoteConnection(); - var g = graph.Traversal().WithRemote(connection); - - var receivedValueMap = g.V().Has("name", "marko").ValueMap<object>().Next(); - - var expectedValueMap = new Dictionary<string, object> - { - {"age", new List<object> {29}}, - {"name", new List<object> {"marko"}} - }; - Assert.Equal(expectedValueMap, receivedValueMap); - } - - [Fact] public void g_V_RepeatXOutX_TimesX2X_ValuesXNameX() { var graph = new Graph();