| /* |
| * Copyright 2015 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.core.interop; |
| |
| import static jsinterop.annotations.JsPackage.GLOBAL; |
| |
| import com.google.gwt.core.interop.MyExportedClass.InnerClass; |
| import com.google.gwt.junit.client.GWTTestCase; |
| |
| import jsinterop.annotations.JsMethod; |
| import jsinterop.annotations.JsProperty; |
| import jsinterop.annotations.JsType; |
| |
| /** |
| * Tests presence and naming of exported classes, fields, and methods. |
| */ |
| public class JsExportTest extends GWTTestCase { |
| |
| @Override |
| public String getModuleName() { |
| return "com.google.gwt.core.Interop"; |
| } |
| |
| @Override |
| public void gwtSetUp() throws Exception { |
| setupGlobal(); |
| } |
| |
| // $global always points to scope of exports |
| private native void setupGlobal() /*-{ |
| $global = window.goog && window.goog.global || $wnd; |
| $wnd.$global = $global; |
| }-*/; |
| |
| private native boolean isClosureFormattedOutputEnabled() /*-{ |
| return !!(window.goog && window.goog.global); |
| }-*/; |
| |
| public void testMethodExport() { |
| myClassExportsMethodCallMe1(); |
| assertTrue(MyClassExportsMethod.calledFromCallMe1); |
| |
| myClassExportsMethodCallMe2(); |
| assertTrue(MyClassExportsMethod.calledFromCallMe2); |
| |
| myClassExportsMethodCallMe3(); |
| assertTrue(MyClassExportsMethod.calledFromCallMe3); |
| |
| myClassExportsMethodCallMe4(); |
| assertTrue(MyClassExportsMethod.calledFromCallMe4); |
| |
| myClassExportsMethodCallMe5(); |
| assertTrue(MyClassExportsMethod.calledFromCallMe5); |
| } |
| |
| @JsMethod(namespace = "$global", name = "exported") |
| private static native void myClassExportsMethodCallMe1(); |
| |
| @JsMethod(namespace = "$global.exportNamespace", name = "exported") |
| private static native void myClassExportsMethodCallMe2(); |
| |
| @JsMethod(namespace = "$global.exportNamespace", name = "callMe3") |
| private static native void myClassExportsMethodCallMe3(); |
| |
| @JsMethod(namespace = "$global.woo.MyClassExportsMethod", name = "exported") |
| private static native void myClassExportsMethodCallMe4(); |
| |
| @JsMethod(namespace = "$global.woo.MyClassExportsMethod", name = "callMe5") |
| private static native void myClassExportsMethodCallMe5(); |
| |
| public void testMethodExportWithLong() { |
| NativeMyJsTypeThatUsesLongType obj = new NativeMyJsTypeThatUsesLongType(); |
| |
| assertEquals(42.0, obj.addLong(40.0, 2.0)); |
| assertEquals(82.0, NativeMyJsTypeThatUsesLongType.addLongStatic(80.0, 2.0)); |
| } |
| |
| /** |
| * Native interface to type MyJsTypeThatUsesLongType which has been exported to a particular |
| * namespaces. |
| */ |
| @JsType(isNative = true, namespace = "$global.woo", name = "MyJsTypeThatUsesLongType") |
| private static class NativeMyJsTypeThatUsesLongType { |
| public native double addLong(double a, double b); |
| |
| public static native double addLongStatic(double a, double b); |
| } |
| |
| public void testMethodExport_notReferencedFromJava() { |
| // Exported by MyClassExportsMethodWithoutReference which is not referenced by Java. This |
| // ensures that we correctly collect root types. |
| assertEquals(42, onlyCalledFromJs()); |
| } |
| |
| @JsMethod( |
| namespace = "$global.woo.MyClassExportsMethodWithoutReference", name = "onlyCalledFromJs") |
| private static native int onlyCalledFromJs(); |
| |
| public void testClinit() { |
| new NativeMyClassExportsMethodWithClinit(); |
| assertEquals(23, MyClassExportsMethodWithClinit.magicNumber); |
| } |
| |
| /** |
| * Native interface to type MyClassExportsMethodWithClinit which has been exported to a particular |
| * namespaces. |
| */ |
| @JsType(isNative = true, namespace = "$global.woo", name = "MyClassExportsMethodWithClinit") |
| private static class NativeMyClassExportsMethodWithClinit { } |
| |
| public void testClinit_staticField() { |
| assertNotNull(getStaticInitializerStaticFieldExported1()); |
| assertNotNull(getStaticInitializerStaticFieldExported2()); |
| assertNotNull(getStaticInitializerStaticFieldInterfaceStatic()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticField", name = "EXPORTED_1") |
| private static native Object getStaticInitializerStaticFieldExported1(); |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticField", name = "EXPORTED_2") |
| private static native Object getStaticInitializerStaticFieldExported2(); |
| |
| @JsProperty( |
| namespace = "$global.woo.StaticInitializerStaticField.InterfaceWithField", name = "STATIC") |
| private static native Object getStaticInitializerStaticFieldInterfaceStatic(); |
| |
| public void testClinit_staticMethod() { |
| assertNotNull(getStaticInitializerStaticMethod()); |
| } |
| |
| @JsMethod( |
| namespace = "$global.woo.StaticInitializerStaticMethod", name = "getInstance") |
| private static native int getStaticInitializerStaticMethod(); |
| |
| public void testClinit_virtualMethod() { |
| assertNotNull(new NativeStaticInitializerVirtualMethod().getInstance()); |
| } |
| |
| /** |
| * Native interface to type StaticInitializerVirtualMethod which has been exported to a particular |
| * namespaces. |
| */ |
| @JsType(isNative = true, namespace = "$global.woo", name = "StaticInitializerVirtualMethod") |
| private static class NativeStaticInitializerVirtualMethod { |
| public native Object getInstance(); |
| } |
| |
| @JsType(namespace = "bar.foo.baz") |
| class MyExportedClassCorrectNamespace { |
| public MyExportedClassCorrectNamespace() { } |
| } |
| |
| public void testExportClass_correctNamespace() { |
| assertNull(getBarMyExportedClassCorrectNamespace()); |
| assertNull(getBarFooMyExportedClassCorrectNamespace()); |
| assertTrue(getBarFooBazMyExportedClassCorrectNamespace() instanceof NativeFunction); |
| Object o = new NativeMyExportedClassCorrectNamespace(); |
| assertNotNull(o); |
| assertTrue(o instanceof MyExportedClassCorrectNamespace); |
| } |
| |
| @JsProperty(namespace = "$global.bar", name = "MyExportedClassCorrectNamespace") |
| private static native Object getBarMyExportedClassCorrectNamespace(); |
| |
| @JsProperty(namespace = "$global.bar.foo", name = "MyExportedClassCorrectNamespace") |
| private static native Object getBarFooMyExportedClassCorrectNamespace(); |
| |
| @JsProperty(namespace = "$global.bar.foo.baz", name = "MyExportedClassCorrectNamespace") |
| private static native Object getBarFooBazMyExportedClassCorrectNamespace(); |
| |
| @JsType(isNative = true, namespace = GLOBAL, name = "Function") |
| private static class NativeFunction { } |
| |
| @JsType( |
| isNative = true, namespace = "$global.bar.foo.baz", name = "MyExportedClassCorrectNamespace") |
| private static class NativeMyExportedClassCorrectNamespace { } |
| |
| public void testExportClass_implicitConstructor() { |
| Object o = new NativeMyExportedClassWithImplicitConstructor(); |
| assertNotNull(o); |
| assertTrue(o instanceof MyExportedClassWithImplicitConstructor); |
| } |
| |
| @JsType( |
| isNative = true, namespace = "$global.woo", name = "MyExportedClassWithImplicitConstructor") |
| private static class NativeMyExportedClassWithImplicitConstructor { } |
| |
| public void testExportConstructors() { |
| MyClassExportsConstructor nativeMyClassExportsConstructor = |
| (MyClassExportsConstructor) (Object) new NativeMyClassExportsConstructor(2); |
| assertEquals(4, nativeMyClassExportsConstructor.foo()); |
| assertEquals(2, new MyClassExportsConstructor().foo()); |
| } |
| |
| @JsType( |
| isNative = true, namespace = "$global.woo", name = "MyClassExportsConstructor") |
| private static class NativeMyClassExportsConstructor { |
| public NativeMyClassExportsConstructor(@SuppressWarnings("unused") int a) { } |
| } |
| |
| public void testGetJsConstructor() { |
| if (isClosureFormattedOutputEnabled()) { |
| return; // Closure formatted output doesn't support jsConstructor. |
| } |
| Object constructorFn = getJsConstructor(MyClassExportsConstructor.class); |
| assertSame(getMyClassExportsConstructor(), constructorFn); |
| assertSame(MyClassExportsConstructor.class, getClass(constructorFn)); |
| |
| assertNull(getJsConstructor(Object.class)); |
| assertNull(getJsConstructor(String.class)); |
| } |
| |
| @JsProperty(namespace = "$global.woo", name = "MyClassExportsConstructor") |
| private static native Object getMyClassExportsConstructor(); |
| |
| private static native Object getJsConstructor(Class<?> clazz) /*-{ |
| return clazz.@Class::jsConstructor; |
| }-*/; |
| |
| private static native Class<?> getClass(Object ctor) /*-{ |
| return ctor.prototype.@Object::___clazz; |
| }-*/; |
| |
| public void testExportedField() { |
| assertEquals(100, MyExportedClass.EXPORTED_1); |
| assertEquals(100, getExportedField()); |
| setExportedField(1000); |
| assertEquals(100, MyExportedClass.EXPORTED_1); |
| assertEquals(1000, getExportedField()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyExportedClass", name = "EXPORTED_1") |
| private static native int getExportedField(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedClass", name = "EXPORTED_1") |
| private static native void setExportedField(int value); |
| |
| public void testExportedMethod() { |
| assertEquals(200, MyExportedClass.foo()); |
| assertEquals(200, callExportedMethod()); |
| setExportedMethod(getReplacementExportedMethod()); |
| assertEquals(200, MyExportedClass.foo()); |
| assertEquals(1000, callExportedMethod()); |
| } |
| |
| @JsMethod( |
| namespace = "$global.woo.MyExportedClass", name = "foo") |
| private static native int callExportedMethod(); |
| |
| @JsProperty( |
| namespace = "$global.woo.MyExportedClass", name = "foo") |
| private static native void setExportedMethod(Object object); |
| |
| @JsProperty( |
| namespace = "$global.woo.MyExportedClass", name = "replacementFoo") |
| private static native Object getReplacementExportedMethod(); |
| |
| public void testExportedFieldRefInExportedMethod() { |
| assertEquals(5, MyExportedClass.bar(0, 0)); |
| assertEquals(5, callExportedFieldByExportedMethod(0, 0)); |
| setExportedField2(myExportedClassNewInnerClass(10)); |
| |
| assertEquals(10, getExportedField2()); |
| assertEquals(7, MyExportedClass.bar(1, 1)); |
| assertEquals(7, callExportedFieldByExportedMethod(1, 1)); |
| } |
| |
| @JsMethod(namespace = "$global.woo.MyExportedClass", name = "bar") |
| private static native int callExportedFieldByExportedMethod(int a, int b); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedClass", name = "EXPORTED_2") |
| private static native void setExportedField2(InnerClass a); |
| |
| @JsMethod(namespace = "$global.woo.MyExportedClass", name = "newInnerClass") |
| private static native InnerClass myExportedClassNewInnerClass(int a); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedClass.EXPORTED_2", name = "field") |
| private static native int getExportedField2(); |
| |
| public void testNoExport() { |
| assertNull(getNotExportedMethod1()); |
| assertNull(getNotExportedMethod2()); |
| |
| assertNull(getNotExported1()); |
| assertNull(getNotExported2()); |
| assertNull(getNotExported3()); |
| assertNull(getNotExported4()); |
| assertNull(getNotExported5()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticMethod", name = "notExported_1") |
| private static native Object getNotExportedMethod1(); |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticMethod", name = "notExported_2") |
| private static native Object getNotExportedMethod2(); |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticField", name = "NOT_EXPORTED_1") |
| private static native Object getNotExported1(); |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticField", name = "NOT_EXPORTED_2") |
| private static native Object getNotExported2(); |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticField", name = "NOT_EXPORTED_3") |
| private static native Object getNotExported3(); |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticField", name = "NOT_EXPORTED_4") |
| private static native Object getNotExported4(); |
| |
| @JsProperty(namespace = "$global.woo.StaticInitializerStaticField", name = "NOT_EXPORTED_5") |
| private static native Object getNotExported5(); |
| |
| public static void testInheritClassNamespace() { |
| assertEquals(42, getBAR()); |
| } |
| |
| @JsProperty(namespace = "$global.foo.MyExportedClassWithNamespace", name = "BAR") |
| private static native int getBAR(); |
| |
| public static void testInheritClassNamespace_empty() { |
| assertEquals(82, getDAN()); |
| assertNotNull(new NativeMyClassWithEmptyNamespace()); |
| } |
| |
| @JsProperty(namespace = "$global.MyClassWithEmptyNamespace", name = "DAN") |
| private static native int getDAN(); |
| |
| @JsType(isNative = true, namespace = "$global", name = "MyClassWithEmptyNamespace") |
| private static class NativeMyClassWithEmptyNamespace { } |
| |
| public static void testInheritClassNamespace_withName() { |
| assertEquals(42, getBooBAR()); |
| } |
| |
| @JsProperty(namespace = "$global.foo.boo", name = "BAR") |
| private static native int getBooBAR(); |
| |
| public static void testInheritClassNamespace_noExport() { |
| assertEquals(99, getBAZ()); |
| } |
| |
| @JsProperty(namespace = "$global.foobaz.MyClassWithNamespace", name = "BAZ") |
| private static native int getBAZ(); |
| |
| public static void testInheritClassNamespace_nested() { |
| assertEquals(99, getLOO()); |
| assertNotNull(new BlooInner()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.Bloo.Inner", name = "LOO") |
| private static native int getLOO(); |
| |
| @JsType(isNative = true, namespace = "$global.woo.Bloo", name = "Inner") |
| private static class BlooInner { } |
| |
| public static void testInheritClassNamespace_nestedNoExport() { |
| assertEquals(999, getWOOZ()); |
| assertNotNull(new NativeInnerWithNamespace()); |
| } |
| |
| @JsProperty(namespace = "$global.zoo.InnerWithNamespace", name = "WOOZ") |
| private static native int getWOOZ(); |
| |
| @JsType(isNative = true, namespace = "$global.zoo", name = "InnerWithNamespace") |
| private static class NativeInnerWithNamespace { } |
| |
| public void testInheritPackageNamespace() { |
| assertEquals(1001, getWOO()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyExportedClassWithPackageNamespace", name = "WOO") |
| private static native int getWOO(); |
| |
| public void testInheritPackageNamespace_nestedClass() { |
| assertEquals(99, getNestedWOO()); |
| assertNotNull(new NativeMyClassWithNestedExportedClassInner()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyClassWithNestedExportedClass.Inner", name = "WOO") |
| private static native int getNestedWOO(); |
| |
| @JsType(isNative = true, namespace = "$global.woo.MyClassWithNestedExportedClass", name = "Inner") |
| private static class NativeMyClassWithNestedExportedClassInner { } |
| |
| public void testInheritPackageNamespace_nestedEnum() { |
| assertNotNull(getNestedEnum()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyClassWithNestedExportedClass.InnerEnum", name = "AA") |
| private static native Object getNestedEnum(); |
| |
| public void testInheritPackageNamespace_subpackage() { |
| assertNull(getNestedSubpackage()); |
| assertNotNull(getNestedSubpackageCorrect()); |
| } |
| |
| @JsProperty(namespace = "$global.woo", name = "subpackage") |
| private static native Object getNestedSubpackage(); |
| |
| @JsProperty( |
| namespace = "$global.com.google.gwt.core.interop.subpackage", |
| name = "MyNestedExportedClassSansPackageNamespace") |
| private static native Object getNestedSubpackageCorrect(); |
| |
| public void testEnum_enumerations() { |
| assertNotNull(getEnumerationTEST1()); |
| assertNotNull(getEnumerationTEST2()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "TEST1") |
| private static native Object getEnumerationTEST1(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "TEST2") |
| private static native Object getEnumerationTEST2(); |
| |
| public void testEnum_exportedMethods() { |
| assertNotNull(getPublicStaticMethodInEnum()); |
| assertNotNull(getValuesMethodInEnum()); |
| assertNotNull(getValueOfMethodInEnum()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "publicStaticMethod") |
| private static native Object getPublicStaticMethodInEnum(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "values") |
| private static native Object getValuesMethodInEnum(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "valueOf") |
| private static native Object getValueOfMethodInEnum(); |
| |
| public void testEnum_exportedFields() { |
| assertEquals(1, getPublicStaticFinalFieldInEnum()); |
| |
| // explicitly marked @JsType() fields must be final |
| // but ones that are in a @JsType()ed class don't need to be final |
| assertEquals(2, getPublicStaticFieldInEnum()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "publicStaticFinalField") |
| private static native int getPublicStaticFinalFieldInEnum(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "publicStaticField") |
| private static native int getPublicStaticFieldInEnum(); |
| |
| public void testEnum_notExported() { |
| assertNull(myExportedEnumPublicFinalField()); |
| assertNull(myExportedEnumPrivateStaticFinalField()); |
| assertNull(myExportedEnumProtectedStaticFinalField()); |
| assertNull(myExportedEnumDefaultStaticFinalField()); |
| |
| assertNull(myExportedEnumPublicMethod()); |
| assertNull(myExportedEnumProtectedStaticMethod()); |
| assertNull(myExportedEnumPrivateStaticMethod()); |
| assertNull(myExportedEnumDefaultStaticMethod()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "publicFinalField") |
| private static native Object myExportedEnumPublicFinalField(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "privateStaticFinalField") |
| private static native Object myExportedEnumPrivateStaticFinalField(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "protectedStaticFinalField") |
| private static native Object myExportedEnumProtectedStaticFinalField(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "defaultStaticFinalField") |
| private static native Object myExportedEnumDefaultStaticFinalField(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "publicMethod") |
| private static native Object myExportedEnumPublicMethod(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "protectedStaticMethod") |
| private static native Object myExportedEnumProtectedStaticMethod(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "privateStaticMethod") |
| private static native Object myExportedEnumPrivateStaticMethod(); |
| |
| @JsProperty(namespace = "$global.woo.MyExportedEnum", name = "defaultStaticMethod") |
| private static native Object myExportedEnumDefaultStaticMethod(); |
| |
| public void testEnum_subclassEnumerations() { |
| assertNotNull(getEnumerationA()); |
| assertNotNull(getEnumerationB()); |
| assertNotNull(getEnumerationC()); |
| } |
| |
| @JsProperty(namespace = "$global.woo.MyEnumWithSubclassGen", name = "A") |
| private static native Object getEnumerationA(); |
| |
| @JsProperty(namespace = "$global.woo.MyEnumWithSubclassGen", name = "B") |
| private static native Object getEnumerationB(); |
| |
| @JsProperty(namespace = "$global.woo.MyEnumWithSubclassGen", name = "C") |
| private static native Object getEnumerationC(); |
| |
| public void testEnum_subclassMethodCallFromExportedEnumerations() { |
| assertEquals(100, callPublicMethodFromEnumerationA()); |
| assertEquals(200, callPublicMethodFromEnumerationB()); |
| assertEquals(1, callPublicMethodFromEnumerationC()); |
| } |
| |
| @JsMethod(namespace = "$global.woo.MyEnumWithSubclassGen.A", name = "foo") |
| private static native int callPublicMethodFromEnumerationA(); |
| |
| @JsMethod(namespace = "$global.woo.MyEnumWithSubclassGen.B", name = "foo") |
| private static native int callPublicMethodFromEnumerationB(); |
| |
| @JsMethod(namespace = "$global.woo.MyEnumWithSubclassGen.C", name = "foo") |
| private static native int callPublicMethodFromEnumerationC(); |
| } |