tinkerpop-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From spmalle...@apache.org
Subject [04/15] tinkerpop git commit: TINKERPOP-1612 WIP - first step to removal of gremlin-groovy-test
Date Thu, 26 Jan 2017 19:57:37 GMT
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java
new file mode 100644
index 0000000..84542e1
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java
@@ -0,0 +1,406 @@
+/*
+ * 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.groovy.jsr223;
+
+import groovy.lang.MissingPropertyException;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider;
+import org.apache.tinkerpop.gremlin.groovy.DefaultImportCustomizerProvider;
+import org.apache.tinkerpop.gremlin.groovy.NoImportCustomizerProvider;
+import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.apache.tinkerpop.gremlin.util.config.YamlConfiguration;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.script.Bindings;
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GremlinGroovyScriptEngineOverGraphTest {
+
+    @Test
+    public void shouldDoSomeGremlin() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final ScriptEngine engine = new GremlinGroovyScriptEngine();
+        final List list = new ArrayList();
+        final Bindings bindings = engine.createBindings();
+        bindings.put("g", g);
+        bindings.put("marko", convertToVertexId(graph, "marko"));
+        bindings.put("temp", list);
+        assertEquals(list.size(), 0);
+        engine.eval("g.V(marko).out().fill(temp)",bindings);
+        assertEquals(list.size(), 3);
+    }
+
+    @Test
+    public void shouldLoadImports() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final ScriptEngine engineNoImports = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) NoImportCustomizerProvider.INSTANCE);
+        try {
+            engineNoImports.eval("Vertex.class.getName()");
+            fail("Should have thrown an exception because no imports were supplied");
+        } catch (Exception se) {
+            assertTrue(se instanceof ScriptException);
+        }
+
+        final ScriptEngine engineWithImports = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) new DefaultImportCustomizerProvider());
+        engineWithImports.put("g", g);
+        assertEquals(Vertex.class.getName(), engineWithImports.eval("Vertex.class.getName()"));
+        assertEquals(2l, engineWithImports.eval("g.V().has('age',gt(30)).count().next()"));
+        assertEquals(Direction.IN, engineWithImports.eval("Direction.IN"));
+        assertEquals(Direction.OUT, engineWithImports.eval("Direction.OUT"));
+        assertEquals(Direction.BOTH, engineWithImports.eval("Direction.BOTH"));
+    }
+
+
+    @Test
+    public void shouldLoadStandardImportsAndThenAddToThem() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) new DefaultImportCustomizerProvider());
+        engine.put("g", g);
+        assertEquals(Vertex.class.getName(), engine.eval("Vertex.class.getName()"));
+        assertEquals(2l, engine.eval("g.V().has('age',gt(30)).count().next()"));
+        assertEquals(Direction.IN, engine.eval("Direction.IN"));
+        assertEquals(Direction.OUT, engine.eval("Direction.OUT"));
+        assertEquals(Direction.BOTH, engine.eval("Direction.BOTH"));
+
+        try {
+            engine.eval("YamlConfiguration.class.getName()");
+            fail("Should have thrown an exception because no imports were supplied");
+        } catch (Exception se) {
+            assertTrue(se instanceof ScriptException);
+        }
+
+        engine.addImports(new HashSet<>(Arrays.asList("import " + YamlConfiguration.class.getCanonicalName())));
+        engine.put("g", g);
+        assertEquals(YamlConfiguration.class.getName(), engine.eval("YamlConfiguration.class.getName()"));
+        assertEquals(Vertex.class.getName(), engine.eval("Vertex.class.getName()"));
+        assertEquals(2l, engine.eval("g.V().has('age',gt(30)).count().next()"));
+        assertEquals(Direction.IN, engine.eval("Direction.IN"));
+        assertEquals(Direction.OUT, engine.eval("Direction.OUT"));
+        assertEquals(Direction.BOTH, engine.eval("Direction.BOTH"));
+    }
+
+    @Test
+    public void shouldProperlyHandleBindings() throws Exception {
+        final Graph graph = TinkerFactory.createClassic();
+        final GraphTraversalSource g = graph.traversal();
+        final ScriptEngine engine = new GremlinGroovyScriptEngine();
+        engine.put("g", g);
+        engine.put("marko", convertToVertexId(graph, "marko"));
+        Assert.assertEquals(g.V(convertToVertexId(graph, "marko")).next(), engine.eval("g.V(marko).next()"));
+
+        final Bindings bindings = engine.createBindings();
+        bindings.put("g", g);
+        bindings.put("s", "marko");
+        bindings.put("f", 0.5f);
+        bindings.put("i", 1);
+        bindings.put("b", true);
+        bindings.put("l", 100l);
+        bindings.put("d", 1.55555d);
+
+        assertEquals(engine.eval("g.E().has('weight',f).next()", bindings), g.E(convertToEdgeId(graph, "marko", "knows", "vadas")).next());
+        assertEquals(engine.eval("g.V().has('name',s).next()", bindings), g.V(convertToVertexId(graph, "marko")).next());
+        assertEquals(engine.eval("g.V().sideEffect{it.get().property('bbb',it.get().value('name')=='marko')}.iterate();g.V().has('bbb',b).next()", bindings), g.V(convertToVertexId(graph, "marko")).next());
+        assertEquals(engine.eval("g.V().sideEffect{it.get().property('iii',it.get().value('name')=='marko'?1:0)}.iterate();g.V().has('iii',i).next()", bindings), g.V(convertToVertexId(graph, "marko")).next());
+        assertEquals(engine.eval("g.V().sideEffect{it.get().property('lll',it.get().value('name')=='marko'?100l:0l)}.iterate();g.V().has('lll',l).next()", bindings), g.V(convertToVertexId(graph, "marko")).next());
+        assertEquals(engine.eval("g.V().sideEffect{it.get().property('ddd',it.get().value('name')=='marko'?1.55555d:0)}.iterate();g.V().has('ddd',d).next()", bindings), g.V(convertToVertexId(graph, "marko")).next());
+    }
+
+    @Test
+    public void shouldClearBindingsBetweenEvals() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final ScriptEngine engine = new GremlinGroovyScriptEngine();
+        engine.put("g", g);
+        engine.put("marko", convertToVertexId(graph, "marko"));
+        assertEquals(g.V(convertToVertexId(graph, "marko")).next(), engine.eval("g.V(marko).next()"));
+
+        final Bindings bindings = engine.createBindings();
+        bindings.put("g", g);
+        bindings.put("s", "marko");
+
+        assertEquals(engine.eval("g.V().has('name',s).next()", bindings), g.V(convertToVertexId(graph, "marko")).next());
+
+        try {
+            engine.eval("g.V().has('name',s).next()");
+            fail("This should have failed because s is no longer bound");
+        } catch (Exception ex) {
+            final Throwable t = ExceptionUtils.getRootCause(ex);
+            assertEquals(MissingPropertyException.class, t.getClass());
+            assertTrue(t.getMessage().startsWith("No such property: s for class"));
+        }
+
+    }
+
+    @Test
+    public void shouldBeThreadSafe() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final ScriptEngine engine = new GremlinGroovyScriptEngine();
+
+        int runs = 500;
+        final CountDownLatch latch = new CountDownLatch(runs);
+        final List<String> names = Arrays.asList("marko", "peter", "josh", "vadas", "stephen", "pavel", "matthias");
+        final Random random = new Random();
+
+        for (int i = 0; i < runs; i++) {
+            new Thread("test-thread-safe-" + i) {
+                public void run() {
+                    String name = names.get(random.nextInt(names.size() - 1));
+                    try {
+                        final Bindings bindings = engine.createBindings();
+                        bindings.put("g", g);
+                        bindings.put("name", name);
+                        final Object result = engine.eval("t = g.V().has('name',name); if(t.hasNext()) { t } else { null }", bindings);
+                        if (name.equals("stephen") || name.equals("pavel") || name.equals("matthias"))
+                            assertNull(result);
+                        else
+                            assertNotNull(result);
+                    } catch (ScriptException e) {
+                        assertFalse(true);
+                    } finally {
+                        if (graph.features().graph().supportsTransactions())
+                            g.tx().rollback();
+                    }
+                    latch.countDown();
+                }
+            }.start();
+        }
+        latch.await();
+    }
+
+    @Test
+    public void shouldBeThreadSafeOnCompiledScript() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine();
+        final CompiledScript script = engine.compile("t = g.V().has('name',name); if(t.hasNext()) { t } else { null }");
+
+        int runs = 500;
+        final CountDownLatch latch = new CountDownLatch(runs);
+        final List<String> names = Arrays.asList("marko", "peter", "josh", "vadas", "stephen", "pavel", "matthias");
+        final Random random = new Random();
+
+        for (int i = 0; i < runs; i++) {
+            new Thread("test-thread-safety-on-compiled-script-" + i) {
+                public void run() {
+                    String name = names.get(random.nextInt(names.size() - 1));
+                    try {
+                        final Bindings bindings = engine.createBindings();
+                        bindings.put("g", g);
+                        bindings.put("name", name);
+                        Object result = script.eval(bindings);
+                        if (name.equals("stephen") || name.equals("pavel") || name.equals("matthias"))
+                            assertNull(result);
+                        else
+                            assertNotNull(result);
+                    } catch (ScriptException e) {
+                        //System.out.println(e);
+                        assertFalse(true);
+                    } finally {
+                        if (graph.features().graph().supportsTransactions())
+                            g.tx().rollback();
+                    }
+                    latch.countDown();
+                }
+            }.start();
+        }
+        latch.await();
+    }
+
+    @Test
+    public void shouldEvalGlobalClosuresEvenAfterEvictionOfClass() throws ScriptException {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine();
+
+        final Bindings bindings = engine.createBindings();
+        bindings.put("g", g);
+        bindings.put("marko", convertToVertexId(graph, "marko"));
+        bindings.put("vadas", convertToVertexId(graph, "vadas"));
+
+        // strong referenced global closure
+        engine.eval("def isVadas(v){v.value('name')=='vadas'}", bindings);
+        assertEquals(true, engine.eval("isVadas(g.V(vadas).next())", bindings));
+
+        // phantom referenced global closure
+        bindings.put(GremlinGroovyScriptEngine.KEY_REFERENCE_TYPE, GremlinGroovyScriptEngine.REFERENCE_TYPE_PHANTOM);
+        engine.eval("def isMarko(v){v.value('name')=='marko'}", bindings);
+
+        try {
+            engine.eval("isMarko(g.V(marko).next())", bindings);
+            fail("the isMarko function should not be present");
+        } catch (Exception ex) {
+
+        }
+
+        assertEquals(true, engine.eval("def isMarko(v){v.value('name')=='marko'}; isMarko(g.V(marko).next())", bindings));
+
+        try {
+            engine.eval("isMarko(g.V(marko"
+            		+ ").next())", bindings);
+            fail("the isMarko function should not be present");
+        } catch (Exception ex) {
+
+        }
+
+        bindings.remove(GremlinGroovyScriptEngine.KEY_REFERENCE_TYPE);
+
+        // isVadas class was a hard reference so it should still be hanging about
+        assertEquals(true, engine.eval("isVadas(g.V(vadas).next())", bindings));
+    }
+
+    @Test
+    public void shouldAllowFunctionsUsedInClosure() throws ScriptException {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine();
+
+        final Bindings bindings = engine.createBindings();
+        bindings.put("g", g);
+        bindings.put("#jsr223.groovy.engine.keep.globals", "phantom");
+        bindings.put("vadas", convertToVertexId(graph, "vadas"));
+
+        // this works on its own when the function and the line that uses it is in one "script".  this is the
+        // current workaround
+        assertEquals(g.V(convertToVertexId(graph, "vadas")).next(), engine.eval("def isVadas(v){v.value('name')=='vadas'};g.V().filter{isVadas(it.get())}.next()", bindings));
+
+        // let's reset this piece and make sure isVadas is not hanging around.
+        engine.reset();
+
+        // validate that isVadas throws an exception since it is not defined
+        try {
+            engine.eval("isVadas(g.V(vadas).next())", bindings);
+
+            // fail the test if the above doesn't throw an exception
+            fail();
+        } catch (Exception ex) {
+            // this is good...we want this. it means isVadas isn't hanging about
+        }
+
+        // now...define the function separately on its own in one script
+        bindings.remove("#jsr223.groovy.engine.keep.globals");
+        engine.eval("def isVadas(v){v.value('name')=='vadas'}", bindings);
+
+        // make sure the function works on its own...no problem
+        assertEquals(true, engine.eval("isVadas(g.V(vadas).next())", bindings));
+
+        // make sure the function works in a closure...this generates a StackOverflowError
+        assertEquals(g.V(convertToVertexId(graph, "vadas")).next(), engine.eval("g.V().filter{isVadas(it.get())}.next()", bindings));
+    }
+
+    @Test
+    @org.junit.Ignore
+    public void shouldAllowUseOfClasses() throws ScriptException {
+        final Graph graph = TinkerFactory.createClassic();
+        final GraphTraversalSource g = graph.traversal();
+        GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine();
+
+        final Bindings bindings = engine.createBindings();
+        bindings.put("g", g);
+        bindings.put("vadas", convertToVertexId(graph, "vadas"));
+
+        // works when it's all defined together
+        assertEquals(true, engine.eval("class c { static def isVadas(v){v.value('name')=='vadas'}};c.isVadas(g.V(vadas).next())", bindings));
+
+        // let's reset this piece and make sure isVadas is not hanging around.
+        engine.reset();
+
+        // validate that isVadas throws an exception since it is not defined
+        try {
+            engine.eval("c.isVadas(g.V(vadas).next())", bindings);
+
+            // fail the test if the above doesn't throw an exception
+            fail("Function should be gone");
+        } catch (Exception ex) {
+            // this is good...we want this. it means isVadas isn't hanging about
+        }
+
+        // now...define the class separately on its own in one script...
+        // HERE'S an AWKWARD BIT.........
+        // YOU HAVE TO END WITH: null;
+        // ....OR ELSE YOU GET:
+        // javax.script.ScriptException: javax.script.ScriptException:
+        // org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: c.main()
+        // is applicable for argument types: ([Ljava.lang.String;) values: [[]]
+        // WOULD BE NICE IF WE DIDN'T HAVE TO DO THAT
+        engine.eval("class c { static def isVadas(v){v.name=='vadas'}};null;", bindings);
+
+        // make sure the class works on its own...this generates: groovy.lang.MissingPropertyException: No such property: c for class: Script2
+        assertEquals(true, engine.eval("c.isVadas(g.V(vadas).next())", bindings));
+    }
+
+    @Test
+    public void shouldProcessUTF8Query() throws Exception {
+        final Graph graph = TinkerGraph.open();
+        final GraphTraversalSource g = graph.traversal();
+        final Vertex nonUtf8 = graph.addVertex("name", "marko", "age", 29);
+        final Vertex utf8Name = graph.addVertex("name", "轉注", "age", 32);
+
+        final ScriptEngine engine = new GremlinGroovyScriptEngine();
+
+        engine.put("g", g);
+        Traversal eval = (Traversal) engine.eval("g.V().has('name', 'marko')");
+        assertEquals(nonUtf8, eval.next());
+        eval = (Traversal) engine.eval("g.V().has('name','轉注')");
+        assertEquals(utf8Name, eval.next());
+    }
+
+    private Object convertToVertexId(final Graph graph, final String vertexName) {
+        return convertToVertex(graph, vertexName).id();
+    }
+
+    private Vertex convertToVertex(final Graph graph, final String vertexName) {
+        // all test graphs have "name" as a unique id which makes it easy to hardcode this...works for now
+        return graph.traversal().V().has("name", vertexName).next();
+    }
+
+    private Object convertToEdgeId(final Graph graph, final String outVertexName, String edgeLabel, final String inVertexName) {
+        return graph.traversal().V().has("name", outVertexName).outE(edgeLabel).as("e").inV().has("name", inVertexName).<Edge>select("e").next().id();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineSandboxedStandardTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineSandboxedStandardTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineSandboxedStandardTest.java
new file mode 100644
index 0000000..349fcd5
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineSandboxedStandardTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider;
+import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
+import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.CompileStaticCustomizerProvider;
+import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.SimpleSandboxExtension;
+import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.TypeCheckedCustomizerProvider;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.codehaus.groovy.control.MultipleCompilationErrorsException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import javax.script.Bindings;
+import java.util.Arrays;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(Parameterized.class)
+public class GremlinGroovyScriptEngineSandboxedStandardTest {
+    @Parameterized.Parameters(name = "{0}")
+    public static Iterable<Object[]> data() {
+        return Arrays.asList(new Object[][]{
+                {TypeCheckedCustomizerProvider.class.getSimpleName(), new TypeCheckedCustomizerProvider(), new TypeCheckedCustomizerProvider(SimpleSandboxExtension.class.getName())},
+                {CompileStaticCustomizerProvider.class.getSimpleName(), new CompileStaticCustomizerProvider(), new CompileStaticCustomizerProvider(SimpleSandboxExtension.class.getName())}});
+    }
+
+    @Parameterized.Parameter(value = 0)
+    public String name;
+
+    @Parameterized.Parameter(value = 1)
+    public CompilerCustomizerProvider notSandboxed;
+
+    @Parameterized.Parameter(value = 2)
+    public CompilerCustomizerProvider sandboxed;
+
+    @Test
+    public void shouldEvalGraphTraversalSource() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine()) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("g", g);
+            bindings.put("marko", convertToVertexId(graph, "marko"));
+            assertEquals(g.V(convertToVertexId(graph, "marko")).next(), engine.eval("g.V(marko).next()", bindings));
+        }
+
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(notSandboxed)) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("g", g);
+            bindings.put("marko", convertToVertexId(graph, "marko"));
+            engine.eval("g.V(marko).next()", bindings);
+            fail("Type checking should have forced an error as 'g' is not defined");
+        } catch (Exception ex) {
+            assertEquals(MultipleCompilationErrorsException.class, ex.getCause().getClass());
+            assertThat(ex.getMessage(), containsString("The variable [g] is undeclared."));
+        }
+
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(sandboxed)) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("g", g);
+            bindings.put("marko", convertToVertexId(graph, "marko"));
+            assertEquals(g.V(convertToVertexId(graph, "marko")).next(), engine.eval("g.V(marko).next()", bindings));
+            assertEquals(g.V(convertToVertexId(graph, "marko")).out("created").count().next(), engine.eval("g.V(marko).out(\"created\").count().next()", bindings));
+        }
+    }
+
+    @Test
+    public void shouldEvalGraph() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine()) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("graph", graph);
+            bindings.put("marko", convertToVertexId(graph, "marko"));
+            assertEquals(graph.vertices(convertToVertexId(graph, "marko")).next(), engine.eval("graph.vertices(marko).next()", bindings));
+        }
+
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(notSandboxed)) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("graph", graph);
+            bindings.put("marko", convertToVertexId(graph, "marko"));
+            assertEquals(graph.vertices(convertToVertexId(graph, "marko")).next(), engine.eval("graph.vertices(marko).next()", bindings));
+            fail("Type checking should have forced an error as 'graph' is not defined");
+        } catch (Exception ex) {
+            assertEquals(MultipleCompilationErrorsException.class, ex.getCause().getClass());
+            assertThat(ex.getMessage(), containsString("The variable [graph] is undeclared."));
+        }
+
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(notSandboxed)) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("graph", graph);
+            bindings.put("x", convertToVertexId(graph, "marko"));
+            assertEquals(graph.vertices(convertToVertexId(graph, "marko")).next(), engine.eval("graph.vertices(x).next()", bindings));
+            fail("Type checking should have forced an error as 'graph' is not defined");
+        } catch (Exception ex) {
+            assertEquals(MultipleCompilationErrorsException.class, ex.getCause().getClass());
+            assertThat(ex.getMessage(), containsString("The variable [graph] is undeclared."));
+        }
+
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(sandboxed)) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("graph", graph);
+            bindings.put("marko", convertToVertexId(graph, "marko"));
+            assertEquals(graph.vertices(convertToVertexId(graph, "marko")).next(), engine.eval("graph.vertices(marko).next()", bindings));
+        }
+
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(sandboxed)) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("graph", graph);
+            bindings.put("x", convertToVertexId(graph, "marko"));
+            assertEquals(graph.vertices(convertToVertexId(graph, "marko")).next(), engine.eval("graph.vertices(x).next()", bindings));
+        }
+    }
+
+    private Object convertToVertexId(final Graph graph, final String vertexName) {
+        return convertToVertex(graph, vertexName).id();
+    }
+
+    private Vertex convertToVertex(final Graph graph, final String vertexName) {
+        // all test graphs have "name" as a unique id which makes it easy to hardcode this...works for now
+        return graph.traversal().V().has("name", vertexName).next();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTinkerPopSandboxTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTinkerPopSandboxTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTinkerPopSandboxTest.java
new file mode 100644
index 0000000..0ff2706
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTinkerPopSandboxTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider;
+import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
+import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.CompileStaticCustomizerProvider;
+import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.TinkerPopSandboxExtension;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.codehaus.groovy.control.MultipleCompilationErrorsException;
+import org.junit.Test;
+
+import javax.script.Bindings;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GremlinGroovyScriptEngineTinkerPopSandboxTest {
+    @Test
+    public void shouldNotEvalAsTheMethodIsNotWhiteListed() throws Exception {
+        final CompilerCustomizerProvider standardSandbox = new CompileStaticCustomizerProvider(TinkerPopSandboxExtension.class.getName());
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(standardSandbox)) {
+            engine.eval("java.lang.Math.abs(123)");
+            fail("Should have a compile error because class/method is not white listed");
+        } catch (Exception ex) {
+            assertEquals(MultipleCompilationErrorsException.class, ex.getCause().getClass());
+            assertThat(ex.getCause().getMessage(), containsString("Not authorized to call this method"));
+        }
+    }
+
+    @Test
+    public void shouldEvalOnGAsTheMethodIsWhiteListed() throws Exception {
+        final Graph graph = TinkerFactory.createModern();
+        final GraphTraversalSource g = graph.traversal();
+        final CompilerCustomizerProvider standardSandbox = new CompileStaticCustomizerProvider(TinkerPopSandboxExtension.class.getName());
+        try (GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(standardSandbox)) {
+            final Bindings bindings = engine.createBindings();
+            bindings.put("g", g);
+            bindings.put("marko", convertToVertexId(graph, "marko"));
+            assertEquals(g.V(convertToVertexId(graph, "marko")).next(), engine.eval("g.V(marko).next()", bindings));
+            assertEquals(g.V(convertToVertexId(graph, "marko")).out("created").count().next(), engine.eval("g.V(marko).out(\"created\").count().next()", bindings));
+        }
+    }
+
+    private Object convertToVertexId(final Graph graph, final String vertexName) {
+        return convertToVertex(graph, vertexName).id();
+    }
+
+    private Vertex convertToVertex(final Graph graph, final String vertexName) {
+        // all test graphs have "name" as a unique id which makes it easy to hardcode this...works for now
+        return graph.traversal().V().has("name", vertexName).next();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyScriptEngineSetup.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyScriptEngineSetup.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyScriptEngineSetup.java
new file mode 100644
index 0000000..a9ef68e
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyScriptEngineSetup.java
@@ -0,0 +1,69 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.jsr223.CoreImports;
+import org.apache.tinkerpop.gremlin.jsr223.ScriptEngineCache;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GroovyScriptEngineSetup {
+
+    private GroovyScriptEngineSetup() {
+    }
+
+    public static void setup() {
+        setup(ScriptEngineCache.get("groovy"));
+    }
+
+    public static ScriptEngine setup(final ScriptEngine groovyScriptEngine) {
+        try {
+            for (Class<?> c : CoreImports.getClassImports()) {
+                groovyScriptEngine.eval("import " + c.getName());
+            }
+
+            final Set<Class<?>> staticImports = new HashSet<>();
+
+            for (Enum e : CoreImports.getEnumImports()) {
+                staticImports.add(e.getDeclaringClass());
+            }
+
+            for (Method m : CoreImports.getMethodImports()) {
+                staticImports.add(m.getDeclaringClass());
+            }
+
+            for (Class<?> c : staticImports) {
+                groovyScriptEngine.eval("import static " + c.getName() + ".*");
+            }
+
+            return groovyScriptEngine;
+        } catch (final ScriptException ex) {
+            throw new IllegalStateException(ex.getMessage(), ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorComputerProvider.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorComputerProvider.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorComputerProvider.java
new file mode 100644
index 0000000..c24021c
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorComputerProvider.java
@@ -0,0 +1,36 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.GraphProvider;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComputer;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@GraphProvider.Descriptor(computer = TinkerGraphComputer.class)
+public class GroovyTranslatorComputerProvider extends GroovyTranslatorProvider {
+
+    @Override
+    public GraphTraversalSource traversal(final Graph graph) {
+        return super.traversal(graph).withComputer();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProcessComputerTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProcessComputerTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProcessComputerTest.java
new file mode 100644
index 0000000..7d09237
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProcessComputerTest.java
@@ -0,0 +1,32 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.GraphProviderClass;
+import org.apache.tinkerpop.gremlin.process.ProcessComputerSuite;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(ProcessComputerSuite.class)
+@GraphProviderClass(provider = GroovyTranslatorComputerProvider.class, graph = TinkerGraph.class)
+public class GroovyTranslatorProcessComputerTest {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProcessStandardTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProcessStandardTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProcessStandardTest.java
new file mode 100644
index 0000000..8794fa0
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProcessStandardTest.java
@@ -0,0 +1,32 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.GraphProviderClass;
+import org.apache.tinkerpop.gremlin.process.ProcessStandardSuite;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(ProcessStandardSuite.class)
+@GraphProviderClass(provider = GroovyTranslatorProvider.class, graph = TinkerGraph.class)
+public class GroovyTranslatorProcessStandardTest {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProvider.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProvider.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProvider.java
new file mode 100644
index 0000000..c56e7069
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorProvider.java
@@ -0,0 +1,73 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.computer.GraphComputerTest;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalInterruptionComputerTest;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalInterruptionTest;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProgramTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategyProcessTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategyProcessTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.util.TinkerGraphProvider;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class GroovyTranslatorProvider extends TinkerGraphProvider {
+
+    private static Set<String> SKIP_TESTS = new HashSet<>(Arrays.asList(
+            "testProfileStrategyCallback",
+            "testProfileStrategyCallbackSideEffect",
+            GraphComputerTest.class.getCanonicalName(),
+            ProgramTest.Traversals.class.getCanonicalName(),
+            TraversalInterruptionTest.class.getCanonicalName(),
+            TraversalInterruptionComputerTest.class.getCanonicalName(),
+            EventStrategyProcessTest.class.getCanonicalName(),
+            ElementIdStrategyProcessTest.class.getCanonicalName()));
+
+
+    @Override
+    public Map<String, Object> getBaseConfiguration(final String graphName, final Class<?> test, final String testMethodName,
+                                                    final LoadGraphWith.GraphData loadGraphWith) {
+
+        final Map<String, Object> config = super.getBaseConfiguration(graphName, test, testMethodName, loadGraphWith);
+        config.put("skipTest", SKIP_TESTS.contains(testMethodName) || SKIP_TESTS.contains(test.getCanonicalName()));
+        return config;
+    }
+
+    @Override
+    public GraphTraversalSource traversal(final Graph graph) {
+        if ((Boolean) graph.configuration().getProperty("skipTest"))
+            return graph.traversal();
+            //throw new VerificationException("This test current does not work with Gremlin-Python", EmptyTraversal.instance());
+        else {
+            final GraphTraversalSource g = graph.traversal();
+            return g.withStrategies(new TranslationStrategy(g, GroovyTranslator.of("g")));
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
new file mode 100644
index 0000000..654cb00
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
@@ -0,0 +1,123 @@
+/*
+ *  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.groovy.jsr223;
+
+import org.apache.commons.configuration.MapConfiguration;
+import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import org.junit.Test;
+
+import javax.script.Bindings;
+import javax.script.SimpleBindings;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class GroovyTranslatorTest {
+
+    @Test
+    public void shouldHandleStrategies() throws Exception {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        GraphTraversalSource g = graph.traversal();
+        g = g.withStrategies(SubgraphStrategy.create(new MapConfiguration(new HashMap<String, Object>() {{
+            put(SubgraphStrategy.VERTICES, __.has("name", "marko"));
+        }})));
+        final Bindings bindings = new SimpleBindings();
+        bindings.put("g", g);
+        Traversal.Admin<Vertex, Object> traversal = new GremlinGroovyScriptEngine().eval(g.V().values("name").asAdmin().getBytecode(), bindings);
+        assertEquals("marko", traversal.next());
+        assertFalse(traversal.hasNext());
+        //
+        traversal = new GremlinGroovyScriptEngine().eval(g.withoutStrategies(SubgraphStrategy.class).V().count().asAdmin().getBytecode(), bindings);
+        assertEquals(new Long(6), traversal.next());
+        assertFalse(traversal.hasNext());
+        //
+        traversal = new GremlinGroovyScriptEngine().eval(g.withStrategies(SubgraphStrategy.create(new MapConfiguration(new HashMap<String, Object>() {{
+            put(SubgraphStrategy.VERTICES, __.has("name", "marko"));
+        }})), ReadOnlyStrategy.instance()).V().values("name").asAdmin().getBytecode(), bindings);
+        assertEquals("marko", traversal.next());
+        assertFalse(traversal.hasNext());
+    }
+
+    @Test
+    public void shouldSupportStringSupplierLambdas() throws Exception {
+        final TinkerGraph graph = TinkerFactory.createModern();
+        GraphTraversalSource g = graph.traversal();
+        g = g.withStrategies(new TranslationStrategy(g, GroovyTranslator.of("g")));
+        GraphTraversal.Admin<Vertex, Integer> t = g.withSideEffect("lengthSum", 0).withSack(1)
+                .V()
+                .filter(Lambda.predicate("it.get().label().equals('person')"))
+                .flatMap(Lambda.function("it.get().vertices(Direction.OUT)"))
+                .map(Lambda.<Traverser<Object>, Integer>function("it.get().value('name').length()"))
+                .sideEffect(Lambda.consumer("{ x -> x.sideEffects(\"lengthSum\", x.<Integer>sideEffects('lengthSum') + x.get()) }"))
+                .order().by(Lambda.comparator("a,b -> a <=> b"))
+                .sack(Lambda.biFunction("{ a,b -> a + b }"))
+                .asAdmin();
+        final List<Integer> sacks = new ArrayList<>();
+        final List<Integer> lengths = new ArrayList<>();
+        while (t.hasNext()) {
+            final Traverser.Admin<Integer> traverser = t.nextTraverser();
+            sacks.add(traverser.sack());
+            lengths.add(traverser.get());
+        }
+        assertFalse(t.hasNext());
+        //
+        assertEquals(6, lengths.size());
+        assertEquals(3, lengths.get(0).intValue());
+        assertEquals(3, lengths.get(1).intValue());
+        assertEquals(3, lengths.get(2).intValue());
+        assertEquals(4, lengths.get(3).intValue());
+        assertEquals(5, lengths.get(4).intValue());
+        assertEquals(6, lengths.get(5).intValue());
+        ///
+        assertEquals(6, sacks.size());
+        assertEquals(4, sacks.get(0).intValue());
+        assertEquals(4, sacks.get(1).intValue());
+        assertEquals(4, sacks.get(2).intValue());
+        assertEquals(5, sacks.get(3).intValue());
+        assertEquals(6, sacks.get(4).intValue());
+        assertEquals(7, sacks.get(5).intValue());
+        //
+        assertEquals(24, t.getSideEffects().<Number>get("lengthSum").intValue());
+    }
+
+    @Test
+    public void shouldHaveValidToString() {
+        assertEquals("translator[h:gremlin-groovy]", GroovyTranslator.of("h").toString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/dsl/credential/CredentialGraphTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/dsl/credential/CredentialGraphTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/dsl/credential/CredentialGraphTest.java
new file mode 100644
index 0000000..3fef17e
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/dsl/credential/CredentialGraphTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.groovy.jsr223.dsl.credential;
+
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.hamcrest.MatcherAssert;
+import org.junit.Test;
+
+import static org.apache.tinkerpop.gremlin.groovy.jsr223.dsl.credential.CredentialGraph.credentials;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class CredentialGraphTest {
+
+    @Test
+    public void shouldCreateUser() {
+        final Graph graph = TinkerGraph.open();
+        final Vertex v = credentials(graph).createUser("stephen", "secret");
+        assertEquals("stephen", v.value("username"));
+        assertEquals("user", v.label());
+        assertNotEquals("secret", v.value("password"));  // hashed to something
+        assertThat(v.value("password").toString().length(), greaterThan(0));
+    }
+
+    @Test
+    public void shouldRemoveUser() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(1, credentials(graph).removeUser("stephen"));
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+    }
+
+    @Test
+    public void shouldNotRemoveUser() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(0, credentials(graph).removeUser("stephanie"));
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+    }
+
+    @Test
+    public void shouldFindUser() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        final Vertex stephen = credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(stephen, credentials(graph).findUser("stephen"));
+    }
+
+    @Test
+    public void shouldNotFindUser() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertNull(credentials(graph).findUser("stephanie"));
+    }
+
+    @Test
+    public void shouldCountUsers() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(3, credentials(graph).countUsers());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void shouldThrowIfFindingMultipleUsers() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertNull(credentials(graph).findUser("stephen"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/plugin/dsl/credential/CredentialGraphTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/plugin/dsl/credential/CredentialGraphTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/plugin/dsl/credential/CredentialGraphTest.java
new file mode 100644
index 0000000..0ea9b2b
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/plugin/dsl/credential/CredentialGraphTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.plugin.dsl.credential;
+
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.hamcrest.MatcherAssert;
+import org.junit.Test;
+
+import static org.apache.tinkerpop.gremlin.groovy.plugin.dsl.credential.CredentialGraph.credentials;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class CredentialGraphTest {
+
+    @Test
+    public void shouldCreateUser() {
+        final Graph graph = TinkerGraph.open();
+        final Vertex v = credentials(graph).createUser("stephen", "secret");
+        assertEquals("stephen", v.value("username"));
+        assertEquals("user", v.label());
+        assertNotEquals("secret", v.value("password"));  // hashed to something
+        assertThat(v.value("password").toString().length(), greaterThan(0));
+    }
+
+    @Test
+    public void shouldRemoveUser() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(1, credentials(graph).removeUser("stephen"));
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+    }
+
+    @Test
+    public void shouldNotRemoveUser() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(0, credentials(graph).removeUser("stephanie"));
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+    }
+
+    @Test
+    public void shouldFindUser() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        final Vertex stephen = credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(stephen, credentials(graph).findUser("stephen"));
+    }
+
+    @Test
+    public void shouldNotFindUser() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertNull(credentials(graph).findUser("stephanie"));
+    }
+
+    @Test
+    public void shouldCountUsers() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("marko", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("daniel", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertEquals(3, credentials(graph).countUsers());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void shouldThrowIfFindingMultipleUsers() {
+        final Graph graph = TinkerGraph.open();
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(false));
+        credentials(graph).createUser("stephen", "secret");
+        credentials(graph).createUser("stephen", "secret");
+        MatcherAssert.assertThat(graph.vertices().hasNext(), is(true));
+
+        assertNull(credentials(graph).findUser("stephen"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/TinkerGraphProvider.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/TinkerGraphProvider.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/TinkerGraphProvider.java
new file mode 100644
index 0000000..c71a31b
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/TinkerGraphProvider.java
@@ -0,0 +1,206 @@
+/*
+ * 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.util;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.tinkerpop.gremlin.AbstractGraphProvider;
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.TestHelper;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.GraphTest;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.io.IoEdgeTest;
+import org.apache.tinkerpop.gremlin.structure.io.IoVertexTest;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedGraphTest;
+import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphTest;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerEdge;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerElement;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraphVariables;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerProperty;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertexProperty;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class TinkerGraphProvider extends AbstractGraphProvider {
+
+    private static final Set<Class> IMPLEMENTATION = new HashSet<Class>() {{
+        add(TinkerEdge.class);
+        add(TinkerElement.class);
+        add(TinkerGraph.class);
+        add(TinkerGraphVariables.class);
+        add(TinkerProperty.class);
+        add(TinkerVertex.class);
+        add(TinkerVertexProperty.class);
+    }};
+
+    @Override
+    public Map<String, Object> getBaseConfiguration(final String graphName, final Class<?> test, final String testMethodName,
+                                                    final LoadGraphWith.GraphData loadGraphWith) {
+        final TinkerGraph.DefaultIdManager idManager = selectIdMakerFromGraphData(loadGraphWith);
+        final String idMaker = (idManager.equals(TinkerGraph.DefaultIdManager.ANY) ? selectIdMakerFromTest(test, testMethodName) : idManager).name();
+        return new HashMap<String, Object>() {{
+            put(Graph.GRAPH, TinkerGraph.class.getName());
+            put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_ID_MANAGER, idMaker);
+            put(TinkerGraph.GREMLIN_TINKERGRAPH_EDGE_ID_MANAGER, idMaker);
+            put(TinkerGraph.GREMLIN_TINKERGRAPH_VERTEX_PROPERTY_ID_MANAGER, idMaker);
+            if (requiresListCardinalityAsDefault(loadGraphWith, test, testMethodName))
+                put(TinkerGraph.GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, VertexProperty.Cardinality.list.name());
+            if (requiresPersistence(test, testMethodName)) {
+                put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_FORMAT, "gryo");
+                final File tempDir = TestHelper.makeTestDataPath(test, "temp");
+                put(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION,
+                        tempDir.getAbsolutePath() + File.separator + testMethodName + ".kryo");
+            }
+        }};
+    }
+
+    @Override
+    public void clear(final Graph graph, final Configuration configuration) throws Exception {
+        if (graph != null)
+            graph.close();
+
+        // in the even the graph is persisted we need to clean up
+        final String graphLocation = configuration.getString(TinkerGraph.GREMLIN_TINKERGRAPH_GRAPH_LOCATION, null);
+        if (graphLocation != null) {
+            final File f = new File(graphLocation);
+            f.delete();
+        }
+    }
+
+    @Override
+    public Set<Class> getImplementations() {
+        return IMPLEMENTATION;
+    }
+
+    /**
+     * Determines if a test requires TinkerGraph persistence to be configured with graph location and format.
+     */
+    protected static boolean requiresPersistence(final Class<?> test, final String testMethodName) {
+        return test == GraphTest.class && testMethodName.equals("shouldPersistDataOnClose");
+    }
+
+    /**
+     * Determines if a test requires a different cardinality as the default or not.
+     */
+    protected static boolean requiresListCardinalityAsDefault(final LoadGraphWith.GraphData loadGraphWith,
+                                                            final Class<?> test, final String testMethodName) {
+        return loadGraphWith == LoadGraphWith.GraphData.CREW
+                || (test == StarGraphTest.class && testMethodName.equals("shouldAttachWithCreateMethod"))
+                || (test == DetachedGraphTest.class && testMethodName.equals("testAttachableCreateMethod"));
+    }
+
+    /**
+     * Some tests require special configuration for TinkerGraph to properly configure the id manager.
+     */
+    protected TinkerGraph.DefaultIdManager selectIdMakerFromTest(final Class<?> test, final String testMethodName) {
+        if (test.equals(GraphTest.class)) {
+            final Set<String> testsThatNeedLongIdManager = new HashSet<String>(){{
+                add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentation");
+                add("shouldIterateVerticesWithNumericIdSupportUsingDoubleRepresentations");
+                add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentation");
+                add("shouldIterateVerticesWithNumericIdSupportUsingIntegerRepresentations");
+                add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentation");
+                add("shouldIterateVerticesWithNumericIdSupportUsingFloatRepresentations");
+                add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentation");
+                add("shouldIterateVerticesWithNumericIdSupportUsingStringRepresentations");
+                add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentation");
+                add("shouldIterateEdgesWithNumericIdSupportUsingDoubleRepresentations");
+                add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentation");
+                add("shouldIterateEdgesWithNumericIdSupportUsingIntegerRepresentations");
+                add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentation");
+                add("shouldIterateEdgesWithNumericIdSupportUsingFloatRepresentations");
+                add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentation");
+                add("shouldIterateEdgesWithNumericIdSupportUsingStringRepresentations");
+            }};
+
+            final Set<String> testsThatNeedUuidIdManager = new HashSet<String>(){{
+                add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentation");
+                add("shouldIterateVerticesWithUuidIdSupportUsingStringRepresentations");
+                add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentation");
+                add("shouldIterateEdgesWithUuidIdSupportUsingStringRepresentations");
+            }};
+
+            if (testsThatNeedLongIdManager.contains(testMethodName))
+                return TinkerGraph.DefaultIdManager.LONG;
+            else if (testsThatNeedUuidIdManager.contains(testMethodName))
+                return TinkerGraph.DefaultIdManager.UUID;
+        }  else if (test.equals(IoEdgeTest.class)) {
+            final Set<String> testsThatNeedLongIdManager = new HashSet<String>(){{
+                add("shouldReadWriteEdge[graphson-v1]");
+                add("shouldReadWriteDetachedEdgeAsReference[graphson-v1]");
+                add("shouldReadWriteDetachedEdge[graphson-v1]");
+                add("shouldReadWriteEdge[graphson-v2]");
+                add("shouldReadWriteDetachedEdgeAsReference[graphson-v2]");
+                add("shouldReadWriteDetachedEdge[graphson-v2]");
+            }};
+
+            if (testsThatNeedLongIdManager.contains(testMethodName))
+                return TinkerGraph.DefaultIdManager.LONG;
+        } else if (test.equals(IoVertexTest.class)) {
+            final Set<String> testsThatNeedLongIdManager = new HashSet<String>(){{
+                add("shouldReadWriteVertexWithBOTHEdges[graphson-v1]");
+                add("shouldReadWriteVertexWithINEdges[graphson-v1]");
+                add("shouldReadWriteVertexWithOUTEdges[graphson-v1]");
+                add("shouldReadWriteVertexNoEdges[graphson-v1]");
+                add("shouldReadWriteDetachedVertexNoEdges[graphson-v1]");
+                add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v1]");
+                add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v1]");
+                add("shouldReadWriteVertexWithBOTHEdges[graphson-v2]");
+                add("shouldReadWriteVertexWithINEdges[graphson-v2]");
+                add("shouldReadWriteVertexWithOUTEdges[graphson-v2]");
+                add("shouldReadWriteVertexNoEdges[graphson-v2]");
+                add("shouldReadWriteDetachedVertexNoEdges[graphson-v2]");
+                add("shouldReadWriteDetachedVertexAsReferenceNoEdges[graphson-v2]");
+                add("shouldReadWriteVertexMultiPropsNoEdges[graphson-v2]");
+            }};
+
+            if (testsThatNeedLongIdManager.contains(testMethodName))
+                return TinkerGraph.DefaultIdManager.LONG;
+        }
+
+        return TinkerGraph.DefaultIdManager.ANY;
+    }
+
+    /**
+     * Test that load with specific graph data can be configured with a specific id manager as the data type to
+     * be used in the test for that graph is known.
+     */
+    protected TinkerGraph.DefaultIdManager selectIdMakerFromGraphData(final LoadGraphWith.GraphData loadGraphWith) {
+        if (null == loadGraphWith) return TinkerGraph.DefaultIdManager.ANY;
+        if (loadGraphWith.equals(LoadGraphWith.GraphData.CLASSIC))
+            return TinkerGraph.DefaultIdManager.INTEGER;
+        else if (loadGraphWith.equals(LoadGraphWith.GraphData.MODERN))
+            return TinkerGraph.DefaultIdManager.INTEGER;
+        else if (loadGraphWith.equals(LoadGraphWith.GraphData.CREW))
+            return TinkerGraph.DefaultIdManager.INTEGER;
+        else if (loadGraphWith.equals(LoadGraphWith.GraphData.GRATEFUL))
+            return TinkerGraph.DefaultIdManager.INTEGER;
+        else
+            throw new IllegalStateException(String.format("Need to define a new %s for %s", TinkerGraph.IdManager.class.getName(), loadGraphWith.name()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-groovy/src/test/resources/org/apache/tinkerpop/gremlin/groovy/jsr223/sandbox.yaml
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/resources/org/apache/tinkerpop/gremlin/groovy/jsr223/sandbox.yaml b/gremlin-groovy/src/test/resources/org/apache/tinkerpop/gremlin/groovy/jsr223/sandbox.yaml
new file mode 100644
index 0000000..b2b7f67
--- /dev/null
+++ b/gremlin-groovy/src/test/resources/org/apache/tinkerpop/gremlin/groovy/jsr223/sandbox.yaml
@@ -0,0 +1,58 @@
+# 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.
+
+# This is an example configuration for the FileSandboxExtension.
+
+autoTypeUnknown: true
+methodWhiteList:
+  - java\.lang\.Boolean.*
+  - java\.lang\.Byte.*
+  - java\.lang\.Character.*
+  - java\.lang\.Double.*
+  - java\.lang\.Enum.*
+  - java\.lang\.Float.*
+  - java\.lang\.Integer.*
+  - java\.lang\.Long.*
+  - java\.lang\.Math.*
+  - java\.lang\.Number.*
+  - java\.lang\.Object.*
+  - java\.lang\.Short.*
+  - java\.lang\.String.*
+  - java\.lang\.StringBuffer.*
+  - java\.lang\.System#currentTimeMillis\(\)
+  - java\.lang\.System#nanoTime\(\)
+  - java\.lang\.Throwable.*
+  - java\.lang\.Void.*
+  - java\.util\..*
+  - org\.codehaus\.groovy\.runtime\.DefaultGroovyMethods.*
+  - org\.codehaus\.groovy\.runtime\.InvokerHelper#runScript\(java\.lang\.Class,java\.lang\.String\[\]\)
+  - org\.codehaus\.groovy\.runtime\.StringGroovyMethods.*
+  - groovy\.lang\.Script#<init>\(groovy.lang.Binding\)
+  - org\.apache\.tinkerpop\.gremlin\.structure\..*
+  - org\.apache\.tinkerpop\.gremlin\.process\..*
+  - org\.apache\.tinkerpop\.gremlin\.process\.computer\..*
+  - org\.apache\.tinkerpop\.gremlin\.process\.computer\.bulkloading\..*
+  - org\.apache\.tinkerpop\.gremlin\.process\.computer\.clustering\.peerpressure\.*
+  - org\.apache\.tinkerpop\.gremlin\.process\.computer\.ranking\.pagerank\.*
+  - org\.apache\.tinkerpop\.gremlin\.process\.computer\.traversal\..*
+  - org\.apache\.tinkerpop\.gremlin\.process\.traversal\..*
+  - org\.apache\.tinkerpop\.gremlin\.process\.traversal\.dsl\.graph\..*
+  - org\.apache\.tinkerpop\.gremlin\.process\.traversal\.engine\..*
+  - org\.apache\.tinkerpop\.gremlin\.server\.util\.LifeCycleHook.*
+staticVariableTypes:
+  graph: org.apache.tinkerpop.gremlin.structure.Graph
+  g: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-python/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml
index 8935dfc..d30ac06 100644
--- a/gremlin-python/pom.xml
+++ b/gremlin-python/pom.xml
@@ -487,7 +487,7 @@ if (${skipTests}) return
 log.info("Starting Gremlin Server instances for native testing of gremlin-python")
 def settings = Settings.read("${gremlin.server.dir}/conf/gremlin-server-modern-py.yaml")
 settings.graphs.graph = "${gremlin.server.dir}/conf/tinkergraph-empty.properties"
-settings.scriptEngines["gremlin-groovy"].scripts = ["${gremlin.server.dir}/scripts/generate-modern.groovy"]
+settings.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files = ["${gremlin.server.dir}/scripts/generate-modern.groovy"]
 settings.port = 45940
 
 def server = new GremlinServer(settings)
@@ -498,7 +498,7 @@ log.info("Gremlin Server with no authentication started on port 45940")
 
 def settingsSecure = Settings.read("${gremlin.server.dir}/conf/gremlin-server-modern-py.yaml")
 settingsSecure.graphs.graph = "${gremlin.server.dir}/conf/tinkergraph-empty.properties"
-settingsSecure.scriptEngines["gremlin-groovy"].scripts = ["${gremlin.server.dir}/scripts/generate-modern.groovy"]
+settings.scriptEngines["gremlin-groovy"].plugins["org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin"].files = ["${gremlin.server.dir}/scripts/generate-modern.groovy"]
 settingsSecure.port = 45941
 settingsSecure.authentication.className = "org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator"
 settingsSecure.authentication.config = [credentialsDb: "${gremlin.server.dir}/conf/tinkergraph-credentials.properties"]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java
index 44d65fa..906f147 100644
--- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java
+++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java
@@ -87,7 +87,6 @@ public class PythonProvider extends AbstractGraphProvider {
     @Override
     public Map<String, Object> getBaseConfiguration(final String graphName, final Class<?> test, final String testMethodName,
                                                     final LoadGraphWith.GraphData loadGraphWith) {
-
         final TinkerGraph.DefaultIdManager idManager = selectIdMakerFromGraphData(loadGraphWith);
         final String idMaker = (idManager.equals(TinkerGraph.DefaultIdManager.ANY) ? selectIdMakerFromGraphData(loadGraphWith) : idManager).name();
         return new HashMap<String, Object>() {{
@@ -150,5 +149,4 @@ public class PythonProvider extends AbstractGraphProvider {
             return g.withStrategies(new TranslationStrategy(g, new PythonGraphSONJavaTranslator<>(PythonTranslator.of("g", IMPORT_STATICS), JavaTranslator.of(g))));
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-python/src/test/resources/org/apache/tinkerpop/gremlin/python/driver/gremlin-server-modern-secure-py.yaml
----------------------------------------------------------------------
diff --git a/gremlin-python/src/test/resources/org/apache/tinkerpop/gremlin/python/driver/gremlin-server-modern-secure-py.yaml b/gremlin-python/src/test/resources/org/apache/tinkerpop/gremlin/python/driver/gremlin-server-modern-secure-py.yaml
index fe32c6e..c846cf4 100644
--- a/gremlin-python/src/test/resources/org/apache/tinkerpop/gremlin/python/driver/gremlin-server-modern-secure-py.yaml
+++ b/gremlin-python/src/test/resources/org/apache/tinkerpop/gremlin/python/driver/gremlin-server-modern-secure-py.yaml
@@ -30,13 +30,13 @@ port: 45940
 scriptEvaluationTimeout: 30000
 graphs: {
   graph: src/test/resources/org/apache/tinkerpop/gremlin/python/driver/tinkergraph-empty.properties}
-plugins:
-  - tinkerpop.tinkergraph
 scriptEngines: {
   gremlin-groovy: {
     imports: [java.lang.Math],
     staticImports: [java.lang.Math.PI],
-    scripts: [src/test/resources/org/apache/tinkerpop/gremlin/python/driver/generate-modern.groovy]},
+    plugins: { org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
+               org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
+               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [src/test/resources/org/apache/tinkerpop/gremlin/python/driver/generate-modern.groovy]}}},
   gremlin-jython: {},
   gremlin-python: {}
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-server/conf/gremlin-server-classic.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-classic.yaml b/gremlin-server/conf/gremlin-server-classic.yaml
index ed256b5..00d304f 100644
--- a/gremlin-server/conf/gremlin-server-classic.yaml
+++ b/gremlin-server/conf/gremlin-server-classic.yaml
@@ -20,13 +20,12 @@ port: 8182
 scriptEvaluationTimeout: 30000
 graphs: {
   graph: conf/tinkergraph-empty.properties}
-plugins:
-  - tinkerpop.tinkergraph
 scriptEngines: {
   gremlin-groovy: {
-    imports: [java.lang.Math],
-    staticImports: [java.lang.Math.PI],
-    scripts: [scripts/generate-classic.groovy]}}
+    plugins: { org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
+               org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
+               org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
+               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-classic.groovy]}}}}
 serializers:
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { useMapperFromGraph: graph }}             # application/vnd.gremlin-v1.0+gryo
   - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoLiteMessageSerializerV1d0, config: { useMapperFromGraph: graph }}         # application/vnd.gremlin-v1.0+gryo-lite

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-server/conf/gremlin-server-min.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-min.yaml b/gremlin-server/conf/gremlin-server-min.yaml
index 9ce6b5e..2b8738c 100644
--- a/gremlin-server/conf/gremlin-server-min.yaml
+++ b/gremlin-server/conf/gremlin-server-min.yaml
@@ -19,7 +19,5 @@ host: localhost
 port: 8182
 graphs: {
   graph: conf/tinkergraph-empty.properties}
-plugins:
-  - tinkerpop.tinkergraph
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a5f528a5/gremlin-server/conf/gremlin-server-modern-py.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-modern-py.yaml b/gremlin-server/conf/gremlin-server-modern-py.yaml
index d030832..1e24914 100644
--- a/gremlin-server/conf/gremlin-server-modern-py.yaml
+++ b/gremlin-server/conf/gremlin-server-modern-py.yaml
@@ -32,13 +32,12 @@ gremlinPool: 8
 scriptEvaluationTimeout: 30000
 graphs: {
   graph: conf/tinkergraph-empty.properties}
-plugins:
-  - tinkerpop.tinkergraph
 scriptEngines: {
   gremlin-groovy: {
-    imports: [java.lang.Math],
-    staticImports: [java.lang.Math.PI],
-    scripts: [scripts/generate-modern.groovy]},
+    plugins: { org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
+               org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
+               org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
+               org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/generate-modern.groovy]}}},
   gremlin-jython: {},
   gremlin-python: {}
 }


Mime
View raw message