You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/05/09 22:51:49 UTC

incubator-tinkerpop git commit: Updated CHANGELOG, finalized some classes that are just static method givers. Moved ScriptEngineLambda to gremlin.function.

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/master 97e46779a -> 8a7118554


Updated CHANGELOG, finalized some classes that are just static method givers. Moved ScriptEngineLambda to gremlin.function.


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

Branch: refs/heads/master
Commit: 8a7118554b2889079a2288e1e17070029799426e
Parents: 97e4677
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Sat May 9 14:51:39 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Sat May 9 14:51:39 2015 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   4 +-
 .../computer/util/ScriptEngineCache.java        |  47 ------
 .../traversal/util/TraversalScriptFunction.java |   2 +-
 .../apache/tinkerpop/gremlin/util/Gremlin.java  |   3 +
 .../gremlin/util/ScriptEngineCache.java         |  47 ++++++
 .../tinkerpop/gremlin/util/Serializer.java      |   5 +-
 .../apache/tinkerpop/gremlin/util/TimeUtil.java |   4 +
 .../util/function/ScriptEngineLambda.java       |   2 +-
 .../computer/util/ScriptEngineLambdaTest.java   | 163 -------------------
 .../util/function/ScriptEngineLambdaTest.java   | 163 +++++++++++++++++++
 10 files changed, 226 insertions(+), 214 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index ecfa23c..85e9cce 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,7 +25,9 @@ image::http://www.tinkerpop.com/docs/current/images/gremlin-hindu.png[width=225]
 TinkerPop 3.0.0.M9 (NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* `VertexProgram` and `MapReduce` now add a `Graph` parameter to `loadState(Graph,Configuration)`.
+* Added `TraversalScriptHelper` with static methods for dynamically creating a `Traversal` from a JSR 223 `ScriptEngine`.
+* Simplified the Gremlin-Groovy test suite where there is now no distinction between `STANDARD` and `COMPUTER` tests.
+* `VertexProgram` and `MapReduce` now add a `Graph` parameter to `loadState(Graph, Configuration)`.
 * Added `ScopingStrategy` which auto-scopes `select()` and `where()` so the language looks clean.
 * Added `Scoping` as a marker interface to state that a step desires a particular `Scope`.
 * `SelectStep`, `SelectOneStep`, and `WhereStep` support both `Scope.local` and `Scope.global` for `Map<String,Object>` or `Path` analysis, respectively.

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ScriptEngineCache.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ScriptEngineCache.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ScriptEngineCache.java
deleted file mode 100644
index 4cbebf7..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ScriptEngineCache.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.process.computer.util;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public final class ScriptEngineCache {
-
-    public final static String DEFAULT_SCRIPT_ENGINE = "gremlin-groovy";
-
-    private final static ScriptEngineManager SCRIPT_ENGINE_MANAGER = new ScriptEngineManager();
-    private final static Map<String, ScriptEngine> CACHED_ENGINES = new ConcurrentHashMap<>();
-
-    public static ScriptEngine get(final String engineName) {
-        return CACHED_ENGINES.compute(engineName, (key, engine) -> {
-            if (null == engine) {
-                engine = SCRIPT_ENGINE_MANAGER.getEngineByName(engineName);
-                if (null == engine) {
-                    throw new IllegalArgumentException("There is no script engine with provided name: " + engineName);
-                }
-            }
-            return engine;
-        });
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalScriptFunction.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalScriptFunction.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalScriptFunction.java
index 73337ef..6d67b0b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalScriptFunction.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalScriptFunction.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.util;
 
-import org.apache.tinkerpop.gremlin.process.computer.util.ScriptEngineCache;
+import org.apache.tinkerpop.gremlin.util.ScriptEngineCache;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.structure.Graph;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java
index 26f9919..2d4a720 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java
@@ -32,6 +32,9 @@ public final class Gremlin {
         version = Manifests.read("version");
     }
 
+    private Gremlin() {
+    }
+
     public static String version() {
         return version;
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/ScriptEngineCache.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/ScriptEngineCache.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/ScriptEngineCache.java
new file mode 100644
index 0000000..8092992
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/ScriptEngineCache.java
@@ -0,0 +1,47 @@
+/*
+ * 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 javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class ScriptEngineCache {
+
+    public final static String DEFAULT_SCRIPT_ENGINE = "gremlin-groovy";
+
+    private final static ScriptEngineManager SCRIPT_ENGINE_MANAGER = new ScriptEngineManager();
+    private final static Map<String, ScriptEngine> CACHED_ENGINES = new ConcurrentHashMap<>();
+
+    public static ScriptEngine get(final String engineName) {
+        return CACHED_ENGINES.compute(engineName, (key, engine) -> {
+            if (null == engine) {
+                engine = SCRIPT_ENGINE_MANAGER.getEngineByName(engineName);
+                if (null == engine) {
+                    throw new IllegalArgumentException("There is no script engine with provided name: " + engineName);
+                }
+            }
+            return engine;
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Serializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Serializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Serializer.java
index 22dba7a..28bab16 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Serializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Serializer.java
@@ -27,7 +27,10 @@ import java.io.ObjectOutputStream;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public class Serializer {
+public final class Serializer {
+
+    private Serializer() {
+    }
 
     public static byte[] serializeObject(final Object object) throws IOException {
         final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TimeUtil.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TimeUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TimeUtil.java
index 1b0a8e3..22a46c5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TimeUtil.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/TimeUtil.java
@@ -26,6 +26,10 @@ import java.util.stream.IntStream;
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
 public final class TimeUtil {
+
+    private TimeUtil() {
+    }
+
     public static long secondsSince(final long startNanos) {
         return timeSince(startNanos, TimeUnit.SECONDS);
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambda.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambda.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambda.java
index cafba62..20a622c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambda.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambda.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.util.function;
 
-import org.apache.tinkerpop.gremlin.process.computer.util.ScriptEngineCache;
+import org.apache.tinkerpop.gremlin.util.ScriptEngineCache;
 
 import javax.script.Bindings;
 import javax.script.ScriptEngine;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/process/computer/util/ScriptEngineLambdaTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/process/computer/util/ScriptEngineLambdaTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/process/computer/util/ScriptEngineLambdaTest.java
deleted file mode 100644
index b0fb5de..0000000
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/process/computer/util/ScriptEngineLambdaTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.process.computer.util;
-
-import org.apache.tinkerpop.gremlin.util.function.ScriptEngineLambda;
-import org.junit.AfterClass;
-import org.junit.Test;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import java.util.HashSet;
-import java.util.Set;
-
-import static org.junit.Assert.*;
-
-/**
- * @author Matt Frantz (matthew.h.frantz+tinkerpop@gmail.com)
- */
-public class ScriptEngineLambdaTest {
-
-    private final static String GROOVY_SCRIPT_ENGINE_NAME = "Groovy";
-
-    // Function.apply
-
-    @Test
-    public void simpleFunctionWorks() {
-        final ScriptEngineLambda lambda = newGroovyLambda("a + 2");
-        assertEquals(lambda.apply(5), 7);
-        assertEquals(lambda.apply("foo"), "foo2");
-    }
-
-    // Supplier.get
-
-    @Test
-    public void simpleSupplierWorks() {
-        final ScriptEngineLambda lambda = newGroovyLambda("System.currentTimeMillis()");
-        assertNotEquals(lambda.get(), 0);
-    }
-
-    // Consumer.accept
-
-    @Test
-    public void simpleConsumerWorks() {
-        final Set set = pokeSet();
-        final ScriptEngineLambda lambda = newGroovyLambda("set.add(a)");
-
-        lambda.accept(1);
-        lambda.accept(2);
-        lambda.accept(3);
-
-        assertEquals(set.size(), 3);
-    }
-
-    // BiConsumer.accept
-
-    @Test
-    public void simpleBiConsumerWorks() {
-        final Set set = pokeSet();
-        final ScriptEngineLambda lambda = newGroovyLambda("set.add([a, b])");
-
-        lambda.accept(1, 2);
-        lambda.accept(2, 3);
-        lambda.accept(3, 4);
-
-        assertEquals(set.size(), 3);
-    }
-
-    // TriConsumer.accept
-
-    @Test
-    public void simpleTriConsumerWorks() {
-        final Set set = pokeSet();
-        final ScriptEngineLambda lambda = newGroovyLambda("set.add([a, b, c])");
-
-        lambda.accept(1, 2, 3);
-        lambda.accept(2, 3, 4);
-        lambda.accept(3, 4, 5);
-
-        assertEquals(set.size(), 3);
-    }
-
-    // Predicate.test
-
-    @Test
-    public void trivialGroovyPredicateWorks() {
-        final ScriptEngineLambda lambda = newGroovyLambda("true");
-        assertTrue(lambda.test("foo"));
-    }
-
-    @Test
-    public void oneArgGroovyPredicateWorks() {
-        final ScriptEngineLambda lambda = newGroovyLambda("a < 100");
-        assertTrue(lambda.test(0));
-        assertTrue(lambda.test(99));
-        assertFalse(lambda.test(100));
-    }
-
-    @Test
-    public void trivialGroovyFunctionWorks() {
-        final ScriptEngineLambda lambda = newGroovyLambda("2 + 2");
-        assertEquals(lambda.apply("foo"), 4);
-    }
-
-    @Test
-    public void oneArgGroovyFunctionWorks() {
-        final ScriptEngineLambda lambda = newGroovyLambda("a + 2");
-        assertEquals(lambda.apply(3), 5);
-        assertEquals(lambda.apply(10), 12);
-        assertEquals(lambda.apply("foo"), "foo2");
-    }
-
-    @AfterClass
-    public static void clearScriptEngineCache() {
-        ScriptEngineCache.get(GROOVY_SCRIPT_ENGINE_NAME).getBindings(ScriptContext.GLOBAL_SCOPE).clear();
-    }
-
-
-    // Utilities
-
-    /**
-     * Bind a set named "set" in the Groovy engine.
-     */
-    private static Set pokeSet() {
-        final ScriptEngine engine = getEngine();
-        final Bindings bindings = engine.createBindings();
-        final Set set = new HashSet();
-        bindings.put("set", set);
-        // Set the global bindings (since ScriptEngineLambda sets the engine bindings on each invocation).
-        engine.setBindings(bindings, ScriptContext.GLOBAL_SCOPE);
-        return set;
-    }
-
-    /**
-     * Return the engine used by ScriptEngineLambda in these tests.
-     */
-    private static ScriptEngine getEngine() {
-        return ScriptEngineCache.get(GROOVY_SCRIPT_ENGINE_NAME);
-    }
-
-    /**
-     * Create a ScriptEngineLambda that will accept Groovy.
-     */
-    private static ScriptEngineLambda newGroovyLambda(String groovy) {
-        return new ScriptEngineLambda(GROOVY_SCRIPT_ENGINE_NAME, groovy);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/8a711855/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambdaTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambdaTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambdaTest.java
new file mode 100644
index 0000000..5b5b616
--- /dev/null
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/util/function/ScriptEngineLambdaTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.function;
+
+import org.apache.tinkerpop.gremlin.util.ScriptEngineCache;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Matt Frantz (matthew.h.frantz+tinkerpop@gmail.com)
+ */
+public class ScriptEngineLambdaTest {
+
+    private final static String GROOVY_SCRIPT_ENGINE_NAME = "Groovy";
+
+    // Function.apply
+
+    @Test
+    public void simpleFunctionWorks() {
+        final ScriptEngineLambda lambda = newGroovyLambda("a + 2");
+        assertEquals(lambda.apply(5), 7);
+        assertEquals(lambda.apply("foo"), "foo2");
+    }
+
+    // Supplier.get
+
+    @Test
+    public void simpleSupplierWorks() {
+        final ScriptEngineLambda lambda = newGroovyLambda("System.currentTimeMillis()");
+        assertNotEquals(lambda.get(), 0);
+    }
+
+    // Consumer.accept
+
+    @Test
+    public void simpleConsumerWorks() {
+        final Set set = pokeSet();
+        final ScriptEngineLambda lambda = newGroovyLambda("set.add(a)");
+
+        lambda.accept(1);
+        lambda.accept(2);
+        lambda.accept(3);
+
+        assertEquals(set.size(), 3);
+    }
+
+    // BiConsumer.accept
+
+    @Test
+    public void simpleBiConsumerWorks() {
+        final Set set = pokeSet();
+        final ScriptEngineLambda lambda = newGroovyLambda("set.add([a, b])");
+
+        lambda.accept(1, 2);
+        lambda.accept(2, 3);
+        lambda.accept(3, 4);
+
+        assertEquals(set.size(), 3);
+    }
+
+    // TriConsumer.accept
+
+    @Test
+    public void simpleTriConsumerWorks() {
+        final Set set = pokeSet();
+        final ScriptEngineLambda lambda = newGroovyLambda("set.add([a, b, c])");
+
+        lambda.accept(1, 2, 3);
+        lambda.accept(2, 3, 4);
+        lambda.accept(3, 4, 5);
+
+        assertEquals(set.size(), 3);
+    }
+
+    // Predicate.test
+
+    @Test
+    public void trivialGroovyPredicateWorks() {
+        final ScriptEngineLambda lambda = newGroovyLambda("true");
+        assertTrue(lambda.test("foo"));
+    }
+
+    @Test
+    public void oneArgGroovyPredicateWorks() {
+        final ScriptEngineLambda lambda = newGroovyLambda("a < 100");
+        assertTrue(lambda.test(0));
+        assertTrue(lambda.test(99));
+        assertFalse(lambda.test(100));
+    }
+
+    @Test
+    public void trivialGroovyFunctionWorks() {
+        final ScriptEngineLambda lambda = newGroovyLambda("2 + 2");
+        assertEquals(lambda.apply("foo"), 4);
+    }
+
+    @Test
+    public void oneArgGroovyFunctionWorks() {
+        final ScriptEngineLambda lambda = newGroovyLambda("a + 2");
+        assertEquals(lambda.apply(3), 5);
+        assertEquals(lambda.apply(10), 12);
+        assertEquals(lambda.apply("foo"), "foo2");
+    }
+
+    @AfterClass
+    public static void clearScriptEngineCache() {
+        ScriptEngineCache.get(GROOVY_SCRIPT_ENGINE_NAME).getBindings(ScriptContext.GLOBAL_SCOPE).clear();
+    }
+
+
+    // Utilities
+
+    /**
+     * Bind a set named "set" in the Groovy engine.
+     */
+    private static Set pokeSet() {
+        final ScriptEngine engine = getEngine();
+        final Bindings bindings = engine.createBindings();
+        final Set set = new HashSet();
+        bindings.put("set", set);
+        // Set the global bindings (since ScriptEngineLambda sets the engine bindings on each invocation).
+        engine.setBindings(bindings, ScriptContext.GLOBAL_SCOPE);
+        return set;
+    }
+
+    /**
+     * Return the engine used by ScriptEngineLambda in these tests.
+     */
+    private static ScriptEngine getEngine() {
+        return ScriptEngineCache.get(GROOVY_SCRIPT_ENGINE_NAME);
+    }
+
+    /**
+     * Create a ScriptEngineLambda that will accept Groovy.
+     */
+    private static ScriptEngineLambda newGroovyLambda(String groovy) {
+        return new ScriptEngineLambda(GROOVY_SCRIPT_ENGINE_NAME, groovy);
+    }
+}