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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * Tests for conversion of JavaScript arrays to Java arrays and the other
  26  * way round. Also generally useful as a JavaScript-to-Java type conversion
  27  * test.
  28  *
  29  * @test
  30  * @run
  31  */
  32 
  33 var x; // used for undefined
  34 var testCount = 0;
  35 
  36 function testF(inputValue, type, testFn) {
  37   var x = Java.to([inputValue], type + "[]")[0];
  38   if(!testFn(x)) {
  39     throw ("unexpected value: " + x)
  40   }
  41   ++testCount;
  42 }
  43 
  44 function test(inputValue, type, expectedValue) {
  45   testF(inputValue, type, function(x) { return x === expectedValue })
  46 }
  47 
  48 function testNaN(inputValue, type) {
  49   testF(inputValue, type, isNaN)
  50 }
  51 
  52 // Those labeled "Correct?" are not clearly correct conversions. Those
  53 // labeled "TypeError maybe?" could actually throw a TypeError, or only
  54 // throw a TypeError when in strict mode.
  55 // The case of ("false", "boolean") => true is particularly amusing.
  56 
  57 test(x, "int", 0) // Correct? TypeError maybe?
  58 test(null, "int", 0) // Correct? TypeError maybe?
  59 test(1234, "int", 1234)
  60 test("1234", "int", 1234)
  61 test("1234.49", "int", 1234)
  62 test("1234.51", "int", 1234) // truncates, not rounds
  63 test(true, "int", 1)
  64 test(false, "int", 0)
  65 test("foo", "int", 0) // Correct? TypeError maybe?
  66 
  67 test(x, "boolean", false) // Correct? TypeError maybe?
  68 test(null, "boolean", false) // Correct? TypeError maybe?
  69 test(0, "boolean", false)
  70 test(1234, "boolean", true)
  71 test("foo", "boolean", true)
  72 test("", "boolean", false)
  73 test("false", "boolean", true) // Correct? false maybe?
  74 
  75 test(x, "java.lang.String", "undefined") // Correct? TypeError maybe?
  76 test(null, "java.lang.String", null)
  77 test(1234, "java.lang.String", "1234")
  78 test(1234.5, "java.lang.String", "1234.5")
  79 test(true, "java.lang.String", "true")
  80 test(false, "java.lang.String", "false")
  81 
  82 test(x, "java.lang.Integer", null) // Correct? TypeError maybe?
  83 test(null, "java.lang.Integer", null)
  84 test(1234, "java.lang.Integer", 1234)
  85 test("1234", "java.lang.Integer", 1234)
  86 test("1234.49", "java.lang.Integer", 1234)
  87 test("1234.51", "java.lang.Integer", 1234) // truncates, not rounds
  88 test(true, "java.lang.Integer", 1)
  89 test(false, "java.lang.Integer", 0)
  90 test("foo", "java.lang.Integer", 0) // Correct? TypeError maybe?
  91 
  92 test(x, "java.lang.Boolean", null) // Correct? TypeError maybe?
  93 test(null, "java.lang.Boolean", null)
  94 test(0, "java.lang.Boolean", false)
  95 test(1234, "java.lang.Boolean", true)
  96 test("foo", "java.lang.Boolean", true)
  97 test("", "java.lang.Boolean", false)
  98 test("false", "java.lang.Boolean", true) // Correct? false maybe?
  99 
 100 testNaN(x, "double")
 101 test(null, "double", 0)
 102 test(1234, "double", 1234)
 103 test("1234", "double", 1234)
 104 test("1234.5", "double", 1234.5)
 105 test(true, "double", 1)
 106 test(false, "double", 0)
 107 testNaN("foo", "double")
 108 
 109 testNaN(x, "java.lang.Double")
 110 test(null, "java.lang.Double", null)
 111 test(1234, "java.lang.Double", 1234)
 112 test("1234", "java.lang.Double", 1234)
 113 test("1234.5", "java.lang.Double", 1234.5)
 114 test(true, "java.lang.Double", 1)
 115 test(false, "java.lang.Double", 0)
 116 testNaN("foo", "java.lang.Double")
 117 
 118 test({ valueOf: function() { return 42; } }, "int", 42)
 119 test({ valueOf: function() { return "42"; } }, "int", 42)
 120 // If there's no valueOf, toString is used
 121 test({ toString: function() { return "42"; } }, "int", 42)
 122 // For numbers, valueOf takes precedence over toString
 123 test({ valueOf: function() { return "42"; },  toString: function() { return "43"; } }, "int", 42)
 124 
 125 test({ toString: function() { return "foo"; } }, "java.lang.String", "foo")
 126 // Yep, even if we have valueOf, toString from prototype takes precedence
 127 test({ valueOf: function() { return 42; } }, "java.lang.String", "[object Object]")
 128 // Converting to string, toString takes precedence over valueOf
 129 test({ valueOf: function() { return "42"; },  toString: function() { return "43"; } }, "java.lang.String", "43")
 130 
 131 function assertCanConvert(sourceType, targetType) {
 132   Java.to([new (Java.type(sourceType))()], targetType + "[]")
 133   ++testCount;
 134 }
 135 
 136 function assertCantConvert(sourceType, targetType) {
 137   try {
 138     Java.to([new (Java.type(sourceType))()], targetType + "[]")
 139     throw "no TypeError encountered"
 140   } catch(e) {
 141       if(!(e instanceof TypeError) ||
 142           !e.message.startsWith("Java.to conversion to array type")) {
 143         throw e;
 144       }
 145       ++testCount;
 146   }
 147 }
 148 
 149 // Arbitrary POJOs to JS Primitive type should work
 150 assertCanConvert("java.util.BitSet", "int")
 151 assertCanConvert("java.util.BitSet", "double")
 152 assertCanConvert("java.util.BitSet", "long")
 153 assertCanConvert("java.util.BitSet", "boolean")
 154 assertCanConvert("java.util.BitSet", "java.lang.String")
 155 
 156 // Arbitrary POJOs can't be converted to Java values
 157 assertCantConvert("java.util.BitSet", "java.lang.Double")
 158 assertCantConvert("java.util.BitSet", "java.lang.Long")
 159 
 160 /***************************************************************************
 161  * Now testing the other way round - Java arrays & collections to JavaScript
 162  **************************************************************************/
 163 
 164 function assert(x) {
 165   if(!x) {
 166     throw "Assertion failed"
 167   }
 168   ++testCount;
 169 }
 170 
 171 var intArray = new (Java.type("int[]"))(3)
 172 intArray[0] = 1234;
 173 intArray[1] = 42;
 174 intArray[2] = 5;
 175 var jsIntArray = Java.from(intArray)
 176 assert(jsIntArray instanceof Array);
 177 assert(jsIntArray[0] === 1234);
 178 assert(jsIntArray[1] === 42);
 179 assert(jsIntArray[2] === 5);
 180 
 181 // The arrays are copies, they don't reflect each other
 182 intArray[2] = 6;
 183 assert(jsIntArray[2] === 5);
 184 jsIntArray[2] = 7;
 185 assert(intArray[2] === 6);
 186 
 187 var byteArray = new (Java.type("byte[]"))(2)
 188 byteArray[0] = -128;
 189 byteArray[1] = 127;
 190 var jsByteArray = Java.from(byteArray)
 191 assert(jsByteArray instanceof Array);
 192 assert(jsByteArray[0] === -128);
 193 assert(jsByteArray[1] === 127);
 194 
 195 var shortArray = new (Java.type("short[]"))(2)
 196 shortArray[0] = -32768;
 197 shortArray[1] = 32767;
 198 var jsShortArray = Java.from(shortArray)
 199 assert(jsShortArray instanceof Array);
 200 assert(jsShortArray[0] === -32768);
 201 assert(jsShortArray[1] === 32767);
 202 
 203 var floatArray = new (Java.type("float[]"))(2)
 204 floatArray[0] = java.lang.Float.MIN_VALUE;
 205 floatArray[1] = java.lang.Float.MAX_VALUE;
 206 var jsFloatArray = Java.from(floatArray)
 207 assert(jsFloatArray instanceof Array);
 208 assert(jsFloatArray[0] == java.lang.Float.MIN_VALUE);
 209 assert(jsFloatArray[1] == java.lang.Float.MAX_VALUE);
 210 
 211 var charArray = new (Java.type("char[]"))(3)
 212 charArray[0] = "a";
 213 charArray[1] = "b";
 214 charArray[2] = "1";
 215 var jsCharArray = Java.from(charArray)
 216 assert(jsCharArray instanceof Array);
 217 assert(jsCharArray[0] === 97);
 218 assert(jsCharArray[1] === 98);
 219 assert(jsCharArray[2] === 49);
 220 
 221 var booleanArray = new (Java.type("boolean[]"))(2)
 222 booleanArray[0] = true;
 223 booleanArray[1] = false;
 224 var jsBooleanArray = Java.from(booleanArray)
 225 assert(jsBooleanArray instanceof Array);
 226 assert(jsBooleanArray[0] === true);
 227 assert(jsBooleanArray[1] === false);
 228 
 229 print(testCount + " tests completed ok")