1.1 --- a/pom.xml Mon Dec 17 12:21:05 2012 +0100
1.2 +++ b/pom.xml Mon Dec 17 17:45:08 2012 +0100
1.3 @@ -15,6 +15,7 @@
1.4 <module>javap</module>
1.5 <module>benchmarks</module>
1.6 <module>launcher</module>
1.7 + <module>vmtest</module>
1.8 </modules>
1.9 <licenses>
1.10 <license>
1.11 @@ -109,5 +110,4 @@
1.12 <properties>
1.13 <license>COPYING</license>
1.14 </properties>
1.15 -</project>
1.16 -
1.17 +</project>
1.18 \ No newline at end of file
2.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Compare.java Mon Dec 17 12:21:05 2012 +0100
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,36 +0,0 @@
2.4 -/**
2.5 - * Back 2 Browser Bytecode Translator
2.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.7 - *
2.8 - * This program is free software: you can redistribute it and/or modify
2.9 - * it under the terms of the GNU General Public License as published by
2.10 - * the Free Software Foundation, version 2 of the License.
2.11 - *
2.12 - * This program is distributed in the hope that it will be useful,
2.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 - * GNU General Public License for more details.
2.16 - *
2.17 - * You should have received a copy of the GNU General Public License
2.18 - * along with this program. Look for COPYING file in the top folder.
2.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
2.20 - */
2.21 -package org.apidesign.vm4brwsr;
2.22 -
2.23 -import java.lang.annotation.ElementType;
2.24 -import java.lang.annotation.Retention;
2.25 -import java.lang.annotation.RetentionPolicy;
2.26 -import java.lang.annotation.Target;
2.27 -
2.28 -/** Can be applied on a method that yields a return value.
2.29 - * Together with {@link VMCompare#create} it can be used to write
2.30 - * methods which are executed in real as well as JavaScript VMs and
2.31 - * their results are compared.
2.32 - *
2.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
2.34 - */
2.35 -@Retention(RetentionPolicy.RUNTIME)
2.36 -@Target(ElementType.METHOD)
2.37 -public @interface Compare {
2.38 -
2.39 -}
3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java Mon Dec 17 12:21:05 2012 +0100
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,197 +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.vm4brwsr;
3.22 -
3.23 -import java.lang.reflect.Method;
3.24 -import java.util.Map;
3.25 -import java.util.WeakHashMap;
3.26 -import javax.script.Invocable;
3.27 -import javax.script.ScriptContext;
3.28 -import javax.script.ScriptEngine;
3.29 -import javax.script.ScriptEngineManager;
3.30 -import org.testng.Assert;
3.31 -import org.testng.ITest;
3.32 -import org.testng.annotations.Factory;
3.33 -import org.testng.annotations.Test;
3.34 -
3.35 -/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
3.36 - * in provided class and builds set of tests that compare the computations
3.37 - * in real as well as JavaScript virtual machines. Use as:<pre>
3.38 - * {@code @}{@link Factory} public static create() {
3.39 - * return @{link CompareVMs}.{@link #create(YourClass.class);
3.40 - * }</pre>
3.41 - *
3.42 - * @author Jaroslav Tulach <jtulach@netbeans.org>
3.43 - */
3.44 -public final class CompareVMs implements ITest {
3.45 - private final Run first, second;
3.46 - private final Method m;
3.47 -
3.48 - private CompareVMs(Method m, Run first, Run second) {
3.49 - this.first = first;
3.50 - this.second = second;
3.51 - this.m = m;
3.52 - }
3.53 -
3.54 - public static Object[] create(Class<?> clazz) {
3.55 - Method[] arr = clazz.getMethods();
3.56 - Object[] ret = new Object[3 * arr.length];
3.57 - int cnt = 0;
3.58 - for (Method m : arr) {
3.59 - Compare c = m.getAnnotation(Compare.class);
3.60 - if (c == null) {
3.61 - continue;
3.62 - }
3.63 - final Run real = new Run(m, false);
3.64 - final Run js = new Run(m, true);
3.65 - ret[cnt++] = real;
3.66 - ret[cnt++] = js;
3.67 - ret[cnt++] = new CompareVMs(m, real, js);
3.68 - }
3.69 - Object[] r = new Object[cnt];
3.70 - for (int i = 0; i < cnt; i++) {
3.71 - r[i] = ret[i];
3.72 - }
3.73 - return r;
3.74 - }
3.75 -
3.76 - @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
3.77 - Object v1 = first.value;
3.78 - Object v2 = second.value;
3.79 - if (v1 instanceof Number) {
3.80 - v1 = ((Number)v1).doubleValue();
3.81 - }
3.82 - Assert.assertEquals(v2, v1, "Comparing results");
3.83 - }
3.84 -
3.85 - @Override
3.86 - public String getTestName() {
3.87 - return m.getName() + "[Compare]";
3.88 - }
3.89 -
3.90 - public static final class Run implements ITest {
3.91 - private final Method m;
3.92 - private final boolean js;
3.93 - Object value;
3.94 - private Invocable code;
3.95 - private CharSequence codeSeq;
3.96 - private static final Map<Class,Object[]> compiled = new WeakHashMap<Class,Object[]>();
3.97 -
3.98 - private Run(Method m, boolean js) {
3.99 - this.m = m;
3.100 - this.js = js;
3.101 - }
3.102 -
3.103 - private void compileTheCode(Class<?> clazz) throws Exception {
3.104 - final Object[] data = compiled.get(clazz);
3.105 - if (data != null) {
3.106 - code = (Invocable) data[0];
3.107 - codeSeq = (CharSequence) data[1];
3.108 - return;
3.109 - }
3.110 - StringBuilder sb = new StringBuilder();
3.111 - Bck2Brwsr.generate(sb, CompareVMs.class.getClassLoader());
3.112 -
3.113 - ScriptEngineManager sem = new ScriptEngineManager();
3.114 - ScriptEngine js = sem.getEngineByExtension("js");
3.115 - js.getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
3.116 -
3.117 - sb.append("\nfunction initVM() {"
3.118 - + "\n return bck2brwsr("
3.119 - + "\n function(name) { return loader.get(name);}"
3.120 - + "\n );"
3.121 - + "\n};");
3.122 -
3.123 - Object res = js.eval(sb.toString());
3.124 - Assert.assertTrue(js instanceof Invocable, "It is invocable object: " + res);
3.125 - code = (Invocable) js;
3.126 - codeSeq = sb;
3.127 - compiled.put(clazz, new Object[] { code, codeSeq });
3.128 - }
3.129 -
3.130 - @Test(groups = "run") public void executeCode() throws Throwable {
3.131 - if (js) {
3.132 - try {
3.133 - compileTheCode(m.getDeclaringClass());
3.134 - Object vm = code.invokeFunction("initVM");
3.135 - Object inst = code.invokeMethod(vm, "loadClass", m.getDeclaringClass().getName());
3.136 - value = code.invokeMethod(inst, m.getName() + "__" + computeSignature(m));
3.137 - } catch (Exception ex) {
3.138 - throw new AssertionError(StaticMethodTest.dumpJS(codeSeq)).initCause(ex);
3.139 - }
3.140 - } else {
3.141 - value = m.invoke(m.getDeclaringClass().newInstance());
3.142 - }
3.143 - }
3.144 - @Override
3.145 - public String getTestName() {
3.146 - return m.getName() + (js ? "[JavaScript]" : "[Java]");
3.147 - }
3.148 -
3.149 - private static String computeSignature(Method m) {
3.150 - StringBuilder sb = new StringBuilder();
3.151 - appendType(sb, m.getReturnType());
3.152 - for (Class<?> c : m.getParameterTypes()) {
3.153 - appendType(sb, c);
3.154 - }
3.155 - return sb.toString();
3.156 - }
3.157 -
3.158 - private static void appendType(StringBuilder sb, Class<?> t) {
3.159 - if (t == null) {
3.160 - sb.append('V');
3.161 - return;
3.162 - }
3.163 - if (t.isPrimitive()) {
3.164 - int ch = -1;
3.165 - if (t == int.class) {
3.166 - ch = 'I';
3.167 - }
3.168 - if (t == short.class) {
3.169 - ch = 'S';
3.170 - }
3.171 - if (t == byte.class) {
3.172 - ch = 'B';
3.173 - }
3.174 - if (t == boolean.class) {
3.175 - ch = 'Z';
3.176 - }
3.177 - if (t == long.class) {
3.178 - ch = 'J';
3.179 - }
3.180 - if (t == float.class) {
3.181 - ch = 'F';
3.182 - }
3.183 - if (t == double.class) {
3.184 - ch = 'D';
3.185 - }
3.186 - assert ch != -1 : "Unknown primitive type " + t;
3.187 - sb.append((char)ch);
3.188 - return;
3.189 - }
3.190 - if (t.isArray()) {
3.191 - sb.append("_3");
3.192 - appendType(sb, t.getComponentType());
3.193 - return;
3.194 - }
3.195 - sb.append('L');
3.196 - sb.append(t.getName().replace('.', '_'));
3.197 - sb.append("_2");
3.198 - }
3.199 - }
3.200 -}
4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareHashTest.java Mon Dec 17 12:21:05 2012 +0100
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,42 +0,0 @@
4.4 -/**
4.5 - * Back 2 Browser Bytecode Translator
4.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
4.7 - *
4.8 - * This program is free software: you can redistribute it and/or modify
4.9 - * it under the terms of the GNU General Public License as published by
4.10 - * the Free Software Foundation, version 2 of the License.
4.11 - *
4.12 - * This program is distributed in the hope that it will be useful,
4.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.15 - * GNU General Public License for more details.
4.16 - *
4.17 - * You should have received a copy of the GNU General Public License
4.18 - * along with this program. Look for COPYING file in the top folder.
4.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
4.20 - */
4.21 -package org.apidesign.vm4brwsr.tck;
4.22 -
4.23 -import org.apidesign.vm4brwsr.Compare;
4.24 -import org.apidesign.vm4brwsr.CompareVMs;
4.25 -import org.testng.annotations.Factory;
4.26 -
4.27 -/**
4.28 - *
4.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
4.30 - */
4.31 -public class CompareHashTest {
4.32 - @Compare public int hashOfString() {
4.33 - return "Ahoj".hashCode();
4.34 - }
4.35 -
4.36 - @Compare public int hashRemainsYieldsZero() {
4.37 - Object o = new Object();
4.38 - return o.hashCode() - o.hashCode();
4.39 - }
4.40 -
4.41 - @Factory
4.42 - public static Object[] create() {
4.43 - return CompareVMs.create(CompareHashTest.class);
4.44 - }
4.45 -}
5.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareStringsTest.java Mon Dec 17 12:21:05 2012 +0100
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,110 +0,0 @@
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.vm4brwsr.tck;
5.22 -
5.23 -import java.net.MalformedURLException;
5.24 -import java.net.URL;
5.25 -import org.apidesign.vm4brwsr.Compare;
5.26 -import org.apidesign.vm4brwsr.CompareVMs;
5.27 -import org.testng.annotations.Factory;
5.28 -
5.29 -/**
5.30 - *
5.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
5.32 - */
5.33 -public class CompareStringsTest {
5.34 - @Compare public static Object compareURLs() throws MalformedURLException {
5.35 - return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
5.36 - }
5.37 -
5.38 - @Compare public String deleteLastTwoCharacters() {
5.39 - StringBuilder sb = new StringBuilder();
5.40 - sb.append("453.0");
5.41 - if (sb.toString().endsWith(".0")) {
5.42 - final int l = sb.length();
5.43 - sb.delete(l - 2, l);
5.44 - }
5.45 - return sb.toString().toString();
5.46 - }
5.47 -
5.48 - @Compare public String nameOfStringClass() throws Exception {
5.49 - return Class.forName("java.lang.String").getName();
5.50 - }
5.51 - @Compare public String nameOfArrayClass() throws Exception {
5.52 - return Class.forName("org.apidesign.vm4brwsr.Array").getName();
5.53 - }
5.54 -
5.55 - @Compare public String lowerHello() {
5.56 - return "HeLlO".toLowerCase();
5.57 - }
5.58 -
5.59 - @Compare public String lowerA() {
5.60 - return String.valueOf(Character.toLowerCase('A')).toString();
5.61 - }
5.62 - @Compare public String upperHello() {
5.63 - return "hello".toUpperCase();
5.64 - }
5.65 -
5.66 - @Compare public String upperA() {
5.67 - return String.valueOf(Character.toUpperCase('a')).toString();
5.68 - }
5.69 -
5.70 - @Compare public boolean matchRegExp() throws Exception {
5.71 - return "58038503".matches("\\d*");
5.72 - }
5.73 -
5.74 - @Compare public boolean doesNotMatchRegExp() throws Exception {
5.75 - return "58038503GH".matches("\\d*");
5.76 - }
5.77 -
5.78 - @Compare public boolean doesNotMatchRegExpFully() throws Exception {
5.79 - return "Hello".matches("Hell");
5.80 - }
5.81 -
5.82 - @Compare public String variousCharacterTests() throws Exception {
5.83 - StringBuilder sb = new StringBuilder();
5.84 -
5.85 - sb.append(Character.isUpperCase('a'));
5.86 - sb.append(Character.isUpperCase('A'));
5.87 - sb.append(Character.isLowerCase('a'));
5.88 - sb.append(Character.isLowerCase('A'));
5.89 -
5.90 - sb.append(Character.isLetter('A'));
5.91 - sb.append(Character.isLetterOrDigit('9'));
5.92 - sb.append(Character.isLetterOrDigit('A'));
5.93 - sb.append(Character.isLetter('0'));
5.94 -
5.95 - return sb.toString().toString();
5.96 - }
5.97 -
5.98 - @Compare
5.99 - public String nullFieldInitialized() {
5.100 - NullField nf = new NullField();
5.101 - return ("" + nf.name).toString();
5.102 - }
5.103 -
5.104 - @Factory
5.105 - public static Object[] create() {
5.106 - return CompareVMs.create(CompareStringsTest.class);
5.107 - }
5.108 -
5.109 - private static final class NullField {
5.110 -
5.111 - String name;
5.112 - }
5.113 -}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/vmtest/pom.xml Mon Dec 17 17:45:08 2012 +0100
6.3 @@ -0,0 +1,56 @@
6.4 +<?xml version="1.0"?>
6.5 +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
6.6 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
6.7 + <modelVersion>4.0.0</modelVersion>
6.8 + <parent>
6.9 + <groupId>org.apidesign</groupId>
6.10 + <artifactId>bck2brwsr</artifactId>
6.11 + <version>0.3-SNAPSHOT</version>
6.12 + </parent>
6.13 + <groupId>org.apidesign.bck2brwsr</groupId>
6.14 + <artifactId>vmtest</artifactId>
6.15 + <version>0.3-SNAPSHOT</version>
6.16 +
6.17 + <name>VM Testing APIs</name>
6.18 + <url>http://bck2brwsr.apidesign.org</url>
6.19 + <build>
6.20 + <plugins>
6.21 + <plugin>
6.22 + <groupId>org.apache.maven.plugins</groupId>
6.23 + <artifactId>maven-compiler-plugin</artifactId>
6.24 + <version>2.3.2</version>
6.25 + <configuration>
6.26 + <source>1.7</source>
6.27 + <target>1.7</target>
6.28 + </configuration>
6.29 + </plugin>
6.30 + </plugins>
6.31 + </build>
6.32 + <properties>
6.33 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
6.34 + </properties>
6.35 + <dependencies>
6.36 + <dependency>
6.37 + <groupId>org.testng</groupId>
6.38 + <artifactId>testng</artifactId>
6.39 + <scope>compile</scope>
6.40 + <exclusions>
6.41 + <exclusion>
6.42 + <artifactId>junit</artifactId>
6.43 + <groupId>junit</groupId>
6.44 + </exclusion>
6.45 + </exclusions>
6.46 + </dependency>
6.47 + <dependency>
6.48 + <groupId>${project.groupId}</groupId>
6.49 + <artifactId>vm4brwsr</artifactId>
6.50 + <version>0.3-SNAPSHOT</version>
6.51 + <type>jar</type>
6.52 + </dependency>
6.53 + <dependency>
6.54 + <groupId>${project.groupId}</groupId>
6.55 + <artifactId>emul</artifactId>
6.56 + <version>0.3-SNAPSHOT</version>
6.57 + </dependency>
6.58 + </dependencies>
6.59 +</project>
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Compare.java Mon Dec 17 17:45:08 2012 +0100
7.3 @@ -0,0 +1,36 @@
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;
7.22 +
7.23 +import java.lang.annotation.ElementType;
7.24 +import java.lang.annotation.Retention;
7.25 +import java.lang.annotation.RetentionPolicy;
7.26 +import java.lang.annotation.Target;
7.27 +
7.28 +/** Can be applied on a method that yields a return value.
7.29 + * Together with {@link VMTest#create} it can be used to write
7.30 + * methods which are executed in real as well as JavaScript VMs and
7.31 + * their results are compared.
7.32 + *
7.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
7.34 + */
7.35 +@Retention(RetentionPolicy.RUNTIME)
7.36 +@Target(ElementType.METHOD)
7.37 +public @interface Compare {
7.38 +
7.39 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java Mon Dec 17 17:45:08 2012 +0100
8.3 @@ -0,0 +1,254 @@
8.4 +/**
8.5 + * Back 2 Browser Bytecode Translator
8.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
8.7 + *
8.8 + * This program is free software: you can redistribute it and/or modify
8.9 + * it under the terms of the GNU General Public License as published by
8.10 + * the Free Software Foundation, version 2 of the License.
8.11 + *
8.12 + * This program is distributed in the hope that it will be useful,
8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.15 + * GNU General Public License for more details.
8.16 + *
8.17 + * You should have received a copy of the GNU General Public License
8.18 + * along with this program. Look for COPYING file in the top folder.
8.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
8.20 + */
8.21 +package org.apidesign.bck2brwsr.vmtest;
8.22 +
8.23 +import java.io.File;
8.24 +import java.io.FileWriter;
8.25 +import java.io.IOException;
8.26 +import java.io.InputStream;
8.27 +import java.lang.reflect.Method;
8.28 +import java.net.URL;
8.29 +import java.util.Enumeration;
8.30 +import java.util.Map;
8.31 +import java.util.WeakHashMap;
8.32 +import javax.script.Invocable;
8.33 +import javax.script.ScriptEngine;
8.34 +import javax.script.ScriptEngineManager;
8.35 +import org.apidesign.vm4brwsr.Bck2Brwsr;
8.36 +import org.testng.Assert;
8.37 +import org.testng.ITest;
8.38 +import org.testng.annotations.Factory;
8.39 +import org.testng.annotations.Test;
8.40 +
8.41 +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
8.42 + * in provided class and builds set of tests that compare the computations
8.43 + * in real as well as JavaScript virtual machines. Use as:<pre>
8.44 + * {@code @}{@link Factory} public static create() {
8.45 + * return @{link VMTest}.{@link #create(YourClass.class);
8.46 + * }</pre>
8.47 + *
8.48 + * @author Jaroslav Tulach <jtulach@netbeans.org>
8.49 + */
8.50 +public final class VMTest implements ITest {
8.51 + private final Run first, second;
8.52 + private final Method m;
8.53 +
8.54 + private VMTest(Method m, Run first, Run second) {
8.55 + this.first = first;
8.56 + this.second = second;
8.57 + this.m = m;
8.58 + }
8.59 +
8.60 + /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
8.61 + * instances of tests. Each insteance runs the test in different virtual
8.62 + * machine and at the end they compare the results.
8.63 + *
8.64 + * @param clazz the class to inspect
8.65 + * @return the set of created tests
8.66 + */
8.67 + public static Object[] create(Class<?> clazz) {
8.68 + Method[] arr = clazz.getMethods();
8.69 + Object[] ret = new Object[3 * arr.length];
8.70 + int cnt = 0;
8.71 + for (Method m : arr) {
8.72 + Compare c = m.getAnnotation(Compare.class);
8.73 + if (c == null) {
8.74 + continue;
8.75 + }
8.76 + final Run real = new Run(m, false);
8.77 + final Run js = new Run(m, true);
8.78 + ret[cnt++] = real;
8.79 + ret[cnt++] = js;
8.80 + ret[cnt++] = new VMTest(m, real, js);
8.81 + }
8.82 + Object[] r = new Object[cnt];
8.83 + for (int i = 0; i < cnt; i++) {
8.84 + r[i] = ret[i];
8.85 + }
8.86 + return r;
8.87 + }
8.88 +
8.89 + /** Test that compares the previous results.
8.90 + * @throws Throwable
8.91 + */
8.92 + @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
8.93 + Object v1 = first.value;
8.94 + Object v2 = second.value;
8.95 + if (v1 instanceof Number) {
8.96 + v1 = ((Number)v1).doubleValue();
8.97 + }
8.98 + Assert.assertEquals(v2, v1, "Comparing results");
8.99 + }
8.100 +
8.101 + /** Test name.
8.102 + * @return name of the tested method followed by a suffix
8.103 + */
8.104 + @Override
8.105 + public String getTestName() {
8.106 + return m.getName() + "[Compare]";
8.107 + }
8.108 +
8.109 + /** Helper method that inspects the classpath and loads given resource
8.110 + * (usually a class file). Used while running tests in Rhino.
8.111 + *
8.112 + * @param name resource name to find
8.113 + * @return the array of bytes in the given resource
8.114 + * @throws IOException I/O in case something goes wrong
8.115 + */
8.116 + public static byte[] read(String name) throws IOException {
8.117 + URL u = null;
8.118 + Enumeration<URL> en = VMTest.class.getClassLoader().getResources(name);
8.119 + while (en.hasMoreElements()) {
8.120 + u = en.nextElement();
8.121 + }
8.122 + if (u == null) {
8.123 + throw new IOException("Can't find " + name);
8.124 + }
8.125 + try (InputStream is = u.openStream()) {
8.126 + byte[] arr;
8.127 + arr = new byte[is.available()];
8.128 + int offset = 0;
8.129 + while (offset < arr.length) {
8.130 + int len = is.read(arr, offset, arr.length - offset);
8.131 + if (len == -1) {
8.132 + throw new IOException("Can't read " + name);
8.133 + }
8.134 + offset += len;
8.135 + }
8.136 + return arr;
8.137 + }
8.138 + }
8.139 +
8.140 + public static final class Run implements ITest {
8.141 + private final Method m;
8.142 + private final boolean js;
8.143 + Object value;
8.144 + private Invocable code;
8.145 + private CharSequence codeSeq;
8.146 + private static final Map<Class,Object[]> compiled = new WeakHashMap<Class,Object[]>();
8.147 +
8.148 + private Run(Method m, boolean js) {
8.149 + this.m = m;
8.150 + this.js = js;
8.151 + }
8.152 +
8.153 + private void compileTheCode(Class<?> clazz) throws Exception {
8.154 + final Object[] data = compiled.get(clazz);
8.155 + if (data != null) {
8.156 + code = (Invocable) data[0];
8.157 + codeSeq = (CharSequence) data[1];
8.158 + return;
8.159 + }
8.160 + StringBuilder sb = new StringBuilder();
8.161 + Bck2Brwsr.generate(sb, VMTest.class.getClassLoader());
8.162 +
8.163 + ScriptEngineManager sem = new ScriptEngineManager();
8.164 + ScriptEngine js = sem.getEngineByExtension("js");
8.165 +
8.166 + sb.append("\nfunction initVM() {"
8.167 + + "\n return bck2brwsr("
8.168 + + "\n function(name) { return org.apidesign.bck2brwsr.vmtest.VMTest.read(name);}"
8.169 + + "\n );"
8.170 + + "\n};");
8.171 +
8.172 + Object res = js.eval(sb.toString());
8.173 + Assert.assertTrue(js instanceof Invocable, "It is invocable object: " + res);
8.174 + code = (Invocable) js;
8.175 + codeSeq = sb;
8.176 + compiled.put(clazz, new Object[] { code, codeSeq });
8.177 + }
8.178 +
8.179 + @Test(groups = "run") public void executeCode() throws Throwable {
8.180 + if (js) {
8.181 + try {
8.182 + compileTheCode(m.getDeclaringClass());
8.183 + Object vm = code.invokeFunction("initVM");
8.184 + Object inst = code.invokeMethod(vm, "loadClass", m.getDeclaringClass().getName());
8.185 + value = code.invokeMethod(inst, m.getName() + "__" + computeSignature(m));
8.186 + } catch (Exception ex) {
8.187 + throw new AssertionError(dumpJS(codeSeq)).initCause(ex);
8.188 + }
8.189 + } else {
8.190 + value = m.invoke(m.getDeclaringClass().newInstance());
8.191 + }
8.192 + }
8.193 + @Override
8.194 + public String getTestName() {
8.195 + return m.getName() + (js ? "[JavaScript]" : "[Java]");
8.196 + }
8.197 +
8.198 + private static String computeSignature(Method m) {
8.199 + StringBuilder sb = new StringBuilder();
8.200 + appendType(sb, m.getReturnType());
8.201 + for (Class<?> c : m.getParameterTypes()) {
8.202 + appendType(sb, c);
8.203 + }
8.204 + return sb.toString();
8.205 + }
8.206 +
8.207 + private static void appendType(StringBuilder sb, Class<?> t) {
8.208 + if (t == null) {
8.209 + sb.append('V');
8.210 + return;
8.211 + }
8.212 + if (t.isPrimitive()) {
8.213 + int ch = -1;
8.214 + if (t == int.class) {
8.215 + ch = 'I';
8.216 + }
8.217 + if (t == short.class) {
8.218 + ch = 'S';
8.219 + }
8.220 + if (t == byte.class) {
8.221 + ch = 'B';
8.222 + }
8.223 + if (t == boolean.class) {
8.224 + ch = 'Z';
8.225 + }
8.226 + if (t == long.class) {
8.227 + ch = 'J';
8.228 + }
8.229 + if (t == float.class) {
8.230 + ch = 'F';
8.231 + }
8.232 + if (t == double.class) {
8.233 + ch = 'D';
8.234 + }
8.235 + assert ch != -1 : "Unknown primitive type " + t;
8.236 + sb.append((char)ch);
8.237 + return;
8.238 + }
8.239 + if (t.isArray()) {
8.240 + sb.append("_3");
8.241 + appendType(sb, t.getComponentType());
8.242 + return;
8.243 + }
8.244 + sb.append('L');
8.245 + sb.append(t.getName().replace('.', '_'));
8.246 + sb.append("_2");
8.247 + }
8.248 + }
8.249 +
8.250 + static StringBuilder dumpJS(CharSequence sb) throws IOException {
8.251 + File f = File.createTempFile("execution", ".js");
8.252 + FileWriter w = new FileWriter(f);
8.253 + w.append(sb);
8.254 + w.close();
8.255 + return new StringBuilder(f.getPath());
8.256 + }
8.257 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java Mon Dec 17 17:45:08 2012 +0100
9.3 @@ -0,0 +1,42 @@
9.4 +/**
9.5 + * Back 2 Browser Bytecode Translator
9.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
9.7 + *
9.8 + * This program is free software: you can redistribute it and/or modify
9.9 + * it under the terms of the GNU General Public License as published by
9.10 + * the Free Software Foundation, version 2 of the License.
9.11 + *
9.12 + * This program is distributed in the hope that it will be useful,
9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.15 + * GNU General Public License for more details.
9.16 + *
9.17 + * You should have received a copy of the GNU General Public License
9.18 + * along with this program. Look for COPYING file in the top folder.
9.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
9.20 + */
9.21 +package org.apidesign.bck2brwsr.tck;
9.22 +
9.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
9.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
9.25 +import org.testng.annotations.Factory;
9.26 +
9.27 +/**
9.28 + *
9.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
9.30 + */
9.31 +public class CompareHashTest {
9.32 + @Compare public int hashOfString() {
9.33 + return "Ahoj".hashCode();
9.34 + }
9.35 +
9.36 + @Compare public int hashRemainsYieldsZero() {
9.37 + Object o = new Object();
9.38 + return o.hashCode() - o.hashCode();
9.39 + }
9.40 +
9.41 + @Factory
9.42 + public static Object[] create() {
9.43 + return VMTest.create(CompareHashTest.class);
9.44 + }
9.45 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Mon Dec 17 17:45:08 2012 +0100
10.3 @@ -0,0 +1,110 @@
10.4 +/**
10.5 + * Back 2 Browser Bytecode Translator
10.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
10.7 + *
10.8 + * This program is free software: you can redistribute it and/or modify
10.9 + * it under the terms of the GNU General Public License as published by
10.10 + * the Free Software Foundation, version 2 of the License.
10.11 + *
10.12 + * This program is distributed in the hope that it will be useful,
10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.15 + * GNU General Public License for more details.
10.16 + *
10.17 + * You should have received a copy of the GNU General Public License
10.18 + * along with this program. Look for COPYING file in the top folder.
10.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
10.20 + */
10.21 +package org.apidesign.bck2brwsr.tck;
10.22 +
10.23 +import java.net.MalformedURLException;
10.24 +import java.net.URL;
10.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
10.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
10.27 +import org.testng.annotations.Factory;
10.28 +
10.29 +/**
10.30 + *
10.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
10.32 + */
10.33 +public class CompareStringsTest {
10.34 + @Compare public static Object compareURLs() throws MalformedURLException {
10.35 + return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
10.36 + }
10.37 +
10.38 + @Compare public String deleteLastTwoCharacters() {
10.39 + StringBuilder sb = new StringBuilder();
10.40 + sb.append("453.0");
10.41 + if (sb.toString().endsWith(".0")) {
10.42 + final int l = sb.length();
10.43 + sb.delete(l - 2, l);
10.44 + }
10.45 + return sb.toString().toString();
10.46 + }
10.47 +
10.48 + @Compare public String nameOfStringClass() throws Exception {
10.49 + return Class.forName("java.lang.String").getName();
10.50 + }
10.51 + @Compare public String nameOfArrayClass() throws Exception {
10.52 + return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName();
10.53 + }
10.54 +
10.55 + @Compare public String lowerHello() {
10.56 + return "HeLlO".toLowerCase();
10.57 + }
10.58 +
10.59 + @Compare public String lowerA() {
10.60 + return String.valueOf(Character.toLowerCase('A')).toString();
10.61 + }
10.62 + @Compare public String upperHello() {
10.63 + return "hello".toUpperCase();
10.64 + }
10.65 +
10.66 + @Compare public String upperA() {
10.67 + return String.valueOf(Character.toUpperCase('a')).toString();
10.68 + }
10.69 +
10.70 + @Compare public boolean matchRegExp() throws Exception {
10.71 + return "58038503".matches("\\d*");
10.72 + }
10.73 +
10.74 + @Compare public boolean doesNotMatchRegExp() throws Exception {
10.75 + return "58038503GH".matches("\\d*");
10.76 + }
10.77 +
10.78 + @Compare public boolean doesNotMatchRegExpFully() throws Exception {
10.79 + return "Hello".matches("Hell");
10.80 + }
10.81 +
10.82 + @Compare public String variousCharacterTests() throws Exception {
10.83 + StringBuilder sb = new StringBuilder();
10.84 +
10.85 + sb.append(Character.isUpperCase('a'));
10.86 + sb.append(Character.isUpperCase('A'));
10.87 + sb.append(Character.isLowerCase('a'));
10.88 + sb.append(Character.isLowerCase('A'));
10.89 +
10.90 + sb.append(Character.isLetter('A'));
10.91 + sb.append(Character.isLetterOrDigit('9'));
10.92 + sb.append(Character.isLetterOrDigit('A'));
10.93 + sb.append(Character.isLetter('0'));
10.94 +
10.95 + return sb.toString().toString();
10.96 + }
10.97 +
10.98 + @Compare
10.99 + public String nullFieldInitialized() {
10.100 + NullField nf = new NullField();
10.101 + return ("" + nf.name).toString();
10.102 + }
10.103 +
10.104 + @Factory
10.105 + public static Object[] create() {
10.106 + return VMTest.create(CompareStringsTest.class);
10.107 + }
10.108 +
10.109 + private static final class NullField {
10.110 +
10.111 + String name;
10.112 + }
10.113 +}