1 /* 2 * Copyright (c) 2016, 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 package jdk.nashorn.internal.runtime.linker.test; 26 27 import java.util.Collection; 28 import java.util.Deque; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Queue; 32 import java.util.function.Function; 33 import java.util.function.Supplier; 34 import javax.script.Bindings; 35 import javax.script.ScriptContext; 36 import javax.script.ScriptEngine; 37 import javax.script.ScriptException; 38 import jdk.nashorn.api.scripting.JSObject; 39 import jdk.nashorn.api.scripting.NashornScriptEngine; 40 import jdk.nashorn.api.scripting.NashornScriptEngineFactory; 41 import jdk.nashorn.api.scripting.ScriptObjectMirror; 42 import jdk.nashorn.internal.runtime.Context; 43 import org.testng.Assert; 44 import org.testng.annotations.Test; 45 46 public class JavaAdapterTest { 47 public interface TestConversions { 48 public byte getByte(byte b); 49 public short getShort(short b); 50 public char getChar(char c); 51 public int getInt(int i); 52 public float getFloat(float f); 53 public long getLong(long l); 54 public double getDouble(double d); 55 } 56 57 @Test 58 public static void testBlah() throws ScriptException { 59 final ScriptEngine e = createEngine(); 60 e.eval("new java.util.Comparator({})"); 61 } 62 63 @Test 64 public static void testConversions() throws ScriptException { 65 final ScriptEngine e = createEngine(); 66 e.put("TestConversionsClass", TestConversions.class); 67 final TestConversions tc = (TestConversions)e.eval( 68 "function id(x) { return x };" + 69 "new TestConversionsClass.static({" + 70 " getByte: id, getShort: id, getChar: id, getInt: id," + 71 " getFloat: id, getLong: id, getDouble: id });"); 72 73 Assert.assertEquals(Byte.MIN_VALUE, tc.getByte(Byte.MIN_VALUE)); 74 Assert.assertEquals(Byte.MAX_VALUE, tc.getByte(Byte.MAX_VALUE)); 75 76 Assert.assertEquals(Short.MIN_VALUE, tc.getShort(Short.MIN_VALUE)); 77 Assert.assertEquals(Short.MAX_VALUE, tc.getShort(Short.MAX_VALUE)); 78 79 Assert.assertEquals(Character.MIN_VALUE, tc.getChar(Character.MIN_VALUE)); 80 Assert.assertEquals(Character.MAX_VALUE, tc.getChar(Character.MAX_VALUE)); 81 82 Assert.assertEquals(Integer.MIN_VALUE, tc.getInt(Integer.MIN_VALUE)); 83 Assert.assertEquals(Integer.MAX_VALUE, tc.getInt(Integer.MAX_VALUE)); 84 85 Assert.assertEquals(Long.MIN_VALUE, tc.getLong(Long.MIN_VALUE)); 86 Assert.assertEquals(Long.MAX_VALUE, tc.getLong(Long.MAX_VALUE)); 87 88 Assert.assertEquals(Float.MIN_VALUE, tc.getFloat(Float.MIN_VALUE)); 89 Assert.assertEquals(Float.MAX_VALUE, tc.getFloat(Float.MAX_VALUE)); 90 Assert.assertEquals(Float.MIN_NORMAL, tc.getFloat(Float.MIN_NORMAL)); 91 Assert.assertEquals(Float.POSITIVE_INFINITY, tc.getFloat(Float.POSITIVE_INFINITY)); 92 Assert.assertEquals(Float.NEGATIVE_INFINITY, tc.getFloat(Float.NEGATIVE_INFINITY)); 93 Assert.assertTrue(Float.isNaN(tc.getFloat(Float.NaN))); 94 95 Assert.assertEquals(Double.MIN_VALUE, tc.getDouble(Double.MIN_VALUE)); 96 Assert.assertEquals(Double.MAX_VALUE, tc.getDouble(Double.MAX_VALUE)); 97 Assert.assertEquals(Double.MIN_NORMAL, tc.getDouble(Double.MIN_NORMAL)); 98 Assert.assertEquals(Double.POSITIVE_INFINITY, tc.getDouble(Double.POSITIVE_INFINITY)); 99 Assert.assertEquals(Double.NEGATIVE_INFINITY, tc.getDouble(Double.NEGATIVE_INFINITY)); 100 Assert.assertTrue(Double.isNaN(tc.getDouble(Double.NaN))); 101 } 102 103 private static ScriptEngine createEngine() { 104 // Use no optimistic typing so we run faster; short-running tests. 105 return new NashornScriptEngineFactory().getScriptEngine("-ot=false"); 106 } 107 108 @Test 109 public static void testUnimplemented() throws ScriptException { 110 final ScriptEngine e = createEngine(); 111 final Runnable r = (Runnable) e.eval("new java.lang.Runnable({})"); 112 Assert.assertNull(Context.getGlobal()); 113 try { 114 r.run(); 115 Assert.fail(); 116 } catch(final UnsupportedOperationException x) { 117 // This is expected 118 } 119 // Check global has been restored 120 Assert.assertNull(Context.getGlobal()); 121 } 122 123 public interface ThrowingRunnable { 124 public void run() throws Throwable; 125 } 126 127 @Test 128 public static void testUnimplementedWithThrowable() throws Throwable { 129 final ScriptEngine e = createEngine(); 130 e.put("ThrowingRunnableClass", ThrowingRunnable.class); 131 final ThrowingRunnable r = (ThrowingRunnable) e.eval("new ThrowingRunnableClass.static({})"); 132 Assert.assertNull(Context.getGlobal()); 133 try { 134 r.run(); 135 Assert.fail(); 136 } catch(final UnsupportedOperationException x) { 137 // This is expected 138 } 139 // Check global has been restored 140 Assert.assertNull(Context.getGlobal()); 141 } 142 143 public interface IntSupplierWithDefault { 144 public default int get() { return 42; } 145 } 146 147 @Test 148 public static void testUnimplementedWithDefault() throws ScriptException { 149 final ScriptEngine e = createEngine(); 150 e.put("IntSupplierWithDefault", IntSupplierWithDefault.class); 151 final IntSupplierWithDefault s1 = (IntSupplierWithDefault) e.eval("new IntSupplierWithDefault.static({})"); 152 Assert.assertEquals(42, s1.get()); 153 final IntSupplierWithDefault s2 = (IntSupplierWithDefault) e.eval("new IntSupplierWithDefault.static({ get: function() { return 43 }})"); 154 Assert.assertEquals(43, s2.get()); 155 } 156 157 public interface SupplierSupplier { 158 public Supplier<Object> getSupplier(); 159 } 160 161 @Test 162 public static void testReturnAdapter() throws ScriptException { 163 final ScriptEngine e = createEngine(); 164 e.put("SupplierSupplier", SupplierSupplier.class); 165 final SupplierSupplier s = (SupplierSupplier) e.eval("new SupplierSupplier.static(function(){ return function() { return 'foo' } })"); 166 Assert.assertEquals("foo", s.getSupplier().get()); 167 } 168 169 public interface MaxParams { 170 public Object method(boolean p1, byte p2, short p3, char p4, int p5, float p6, long p7, double p8, 171 Object p9, Object p10, Object p11, Object p12, Object p13, Object p14, Object p15, Object p16, 172 Object p17, Object p18, Object p19, Object p20, Object p21, Object p22, Object p23, Object p24, 173 Object p25, Object p26, Object p27, Object p28, Object p29, Object p30, Object p31, Object p32, 174 Object p33, Object p34, Object p35, Object p36, Object p37, Object p38, Object p39, Object p40, 175 Object p41, Object p42, Object p43, Object p44, Object p45, Object p46, Object p47, Object p48, 176 Object p49, Object p50, Object p51, Object p52, Object p53, Object p54, Object p55, Object p56, 177 Object p57, Object p58, Object p59, Object p60, Object p61, Object p62, Object p63, Object p64, 178 Object p65, Object p66, Object p67, Object p68, Object p69, Object p70, Object p71, Object p72, 179 Object p73, Object p74, Object p75, Object p76, Object p77, Object p78, Object p79, Object p80, 180 Object p81, Object p82, Object p83, Object p84, Object p85, Object p86, Object p87, Object p88, 181 Object p89, Object p90, Object p91, Object p92, Object p93, Object p94, Object p95, Object p96, 182 Object p97, Object p98, Object p99, Object p100, Object p101, Object p102, Object p103, Object p104, 183 Object p105, Object p106, Object p107, Object p108, Object p109, Object p110, Object p111, Object p112, 184 Object p113, Object p114, Object p115, Object p116, Object p117, Object p118, Object p119, Object p120, 185 Object p121, Object p122, Object p123, Object p124, Object p125, Object p126, Object p127, Object p128, 186 Object p129, Object p130, Object p131, Object p132, Object p133, Object p134, Object p135, Object p136, 187 Object p137, Object p138, Object p139, Object p140, Object p141, Object p142, Object p143, Object p144, 188 Object p145, Object p146, Object p147, Object p148, Object p149, Object p150, Object p151, Object p152, 189 Object p153, Object p154, Object p155, Object p156, Object p157, Object p158, Object p159, Object p160, 190 Object p161, Object p162, Object p163, Object p164, Object p165, Object p166, Object p167, Object p168, 191 Object p169, Object p170, Object p171, Object p172, Object p173, Object p174, Object p175, Object p176, 192 Object p177, Object p178, Object p179, Object p180, Object p181, Object p182, Object p183, Object p184, 193 Object p185, Object p186, Object p187, Object p188, Object p189, Object p190, Object p191, Object p192, 194 Object p193, Object p194, Object p195, Object p196, Object p197, Object p198, Object p199, Object p200, 195 Object p201, Object p202, Object p203, Object p204, Object p205, Object p206, Object p207, Object p208, 196 Object p209, Object p210, Object p211, Object p212, Object p213, Object p214, Object p215, Object p216, 197 Object p217, Object p218, Object p219, Object p220, Object p221, Object p222, Object p223, Object p224, 198 Object p225, Object p226, Object p227, Object p228, Object p229, Object p230, Object p231, Object p232, 199 Object p233, Object p234, Object p235, Object p236, Object p237, Object p238, Object p239, Object p240, 200 Object p241, Object p242, Object p243, Object p244, Object p245, Object p246, Object p247, Object p248, 201 Object p249, Object p250, Object p251, Object p252); 202 } 203 204 @Test 205 public static void testMaxLengthAdapter() throws ScriptException { 206 final ScriptEngine e = createEngine(); 207 e.put("MaxParams", MaxParams.class); 208 final MaxParams s = (MaxParams) e.eval("new MaxParams.static(function(){ return arguments })"); 209 final ScriptObjectMirror m = (ScriptObjectMirror)s.method(true, Byte.MIN_VALUE, Short.MIN_VALUE, 'a', Integer.MAX_VALUE, Float.MAX_VALUE, Long.MAX_VALUE, Double.MAX_VALUE, 210 "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", 211 "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", 212 "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", 213 "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", 214 "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", 215 "99", "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", "110", "111", "112", "113", "114", 216 "115", "116", "117", "118", "119", "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", "130", 217 "131", "132", "133", "134", "135", "136", "137", "138", "139", "140", "141", "142", "143", "144", "145", "146", 218 "147", "148", "149", "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", "160", "161", "162", 219 "163", "164", "165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175", "176", "177", "178", 220 "179", "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", "190", "191", "192", "193", "194", 221 "195", "196", "197", "198", "199", "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", "210", 222 "211", "212", "213", "214", "215", "216", "217", "218", "219", "220", "221", "222", "223", "224", "225", "226", 223 "227", "228", "229", "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", "240", "241", "242", 224 "243", "244", "245", "246", "247", "248", "249", "250", "251"); 225 Assert.assertEquals(true, m.getSlot(0)); 226 Assert.assertEquals(Integer.valueOf(Byte.MIN_VALUE), m.getSlot(1)); // Byte becomes Integer 227 Assert.assertEquals(Integer.valueOf(Short.MIN_VALUE), m.getSlot(2)); // Short becomes Integer 228 Assert.assertEquals(Character.valueOf('a'), m.getSlot(3)); 229 Assert.assertEquals(Integer.valueOf(Integer.MAX_VALUE), m.getSlot(4)); 230 Assert.assertEquals(Double.valueOf(Float.MAX_VALUE), m.getSlot(5)); // Float becomes Double 231 Assert.assertEquals(Long.valueOf(Long.MAX_VALUE), m.getSlot(6)); // Long was untouched 232 Assert.assertEquals(Double.valueOf(Double.MAX_VALUE), m.getSlot(7)); 233 for (int i = 8; i < 252; ++i) { 234 Assert.assertEquals(String.valueOf(i), m.getSlot(i)); 235 } 236 } 237 238 public interface TestScriptObjectMirror { 239 public JSObject getJSObject(); 240 public ScriptObjectMirror getScriptObjectMirror(); 241 public Map<Object, Object> getMap(); 242 public Bindings getBindings(); 243 } 244 245 @Test 246 public static void testReturnsScriptObjectMirror() throws ScriptException { 247 final ScriptEngine e = createEngine(); 248 e.put("TestScriptObjectMirrorClass", TestScriptObjectMirror.class); 249 final TestScriptObjectMirror tsom = (TestScriptObjectMirror)e.eval( 250 "new TestScriptObjectMirrorClass.static({\n" + 251 " getJSObject: function() { return { 'kind': 'JSObject' } },\n" + 252 " getScriptObjectMirror: function() { return { 'kind': 'ScriptObjectMirror' } },\n" + 253 " getMap: function() { return { 'kind': 'Map' } },\n" + 254 " getBindings: function() { return { 'kind': 'Bindings' } } })\n"); 255 Assert.assertEquals(tsom.getJSObject().getMember("kind"), "JSObject"); 256 Assert.assertEquals(tsom.getScriptObjectMirror().getMember("kind"), "ScriptObjectMirror"); 257 Assert.assertEquals(tsom.getMap().get("kind"), "Map"); 258 Assert.assertEquals(tsom.getBindings().get("kind"), "Bindings"); 259 } 260 261 public interface TestListAdapter { 262 public List<Object> getList(); 263 public Collection<Object> getCollection(); 264 public Queue<Object> getQueue(); 265 public Deque<Object> getDequeue(); 266 } 267 268 @Test 269 public static void testReturnsListAdapter() throws ScriptException { 270 final ScriptEngine e = createEngine(); 271 e.put("TestListAdapterClass", TestListAdapter.class); 272 final TestListAdapter tla = (TestListAdapter)e.eval( 273 "new TestListAdapterClass.static({\n" + 274 " getList: function() { return [ 'List' ] },\n" + 275 " getCollection: function() { return [ 'Collection' ] },\n" + 276 " getQueue: function() { return [ 'Queue' ] },\n" + 277 " getDequeue: function() { return [ 'Dequeue' ] } })\n"); 278 Assert.assertEquals(tla.getList().get(0), "List"); 279 Assert.assertEquals(tla.getCollection().iterator().next(), "Collection"); 280 Assert.assertEquals(tla.getQueue().peek(), "Queue"); 281 Assert.assertEquals(tla.getDequeue().peek(), "Dequeue"); 282 } 283 284 @Test 285 public static void testMirrorAdapter() throws ScriptException { 286 final NashornScriptEngine e = (NashornScriptEngine) createEngine(); 287 e.setBindings(e.createBindings(), ScriptContext.GLOBAL_SCOPE); // Null by default 288 289 // Referencing functions from across scopes causes them to be wrapped in ScriptObjectMirrors 290 e.eval("function convertObjectFromEngineScope(){ return new java.util.concurrent.Callable(o).call(); }", e.getBindings(ScriptContext.ENGINE_SCOPE)); 291 e.eval("function convertObjectFromGlobalScope(){ return new java.util.concurrent.Callable(o).call(); }", e.getBindings(ScriptContext.GLOBAL_SCOPE)); 292 e.eval("function convertFuncFromEngineScope(){ return new java.util.concurrent.Callable(g).call(); }", e.getBindings(ScriptContext.ENGINE_SCOPE)); 293 e.eval("function convertFuncFromGlobalScope(){ return new java.util.concurrent.Callable(g).call(); }", e.getBindings(ScriptContext.GLOBAL_SCOPE)); 294 e.eval("function convertParamFromEngineScope(){ return Java.type('jdk.nashorn.internal.runtime.linker.test.JavaAdapterTest').m(f);}", e.getBindings(ScriptContext.ENGINE_SCOPE)); 295 e.eval("function convertParamFromGlobalScope(){ return Java.type('jdk.nashorn.internal.runtime.linker.test.JavaAdapterTest').m(f);}", e.getBindings(ScriptContext.GLOBAL_SCOPE)); 296 297 e.eval("var o = { call: function () { return 'ok from o'; } }", e.getBindings(ScriptContext.ENGINE_SCOPE)); 298 e.eval("function g() { return 'ok from g'; }", e.getBindings(ScriptContext.ENGINE_SCOPE)); 299 e.eval("function f(a) { return a.toUpperCase(); }", e.getBindings(ScriptContext.ENGINE_SCOPE)); 300 301 try { 302 Assert.assertEquals(e.invokeFunction("convertObjectFromEngineScope"), "ok from o"); 303 Assert.assertEquals(e.invokeFunction("convertObjectFromGlobalScope"), "ok from o"); 304 Assert.assertEquals(e.invokeFunction("convertFuncFromEngineScope"), "ok from g"); 305 Assert.assertEquals(e.invokeFunction("convertFuncFromGlobalScope"), "ok from g"); 306 Assert.assertEquals(e.invokeFunction("convertParamFromEngineScope"), "OK"); 307 Assert.assertEquals(e.invokeFunction("convertParamFromGlobalScope"), "OK"); 308 } catch (final NoSuchMethodException x) { 309 throw new RuntimeException(x); 310 } 311 } 312 313 public static String m(final Function<String, String> f){ 314 return f.apply("ok"); 315 } 316 }