| /* | |
| * 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() { | |
| public void foo() { | |
| log("1a foo"); | |
| } | |
| }; | |
| a.foo(); | |
| TestInterface b = new TestInterface() { | |
| 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() { | |
| 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() { | |
| 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() { | |
| 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() { | |
| public void foo() { | |
| log("2a foo"); | |
| } | |
| }; | |
| a.foo(); | |
| EmmaClassLoadingTest.TestInterface b = new EmmaClassLoadingTest.TestInterface() { | |
| @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() { | |
| @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() { | |
| @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() { | |
| @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() { | |
| @SuppressWarnings("jsni") | |
| public native void foo() /*-{ | |
| @com.google.gwt.dev.shell.rewrite.client.ThirdTopLevelClass::log(Ljava/lang/String;)("3a foo"); | |
| }-*/; | |
| }; | |
| a.foo(); | |
| } | |
| } |