diff --git a/teavm-classlib/pom.xml b/teavm-classlib/pom.xml index 9f638f16a..1bf13a0ec 100644 --- a/teavm-classlib/pom.xml +++ b/teavm-classlib/pom.xml @@ -48,7 +48,7 @@ generate-javascript-tests - build-junit + build-test-javascript process-test-classes @@ -76,7 +76,7 @@ teavm-maven-plugin [0.0.1-SNAPSHOT,) - build-junit + build-test-javascript diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java index 58078199e..1340ae7a2 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java @@ -245,7 +245,8 @@ public class DependencyChecker implements DependencyInfo { } ValueType[] arguments = methodRef.getParameterTypes(); int paramCount = arguments.length + 1; - int varCount = Math.max(paramCount, method != null ? method.getProgram().variableCount() : 0); + int varCount = Math.max(paramCount, method != null && method.getProgram() != null ? + method.getProgram().variableCount() : 0); DependencyNode[] parameterNodes = new DependencyNode[varCount]; for (int i = 0; i < varCount; ++i) { parameterNodes[i] = new DependencyNode(this); diff --git a/teavm-html4j/pom.xml b/teavm-html4j/pom.xml index aad32b294..064790534 100644 --- a/teavm-html4j/pom.xml +++ b/teavm-html4j/pom.xml @@ -39,6 +39,12 @@ net.java.html.boot 0.8-SNAPSHOT + + org.netbeans.html + net.java.html.json.tck + 0.8-SNAPSHOT + true + junit junit @@ -57,12 +63,30 @@ generate-javascript-tests - build-junit + build-test-javascript process-test-classes false 1 + ${project.build.directory}/javascript-test + + + + generate-javascript-tck + + build-test-javascript + + process-test-classes + + false + 1 + true + ${project.build.directory}/javascript-tck + org.teavm.html4j.testing.KOTestAdapter + + net.java.html.js.tests.*Test + @@ -70,6 +94,14 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 2.16 + + true + + org.eclipse.m2e @@ -84,7 +116,7 @@ teavm-maven-plugin [0.0.1-SNAPSHOT,) - build-junit + build-test-javascript diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java index 00a53ea18..4359fcc42 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java @@ -32,6 +32,8 @@ public class JavaScriptBodyTransformer implements ClassHolderTransformer { genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( JavaScriptBodyGenerator.class.getName()))); method.getAnnotations().add(genAnnot); + method.setProgram(null); + method.getModifiers().add(ElementModifier.NATIVE); } } } diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/testing/KOTestAdapter.java b/teavm-html4j/src/main/java/org/teavm/html4j/testing/KOTestAdapter.java new file mode 100644 index 000000000..d684ec611 --- /dev/null +++ b/teavm-html4j/src/main/java/org/teavm/html4j/testing/KOTestAdapter.java @@ -0,0 +1,51 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * 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 org.teavm.html4j.testing; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.Collections; +import org.apidesign.html.json.tck.KOTest; +import org.teavm.model.MethodReader; +import org.teavm.testing.TestAdapter; + +/** + * + * @author Alexey Andreev + */ +public class KOTestAdapter implements TestAdapter { + @Override + public boolean acceptClass(Class cls) { + for (Method method : cls.getDeclaredMethods()) { + for (Annotation annot : method.getAnnotations()) { + if (annot.annotationType().getName().equals(KOTest.class.getName())) { + return true; + } + } + } + return false; + } + + @Override + public boolean acceptMethod(MethodReader method) { + return method.getAnnotations().get(KOTest.class.getName()) != null; + } + + @Override + public Iterable getExpectedExceptions(MethodReader method) { + return Collections.emptyList(); + } +} diff --git a/teavm-html4j/src/test/java/net/java/html/js/tests/Bodies.java b/teavm-html4j/src/test/java/net/java/html/js/tests/Bodies.java deleted file mode 100644 index 1fc2b0d57..000000000 --- a/teavm-html4j/src/test/java/net/java/html/js/tests/Bodies.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. - * - * Oracle and Java are registered trademarks of Oracle and/or its affiliates. - * Other names may be trademarks of their respective owners. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package net.java.html.js.tests; - -import java.util.concurrent.Callable; -import net.java.html.js.JavaScriptBody; - -/** - * - * @author Jaroslav Tulach - */ -final class Bodies { - @JavaScriptBody(args = { "a", "b" }, body = "return a + b;") - public static native int sum(int a, int b); - - @JavaScriptBody(args = {"r"}, javacall = true, body = "r.@java.lang.Runnable::run()();") - static native void callback(Runnable r); - - @JavaScriptBody(args = {"c"}, javacall = true, body = "return c.@java.util.concurrent.Callable::call()();") - static native Object callback(Callable c); - - @JavaScriptBody(args = {"c", "v"}, javacall = true, body = "var arr = c.@java.util.concurrent.Callable::call()(); arr.push(v); return arr;") - static native Object callbackAndPush(Callable c, String v); - - @JavaScriptBody(args = { "v" }, body = "return v;") - public static native Object id(Object v); - - @JavaScriptBody(args = { "v" }, body = "return { 'x' : v };") - public static native Object instance(int v); - - @JavaScriptBody(args = "o", body = "o.x++;") - public static native void incrementX(Object o); - - @JavaScriptBody(args = "o", body = "return o.x;") - public static native int readX(Object o); - - @JavaScriptBody(args = { "c" }, javacall = true, body = - "return c.@net.java.html.js.tests.Sum::sum(II)(40, 2);" - ) - public static native int sumIndirect(Sum c); - - @JavaScriptBody(args = { "arr", "index" }, body = "return arr[index];") - public static native Object select(Object[] arr, int index); - - @JavaScriptBody(args = { "arr" }, body = "return arr.length;") - public static native int length(Object[] arr); - - @JavaScriptBody(args = { "o", "vo" }, body = "if (vo) o = o.valueOf(); return typeof o;") - public static native String typeof(Object o, boolean useValueOf); - - @JavaScriptBody(args = { "b" }, body = "return typeof b;") - public static native String typeof(boolean b); - - @JavaScriptBody(args = { "o" }, body = "return Array.isArray(o);") - public static native boolean isArray(Object o); - - @JavaScriptBody(args = { "arr", "i", "value" }, body = "arr[i] = value; return arr[i];") - public static native String modify(String[] arr, int i, String value); - - @JavaScriptBody(args = {}, body = "return true;") - public static native boolean truth(); - - @JavaScriptBody(args = { "s" }, javacall = true, body = - "return s.@net.java.html.js.tests.Sum::sum([Ljava/lang/Object;)([1, 2, 3]);" - ) - public static native int sumArr(Sum s); -} diff --git a/teavm-html4j/src/test/java/net/java/html/js/tests/Factorial.java b/teavm-html4j/src/test/java/net/java/html/js/tests/Factorial.java deleted file mode 100644 index ee6ae36b2..000000000 --- a/teavm-html4j/src/test/java/net/java/html/js/tests/Factorial.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. - * - * Oracle and Java are registered trademarks of Oracle and/or its affiliates. - * Other names may be trademarks of their respective owners. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package net.java.html.js.tests; - -import net.java.html.js.JavaScriptBody; - -/** - * - * @author Jaroslav Tulach - */ -public final class Factorial { - int minusOne(int i) { - return i - 1; - } - - @JavaScriptBody(args = { "i" }, javacall = true,body = - "if (i <= 1) return 1;\n" - + "var im1 = this.@net.java.html.js.tests.Factorial::minusOne(I)(i);\n" - + "return this.@net.java.html.js.tests.Factorial::factorial(I)(im1) * i;" - ) - native int factorial(int n); -} diff --git a/teavm-html4j/src/test/java/net/java/html/js/tests/JavaScriptBodyTests.java b/teavm-html4j/src/test/java/net/java/html/js/tests/JavaScriptBodyTests.java deleted file mode 100644 index 520e8fdab..000000000 --- a/teavm-html4j/src/test/java/net/java/html/js/tests/JavaScriptBodyTests.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright 2014 Alexey Andreev. - * - * 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 ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. - * - * Oracle and Java are registered trademarks of Oracle and/or its affiliates. - * Other names may be trademarks of their respective owners. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package net.java.html.js.tests; - -import static org.junit.Assert.*; -import java.io.StringReader; -import java.util.Arrays; -import java.util.concurrent.Callable; -import org.apidesign.html.boot.spi.Fn; -import org.junit.Test; - -/** - * - * @author Jaroslav Tulach - */ -public class JavaScriptBodyTests { - @Test public void sumTwoNumbers() { - int res = Bodies.sum(5, 3); - assertEquals(8, res); - } - - @Test public void accessJsObject() { - Object o = Bodies.instance(10); - int ten = Bodies.readX(o); - assertEquals(10, ten); - } - - @Test public void callWithNoReturnType() { - Object o = Bodies.instance(10); - Bodies.incrementX(o); - int ten = Bodies.readX(o); - assertEquals(11, ten); - } - - @Test public void callbackToRunnable() { - R run = new R(); - Bodies.callback(run); - assertEquals(1, run.cnt); - } - - @Test public void typeOfCharacter() { - String charType = Bodies.typeof('a', false); - assertEquals("number", charType); - } - - @Test public void typeOfBoolean() { - String booleanType = Bodies.typeof(true, false); - assertEquals("boolean", booleanType); - } - - @Test public void typeOfPrimitiveBoolean() { - String booleanType = Bodies.typeof(true); - assertTrue("boolean".equals(booleanType) || "number".equals(booleanType)); - } - - @Test public void typeOfInteger() { - String intType = Bodies.typeof(1, false); - assertEquals("number", intType); - } - - @Test public void typeOfString() { - String strType = Bodies.typeof("Ahoj", false); - assertEquals("string", strType); - } - - @Test public void typeOfDouble() { - String doubleType = Bodies.typeof(0.33, false); - assertEquals("number", doubleType); - } - - @Test public void typeOfBooleanValueOf() { - String booleanType = Bodies.typeof(true, true); - assertEquals("boolean", booleanType); - } - - @Test public void typeOfIntegerValueOf() { - String intType = Bodies.typeof(1, true); - assertEquals("number", intType); - } - - @Test public void typeOfStringValueOf() { - String strType = Bodies.typeof("Ahoj", true); - assertEquals("string", strType); - } - - @Test public void typeOfDoubleValueOf() { - String doubleType = Bodies.typeof(0.33, true); - assertEquals("number", doubleType); - } - - @Test public void computeInARunnable() { - final int[] sum = new int[2]; - class First implements Runnable { - @Override public void run() { - sum[0] = Bodies.sum(22, 20); - sum[1] = Bodies.sum(32, 10); - } - } - Bodies.callback(new First()); - assertEquals(42, sum[0]); - assertEquals(42, sum[1]); - } - - @Test public void doubleCallbackToRunnable() { - final R run = new R(); - final R r2 = new R(); - class First implements Runnable { - @Override public void run() { - Bodies.callback(run); - Bodies.callback(r2); - } - } - Bodies.callback(new First()); - assert run.cnt == 1 : "Can call even private implementation classes: " + run.cnt; - assert r2.cnt == 1 : "Can call even private implementation classes: " + r2.cnt; - } - - @Test public void identity() { - Object p = new Object(); - Object r = Bodies.id(p); - assert r == p : "The object is the same"; - } - - @Test public void encodingString() { - Object p = "Ji\n\"Hi\"\nHon"; - Object r = Bodies.id(p); - assert p.equals(r) : "The object is the same: " + p + " != " + r; - } - - @Test public void encodingBackslashString() { - Object p = "{\"firstName\":\"/*\\n * Copyright (c) 2013\",\"lastName\":null,\"sex\":\"MALE\",\"address\":{\"street\":null}}"; - Object r = Bodies.id(p); - assert p.equals(r) : "The object is the same: " + p + " != " + r; - } - - @Test public void nullIsNull() { - Object p = null; - Object r = Bodies.id(p); - assert r == p : "The null is the same"; - } - - @Test public void callbackWithResult() { - Callable c = new C(); - Object b = Bodies.callback(c); - assert b == Boolean.TRUE : "Should return true"; - } - - @Test public void callbackWithParameters() { - int res = Bodies.sumIndirect(new Sum()); - assert res == 42 : "Expecting 42"; - } - - @Test public void selectFromStringJavaArray() { - String[] arr = { "Ahoj", "World" }; - Object res = Bodies.select(arr, 1); - assert "World".equals(res) : "Expecting World, but was: " + res; - } - - @Test public void selectFromObjectJavaArray() { - Object[] arr = { new Object(), new Object() }; - Object res = Bodies.select(arr, 1); - assert arr[1].equals(res) : "Expecting " + arr[1] + ", but was: " + res; - } - - @Test public void lengthOfJavaArray() { - String[] arr = { "Ahoj", "World" }; - int res = Bodies.length(arr); - assert res == 2 : "Expecting 2, but was: " + res; - } - - @Test public void isJavaArray() { - String[] arr = { "Ahoj", "World" }; - boolean is = Bodies.isArray(arr); - assert is: "Expecting it to be an array: " + is; - } - - @Test public void javaArrayInOutIsCopied() { - String[] arr = { "Ahoj", "World" }; - Object res = Bodies.id(arr); - assert res != null : "Non-null is returned"; - assert res instanceof Object[] : "Returned an array: " + res; - assert !(res instanceof String[]) : "Not returned a string array: " + res; - - Object[] ret = (Object[]) res; - assert arr.length == ret.length : "Same length: " + ret.length; - assert arr[0].equals(ret[0]) : "Same first elem"; - assert arr[1].equals(ret[1]) : "Same 2nd elem"; - } - - @Test public void modifyJavaArrayHasNoEffect() { - String[] arr = { "Ahoj", "World" }; - String value = Bodies.modify(arr, 0, "Hello"); - assert "Hello".equals(value) : "Inside JS the value is changed: " + value; - assert "Ahoj".equals(arr[0]) : "From a Java point of view it remains: " + arr[0]; - } - - @Test - public void callbackWithArray() { - class A implements Callable { - @Override - public String[] call() throws Exception { - return new String[] { "Hello" }; - } - } - Callable a = new A(); - Object b = Bodies.callbackAndPush(a, "World!"); - assert b instanceof Object[] : "Returns an array: " + b; - Object[] arr = (Object[]) b; - String str = Arrays.toString(arr); - assert arr.length == 2 : "Size is two " + str; - assert "Hello".equals(arr[0]) : "Hello expected: " + arr[0]; - assert "World!".equals(arr[1]) : "World! expected: " + arr[1]; - } - - @Test public void truth() { - assert Bodies.truth() : "True is true"; - } - - @Test public void factorial2() { - assert new Factorial().factorial(2) == 2; - } - - @Test public void factorial3() { - assert new Factorial().factorial(3) == 6; - } - - @Test public void factorial4() { - assert new Factorial().factorial(4) == 24; - } - - @Test public void factorial5() { - assert new Factorial().factorial(5) == 120; - } - - @Test public void factorial6() { - assert new Factorial().factorial(6) == 720; - } - - @Test public void sumArray() { - int r = Bodies.sumArr(new Sum()); - assert r == 6 : "Sum is six: " + r; - } - - @Test public void callLater() throws Exception{ - final Fn.Presenter p = Fn.activePresenter(); - if (p == null) { - return; - } - p.loadScript(new StringReader( - "if (typeof window === 'undefined') window = {};" - )); - Later l = new Later(); - l.register(); - p.loadScript(new StringReader( - "window.later();" - )); - for (int i = 0; i < 100 && l.call != 42; i++) { - Thread.sleep(50); - } - assert l.call == 42 : "Method was called: " + l.call; - } - - private static class R implements Runnable { - int cnt; - private final Thread initThread; - - public R() { - initThread = Thread.currentThread(); - } - - @Override - public void run() { - assert initThread == Thread.currentThread() : "Expecting to run in " + initThread + " but running in " + Thread.currentThread(); - cnt++; - } - } - - private static class C implements Callable { - @Override - public Boolean call() throws Exception { - return Boolean.TRUE; - } - } -} diff --git a/teavm-html4j/src/test/java/net/java/html/js/tests/Later.java b/teavm-html4j/src/test/java/net/java/html/js/tests/Later.java deleted file mode 100644 index 71293937b..000000000 --- a/teavm-html4j/src/test/java/net/java/html/js/tests/Later.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. - * - * Oracle and Java are registered trademarks of Oracle and/or its affiliates. - * Other names may be trademarks of their respective owners. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package net.java.html.js.tests; - -import net.java.html.js.JavaScriptBody; - -/** - * - * @author Jaroslav Tulach - */ -public final class Later { - volatile int call; - - @JavaScriptBody(args = { }, javacall = true, body = - "var self = this;" - + "window.later = function() {" - + " self.@net.java.html.js.tests.Later::call(I)(42);" - + "};" - ) - native void register(); - - void call(int value) { - this.call = value; - } -} diff --git a/teavm-html4j/src/test/java/net/java/html/js/tests/Sum.java b/teavm-html4j/src/test/java/net/java/html/js/tests/Sum.java deleted file mode 100644 index ae18175af..000000000 --- a/teavm-html4j/src/test/java/net/java/html/js/tests/Sum.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. - * - * Oracle and Java are registered trademarks of Oracle and/or its affiliates. - * Other names may be trademarks of their respective owners. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package net.java.html.js.tests; - -/** - * - * @author Jaroslav Tulach - */ -public final class Sum { - public int sum(int a, int b) { - return a + b; - } - - public int sum(Object[] arr) { - int s = 0; - for (int i = 0; i < arr.length; i++) { - if (arr[i] instanceof Number) { - s += ((Number)arr[i]).intValue(); - } - } - return s; - } -} diff --git a/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyConversionTests.java b/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyConversionTest.java similarity index 98% rename from teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyConversionTests.java rename to teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyConversionTest.java index 0cfaa1185..b8b6910a7 100644 --- a/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyConversionTests.java +++ b/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyConversionTest.java @@ -23,7 +23,7 @@ import org.junit.Test; * * @author Alexey Andreev */ -public class JavaScriptBodyConversionTests { +public class JavaScriptBodyConversionTest { @Test public void convertsInteger() { assertEquals(23, returnAsInt(23)); diff --git a/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTests.java b/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTest.java similarity index 96% rename from teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTests.java rename to teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTest.java index a49ab769a..a3dce3b5d 100644 --- a/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTests.java +++ b/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTest.java @@ -23,7 +23,7 @@ import org.junit.Test; * * @author Alexey Andreev */ -public class JavaScriptBodyTests { +public class JavaScriptBodyTest { @Test public void javaScriptBodyHandled() { assertEquals(23, simpleNativeMethod()); @@ -92,7 +92,7 @@ public class JavaScriptBodyTests { } @JavaScriptBody(args = { "a" }, body = "return " + - "@org.teavm.html4j.test.JavaScriptBodyTests::staticCallback(" + + "@org.teavm.html4j.test.JavaScriptBodyTest::staticCallback(" + "Lorg/teavm/html4j/test/A;)(a)", javacall = true) private native int invokeStaticCallback(A a); } diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java b/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java index 2c02ea738..e44e6e994 100644 --- a/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java +++ b/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java @@ -22,6 +22,9 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; @@ -48,7 +51,7 @@ import org.teavm.testing.TestAdapter; * * @author Alexey Andreev */ -@Mojo(name = "build-junit", requiresDependencyResolution = ResolutionScope.TEST, +@Mojo(name = "build-test-javascript", requiresDependencyResolution = ResolutionScope.TEST, requiresDependencyCollection = ResolutionScope.TEST) public class BuildJavascriptTestMojo extends AbstractMojo { private static Set testScopes = new HashSet<>(Arrays.asList( @@ -63,7 +66,7 @@ public class BuildJavascriptTestMojo extends AbstractMojo { @Component private MavenProject project; - @Parameter(defaultValue = "${project.build.directory}/javascript-junit") + @Parameter(defaultValue = "${project.build.directory}/javascript-test") private File outputDir; @Parameter(defaultValue = "${project.build.outputDirectory}") @@ -73,16 +76,19 @@ public class BuildJavascriptTestMojo extends AbstractMojo { private File testFiles; @Parameter - private String[] testFilePatterns = { "*Test", "*UnitTest" }; + private String[] wildcards = { "**.*Test", "**.*UnitTest" }; @Parameter private boolean minifying = true; + @Parameter + private boolean scanDependencies; + @Parameter private int numThreads = 1; @Parameter - private Class adapterClass = JUnitTestAdapter.class; + private String adapterClass = JUnitTestAdapter.class.getName(); public void setProject(MavenProject project) { this.project = project; @@ -108,18 +114,25 @@ public class BuildJavascriptTestMojo extends AbstractMojo { this.numThreads = numThreads; } - public void setAdapterClass(Class adapterClass) { + public void setAdapterClass(String adapterClass) { this.adapterClass = adapterClass; } + public void setWildcards(String[] wildcards) { + this.wildcards = wildcards; + } + @Override public void execute() throws MojoExecutionException, MojoFailureException { Runnable finalizer = null; - createAdapter(); try { final ClassLoader classLoader = prepareClassLoader(); + createAdapter(classLoader); getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'"); findTestClasses(classLoader, testFiles, ""); + if (scanDependencies) { + findTestsInDependencies(classLoader); + } final Log log = getLog(); new File(outputDir, "tests").mkdirs(); resourceToFile("org/teavm/javascript/runtime.js", "runtime.js"); @@ -210,13 +223,23 @@ public class BuildJavascriptTestMojo extends AbstractMojo { } } - private void createAdapter() throws MojoExecutionException { + private void createAdapter(ClassLoader classLoader) throws MojoExecutionException { + Class adapterClsRaw; + try { + adapterClsRaw = Class.forName(adapterClass, true, classLoader); + } catch (ClassNotFoundException e) { + throw new MojoExecutionException("Adapter not found: " + adapterClass, e); + } + if (!TestAdapter.class.isAssignableFrom(adapterClsRaw)) { + throw new MojoExecutionException("Adapter " + adapterClass + " does not implement " + + TestAdapter.class.getName()); + } + Class adapterCls = adapterClsRaw.asSubclass(TestAdapter.class); Constructor cons; try { - cons = adapterClass.getConstructor(); + cons = adapterCls.getConstructor(); } catch (NoSuchMethodException e) { - throw new MojoExecutionException("No default constructor found for test adapter " + - adapterClass.getName(), e); + throw new MojoExecutionException("No default constructor found for test adapter " + adapterClass, e); } try { adapter = cons.newInstance(); @@ -230,7 +253,7 @@ public class BuildJavascriptTestMojo extends AbstractMojo { private ClassLoader prepareClassLoader() throws MojoExecutionException { try { Log log = getLog(); - log.info("Preparing classpath for JavaScript JUnit generation"); + log.info("Preparing classpath for JavaScript test generation"); List urls = new ArrayList<>(); StringBuilder classpath = new StringBuilder(); for (Artifact artifact : project.getArtifacts()) { @@ -251,7 +274,7 @@ public class BuildJavascriptTestMojo extends AbstractMojo { urls.add(testFiles.toURI().toURL()); classpath.append(':').append(classFiles.getPath()); urls.add(classFiles.toURI().toURL()); - log.info("Using the following classpath for JavaScript JUnit generation: " + classpath); + log.info("Using the following classpath for JavaScript test generation: " + classpath); return new URLClassLoader(urls.toArray(new URL[urls.size()]), BuildJavascriptTestMojo.class.getClassLoader()); } catch (MalformedURLException e) { @@ -335,6 +358,28 @@ public class BuildJavascriptTestMojo extends AbstractMojo { writer.append('\"'); } + private void findTestsInDependencies(ClassLoader classLoader) throws MojoExecutionException { + try { + Log log = getLog(); + log.info("Scanning dependencies for tests"); + for (Artifact artifact : project.getArtifacts()) { + if (!testScopes.contains(artifact.getScope())) { + continue; + } + File file = artifact.getFile(); + if (file.isDirectory()) { + findTestClasses(classLoader, file, ""); + } else if (file.getName().endsWith(".jar")) { + findTestClassesInJar(classLoader, new JarFile(file)); + } + } + } catch (MalformedURLException e) { + throw new MojoExecutionException("Error gathering classpath information", e); + } catch (IOException e) { + throw new MojoExecutionException("Error scanning dependencies for tests", e); + } + } + private void findTestClasses(ClassLoader classLoader, File folder, String prefix) { for (File file : folder.listFiles()) { if (file.isDirectory()) { @@ -345,19 +390,47 @@ public class BuildJavascriptTestMojo extends AbstractMojo { if (!prefix.isEmpty()) { className = prefix + "." + className; } - try { - Class candidate = Class.forName(className, true, classLoader); - if (adapter.acceptClass(candidate)) { - testClasses.add(candidate.getName()); - getLog().info("Test class detected: " + candidate.getName()); - } - } catch (ClassNotFoundException e) { - getLog().info("Could not load class `" + className + "' to search for tests"); - } + addCandidate(classLoader, className); } } } + private void findTestClassesInJar(ClassLoader classLoader, JarFile jarFile) { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (entry.isDirectory() || !entry.getName().endsWith(".class")) { + continue; + } + String className = entry.getName().substring(0, entry.getName().length() - ".class".length()) + .replace('/', '.'); + addCandidate(classLoader, className); + } + } + + private void addCandidate(ClassLoader classLoader, String className) { + boolean matches = false; + String simpleName = className.replace('.', '/'); + for (String wildcard : wildcards) { + if (FilenameUtils.wildcardMatch(simpleName, wildcard.replace('.', '/'))) { + matches = true; + break; + } + } + if (!matches) { + return; + } + try { + Class candidate = Class.forName(className, true, classLoader); + if (adapter.acceptClass(candidate)) { + testClasses.add(candidate.getName()); + getLog().info("Test class detected: " + candidate.getName()); + } + } catch (ClassNotFoundException e) { + getLog().info("Could not load class `" + className + "' to search for tests"); + } + } + private void findTests(ClassHolder cls) { for (MethodHolder method : cls.getMethods()) { if (adapter.acceptMethod(method)) {