# HG changeset patch # User Jaroslav Tulach # Date 1356301806 -3600 # Node ID 3485327d30804f8940cdd9204e4d20b125693731 # Parent bafc670aa10d519552ba06bc11f34c4f3018b926 Execution time reported by TestNG reflect the time it took to run the query inside of a browser diff -r bafc670aa10d -r 3485327d3080 launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Sun Dec 23 18:24:18 2012 +0100 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Sun Dec 23 23:30:06 2012 +0100 @@ -54,6 +54,7 @@ */ public class Bck2BrwsrLauncher { private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName()); + private static final MethodInvocation END = new MethodInvocation(null, null); private Set loaders = new LinkedHashSet<>(); private BlockingQueue methods = new LinkedBlockingQueue<>(); private long timeOut; @@ -153,10 +154,11 @@ } MethodInvocation mi = methods.take(); - if (mi == null) { + if (mi == END) { response.getWriter().write(""); wait.countDown(); cnt = 0; + LOG.log(Level.INFO, "End of data reached. Exiting."); return; } @@ -177,6 +179,7 @@ } public void shutdown() throws InterruptedException, IOException { + methods.offer(END); for (;;) { int prev = methods.size(); if (wait.await(timeOut, TimeUnit.MILLISECONDS)) { diff -r bafc670aa10d -r 3485327d3080 mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Sun Dec 23 18:24:18 2012 +0100 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Sun Dec 23 23:30:06 2012 +0100 @@ -20,14 +20,16 @@ import org.apache.maven.plugin.AbstractMojo; import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; @@ -35,7 +37,6 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher; -import org.apidesign.vm4brwsr.Bck2Brwsr; /** Executes given HTML page in a browser. */ @Mojo(name="brwsr", defaultPhase=LifecyclePhase.DEPLOY) @@ -63,9 +64,12 @@ URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts()); Bck2BrwsrLauncher httpServer = new Bck2BrwsrLauncher(); - httpServer.setStartPage(startpage); httpServer.addClassLoader(url); - httpServer.execute(); + try { + httpServer.showURL(startpage); + } catch (Exception ex) { + throw new MojoExecutionException("Can't open " + startpage, ex); + } System.in.read(); } catch (IOException ex) { diff -r bafc670aa10d -r 3485327d3080 vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Launcher.java --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Launcher.java Sun Dec 23 18:24:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/** - * Back 2 Browser Bytecode Translator - * Copyright (C) 2012 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://opensource.org/licenses/GPL-2.0. - */ -package org.apidesign.bck2brwsr.vmtest; - -import java.io.IOException; -import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher; -import org.apidesign.bck2brwsr.launcher.JSLauncher; -import org.apidesign.bck2brwsr.launcher.MethodInvocation; - -/** - * - * @author Jaroslav Tulach - */ -final class Launcher { - private final String sen; - private Object launcher; - - Launcher() { - this(null); - } - Launcher(String sen) { - this.sen = sen; - } - - synchronized Object clear() { - Object l = launcher; - launcher = null; - return l; - } - - synchronized MethodInvocation addMethod(Class clazz, String name) throws IOException { - if (launcher == null) { - if (sen != null) { - JSLauncher js = new JSLauncher(); - js.addClassLoader(clazz.getClassLoader()); - js.initialize(); - launcher = js; - } else { - Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(); - l.initialize(); - l.setTimeout(180000); - launcher = l; - } - } - if (launcher instanceof JSLauncher) { - return ((JSLauncher)launcher).addMethod(clazz, name); - } else { - return ((Bck2BrwsrLauncher)launcher).addMethod(clazz, name); - } - } - - void exec() throws Exception { - Object l = clear(); - } - -} diff -r bafc670aa10d -r 3485327d3080 vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java Sun Dec 23 18:24:18 2012 +0100 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java Sun Dec 23 23:30:06 2012 +0100 @@ -17,20 +17,8 @@ */ package org.apidesign.bck2brwsr.vmtest; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.script.Invocable; -import org.apidesign.bck2brwsr.launcher.MethodInvocation; -import org.testng.Assert; -import org.testng.ITest; +import org.apidesign.bck2brwsr.vmtest.impl.CompareCase; import org.testng.annotations.Factory; -import org.testng.annotations.Test; /** A TestNG {@link Factory} that seeks for {@link Compare} annotations * in provided class and builds set of tests that compare the computations @@ -41,19 +29,7 @@ * * @author Jaroslav Tulach */ -public final class VMTest implements ITest { - private static final Launcher JS = new Launcher("js"); - private static final Launcher BROWSER = new Launcher(); - - private final Run first, second; - private final Method m; - - private VMTest(Method m, Run first, Run second) { - this.first = first; - this.second = second; - this.m = m; - } - +public final class VMTest { /** Inspects clazz and for each {@lik Compare} method creates * instances of tests. Each instance runs the test in different virtual * machine and at the end they compare the results. @@ -62,164 +38,6 @@ * @return the set of created tests */ public static Object[] create(Class clazz) { - Method[] arr = clazz.getMethods(); - Object[] ret = new Object[5 * arr.length]; - int cnt = 0; - for (Method m : arr) { - Compare c = m.getAnnotation(Compare.class); - if (c == null) { - continue; - } - final Run real = new Run(m, 0); - final Run js = new Run(m, 1); - final Run brwsr = new Run(m, 2); - ret[cnt++] = real; - ret[cnt++] = js; - ret[cnt++] = brwsr; - ret[cnt++] = new VMTest(m, real, js); - ret[cnt++] = new VMTest(m, real, brwsr); - } - Object[] r = new Object[cnt]; - for (int i = 0; i < cnt; i++) { - r[i] = ret[i]; - } - return r; - } - - /** Test that compares the previous results. - * @throws Throwable - */ - @Test(dependsOnGroups = "run") public void compareResults() throws Throwable { - Object v1 = first.value; - Object v2 = second.value; - if (v1 != null) { - v1 = v1.toString(); - } else { - v1 = "null"; - } - Assert.assertEquals(v2, v1, "Comparing results"); - } - - /** Test name. - * @return name of the tested method followed by a suffix - */ - @Override - public String getTestName() { - return m.getName() + "[Compare " + second.typeName() + "]"; - } - - public static final class Run implements ITest { - private final Method m; - private final int type; - Object value; - private Invocable code; - private CharSequence codeSeq; - private static final Map compiled = new WeakHashMap<>(); - private Object inst; - - private Run(Method m, int type) { - this.m = m; - this.type = type; - try { - initialize(); - } catch (Throwable ex) { - Logger.getLogger(VMTest.class.getName()).log(Level.SEVERE, null, ex); - } - } - - private void initialize() throws Throwable { - if (type == 1) { - inst = JS.addMethod(m.getDeclaringClass(), m.getName()); - } - if (type == 2) { - inst = BROWSER.addMethod(m.getDeclaringClass(), m.getName()); - } - } - - @Test(groups = "run") public void executeCode() throws Throwable { - if (type == 1) { - MethodInvocation c = (MethodInvocation) inst; - JS.exec(); - value = c.toString(); - } else if (type == 2) { - MethodInvocation c = (MethodInvocation) inst; - BROWSER.exec(); - value = c.toString(); - } else { - value = m.invoke(m.getDeclaringClass().newInstance()); - } - } - @Override - public String getTestName() { - return m.getName() + "[" + typeName() + "]"; - } - - final String typeName() { - switch (type) { - case 0: return "Java"; - case 1: return "JavaScript"; - case 2: return "Browser"; - default: return "Unknown type " + type; - } - } - - private static String computeSignature(Method m) { - StringBuilder sb = new StringBuilder(); - appendType(sb, m.getReturnType()); - for (Class c : m.getParameterTypes()) { - appendType(sb, c); - } - return sb.toString(); - } - - private static void appendType(StringBuilder sb, Class t) { - if (t == null) { - sb.append('V'); - return; - } - if (t.isPrimitive()) { - int ch = -1; - if (t == int.class) { - ch = 'I'; - } - if (t == short.class) { - ch = 'S'; - } - if (t == byte.class) { - ch = 'B'; - } - if (t == boolean.class) { - ch = 'Z'; - } - if (t == long.class) { - ch = 'J'; - } - if (t == float.class) { - ch = 'F'; - } - if (t == double.class) { - ch = 'D'; - } - assert ch != -1 : "Unknown primitive type " + t; - sb.append((char)ch); - return; - } - if (t.isArray()) { - sb.append("_3"); - appendType(sb, t.getComponentType()); - return; - } - sb.append('L'); - sb.append(t.getName().replace('.', '_')); - sb.append("_2"); - } - } - - static StringBuilder dumpJS(CharSequence sb) throws IOException { - File f = File.createTempFile("execution", ".js"); - try (FileWriter w = new FileWriter(f)) { - w.append(sb); - } - return new StringBuilder(f.getPath()); + return CompareCase.create(clazz); } } diff -r bafc670aa10d -r 3485327d3080 vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Sun Dec 23 23:30:06 2012 +0100 @@ -0,0 +1,130 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.vmtest.impl; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.WeakHashMap; +import javax.script.Invocable; +import org.apidesign.bck2brwsr.launcher.MethodInvocation; +import org.testng.ITest; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public final class Bck2BrwsrCase implements ITest { + private final Method m; + private final Launchers l; + private final int type; + Object value; + private Invocable code; + private CharSequence codeSeq; + private static final Map compiled = new WeakHashMap<>(); + private Object inst; + + Bck2BrwsrCase(Method m, int type, Launchers l) { + this.l = l; + this.m = m; + this.type = type; + } + + @Test(groups = "run") + public void executeCode() throws Throwable { + if (type == 1) { + MethodInvocation c = l.addMethod(m.getDeclaringClass(), m.getName(), false); + value = c.toString(); + } else if (type == 2) { + MethodInvocation c = l.addMethod(m.getDeclaringClass(), m.getName(), true); + value = c.toString(); + } else { + value = m.invoke(m.getDeclaringClass().newInstance()); + } + } + + @Override + public String getTestName() { + return m.getName() + "[" + typeName() + "]"; + } + + final String typeName() { + switch (type) { + case 0: + return "Java"; + case 1: + return "JavaScript"; + case 2: + return "Browser"; + default: + return "Unknown type " + type; + } + } + + private static String computeSignature(Method m) { + StringBuilder sb = new StringBuilder(); + appendType(sb, m.getReturnType()); + for (Class c : m.getParameterTypes()) { + appendType(sb, c); + } + return sb.toString(); + } + + private static void appendType(StringBuilder sb, Class t) { + if (t == null) { + sb.append('V'); + return; + } + if (t.isPrimitive()) { + int ch = -1; + if (t == int.class) { + ch = 'I'; + } + if (t == short.class) { + ch = 'S'; + } + if (t == byte.class) { + ch = 'B'; + } + if (t == boolean.class) { + ch = 'Z'; + } + if (t == long.class) { + ch = 'J'; + } + if (t == float.class) { + ch = 'F'; + } + if (t == double.class) { + ch = 'D'; + } + assert ch != -1 : "Unknown primitive type " + t; + sb.append((char) ch); + return; + } + if (t.isArray()) { + sb.append("_3"); + appendType(sb, t.getComponentType()); + return; + } + sb.append('L'); + sb.append(t.getName().replace('.', '_')); + sb.append("_2"); + } + +} diff -r bafc670aa10d -r 3485327d3080 vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Sun Dec 23 23:30:06 2012 +0100 @@ -0,0 +1,114 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.vmtest.impl; + +import org.apidesign.bck2brwsr.vmtest.*; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import org.testng.Assert; +import org.testng.ITest; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations + * in provided class and builds set of tests that compare the computations + * in real as well as JavaScript virtual machines. Use as:
+ * {@code @}{@link Factory} public static create() {
+ *   return @{link VMTest}.{@link #create(YourClass.class);
+ * }
+ * + * @author Jaroslav Tulach + */ +public final class CompareCase implements ITest { + private final Bck2BrwsrCase first, second; + private final Method m; + + private CompareCase(Method m, Bck2BrwsrCase first, Bck2BrwsrCase second) { + this.first = first; + this.second = second; + this.m = m; + } + + /** Inspects clazz and for each {@lik Compare} method creates + * instances of tests. Each instance runs the test in different virtual + * machine and at the end they compare the results. + * + * @param clazz the class to inspect + * @return the set of created tests + */ + public static Object[] create(Class clazz) { + Method[] arr = clazz.getMethods(); + List ret = new ArrayList<>(); + + final Launchers l = Launchers.INSTANCE; + + ret.add(l); + + for (Method m : arr) { + Compare c = m.getAnnotation(Compare.class); + if (c == null) { + continue; + } + final Bck2BrwsrCase real = new Bck2BrwsrCase(m, 0, null); + final Bck2BrwsrCase js = new Bck2BrwsrCase(m, 1, l); + final Bck2BrwsrCase brwsr = new Bck2BrwsrCase(m, 2, l); + + ret.add(real); + ret.add(js); + ret.add(brwsr); + + ret.add(new CompareCase(m, real, js)); + ret.add(new CompareCase(m, real, brwsr)); + } + return ret.toArray(); + } + + /** Test that compares the previous results. + * @throws Throwable + */ + @Test(dependsOnGroups = "run") public void compareResults() throws Throwable { + Object v1 = first.value; + Object v2 = second.value; + if (v1 != null) { + v1 = v1.toString(); + } else { + v1 = "null"; + } + Assert.assertEquals(v2, v1, "Comparing results"); + } + + /** Test name. + * @return name of the tested method followed by a suffix + */ + @Override + public String getTestName() { + return m.getName() + "[Compare " + second.typeName() + "]"; + } + + static StringBuilder dumpJS(CharSequence sb) throws IOException { + File f = File.createTempFile("execution", ".js"); + try (FileWriter w = new FileWriter(f)) { + w.append(sb); + } + return new StringBuilder(f.getPath()); + } +} diff -r bafc670aa10d -r 3485327d3080 vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Launchers.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Launchers.java Sun Dec 23 23:30:06 2012 +0100 @@ -0,0 +1,67 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.vmtest.impl; + +import java.io.IOException; +import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher; +import org.apidesign.bck2brwsr.launcher.JSLauncher; +import org.apidesign.bck2brwsr.launcher.MethodInvocation; +import org.apidesign.vm4brwsr.Bck2Brwsr; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.BeforeSuite; + +/** + * + * @author Jaroslav Tulach + */ +public final class Launchers { + public static final Launchers INSTANCE = new Launchers(); + + private JSLauncher jsl; + private Bck2BrwsrLauncher brwsr; + + private Launchers() { + } + + @BeforeGroups("run") + public void initializeLauncher() throws IOException { + jsl = new JSLauncher(); + jsl.addClassLoader(Bck2Brwsr.class.getClassLoader()); + jsl.initialize(); + Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(); + l.addClassLoader(Bck2Brwsr.class.getClassLoader()); + l.initialize(); + l.setTimeout(180000); + brwsr = l; + } + + @AfterGroups("run") + public void shutDownLauncher() throws IOException, InterruptedException { + brwsr.shutdown(); + } + + public MethodInvocation addMethod(Class clazz, String name, boolean inBrwsr) throws IOException { + if (!inBrwsr) { + return jsl.addMethod(clazz, name); + } else { + return brwsr.addMethod(clazz, name); + } + } +}