You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by jo...@apache.org on 2017/11/30 09:20:08 UTC

[24/33] tinkerpop git commit: Add support for more steps

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/TINKERPOP-1827
Commit: bfb9df397dd47b5ac2ffaf52d5c452213c5319e0
Parents: 4b86d19
Author: Jorge Bay Gondra <jo...@gmail.com>
Authored: Thu Nov 16 09:26:38 2017 +0100
Committer: Jorge Bay Gondra <jo...@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();