1.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java Mon Dec 17 12:21:05 2012 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,197 +0,0 @@
1.4 -/**
1.5 - * Back 2 Browser Bytecode Translator
1.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
1.7 - *
1.8 - * This program is free software: you can redistribute it and/or modify
1.9 - * it under the terms of the GNU General Public License as published by
1.10 - * the Free Software Foundation, version 2 of the License.
1.11 - *
1.12 - * This program is distributed in the hope that it will be useful,
1.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 - * GNU General Public License for more details.
1.16 - *
1.17 - * You should have received a copy of the GNU General Public License
1.18 - * along with this program. Look for COPYING file in the top folder.
1.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
1.20 - */
1.21 -package org.apidesign.vm4brwsr;
1.22 -
1.23 -import java.lang.reflect.Method;
1.24 -import java.util.Map;
1.25 -import java.util.WeakHashMap;
1.26 -import javax.script.Invocable;
1.27 -import javax.script.ScriptContext;
1.28 -import javax.script.ScriptEngine;
1.29 -import javax.script.ScriptEngineManager;
1.30 -import org.testng.Assert;
1.31 -import org.testng.ITest;
1.32 -import org.testng.annotations.Factory;
1.33 -import org.testng.annotations.Test;
1.34 -
1.35 -/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
1.36 - * in provided class and builds set of tests that compare the computations
1.37 - * in real as well as JavaScript virtual machines. Use as:<pre>
1.38 - * {@code @}{@link Factory} public static create() {
1.39 - * return @{link CompareVMs}.{@link #create(YourClass.class);
1.40 - * }</pre>
1.41 - *
1.42 - * @author Jaroslav Tulach <jtulach@netbeans.org>
1.43 - */
1.44 -public final class CompareVMs implements ITest {
1.45 - private final Run first, second;
1.46 - private final Method m;
1.47 -
1.48 - private CompareVMs(Method m, Run first, Run second) {
1.49 - this.first = first;
1.50 - this.second = second;
1.51 - this.m = m;
1.52 - }
1.53 -
1.54 - public static Object[] create(Class<?> clazz) {
1.55 - Method[] arr = clazz.getMethods();
1.56 - Object[] ret = new Object[3 * arr.length];
1.57 - int cnt = 0;
1.58 - for (Method m : arr) {
1.59 - Compare c = m.getAnnotation(Compare.class);
1.60 - if (c == null) {
1.61 - continue;
1.62 - }
1.63 - final Run real = new Run(m, false);
1.64 - final Run js = new Run(m, true);
1.65 - ret[cnt++] = real;
1.66 - ret[cnt++] = js;
1.67 - ret[cnt++] = new CompareVMs(m, real, js);
1.68 - }
1.69 - Object[] r = new Object[cnt];
1.70 - for (int i = 0; i < cnt; i++) {
1.71 - r[i] = ret[i];
1.72 - }
1.73 - return r;
1.74 - }
1.75 -
1.76 - @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
1.77 - Object v1 = first.value;
1.78 - Object v2 = second.value;
1.79 - if (v1 instanceof Number) {
1.80 - v1 = ((Number)v1).doubleValue();
1.81 - }
1.82 - Assert.assertEquals(v2, v1, "Comparing results");
1.83 - }
1.84 -
1.85 - @Override
1.86 - public String getTestName() {
1.87 - return m.getName() + "[Compare]";
1.88 - }
1.89 -
1.90 - public static final class Run implements ITest {
1.91 - private final Method m;
1.92 - private final boolean js;
1.93 - Object value;
1.94 - private Invocable code;
1.95 - private CharSequence codeSeq;
1.96 - private static final Map<Class,Object[]> compiled = new WeakHashMap<Class,Object[]>();
1.97 -
1.98 - private Run(Method m, boolean js) {
1.99 - this.m = m;
1.100 - this.js = js;
1.101 - }
1.102 -
1.103 - private void compileTheCode(Class<?> clazz) throws Exception {
1.104 - final Object[] data = compiled.get(clazz);
1.105 - if (data != null) {
1.106 - code = (Invocable) data[0];
1.107 - codeSeq = (CharSequence) data[1];
1.108 - return;
1.109 - }
1.110 - StringBuilder sb = new StringBuilder();
1.111 - Bck2Brwsr.generate(sb, CompareVMs.class.getClassLoader());
1.112 -
1.113 - ScriptEngineManager sem = new ScriptEngineManager();
1.114 - ScriptEngine js = sem.getEngineByExtension("js");
1.115 - js.getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
1.116 -
1.117 - sb.append("\nfunction initVM() {"
1.118 - + "\n return bck2brwsr("
1.119 - + "\n function(name) { return loader.get(name);}"
1.120 - + "\n );"
1.121 - + "\n};");
1.122 -
1.123 - Object res = js.eval(sb.toString());
1.124 - Assert.assertTrue(js instanceof Invocable, "It is invocable object: " + res);
1.125 - code = (Invocable) js;
1.126 - codeSeq = sb;
1.127 - compiled.put(clazz, new Object[] { code, codeSeq });
1.128 - }
1.129 -
1.130 - @Test(groups = "run") public void executeCode() throws Throwable {
1.131 - if (js) {
1.132 - try {
1.133 - compileTheCode(m.getDeclaringClass());
1.134 - Object vm = code.invokeFunction("initVM");
1.135 - Object inst = code.invokeMethod(vm, "loadClass", m.getDeclaringClass().getName());
1.136 - value = code.invokeMethod(inst, m.getName() + "__" + computeSignature(m));
1.137 - } catch (Exception ex) {
1.138 - throw new AssertionError(StaticMethodTest.dumpJS(codeSeq)).initCause(ex);
1.139 - }
1.140 - } else {
1.141 - value = m.invoke(m.getDeclaringClass().newInstance());
1.142 - }
1.143 - }
1.144 - @Override
1.145 - public String getTestName() {
1.146 - return m.getName() + (js ? "[JavaScript]" : "[Java]");
1.147 - }
1.148 -
1.149 - private static String computeSignature(Method m) {
1.150 - StringBuilder sb = new StringBuilder();
1.151 - appendType(sb, m.getReturnType());
1.152 - for (Class<?> c : m.getParameterTypes()) {
1.153 - appendType(sb, c);
1.154 - }
1.155 - return sb.toString();
1.156 - }
1.157 -
1.158 - private static void appendType(StringBuilder sb, Class<?> t) {
1.159 - if (t == null) {
1.160 - sb.append('V');
1.161 - return;
1.162 - }
1.163 - if (t.isPrimitive()) {
1.164 - int ch = -1;
1.165 - if (t == int.class) {
1.166 - ch = 'I';
1.167 - }
1.168 - if (t == short.class) {
1.169 - ch = 'S';
1.170 - }
1.171 - if (t == byte.class) {
1.172 - ch = 'B';
1.173 - }
1.174 - if (t == boolean.class) {
1.175 - ch = 'Z';
1.176 - }
1.177 - if (t == long.class) {
1.178 - ch = 'J';
1.179 - }
1.180 - if (t == float.class) {
1.181 - ch = 'F';
1.182 - }
1.183 - if (t == double.class) {
1.184 - ch = 'D';
1.185 - }
1.186 - assert ch != -1 : "Unknown primitive type " + t;
1.187 - sb.append((char)ch);
1.188 - return;
1.189 - }
1.190 - if (t.isArray()) {
1.191 - sb.append("_3");
1.192 - appendType(sb, t.getComponentType());
1.193 - return;
1.194 - }
1.195 - sb.append('L');
1.196 - sb.append(t.getName().replace('.', '_'));
1.197 - sb.append("_2");
1.198 - }
1.199 - }
1.200 -}