1 /*
   2  * Copyright (c) 2010, 2013, 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 
  26 package jdk.nashorn.api.scripting;
  27 
  28 import java.util.HashMap;
  29 import java.util.List;
  30 import java.util.Map;
  31 import javax.script.ScriptEngine;
  32 import javax.script.ScriptEngineManager;
  33 import javax.script.ScriptException;
  34 import static org.testng.Assert.assertEquals;
  35 import static org.testng.Assert.assertFalse;
  36 import static org.testng.Assert.assertTrue;
  37 import static org.testng.Assert.fail;
  38 import org.testng.annotations.Test;
  39 
  40 /**
  41  * Tests to check jdk.nashorn.api.scripting.ScriptObjectMirror API.
  42  */
  43 public class ScriptObjectMirrorTest {
  44 
  45     @SuppressWarnings("unchecked")
  46     @Test
  47     public void reflectionTest() throws ScriptException {
  48         final ScriptEngineManager m = new ScriptEngineManager();
  49         final ScriptEngine e = m.getEngineByName("nashorn");
  50 
  51         e.eval("var obj = { x: 344, y: 'nashorn' }");
  52 
  53         int count = 0;
  54         Map<Object, Object> map = (Map<Object, Object>) e.get("obj");
  55         assertFalse(map.isEmpty());
  56         assertTrue(map.keySet().contains("x"));
  57         assertTrue(map.containsKey("x"));
  58         assertTrue(map.values().contains("nashorn"));
  59         assertTrue(map.containsValue("nashorn"));
  60         for (final Map.Entry<?, ?> ex : map.entrySet()) {
  61             final Object key = ex.getKey();
  62             if (key.equals("x")) {
  63                 assertTrue(344 == ((Number) ex.getValue()).doubleValue());
  64                 count++;
  65             } else if (key.equals("y")) {
  66                 assertEquals(ex.getValue(), "nashorn");
  67                 count++;
  68             }
  69         }
  70         assertEquals(2, count);
  71         assertEquals(2, map.size());
  72 
  73         // add property
  74         map.put("z", "hello");
  75         assertEquals(e.eval("obj.z"), "hello");
  76         assertEquals(map.get("z"), "hello");
  77         assertTrue(map.keySet().contains("z"));
  78         assertTrue(map.containsKey("z"));
  79         assertTrue(map.values().contains("hello"));
  80         assertTrue(map.containsValue("hello"));
  81         assertEquals(map.size(), 3);
  82 
  83         final Map<Object, Object> newMap = new HashMap<>();
  84         newMap.put("foo", 23.0);
  85         newMap.put("bar", true);
  86         map.putAll(newMap);
  87 
  88         assertEquals(e.eval("obj.foo"), 23.0);
  89         assertEquals(e.eval("obj.bar"), true);
  90 
  91         // remove using map method
  92         map.remove("foo");
  93         assertEquals(e.eval("typeof obj.foo"), "undefined");
  94 
  95         count = 0;
  96         e.eval("var arr = [ true, 'hello' ]");
  97         map = (Map<Object, Object>) e.get("arr");
  98         assertFalse(map.isEmpty());
  99         assertTrue(map.containsKey("length"));
 100         assertTrue(map.containsValue("hello"));
 101         for (final Map.Entry<?, ?> ex : map.entrySet()) {
 102             final Object key = ex.getKey();
 103             if (key.equals("0")) {
 104                 assertEquals(ex.getValue(), Boolean.TRUE);
 105                 count++;
 106             } else if (key.equals("1")) {
 107                 assertEquals(ex.getValue(), "hello");
 108                 count++;
 109             }
 110         }
 111         assertEquals(count, 2);
 112         assertEquals(map.size(), 2);
 113 
 114         // add element
 115         map.put("2", "world");
 116         assertEquals(map.get("2"), "world");
 117         assertEquals(map.size(), 3);
 118 
 119         // remove all
 120         map.clear();
 121         assertTrue(map.isEmpty());
 122         assertEquals(e.eval("typeof arr[0]"), "undefined");
 123         assertEquals(e.eval("typeof arr[1]"), "undefined");
 124         assertEquals(e.eval("typeof arr[2]"), "undefined");
 125     }
 126 
 127     @Test
 128     public void jsobjectTest() {
 129         final ScriptEngineManager m = new ScriptEngineManager();
 130         final ScriptEngine e = m.getEngineByName("nashorn");
 131         try {
 132             e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }");
 133             ScriptObjectMirror obj = (ScriptObjectMirror) e.get("obj");
 134 
 135             // try basic get on existing properties
 136             if (!obj.getMember("bar").equals("hello")) {
 137                 fail("obj.bar != 'hello'");
 138             }
 139 
 140             if (!obj.getSlot(1).equals("world")) {
 141                 fail("obj[1] != 'world'");
 142             }
 143 
 144             if (!obj.callMember("func", new Object[0]).equals("hello")) {
 145                 fail("obj.func() != 'hello'");
 146             }
 147 
 148             // try setting properties
 149             obj.setMember("bar", "new-bar");
 150             obj.setSlot(1, "new-element-1");
 151             if (!obj.getMember("bar").equals("new-bar")) {
 152                 fail("obj.bar != 'new-bar'");
 153             }
 154 
 155             if (!obj.getSlot(1).equals("new-element-1")) {
 156                 fail("obj[1] != 'new-element-1'");
 157             }
 158 
 159             // try adding properties
 160             obj.setMember("prop", "prop-value");
 161             obj.setSlot(12, "element-12");
 162             if (!obj.getMember("prop").equals("prop-value")) {
 163                 fail("obj.prop != 'prop-value'");
 164             }
 165 
 166             if (!obj.getSlot(12).equals("element-12")) {
 167                 fail("obj[12] != 'element-12'");
 168             }
 169 
 170             // delete properties
 171             obj.removeMember("prop");
 172             if ("prop-value".equals(obj.getMember("prop"))) {
 173                 fail("obj.prop is not deleted!");
 174             }
 175 
 176             // Simple eval tests
 177             assertEquals(obj.eval("typeof Object"), "function");
 178             assertEquals(obj.eval("'nashorn'.substring(3)"), "horn");
 179         } catch (final Exception exp) {
 180             exp.printStackTrace();
 181             fail(exp.getMessage());
 182         }
 183     }
 184 
 185     @Test
 186     public void scriptObjectMirrorToStringTest() {
 187         final ScriptEngineManager m = new ScriptEngineManager();
 188         final ScriptEngine e = m.getEngineByName("nashorn");
 189         try {
 190             Object obj = e.eval("new TypeError('wrong type')");
 191             assertEquals(obj.toString(), "TypeError: wrong type", "toString returns wrong value");
 192         } catch (final Throwable t) {
 193             t.printStackTrace();
 194             fail(t.getMessage());
 195         }
 196 
 197         try {
 198             Object obj = e.eval("function func() { print('hello'); }");
 199             assertEquals(obj.toString(), "function func() { print('hello'); }", "toString returns wrong value");
 200         } catch (final Throwable t) {
 201             t.printStackTrace();
 202             fail(t.getMessage());
 203         }
 204     }
 205 
 206     @Test
 207     public void mirrorNewObjectGlobalFunctionTest() throws ScriptException {
 208         final ScriptEngineManager m = new ScriptEngineManager();
 209         final ScriptEngine e = m.getEngineByName("nashorn");
 210         final ScriptEngine e2 = m.getEngineByName("nashorn");
 211 
 212         e.eval("function func() {}");
 213         e2.put("foo", e.get("func"));
 214         final ScriptObjectMirror e2global = (ScriptObjectMirror)e2.eval("this");
 215         final Object newObj = ((ScriptObjectMirror)e2global.getMember("foo")).newObject();
 216         assertTrue(newObj instanceof ScriptObjectMirror);
 217     }
 218 
 219     @Test
 220     public void mirrorNewObjectInstanceFunctionTest() throws ScriptException {
 221         final ScriptEngineManager m = new ScriptEngineManager();
 222         final ScriptEngine e = m.getEngineByName("nashorn");
 223         final ScriptEngine e2 = m.getEngineByName("nashorn");
 224 
 225         e.eval("function func() {}");
 226         e2.put("func", e.get("func"));
 227         final ScriptObjectMirror e2obj = (ScriptObjectMirror)e2.eval("({ foo: func })");
 228         final Object newObj = ((ScriptObjectMirror)e2obj.getMember("foo")).newObject();
 229         assertTrue(newObj instanceof ScriptObjectMirror);
 230     }
 231 
 232     @Test
 233     public void conversionTest() throws ScriptException {
 234         final ScriptEngineManager m = new ScriptEngineManager();
 235         final ScriptEngine e = m.getEngineByName("nashorn");
 236         final ScriptObjectMirror arr = (ScriptObjectMirror)e.eval("[33, 45, 23]");
 237         final int[] intArr = arr.to(int[].class);
 238         assertEquals(intArr[0], 33);
 239         assertEquals(intArr[1], 45);
 240         assertEquals(intArr[2], 23);
 241 
 242         final List<?> list = arr.to(List.class);
 243         assertEquals(list.get(0), 33);
 244         assertEquals(list.get(1), 45);
 245         assertEquals(list.get(2), 23);
 246 
 247         ScriptObjectMirror obj = (ScriptObjectMirror)e.eval(
 248             "({ valueOf: function() { return 42 } })");
 249         assertEquals(Double.valueOf(42.0), obj.to(Double.class));
 250 
 251         obj = (ScriptObjectMirror)e.eval(
 252             "({ toString: function() { return 'foo' } })");
 253         assertEquals("foo", obj.to(String.class));
 254     }
 255 }