Execution time reported by TestNG reflect the time it took to run the query inside of a browser launcher
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 23 Dec 2012 23:30:06 +0100
branchlauncher
changeset 3723485327d3080
parent 371 bafc670aa10d
child 374 e5b4bd29f268
Execution time reported by TestNG reflect the time it took to run the query inside of a browser
launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java
vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Launcher.java
vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java
vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java
vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java
vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Launchers.java
     1.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Sun Dec 23 18:24:18 2012 +0100
     1.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Sun Dec 23 23:30:06 2012 +0100
     1.3 @@ -54,6 +54,7 @@
     1.4   */
     1.5  public class Bck2BrwsrLauncher {
     1.6      private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
     1.7 +    private static final MethodInvocation END = new MethodInvocation(null, null);
     1.8      private Set<ClassLoader> loaders = new LinkedHashSet<>();
     1.9      private BlockingQueue<MethodInvocation> methods = new LinkedBlockingQueue<>();
    1.10      private long timeOut;
    1.11 @@ -153,10 +154,11 @@
    1.12                  }
    1.13                  
    1.14                  MethodInvocation mi = methods.take();
    1.15 -                if (mi == null) {
    1.16 +                if (mi == END) {
    1.17                      response.getWriter().write("");
    1.18                      wait.countDown();
    1.19                      cnt = 0;
    1.20 +                    LOG.log(Level.INFO, "End of data reached. Exiting.");
    1.21                      return;
    1.22                  }
    1.23                  
    1.24 @@ -177,6 +179,7 @@
    1.25      }
    1.26      
    1.27      public void shutdown() throws InterruptedException, IOException {
    1.28 +        methods.offer(END);
    1.29          for (;;) {
    1.30              int prev = methods.size();
    1.31              if (wait.await(timeOut, TimeUnit.MILLISECONDS)) {
     2.1 --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java	Sun Dec 23 18:24:18 2012 +0100
     2.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java	Sun Dec 23 23:30:06 2012 +0100
     2.3 @@ -20,14 +20,16 @@
     2.4  import org.apache.maven.plugin.AbstractMojo;
     2.5  
     2.6  import java.io.File;
     2.7 -import java.io.FileWriter;
     2.8  import java.io.IOException;
     2.9  import java.net.MalformedURLException;
    2.10 +import java.net.URISyntaxException;
    2.11  import java.net.URL;
    2.12  import java.net.URLClassLoader;
    2.13  import java.util.ArrayList;
    2.14  import java.util.Collection;
    2.15  import java.util.List;
    2.16 +import java.util.logging.Level;
    2.17 +import java.util.logging.Logger;
    2.18  import org.apache.maven.artifact.Artifact;
    2.19  import org.apache.maven.plugin.MojoExecutionException;
    2.20  import org.apache.maven.plugins.annotations.LifecyclePhase;
    2.21 @@ -35,7 +37,6 @@
    2.22  import org.apache.maven.plugins.annotations.Parameter;
    2.23  import org.apache.maven.project.MavenProject;
    2.24  import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher;
    2.25 -import org.apidesign.vm4brwsr.Bck2Brwsr;
    2.26  
    2.27  /** Executes given HTML page in a browser. */
    2.28  @Mojo(name="brwsr", defaultPhase=LifecyclePhase.DEPLOY)
    2.29 @@ -63,9 +64,12 @@
    2.30              URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
    2.31              
    2.32              Bck2BrwsrLauncher httpServer = new Bck2BrwsrLauncher();
    2.33 -            httpServer.setStartPage(startpage);
    2.34              httpServer.addClassLoader(url);
    2.35 -            httpServer.execute();
    2.36 +            try {
    2.37 +                httpServer.showURL(startpage);
    2.38 +            } catch (Exception ex) {
    2.39 +                throw new MojoExecutionException("Can't open " + startpage, ex);
    2.40 +            }
    2.41              
    2.42              System.in.read();
    2.43          } catch (IOException ex) {
     3.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Launcher.java	Sun Dec 23 18:24:18 2012 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,71 +0,0 @@
     3.4 -/**
     3.5 - * Back 2 Browser Bytecode Translator
     3.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 - *
     3.8 - * This program is free software: you can redistribute it and/or modify
     3.9 - * it under the terms of the GNU General Public License as published by
    3.10 - * the Free Software Foundation, version 2 of the License.
    3.11 - *
    3.12 - * This program is distributed in the hope that it will be useful,
    3.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 - * GNU General Public License for more details.
    3.16 - *
    3.17 - * You should have received a copy of the GNU General Public License
    3.18 - * along with this program. Look for COPYING file in the top folder.
    3.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    3.20 - */
    3.21 -package org.apidesign.bck2brwsr.vmtest;
    3.22 -
    3.23 -import java.io.IOException;
    3.24 -import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher;
    3.25 -import org.apidesign.bck2brwsr.launcher.JSLauncher;
    3.26 -import org.apidesign.bck2brwsr.launcher.MethodInvocation;
    3.27 -
    3.28 -/**
    3.29 - *
    3.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.31 - */
    3.32 -final class Launcher {
    3.33 -    private final String sen;
    3.34 -    private Object launcher;
    3.35 -    
    3.36 -    Launcher() {
    3.37 -        this(null);
    3.38 -    }
    3.39 -    Launcher(String sen) {
    3.40 -        this.sen = sen;
    3.41 -    }
    3.42 -
    3.43 -    synchronized Object clear() {
    3.44 -        Object l = launcher;
    3.45 -        launcher = null;
    3.46 -        return l;
    3.47 -    }
    3.48 -
    3.49 -    synchronized MethodInvocation addMethod(Class<?> clazz, String name) throws IOException {
    3.50 -        if (launcher == null) {
    3.51 -            if (sen != null) {
    3.52 -                JSLauncher js = new JSLauncher();
    3.53 -                js.addClassLoader(clazz.getClassLoader());
    3.54 -                js.initialize();
    3.55 -                launcher = js;
    3.56 -            } else {
    3.57 -                Bck2BrwsrLauncher l = new Bck2BrwsrLauncher();
    3.58 -                l.initialize();
    3.59 -                l.setTimeout(180000);
    3.60 -                launcher = l;
    3.61 -            }
    3.62 -        }
    3.63 -        if (launcher instanceof JSLauncher) {
    3.64 -            return ((JSLauncher)launcher).addMethod(clazz, name);
    3.65 -        } else {
    3.66 -            return ((Bck2BrwsrLauncher)launcher).addMethod(clazz, name);
    3.67 -        }
    3.68 -    }
    3.69 -
    3.70 -    void exec() throws Exception {
    3.71 -        Object l = clear();
    3.72 -    }
    3.73 -    
    3.74 -}
     4.1 --- a/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java	Sun Dec 23 18:24:18 2012 +0100
     4.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java	Sun Dec 23 23:30:06 2012 +0100
     4.3 @@ -17,20 +17,8 @@
     4.4   */
     4.5  package org.apidesign.bck2brwsr.vmtest;
     4.6  
     4.7 -import java.io.File;
     4.8 -import java.io.FileWriter;
     4.9 -import java.io.IOException;
    4.10 -import java.lang.reflect.Method;
    4.11 -import java.util.Map;
    4.12 -import java.util.WeakHashMap;
    4.13 -import java.util.logging.Level;
    4.14 -import java.util.logging.Logger;
    4.15 -import javax.script.Invocable;
    4.16 -import org.apidesign.bck2brwsr.launcher.MethodInvocation;
    4.17 -import org.testng.Assert;
    4.18 -import org.testng.ITest;
    4.19 +import org.apidesign.bck2brwsr.vmtest.impl.CompareCase;
    4.20  import org.testng.annotations.Factory;
    4.21 -import org.testng.annotations.Test;
    4.22  
    4.23  /** A TestNG {@link Factory} that seeks for {@link Compare} annotations
    4.24   * in provided class and builds set of tests that compare the computations
    4.25 @@ -41,19 +29,7 @@
    4.26   *
    4.27   * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.28   */
    4.29 -public final class VMTest implements ITest {
    4.30 -    private static final Launcher JS = new Launcher("js");
    4.31 -    private static final Launcher BROWSER = new Launcher();
    4.32 -    
    4.33 -    private final Run first, second;
    4.34 -    private final Method m;
    4.35 -    
    4.36 -    private VMTest(Method m, Run first, Run second) {
    4.37 -        this.first = first;
    4.38 -        this.second = second;
    4.39 -        this.m = m;
    4.40 -    }
    4.41 -
    4.42 +public final class VMTest {
    4.43      /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
    4.44       * instances of tests. Each instance runs the test in different virtual
    4.45       * machine and at the end they compare the results.
    4.46 @@ -62,164 +38,6 @@
    4.47       * @return the set of created tests
    4.48       */
    4.49      public static Object[] create(Class<?> clazz) {
    4.50 -        Method[] arr = clazz.getMethods();
    4.51 -        Object[] ret = new Object[5 * arr.length];
    4.52 -        int cnt = 0;
    4.53 -        for (Method m : arr) {
    4.54 -            Compare c = m.getAnnotation(Compare.class);
    4.55 -            if (c == null) {
    4.56 -                continue;
    4.57 -            }
    4.58 -            final Run real = new Run(m, 0);
    4.59 -            final Run js = new Run(m, 1);
    4.60 -            final Run brwsr = new Run(m, 2);
    4.61 -            ret[cnt++] = real;
    4.62 -            ret[cnt++] = js;
    4.63 -            ret[cnt++] = brwsr;
    4.64 -            ret[cnt++] = new VMTest(m, real, js);
    4.65 -            ret[cnt++] = new VMTest(m, real, brwsr);
    4.66 -        }
    4.67 -        Object[] r = new Object[cnt];
    4.68 -        for (int i = 0; i < cnt; i++) {
    4.69 -            r[i] = ret[i];
    4.70 -        }
    4.71 -        return r;
    4.72 -    }
    4.73 -
    4.74 -    /** Test that compares the previous results.
    4.75 -     * @throws Throwable 
    4.76 -     */
    4.77 -    @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
    4.78 -        Object v1 = first.value;
    4.79 -        Object v2 = second.value;
    4.80 -        if (v1 != null) {
    4.81 -            v1 = v1.toString();
    4.82 -        } else {
    4.83 -            v1 = "null";
    4.84 -        }
    4.85 -        Assert.assertEquals(v2, v1, "Comparing results");
    4.86 -    }
    4.87 -    
    4.88 -    /** Test name.
    4.89 -     * @return name of the tested method followed by a suffix
    4.90 -     */
    4.91 -    @Override
    4.92 -    public String getTestName() {
    4.93 -        return m.getName() + "[Compare " + second.typeName() + "]";
    4.94 -    }
    4.95 -
    4.96 -    public static final class Run implements ITest {
    4.97 -        private final Method m;
    4.98 -        private final int type;
    4.99 -        Object value;
   4.100 -        private Invocable code;
   4.101 -        private CharSequence codeSeq;
   4.102 -        private static final Map<Class,Object[]> compiled = new WeakHashMap<>();
   4.103 -        private Object inst;
   4.104 -
   4.105 -        private Run(Method m, int type) {
   4.106 -            this.m = m;
   4.107 -            this.type = type;
   4.108 -            try {
   4.109 -                initialize();
   4.110 -            } catch (Throwable ex) {
   4.111 -                Logger.getLogger(VMTest.class.getName()).log(Level.SEVERE, null, ex);
   4.112 -            }
   4.113 -        }
   4.114 -
   4.115 -        private void initialize() throws Throwable {
   4.116 -            if (type == 1) {
   4.117 -                inst = JS.addMethod(m.getDeclaringClass(), m.getName());
   4.118 -            }
   4.119 -            if (type == 2) {
   4.120 -                inst = BROWSER.addMethod(m.getDeclaringClass(), m.getName());
   4.121 -            }
   4.122 -        }
   4.123 -
   4.124 -        @Test(groups = "run") public void executeCode() throws Throwable {
   4.125 -            if (type == 1) {
   4.126 -                MethodInvocation c = (MethodInvocation) inst;
   4.127 -                JS.exec();
   4.128 -                value = c.toString();
   4.129 -            } else if (type == 2) {
   4.130 -                MethodInvocation c = (MethodInvocation) inst;
   4.131 -                BROWSER.exec();
   4.132 -                value = c.toString();
   4.133 -            } else {
   4.134 -                value = m.invoke(m.getDeclaringClass().newInstance());
   4.135 -            }
   4.136 -        }
   4.137 -        @Override
   4.138 -        public String getTestName() {
   4.139 -            return m.getName() + "[" + typeName() + "]";
   4.140 -        }
   4.141 -        
   4.142 -        final String typeName() {
   4.143 -            switch (type) {
   4.144 -                case 0: return "Java";
   4.145 -                case 1: return "JavaScript";
   4.146 -                case 2: return "Browser";
   4.147 -                default: return "Unknown type " + type;
   4.148 -            }
   4.149 -        }
   4.150 -        
   4.151 -        private static String computeSignature(Method m) {
   4.152 -            StringBuilder sb = new StringBuilder();
   4.153 -            appendType(sb, m.getReturnType());
   4.154 -            for (Class<?> c : m.getParameterTypes()) {
   4.155 -                appendType(sb, c);
   4.156 -            }
   4.157 -            return sb.toString();
   4.158 -        }
   4.159 -        
   4.160 -        private static void appendType(StringBuilder sb, Class<?> t) {
   4.161 -            if (t == null) {
   4.162 -                sb.append('V');
   4.163 -                return;
   4.164 -            }
   4.165 -            if (t.isPrimitive()) {
   4.166 -                int ch = -1;
   4.167 -                if (t == int.class) {
   4.168 -                    ch = 'I';
   4.169 -                }
   4.170 -                if (t == short.class) {
   4.171 -                    ch = 'S';
   4.172 -                }
   4.173 -                if (t == byte.class) {
   4.174 -                    ch = 'B';
   4.175 -                }
   4.176 -                if (t == boolean.class) {
   4.177 -                    ch = 'Z';
   4.178 -                }
   4.179 -                if (t == long.class) {
   4.180 -                    ch = 'J';
   4.181 -                }
   4.182 -                if (t == float.class) {
   4.183 -                    ch = 'F';
   4.184 -                }
   4.185 -                if (t == double.class) {
   4.186 -                    ch = 'D';
   4.187 -                }
   4.188 -                assert ch != -1 : "Unknown primitive type " + t;
   4.189 -                sb.append((char)ch);
   4.190 -                return;
   4.191 -            }
   4.192 -            if (t.isArray()) {
   4.193 -                sb.append("_3");
   4.194 -                appendType(sb, t.getComponentType());
   4.195 -                return;
   4.196 -            }
   4.197 -            sb.append('L');
   4.198 -            sb.append(t.getName().replace('.', '_'));
   4.199 -            sb.append("_2");
   4.200 -        }
   4.201 -    }
   4.202 -    
   4.203 -    static StringBuilder dumpJS(CharSequence sb) throws IOException {
   4.204 -        File f = File.createTempFile("execution", ".js");
   4.205 -        try (FileWriter w = new FileWriter(f)) {
   4.206 -            w.append(sb);
   4.207 -        }
   4.208 -        return new StringBuilder(f.getPath());
   4.209 +        return CompareCase.create(clazz);
   4.210      }
   4.211  }
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Sun Dec 23 23:30:06 2012 +0100
     5.3 @@ -0,0 +1,130 @@
     5.4 +/**
     5.5 + * Back 2 Browser Bytecode Translator
     5.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 + *
     5.8 + * This program is free software: you can redistribute it and/or modify
     5.9 + * it under the terms of the GNU General Public License as published by
    5.10 + * the Free Software Foundation, version 2 of the License.
    5.11 + *
    5.12 + * This program is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU General Public License
    5.18 + * along with this program. Look for COPYING file in the top folder.
    5.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    5.20 + */
    5.21 +package org.apidesign.bck2brwsr.vmtest.impl;
    5.22 +
    5.23 +import java.lang.reflect.Method;
    5.24 +import java.util.Map;
    5.25 +import java.util.WeakHashMap;
    5.26 +import javax.script.Invocable;
    5.27 +import org.apidesign.bck2brwsr.launcher.MethodInvocation;
    5.28 +import org.testng.ITest;
    5.29 +import org.testng.annotations.Test;
    5.30 +
    5.31 +/**
    5.32 + *
    5.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.34 + */
    5.35 +public final class Bck2BrwsrCase implements ITest {
    5.36 +    private final Method m;
    5.37 +    private final Launchers l;
    5.38 +    private final int type;
    5.39 +    Object value;
    5.40 +    private Invocable code;
    5.41 +    private CharSequence codeSeq;
    5.42 +    private static final Map<Class, Object[]> compiled = new WeakHashMap<>();
    5.43 +    private Object inst;
    5.44 +
    5.45 +    Bck2BrwsrCase(Method m, int type, Launchers l) {
    5.46 +        this.l = l;
    5.47 +        this.m = m;
    5.48 +        this.type = type;
    5.49 +    }
    5.50 +
    5.51 +    @Test(groups = "run")
    5.52 +    public void executeCode() throws Throwable {
    5.53 +        if (type == 1) {
    5.54 +            MethodInvocation c = l.addMethod(m.getDeclaringClass(), m.getName(), false);
    5.55 +            value = c.toString();
    5.56 +        } else if (type == 2) {
    5.57 +            MethodInvocation c = l.addMethod(m.getDeclaringClass(), m.getName(), true);
    5.58 +            value = c.toString();
    5.59 +        } else {
    5.60 +            value = m.invoke(m.getDeclaringClass().newInstance());
    5.61 +        }
    5.62 +    }
    5.63 +
    5.64 +    @Override
    5.65 +    public String getTestName() {
    5.66 +        return m.getName() + "[" + typeName() + "]";
    5.67 +    }
    5.68 +
    5.69 +    final String typeName() {
    5.70 +        switch (type) {
    5.71 +            case 0:
    5.72 +                return "Java";
    5.73 +            case 1:
    5.74 +                return "JavaScript";
    5.75 +            case 2:
    5.76 +                return "Browser";
    5.77 +            default:
    5.78 +                return "Unknown type " + type;
    5.79 +        }
    5.80 +    }
    5.81 +
    5.82 +    private static String computeSignature(Method m) {
    5.83 +        StringBuilder sb = new StringBuilder();
    5.84 +        appendType(sb, m.getReturnType());
    5.85 +        for (Class<?> c : m.getParameterTypes()) {
    5.86 +            appendType(sb, c);
    5.87 +        }
    5.88 +        return sb.toString();
    5.89 +    }
    5.90 +
    5.91 +    private static void appendType(StringBuilder sb, Class<?> t) {
    5.92 +        if (t == null) {
    5.93 +            sb.append('V');
    5.94 +            return;
    5.95 +        }
    5.96 +        if (t.isPrimitive()) {
    5.97 +            int ch = -1;
    5.98 +            if (t == int.class) {
    5.99 +                ch = 'I';
   5.100 +            }
   5.101 +            if (t == short.class) {
   5.102 +                ch = 'S';
   5.103 +            }
   5.104 +            if (t == byte.class) {
   5.105 +                ch = 'B';
   5.106 +            }
   5.107 +            if (t == boolean.class) {
   5.108 +                ch = 'Z';
   5.109 +            }
   5.110 +            if (t == long.class) {
   5.111 +                ch = 'J';
   5.112 +            }
   5.113 +            if (t == float.class) {
   5.114 +                ch = 'F';
   5.115 +            }
   5.116 +            if (t == double.class) {
   5.117 +                ch = 'D';
   5.118 +            }
   5.119 +            assert ch != -1 : "Unknown primitive type " + t;
   5.120 +            sb.append((char) ch);
   5.121 +            return;
   5.122 +        }
   5.123 +        if (t.isArray()) {
   5.124 +            sb.append("_3");
   5.125 +            appendType(sb, t.getComponentType());
   5.126 +            return;
   5.127 +        }
   5.128 +        sb.append('L');
   5.129 +        sb.append(t.getName().replace('.', '_'));
   5.130 +        sb.append("_2");
   5.131 +    }
   5.132 +    
   5.133 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Sun Dec 23 23:30:06 2012 +0100
     6.3 @@ -0,0 +1,114 @@
     6.4 +/**
     6.5 + * Back 2 Browser Bytecode Translator
     6.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 + *
     6.8 + * This program is free software: you can redistribute it and/or modify
     6.9 + * it under the terms of the GNU General Public License as published by
    6.10 + * the Free Software Foundation, version 2 of the License.
    6.11 + *
    6.12 + * This program is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 + * GNU General Public License for more details.
    6.16 + *
    6.17 + * You should have received a copy of the GNU General Public License
    6.18 + * along with this program. Look for COPYING file in the top folder.
    6.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    6.20 + */
    6.21 +package org.apidesign.bck2brwsr.vmtest.impl;
    6.22 +
    6.23 +import org.apidesign.bck2brwsr.vmtest.*;
    6.24 +import java.io.File;
    6.25 +import java.io.FileWriter;
    6.26 +import java.io.IOException;
    6.27 +import java.lang.reflect.Method;
    6.28 +import java.util.ArrayList;
    6.29 +import java.util.List;
    6.30 +import org.testng.Assert;
    6.31 +import org.testng.ITest;
    6.32 +import org.testng.annotations.Factory;
    6.33 +import org.testng.annotations.Test;
    6.34 +
    6.35 +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
    6.36 + * in provided class and builds set of tests that compare the computations
    6.37 + * in real as well as JavaScript virtual machines. Use as:<pre>
    6.38 + * {@code @}{@link Factory} public static create() {
    6.39 + *   return @{link VMTest}.{@link #create(YourClass.class);
    6.40 + * }</pre>
    6.41 + *
    6.42 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    6.43 + */
    6.44 +public final class CompareCase implements ITest {
    6.45 +    private final Bck2BrwsrCase first, second;
    6.46 +    private final Method m;
    6.47 +    
    6.48 +    private CompareCase(Method m, Bck2BrwsrCase first, Bck2BrwsrCase second) {
    6.49 +        this.first = first;
    6.50 +        this.second = second;
    6.51 +        this.m = m;
    6.52 +    }
    6.53 +
    6.54 +    /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
    6.55 +     * instances of tests. Each instance runs the test in different virtual
    6.56 +     * machine and at the end they compare the results.
    6.57 +     * 
    6.58 +     * @param clazz the class to inspect
    6.59 +     * @return the set of created tests
    6.60 +     */
    6.61 +    public static Object[] create(Class<?> clazz) {
    6.62 +        Method[] arr = clazz.getMethods();
    6.63 +        List<Object> ret = new ArrayList<>();
    6.64 +        
    6.65 +        final Launchers l = Launchers.INSTANCE;
    6.66 +    
    6.67 +        ret.add(l);
    6.68 +        
    6.69 +        for (Method m : arr) {
    6.70 +            Compare c = m.getAnnotation(Compare.class);
    6.71 +            if (c == null) {
    6.72 +                continue;
    6.73 +            }
    6.74 +            final Bck2BrwsrCase real = new Bck2BrwsrCase(m, 0, null);
    6.75 +            final Bck2BrwsrCase js = new Bck2BrwsrCase(m, 1, l);
    6.76 +            final Bck2BrwsrCase brwsr = new Bck2BrwsrCase(m, 2, l);
    6.77 +            
    6.78 +            ret.add(real);
    6.79 +            ret.add(js);
    6.80 +            ret.add(brwsr);
    6.81 +            
    6.82 +            ret.add(new CompareCase(m, real, js));
    6.83 +            ret.add(new CompareCase(m, real, brwsr));
    6.84 +        }
    6.85 +        return ret.toArray();
    6.86 +    }
    6.87 +
    6.88 +    /** Test that compares the previous results.
    6.89 +     * @throws Throwable 
    6.90 +     */
    6.91 +    @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
    6.92 +        Object v1 = first.value;
    6.93 +        Object v2 = second.value;
    6.94 +        if (v1 != null) {
    6.95 +            v1 = v1.toString();
    6.96 +        } else {
    6.97 +            v1 = "null";
    6.98 +        }
    6.99 +        Assert.assertEquals(v2, v1, "Comparing results");
   6.100 +    }
   6.101 +    
   6.102 +    /** Test name.
   6.103 +     * @return name of the tested method followed by a suffix
   6.104 +     */
   6.105 +    @Override
   6.106 +    public String getTestName() {
   6.107 +        return m.getName() + "[Compare " + second.typeName() + "]";
   6.108 +    }
   6.109 +    
   6.110 +    static StringBuilder dumpJS(CharSequence sb) throws IOException {
   6.111 +        File f = File.createTempFile("execution", ".js");
   6.112 +        try (FileWriter w = new FileWriter(f)) {
   6.113 +            w.append(sb);
   6.114 +        }
   6.115 +        return new StringBuilder(f.getPath());
   6.116 +    }
   6.117 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Launchers.java	Sun Dec 23 23:30:06 2012 +0100
     7.3 @@ -0,0 +1,67 @@
     7.4 +/**
     7.5 + * Back 2 Browser Bytecode Translator
     7.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.7 + *
     7.8 + * This program is free software: you can redistribute it and/or modify
     7.9 + * it under the terms of the GNU General Public License as published by
    7.10 + * the Free Software Foundation, version 2 of the License.
    7.11 + *
    7.12 + * This program is distributed in the hope that it will be useful,
    7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 + * GNU General Public License for more details.
    7.16 + *
    7.17 + * You should have received a copy of the GNU General Public License
    7.18 + * along with this program. Look for COPYING file in the top folder.
    7.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    7.20 + */
    7.21 +package org.apidesign.bck2brwsr.vmtest.impl;
    7.22 +
    7.23 +import java.io.IOException;
    7.24 +import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher;
    7.25 +import org.apidesign.bck2brwsr.launcher.JSLauncher;
    7.26 +import org.apidesign.bck2brwsr.launcher.MethodInvocation;
    7.27 +import org.apidesign.vm4brwsr.Bck2Brwsr;
    7.28 +import org.testng.annotations.AfterGroups;
    7.29 +import org.testng.annotations.AfterSuite;
    7.30 +import org.testng.annotations.BeforeGroups;
    7.31 +import org.testng.annotations.BeforeSuite;
    7.32 +
    7.33 +/**
    7.34 + *
    7.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    7.36 + */
    7.37 +public final class Launchers {
    7.38 +    public static final Launchers INSTANCE = new Launchers();
    7.39 +    
    7.40 +    private JSLauncher jsl;
    7.41 +    private Bck2BrwsrLauncher brwsr;
    7.42 +    
    7.43 +    private Launchers() {
    7.44 +    }
    7.45 +
    7.46 +    @BeforeGroups("run")
    7.47 +    public void initializeLauncher() throws IOException {
    7.48 +        jsl = new JSLauncher();
    7.49 +        jsl.addClassLoader(Bck2Brwsr.class.getClassLoader());
    7.50 +        jsl.initialize();
    7.51 +        Bck2BrwsrLauncher l = new Bck2BrwsrLauncher();
    7.52 +        l.addClassLoader(Bck2Brwsr.class.getClassLoader());
    7.53 +        l.initialize();
    7.54 +        l.setTimeout(180000);
    7.55 +        brwsr = l;
    7.56 +    }
    7.57 +
    7.58 +    @AfterGroups("run")
    7.59 +    public void shutDownLauncher() throws IOException, InterruptedException {
    7.60 +        brwsr.shutdown();
    7.61 +    }
    7.62 +
    7.63 +    public MethodInvocation addMethod(Class<?> clazz, String name, boolean inBrwsr) throws IOException {
    7.64 +        if (!inBrwsr) {
    7.65 +            return jsl.addMethod(clazz, name);
    7.66 +        } else {
    7.67 +            return brwsr.addMethod(clazz, name);
    7.68 +        }
    7.69 +    }
    7.70 +}