/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.scripting; import static com.github.anba.es6draft.util.matchers.IsInstanceOfWith.instanceOfWith; import static com.github.anba.es6draft.util.matchers.IsNumberCloseTo.numberCloseTo; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; import java.io.StringReader; import javax.script.Bindings; import javax.script.Invocable; import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import org.junit.Before; import org.junit.Test; /** * JSR-223 Scripting API tests */ public final class ScriptEngineTest { private ScriptEngineManager manager; private ScriptEngine engine; @Before public void setUp() { manager = new ScriptEngineManager(); engine = manager.getEngineByName("es6draft"); assertThat(engine, notNullValue()); } @Test public void contextAndBindings() { ScriptContext context = engine.getContext(); assertThat(context, notNullValue()); assertThat(context, sameInstance(engine.getContext())); Bindings globalScope = engine.getBindings(ScriptContext.GLOBAL_SCOPE); assertThat(globalScope, notNullValue()); assertThat(globalScope, sameInstance(engine.getBindings(ScriptContext.GLOBAL_SCOPE))); assertThat(globalScope, sameInstance(context.getBindings(ScriptContext.GLOBAL_SCOPE))); assertThat(globalScope, sameInstance(manager.getBindings())); Bindings engineScope = engine.getBindings(ScriptContext.ENGINE_SCOPE); assertThat(engineScope, notNullValue()); assertThat(engineScope, sameInstance(engine.getBindings(ScriptContext.ENGINE_SCOPE))); assertThat(engineScope, sameInstance(context.getBindings(ScriptContext.ENGINE_SCOPE))); assertThat(engineScope, not(sameInstance(manager.getBindings()))); } @Test(expected = IllegalArgumentException.class) public void invalidBinding() { engine.getBindings(ScriptContext.ENGINE_SCOPE + 1); } @Test public void getAndPut() throws ScriptException { final String key1 = "key1", key2 = "key2"; final String value1 = "value1", value2 = "value2", value3 = "value3"; Bindings engineScope = engine.getBindings(ScriptContext.ENGINE_SCOPE); // key-value is initially null assertThat(engine.get(key1), nullValue()); assertThat(engineScope.get(key1), nullValue()); // can set from engine key-value and retrieve values from engine and bindings engine.put(key1, value1); assertThat(engine.get(key1), instanceOfWith(String.class, is(value1))); assertThat(engineScope.get(key1), instanceOfWith(String.class, is(value1))); // can override from engine key-value and retrieve new values from engine and bindings engine.put(key1, value2); assertThat(engine.get(key1), instanceOfWith(String.class, is(value2))); assertThat(engineScope.get(key1), instanceOfWith(String.class, is(value2))); // can override key-value from bindings and retrieve new values from engine and bindings Object oldValueA = engineScope.put(key1, value3); assertThat(oldValueA, instanceOfWith(String.class, is(value2))); assertThat(engine.get(key1), instanceOfWith(String.class, is(value3))); assertThat(engineScope.get(key1), instanceOfWith(String.class, is(value3))); // can set key-value from bindings and retrieve values from engine and bindings Object oldValueB = engineScope.put(key2, value1); assertThat(oldValueB, nullValue()); assertThat(engine.get(key2), instanceOfWith(String.class, is(value1))); assertThat(engineScope.get(key2), instanceOfWith(String.class, is(value1))); // can override key-value from bindings and retrieve new values from engine and bindings Object oldValueC = engineScope.put(key2, value2); assertThat(oldValueC, instanceOfWith(String.class, is(value1))); assertThat(engine.get(key2), instanceOfWith(String.class, is(value2))); assertThat(engineScope.get(key2), instanceOfWith(String.class, is(value2))); // can override key-value from engine and retrieve new values from engine and bindings engine.put(key2, value3); assertThat(engine.get(key2), instanceOfWith(String.class, is(value3))); assertThat(engineScope.get(key2), instanceOfWith(String.class, is(value3))); } @Test(expected = NullPointerException.class) public void getNullKey() { engine.get(null); } @Test(expected = IllegalArgumentException.class) public void getEmptyKey() { engine.get(""); } @Test(expected = NullPointerException.class) public void putNullKey() { engine.put(null, 0); } @Test(expected = IllegalArgumentException.class) public void putEmptyKey() { engine.put("", 0); } @Test public void evalString() throws ScriptException { Object value1 = engine.eval("1 + 2"); assertThat(value1, instanceOfWith(Number.class, is(numberCloseTo(3)))); Object value2 = engine.eval("function f() { return 5 * 2 } f()"); assertThat(value2, instanceOfWith(Number.class, is(numberCloseTo(10)))); } @Test public void evalReader() throws ScriptException { Object value1 = engine.eval(new StringReader("4 + 2")); assertThat(value1, instanceOfWith(Number.class, is(numberCloseTo(6)))); Object value2 = engine.eval(new StringReader("function f() { return 10 * 3.5 } f()")); assertThat(value2, instanceOfWith(Number.class, is(numberCloseTo(35)))); } @Test public void evalDeclarations() throws ScriptException { engine.eval("function f() { return 'vvv' }"); Object value = engine.eval("f()"); assertThat(value, instanceOfWith(String.class, is("vvv"))); } @Test public void evalExplicitContext() throws ScriptException { ScriptContext context = engine.getContext(); assertThat(context, notNullValue()); Object value = engine.eval("function f() { return 'vvv' } f()", context); assertThat(value, instanceOfWith(String.class, is("vvv"))); } @Test public void evalExplicitBindings() throws ScriptException { Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); assertThat(bindings, notNullValue()); Object value = engine.eval("function f() { return 'vvv' } f()", bindings); assertThat(value, instanceOfWith(String.class, is("vvv"))); } @Test(expected = ScriptException.class) public void evalMissingDefinition() throws ScriptException { engine.eval("f()"); } @Test(expected = ScriptException.class) public void evalSyntaxError() throws ScriptException { engine.eval("invalid[syntax"); } @Test public void processJobQueue() throws ScriptException { engine.put("log", ""); Object value = engine.eval("Promise.resolve().then(() => log += 'b'); log = 'a'; log;"); assertThat(value, instanceOfWith(String.class, is("a"))); assertThat(engine.get("log"), instanceOfWith(String.class, is("ab"))); } @Test public void processJobQueueWithInvoke() throws ScriptException, NoSuchMethodException { engine.put("log", ""); engine.eval("function F() { Promise.resolve().then(() => log += 'b'); log = 'a'; return log; }"); Object value = ((Invocable) engine).invokeFunction("F"); assertThat(value, instanceOfWith(String.class, is("a"))); assertThat(engine.get("log"), instanceOfWith(String.class, is("ab"))); } }