You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by co...@apache.org on 2023/05/31 23:47:06 UTC

[tinkerpop] branch 3.6-dev updated: Run feature tests against a driver/server configuration.

This is an automated email from the ASF dual-hosted git repository.

colegreer pushed a commit to branch 3.6-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/3.6-dev by this push:
     new 78b38a36c1 Run feature tests against a driver/server configuration.
     new ce14b3a5bf Merge pull request #2075 from Bit-Quill/ken/remotecucumberfeaturetests
78b38a36c1 is described below

commit 78b38a36c136e8690ee7995457e51c8a826276f5
Author: Ken Hu <10...@users.noreply.github.com>
AuthorDate: Mon May 15 15:08:18 2023 -0700

    Run feature tests against a driver/server configuration.
    
    RemoteOnly still required because the Java StepDefinition uses
    gremlin-language to parse the scenario query which contains a lambda
    which isn't supported.
    
    Bytecode copied because the server needs it for formatting a Failure.
---
 CHANGELOG.asciidoc                                 |   1 +
 .../strategy/decoration/VertexProgramStrategy.java |   2 +-
 gremlin-server/pom.xml                             |   6 +
 .../gremlin/driver/remote/AbstractFeatureTest.java |  50 ++++++
 .../GraphBinaryRemoteComputerFeatureTest.java      |  51 ++++++
 .../remote/GraphBinaryRemoteFeatureTest.java       |  51 ++++++
 .../remote/GraphSONRemoteComputerFeatureTest.java  |  51 ++++++
 .../driver/remote/GraphSONRemoteFeatureTest.java   |  51 ++++++
 .../gremlin/driver/remote/RemoteWorld.java         | 187 +++++++++++++++++++++
 .../io.cucumber.core.backend.ObjectFactory         |   4 +
 10 files changed, 453 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 56a14fc190..b2fa162788 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -27,6 +27,7 @@ This release also includes changes from <<release-3-5-7, 3.5.7>>.
 
 * Added `text/plain` MIME type to the HTTP endpoint to return a Gremlin Console-like representation of the data.
 * Added GraphBinary serialization option to the HTTP endpoint.
+* Fixed bug with `fail` step not working with a `VertexProgram` running on the server.
 
 [[release-3-6-4]]
 === TinkerPop 3.6.4 (Release Date: May 12, 2023)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
index 8c2e28ac40..0ca3dc00f1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
@@ -104,7 +104,7 @@ public final class VertexProgramStrategy extends AbstractTraversalStrategy<Trave
         // wrap all non-VertexComputing steps into a TraversalVertexProgramStep
         currentStep = traversal.getStartStep();
         while (!(currentStep instanceof EmptyStep)) {
-            final Traversal.Admin<?, ?> computerTraversal = new DefaultTraversal<>();
+            final Traversal.Admin<?, ?> computerTraversal = new DefaultTraversal<>(traversal.getBytecode());
             final Step<?, ?> firstLegalOLAPStep = getFirstLegalOLAPStep(currentStep);
             final Step<?, ?> lastLegalOLAPStep = getLastLegalOLAPStep(currentStep);
             if (!(firstLegalOLAPStep instanceof EmptyStep)) {
diff --git a/gremlin-server/pom.xml b/gremlin-server/pom.xml
index 35e17cf2c1..a704739117 100644
--- a/gremlin-server/pom.xml
+++ b/gremlin-server/pom.xml
@@ -92,6 +92,12 @@ limitations under the License.
             <artifactId>httpclient</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <version>${guice.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.tinkerpop</groupId>
             <artifactId>neo4j-gremlin</artifactId>
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/AbstractFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/AbstractFeatureTest.java
new file mode 100644
index 0000000000..387ae280ec
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/AbstractFeatureTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.driver.remote;
+
+import org.apache.tinkerpop.gremlin.server.GremlinServer;
+import org.apache.tinkerpop.gremlin.server.ServerTestHelper;
+import org.apache.tinkerpop.gremlin.server.Settings;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Abstract class that contains the setup and teardown for running feature tests.
+ */
+public abstract class AbstractFeatureTest {
+    private static GremlinServer server;
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        final InputStream stream = GremlinServer.class.getResourceAsStream("gremlin-server-integration.yaml");
+        final Settings settings = Settings.read(stream);
+        ServerTestHelper.rewritePathsInGremlinServerSettings(settings);
+
+        server = new GremlinServer(settings);
+        server.start().get(100, TimeUnit.SECONDS);
+    }
+
+    @AfterClass
+    public static void tearDown() throws Exception {
+        server.stop().get(100, TimeUnit.SECONDS);
+    }
+}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteComputerFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteComputerFeatureTest.java
new file mode 100644
index 0000000000..dd03370c48
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteComputerFeatureTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.driver.remote;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Stage;
+import io.cucumber.guice.CucumberModules;
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.apache.tinkerpop.gremlin.features.AbstractGuiceFactory;
+import org.apache.tinkerpop.gremlin.features.World;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(
+        tags = "not @RemoteOnly and not @GraphComputerVerificationElementSupported",
+        glue = { "org.apache.tinkerpop.gremlin.features" },
+        objectFactory = GraphBinaryRemoteComputerFeatureTest.RemoteGuiceFactory.class,
+        features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
+        plugin = {"progress", "junit:target/cucumber.xml"})
+public class GraphBinaryRemoteComputerFeatureTest extends AbstractFeatureTest {
+    public static class RemoteGuiceFactory extends AbstractGuiceFactory {
+        public RemoteGuiceFactory() {
+            super(Guice.createInjector(Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule()));
+        }
+    }
+
+    public static final class ServiceModule extends AbstractModule {
+        @Override
+        protected void configure() {
+            bind(World.class).to(RemoteWorld.GraphBinaryRemoteComputerWorld.class);
+        }
+    }
+}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteFeatureTest.java
new file mode 100644
index 0000000000..91c7fff3b7
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteFeatureTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.driver.remote;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Stage;
+import io.cucumber.guice.CucumberModules;
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.apache.tinkerpop.gremlin.features.AbstractGuiceFactory;
+import org.apache.tinkerpop.gremlin.features.World;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(
+        tags = "not @RemoteOnly and not @GraphComputerOnly and not @AllowNullPropertyValues",
+        glue = { "org.apache.tinkerpop.gremlin.features" },
+        objectFactory = GraphBinaryRemoteFeatureTest.RemoteGuiceFactory.class,
+        features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
+        plugin = {"progress", "junit:target/cucumber.xml"})
+public class GraphBinaryRemoteFeatureTest extends AbstractFeatureTest {
+    public static class RemoteGuiceFactory extends AbstractGuiceFactory {
+        public RemoteGuiceFactory() {
+            super(Guice.createInjector(Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule()));
+        }
+    }
+
+    public static final class ServiceModule extends AbstractModule {
+        @Override
+        protected void configure() {
+            bind(World.class).to(RemoteWorld.GraphBinaryRemoteWorld.class);
+        }
+    }
+}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteComputerFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteComputerFeatureTest.java
new file mode 100644
index 0000000000..ed170e470f
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteComputerFeatureTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.driver.remote;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Stage;
+import io.cucumber.guice.CucumberModules;
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.apache.tinkerpop.gremlin.features.AbstractGuiceFactory;
+import org.apache.tinkerpop.gremlin.features.World;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(
+        tags = "not @RemoteOnly and not @GraphComputerVerificationElementSupported",
+        glue = { "org.apache.tinkerpop.gremlin.features" },
+        objectFactory = GraphSONRemoteComputerFeatureTest.RemoteGuiceFactory.class,
+        features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
+        plugin = {"progress", "junit:target/cucumber.xml"})
+public class GraphSONRemoteComputerFeatureTest extends AbstractFeatureTest {
+    public static class RemoteGuiceFactory extends AbstractGuiceFactory {
+        public RemoteGuiceFactory() {
+            super(Guice.createInjector(Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule()));
+        }
+    }
+
+    public static final class ServiceModule extends AbstractModule {
+        @Override
+        protected void configure() {
+            bind(World.class).to(RemoteWorld.GraphSONRemoteComputerWorld.class);
+        }
+    }
+}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteFeatureTest.java
new file mode 100644
index 0000000000..901ac413b1
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteFeatureTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.driver.remote;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Stage;
+import io.cucumber.guice.CucumberModules;
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.apache.tinkerpop.gremlin.features.AbstractGuiceFactory;
+import org.apache.tinkerpop.gremlin.features.World;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(
+        tags = "not @RemoteOnly and not @GraphComputerOnly and not @AllowNullPropertyValues",
+        glue = { "org.apache.tinkerpop.gremlin.features" },
+        objectFactory = GraphSONRemoteFeatureTest.RemoteGuiceFactory.class,
+        features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
+        plugin = {"progress", "junit:target/cucumber.xml"})
+public class GraphSONRemoteFeatureTest extends AbstractFeatureTest {
+    public static class RemoteGuiceFactory extends AbstractGuiceFactory {
+        public RemoteGuiceFactory() {
+            super(Guice.createInjector(Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule()));
+        }
+    }
+
+    public static final class ServiceModule extends AbstractModule {
+        @Override
+        protected void configure() {
+            bind(World.class).to(RemoteWorld.GraphSONRemoteWorld.class);
+        }
+    }
+}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
new file mode 100644
index 0000000000..0b1ac62b4b
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.driver.remote;
+
+import io.cucumber.java.Scenario;
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.TestHelper;
+import org.apache.tinkerpop.gremlin.driver.Client;
+import org.apache.tinkerpop.gremlin.driver.Cluster;
+import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.features.World;
+import org.apache.tinkerpop.gremlin.process.computer.Computer;
+import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.server.GremlinServer;
+import org.apache.tinkerpop.gremlin.server.ServerTestHelper;
+import org.apache.tinkerpop.gremlin.server.Settings;
+import org.apache.tinkerpop.gremlin.server.TestClientFactory;
+import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComputer;
+import org.junit.AssumptionViolatedException;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * The abstract {@link World} implementation for driver/server that provides the {@link GraphTraversalSource} instances
+ * required by the Gherkin test suite. A new cluster and client is injected per scenario. To reduce runtime of the
+ * tests, the same server is used for every scenario.
+ */
+public abstract class RemoteWorld implements World {
+    private final Cluster cluster;
+
+    /**
+     * Helper method to create a test cluster based on the type of serializer. Can be used by implementations to help
+     * construct a RemoteWorld.
+     */
+    public static Cluster createTestCluster(final Serializers serializer) {
+        return TestClientFactory.build().serializer(serializer).create();
+    }
+
+    public RemoteWorld(Cluster cluster) {
+        this.cluster = cluster;
+    }
+
+    @Override
+    public void afterEachScenario() {
+        cluster.close();
+    }
+
+    @Override
+    public GraphTraversalSource getGraphTraversalSource(final LoadGraphWith.GraphData graphData) {
+        String remoteTraversalSource = "g"; // these names are from gremlin-server-integration.yaml
+        final Client client = cluster.connect();
+
+        if (null == graphData) {
+            try { // Clear data before run because tests are allowed to modify data for the empty graph.
+                client.submit("graph.clear();").all().get();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            remoteTraversalSource = "ggraph";
+        } else {
+            switch (graphData) {
+                case CLASSIC:
+                    remoteTraversalSource = "gclassic";
+                    break;
+                case CREW:
+                    remoteTraversalSource = "gcrew";
+                    break;
+                case MODERN:
+                    remoteTraversalSource = "gmodern";
+                    break;
+                case SINK:
+                    remoteTraversalSource = "gsink";
+                    break;
+                case GRATEFUL:
+                    remoteTraversalSource = "ggrateful";
+                    break;
+                default:
+                    throw new UnsupportedOperationException("GraphData not supported: " + graphData.name());
+            }
+        }
+
+        return AnonymousTraversalSource.traversal().withRemote(DriverRemoteConnection.using(client, remoteTraversalSource));
+    }
+
+    @Override
+    public String changePathToDataFile(final String pathToFileFromGremlin) {
+        return ".." + File.separator + pathToFileFromGremlin;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * The abstract {@link World} implementation for driver/server that provides the {@link GraphTraversalSource}
+     * instances that include the VertexProgramStrategy.
+     */
+    public abstract static class RemoteComputerWorld extends RemoteWorld {
+        private static final List<String> TAGS_TO_IGNORE = Arrays.asList(
+                "@StepDrop",
+                "@StepInject",
+                "@StepV",
+                "@GraphComputerVerificationOneBulk",
+                "@GraphComputerVerificationStrategyNotSupported",
+                "@GraphComputerVerificationMidVNotSupported",
+                "@GraphComputerVerificationInjectionNotSupported",
+                "@GraphComputerVerificationStarGraphExceeded",
+                "@GraphComputerVerificationReferenceOnly",
+                "@TinkerServiceRegistry");
+
+        private final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
+
+        public RemoteComputerWorld(Cluster cluster) {
+            super(cluster);
+        }
+
+        @Override
+        public void beforeEachScenario(final Scenario scenario) {
+            final List<String> ignores = TAGS_TO_IGNORE.stream().filter(t -> scenario.getSourceTagNames().contains(t)).collect(Collectors.toList());
+            if (!ignores.isEmpty())
+                throw new AssumptionViolatedException(String.format("This scenario is not supported with GraphComputer: %s", ignores));
+        }
+
+        @Override
+        public GraphTraversalSource getGraphTraversalSource(final LoadGraphWith.GraphData graphData) {
+            if (null == graphData) throw new AssumptionViolatedException("GraphComputer does not support mutation");
+
+            final int state = TestHelper.RANDOM.nextInt(3);
+            switch (state) {
+                case 0:
+                    return super.getGraphTraversalSource(graphData).withComputer();
+                case 1:
+                    return super.getGraphTraversalSource(graphData).withComputer(Computer.compute(TinkerGraphComputer.class));
+                case 2:
+                    return super.getGraphTraversalSource(graphData)
+                            .withComputer(Computer.compute(TinkerGraphComputer.class)
+                                    .workers(TestHelper.RANDOM.nextInt(AVAILABLE_PROCESSORS) + 1));
+                default:
+                    throw new IllegalStateException("This state should not have occurred: " + state);
+            }
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static class GraphBinaryRemoteWorld extends RemoteWorld {
+        public GraphBinaryRemoteWorld() { super(createTestCluster(Serializers.GRAPHBINARY_V1D0)); }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static class GraphBinaryRemoteComputerWorld extends RemoteComputerWorld {
+        public GraphBinaryRemoteComputerWorld() { super(createTestCluster(Serializers.GRAPHBINARY_V1D0)); }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static class GraphSONRemoteWorld extends RemoteWorld {
+        public GraphSONRemoteWorld() { super(createTestCluster(Serializers.GRAPHSON_V3D0)); }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static class GraphSONRemoteComputerWorld extends RemoteComputerWorld {
+        public GraphSONRemoteComputerWorld() { super(createTestCluster(Serializers.GRAPHSON_V3D0)); }
+    }
+}
diff --git a/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory b/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
new file mode 100644
index 0000000000..023350111b
--- /dev/null
+++ b/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
@@ -0,0 +1,4 @@
+org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryRemoteFeatureTest$RemoteGuiceFactory
+org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryRemoteComputerFeatureTest$RemoteGuiceFactory
+org.apache.tinkerpop.gremlin.driver.remote.GraphSONRemoteFeatureTest$RemoteGuiceFactory
+org.apache.tinkerpop.gremlin.driver.remote.GraphSONRemoteComputerFeatureTest$RemoteGuiceFactory