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.javaaccess.test;
  27 
  28 import static org.testng.AssertJUnit.assertEquals;
  29 import static org.testng.AssertJUnit.assertFalse;
  30 import static org.testng.AssertJUnit.assertNull;
  31 import static org.testng.AssertJUnit.assertTrue;
  32 import java.util.Arrays;
  33 import java.util.List;
  34 import javax.script.ScriptContext;
  35 import javax.script.ScriptEngine;
  36 import javax.script.ScriptEngineManager;
  37 import javax.script.ScriptException;
  38 import org.testng.TestNG;
  39 import org.testng.annotations.AfterClass;
  40 import org.testng.annotations.BeforeClass;
  41 import org.testng.annotations.Test;
  42 
  43 /**
  44  * @test
  45  * @run testng/othervm jdk.nashorn.api.javaaccess.test.ArrayConversionTest
  46  */
  47 @SuppressWarnings("javadoc")
  48 public class ArrayConversionTest {
  49     private static ScriptEngine e = null;
  50 
  51     public static void main(final String[] args) {
  52         TestNG.main(args);
  53     }
  54 
  55     @BeforeClass
  56     public static void setUpClass() {
  57         e = new ScriptEngineManager().getEngineByName("nashorn");
  58     }
  59 
  60     @AfterClass
  61     public static void tearDownClass() {
  62         e = null;
  63     }
  64 
  65     @Test
  66     public void testIntArrays() throws ScriptException {
  67         runTest("assertNullIntArray", "null");
  68         runTest("assertEmptyIntArray", "[]");
  69         runTest("assertSingle42IntArray", "[42]");
  70         runTest("assertSingle42IntArray", "['42']");
  71         runTest("assertIntArrayConversions", "[false, true, NaN, Infinity, -Infinity, 0.4, 0.6, null, undefined, [], {}, [1], [1, 2]]");
  72     }
  73 
  74     @Test
  75     public void testIntIntArrays() throws ScriptException {
  76         runTest("assertNullIntIntArray", "null");
  77         runTest("assertEmptyIntIntArray", "[]");
  78         runTest("assertSingleEmptyIntIntArray", "[[]]");
  79         runTest("assertSingleNullIntIntArray", "[null]");
  80         runTest("assertLargeIntIntArray", "[[false], [1], [2, 3], [4, 5, 6], ['7', {valueOf: function() { return 8 }}]]");
  81     }
  82 
  83     @Test
  84     public void testObjectObjectArrays() throws ScriptException {
  85         runTest("assertLargeObjectObjectArray", "[[false], [1], ['foo', 42.3], [{x: 17}]]");
  86     }
  87 
  88     @Test
  89     public void testBooleanArrays() throws ScriptException {
  90         runTest("assertBooleanArrayConversions", "[false, true, '', 'false', 0, 1, 0.4, 0.6, {}, [], [false], [true], NaN, Infinity, null, undefined]");
  91     }
  92 
  93     @Test
  94     public void testArrayAmbiguity() throws ScriptException {
  95         runTest("x", "'abc'");
  96         runTest("x", "['foo', 'bar']");
  97     }
  98 
  99     @Test
 100     public void testListArrays() throws ScriptException {
 101         runTest("assertListArray", "[['foo', 'bar'], ['apple', 'orange']]");
 102     }
 103 
 104     @Test
 105     public void testVarArgs() throws ScriptException {
 106         // Sole NativeArray in vararg position becomes vararg array itself
 107         runTest("assertVarArgWith42And17", "[42, 17]");
 108         // NativeArray in vararg position becomes an argument if there are more arguments
 109         runTest("assertVarArgArray7", "[42], 18");
 110         // Only NativeArray is converted to vararg array, other objects (e.g. a function) aren't
 111         runTest("assertVarArgFunction", "function() { return 'Hello' }");
 112     }
 113 
 114     private static void runTest(final String testMethodName, final String argument) throws ScriptException {
 115         e.eval("Java.type('" + ArrayConversionTest.class.getName() + "')." + testMethodName + "(" + argument + ")");
 116     }
 117 
 118     public static void assertNullIntArray(final int[] array) {
 119         assertNull(array);
 120     }
 121 
 122     public static void assertNullIntIntArray(final int[][] array) {
 123         assertNull(array);
 124     }
 125 
 126     public static void assertEmptyIntArray(final int[] array) {
 127         assertEquals(0, array.length);
 128     }
 129 
 130     public static void assertSingle42IntArray(final int[] array) {
 131         assertEquals(1, array.length);
 132         assertEquals(42, array[0]);
 133     }
 134 
 135 
 136     public static void assertIntArrayConversions(final int[] array) {
 137         assertEquals(13, array.length);
 138         assertEquals(0, array[0]); // false
 139         assertEquals(1, array[1]); // true
 140         assertEquals(0, array[2]); // NaN
 141         assertEquals(0, array[3]); // Infinity
 142         assertEquals(0, array[4]); // -Infinity
 143         assertEquals(0, array[5]); // 0.4
 144         assertEquals(0, array[6]); // 0.6 - floor, not round
 145         assertEquals(0, array[7]); // null
 146         assertEquals(0, array[8]); // undefined
 147         assertEquals(0, array[9]); // []
 148         assertEquals(0, array[10]); // {}
 149         assertEquals(1, array[11]); // [1]
 150         assertEquals(0, array[12]); // [1, 2]
 151     }
 152 
 153     public static void assertEmptyIntIntArray(final int[][] array) {
 154         assertEquals(0, array.length);
 155     }
 156 
 157     public static void assertSingleEmptyIntIntArray(final int[][] array) {
 158         assertEquals(1, array.length);
 159         assertTrue(Arrays.equals(new int[0], array[0]));
 160     }
 161 
 162     public static void assertSingleNullIntIntArray(final int[][] array) {
 163         assertEquals(1, array.length);
 164         assertNull(null, array[0]);
 165     }
 166 
 167     public static void assertLargeIntIntArray(final int[][] array) {
 168         assertEquals(5, array.length);
 169         assertTrue(Arrays.equals(new int[] { 0 }, array[0]));
 170         assertTrue(Arrays.equals(new int[] { 1 }, array[1]));
 171         assertTrue(Arrays.equals(new int[] { 2, 3 }, array[2]));
 172         assertTrue(Arrays.equals(new int[] { 4, 5, 6 }, array[3]));
 173         assertTrue(Arrays.equals(new int[] { 7, 8 }, array[4]));
 174     }
 175 
 176     public static void assertLargeObjectObjectArray(final Object[][] array) throws ScriptException {
 177         assertEquals(4, array.length);
 178         assertTrue(Arrays.equals(new Object[] { Boolean.FALSE }, array[0]));
 179         assertTrue(Arrays.equals(new Object[] { 1 }, array[1]));
 180         assertTrue(Arrays.equals(new Object[] { "foo", 42.3d }, array[2]));
 181         assertEquals(1, array[3].length);
 182         e.getBindings(ScriptContext.ENGINE_SCOPE).put("obj", array[3][0]);
 183         assertEquals(17, e.eval("obj.x"));
 184     }
 185 
 186     public static void assertBooleanArrayConversions(final boolean[] array) {
 187         assertEquals(16, array.length);
 188         assertFalse(array[0]); // false
 189         assertTrue(array[1]); // true
 190         assertFalse(array[2]); // ''
 191         assertTrue(array[3]); // 'false' (yep, every non-empty string converts to true)
 192         assertFalse(array[4]); // 0
 193         assertTrue(array[5]); // 1
 194         assertTrue(array[6]); // 0.4
 195         assertTrue(array[7]); // 0.6
 196         assertTrue(array[8]); // {}
 197         assertTrue(array[9]); // []
 198         assertTrue(array[10]); // [false]
 199         assertTrue(array[11]); // [true]
 200         assertFalse(array[12]); // NaN
 201         assertTrue(array[13]); // Infinity
 202         assertFalse(array[14]); // null
 203         assertFalse(array[15]); // undefined
 204     }
 205 
 206     public static void assertListArray(final List<?>[] array) {
 207         assertEquals(2, array.length);
 208         assertEquals(Arrays.asList("foo", "bar"), array[0]);
 209         assertEquals(Arrays.asList("apple", "orange"), array[1]);
 210     }
 211 
 212     public static void assertVarArgWith42And17(final Object... args) {
 213         assertEquals(2, args.length);
 214         assertEquals(42, ((Number)args[0]).intValue());
 215         assertEquals(17, ((Number)args[1]).intValue());
 216     }
 217 
 218     public static void assertVarArgArray7(final Object... args) throws ScriptException {
 219         assertEquals(2, args.length);
 220         e.getBindings(ScriptContext.ENGINE_SCOPE).put("arr", args[0]);
 221         assertTrue((Boolean)e.eval("arr instanceof Array && arr.length == 1 && arr[0] == 42"));
 222         assertEquals(18, ((Number)args[1]).intValue());
 223     }
 224 
 225     public static void assertVarArgFunction(final Object... args) throws ScriptException {
 226         assertEquals(1, args.length);
 227         e.getBindings(ScriptContext.ENGINE_SCOPE).put("fn", args[0]);
 228         assertEquals("Hello", e.eval("fn()"));
 229     }
 230 
 231 
 232 
 233     public static void x(final String y) {
 234         assertEquals("abc", y);
 235     }
 236     public static void x(final String[] y) {
 237         assertTrue(Arrays.equals(new String[] { "foo", "bar"}, y));
 238     }
 239 }