blob: afee926e11b7a69c818d11f43e0c10b3024933a7 [file] [log] [blame]
/*
* Copyright 2008 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.
*/
package com.google.gwt.dev.shell.rewrite.client;
import com.google.gwt.junit.client.GWTTestCase;
import junit.framework.TestCase;
/**
* Test-case to check if the jsni blocks are mapped correctly between the
* synthetic and anonymous classes generated by the javac and the jdt compiler.
* <p>
* This issue arises when emma.jar is in the classpath. Gwt then follows the
* emma strategy and loads (offline-instrumented) classes from the disk. These
* classes could have been generated by any java compiler -- the java compiler
* does not have to be jdt and frequently is javac. These class files may
* contain references to synthetic classes and anonymous classes that the jdt
* does not know about. This testcase checks that gwt handles these cases
* correctly.
*/
public class EmmaClassLoadingTest extends GWTTestCase {
enum EnumClass {
A, B, C,
}
interface TestInterface {
void foo();
}
private static String messages[] = {
"1a foo", "1b foo", "1enum A", "1d foo", "1e foo"};
private static int logCount = 0;
private static void log(String msg) {
assertEquals(messages[logCount++], msg);
}
@Override
public String getModuleName() {
return "com.google.gwt.dev.shell.rewrite.EmmaClassLoadingTest";
}
public void test1() {
TestInterface a = new TestInterface() {
@Override
public void foo() {
log("1a foo");
}
};
a.foo();
TestInterface b = new TestInterface() {
@Override
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.EmmaClassLoadingTest::log(Ljava/lang/String;)("1b foo");
}-*/;
};
b.foo();
if (false) {
TestInterface c = new TestInterface() {
@Override
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.EmmaClassLoadingTest::log(Ljava/lang/String;)("ANY_FOO_1");
}-*/;
};
}
EnumClass et = EnumClass.A;
switch (et) {
case A:
log("1enum A");
break;
case B:
log("ANY_FOO_2");
break;
case C:
log("ANY_FOO_3");
break;
}
TestInterface d = new TestInterface() {
@Override
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.EmmaClassLoadingTest::log(Ljava/lang/String;)("1d foo");
}-*/;
};
d.foo();
/*
* jdt generates $1 (a), $2 (b), $3 (d), $4 (e). javac generates $1 (a), $2
* (b), $3 (c), $4 (d), $5 (e), $6 (synthetic). Added e so that the test
* fails quickly. Otherwise, it had to wait for a time-out (in looking
* through jdt generated code for non-existent jsni methods of $4) to fail.
*/
TestInterface e = new TestInterface() {
@Override
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.EmmaClassLoadingTest::log(Ljava/lang/String;)("1e foo");
}-*/;
};
e.foo();
}
public void test2() {
// SecondTopLevelClass second = new SecondTopLevelClass();
SecondTopLevelClass.InnerClass.test();
}
public void test3() {
ThirdTopLevelClass third = new ThirdTopLevelClass();
third.test();
}
public void test4() {
FourthTopLevelClass fourth = new FourthTopLevelClass();
fourth.test();
}
}
/**
* Check that the algorithm correctly maps named inner classes. In this example,
* jdt generates $1Foo and $2Foo whereas javac generates $2Foo and $3Foo.
*
*/
class FourthTopLevelClass extends TestCase {
private static String messages[] = {"4a foo"};
private static int logCount = 0;
@SuppressWarnings("unused") // used by JSNI
private static void log(String msg) {
assertEquals(messages[logCount++], msg);
}
void test() {
test1();
test2();
};
private void test1() {
if (false) {
class Foo {
@SuppressWarnings("jsni")
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.FourthTopLevelClass::log(Ljava/lang/String;)("ANY_FOO");
}-*/;
}
new Foo().foo();
}
}
private void test2() {
class Foo {
@SuppressWarnings("jsni")
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.FourthTopLevelClass::log(Ljava/lang/String;)("4a foo");
}-*/;
}
new Foo().foo();
}
/*
* Added a test3() method so that when the test fails, it fails quickly.
* Instead of timing out, the AssertEquals fails
*/
@SuppressWarnings("unused")
private void test3() {
class Foo {
@SuppressWarnings("jsni")
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.FourthTopLevelClass::log(Ljava/lang/String;)("4b foo");
}-*/;
}
new Foo().foo();
}
}
/**
* Check if GWT is able to correctly compile cases when there are multiple
* top-level classes and when there is a need to traverse inner classes. This
* class's test method simply mirrors the test methods of EmmaClassLoadingTest.
*
*/
class SecondTopLevelClass extends TestCase {
static class InnerClass {
/**
* Test that mapping is constructed for something which is not in the main
* unit as well.
*/
static void test() {
EmmaClassLoadingTest.TestInterface a = new EmmaClassLoadingTest.TestInterface() {
@Override
public void foo() {
log("2a foo");
}
};
a.foo();
EmmaClassLoadingTest.TestInterface b = new EmmaClassLoadingTest.TestInterface() {
@Override
@SuppressWarnings("jsni")
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.SecondTopLevelClass::log(Ljava/lang/String;)("2b foo");
}-*/;
};
b.foo();
if (false) {
EmmaClassLoadingTest.TestInterface c = new EmmaClassLoadingTest.TestInterface() {
@Override
@SuppressWarnings("jsni")
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.SecondTopLevelClass::log(Ljava/lang/String;)("ANY_FOO_1");
}-*/;
};
}
EmmaClassLoadingTest.EnumClass et = EmmaClassLoadingTest.EnumClass.A;
switch (et) {
case A:
log("2enum A");
break;
case B:
log("ANY_FOO_2");
break;
case C:
log("ANY_FOO_3");
break;
}
EmmaClassLoadingTest.TestInterface d = new EmmaClassLoadingTest.TestInterface() {
@Override
@SuppressWarnings("jsni")
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.SecondTopLevelClass::log(Ljava/lang/String;)("2d foo");
}-*/;
};
d.foo();
/*
* jdt generates $1 (a), $2 (b), $3 (d), $4 (e). javac generates $1 (a),
* $2 (b), $3 (c), $4 (d), $5 (e), $6 (synthetic). Added e so that the
* test fails quickly. Otherwise, it had to wait for a time-out (in
* looking through jdt generated code for non-existent jsni methods of $4)
* to fail.
*/
EmmaClassLoadingTest.TestInterface e = new EmmaClassLoadingTest.TestInterface() {
@Override
@SuppressWarnings("jsni")
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.SecondTopLevelClass::log(Ljava/lang/String;)("2e foo");
}-*/;
};
e.foo();
}
}
private static String messages[] = {
"2a foo", "2b foo", "2enum A", "2d foo", "2e foo"};
private static int logCount = 0;
private static void log(String msg) {
assertEquals(messages[logCount++], msg);
}
}
/**
* Check that the mapping algorithm is not confused by the presence of other
* inner classes.
*/
class ThirdTopLevelClass extends TestCase {
private static String messages[] = {"3a foo"};
private static int logCount = 0;
@SuppressWarnings("unused") // called by JSNI
private static void log(String msg) {
assertEquals(messages[logCount++], msg);
}
void test() {
EmmaClassLoadingTest.TestInterface a = new EmmaClassLoadingTest.TestInterface() {
@Override
@SuppressWarnings("jsni")
public native void foo() /*-{
@com.google.gwt.dev.shell.rewrite.client.ThirdTopLevelClass::log(Ljava/lang/String;)("3a foo");
}-*/;
};
a.foo();
}
}