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/23 08:16:07 UTC
[32/50] tinkerpop git commit: Traversal parser for tests
Traversal parser for tests
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/5dd3d6c8
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/5dd3d6c8
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/5dd3d6c8
Branch: refs/heads/TINKERPOP-1827
Commit: 5dd3d6c84dd95f2fa8569a80c2094e7a2f91bec4
Parents: 458b58d
Author: Jorge Bay Gondra <jo...@gmail.com>
Authored: Thu Oct 26 13:06:04 2017 +0200
Committer: Jorge Bay Gondra <jo...@gmail.com>
Committed: Thu Nov 23 09:08:06 2017 +0100
----------------------------------------------------------------------
.../Gherkin/CommonSteps.cs | 13 +-
.../Gherkin/GherkinTestRunner.cs | 45 +++-
.../TraversalEvaluation/ITokenParameter.cs | 30 +++
.../TraversalEvaluation/NumericParameter.cs | 68 +++++
.../StaticTraversalParameter.cs | 57 ++++
.../TraversalEvaluation/StringParameter.cs | 69 +++++
.../Gherkin/TraversalEvaluation/Token.cs | 76 ++++++
.../TraversalEvaluationTests.cs | 79 ++++++
.../TraversalEvaluation/TraversalParser.cs | 261 +++++++++++++++++++
.../TraversalPredicateParameter.cs | 60 +++++
.../TraversalTokenParameter.cs | 60 +++++
.../Gherkin/TraversalTranslations.cs | 102 --------
12 files changed, 810 insertions(+), 110 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/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 50ea9b8..16aef9d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -29,6 +29,7 @@ using System.Net.Http.Headers;
using System.Runtime.CompilerServices;
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;
@@ -67,6 +68,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
_result = enumerable.Cast<object>().ToArray();
}
+ [When("iterated next")]
+ public void IterateNext()
+ {
+ if (!(_traversal is ITraversal))
+ {
+ throw new InvalidOperationException("Traversal should be set before iterating");
+ }
+ _result = _traversal.Next();
+ }
+
[Given("the traversal of")]
public void TranslateTraversal(string traversalText)
{
@@ -74,7 +85,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{
throw new InvalidOperationException("g should be a traversal source");
}
- _traversal = TraversalTranslations.GetTraversal(traversalText, _g);
+ _traversal = TraversalParser.GetTraversal(traversalText, _g);
}
[Then("the result should be (\\w+)")]
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/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 e1df3a8..7523b0b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
@@ -24,6 +24,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
@@ -146,8 +147,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
WriteOutput($" Scenario: {resultScenario.Key.Name}");
foreach (var step in resultScenario.Key.Steps)
{
- Exception failure;
- resultScenario.Value.TryGetValue(step, out failure);
+ resultScenario.Value.TryGetValue(step, out var failure);
if (failure == null)
{
WriteOutput($" {step.Keyword} {step.Text}");
@@ -295,11 +295,42 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
private IEnumerable<Feature> GetFeatures()
{
- // TODO: go through all the .feature files
- const string gherkinFile = "/Users/jorge/workspace/temp/count.feature";
- var parser = new Parser();
- var doc = parser.Parse(gherkinFile);
- yield return doc.Feature;
+ var rootPath = GetRootPath();
+ var path = Path.Combine(rootPath, "gremlin-test", "features");
+ WriteOutput(path);
+ WriteOutput("------");
+
+ 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();
+ WriteOutput("Parsing " + gherkinFile);
+ var doc = parser.Parse(gherkinFile);
+ yield return doc.Feature;
+ }
+ }
+
+ private string GetRootPath()
+ {
+ var codeBaseUrl = new Uri(GetType().GetTypeInfo().Assembly.CodeBase);
+ var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
+ DirectoryInfo rootDir = null;
+ for (var dir = Directory.GetParent(Path.GetDirectoryName(codeBasePath));
+ dir.Parent != null;
+ dir = dir.Parent)
+ {
+ if (dir.Name == "gremlin-dotnet" && dir.Parent?.Name == "tinkerpop")
+ {
+ rootDir = dir.Parent;
+ break;
+ }
+ }
+ if (rootDir == null)
+ {
+ throw new FileNotFoundException("tinkerpop root not found in path");
+ }
+ return rootDir.FullName;
}
private void PrintGherkin()
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
new file mode 100644
index 0000000..1c940db
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
@@ -0,0 +1,30 @@
+#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
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ public interface ITokenParameter
+ {
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
new file mode 100644
index 0000000..9effc17
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
@@ -0,0 +1,68 @@
+#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;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ public class NumericParameter<T> : ITokenParameter, IEquatable<NumericParameter<T>> where T : struct
+ {
+ public bool Equals(NumericParameter<T> other)
+ {
+ return Value.Equals(other.Value);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((NumericParameter<T>) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return Value.GetHashCode();
+ }
+
+ public T Value { get; }
+
+ public NumericParameter(T value)
+ {
+ Value = value;
+ }
+
+ public override string ToString()
+ {
+ return $"NumericParameter<{typeof(T).Name}>({Value})";
+ }
+ }
+
+ internal static class NumericParameter
+ {
+ public static NumericParameter<TType> Create<TType>(TType value) where TType : struct
+ {
+ return new NumericParameter<TType>(value);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
new file mode 100644
index 0000000..b054cbc
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
@@ -0,0 +1,57 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ internal class StaticTraversalParameter : ITokenParameter, IEquatable<StaticTraversalParameter>
+ {
+ public bool Equals(StaticTraversalParameter other)
+ {
+ return Parts.SequenceEqual(other.Parts);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((StaticTraversalParameter) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return Parts != null ? Parts.GetHashCode() : 0;
+ }
+
+ public IList<Token> Parts { get; }
+
+ public StaticTraversalParameter(IList<Token> parts)
+ {
+ Parts = parts;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/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
new file mode 100644
index 0000000..ad182b5
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
@@ -0,0 +1,69 @@
+#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;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ internal class StringParameter : ITokenParameter, IEquatable<StringParameter>
+ {
+ public bool Equals(StringParameter other)
+ {
+ return string.Equals(Value, other.Value);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((StringParameter) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return (Value != null ? Value.GetHashCode() : 0);
+ }
+
+ public string Value { get; }
+
+ public StringParameter(string value)
+ {
+ Value = value;
+ }
+
+ public static StringParameter Parse(string text, ref int i)
+ {
+ i++;
+ var endIndex = text.IndexOf('"', i);
+ var result = new StringParameter(text.Substring(i, endIndex - i));
+ i = endIndex;
+ return result;
+ }
+
+ public override string ToString()
+ {
+ return $"{GetType().Name}({Value})";
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
new file mode 100644
index 0000000..633e2b5
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
@@ -0,0 +1,76 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ internal class Token : IEquatable<Token>
+ {
+ private static readonly IList<ITokenParameter> EmptyParameters = new ITokenParameter[0];
+
+ public bool Equals(Token other)
+ {
+ if (!string.Equals(Name, other.Name))
+ {
+ return false;
+ }
+ return (Parameters ?? EmptyParameters).SequenceEqual(other.Parameters ?? EmptyParameters);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((Token) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return ((Name != null ? Name.GetHashCode() : 0) * 397) ^
+ (Parameters != null ? Parameters.GetHashCode() : 0);
+ }
+ }
+
+ public string Name { get; }
+
+ public ICollection<ITokenParameter> Parameters { get; }
+
+ public Token(string name, ICollection<ITokenParameter> parameters = null)
+ {
+ Name = name;
+ Parameters = parameters;
+ }
+
+ public Token(string name, ITokenParameter parameter)
+ {
+ Name = name;
+ Parameters = new[] {parameter};
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/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
new file mode 100644
index 0000000..ea65cd2
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
@@ -0,0 +1,79 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Xunit;
+using Xunit.Abstractions;
+using Xunit.Sdk;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ public class TraversalEvaluationTests
+ {
+ private readonly ITestOutputHelper _output;
+
+ public TraversalEvaluationTests(ITestOutputHelper output)
+ {
+ _output = output;
+ }
+
+ [Fact]
+ public void Traversal_Parser_Should_Parse_Parts()
+ {
+ var items = new[]
+ {
+ Tuple.Create("g.V().count()", new[] {new Token("count")}),
+ Tuple.Create("g.V().values(\"name\")",
+ new[] {new Token("values", new StringParameter("name"))}),
+ Tuple.Create("g.V().constant(123l)",
+ new[] {new Token("constant", new[] {NumericParameter.Create(123L)})}),
+ Tuple.Create("g.V().has(\"no\").count()",
+ new[] {new Token("has", new StringParameter("no")), new Token("count")}),
+ Tuple.Create("g.V().has(\"lang\", \"java\")",
+ new[] {new Token("has", new[] {new StringParameter("lang"), new StringParameter("java")})}),
+ Tuple.Create("g.V().where(__.in(\"knows\"))",
+ new[] {new Token("where", new[] {new StaticTraversalParameter(
+ new[] {new Token("__"), new Token("in", new StringParameter("knows"))})})}),
+ Tuple.Create("g.V().has(\"age\", P.gt(27)",
+ new[] {new Token("has", new ITokenParameter[] { new StringParameter("age"),
+ new TraversalPredicateParameter(
+ new[] { new Token("P"), new Token("gt", NumericParameter.Create(27)) }) })})
+ };
+ foreach (var item in items)
+ {
+ var parts = TraversalParser.ParseParts(item.Item1);
+ _output.WriteLine("Parsing " + item.Item1);
+ if (parts[parts.Count-1].Parameters != null)
+ {
+ _output.WriteLine("{0}", parts[parts.Count-1].Parameters.Count);
+ _output.WriteLine("Values: " +
+ string.Join(", ", parts[parts.Count - 1].Parameters.Select(p => p.ToString())));
+ }
+ Assert.Equal(new[] {new Token("g"), new Token("V")}.Concat(item.Item2), parts);
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/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
new file mode 100644
index 0000000..0ac97ff
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -0,0 +1,261 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ public class TraversalParser
+ {
+ private static readonly IDictionary<string, Func<GraphTraversalSource, ITraversal>> FixedTranslations =
+ new Dictionary<string, Func<GraphTraversalSource, ITraversal>>
+ {
+ { "g.V().has(\"no\").count()", g => g.V().Has("no").Count() },
+ { "g.V().fold().count(Scope.local)", g => g.V().Fold<object>().Count(Scope.Local)}
+ };
+
+ private static readonly Regex RegexInteger = new Regex(@"\d+", RegexOptions.Compiled);
+ private static readonly Regex RegexDouble = new Regex(@"\d+\.\d+", RegexOptions.Compiled);
+ private static readonly Regex RegexFloat =
+ new Regex(@"\d+\.\d+f", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+ private static readonly Regex RegexLong = new Regex(@"\d+l", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
+ internal static ITraversal GetTraversal(string traversalText, GraphTraversalSource g)
+ {
+ Func<GraphTraversalSource, ITraversal> traversalBuilder;
+ if (!FixedTranslations.TryGetValue(traversalText, out traversalBuilder))
+ {
+ return BuildFromMethods(traversalText, g);
+ }
+ return traversalBuilder(g);
+ }
+
+ private static ITraversal BuildFromMethods(string traversalText, GraphTraversalSource g)
+ {
+ var parts = traversalText.Split('.');
+ if (parts[0] != "g")
+ {
+ throw BuildException(traversalText);
+ }
+ ITraversal traversal;
+ switch (parts[1])
+ {
+ case "V()":
+ traversal = g.V();
+ break;
+ case "E()":
+ traversal = g.E();
+ break;
+ default:
+ throw BuildException(traversalText);
+ }
+ for (var i = 2; i < parts.Length; i++)
+ {
+ var name = GetCsharpName(parts[i], traversalText);
+ var method = traversal.GetType().GetMethod(name);
+ if (method == null)
+ {
+ throw new InvalidOperationException($"Traversal method '{parts[i]}' not found for testing");
+ }
+ if (method.IsGenericMethod)
+ {
+ throw new InvalidOperationException(
+ $"Can not build traversal to test as '{name}()' method is generic");
+ }
+ traversal = (ITraversal) method.Invoke(traversal, new object[] { new object[0]});
+ }
+ return traversal;
+ }
+
+ private static string GetCsharpName(string part, string traversalText)
+ {
+ if (!part.EndsWith("()"))
+ {
+ throw BuildException(traversalText);
+ }
+ // Transform to PascalCasing and remove the parenthesis
+ return char.ToUpper(part[0]) + part.Substring(1, part.Length - 3);
+ }
+
+ private static Exception BuildException(string traversalText)
+ {
+ return new InvalidOperationException($"Can not build a traversal to test from '{traversalText}'");
+ }
+
+ internal static IList<Token> ParseParts(string traversalText)
+ {
+ var index = 0;
+ return ParseTokens(traversalText, ref index);
+ }
+
+ private static IList<Token> ParseTokens(string text, ref int i)
+ {
+ var result = new List<Token>();
+ var startIndex = i;
+ var parsing = ParsingPart.Name;
+ string name = null;
+ var parameters = new List<ITokenParameter>();
+ while (i < text.Length)
+ {
+ switch (text[i])
+ {
+ case '.':
+ if (name == null)
+ {
+ name = text.Substring(startIndex, i - startIndex);
+ }
+ startIndex = i + 1;
+ result.Add(new Token(name, parameters));
+ name = null;
+ parameters = new List<ITokenParameter>();
+ parsing = ParsingPart.Name;
+ break;
+ case '(':
+ {
+ name = text.Substring(startIndex, i - startIndex);
+ i++;
+ parsing = ParsingPart.StartParameters;
+ var param = ParseParameter(text, ref i);
+ if (param == null)
+ {
+ parsing = ParsingPart.EndParameters;
+ }
+ else
+ {
+ parameters.Add(param);
+ }
+ break;
+ }
+ case ',' when text[i+1] != ' ':
+ case ' ' when text[i+1] != ' ':
+ {
+ if (parsing != ParsingPart.StartParameters)
+ {
+ throw new InvalidOperationException(
+ "Can not parse space or comma chars outside parameters");
+ }
+ i++;
+ var param = ParseParameter(text, ref i);
+ if (param == null)
+ {
+ parsing = ParsingPart.EndParameters;
+ }
+ else
+ {
+ parameters.Add(param);
+ }
+ break;
+ }
+ case ')' when parsing != ParsingPart.StartParameters:
+ // The traversal already ended
+ i--;
+ if (name != null)
+ {
+ result.Add(new Token(name, parameters));
+ }
+ return result;
+ case ')':
+ parsing = ParsingPart.EndParameters;
+ break;
+ }
+ i++;
+ }
+ if (name != null)
+ {
+ result.Add(new Token(name, parameters));
+ }
+ return result;
+ }
+
+ private static ITokenParameter ParseParameter(string text, ref int i)
+ {
+ var firstChar = text[i];
+ if (firstChar == ')')
+ {
+ return null;
+ }
+ if (firstChar == '"')
+ {
+ return StringParameter.Parse(text, ref i);
+ }
+ if (char.IsDigit(firstChar))
+ {
+ return ParseNumber(text, ref i);
+ }
+ if (text.Substring(i, 3).StartsWith("__."))
+ {
+ return new StaticTraversalParameter(ParseTokens(text, ref i));
+ }
+ if (text.Substring(i, 2).StartsWith("T."))
+ {
+ return new TraversalTokenParameter(ParseTokens(text, ref i));
+ }
+ if (text.Substring(i, 2).StartsWith("P."))
+ {
+ return new TraversalPredicateParameter(ParseTokens(text, ref i));
+ }
+ return null;
+ }
+
+ private static ITokenParameter ParseNumber(string text, ref int i)
+ {
+ var match = RegexLong.Match(text.Substring(i));
+ if (match.Success)
+ {
+ i += match.Value.Length - 1;
+ return NumericParameter.Create(Convert.ToInt64(match.Value.Substring(0, match.Value.Length-1)));
+ }
+ match = RegexFloat.Match(text.Substring(i));
+ if (match.Success)
+ {
+ i += match.Value.Length - 1;
+ return NumericParameter.Create(Convert.ToSingle(match.Value.Substring(0, match.Value.Length-1)));
+ }
+ match = RegexDouble.Match(text.Substring(i));
+ if (match.Success)
+ {
+ i += match.Value.Length;
+ return NumericParameter.Create(Convert.ToSingle(match.Value));
+ }
+ match = RegexInteger.Match(text.Substring(i));
+ if (!match.Success)
+ {
+ throw new InvalidOperationException(
+ $"Could not parse numeric value from the beginning of {text.Substring(i)}");
+ }
+ i += match.Value.Length;
+ return NumericParameter.Create(Convert.ToInt32(match.Value));
+ }
+
+ private enum ParsingPart
+ {
+ Name,
+ StartParameters,
+ EndParameters
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
new file mode 100644
index 0000000..d9bf061
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
@@ -0,0 +1,60 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ /// <summary>
+ /// Represents a parameter for a traversal predicate (ie: P.gt())
+ /// </summary>
+ internal class TraversalPredicateParameter : ITokenParameter, IEquatable<TraversalPredicateParameter>
+ {
+ public bool Equals(TraversalPredicateParameter other)
+ {
+ return Parts.SequenceEqual(other.Parts);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((TraversalPredicateParameter) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return Parts != null ? Parts.GetHashCode() : 0;
+ }
+
+ public IList<Token> Parts { get; }
+
+ public TraversalPredicateParameter(IList<Token> parts)
+ {
+ Parts = parts;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
new file mode 100644
index 0000000..5a5e8c1
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
@@ -0,0 +1,60 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ /// <summary>
+ /// Represents a parameter for a traversal token (ie: T.label)
+ /// </summary>
+ internal class TraversalTokenParameter : ITokenParameter, IEquatable<TraversalTokenParameter>
+ {
+ public bool Equals(TraversalTokenParameter other)
+ {
+ return Parts.SequenceEqual(other.Parts);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((TraversalTokenParameter) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return Parts != null ? Parts.GetHashCode() : 0;
+ }
+
+ public IList<Token> Parts { get; }
+
+ public TraversalTokenParameter(IList<Token> parts)
+ {
+ Parts = parts;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalTranslations.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalTranslations.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalTranslations.cs
deleted file mode 100644
index af02b8c..0000000
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalTranslations.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-#region License
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using Gremlin.Net.Process.Traversal;
-
-namespace Gremlin.Net.IntegrationTest.Gherkin
-{
- internal class TraversalTranslations
- {
- private static readonly IDictionary<string, Func<GraphTraversalSource, ITraversal>> FixedTranslations =
- new Dictionary<string, Func<GraphTraversalSource, ITraversal>>
- {
- { "g.V().has(\"no\").count()", g => g.V().Has("no").Count() },
- { "g.V().fold().count(Scope.local)", g => g.V().Fold<object>().Count(Scope.Local)}
- };
-
- internal static ITraversal GetTraversal(string traversalText, GraphTraversalSource g)
- {
- Func<GraphTraversalSource, ITraversal> traversalBuilder;
- if (!FixedTranslations.TryGetValue(traversalText, out traversalBuilder))
- {
- return BuildFromMethods(traversalText, g);
- }
- return traversalBuilder(g);
- }
-
- private static ITraversal BuildFromMethods(string traversalText, GraphTraversalSource g)
- {
- var parts = traversalText.Split('.');
- if (parts[0] != "g")
- {
- throw BuildException(traversalText);
- }
- ITraversal traversal;
- switch (parts[1])
- {
- case "V()":
- traversal = g.V();
- break;
- case "E()":
- traversal = g.E();
- break;
- default:
- throw BuildException(traversalText);
- }
- for (var i = 2; i < parts.Length; i++)
- {
- var name = GetCsharpName(parts[i], traversalText);
- var method = traversal.GetType().GetMethod(name);
- if (method == null)
- {
- throw new InvalidOperationException($"Traversal method '{parts[i]}' not found for testing");
- }
- if (method.IsGenericMethod)
- {
- throw new InvalidOperationException(
- $"Can not build traversal to test as '{name}()' method is generic");
- }
- traversal = (ITraversal) method.Invoke(traversal, new object[] { new object[0]});
- }
- return traversal;
- }
-
- private static string GetCsharpName(string part, string traversalText)
- {
- if (!part.EndsWith("()"))
- {
- throw BuildException(traversalText);
- }
- // Transform to PascalCasing and remove the parenthesis
- return char.ToUpper(part[0]) + part.Substring(1, part.Length - 3);
- }
-
- private static Exception BuildException(string traversalText)
- {
- return new InvalidOperationException($"Can not build a traversal to test from '{traversalText}'");
- }
- }
-}
\ No newline at end of file