diff -r 4adbde04e899 -r b671ac44bc55 vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java Mon Dec 17 12:21:05 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +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.vm4brwsr; - -import java.lang.reflect.Method; -import java.util.Map; -import java.util.WeakHashMap; -import javax.script.Invocable; -import javax.script.ScriptContext; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -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 CompareVMs}.{@link #create(YourClass.class);
- * }
- * - * @author Jaroslav Tulach - */ -public final class CompareVMs implements ITest { - private final Run first, second; - private final Method m; - - private CompareVMs(Method m, Run first, Run second) { - this.first = first; - this.second = second; - this.m = m; - } - - public static Object[] create(Class clazz) { - Method[] arr = clazz.getMethods(); - Object[] ret = new Object[3 * 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, false); - final Run js = new Run(m, true); - ret[cnt++] = real; - ret[cnt++] = js; - ret[cnt++] = new CompareVMs(m, real, js); - } - Object[] r = new Object[cnt]; - for (int i = 0; i < cnt; i++) { - r[i] = ret[i]; - } - return r; - } - - @Test(dependsOnGroups = "run") public void compareResults() throws Throwable { - Object v1 = first.value; - Object v2 = second.value; - if (v1 instanceof Number) { - v1 = ((Number)v1).doubleValue(); - } - Assert.assertEquals(v2, v1, "Comparing results"); - } - - @Override - public String getTestName() { - return m.getName() + "[Compare]"; - } - - public static final class Run implements ITest { - private final Method m; - private final boolean js; - Object value; - private Invocable code; - private CharSequence codeSeq; - private static final Map compiled = new WeakHashMap(); - - private Run(Method m, boolean js) { - this.m = m; - this.js = js; - } - - private void compileTheCode(Class clazz) throws Exception { - final Object[] data = compiled.get(clazz); - if (data != null) { - code = (Invocable) data[0]; - codeSeq = (CharSequence) data[1]; - return; - } - StringBuilder sb = new StringBuilder(); - Bck2Brwsr.generate(sb, CompareVMs.class.getClassLoader()); - - ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine js = sem.getEngineByExtension("js"); - js.getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE); - - sb.append("\nfunction initVM() {" - + "\n return bck2brwsr(" - + "\n function(name) { return loader.get(name);}" - + "\n );" - + "\n};"); - - Object res = js.eval(sb.toString()); - Assert.assertTrue(js instanceof Invocable, "It is invocable object: " + res); - code = (Invocable) js; - codeSeq = sb; - compiled.put(clazz, new Object[] { code, codeSeq }); - } - - @Test(groups = "run") public void executeCode() throws Throwable { - if (js) { - try { - compileTheCode(m.getDeclaringClass()); - Object vm = code.invokeFunction("initVM"); - Object inst = code.invokeMethod(vm, "loadClass", m.getDeclaringClass().getName()); - value = code.invokeMethod(inst, m.getName() + "__" + computeSignature(m)); - } catch (Exception ex) { - throw new AssertionError(StaticMethodTest.dumpJS(codeSeq)).initCause(ex); - } - } else { - value = m.invoke(m.getDeclaringClass().newInstance()); - } - } - @Override - public String getTestName() { - return m.getName() + (js ? "[JavaScript]" : "[Java]"); - } - - 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"); - } - } -}