LexicalBindingTest.java revision 1239:77609e069f9f
1/*
2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.runtime.test;
27
28import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
29import org.testng.annotations.Test;
30
31import javax.script.Bindings;
32import javax.script.ScriptContext;
33import javax.script.ScriptEngine;
34import javax.script.ScriptException;
35import javax.script.SimpleScriptContext;
36
37import static org.testng.Assert.assertEquals;
38
39/**
40 * Top-level lexical binding tests.
41 *
42 * @test
43 * @run testng jdk.nashorn.internal.runtime.LexicalBindingTest
44 */
45@SuppressWarnings("javadoc")
46public class LexicalBindingTest {
47
48    final static String LANGUAGE_ES6 = "--language=es6";
49    final static int NUMBER_OF_CONTEXTS = 20;
50    final static int MEGAMORPHIC_LOOP_COUNT = 20;
51
52    /**
53     * Test access to global var-declared variables for shared script classes with multiple globals.
54     */
55    @Test
56    public static void megamorphicVarTest() throws ScriptException, InterruptedException {
57        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
58        final ScriptEngine e = factory.getScriptEngine();
59        final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
60        final String sharedScript = "foo";
61
62
63        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
64            final ScriptContext context = contexts[i] = new SimpleScriptContext();
65            final Bindings b = e.createBindings();
66            context.setBindings(b, ScriptContext.ENGINE_SCOPE);
67            assertEquals(e.eval("var foo = '" + i + "';", context), null);
68        }
69
70        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
71            final ScriptContext context = contexts[i];
72            assertEquals(e.eval(sharedScript, context), String.valueOf(i));
73        }
74    }
75
76    /**
77     * Test access to global lexically declared variables for shared script classes with multiple globals.
78     */
79    @Test
80    public static void megamorphicMultiGlobalLetTest() throws ScriptException, InterruptedException {
81        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
82        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
83        final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
84        final String sharedScript = "foo";
85
86
87        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
88            final ScriptContext context = contexts[i] = new SimpleScriptContext();
89            final Bindings b = e.createBindings();
90            context.setBindings(b, ScriptContext.ENGINE_SCOPE);
91            assertEquals(e.eval("let foo = '" + i + "';", context), null);
92        }
93
94        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
95            final ScriptContext context = contexts[i];
96            assertEquals(e.eval(sharedScript, context), String.valueOf(i));
97        }
98    }
99
100
101    /**
102     * Test access to global lexically declared variables for shared script classes with single global.
103     */
104    @Test
105    public static void megamorphicSingleGlobalLetTest() throws ScriptException, InterruptedException {
106        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
107        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
108        final String sharedGetterScript = "foo";
109        final String sharedSetterScript = "foo = 1";
110
111        for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
112            assertEquals(e.eval(sharedSetterScript), 1);
113            assertEquals(e.eval(sharedGetterScript), 1);
114            assertEquals(e.eval("delete foo; a" + i + " = 1; foo = " + i + ";"), i);
115            assertEquals(e.eval(sharedGetterScript), i);
116        }
117
118        assertEquals(e.eval("let foo = 'foo';"), null);
119        assertEquals(e.eval(sharedGetterScript), "foo");
120        assertEquals(e.eval(sharedSetterScript), 1);
121        assertEquals(e.eval(sharedGetterScript), 1);
122        assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
123    }
124
125    /**
126     * Test access to global lexically declared variables for shared script classes with single global.
127     */
128    @Test
129    public static void megamorphicInheritedGlobalLetTest() throws ScriptException, InterruptedException {
130        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
131        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
132        final String sharedGetterScript = "foo";
133        final String sharedSetterScript = "foo = 1";
134
135        for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
136            assertEquals(e.eval(sharedSetterScript), 1);
137            assertEquals(e.eval(sharedGetterScript), 1);
138            assertEquals(e.eval("delete foo; a" + i + " = 1; Object.prototype.foo = " + i + ";"), i);
139            assertEquals(e.eval(sharedGetterScript), i);
140        }
141
142        assertEquals(e.eval("let foo = 'foo';"), null);
143        assertEquals(e.eval(sharedGetterScript), "foo");
144        assertEquals(e.eval(sharedSetterScript), 1);
145        assertEquals(e.eval(sharedGetterScript), 1);
146        assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
147    }
148
149    /**
150     * Test multi-threaded access to global lexically declared variables for shared script classes with multiple globals.
151     */
152    @Test
153    public static void multiThreadedLetTest() throws ScriptException, InterruptedException {
154        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
155        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
156        final Bindings b = e.createBindings();
157        final ScriptContext origContext = e.getContext();
158        final ScriptContext newCtxt = new SimpleScriptContext();
159        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
160        final String sharedScript = "foo";
161
162        assertEquals(e.eval("let foo = 'original context';", origContext), null);
163        assertEquals(e.eval("let foo = 'new context';", newCtxt), null);
164
165        final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
166        final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
167        t1.start();
168        t2.start();
169        t1.join();
170        t2.join();
171
172        assertEquals(e.eval("foo = 'newer context';", newCtxt), "newer context");
173        final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
174        final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
175
176        t3.start();
177        t4.start();
178        t3.join();
179        t4.join();
180
181        assertEquals(e.eval(sharedScript), "original context");
182        assertEquals(e.eval(sharedScript, newCtxt), "newer context");
183    }
184
185    private static class ScriptRunner implements Runnable {
186
187        final ScriptEngine engine;
188        final ScriptContext context;
189        final String source;
190        final Object expected;
191        final int iterations;
192
193        ScriptRunner(final ScriptEngine engine, final ScriptContext context, final String source, final Object expected, final int iterations) {
194            this.engine = engine;
195            this.context = context;
196            this.source = source;
197            this.expected = expected;
198            this.iterations = iterations;
199        }
200
201        @Override
202        public void run() {
203            try {
204                for (int i = 0; i < iterations; i++) {
205                    assertEquals(engine.eval(source, context), expected);
206                }
207            } catch (final ScriptException se) {
208                throw new RuntimeException(se);
209            }
210        }
211    }
212}
213