aoqi@0: /* aoqi@0: * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. attila@962: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. attila@962: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). attila@962: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. attila@962: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /** aoqi@0: * Tests for conversion of JavaScript arrays to Java arrays and the other attila@962: * way round. Also generally useful as a JavaScript-to-Java type conversion aoqi@0: * test. aoqi@0: * aoqi@0: * @test aoqi@0: * @run aoqi@0: */ aoqi@0: aoqi@0: var x; // used for undefined aoqi@0: var testCount = 0; aoqi@0: aoqi@0: function testF(inputValue, type, testFn) { aoqi@0: var x = Java.to([inputValue], type + "[]")[0]; aoqi@0: if(!testFn(x)) { aoqi@0: throw ("unexpected value: " + x) aoqi@0: } aoqi@0: ++testCount; aoqi@0: } aoqi@0: aoqi@0: function test(inputValue, type, expectedValue) { aoqi@0: testF(inputValue, type, function(x) { return x === expectedValue }) aoqi@0: } aoqi@0: aoqi@0: function testNaN(inputValue, type) { aoqi@0: testF(inputValue, type, isNaN) aoqi@0: } aoqi@0: attila@962: // Those labeled "Correct?" are not clearly correct conversions. Those attila@962: // labeled "TypeError maybe?" could actually throw a TypeError, or only attila@962: // throw a TypeError when in strict mode. aoqi@0: // The case of ("false", "boolean") => true is particularly amusing. aoqi@0: aoqi@0: test(x, "int", 0) // Correct? TypeError maybe? aoqi@0: test(null, "int", 0) // Correct? TypeError maybe? aoqi@0: test(1234, "int", 1234) aoqi@0: test("1234", "int", 1234) aoqi@0: test("1234.49", "int", 1234) aoqi@0: test("1234.51", "int", 1234) // truncates, not rounds aoqi@0: test(true, "int", 1) aoqi@0: test(false, "int", 0) aoqi@0: test("foo", "int", 0) // Correct? TypeError maybe? aoqi@0: aoqi@0: test(x, "boolean", false) // Correct? TypeError maybe? aoqi@0: test(null, "boolean", false) // Correct? TypeError maybe? aoqi@0: test(0, "boolean", false) aoqi@0: test(1234, "boolean", true) aoqi@0: test("foo", "boolean", true) aoqi@0: test("", "boolean", false) aoqi@0: test("false", "boolean", true) // Correct? false maybe? aoqi@0: aoqi@0: test(x, "java.lang.String", "undefined") // Correct? TypeError maybe? aoqi@0: test(null, "java.lang.String", null) aoqi@0: test(1234, "java.lang.String", "1234") aoqi@0: test(1234.5, "java.lang.String", "1234.5") aoqi@0: test(true, "java.lang.String", "true") aoqi@0: test(false, "java.lang.String", "false") aoqi@0: aoqi@0: test(x, "java.lang.Integer", null) // Correct? TypeError maybe? aoqi@0: test(null, "java.lang.Integer", null) aoqi@0: test(1234, "java.lang.Integer", 1234) aoqi@0: test("1234", "java.lang.Integer", 1234) aoqi@0: test("1234.49", "java.lang.Integer", 1234) aoqi@0: test("1234.51", "java.lang.Integer", 1234) // truncates, not rounds aoqi@0: test(true, "java.lang.Integer", 1) aoqi@0: test(false, "java.lang.Integer", 0) aoqi@0: test("foo", "java.lang.Integer", 0) // Correct? TypeError maybe? aoqi@0: aoqi@0: test(x, "java.lang.Boolean", null) // Correct? TypeError maybe? aoqi@0: test(null, "java.lang.Boolean", null) aoqi@0: test(0, "java.lang.Boolean", false) aoqi@0: test(1234, "java.lang.Boolean", true) aoqi@0: test("foo", "java.lang.Boolean", true) aoqi@0: test("", "java.lang.Boolean", false) aoqi@0: test("false", "java.lang.Boolean", true) // Correct? false maybe? aoqi@0: aoqi@0: testNaN(x, "double") aoqi@0: test(null, "double", 0) aoqi@0: test(1234, "double", 1234) aoqi@0: test("1234", "double", 1234) aoqi@0: test("1234.5", "double", 1234.5) aoqi@0: test(true, "double", 1) aoqi@0: test(false, "double", 0) aoqi@0: testNaN("foo", "double") aoqi@0: aoqi@0: testNaN(x, "java.lang.Double") aoqi@0: test(null, "java.lang.Double", null) aoqi@0: test(1234, "java.lang.Double", 1234) aoqi@0: test("1234", "java.lang.Double", 1234) aoqi@0: test("1234.5", "java.lang.Double", 1234.5) aoqi@0: test(true, "java.lang.Double", 1) aoqi@0: test(false, "java.lang.Double", 0) aoqi@0: testNaN("foo", "java.lang.Double") aoqi@0: aoqi@0: test({ valueOf: function() { return 42; } }, "int", 42) aoqi@0: test({ valueOf: function() { return "42"; } }, "int", 42) aoqi@0: // If there's no valueOf, toString is used aoqi@0: test({ toString: function() { return "42"; } }, "int", 42) aoqi@0: // For numbers, valueOf takes precedence over toString aoqi@0: test({ valueOf: function() { return "42"; }, toString: function() { return "43"; } }, "int", 42) aoqi@0: aoqi@0: test({ toString: function() { return "foo"; } }, "java.lang.String", "foo") aoqi@0: // Yep, even if we have valueOf, toString from prototype takes precedence aoqi@0: test({ valueOf: function() { return 42; } }, "java.lang.String", "[object Object]") aoqi@0: // Converting to string, toString takes precedence over valueOf aoqi@0: test({ valueOf: function() { return "42"; }, toString: function() { return "43"; } }, "java.lang.String", "43") aoqi@0: sundar@1533: function assertCanConvert(sourceType, targetType) { sundar@1533: Java.to([new (Java.type(sourceType))()], targetType + "[]") sundar@1533: ++testCount; sundar@1533: } sundar@1533: aoqi@0: function assertCantConvert(sourceType, targetType) { aoqi@0: try { sundar@1533: Java.to([new (Java.type(sourceType))()], targetType + "[]") aoqi@0: throw "no TypeError encountered" aoqi@0: } catch(e) { sundar@1533: if(!(e instanceof TypeError) || sundar@1533: !e.message.startsWith("Java.to conversion to array type")) { aoqi@0: throw e; aoqi@0: } aoqi@0: ++testCount; aoqi@0: } aoqi@0: } aoqi@0: sundar@1533: // Arbitrary POJOs to JS Primitive type should work sundar@1533: assertCanConvert("java.util.BitSet", "int") sundar@1533: assertCanConvert("java.util.BitSet", "double") sundar@1533: assertCanConvert("java.util.BitSet", "long") sundar@1533: assertCanConvert("java.util.BitSet", "boolean") sundar@1533: assertCanConvert("java.util.BitSet", "java.lang.String") sundar@1533: aoqi@0: // Arbitrary POJOs can't be converted to Java values aoqi@0: assertCantConvert("java.util.BitSet", "java.lang.Double") aoqi@0: assertCantConvert("java.util.BitSet", "java.lang.Long") aoqi@0: aoqi@0: /*************************************************************************** aoqi@0: * Now testing the other way round - Java arrays & collections to JavaScript aoqi@0: **************************************************************************/ aoqi@0: aoqi@0: function assert(x) { aoqi@0: if(!x) { aoqi@0: throw "Assertion failed" aoqi@0: } aoqi@0: ++testCount; aoqi@0: } aoqi@0: aoqi@0: var intArray = new (Java.type("int[]"))(3) aoqi@0: intArray[0] = 1234; aoqi@0: intArray[1] = 42; aoqi@0: intArray[2] = 5; aoqi@0: var jsIntArray = Java.from(intArray) aoqi@0: assert(jsIntArray instanceof Array); aoqi@0: assert(jsIntArray[0] === 1234); aoqi@0: assert(jsIntArray[1] === 42); aoqi@0: assert(jsIntArray[2] === 5); aoqi@0: aoqi@0: // The arrays are copies, they don't reflect each other aoqi@0: intArray[2] = 6; aoqi@0: assert(jsIntArray[2] === 5); aoqi@0: jsIntArray[2] = 7; aoqi@0: assert(intArray[2] === 6); aoqi@0: aoqi@0: var byteArray = new (Java.type("byte[]"))(2) aoqi@0: byteArray[0] = -128; aoqi@0: byteArray[1] = 127; aoqi@0: var jsByteArray = Java.from(byteArray) aoqi@0: assert(jsByteArray instanceof Array); aoqi@0: assert(jsByteArray[0] === -128); aoqi@0: assert(jsByteArray[1] === 127); aoqi@0: aoqi@0: var shortArray = new (Java.type("short[]"))(2) aoqi@0: shortArray[0] = -32768; aoqi@0: shortArray[1] = 32767; aoqi@0: var jsShortArray = Java.from(shortArray) aoqi@0: assert(jsShortArray instanceof Array); aoqi@0: assert(jsShortArray[0] === -32768); aoqi@0: assert(jsShortArray[1] === 32767); aoqi@0: aoqi@0: var floatArray = new (Java.type("float[]"))(2) aoqi@0: floatArray[0] = java.lang.Float.MIN_VALUE; aoqi@0: floatArray[1] = java.lang.Float.MAX_VALUE; aoqi@0: var jsFloatArray = Java.from(floatArray) aoqi@0: assert(jsFloatArray instanceof Array); aoqi@0: assert(jsFloatArray[0] == java.lang.Float.MIN_VALUE); aoqi@0: assert(jsFloatArray[1] == java.lang.Float.MAX_VALUE); aoqi@0: aoqi@0: var charArray = new (Java.type("char[]"))(3) aoqi@0: charArray[0] = "a"; aoqi@0: charArray[1] = "b"; aoqi@0: charArray[2] = "1"; aoqi@0: var jsCharArray = Java.from(charArray) aoqi@0: assert(jsCharArray instanceof Array); aoqi@0: assert(jsCharArray[0] === 97); aoqi@0: assert(jsCharArray[1] === 98); aoqi@0: assert(jsCharArray[2] === 49); aoqi@0: aoqi@0: var booleanArray = new (Java.type("boolean[]"))(2) aoqi@0: booleanArray[0] = true; aoqi@0: booleanArray[1] = false; aoqi@0: var jsBooleanArray = Java.from(booleanArray) aoqi@0: assert(jsBooleanArray instanceof Array); aoqi@0: assert(jsBooleanArray[0] === true); aoqi@0: assert(jsBooleanArray[1] === false); aoqi@0: aoqi@0: print(testCount + " tests completed ok")