http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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/34bbd6a1/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: {} }