Merge branch 'tp32'

Conflicts:
        
gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/driver/remote/gremlin-server-integration.yaml
        
gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
        
gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-performance.yaml
        gremlin-server/src/test/scripts/test-server-start.groovy
        
gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/OptionalTest.java


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/04c52201
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/04c52201
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/04c52201

Branch: refs/heads/master
Commit: 04c52201857a92ccfdd7e8d2e19e4aceaae9d76a
Parents: 65259d2 78a1095
Author: Stephen Mallette <[email protected]>
Authored: Wed Nov 22 13:47:48 2017 -0500
Committer: Stephen Mallette <[email protected]>
Committed: Wed Nov 22 13:47:48 2017 -0500

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   2 +
 .../Driver/Remote/DriverRemoteConnection.cs     |  16 +-
 .../GraphTraversalTests.cs                      |   8 +-
 .../RemoteConnectionFactory.cs                  |   8 +-
 gremlin-dotnet/test/pom.xml                     |   6 +-
 gremlin-python/pom.xml                          |  21 +-
 .../src/main/jython/radish/feature_steps.py     | 230 +++++++++
 .../src/main/jython/radish/terrain.py           | 101 ++++
 gremlin-python/src/main/jython/setup.py         |   4 +-
 .../remote/gremlin-server-integration.yaml      |   3 -
 .../server/gremlin-server-integration.yaml      |   3 -
 .../src/test/scripts/generate-all.groovy        |  40 ++
 .../src/test/scripts/test-server-start.groovy   |  26 +-
 .../test/scripts/tinkergraph-empty.properties   |  20 +
 gremlin-test/features/branch/Branch.feature     |  92 ++++
 gremlin-test/features/branch/Choose.feature     | 124 +++++
 gremlin-test/features/branch/Local.feature      | 183 +++++++
 gremlin-test/features/branch/Optional.feature   |  81 ++++
 gremlin-test/features/branch/Repeat.feature     | 230 +++++++++
 gremlin-test/features/branch/Union.feature      | 140 ++++++
 gremlin-test/features/filter/And.feature        |  69 +++
 gremlin-test/features/filter/Coin.feature       |  43 ++
 gremlin-test/features/filter/CyclicPath.feature |  52 ++
 gremlin-test/features/filter/Dedup.feature      | 237 +++++++++
 gremlin-test/features/filter/Drop.feature       |  63 +++
 gremlin-test/features/filter/Filter.feature     | 111 +++++
 gremlin-test/features/filter/Has.feature        |  45 ++
 gremlin-test/features/filter/Is.feature         |  75 +++
 gremlin-test/features/filter/Or.feature         |  62 +++
 gremlin-test/features/filter/Range.feature      | 171 +++++++
 gremlin-test/features/filter/Sample.feature     |  75 +++
 gremlin-test/features/filter/SimplePath.feature |  72 +++
 gremlin-test/features/filter/Tail.feature       | 145 ++++++
 gremlin-test/features/filter/Where.feature      | 105 ++++
 gremlin-test/features/map/AddEdge.feature       | 307 ++++++++++++
 gremlin-test/features/map/AddVertex.feature     | 147 ++++++
 gremlin-test/features/map/Coalesce.feature      |  78 +++
 gremlin-test/features/map/Constant.feature      |  52 ++
 gremlin-test/features/map/Count.feature         | 125 +++++
 gremlin-test/features/map/FlatMap.feature       |  35 ++
 gremlin-test/features/map/Fold.feature          |  57 +++
 gremlin-test/features/map/Graph.feature         | 109 +++++
 gremlin-test/features/map/Loops.feature         |  68 +++
 gremlin-test/features/map/Map.feature           | 108 +++++
 gremlin-test/features/map/Match.feature         |  80 ++++
 gremlin-test/features/map/Max.feature           |  51 ++
 gremlin-test/features/map/Mean.feature          |  40 ++
 gremlin-test/features/map/Min.feature           |  51 ++
 gremlin-test/features/map/Order.feature         | 132 ++++++
 gremlin-test/features/map/Path.feature          | 105 ++++
 gremlin-test/features/map/Project.feature       |  55 +++
 gremlin-test/features/map/Properties.feature    |  68 +++
 gremlin-test/features/map/Select.feature        | 324 +++++++++++++
 gremlin-test/features/map/Sum.feature           |  40 ++
 gremlin-test/features/map/Unfold.feature        |  76 +++
 gremlin-test/features/map/ValueMap.feature      |  62 +++
 gremlin-test/features/map/Vertex.feature        | 475 +++++++++++++++++++
 .../features/sideEffect/Aggregate.feature       |  80 ++++
 gremlin-test/features/sideEffect/Group.feature  | 244 ++++++++++
 .../features/sideEffect/GroupCount.feature      | 187 ++++++++
 gremlin-test/features/sideEffect/Inject.feature |  51 ++
 gremlin-test/features/sideEffect/Sack.feature   |  71 +++
 .../features/sideEffect/SideEffectCap.feature   |  38 ++
 gremlin-test/features/sideEffect/Store.feature  |  87 ++++
 .../step/sideEffect/GroupCountTest.java         |   2 +-
 .../gremlin/process/FeatureCoverageTest.java    | 131 +++++
 66 files changed, 6174 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/CHANGELOG.asciidoc
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
----------------------------------------------------------------------
diff --cc 
gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
index 406bbb6,d9c47f1..90b2ea8
--- 
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
+++ 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
@@@ -135,10 -135,10 +135,10 @@@ namespace Gremlin.Net.IntegrationTest.P
              var g = graph.Traversal().WithRemote(connection);
  
              var shortestPath =
 -                
g.V(5).Repeat(__.Both().SimplePath()).Until(__.HasId(6)).Limit(1).Path().Next();
 +                
g.V(5).Repeat(__.Both().SimplePath()).Until(__.HasId(6)).Limit<Vertex>(1).Path().Next();
  
              Assert.Equal(4, shortestPath.Count);
-             Assert.Equal(new Vertex((long) 6), shortestPath[3]);
+             Assert.Equal(new Vertex(6), shortestPath[3]);
          }
  
          [Fact]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-dotnet/test/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-python/pom.xml
----------------------------------------------------------------------
diff --cc gremlin-python/pom.xml
index 7365f6f,a1aee4a..27b3221
--- a/gremlin-python/pom.xml
+++ b/gremlin-python/pom.xml
@@@ -440,6 -440,17 +440,17 @@@ limitations under the License
                                              <env key="PYTHONPATH" value=""/>
                                              <arg line="setup.py test"/>
                                          </exec>
+                                         <!-- radish seems to like all 
dependencies in place -->
+                                         <exec executable="env/bin/python" 
dir="${project.build.directory}/python2"
+                                               failonerror="true">
+                                             <env key="PYTHONPATH" value=""/>
+                                             <arg line="setup.py install"/>
+                                         </exec>
+                                         <exec executable="env/bin/radish" 
dir="${project.build.directory}/python2"
+                                               failonerror="true">
+                                             <env key="PYTHONPATH" value=""/>
 -                                            <arg line="-e -t -b 
${project.build.directory}/python2/radish 
${project.basedir}/../gremlin-test/features/"/> <!-- -no-line-jump -->
++                                            <arg line="-e -t -b 
${project.build.directory}/python2/radish 
${project.basedir}/../gremlin-test/features/ --no-line-jump"/> <!-- 
-no-line-jump -->
+                                         </exec>
                                      </target>
                                  </configuration>
                              </execution>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-python/src/main/jython/radish/terrain.py
----------------------------------------------------------------------
diff --cc gremlin-python/src/main/jython/radish/terrain.py
index 0000000,5897852..f91c603
mode 000000,100644..100644
--- a/gremlin-python/src/main/jython/radish/terrain.py
+++ b/gremlin-python/src/main/jython/radish/terrain.py
@@@ -1,0 -1,114 +1,101 @@@
+ '''
+ 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.
+ '''
+ 
+ import re
+ from gremlin_python.structure.graph import Graph
+ from gremlin_python.process.graph_traversal import __
++from gremlin_python.driver import serializer
+ from gremlin_python.driver.driver_remote_connection import 
DriverRemoteConnection
+ from radish import before, after, world
+ 
+ outV = __.outV
+ label = __.label
+ inV = __.inV
+ project = __.project
+ tail = __.tail
+ 
+ 
+ @before.all
+ def prepare_static_traversal_source(features, marker):
+     # as the various traversal sources for testing do not change their data, 
there is no need to re-create remotes
+     # and client side lookup data over and over. it can be created once for 
all tests and be reused.
+     cache = {}
+     for graph_name in (("modern", "gmodern"), ("classic", "gclassic"), 
("crew", "gcrew"), ("grateful", "ggrateful")):
+         cache[graph_name[0]] = {}
+         remote = __create_remote(graph_name[1])
+         cache[graph_name[0]]["remote_conn"] = __create_remote(graph_name[1])
+         cache[graph_name[0]]["lookup_v"] = __create_lookup_v(remote)
+         cache[graph_name[0]]["lookup_e"] = __create_lookup_e(remote)
+ 
+     # store the cache on the global context so that remotes can be shutdown 
cleanly at the end of the tests
+     world.cache = cache
+ 
+     # iterate each feature and apply the cached remotes/lookups to each 
scenario context so that they are
+     # accessible to the feature steps for test logic
+     for feature in features:
+         for scenario in feature.all_scenarios:
+             scenario.context.remote_conn = {}
+             scenario.context.lookup_v = {}
+             scenario.context.lookup_e = {}
+ 
+             for graph_name in ("modern", "classic", "crew", "grateful"):
+                 scenario.context.remote_conn[graph_name] = 
cache[graph_name]["remote_conn"]
+                 scenario.context.lookup_v[graph_name] = 
cache[graph_name]["lookup_v"]
+                 scenario.context.lookup_e[graph_name] = 
cache[graph_name]["lookup_e"]
+ 
+ 
+ @before.each_scenario
+ def prepare_traversal_source(scenario):
+     # some tests create data - create a fresh remote to the empty graph and 
clear that graph prior to each test
 -    remote = DriverRemoteConnection('ws://localhost:45940/gremlin', "ggraph")
++    remote = DriverRemoteConnection('ws://localhost:45940/gremlin', "ggraph", 
message_serializer=serializer.GraphSONSerializersV2d0())
+     scenario.context.remote_conn["empty"] = remote
+     g = Graph().traversal().withRemote(remote)
+     g.V().drop().iterate()
+ 
+ 
+ @after.each_scenario
+ def close_traversal_source(scenario):
+     scenario.context.remote_conn["empty"].close()
+ 
+ 
+ @after.all
+ def close_static_traversal_source(features, marker):
+     for key, value in world.cache.iteritems():
+         value["remote_conn"].close()
+ 
+ 
+ def __create_remote(server_graph_name):
 -    return DriverRemoteConnection('ws://localhost:45940/gremlin', 
server_graph_name)
++    return DriverRemoteConnection('ws://localhost:45940/gremlin', 
server_graph_name, message_serializer=serializer.GraphSONSerializersV2d0())
+ 
+ 
+ def __create_lookup_v(remote):
+     g = Graph().traversal().withRemote(remote)
+ 
+     # hold a map of name/vertex for use in asserting results
+     return g.V().group().by('name').by(tail()).next()
+ 
+ 
+ def __create_lookup_e(remote):
+     g = Graph().traversal().withRemote(remote)
+ 
+     # hold a map of the "name"/edge for use in asserting results - "name" in 
this context is in the form of
+     # outgoingV-label->incomingV
 -    projection_of_edges = g.E().group(). \
 -        by(project("o", "l", "i").
 -           by(outV().values("name")).
 -           by(label()).
 -           by(inV().values("name"))). \
++    return g.E().group(). \
++        by(lambda: ("it.outVertex().value('name') + '-' + it.label() + '->' + 
it.inVertex().value('name')", "gremlin-groovy")).\
+         by(tail()).next()
 -    edges = {}
 -
 -    # in GraphSON 3.0 the "key" will be a dictionary and this can work more 
nicely - right now it's stuck as
 -    # a string and has to be parsed
 -    for key, value in projection_of_edges.items():
 -        o = re.search("o=(.+?)[,\}]", key).group(1)
 -        l = re.search("l=(.+?)[,\}]", key).group(1)
 -        i = re.search("i=(.+?)[,\}]", key).group(1)
 -        edges[o + "-" + l + "->" + i] = value
 -
 -    return edges

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/driver/remote/gremlin-server-integration.yaml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-server/src/test/scripts/test-server-start.groovy
----------------------------------------------------------------------
diff --cc gremlin-server/src/test/scripts/test-server-start.groovy
index c187752,157f01c..00ebb59
--- a/gremlin-server/src/test/scripts/test-server-start.groovy
+++ b/gremlin-server/src/test/scripts/test-server-start.groovy
@@@ -25,9 -25,16 +25,16 @@@ if (Boolean.parseBoolean(skipTests)) re
  
  log.info("Starting Gremlin Server instances for native testing of 
${executionName}")
  def settings = Settings.read("${settingsFile}")
- settings.graphs.graph = gremlinServerDir + 
"/conf/tinkergraph-empty.properties"
- 
settings.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files
 = [gremlinServerDir + "/scripts/generate-modern.groovy"]
- settings.serializers << new 
SerializerSettings("org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0",
 [:])
+ settings.graphs.graph = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
+ settings.graphs.classic = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
+ settings.graphs.modern = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
+ settings.graphs.crew = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
+ settings.graphs.grateful = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
 -settings.scriptEngines["gremlin-groovy"].scripts = [gremlinServerDir + 
"/src/test/scripts/generate-all.groovy"]
++settings.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files
 = [gremlinServerDir + "/src/test/scripts/generate-all.groovy"]
+ if (Boolean.parseBoolean(python)) {
+     settings.scriptEngines["gremlin-python"] = new 
Settings.ScriptEngineSettings()
+     settings.scriptEngines["gremlin-jython"] = new 
Settings.ScriptEngineSettings()
+ }
  settings.port = 45940
  
  def server = new GremlinServer(settings)
@@@ -36,22 -43,20 +43,29 @@@ server.start().join(
  project.setContextValue("gremlin.server", server)
  log.info("Gremlin Server with no authentication started on port 45940")
  
 +def securePropsFile = new 
File("${projectBaseDir}/target/tinkergraph-credentials.properties")
 +if (!securePropsFile.exists()) {
 +    securePropsFile.createNewFile()
 +    securePropsFile << 
"gremlin.graph=org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph\n"
 +    securePropsFile << "gremlin.tinkergraph.vertexIdManager=LONG\n"
 +    securePropsFile << 
"gremlin.tinkergraph.graphLocation=${gremlinServerDir}/data/credentials.kryo\n"
 +    securePropsFile << "gremlin.tinkergraph.graphFormat=gryo"
 +}
 +
  def settingsSecure = Settings.read("${settingsFile}")
- settingsSecure.graphs.graph = gremlinServerDir + 
"/conf/tinkergraph-empty.properties"
- 
settingsSecure.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files
 = [gremlinServerDir + "/scripts/generate-modern.groovy"]
- settingsSecure.serializers << new 
SerializerSettings("org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0",
 [:])
+ settingsSecure.graphs.graph = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
+ settingsSecure.graphs.classic = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
+ settingsSecure.graphs.modern = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
+ settingsSecure.graphs.crew = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
+ settingsSecure.graphs.grateful = gremlinServerDir + 
"/src/test/scripts/tinkergraph-empty.properties"
 -settingsSecure.scriptEngines["gremlin-groovy"].scripts = [gremlinServerDir + 
"/src/test/scripts/generate-all.groovy"]
++settingsSecure.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files
 = [gremlinServerDir + "/src/test/scripts/generate-all.groovy"]
+ if (Boolean.parseBoolean(python)) {
+     settingsSecure.scriptEngines["gremlin-python"] = new 
Settings.ScriptEngineSettings()
+     settingsSecure.scriptEngines["gremlin-jython"] = new 
Settings.ScriptEngineSettings()
+ }
  settingsSecure.port = 45941
 -settingsSecure.authentication.className = SimpleAuthenticator.class.name
 -settingsSecure.authentication.config = [credentialsDb: gremlinServerDir + 
"/conf/tinkergraph-credentials.properties", credentialsDbLocation: 
gremlinServerDir + "/data/credentials.kryo"]
 +settingsSecure.authentication.authenticator = 
"org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator"
 +settingsSecure.authentication.config = [credentialsDb: projectBaseDir + 
"/target/tinkergraph-credentials.properties"]
  
  def serverSecure = new GremlinServer(settingsSecure)
  serverSecure.start().join()

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-test/features/filter/Range.feature
----------------------------------------------------------------------
diff --cc gremlin-test/features/filter/Range.feature
index 0000000,42e2f9a..d9e7f23
mode 000000,100644..100644
--- a/gremlin-test/features/filter/Range.feature
+++ b/gremlin-test/features/filter/Range.feature
@@@ -1,0 -1,228 +1,171 @@@
+ # 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.
+ 
+ Feature: Step - range()
+ 
+   Scenario: g_VX1X_out_limitX2X
+     Given the modern graph
+     And using the parameter v1Id defined as "v[marko].id"
+     And the traversal of
+       """
+       g.V(v1Id).out().limit(2)
+       """
+     When iterated to list
+     Then the result should be of
+       | result |
+       | v[josh] |
+       | v[vadas] |
+       | v[lop] |
+     And the result should have a count of 2
+ 
+   Scenario: g_V_localXoutE_limitX1X_inVX_limitX3X
+     Given the modern graph
+     And the traversal of
+       """
+       g.V().local(__.outE().limit(1)).inV().limit(3)
+       """
+     When iterated to list
+     Then the result should be of
+       | result |
+       | v[josh] |
+       | v[vadas] |
+       | v[lop] |
+       | v[ripple] |
+     And the result should have a count of 3
+ 
+   Scenario: g_VX1X_outXknowsX_outEXcreatedX_rangeX0_1X_inV
+     Given the modern graph
+     And using the parameter v1Id defined as "v[marko].id"
+     And the traversal of
+       """
+       g.V(v1Id).out("knows").outE("created").range(0, 1).inV()
+       """
+     When iterated to list
+     Then the result should be of
+       | result |
+       | v[lop] |
+       | v[ripple] |
+     And the result should have a count of 1
+ 
+   Scenario: g_VX1X_outXknowsX_outXcreatedX_rangeX0_1X
+     Given the modern graph
+     And using the parameter v1Id defined as "v[marko].id"
+     And the traversal of
+       """
+       g.V(v1Id).out("knows").out("created").range(0, 1)
+       """
+     When iterated to list
+     Then the result should be of
+       | result |
+       | v[lop] |
+       | v[ripple] |
+     And the result should have a count of 1
+ 
+   Scenario: g_VX1X_outXcreatedX_inXcreatedX_rangeX1_3X
+     Given the modern graph
+     And using the parameter v1Id defined as "v[marko].id"
+     And the traversal of
+       """
+       g.V(v1Id).out("created").in("created").range(1, 3)
+       """
+     When iterated to list
+     Then the result should be of
+       | result |
+       | v[marko] |
+       | v[josh] |
+       | v[peter] |
+     And the result should have a count of 2
+ 
+   Scenario: get_g_VX1X_outXcreatedX_inEXcreatedX_rangeX1_3X_outV
+     Given the modern graph
+     And using the parameter v1Id defined as "v[marko].id"
+     And the traversal of
+       """
+       g.V(v1Id).out("created").inE("created").range(1, 3).outV()
+       """
+     When iterated to list
+     Then the result should be of
+       | result |
+       | v[marko] |
+       | v[josh] |
+       | v[peter] |
+     And the result should have a count of 2
+ 
+   Scenario: get_g_V_repeatXbothX_timesX3X_rangeX5_11X
+     Given the modern graph
+     And the traversal of
+       """
+       g.V().repeat(__.both()).times(3).range(5, 11)
+       """
+     When iterated to list
+     Then the result should be of
+       | result |
+       | v[marko] |
+       | v[josh] |
+       | v[peter] |
+       | v[lop] |
+       | v[vadas] |
+       | v[ripple] |
+     And the result should have a count of 6
+ 
 -  Scenario: 
g_V_asXaX_in_asXaX_in_asXaX_selectXaX_byXunfold_valuesXnameX_foldX_limitXlocal_2X
 -    Given the modern graph
 -    And the traversal of
 -      """
 -      
g.V().as("a").in().as("a").in().as("a").select("a").by(__.unfold().values("name").fold()).limit(Scope.local,
 2)
 -      """
 -    When iterated to list
 -    Then the result should be unordered
 -      | result |
 -      | l[lop,josh] |
 -      | l[ripple,josh] |
 -
 -  Scenario: 
g_V_asXaX_in_asXaX_in_asXaX_selectXaX_byXunfold_valuesXnameX_foldX_limitXlocal_1X
 -    Given the modern graph
 -    And the traversal of
 -      """
 -      
g.V().as("a").in().as("a").in().as("a").select("a").by(__.unfold().values("name").fold()).limit(Scope.local,
 1)
 -      """
 -    When iterated to list
 -    Then the result should be unordered
 -      | result |
 -      | lop |
 -      | ripple |
 -
 -  Scenario: 
g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_valuesXnameX_foldX_rangeXlocal_1_3X
 -    Given the modern graph
 -    And the traversal of
 -      """
 -      
g.V().as("a").out().as("a").out().as("a").select("a").by(__.unfold().values("name").fold()).range(Scope.local,
 1, 3)
 -      """
 -    When iterated to list
 -    Then the result should be unordered
 -      | result |
 -      | l[josh,ripple] |
 -      | l[josh,lop] |
 -
 -  Scenario: 
g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_valuesXnameX_foldX_rangeXlocal_1_2X
 -    Given the modern graph
 -    And the traversal of
 -      """
 -      
g.V().as("a").out().as("a").out().as("a").select("a").by(__.unfold().values("name").fold()).range(Scope.local,
 1, 2)
 -      """
 -    When iterated to list
 -    Then the result should be unordered
 -      | result |
 -      | josh |
 -      | josh |
 -
 -  Scenario: 
g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_valuesXnameX_foldX_rangeXlocal_4_5X
 -    Given the modern graph
 -    And the traversal of
 -      """
 -      
g.V().as("a").out().as("a").out().as("a").select("a").by(__.unfold().values("name").fold()).range(Scope.local,
 4, 5)
 -      """
 -    When iterated to list
 -    Then the result should be empty
 -
+   Scenario: g_V_asXaX_in_asXbX_in_asXcX_selectXa_b_cX_byXnameX_limitXlocal_2X
+     Given the modern graph
+     And the traversal of
+       """
+       
g.V().as("a").in().as("b").in().as("c").select("a","b","c").by("name").limit(Scope.local,
 2)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | m[{"a":"lop","b":"josh"}] |
+       | m[{"a":"ripple","b":"josh"}] |
+ 
+   Scenario: g_V_asXaX_in_asXbX_in_asXcX_selectXa_b_cX_byXnameX_limitXlocal_1X
+     Given the modern graph
+     And the traversal of
+       """
+       
g.V().as("a").in().as("b").in().as("c").select("a","b","c").by("name").limit(Scope.local,
 1)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | m[{"a":"lop"}] |
+       | m[{"a":"ripple"}] |
+ 
+   Scenario: 
g_V_asXaX_out_asXbX_out_asXcX_selectXa_b_cX_byXnameX_rangeXlocal_1_3X
+     Given the modern graph
+     And the traversal of
+       """
+       
g.V().as("a").out().as("b").out().as("c").select("a","b","c").by("name").range(Scope.local,
 1, 3)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | m[{"b":"josh","c":"lop"}] |
+       | m[{"b":"josh","c":"ripple"}] |
+ 
+   Scenario: 
g_V_asXaX_out_asXbX_out_asXcX_selectXa_b_cX_byXnameX_rangeXlocal_1_2X
+     Given the modern graph
+     And the traversal of
+       """
+       
g.V().as("a").out().as("b").out().as("c").select("a","b","c").by("name").range(Scope.local,
 1, 2)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | m[{"b":"josh"}] |
+       | m[{"b":"josh"}] |

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/04c52201/gremlin-test/features/filter/Tail.feature
----------------------------------------------------------------------
diff --cc gremlin-test/features/filter/Tail.feature
index 0000000,b2daa2b..ef0643e
mode 000000,100644..100644
--- a/gremlin-test/features/filter/Tail.feature
+++ b/gremlin-test/features/filter/Tail.feature
@@@ -1,0 -1,166 +1,145 @@@
+ # 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.
+ 
+ Feature: Step - tail()
+ 
+   Scenario: g_V_valuesXnameX_order_tailXglobal_2X
+     Given the modern graph
+     And the traversal of
+       """
+       g.V().values("name").order().tail(Scope.global, 2)
+       """
+     When iterated to list
+     Then the result should be ordered
+       | result |
+       | ripple |
+       | vadas |
+ 
+   Scenario: g_V_valuesXnameX_order_tailX2X
+     Given the modern graph
+     And the traversal of
+       """
+       g.V().values("name").order().tail(2)
+       """
+     When iterated to list
+     Then the result should be ordered
+       | result |
+       | ripple |
+       | vadas |
+ 
+   Scenario: g_V_valuesXnameX_order_tail
+     Given the modern graph
+     And the traversal of
+       """
+       g.V().values("name").order().tail()
+       """
+     When iterated to list
+     Then the result should be ordered
+       | result |
+       | vadas |
+ 
+   Scenario: g_V_valuesXnameX_order_tailX7X
+     Given the modern graph
+     And the traversal of
+       """
+       g.V().values("name").order().tail(7)
+       """
+     When iterated to list
+     Then the result should be ordered
+       | result |
+       | josh   |
+       | lop    |
+       | marko  |
+       | peter  |
+       | ripple |
+       | vadas  |
+ 
+   Scenario: g_V_repeatXbothX_timesX3X_tailX7X
+     Given the modern graph
+     And the traversal of
+       """
+       g.V().repeat(__.both()).times(3).tail(7)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | v[peter] |
+       | v[peter] |
+       | v[peter] |
+       | v[peter] |
+       | v[marko] |
+       | v[marko] |
+       | v[marko] |
+ 
+   Scenario: g_V_repeatXin_outX_timesX3X_tailX7X_count
+     Given the modern graph
+     And the traversal of
+       """
+       g.V().repeat(__.in().out()).times(3).tail(7).count()
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | d[7].l |
+ 
 -  Scenario: 
g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_valuesXnameX_foldX_tailXlocal_2X
 -    Given the modern graph
 -    And the traversal of
 -      """
 -      
g.V().as("a").out().as("a").out().as("a").select("a").by(__.unfold().values("name").fold()).tail(Scope.local,
 2)
 -      """
 -    When iterated to list
 -    Then the result should be unordered
 -      | result |
 -      | l[josh,ripple] |
 -      | l[josh,lop] |
 -
+   Scenario: 
g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_valuesXnameX_foldX_tailXlocal_1X
+     Given the modern graph
+     And the traversal of
+       """
+       
g.V().as("a").out().as("a").out().as("a").select("a").by(__.unfold().values("name").fold()).tail(Scope.local,
 1)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | ripple |
+       | lop |
+ 
+   Scenario: 
g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXunfold_valuesXnameX_foldX_tailXlocalX
+     Given the modern graph
+     And the traversal of
+       """
+       
g.V().as("a").out().as("a").out().as("a").select("a").by(__.unfold().values("name").fold()).tail(Scope.local)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | ripple |
+       | lop |
+ 
 -  Scenario: 
g_V_asXaX_out_asXaX_out_asXaX_selectXaX_byXlimitXlocal_0XX_tailXlocal_1X
 -    Given the modern graph
 -    And the traversal of
 -      """
 -      
g.V().as("a").out().as("a").out().as("a").select("a").by(__.limit(Scope.local, 
0)).tail(Scope.local, 1)
 -      """
 -    When iterated to list
 -    Then the result should be empty
 -
+   Scenario: g_V_asXaX_out_asXbX_out_asXcX_selectXa_b_cX_byXnameX_tailXlocal_2X
+     Given the modern graph
+     And the traversal of
+       """
+       
g.V().as("a").out().as("b").out().as("c").select("a","b","c").by("name").tail(Scope.local,
 2)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | m[{"b":"josh","c":"ripple"}] |
+       | m[{"b":"josh","c":"lop"}] |
+ 
+   Scenario: g_V_asXaX_out_asXbX_out_asXcX_selectXa_b_cX_byXnameX_tailXlocal_1X
+     Given the modern graph
+     And the traversal of
+       """
+       
g.V().as("a").out().as("b").out().as("c").select("a","b","c").by("name").tail(Scope.local,
 1)
+       """
+     When iterated to list
+     Then the result should be unordered
+       | result |
+       | m[{"c":"ripple"}] |
+       | m[{"c":"lop"}] |

Reply via email to