package org.enumerable.lambda.support.groovy; import static java.util.Arrays.*; import static org.enumerable.lambda.Parameters.*; import static org.enumerable.lambda.support.groovy.LambdaGroovy.*; import static org.junit.Assert.*; import groovy.lang.Closure; import groovy.lang.MissingMethodException; import java.util.List; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import org.codehaus.groovy.runtime.MethodClosure; import org.enumerable.lambda.Fn1; import org.enumerable.lambda.Lambda; import org.enumerable.lambda.enumerable.Enumerable; import org.enumerable.lambda.support.clojure.ClojureTest; import org.enumerable.lambda.support.clojure.LambdaClojure; import org.enumerable.lambda.support.groovy.LambdaGroovy.ClosureFn2; import org.enumerable.lambda.support.javascript.JavaScriptTest; import org.enumerable.lambda.support.javascript.LambdaJavaScript; import org.enumerable.lambda.support.jruby.JRubyTest; import org.enumerable.lambda.support.jruby.LambdaJRuby; import org.enumerable.lambda.support.scala.LambdaScala; import org.enumerable.lambda.support.scala.ScalaTest; import org.enumerable.lambda.support.scala.ScalaTest.ScalaInterpreter; import org.jruby.RubyProc; import org.junit.Before; import org.junit.Test; import scala.Function2; import sun.org.mozilla.javascript.internal.Function; import clojure.lang.IFn; public class GroovyTest { ScriptEngine groovy; @Test public void interactingWithGroovy() throws ScriptException { groovy.put("c", closure(n, n * 2)); assertEquals(4, groovy.eval("c(2);")); groovy.put("c", closure(b, !b)); assertTrue((Boolean) groovy.eval("c(false);")); groovy.put("c", closure(s, s.toUpperCase())); assertEquals("HELLO", groovy.eval("c('hello');")); groovy.put("c", closure(obj, obj)); assertNull(groovy.eval("c(null);")); } @Test public void defaultValuesForJavaScriptFunctions() throws ScriptException { groovy.put("c", closure(n = 2, n * 2)); assertEquals(4, groovy.eval("c()")); groovy.put("c", closure(n, m = 2, n * m)); assertEquals(8, groovy.eval("c(4)")); groovy.put("c", closure(n = 2, m = 2, n * m)); assertEquals(4, groovy.eval("c()")); } @Test public void convertFnToClosure() throws ScriptException { Closure<?> closure = toClosure(Lambda.λ(s, s.toUpperCase())); assertEquals("HELLO", closure.call(new Object[] { "hello" })); } @Test public void convertFnToClosureKeepsDefaultValues() throws ScriptException { Closure<?> closure = toClosure(Lambda.λ(s = "world", s.toUpperCase())); assertEquals("WORLD", closure.call(new Object[0])); } @Test(expected = NullPointerException.class) public void convertedClosureThrowsExceptionWhenCalledWithTooFewArguments() throws ScriptException { Closure<?> closure = toClosure(Lambda.λ(s, s.toUpperCase())); closure.call(new Object[0]); } @Test(expected = MissingMethodException.class) public void convertedClosureThrowsExceptionWhenCalledWithTooManyArguments() throws ScriptException { Closure<?> closure = toClosure(Lambda.λ(s, s.toUpperCase())); closure.call(new Object[] { "hello", "world" }); } @Test public void convertClosureToFn() throws ScriptException { Closure<?> closure = (Closure<?>) groovy.eval("{ it -> it.toUpperCase() }"); assertEquals("HELLO", toFn1(closure).call("hello")); } @Test public void convertGroovyMethodToFn() throws ScriptException { MethodClosure closure = (MethodClosure) groovy.eval("'hello'.&toUpperCase"); assertEquals("HELLO", toFn0(closure).call()); } @Test public void interactingWithEnumerableJava() throws Exception { List<Integer> list = asList(1, 2, 3); Fn1<Object, Object> block = toFn1((Closure<?>) groovy.eval("{ n -> n * 2 }")); assertEquals(asList(2, 4, 6), Enumerable.collect(list, block)); } @Test public void interactingWithClojure() throws Exception { IFn star = (IFn) ClojureTest.getClojureEngine().eval("*"); Closure<?> closure = toClosure(LambdaClojure.toFn2(star)); groovy.put("f", closure); assertEquals(6L, groovy.eval("f(2, 3)")); } @Test public void interactingWithJRuby() throws Exception { ScriptEngine rb = JRubyTest.getJRubyEngine(); RubyProc proc = (RubyProc) rb.eval(":*.to_proc"); Closure<?> closure = toClosure(LambdaJRuby.toFn2(proc)); groovy.put("f", closure); assertEquals(6L, groovy.eval("f(2, 3)")); } @Test public void interactingWithJavaScript() throws Exception { ScriptEngine js = JavaScriptTest.getJavaScriptEngine(); Function f = (Function) js.eval("var f = function(n, m) { return n * m; }; f;"); ClosureFn2 closure = toClosure(LambdaJavaScript.toFn2(f)); assertEquals(6.0, closure.call(new Object[] { 2, 3 })); groovy.put("closure", closure); assertEquals(120.0, groovy.eval("[1, 2, 3, 4, 5].inject(1, closure)")); } @SuppressWarnings("unchecked") @Test public void interactingWithScala() throws Exception { ScalaInterpreter scala = ScalaTest.getScalaInterpreter(); Function2<Integer, Integer, Integer> f = (Function2<Integer, Integer, Integer>) scala.eval("(n: Int, m: Int) => n * m"); Closure<?> closure = toClosure(LambdaScala.toFn2(f)); groovy.put("closure", closure); assertEquals(120, groovy.eval("[1, 2, 3, 4, 5].inject(1, closure)")); } @Before public void initEngine() { groovy = getGroovyEngine(); } public static ScriptEngine getGroovyEngine() { ScriptEngineManager manager = new ScriptEngineManager(); return manager.getEngineByName("Groovy"); } }