blob: 809a91df22efa7fdbcb1f7f95ce8e0aaf9517413 [file] [log] [blame]
/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/**********************
* *
* DO NOT FORMAT *
* *
**********************/
package com.google.gwt.dev.jjs.test;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.junit.client.GWTTestCase;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//CHECKSTYLE_NAMING_OFF
/**
* TODO: document me.
*/
public class HostedTest extends GWTTestCase {
/**
* Tests that we can use a source level name for a nested type instead of the
* binary name.
*/
protected static class A {
/**
* TODO: document me.
*/
public static class B {
int b = 1;
public native int getUsingBinaryRef() /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest$A$B::b;
}-*/;
public native int getUsingSourceRef() /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest.A.B::b;
}-*/;
}
}
private static class GenericListTest extends AbstractList<Object> {
@Override
public Object get(int index) {
return this;
}
@Override
public int size() {
return 42;
}
}
private static class TestCovariantChild extends TestCovariantSuper {
@Override
public native String foo(String val) /*-{
return val;
}-*/;
}
private static class TestCovariantSuper {
public native Object foo(String val) /*-{
return val;
}-*/;
}
private static enum TestEnum {
VAL1, VAL2, VAL3
}
static String sFoo(String s) {
return s + "foo";
}
private native static JavaScriptObject getBoxedBooleanAsObject(boolean v) /*-{
return new Boolean(v);
}-*/;
private native static JavaScriptObject getBoxedNumberAsObject(double v) /*-{
return new Number(v);
}-*/;
private native static JavaScriptObject getBoxedStringAsObject(String v) /*-{
return new String(v);
}-*/;
private native static String getBoxedStringAsString(String v) /*-{
return new String(v);
}-*/;
private native static double getDouble(double v) /*-{
return -v;
}-*/;
private static native float getFloat() /*-{
return myFloatValue;
}-*/;
private static native float getFloatString() /*-{
return Number(myFloatValue.toString());
}-*/;
private native static int getInt(int v) /*-{
return -v;
}-*/;
// this should cause an exception
private static native Object getIntAsObject() /*-{
return 5;
}-*/;
private native static String getJSOAsString(JavaScriptObject jso) /*-{
return "" + jso;
}-*/;
private native static Object getObject(Object o) /*-{
return o;
}-*/;
private static native JavaScriptObject getsFooFunc() /*-{
return @com.google.gwt.dev.jjs.test.HostedTest::sFoo(Ljava/lang/String;);
}-*/;
private native static String getString(String s) /*-{
return s + "me";
}-*/;
// ok to return JS string from an Object method
private static native Object getStringAsObject() /*-{
return "test";
}-*/;
private native static int getStringLength(String s) /*-{
return s.length;
}-*/;
private static native int passThroughInt(int val) /*-{
return val;
}-*/;
private static native String sFooCall(String s) /*-{
var func = @com.google.gwt.dev.jjs.test.HostedTest::sFoo(Ljava/lang/String;);
return func.call(null, s);
}-*/;
private static native String sFooDirect(String s) /*-{
return @com.google.gwt.dev.jjs.test.HostedTest::sFoo(Ljava/lang/String;)(s);
}-*/;
private static native String sFooFuncAsStr() /*-{
var f = @com.google.gwt.dev.jjs.test.HostedTest::sFoo(Ljava/lang/String;);
return "" + f;
}-*/;
private static native String sFooFuncToString() /*-{
var f = @com.google.gwt.dev.jjs.test.HostedTest::sFoo(Ljava/lang/String;);
return f.toString();
}-*/;
private static native String sFooInvoke(String s) /*-{
var func = @com.google.gwt.dev.jjs.test.HostedTest::sFoo(Ljava/lang/String;);
return func(s);
}-*/;
private static native String sFooRoundTrip(JavaScriptObject fooFunc, String s) /*-{
return fooFunc(s);
}-*/;
private static native void storeFloat(float f) /*-{
myFloatValue = f;
}-*/;
@Override
public String getModuleName() {
return "com.google.gwt.dev.jjs.CompilerSuite";
}
public void test32BitInt() {
assertEquals(Integer.MAX_VALUE, passThroughInt(Integer.MAX_VALUE));
assertEquals(Integer.MIN_VALUE, passThroughInt(Integer.MIN_VALUE));
}
/*
* Test that returning JavaScript boxed primitives works as expected.
* Note that Boolean and Number cannot be supported properly in web
* mode, so we do not support it in hosted mode and therefore do not
* test it here.
*/
public void testAutoBoxing() {
JavaScriptObject bvo = getBoxedBooleanAsObject(true);
assertEquals(getJSOAsString(bvo), "true");
JavaScriptObject nvo = getBoxedNumberAsObject(42);
assertEquals(getJSOAsString(nvo), "42");
JavaScriptObject svo = getBoxedStringAsObject("test");
assertEquals(getJSOAsString(svo), "test");
String sv = getBoxedStringAsString("test");
assertEquals(sv, "test");
}
public void testBasic() {
int iv = getInt(14);
assertEquals(iv, -14);
double dv = getDouble(31.5);
assertEquals(dv, -31.5, 0.0);
String sv = getString("test");
assertEquals(sv, "testme");
Object oin = String.class;
Object oout = getObject(oin);
assertEquals(oin, oout);
}
public void testByteMarshalling() {
byte b = 100;
assertEquals(100, byteAsInt(b));
b = -125;
assertEquals(-125, byteAsInt(b));
}
public void testCovariant() {
TestCovariantSuper parent = new TestCovariantSuper();
TestCovariantChild child = new TestCovariantChild();
Object val1 = parent.foo("bar");
assertTrue(val1 instanceof String);
assertEquals("bar", val1);
String val2 = child.foo("bar");
assertEquals("bar", val2);
}
public void testEmbeddedNullsInStrings() {
String s = "Pre\u0000Post";
assertEquals(s.length(), getStringLength(s));
assertEquals(s + "me", getString(s));
}
public void testEnum() {
TestEnum val = enumSimple(TestEnum.VAL2);
assertEquals(TestEnum.VAL2, val);
int ord = enumValue(val);
assertEquals(TestEnum.VAL2.ordinal(), ord);
String name = enumName(val);
assertEquals(TestEnum.VAL2.name(), name);
}
public void testFloat() {
storeFloat(Float.MIN_VALUE);
float f = getFloat();
assertTrue(f == Float.MIN_VALUE);
f = getFloatString();
assertTrue(f == Float.MIN_VALUE);
storeFloat(Float.MAX_VALUE);
f = getFloat();
assertTrue(f == Float.MAX_VALUE);
f = getFloatString();
assertTrue(f == Float.MAX_VALUE);
}
public void testFunctionCaching() {
assertEquals("barfoo", sFooCall("bar"));
assertEquals("barfoo", sFooDirect("bar"));
assertEquals("barfoo", sFooInvoke("bar"));
assertEquals("barfoo", sFooRoundTrip(getsFooFunc(), "bar"));
assertEquals("barfoo", fooCall("bar"));
assertEquals("barfoo", fooDirect("bar"));
assertEquals("barfoo", fooRoundTrip(getFooFunc(), "bar"));
String sFooString = getsFooFunc().toString();
assertEquals(sFooString, sFooFuncAsStr());
assertEquals(sFooString, sFooFuncToString());
String fooString = getFooFunc().toString();
assertEquals(fooString, fooFuncAsStr());
assertEquals(fooString, fooFuncToString());
}
public void testGenerics() {
String s = genericSimple("test");
assertEquals("test", s);
String v = genericGet(s);
assertEquals("test", v);
List<String> list = new ArrayList<String>();
list.add("foo");
Object obj = genericWildcard(list);
assertTrue(obj instanceof String);
assertEquals("foo", obj);
obj = genericSubtype("test");
List<Object> list2 = genericSubtype(new GenericListTest());
assertTrue(list2 instanceof GenericListTest);
assertEquals(42, list2.size());
assertEquals(list2, list2.get(0));
String[] array = new String[] { "foo", "bar" };
String[] ret = genericArray(array);
assertEquals(2, ret.length);
assertEquals("bar", ret[1]);
assertTrue(Arrays.deepEquals(array, ret));
}
/**
* Tests that we are able to use binary and source level names when referencing
* a Java identifier from JSNI.
*/
public void testJavaMemberRefResolution() {
A.B b = new A.B();
assertEquals(1, b.getUsingSourceRef());
assertEquals(1, b.getUsingBinaryRef());
}
public void testJsniFormats() {
jsniA();
jsniB();
jsniC();
jsniD();
jsniE();
jsniF();
jsniG();
jsniH();
jsniI();
jsniJ();
jsniK();
jsniL();
}
/**
* Tests that using the JavaScript toString method results in a call to
* the java.lang.Object::toString() method.
*
*/
public void testJSNIToStringResolution() {
class Foo {
@Override
public String toString() {
return "FOO";
}
}
assertEquals("FOO", callJSNIToString(new Foo()));
}
public void testLocalJsni() {
class Foo {
native String a() /*-{
return "blah";
}-*/;
native String b() /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest$2Foo::a()();
}-*/;
String c() {
return a();
}
}
Foo f = new Foo();
assertEquals(f.a(), "blah");
assertEquals(f.b(), "blah");
assertEquals(f.c(), "blah");
Foo fo = new Foo() {
@Override
native String a() /*-{
return "oblah";
}-*/;
@Override
native String b() /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest$2Foo::a()();
}-*/;
@Override
native String c() /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest$1::a()();
}-*/;
};
assertEquals(fo.a(), "oblah");
assertEquals(fo.b(), "oblah");
assertEquals(fo.c(), "oblah");
}
public void testLongMarshalling() {
// a big number that cannot accurately be represented as a double
long l = 1234567890123456789L;
double d = l;
assertTrue(isEq(l, d));
}
/*
* Test that returning strings from methods declared as returning Object
* works, and that returning a primitive does not.
*/
public void testObjectReturns() {
String str = (String)getStringAsObject();
assertEquals(str, "test");
try {
getIntAsObject();
// should have thrown an exception in hosted mode,
// so fail unless we are in web mode
assertTrue(GWT.isScript());
} catch (IllegalArgumentException e) {
// expected exception
}
}
public void testVarargs() {
String[] strs = varargsHelper("foo", "bar");
assertEquals(2, strs.length);
assertEquals("bar", strs[1]);
// TODO: not sure if we want to support this or not.
// strs = varargsFromJS1();
// assertEquals(2, strs.length);
// assertEquals("bar", strs[1]);
strs = varargsFromJS2(strs);
assertEquals(2, strs.length);
assertEquals("bar", strs[1]);
}
String foo(String s) {
return s + "foo";
}
private native int byteAsInt(byte b) /*-{
return b;
}-*/;
private native String callJSNIToString(Object obj) /*-{
return obj.toString();
}-*/;
private native String enumName(TestEnum val) /*-{
return val.@com.google.gwt.dev.jjs.test.HostedTest.TestEnum::name()();
}-*/;
private native TestEnum enumSimple(TestEnum val) /*-{
return val;
}-*/;
private native int enumValue(TestEnum val) /*-{
return val.@com.google.gwt.dev.jjs.test.HostedTest.TestEnum::ordinal()();
}-*/;
private native String fooCall(String s) /*-{
var f = this.@com.google.gwt.dev.jjs.test.HostedTest::foo(Ljava/lang/String;);
return f.call(this, s);
}-*/;
private native String fooDirect(String s) /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest::foo(Ljava/lang/String;)(s);
}-*/;
private native String fooFuncAsStr() /*-{
var f = this.@com.google.gwt.dev.jjs.test.HostedTest::foo(Ljava/lang/String;);
return "" + f;
}-*/;
private native String fooFuncToString() /*-{
var f = this.@com.google.gwt.dev.jjs.test.HostedTest::foo(Ljava/lang/String;);
return f.toString();
}-*/;
private native String fooRoundTrip(JavaScriptObject fooFunc, String s) /*-{
return fooFunc.call(this, s);
}-*/;
// Make this a JSNI method calling the Java method when that is implemented.
private native <T> T[] genericArray(T[] array) /*-{
// return genericPassthrough(array);
return this.@com.google.gwt.dev.jjs.test.HostedTest::genericPassthrough([Ljava/lang/Object;)(array);
}-*/;
/*
* Since we can't generate a generic instance from within JS, K and V
* have to actually be compatible.
*/
private native <K,V> V genericGet(K key) /*-{
return key;
}-*/;
@SuppressWarnings("unused") // called by JSNI
private <T> T[] genericPassthrough(T[] array) {
return array;
}
// generics helper methods
private native <T> T genericSimple(T val) /*-{
return val;
}-*/;
private native <T,U extends T> T genericSubtype(U val) /*-{
return val;
}-*/;
private native Object genericWildcard(List<?> list) /*-{
return list.@java.util.List::get(I)(0);
}-*/;
private native JavaScriptObject getFooFunc() /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest::foo(Ljava/lang/String;);
}-*/;
private native boolean isEq(long l, double d) /*-{
return l == d;
}-*/;
private native void jsniA()/*-{}-*/;
private native void jsniB()/*-{
}-*/;
private native void jsniC()
/*-{
}-*/;
private native void jsniD()
/*-{}-*/;
/**
* comment.
*/
private native void jsniE()/*-{}-*/;
/** comment. */
private native void jsniF()/*-{}-*/;
/** comment */private native void jsniG()/*-{}-*/;
/*
* comment
*/
private native void jsniH()/*-{}-*/;
/* comment */private native void jsniI()/*-{}-*/;
// comment
private native void jsniJ()/*-{}-*/;
private
native
void
jsniK()
/*-{
}-*/;
/*-{ try to mess with compiler }-*/
private native void jsniL()/*-{}-*/ ;
// test that JS can pass a series of arguments to a varargs function
private native String[] varargsFromJS1() /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest::varargsPassthrough([Ljava/lang/String;)("foo", "bar");
}-*/;
// test that JS can pass a Java-created array to a varargs function
private native String[] varargsFromJS2(String[] arr) /*-{
return this.@com.google.gwt.dev.jjs.test.HostedTest::varargsPassthrough([Ljava/lang/String;)(arr);
}-*/;
private native String[] varargsHelper(String... args) /*-{
return args;
}-*/;
@SuppressWarnings("unused") // called from JSNI
private String[] varargsPassthrough(String... args) {
return args;
}
}