# HG changeset patch # User Jaroslav Tulach # Date 1367245934 -7200 # Node ID 3f7991249a205107af58cc856c9a9a1437087a17 # Parent c7a085d63ab5a2ab399d70c0014c5b0aca5e1398# Parent e61f24684a69d82f54c8a84a010f1f326cac10ce Separation of launchers into three pieces seems to work ok. Merging work from model branch to default one. diff -r c7a085d63ab5 -r 3f7991249a20 benchmarks/matrix-multiplication/pom.xml --- a/benchmarks/matrix-multiplication/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/benchmarks/matrix-multiplication/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -94,5 +94,11 @@ 0.7-SNAPSHOT test + + org.apidesign.bck2brwsr + launcher.http + 0.7-SNAPSHOT + test + diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/api/pom.xml --- a/javaquery/api/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/api/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -73,5 +73,11 @@ ${project.version} test + + ${project.groupId} + launcher.http + ${project.version} + test + diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java Mon Apr 29 16:32:14 2013 +0200 @@ -22,16 +22,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** Can be used in classes annotated with {@link Page} annotation to - * define a derived property. Value of derived property is based on values - * of {@link Property} as enumerated by {@link Page#properties()}. - *

- * The name of the derived property is the name of the method. The arguments - * of the method define the property names (from {@link Page#properties()} list) - * the value of property depends on. - * +/** + * @deprecated Replaced by new {@link net.java.html.json.ComputedProperty net.java.html.json} API. * @author Jaroslav Tulach */ +@Deprecated @Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) public @interface ComputedProperty { diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Model.java --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Model.java Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Model.java Mon Apr 29 16:32:14 2013 +0200 @@ -22,19 +22,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** Defines a model class named {@link #className()} which contains - * defined {@link #properties()}. This class can have methods - * annotated by {@link ComputedProperty} which define derived - * properties in the model class. - *

- * The {@link #className() generated class}'s toString - * converts the state of the object into - * JSON format. - * +/** + * @deprecated Replaced by new {@link net.java.html.json.Model net.java.html.json} API. * @author Jaroslav Tulach */ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) +@Deprecated public @interface Model { /** Name of the model class */ String className(); diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnFunction.java --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnFunction.java Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnFunction.java Mon Apr 29 16:32:14 2013 +0200 @@ -22,13 +22,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** Methods in class annotated by {@link Model} or {@link Page} can be - * annotated by this annotation to signal that they should be available - * as functions to users of the model classes. - * +/** + * @deprecated Replaced by new {@link net.java.html.json.Function net.java.html.json} API. * @author Jaroslav Tulach */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) +@Deprecated public @interface OnFunction { } diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnPropertyChange.java --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnPropertyChange.java Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnPropertyChange.java Mon Apr 29 16:32:14 2013 +0200 @@ -22,13 +22,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** Represents a property. Either in a generated model of an HTML - * {@link Page} or in a class defined by {@link Model}. - * +/** + * @deprecated Replaced by new {@link net.java.html.json.OnPropertyChange net.java.html.json} API. * @author Jaroslav Tulach */ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) +@Deprecated public @interface OnPropertyChange { /** Name(s) of the properties. One wishes to observe. * diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnReceive.java --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnReceive.java Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnReceive.java Mon Apr 29 16:32:14 2013 +0200 @@ -22,54 +22,14 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** Static methods in classes annotated by {@link Page} - * can be marked by this annotation to establish a - * JSON - * communication point. - * The associated model page then gets new method to invoke a network - * connection. Example follows: - * - *

- * {@link Page @Page}(className="MyModel", xhtml="page.html", properties={
- *   {@link Property @Property}(name = "people", type=Person.class, array=true)
- * })
- * class MyModelImpl {
- *   {@link Model @Model}(className="Person", properties={
- *     {@link Property @Property}(name = "firstName", type=String.class),
- *     {@link Property @Property}(name = "lastName", type=String.class)
- *   })
- *   static class PersonImpl {
- *     {@link ComputedProperty @ComputedProperty}
- *     static String fullName(String firstName, String lastName) {
- *       return firstName + " " + lastName;
- *     }
- *   }
- * 
- *   {@link OnReceive @OnReceive}(url = "{protocol}://your.server.com/person/{name}")
- *   static void getANewPerson(MyModel m, Person p) {
- *     {@link Element#alert Element.alert}("Adding " + p.getFullName() + '!');
- *     m.getPeople().add(p);
- *   }
- * 
- *   // the above will generate method getANewPerson in class MyModel.
- *   // with protocol and name arguments
- *   // which asynchronously contacts the server and in case of success calls
- *   // your {@link OnReceive @OnReceive} with parsed in data
- * 
- *   {@link On @On}(event={@link OnEvent#CLICK OnEvent.CLICK}, id="rqst")
- *   static void requestSmith(MyModel m) {
- *     m.getANewPerson("http", "Smith");
- *   }
- * }
- * 
- * When the server returns { "firstName" : "John", "lastName" : "Smith" } - * the browser will show alert message Adding John Smith!. - * +/** + * @deprecated Replaced by new {@link net.java.html.json.OnReceive net.java.html.json} API. * @author Jaroslav Tulach * @since 0.6 */ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) +@Deprecated public @interface OnReceive { /** The URL to connect to. Can contain variable names surrounded by '{' and '}'. * Those parameters will then become variables of the associated method. diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java Mon Apr 29 16:32:14 2013 +0200 @@ -22,13 +22,13 @@ import java.lang.annotation.Target; import java.util.List; -/** Represents a property. Either in a generated model of an HTML - * {@link Page} or in a class defined by {@link Model}. - * +/** + * @deprecated Replaced by new {@link net.java.html.json.Property net.java.html.json} API. * @author Jaroslav Tulach */ @Retention(RetentionPolicy.SOURCE) @Target({}) +@Deprecated public @interface Property { /** Name of the property. Will be used to define proper getter and setter * in the associated class. diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/demo-calculator/pom.xml --- a/javaquery/demo-calculator/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/demo-calculator/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -12,7 +12,7 @@ UTF-8 - FULL + MINIMAL diff -r c7a085d63ab5 -r 3f7991249a20 javaquery/demo-twitter/pom.xml --- a/javaquery/demo-twitter/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/javaquery/demo-twitter/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -141,5 +141,11 @@ ${project.version} test + + org.apidesign.bck2brwsr + launcher.http + ${project.version} + runtime + diff -r c7a085d63ab5 -r 3f7991249a20 launcher/api/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/api/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,20 @@ + + + 4.0.0 + + org.apidesign.bck2brwsr + launcher-pom + 0.7-SNAPSHOT + + org.apidesign.bck2brwsr + launcher + 0.7-SNAPSHOT + Launcher API + http://maven.apache.org + + UTF-8 + + + + diff -r c7a085d63ab5 -r 3f7991249a20 launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,115 @@ +/** + * 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.launcher; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** Represents individual method invocation, its context and its result. + * + * @author Jaroslav Tulach + */ +public final class InvocationContext { + final CountDownLatch wait = new CountDownLatch(1); + final Class clazz; + final String methodName; + private final Launcher launcher; + private String result; + private Throwable exception; + String html; + final List resources = new ArrayList<>(); + + InvocationContext(Launcher launcher, Class clazz, String methodName) { + this.launcher = launcher; + this.clazz = clazz; + this.methodName = methodName; + } + + /** An HTML fragment to be available for the execution. Useful primarily when + * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}. + * @param html the html fragment + */ + public void setHtmlFragment(String html) { + this.html = html; + } + + /** HTTP resource to be available during execution. An invocation may + * perform an HTTP query and obtain a resource relative to the page. + */ + public void addHttpResource(String relativePath, String mimeType, String[] parameters, InputStream content) { + if (relativePath == null || mimeType == null || content == null || parameters == null) { + throw new NullPointerException(); + } + resources.add(new Resource(content, mimeType, relativePath, parameters)); + } + + /** Invokes the associated method. + * @return the textual result of the invocation + */ + public String invoke() throws IOException { + launcher.runMethod(this); + return toString(); + } + + /** Obtains textual result of the invocation. + * @return text representing the exception or result value + */ + @Override + public String toString() { + if (exception != null) { + return exception.toString(); + } + return result; + } + + /** + * @param timeOut + * @throws InterruptedException + */ + void await(long timeOut) throws InterruptedException { + wait.await(timeOut, TimeUnit.MILLISECONDS); + } + + void result(String r, Throwable e) { + this.result = r; + this.exception = e; + wait.countDown(); + } + + + static final class Resource { + final InputStream httpContent; + final String httpType; + final String httpPath; + final String[] parameters; + + Resource(InputStream httpContent, String httpType, String httpPath, + String[] parameters + ) { + httpContent.mark(Integer.MAX_VALUE); + this.httpContent = httpContent; + this.httpType = httpType; + this.httpPath = httpPath; + this.parameters = parameters; + } + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,166 @@ +/** + * 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.launcher; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Constructor; + +/** An abstraction for executing tests in a Bck2Brwsr virtual machine. + * Either in {@link Launcher#createJavaScript JavaScript engine}, + * or in {@link Launcher#createBrowser external browser}. + *

+ * There also are methods to {@link #showDir(java.io.File, java.lang.String) display pages} + * in an external browser served by internal HTTP server. + * + * @author Jaroslav Tulach + */ +public abstract class Launcher { + + Launcher() { + } + + /** Initializes the launcher. This may mean starting a web browser or + * initializing execution engine. + * @throws IOException if something goes wrong + */ + public abstract void initialize() throws IOException; + + /** Shuts down the launcher. + * @throws IOException if something goes wrong + */ + public abstract void shutdown() throws IOException; + + + /** Builds an invocation context. The context can later be customized + * and {@link InvocationContext#invoke() invoked}. + * + * @param clazz the class to execute method from + * @param method the method to execute + * @return the context pointing to the selected method + */ + public InvocationContext createInvocation(Class clazz, String method) { + return new InvocationContext(this, clazz, method); + } + + + /** Creates launcher that uses internal JavaScript engine (Rhino). + * @return the launcher + */ + public static Launcher createJavaScript() { + try { + Class c = loadClass("org.apidesign.bck2brwsr.launcher.JSLauncher"); + return (Launcher) c.newInstance(); + } catch (Exception ex) { + throw new IllegalStateException("Please include org.apidesign.bck2brwsr:launcher.html dependency!", ex); + } + } + + /** Creates launcher that is using external browser. + * + * @param cmd null to use java.awt.Desktop to show the launcher + * or a string to execute in an external process (with a parameter to the URL) + * @return launcher executing in external browser. + */ + public static Launcher createBrowser(String cmd) { + String msg = "Trying to create browser '" + cmd + "'"; + try { + Class c; + if ("fxbrwsr".equals(cmd)) { // NOI18N + msg = "Please include org.apidesign.bck2brwsr:launcher.fx dependency!"; + c = loadClass("org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher"); // NOI18N + } else { + msg = "Please include org.apidesign.bck2brwsr:launcher.html dependency!"; + c = loadClass("org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher"); // NOI18N + if ("bck2brwsr".equals(cmd)) { // NOI18N + // use default executable + cmd = null; + } + } + Constructor cnstr = c.getConstructor(String.class); + return (Launcher) cnstr.newInstance(cmd); + } catch (Exception ex) { + throw new IllegalStateException(msg, ex); + } + } + + /** Starts an HTTP server which provides access to classes and resources + * available in the classes URL and shows a start page + * available as {@link ClassLoader#getResource(java.lang.String)} from the + * provide classloader. Opens a browser with URL showing the start page. + * + * @param classes classloader offering access to classes and resources + * @param startpage page to show in the browser + * @return interface that allows one to stop the server + * @throws IOException if something goes wrong + */ + public static Closeable showURL(ClassLoader classes, String startpage) throws IOException { + return showURL(null, classes, startpage); + } + /** Starts an HTTP server which provides access to classes and resources + * available in the classes URL and shows a start page + * available as {@link ClassLoader#getResource(java.lang.String)} from the + * provide classloader. Opens a browser with URL showing the start page. + * + * @param brwsr name of browser to use or null + * @param classes classloader offering access to classes and resources + * @param startpage page to show in the browser + * @return interface that allows one to stop the server + * @throws IOException if something goes wrong + * @since 0.7 + */ + public static Closeable showURL(String brwsr, ClassLoader classes, String startpage) throws IOException { + Launcher l = createBrowser(brwsr); + l.addClassLoader(classes); + l.showURL(startpage); + return (Closeable) l; + } + /** Starts an HTTP server which provides access to certain directory. + * The startpage should be relative location inside the root + * directory. Opens a browser with URL showing the start page. + * + * @param directory the root directory on disk + * @param startpage relative path from the root to the page + * @exception IOException if something goes wrong. + */ + public static Closeable showDir(File directory, String startpage) throws IOException { + Launcher l = createBrowser(null); + l.showDirectory(directory, startpage); + return (Closeable) l; + } + + abstract InvocationContext runMethod(InvocationContext c) throws IOException; + + + private static Class loadClass(String cn) throws ClassNotFoundException { + return Launcher.class.getClassLoader().loadClass(cn); + } + + void showDirectory(File directory, String startpage) throws IOException { + throw new UnsupportedOperationException(); + } + + void showURL(String startpage) throws IOException { + throw new UnsupportedOperationException(); + } + + void addClassLoader(ClassLoader classes) { + throw new UnsupportedOperationException(); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/fx/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,49 @@ + + + 4.0.0 + + org.apidesign.bck2brwsr + launcher-pom + 0.7-SNAPSHOT + + org.apidesign.bck2brwsr + launcher.fx + 0.7-SNAPSHOT + FXBrwsr Launcher + http://maven.apache.org + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + UTF-8 + + + + ${project.groupId} + launcher + ${project.version} + + + org.glassfish.grizzly + grizzly-http-server + 2.2.19 + + + com.oracle + javafx + 2.2 + system + ${java.home}/lib/jfxrt.jar + + + diff -r c7a085d63ab5 -r 3f7991249a20 launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,588 @@ +/** + * 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.launcher; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource; +import org.glassfish.grizzly.PortRange; +import org.glassfish.grizzly.http.server.HttpHandler; +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.grizzly.http.server.NetworkListener; +import org.glassfish.grizzly.http.server.Request; +import org.glassfish.grizzly.http.server.Response; +import org.glassfish.grizzly.http.server.ServerConfiguration; +import org.glassfish.grizzly.http.util.HttpStatus; + +/** + * Lightweight server to launch Bck2Brwsr applications and tests. + * Supports execution in native browser as well as Java's internal + * execution engine. + */ +abstract class BaseHTTPLauncher extends Launcher implements Closeable { + private static final Logger LOG = Logger.getLogger(BaseHTTPLauncher.class.getName()); + private static final InvocationContext END = new InvocationContext(null, null, null); + private final Set loaders = new LinkedHashSet<>(); + private final BlockingQueue methods = new LinkedBlockingQueue<>(); + private long timeOut; + private final Res resources = new Res(); + private final String cmd; + private Object[] brwsr; + private HttpServer server; + private CountDownLatch wait; + + public BaseHTTPLauncher(String cmd) { + this.cmd = cmd; + addClassLoader(BaseHTTPLauncher.class.getClassLoader()); + setTimeout(180000); + } + + @Override + InvocationContext runMethod(InvocationContext c) throws IOException { + loaders.add(c.clazz.getClassLoader()); + methods.add(c); + try { + c.await(timeOut); + } catch (InterruptedException ex) { + throw new IOException(ex); + } + return c; + } + + public void setTimeout(long ms) { + timeOut = ms; + } + + public void addClassLoader(ClassLoader url) { + this.loaders.add(url); + } + + ClassLoader[] loaders() { + return loaders.toArray(new ClassLoader[loaders.size()]); + } + + public void showURL(String startpage) throws IOException { + if (!startpage.startsWith("/")) { + startpage = "/" + startpage; + } + HttpServer s = initServer(".", true); + int last = startpage.lastIndexOf('/'); + String prefix = startpage.substring(0, last); + String simpleName = startpage.substring(last); + s.getServerConfiguration().addHttpHandler(new SubTree(resources, prefix), "/"); + try { + launchServerAndBrwsr(s, simpleName); + } catch (URISyntaxException | InterruptedException ex) { + throw new IOException(ex); + } + } + + void showDirectory(File dir, String startpage) throws IOException { + if (!startpage.startsWith("/")) { + startpage = "/" + startpage; + } + HttpServer s = initServer(dir.getPath(), false); + try { + launchServerAndBrwsr(s, startpage); + } catch (URISyntaxException | InterruptedException ex) { + throw new IOException(ex); + } + } + + @Override + public void initialize() throws IOException { + try { + executeInBrowser(); + } catch (InterruptedException ex) { + final InterruptedIOException iio = new InterruptedIOException(ex.getMessage()); + iio.initCause(ex); + throw iio; + } catch (Exception ex) { + if (ex instanceof IOException) { + throw (IOException)ex; + } + if (ex instanceof RuntimeException) { + throw (RuntimeException)ex; + } + throw new IOException(ex); + } + } + + private HttpServer initServer(String path, boolean addClasses) throws IOException { + HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535)); + + final ServerConfiguration conf = s.getServerConfiguration(); + if (addClasses) { + conf.addHttpHandler(new VM(), "/bck2brwsr.js"); + conf.addHttpHandler(new Classes(resources), "/classes/"); + } + return s; + } + + private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException { + wait = new CountDownLatch(1); + server = initServer(".", true); + final ServerConfiguration conf = server.getServerConfiguration(); + + class DynamicResourceHandler extends HttpHandler { + private final InvocationContext ic; + public DynamicResourceHandler(InvocationContext ic) { + if (ic == null || ic.resources.isEmpty()) { + throw new NullPointerException(); + } + this.ic = ic; + for (Resource r : ic.resources) { + conf.addHttpHandler(this, r.httpPath); + } + } + + public void close() { + conf.removeHttpHandler(this); + } + + @Override + public void service(Request request, Response response) throws Exception { + for (Resource r : ic.resources) { + if (r.httpPath.equals(request.getRequestURI())) { + LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI()); + response.setContentType(r.httpType); + r.httpContent.reset(); + String[] params = null; + if (r.parameters.length != 0) { + params = new String[r.parameters.length]; + for (int i = 0; i < r.parameters.length; i++) { + params[i] = request.getParameter(r.parameters[i]); + } + } + + copyStream(r.httpContent, response.getOutputStream(), null, params); + } + } + } + } + + conf.addHttpHandler(new Page(resources, + "org/apidesign/bck2brwsr/launcher/fximpl/harness.xhtml" + ), "/execute"); + + conf.addHttpHandler(new HttpHandler() { + int cnt; + List cases = new ArrayList<>(); + DynamicResourceHandler prev; + @Override + public void service(Request request, Response response) throws Exception { + String id = request.getParameter("request"); + String value = request.getParameter("result"); + if (value != null && value.indexOf((char)0xC5) != -1) { + value = toUTF8(value); + } + + + InvocationContext mi = null; + int caseNmbr = -1; + + if (id != null && value != null) { + LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value}); + value = decodeURL(value); + int indx = Integer.parseInt(id); + cases.get(indx).result(value, null); + if (++indx < cases.size()) { + mi = cases.get(indx); + LOG.log(Level.INFO, "Re-executing case {0}", indx); + caseNmbr = indx; + } + } else { + if (!cases.isEmpty()) { + LOG.info("Re-executing test cases"); + mi = cases.get(0); + caseNmbr = 0; + } + } + + if (prev != null) { + prev.close(); + prev = null; + } + + if (mi == null) { + mi = methods.take(); + caseNmbr = cnt++; + } + if (mi == END) { + response.getWriter().write(""); + wait.countDown(); + cnt = 0; + LOG.log(Level.INFO, "End of data reached. Exiting."); + return; + } + + if (!mi.resources.isEmpty()) { + prev = new DynamicResourceHandler(mi); + } + + cases.add(mi); + final String cn = mi.clazz.getName(); + final String mn = mi.methodName; + LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn}); + response.getWriter().write("{" + + "className: '" + cn + "', " + + "methodName: '" + mn + "', " + + "request: " + caseNmbr + ); + if (mi.html != null) { + response.getWriter().write(", html: '"); + response.getWriter().write(encodeJSON(mi.html)); + response.getWriter().write("'"); + } + response.getWriter().write("}"); + } + }, "/data"); + + this.brwsr = launchServerAndBrwsr(server, "/execute"); + } + + private static String encodeJSON(String in) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < in.length(); i++) { + char ch = in.charAt(i); + if (ch < 32 || ch == '\'' || ch == '"') { + sb.append("\\u"); + String hs = "0000" + Integer.toHexString(ch); + hs = hs.substring(hs.length() - 4); + sb.append(hs); + } else { + sb.append(ch); + } + } + return sb.toString(); + } + + @Override + public void shutdown() throws IOException { + methods.offer(END); + for (;;) { + int prev = methods.size(); + try { + if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) { + break; + } + } catch (InterruptedException ex) { + throw new IOException(ex); + } + if (prev == methods.size()) { + LOG.log( + Level.WARNING, + "Timeout and no test has been executed meanwhile (at {0}). Giving up.", + methods.size() + ); + break; + } + LOG.log(Level.INFO, + "Timeout, but tests got from {0} to {1}. Trying again.", + new Object[]{prev, methods.size()} + ); + } + stopServerAndBrwsr(server, brwsr); + } + + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException { + for (;;) { + int ch = is.read(); + if (ch == -1) { + break; + } + if (ch == '$' && params.length > 0) { + int cnt = is.read() - '0'; + if (baseURL != null && cnt == 'U' - '0') { + os.write(baseURL.getBytes("UTF-8")); + } else { + if (cnt >= 0 && cnt < params.length) { + os.write(params[cnt].getBytes("UTF-8")); + } else { + os.write('$'); + os.write(cnt + '0'); + } + } + } else { + os.write(ch); + } + } + } + + private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException { + server.start(); + NetworkListener listener = server.getListeners().iterator().next(); + int port = listener.getPort(); + + URI uri = new URI("http://localhost:" + port + page); + return showBrwsr(uri); + } + private static String toUTF8(String value) throws UnsupportedEncodingException { + byte[] arr = new byte[value.length()]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (byte)value.charAt(i); + } + return new String(arr, "UTF-8"); + } + + private static String decodeURL(String s) { + for (;;) { + int pos = s.indexOf('%'); + if (pos == -1) { + return s; + } + int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16); + s = s.substring(0, pos) + (char)i + s.substring(pos + 2); + } + } + + private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException { + if (brwsr == null) { + return; + } + Process process = (Process)brwsr[0]; + + server.stop(); + InputStream stdout = process.getInputStream(); + InputStream stderr = process.getErrorStream(); + drain("StdOut", stdout); + drain("StdErr", stderr); + process.destroy(); + int res; + try { + res = process.waitFor(); + } catch (InterruptedException ex) { + throw new IOException(ex); + } + LOG.log(Level.INFO, "Exit code: {0}", res); + + deleteTree((File)brwsr[1]); + } + + private static void drain(String name, InputStream is) throws IOException { + int av = is.available(); + if (av > 0) { + StringBuilder sb = new StringBuilder(); + sb.append("v== ").append(name).append(" ==v\n"); + while (av-- > 0) { + sb.append((char)is.read()); + } + sb.append("\n^== ").append(name).append(" ==^"); + LOG.log(Level.INFO, sb.toString()); + } + } + + private void deleteTree(File file) { + if (file == null) { + return; + } + File[] arr = file.listFiles(); + if (arr != null) { + for (File s : arr) { + deleteTree(s); + } + } + file.delete(); + } + + @Override + public void close() throws IOException { + shutdown(); + } + + protected Object[] showBrwsr(URI uri) throws IOException { + LOG.log(Level.INFO, "Showing {0}", uri); + if (cmd == null) { + try { + LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] { + System.getProperty("java.vm.name"), + System.getProperty("java.vm.vendor"), + System.getProperty("java.vm.version"), + }); + java.awt.Desktop.getDesktop().browse(uri); + LOG.log(Level.INFO, "Desktop.browse successfully finished"); + return null; + } catch (UnsupportedOperationException ex) { + LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage()); + LOG.log(Level.FINE, null, ex); + } + } + { + String cmdName = cmd == null ? "xdg-open" : cmd; + String[] cmdArr = { + cmdName, uri.toString() + }; + LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr)); + final Process process = Runtime.getRuntime().exec(cmdArr); + return new Object[] { process, null }; + } + } + + abstract void generateBck2BrwsrJS(StringBuilder sb, Object loader) throws IOException; + + private class Res { + public InputStream get(String resource) throws IOException { + for (ClassLoader l : loaders) { + URL u = null; + Enumeration en = l.getResources(resource); + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u != null) { + return u.openStream(); + } + } + throw new IOException("Can't find " + resource); + } + } + + private static class Page extends HttpHandler { + final String resource; + private final String[] args; + private final Res res; + + public Page(Res res, String resource, String... args) { + this.res = res; + this.resource = resource; + this.args = args.length == 0 ? new String[] { "$0" } : args; + } + + @Override + public void service(Request request, Response response) throws Exception { + String r = computePage(request); + if (r.startsWith("/")) { + r = r.substring(1); + } + String[] replace = {}; + if (r.endsWith(".html")) { + response.setContentType("text/html"); + LOG.info("Content type text/html"); + replace = args; + } + if (r.endsWith(".xhtml")) { + response.setContentType("application/xhtml+xml"); + LOG.info("Content type application/xhtml+xml"); + replace = args; + } + OutputStream os = response.getOutputStream(); + try (InputStream is = res.get(r)) { + copyStream(is, os, request.getRequestURL().toString(), replace); + } catch (IOException ex) { + response.setDetailMessage(ex.getLocalizedMessage()); + response.setError(); + response.setStatus(404); + } + } + + protected String computePage(Request request) { + String r = resource; + if (r == null) { + r = request.getHttpHandlerPath(); + } + return r; + } + } + + private static class SubTree extends Page { + + public SubTree(Res res, String resource, String... args) { + super(res, resource, args); + } + + @Override + protected String computePage(Request request) { + return resource + request.getHttpHandlerPath(); + } + + + } + + private class VM extends HttpHandler { + @Override + public void service(Request request, Response response) throws Exception { + response.setCharacterEncoding("UTF-8"); + response.setContentType("text/javascript"); + StringBuilder sb = new StringBuilder(); + generateBck2BrwsrJS(sb, BaseHTTPLauncher.this.resources); + response.getWriter().write(sb.toString()); + } + } + + private static class Classes extends HttpHandler { + private final Res loader; + + public Classes(Res loader) { + this.loader = loader; + } + + @Override + public void service(Request request, Response response) throws Exception { + String res = request.getHttpHandlerPath(); + if (res.startsWith("/")) { + res = res.substring(1); + } + try (InputStream is = loader.get(res)) { + response.setContentType("text/javascript"); + Writer w = response.getWriter(); + w.append("["); + for (int i = 0;; i++) { + int b = is.read(); + if (b == -1) { + break; + } + if (i > 0) { + w.append(", "); + } + if (i % 20 == 0) { + w.write("\n"); + } + if (b > 127) { + b = b - 256; + } + w.append(Integer.toString(b)); + } + w.append("\n]"); + } catch (IOException ex) { + response.setStatus(HttpStatus.NOT_FOUND_404); + response.setError(); + response.setDetailMessage(ex.getMessage()); + } + } + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,129 @@ +/** + * 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.launcher; + +import org.apidesign.bck2brwsr.launcher.fximpl.FXBrwsr; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; + +import java.util.concurrent.Executors; +import java.util.jar.Manifest; +import java.util.logging.Level; +import java.util.logging.Logger; +import javafx.application.Platform; +import org.apidesign.bck2brwsr.launcher.fximpl.JVMBridge; + +/** + * + * @author Jaroslav Tulach + */ +final class FXBrwsrLauncher extends BaseHTTPLauncher { + private static final Logger LOG = Logger.getLogger(FXBrwsrLauncher.class.getName()); + static { + try { + Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); + m.setAccessible(true); + URL l = new URL("file://" + System.getProperty("java.home") + "/lib/jfxrt.jar"); + LOG.log(Level.INFO, "url : {0}", l); + m.invoke(ClassLoader.getSystemClassLoader(), l); + } catch (Exception ex) { + throw new LinkageError("Can't add jfxrt.jar on the classpath", ex); + } + } + + public FXBrwsrLauncher(String ignore) { + super(null); + } + + @Override + protected Object[] showBrwsr(final URI url) throws IOException { + try { + LOG.log(Level.INFO, "showBrwsr for {0}", url); + JVMBridge.registerClassLoaders(loaders()); + LOG.info("About to launch WebView"); + Executors.newSingleThreadExecutor().submit(new Runnable() { + @Override + public void run() { + LOG.log(Level.INFO, "In FX thread. Launching!"); + try { + FXBrwsr.launch(FXBrwsr.class, url.toString()); + LOG.log(Level.INFO, "Launcher is back. Closing"); + close(); + } catch (Throwable ex) { + LOG.log(Level.WARNING, "Error launching Web View", ex); + } + } + }); + } catch (Throwable ex) { + LOG.log(Level.WARNING, "Can't open WebView", ex); + } + return null; + } + + @Override + void generateBck2BrwsrJS(StringBuilder sb, Object loader) throws IOException { + sb.append("(function() {\n" + + " var impl = this.bck2brwsr;\n" + + " this.bck2brwsr = function() { return impl; };\n" + + "})(window);\n" + ); + JVMBridge.onBck2BrwsrLoad(); + } + + + + @Override + public void close() throws IOException { + super.close(); + Platform.exit(); + } + + public static void main(String... args) throws IOException { + String startPage = null; + + final ClassLoader cl = FXBrwsrLauncher.class.getClassLoader(); + startPage = findStartPage(cl, startPage); + if (startPage == null) { + throw new NullPointerException("Can't find StartPage tag in manifests!"); + } + + Launcher.showURL("fxbrwsr", cl, startPage); + } + + private static String findStartPage(final ClassLoader cl, String startPage) throws IOException { + Enumeration en = cl.getResources("META-INF/MANIFEST.MF"); + while (en.hasMoreElements()) { + URL url = en.nextElement(); + Manifest mf; + try (InputStream is = url.openStream()) { + mf = new Manifest(is); + } + String sp = mf.getMainAttributes().getValue("StartPage"); + if (sp != null) { + startPage = sp; + break; + } + } + return startPage; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,395 @@ +/** + * 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.launcher.fximpl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.Enumeration; +import javafx.scene.web.WebEngine; +import netscape.javascript.JSObject; + +/** + * + * @author Jaroslav Tulach + */ +public final class Console { + public Console() { + } + + private static Object getAttr(Object elem, String attr) { + return InvokeJS.CObject.call("getAttr", elem, attr); + } + + private static void setAttr(String id, String attr, Object value) { + InvokeJS.CObject.call("setAttrId", id, attr, value); + } + private static void setAttr(Object id, String attr, Object value) { + InvokeJS.CObject.call("setAttr", id, attr, value); + } + + private static void closeWindow() {} + + private static Object textArea; + private static Object statusArea; + + private static void log(String newText) { + if (textArea == null) { + return; + } + String attr = "value"; + setAttr(textArea, attr, getAttr(textArea, attr) + "\n" + newText); + setAttr(textArea, "scrollTop", getAttr(textArea, "scrollHeight")); + } + + private static void beginTest(Case c) { + Object[] arr = new Object[2]; + beginTest(c.getClassName() + "." + c.getMethodName(), c, arr); + textArea = arr[0]; + statusArea = arr[1]; + } + + private static void finishTest(Case c, Object res) { + if ("null".equals(res)) { + setAttr(statusArea, "innerHTML", "Success"); + } else { + setAttr(statusArea, "innerHTML", "Result " + res); + } + statusArea = null; + textArea = null; + } + + private static final String BEGIN_TEST = + "var ul = window.document.getElementById('bck2brwsr.result');\n" + + "var li = window.document.createElement('li');\n" + + "var span = window.document.createElement('span');" + + "span.innerHTML = test + ' - ';\n" + + "var details = window.document.createElement('a');\n" + + "details.innerHTML = 'Details';\n" + + "details.href = '#';\n" + + "var p = window.document.createElement('p');\n" + + "var status = window.document.createElement('a');\n" + + "status.innerHTML = 'running';" + + "details.onclick = function() { li.appendChild(p); li.removeChild(details); status.innerHTML = 'Run Again'; status.href = '#'; };\n" + + "status.onclick = function() { c.again(arr); }\n" + + "var pre = window.document.createElement('textarea');\n" + + "pre.cols = 100;" + + "pre.rows = 10;" + + "li.appendChild(span);\n" + + "li.appendChild(status);\n" + + "var span = window.document.createElement('span');" + + "span.innerHTML = ' ';\n" + + "li.appendChild(span);\n" + + "li.appendChild(details);\n" + + "p.appendChild(pre);\n" + + "ul.appendChild(li);\n" + + "arr[0] = pre;\n" + + "arr[1] = status;\n"; + + private static void beginTest(String test, Case c, Object[] arr) { + InvokeJS.CObject.call("beginTest", test, c, arr); + } + + private static final String LOAD_TEXT = + "var request = new XMLHttpRequest();\n" + + "request.open('GET', url, true);\n" + + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n" + + "request.onreadystatechange = function() {\n" + + " if (this.readyState!==4) return;\n" + + " try {" + + " arr[0] = this.responseText;\n" + + " callback.run__V();\n" + + " } catch (e) { alert(e); }" + + "};" + + "request.send();"; + private static void loadText(String url, Runnable callback, String[] arr) throws IOException { + InvokeJS.CObject.call("loadText", url, new Run(callback), arr); + } + + public static void runHarness(String url) throws IOException { + new Console().harness(url); + } + + public void harness(String url) throws IOException { + log("Connecting to " + url); + Request r = new Request(url); + } + + private static class Request implements Runnable { + private final String[] arr = { null }; + private final String url; + private Case c; + private int retries; + + private Request(String url) throws IOException { + this.url = url; + loadText(url, this, arr); + } + private Request(String url, String u) throws IOException { + this.url = url; + loadText(u, this, arr); + } + + @Override + public void run() { + try { + if (c == null) { + String data = arr[0]; + + if (data == null) { + log("Some error exiting"); + closeWindow(); + return; + } + + if (data.isEmpty()) { + log("No data, exiting"); + closeWindow(); + return; + } + + c = Case.parseData(data); + beginTest(c); + log("Got \"" + data + "\""); + } else { + log("Processing \"" + arr[0] + "\" for " + retries + " time"); + } + Object result = retries++ >= 10 ? "java.lang.InterruptedException:timeout" : c.runTest(); + finishTest(c, result); + + String u = url + "?request=" + c.getRequestId() + "&result=" + result; + new Request(url, u); + } catch (Exception ex) { + if (ex instanceof InterruptedException) { + log("Re-scheduling in 100ms"); + schedule(this, 100); + return; + } + log(ex.getClass().getName() + ":" + ex.getMessage()); + } + } + } + + private static String encodeURL(String r) throws UnsupportedEncodingException { + final String SPECIAL = "%$&+,/:;=?@"; + StringBuilder sb = new StringBuilder(); + byte[] utf8 = r.getBytes("UTF-8"); + for (int i = 0; i < utf8.length; i++) { + int ch = utf8[i] & 0xff; + if (ch < 32 || ch > 127 || SPECIAL.indexOf(ch) >= 0) { + final String numbers = "0" + Integer.toHexString(ch); + sb.append("%").append(numbers.substring(numbers.length() - 2)); + } else { + if (ch == 32) { + sb.append("+"); + } else { + sb.append((char)ch); + } + } + } + return sb.toString(); + } + + static String invoke(String clazz, String method) throws + ClassNotFoundException, InvocationTargetException, IllegalAccessException, + InstantiationException, InterruptedException { + final Object r = new Case(null).invokeMethod(clazz, method); + return r == null ? "null" : r.toString().toString(); + } + + /** Helper method that inspects the classpath and loads given resource + * (usually a class file). Used while running tests in Rhino. + * + * @param name resource name to find + * @return the array of bytes in the given resource + * @throws IOException I/O in case something goes wrong + */ + public static byte[] read(String name) throws IOException { + URL u = null; + Enumeration en = Console.class.getClassLoader().getResources(name); + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u == null) { + throw new IOException("Can't find " + name); + } + try (InputStream is = u.openStream()) { + byte[] arr; + arr = new byte[is.available()]; + int offset = 0; + while (offset < arr.length) { + int len = is.read(arr, offset, arr.length - offset); + if (len == -1) { + throw new IOException("Can't read " + name); + } + offset += len; + } + return arr; + } + } + + private static void turnAssetionStatusOn() { + } + + private static Object schedule(Runnable r, int time) { + return InvokeJS.CObject.call("schedule", new Run(r), time); + } + + private static final class Case { + private final Object data; + private Object inst; + + private Case(Object data) { + this.data = data; + } + + public static Case parseData(String s) { + return new Case(toJSON(s)); + } + + public String getMethodName() { + return (String) value("methodName", data); + } + + public String getClassName() { + return (String) value("className", data); + } + + public int getRequestId() { + Object v = value("request", data); + if (v instanceof Number) { + return ((Number)v).intValue(); + } + return Integer.parseInt(v.toString()); + } + + public String getHtmlFragment() { + return (String) value("html", data); + } + + void again(Object[] arr) { + try { + textArea = arr[0]; + statusArea = arr[1]; + setAttr(textArea, "value", ""); + runTest(); + } catch (Exception ex) { + log(ex.getClass().getName() + ":" + ex.getMessage()); + } + } + + private Object runTest() throws IllegalAccessException, + IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException, + InvocationTargetException, InstantiationException, InterruptedException { + if (this.getHtmlFragment() != null) { + setAttr("bck2brwsr.fragment", "innerHTML", this.getHtmlFragment()); + } + log("Invoking " + this.getClassName() + '.' + this.getMethodName() + " as request: " + this.getRequestId()); + Object result = invokeMethod(this.getClassName(), this.getMethodName()); + setAttr("bck2brwsr.fragment", "innerHTML", ""); + log("Result: " + result); + result = encodeURL("" + result); + log("Sending back: ...?request=" + this.getRequestId() + "&result=" + result); + return result; + } + + private Object invokeMethod(String clazz, String method) + throws ClassNotFoundException, InvocationTargetException, + InterruptedException, IllegalAccessException, IllegalArgumentException, + InstantiationException { + Method found = null; + Class c = Class.forName(clazz); + for (Method m : c.getMethods()) { + if (m.getName().equals(method)) { + found = m; + } + } + Object res; + if (found != null) { + try { + if ((found.getModifiers() & Modifier.STATIC) != 0) { + res = found.invoke(null); + } else { + if (inst == null) { + inst = c.newInstance(); + } + res = found.invoke(inst); + } + } catch (Throwable ex) { + if (ex instanceof InvocationTargetException) { + ex = ((InvocationTargetException) ex).getTargetException(); + } + if (ex instanceof InterruptedException) { + throw (InterruptedException)ex; + } + res = ex.getClass().getName() + ":" + ex.getMessage(); + } + } else { + res = "Can't find method " + method + " in " + clazz; + } + return res; + } + + private static Object toJSON(String s) { + return InvokeJS.CObject.call("toJSON", s); + } + + private static Object value(String p, Object d) { + return ((JSObject)d).getMember(p); + } + } + + private static String safe(String txt) { + return "try {" + txt + "} catch (err) { alert(err); }"; + } + + static { + turnAssetionStatusOn(); + } + + private static final class InvokeJS { + static final JSObject CObject = initJS(); + + private static JSObject initJS() { + WebEngine web = (WebEngine) System.getProperties().get("webEngine"); + return (JSObject) web.executeScript("(function() {" + + "var CObject = {};" + + + "CObject.getAttr = function(elem, attr) { return elem[attr].toString(); };" + + + "CObject.setAttrId = function(id, attr, value) { window.document.getElementById(id)[attr] = value; };" + + "CObject.setAttr = function(elem, attr, value) { elem[attr] = value; };" + + + "CObject.beginTest = function(test, c, arr) {" + safe(BEGIN_TEST) + "};" + + + "CObject.loadText = function(url, callback, arr) {" + safe(LOAD_TEXT.replace("run__V", "run")) + "};" + + + "CObject.schedule = function(r, time) { return window.setTimeout(function() { r.run(); }, time); };" + + + "CObject.toJSON = function(s) { return eval('(' + s + ')'); };" + + + "return CObject;" + + "})(this)"); + } + } + +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,184 @@ +/** + * 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.launcher.fximpl; + +import java.util.List; +import java.util.TooManyListenersException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.HPos; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.geometry.VPos; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.layout.ColumnConstraints; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.scene.text.Text; +import javafx.scene.web.WebEngine; +import javafx.scene.web.WebEvent; +import javafx.scene.web.WebView; +import javafx.stage.Modality; +import javafx.stage.Stage; +import netscape.javascript.JSObject; + +/** + * Demonstrates a WebView object accessing a web page. + * + * @see javafx.scene.web.WebView + * @see javafx.scene.web.WebEngine + */ +public class FXBrwsr extends Application { + private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName()); + + @Override + public void start(Stage primaryStage) throws Exception { + Pane root = new WebViewPane(getParameters().getUnnamed()); + primaryStage.setScene(new Scene(root, 1024, 768)); + LOG.info("Showing the stage"); + primaryStage.show(); + LOG.log(Level.INFO, "State shown: {0}", primaryStage.isShowing()); + } + + /** + * Create a resizable WebView pane + */ + private class WebViewPane extends Pane { + private final JVMBridge bridge = new JVMBridge(); + + public WebViewPane(List params) { + LOG.log(Level.INFO, "Initializing WebView with {0}", params); + VBox.setVgrow(this, Priority.ALWAYS); + setMaxWidth(Double.MAX_VALUE); + setMaxHeight(Double.MAX_VALUE); + WebView view = new WebView(); + view.setMinSize(500, 400); + view.setPrefSize(500, 400); + final WebEngine eng = view.getEngine(); + try { + JVMBridge.addBck2BrwsrLoad(new InitBck2Brwsr(eng)); + } catch (TooManyListenersException ex) { + LOG.log(Level.SEVERE, null, ex); + } + + if (params.size() > 0) { + LOG.log(Level.INFO, "loading page {0}", params.get(0)); + eng.load(params.get(0)); + LOG.fine("back from load"); + } + eng.setOnAlert(new EventHandler>() { + @Override + public void handle(WebEvent t) { + final Stage dialogStage = new Stage(); + dialogStage.initModality(Modality.WINDOW_MODAL); + dialogStage.setTitle("Warning"); + final Button button = new Button("Close"); + final Text text = new Text(t.getData()); + + VBox box = new VBox(); + box.setAlignment(Pos.CENTER); + box.setSpacing(10); + box.setPadding(new Insets(10)); + box.getChildren().addAll(text, button); + + dialogStage.setScene(new Scene(box)); + + button.setCancelButton(true); + button.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent t) { + dialogStage.close(); + } + }); + + dialogStage.centerOnScreen(); + dialogStage.showAndWait(); + } + }); + GridPane grid = new GridPane(); + grid.setVgap(5); + grid.setHgap(5); + GridPane.setConstraints(view, 0, 1, 2, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS); + grid.getColumnConstraints().addAll(new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true), new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true)); + grid.getChildren().addAll(view); + getChildren().add(grid); + } + + boolean initBck2Brwsr(WebEngine webEngine) { + JSObject jsobj = (JSObject) webEngine.executeScript("window"); + LOG.log(Level.FINE, "window: {0}", jsobj); + Object prev = jsobj.getMember("bck2brwsr"); + if ("undefined".equals(prev)) { + System.getProperties().put("webEngine", webEngine); + jsobj.setMember("bck2brwsr", bridge); + return true; + } + return false; + } + + @Override + protected void layoutChildren() { + List managed = getManagedChildren(); + double width = getWidth(); + double height = getHeight(); + double top = getInsets().getTop(); + double right = getInsets().getRight(); + double left = getInsets().getLeft(); + double bottom = getInsets().getBottom(); + for (int i = 0; i < managed.size(); i++) { + Node child = managed.get(i); + layoutInArea(child, left, top, width - left - right, height - top - bottom, 0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER); + } + } + + private class InitBck2Brwsr implements ChangeListener, Runnable { + private final WebEngine eng; + + public InitBck2Brwsr(WebEngine eng) { + this.eng = eng; + } + + @Override + public synchronized void changed(ObservableValue ov, Void t, Void t1) { + Platform.runLater(this); + try { + wait(); + } catch (InterruptedException ex) { + LOG.log(Level.SEVERE, null, ex); + } + } + + @Override + public synchronized void run() { + initBck2Brwsr(eng); + notifyAll(); + } + } + } + +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,64 @@ +/** + * 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.launcher.fximpl; + +import java.util.TooManyListenersException; +import javafx.beans.value.ChangeListener; + +/** + * + * @author Jaroslav Tulach + */ +public final class JVMBridge { + private static ClassLoader[] ldrs; + private static ChangeListener onBck2BrwsrLoad; + + public static void registerClassLoaders(ClassLoader[] loaders) { + ldrs = loaders.clone(); + } + + public static void addBck2BrwsrLoad(ChangeListener l) throws TooManyListenersException { + if (onBck2BrwsrLoad != null) { + throw new TooManyListenersException(); + } + onBck2BrwsrLoad = l; + } + + public static void onBck2BrwsrLoad() { + ChangeListener l = onBck2BrwsrLoad; + if (l != null) { + l.changed(null, null, null); + } + } + + public Class loadClass(String name) throws ClassNotFoundException { + System.err.println("trying to load " + name); + ClassNotFoundException ex = null; + if (ldrs != null) for (ClassLoader l : ldrs) { + try { + return Class.forName(name, true, l); + } catch (ClassNotFoundException ex2) { + ex = ex2; + } + } + if (ex == null) { + ex = new ClassNotFoundException("No loaders"); + } + throw ex; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,35 @@ +/** + * 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.launcher.fximpl; + +/** + * + * @author Jaroslav Tulach + */ +public final class Run implements Runnable { + private final Runnable r; + Run(Runnable r) { + this.r = r; + } + + @Override + public void run() { + r.run(); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/harness.xhtml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/harness.xhtml Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,52 @@ + + + + + + Bck2Brwsr Harness + + + + + +

Bck2Brwsr Execution Harness

+ +
    +
+ +
+ + + + diff -r c7a085d63ab5 -r 3f7991249a20 launcher/http/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/http/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,47 @@ + + + 4.0.0 + + org.apidesign.bck2brwsr + launcher-pom + 0.7-SNAPSHOT + + org.apidesign.bck2brwsr + launcher.http + 0.7-SNAPSHOT + Bck2Brwsr Launcher + http://maven.apache.org + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + UTF-8 + + + + ${project.groupId} + launcher + ${project.version} + + + org.glassfish.grizzly + grizzly-http-server + 2.2.19 + + + ${project.groupId} + vm4brwsr + ${project.version} + + + diff -r c7a085d63ab5 -r 3f7991249a20 launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,604 @@ +/** + * 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.launcher; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource; +import org.apidesign.vm4brwsr.Bck2Brwsr; +import org.glassfish.grizzly.PortRange; +import org.glassfish.grizzly.http.server.HttpHandler; +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.grizzly.http.server.NetworkListener; +import org.glassfish.grizzly.http.server.Request; +import org.glassfish.grizzly.http.server.Response; +import org.glassfish.grizzly.http.server.ServerConfiguration; +import org.glassfish.grizzly.http.util.HttpStatus; + +/** + * Lightweight server to launch Bck2Brwsr applications and tests. + * Supports execution in native browser as well as Java's internal + * execution engine. + */ +final class Bck2BrwsrLauncher extends Launcher implements Closeable { + private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName()); + private static final InvocationContext END = new InvocationContext(null, null, null); + private final Set loaders = new LinkedHashSet<>(); + private final BlockingQueue methods = new LinkedBlockingQueue<>(); + private long timeOut; + private final Res resources = new Res(); + private final String cmd; + private Object[] brwsr; + private HttpServer server; + private CountDownLatch wait; + + public Bck2BrwsrLauncher(String cmd) { + this.cmd = cmd; + addClassLoader(Bck2Brwsr.class.getClassLoader()); + setTimeout(180000); + } + + @Override + InvocationContext runMethod(InvocationContext c) throws IOException { + loaders.add(c.clazz.getClassLoader()); + methods.add(c); + try { + c.await(timeOut); + } catch (InterruptedException ex) { + throw new IOException(ex); + } + return c; + } + + public void setTimeout(long ms) { + timeOut = ms; + } + + public void addClassLoader(ClassLoader url) { + this.loaders.add(url); + } + + public void showURL(String startpage) throws IOException { + if (!startpage.startsWith("/")) { + startpage = "/" + startpage; + } + HttpServer s = initServer(".", true); + int last = startpage.lastIndexOf('/'); + String prefix = startpage.substring(0, last); + String simpleName = startpage.substring(last); + s.getServerConfiguration().addHttpHandler(new SubTree(resources, prefix), "/"); + try { + launchServerAndBrwsr(s, simpleName); + } catch (URISyntaxException | InterruptedException ex) { + throw new IOException(ex); + } + } + + void showDirectory(File dir, String startpage) throws IOException { + if (!startpage.startsWith("/")) { + startpage = "/" + startpage; + } + HttpServer s = initServer(dir.getPath(), false); + try { + launchServerAndBrwsr(s, startpage); + } catch (URISyntaxException | InterruptedException ex) { + throw new IOException(ex); + } + } + + @Override + public void initialize() throws IOException { + try { + executeInBrowser(); + } catch (InterruptedException ex) { + final InterruptedIOException iio = new InterruptedIOException(ex.getMessage()); + iio.initCause(ex); + throw iio; + } catch (Exception ex) { + if (ex instanceof IOException) { + throw (IOException)ex; + } + if (ex instanceof RuntimeException) { + throw (RuntimeException)ex; + } + throw new IOException(ex); + } + } + + private HttpServer initServer(String path, boolean addClasses) throws IOException { + HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535)); + + final ServerConfiguration conf = s.getServerConfiguration(); + if (addClasses) { + conf.addHttpHandler(new VM(resources), "/bck2brwsr.js"); + conf.addHttpHandler(new Classes(resources), "/classes/"); + } + return s; + } + + private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException { + wait = new CountDownLatch(1); + server = initServer(".", true); + final ServerConfiguration conf = server.getServerConfiguration(); + + class DynamicResourceHandler extends HttpHandler { + private final InvocationContext ic; + public DynamicResourceHandler(InvocationContext ic) { + if (ic == null || ic.resources.isEmpty()) { + throw new NullPointerException(); + } + this.ic = ic; + for (Resource r : ic.resources) { + conf.addHttpHandler(this, r.httpPath); + } + } + + public void close() { + conf.removeHttpHandler(this); + } + + @Override + public void service(Request request, Response response) throws Exception { + for (Resource r : ic.resources) { + if (r.httpPath.equals(request.getRequestURI())) { + LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI()); + response.setContentType(r.httpType); + r.httpContent.reset(); + String[] params = null; + if (r.parameters.length != 0) { + params = new String[r.parameters.length]; + for (int i = 0; i < r.parameters.length; i++) { + params[i] = request.getParameter(r.parameters[i]); + } + } + + copyStream(r.httpContent, response.getOutputStream(), null, params); + } + } + } + } + + conf.addHttpHandler(new Page(resources, + "org/apidesign/bck2brwsr/launcher/harness.xhtml" + ), "/execute"); + + conf.addHttpHandler(new HttpHandler() { + int cnt; + List cases = new ArrayList<>(); + DynamicResourceHandler prev; + @Override + public void service(Request request, Response response) throws Exception { + String id = request.getParameter("request"); + String value = request.getParameter("result"); + if (value != null && value.indexOf((char)0xC5) != -1) { + value = toUTF8(value); + } + + + InvocationContext mi = null; + int caseNmbr = -1; + + if (id != null && value != null) { + LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value}); + value = decodeURL(value); + int indx = Integer.parseInt(id); + cases.get(indx).result(value, null); + if (++indx < cases.size()) { + mi = cases.get(indx); + LOG.log(Level.INFO, "Re-executing case {0}", indx); + caseNmbr = indx; + } + } else { + if (!cases.isEmpty()) { + LOG.info("Re-executing test cases"); + mi = cases.get(0); + caseNmbr = 0; + } + } + + if (prev != null) { + prev.close(); + prev = null; + } + + if (mi == null) { + mi = methods.take(); + caseNmbr = cnt++; + } + if (mi == END) { + response.getWriter().write(""); + wait.countDown(); + cnt = 0; + LOG.log(Level.INFO, "End of data reached. Exiting."); + return; + } + + if (!mi.resources.isEmpty()) { + prev = new DynamicResourceHandler(mi); + } + + cases.add(mi); + final String cn = mi.clazz.getName(); + final String mn = mi.methodName; + LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn}); + response.getWriter().write("{" + + "className: '" + cn + "', " + + "methodName: '" + mn + "', " + + "request: " + caseNmbr + ); + if (mi.html != null) { + response.getWriter().write(", html: '"); + response.getWriter().write(encodeJSON(mi.html)); + response.getWriter().write("'"); + } + response.getWriter().write("}"); + } + }, "/data"); + + this.brwsr = launchServerAndBrwsr(server, "/execute"); + } + + private static String encodeJSON(String in) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < in.length(); i++) { + char ch = in.charAt(i); + if (ch < 32 || ch == '\'' || ch == '"') { + sb.append("\\u"); + String hs = "0000" + Integer.toHexString(ch); + hs = hs.substring(hs.length() - 4); + sb.append(hs); + } else { + sb.append(ch); + } + } + return sb.toString(); + } + + @Override + public void shutdown() throws IOException { + methods.offer(END); + for (;;) { + int prev = methods.size(); + try { + if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) { + break; + } + } catch (InterruptedException ex) { + throw new IOException(ex); + } + if (prev == methods.size()) { + LOG.log( + Level.WARNING, + "Timeout and no test has been executed meanwhile (at {0}). Giving up.", + methods.size() + ); + break; + } + LOG.log(Level.INFO, + "Timeout, but tests got from {0} to {1}. Trying again.", + new Object[]{prev, methods.size()} + ); + } + stopServerAndBrwsr(server, brwsr); + } + + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException { + for (;;) { + int ch = is.read(); + if (ch == -1) { + break; + } + if (ch == '$' && params.length > 0) { + int cnt = is.read() - '0'; + if (baseURL != null && cnt == 'U' - '0') { + os.write(baseURL.getBytes("UTF-8")); + } else { + if (cnt >= 0 && cnt < params.length) { + os.write(params[cnt].getBytes("UTF-8")); + } else { + os.write('$'); + os.write(cnt + '0'); + } + } + } else { + os.write(ch); + } + } + } + + private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException { + server.start(); + NetworkListener listener = server.getListeners().iterator().next(); + int port = listener.getPort(); + + URI uri = new URI("http://localhost:" + port + page); + LOG.log(Level.INFO, "Showing {0}", uri); + if (cmd == null) { + try { + LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] { + System.getProperty("java.vm.name"), + System.getProperty("java.vm.vendor"), + System.getProperty("java.vm.version"), + }); + java.awt.Desktop.getDesktop().browse(uri); + LOG.log(Level.INFO, "Desktop.browse successfully finished"); + return null; + } catch (UnsupportedOperationException ex) { + LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage()); + LOG.log(Level.FINE, null, ex); + } + } + { + String cmdName = cmd == null ? "xdg-open" : cmd; + String[] cmdArr = { + cmdName, uri.toString() + }; + LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr)); + final Process process = Runtime.getRuntime().exec(cmdArr); + return new Object[] { process, null }; + } + } + private static String toUTF8(String value) throws UnsupportedEncodingException { + byte[] arr = new byte[value.length()]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (byte)value.charAt(i); + } + return new String(arr, "UTF-8"); + } + + private static String decodeURL(String s) { + for (;;) { + int pos = s.indexOf('%'); + if (pos == -1) { + return s; + } + int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16); + s = s.substring(0, pos) + (char)i + s.substring(pos + 2); + } + } + + private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException { + if (brwsr == null) { + return; + } + Process process = (Process)brwsr[0]; + + server.stop(); + InputStream stdout = process.getInputStream(); + InputStream stderr = process.getErrorStream(); + drain("StdOut", stdout); + drain("StdErr", stderr); + process.destroy(); + int res; + try { + res = process.waitFor(); + } catch (InterruptedException ex) { + throw new IOException(ex); + } + LOG.log(Level.INFO, "Exit code: {0}", res); + + deleteTree((File)brwsr[1]); + } + + private static void drain(String name, InputStream is) throws IOException { + int av = is.available(); + if (av > 0) { + StringBuilder sb = new StringBuilder(); + sb.append("v== ").append(name).append(" ==v\n"); + while (av-- > 0) { + sb.append((char)is.read()); + } + sb.append("\n^== ").append(name).append(" ==^"); + LOG.log(Level.INFO, sb.toString()); + } + } + + private void deleteTree(File file) { + if (file == null) { + return; + } + File[] arr = file.listFiles(); + if (arr != null) { + for (File s : arr) { + deleteTree(s); + } + } + file.delete(); + } + + @Override + public void close() throws IOException { + shutdown(); + } + + private class Res implements Bck2Brwsr.Resources { + @Override + public InputStream get(String resource) throws IOException { + URL u = null; + for (ClassLoader l : loaders) { + Enumeration en = l.getResources(resource); + while (en.hasMoreElements()) { + u = en.nextElement(); + } + } + if (u != null) { + return u.openStream(); + } + throw new IOException("Can't find " + resource); + } + } + + private static class Page extends HttpHandler { + final String resource; + private final String[] args; + private final Res res; + + public Page(Res res, String resource, String... args) { + this.res = res; + this.resource = resource; + this.args = args.length == 0 ? new String[] { "$0" } : args; + } + + @Override + public void service(Request request, Response response) throws Exception { + String r = computePage(request); + if (r.startsWith("/")) { + r = r.substring(1); + } + String[] replace = {}; + if (r.endsWith(".html")) { + response.setContentType("text/html"); + LOG.info("Content type text/html"); + replace = args; + } + if (r.endsWith(".xhtml")) { + response.setContentType("application/xhtml+xml"); + LOG.info("Content type application/xhtml+xml"); + replace = args; + } + OutputStream os = response.getOutputStream(); + try (InputStream is = res.get(r)) { + copyStream(is, os, request.getRequestURL().toString(), replace); + } catch (IOException ex) { + response.setDetailMessage(ex.getLocalizedMessage()); + response.setError(); + response.setStatus(404); + } + } + + protected String computePage(Request request) { + String r = resource; + if (r == null) { + r = request.getHttpHandlerPath(); + } + return r; + } + } + + private static class SubTree extends Page { + + public SubTree(Res res, String resource, String... args) { + super(res, resource, args); + } + + @Override + protected String computePage(Request request) { + return resource + request.getHttpHandlerPath(); + } + + + } + + private static class VM extends HttpHandler { + private final String bck2brwsr; + + public VM(Res loader) throws IOException { + StringBuilder sb = new StringBuilder(); + Bck2Brwsr.generate(sb, loader); + sb.append( + "(function WrapperVM(global) {" + + " function ldCls(res) {\n" + + " var request = new XMLHttpRequest();\n" + + " request.open('GET', '/classes/' + res, false);\n" + + " request.send();\n" + + " if (request.status !== 200) return null;\n" + + " var arr = eval('(' + request.responseText + ')');\n" + + " return arr;\n" + + " }\n" + + " var prevvm = global.bck2brwsr;\n" + + " global.bck2brwsr = function() {\n" + + " var args = Array.prototype.slice.apply(arguments);\n" + + " args.unshift(ldCls);\n" + + " return prevvm.apply(null, args);\n" + + " };\n" + + "})(this);\n" + ); + this.bck2brwsr = sb.toString(); + } + + @Override + public void service(Request request, Response response) throws Exception { + response.setCharacterEncoding("UTF-8"); + response.setContentType("text/javascript"); + response.getWriter().write(bck2brwsr); + } + } + + private static class Classes extends HttpHandler { + private final Res loader; + + public Classes(Res loader) { + this.loader = loader; + } + + @Override + public void service(Request request, Response response) throws Exception { + String res = request.getHttpHandlerPath(); + if (res.startsWith("/")) { + res = res.substring(1); + } + try (InputStream is = loader.get(res)) { + response.setContentType("text/javascript"); + Writer w = response.getWriter(); + w.append("["); + for (int i = 0;; i++) { + int b = is.read(); + if (b == -1) { + break; + } + if (i > 0) { + w.append(", "); + } + if (i % 20 == 0) { + w.write("\n"); + } + if (b > 127) { + b = b - 256; + } + w.append(Integer.toString(b)); + } + w.append("\n]"); + } catch (IOException ex) { + response.setStatus(HttpStatus.NOT_FOUND_404); + response.setError(); + response.setDetailMessage(ex.getMessage()); + } + } + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,135 @@ +/** + * 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.launcher; + +import org.apidesign.bck2brwsr.launcher.impl.Console; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.script.Invocable; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import org.apidesign.vm4brwsr.Bck2Brwsr; + +/** + * Tests execution in Java's internal scripting engine. + */ +final class JSLauncher extends Launcher { + private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName()); + private Set loaders = new LinkedHashSet<>(); + private final Res resources = new Res(); + private Invocable code; + private StringBuilder codeSeq; + private Object console; + + JSLauncher() { + addClassLoader(Bck2Brwsr.class.getClassLoader()); + } + + @Override InvocationContext runMethod(InvocationContext mi) { + loaders.add(mi.clazz.getClassLoader()); + try { + long time = System.currentTimeMillis(); + LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName}); + String res = code.invokeMethod( + console, + "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2", + mi.clazz.getName(), mi.methodName).toString(); + time = System.currentTimeMillis() - time; + LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time}); + mi.result(res, null); + } catch (ScriptException | NoSuchMethodException ex) { + mi.result(null, ex); + } + return mi; + } + + public void addClassLoader(ClassLoader url) { + this.loaders.add(url); + } + + @Override + public void initialize() throws IOException { + try { + initRhino(); + } catch (Exception ex) { + if (ex instanceof IOException) { + throw (IOException)ex; + } + if (ex instanceof RuntimeException) { + throw (RuntimeException)ex; + } + throw new IOException(ex); + } + } + + private void initRhino() throws IOException, ScriptException, NoSuchMethodException { + StringBuilder sb = new StringBuilder(); + Bck2Brwsr.generate(sb, new Res()); + + ScriptEngineManager sem = new ScriptEngineManager(); + ScriptEngine mach = sem.getEngineByExtension("js"); + + sb.append( + "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);" + + "\nfunction initVM() { return vm; };" + + "\n"); + + Object res = mach.eval(sb.toString()); + if (!(mach instanceof Invocable)) { + throw new IOException("It is invocable object: " + res); + } + code = (Invocable) mach; + codeSeq = sb; + + Object vm = code.invokeFunction("initVM"); + console = code.invokeMethod(vm, "loadClass", Console.class.getName()); + } + + @Override + public void shutdown() throws IOException { + } + + @Override + public String toString() { + return codeSeq.toString(); + } + + private class Res implements Bck2Brwsr.Resources { + @Override + public InputStream get(String resource) throws IOException { + for (ClassLoader l : loaders) { + URL u = null; + Enumeration en = l.getResources(resource); + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u != null) { + return u.openStream(); + } + } + throw new IOException("Can't find " + resource); + } + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,356 @@ +/** + * 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.launcher.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.Enumeration; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Jaroslav Tulach + */ +public class Console { + private Console() { + } + static { + turnAssetionStatusOn(); + } + + @JavaScriptBody(args = {"id", "attr"}, body = + "return window.document.getElementById(id)[attr].toString();") + private static native Object getAttr(String id, String attr); + @JavaScriptBody(args = {"elem", "attr"}, body = + "return elem[attr].toString();") + private static native Object getAttr(Object elem, String attr); + + @JavaScriptBody(args = {"id", "attr", "value"}, body = + "window.document.getElementById(id)[attr] = value;") + private static native void setAttr(String id, String attr, Object value); + @JavaScriptBody(args = {"elem", "attr", "value"}, body = + "elem[attr] = value;") + private static native void setAttr(Object id, String attr, Object value); + + @JavaScriptBody(args = {}, body = "return; window.close();") + private static native void closeWindow(); + + private static Object textArea; + private static Object statusArea; + + private static void log(String newText) { + if (textArea == null) { + return; + } + String attr = "value"; + setAttr(textArea, attr, getAttr(textArea, attr) + "\n" + newText); + setAttr(textArea, "scrollTop", getAttr(textArea, "scrollHeight")); + } + + private static void beginTest(Case c) { + Object[] arr = new Object[2]; + beginTest(c.getClassName() + "." + c.getMethodName(), c, arr); + textArea = arr[0]; + statusArea = arr[1]; + } + + private static void finishTest(Case c, Object res) { + if ("null".equals(res)) { + setAttr(statusArea, "innerHTML", "Success"); + } else { + setAttr(statusArea, "innerHTML", "Result " + res); + } + statusArea = null; + textArea = null; + } + + @JavaScriptBody(args = { "test", "c", "arr" }, body = + "var ul = window.document.getElementById('bck2brwsr.result');\n" + + "var li = window.document.createElement('li');\n" + + "var span = window.document.createElement('span');" + + "span.innerHTML = test + ' - ';\n" + + "var details = window.document.createElement('a');\n" + + "details.innerHTML = 'Details';\n" + + "details.href = '#';\n" + + "var p = window.document.createElement('p');\n" + + "var status = window.document.createElement('a');\n" + + "status.innerHTML = 'running';" + + "details.onclick = function() { li.appendChild(p); li.removeChild(details); status.innerHTML = 'Run Again'; status.href = '#'; };\n" + + "status.onclick = function() { c.again__V_3Ljava_lang_Object_2(arr); }\n" + + "var pre = window.document.createElement('textarea');\n" + + "pre.cols = 100;" + + "pre.rows = 10;" + + "li.appendChild(span);\n" + + "li.appendChild(status);\n" + + "var span = window.document.createElement('span');" + + "span.innerHTML = ' ';\n" + + "li.appendChild(span);\n" + + "li.appendChild(details);\n" + + "p.appendChild(pre);\n" + + "ul.appendChild(li);\n" + + "arr[0] = pre;\n" + + "arr[1] = status;\n" + ) + private static native void beginTest(String test, Case c, Object[] arr); + + @JavaScriptBody(args = { "url", "callback", "arr" }, body = "" + + "var request = new XMLHttpRequest();\n" + + "request.open('GET', url, true);\n" + + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n" + + "request.onreadystatechange = function() {\n" + + " if (this.readyState!==4) return;\n" + + " arr[0] = this.responseText;\n" + + " callback.run__V();\n" + + "};" + + "request.send();" + ) + private static native void loadText(String url, Runnable callback, String[] arr) throws IOException; + + public static void harness(String url) throws IOException { + log("Connecting to " + url); + Request r = new Request(url); + } + + private static class Request implements Runnable { + private final String[] arr = { null }; + private final String url; + private Case c; + private int retries; + + private Request(String url) throws IOException { + this.url = url; + loadText(url, this, arr); + } + private Request(String url, String u) throws IOException { + this.url = url; + loadText(u, this, arr); + } + + @Override + public void run() { + try { + if (c == null) { + String data = arr[0]; + + if (data == null) { + log("Some error exiting"); + closeWindow(); + return; + } + + if (data.isEmpty()) { + log("No data, exiting"); + closeWindow(); + return; + } + + c = Case.parseData(data); + beginTest(c); + log("Got \"" + data + "\""); + } else { + log("Processing \"" + arr[0] + "\" for " + retries + " time"); + } + Object result = retries++ >= 10 ? "java.lang.InterruptedException:timeout" : c.runTest(); + finishTest(c, result); + + String u = url + "?request=" + c.getRequestId() + "&result=" + result; + new Request(url, u); + } catch (Exception ex) { + if (ex instanceof InterruptedException) { + log("Re-scheduling in 100ms"); + schedule(this, 100); + return; + } + log(ex.getClass().getName() + ":" + ex.getMessage()); + } + } + } + + private static String encodeURL(String r) throws UnsupportedEncodingException { + final String SPECIAL = "%$&+,/:;=?@"; + StringBuilder sb = new StringBuilder(); + byte[] utf8 = r.getBytes("UTF-8"); + for (int i = 0; i < utf8.length; i++) { + int ch = utf8[i] & 0xff; + if (ch < 32 || ch > 127 || SPECIAL.indexOf(ch) >= 0) { + final String numbers = "0" + Integer.toHexString(ch); + sb.append("%").append(numbers.substring(numbers.length() - 2)); + } else { + if (ch == 32) { + sb.append("+"); + } else { + sb.append((char)ch); + } + } + } + return sb.toString(); + } + + static String invoke(String clazz, String method) throws + ClassNotFoundException, InvocationTargetException, IllegalAccessException, + InstantiationException, InterruptedException { + final Object r = new Case(null).invokeMethod(clazz, method); + return r == null ? "null" : r.toString().toString(); + } + + /** Helper method that inspects the classpath and loads given resource + * (usually a class file). Used while running tests in Rhino. + * + * @param name resource name to find + * @return the array of bytes in the given resource + * @throws IOException I/O in case something goes wrong + */ + public static byte[] read(String name) throws IOException { + URL u = null; + Enumeration en = Console.class.getClassLoader().getResources(name); + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u == null) { + throw new IOException("Can't find " + name); + } + try (InputStream is = u.openStream()) { + byte[] arr; + arr = new byte[is.available()]; + int offset = 0; + while (offset < arr.length) { + int len = is.read(arr, offset, arr.length - offset); + if (len == -1) { + throw new IOException("Can't read " + name); + } + offset += len; + } + return arr; + } + } + + @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;") + private static void turnAssetionStatusOn() { + } + + @JavaScriptBody(args = {"r", "time"}, body = + "return window.setTimeout(function() { r.run__V(); }, time);") + private static native Object schedule(Runnable r, int time); + + private static final class Case { + private final Object data; + private Object inst; + + private Case(Object data) { + this.data = data; + } + + public static Case parseData(String s) { + return new Case(toJSON(s)); + } + + public String getMethodName() { + return value("methodName", data); + } + + public String getClassName() { + return value("className", data); + } + + public String getRequestId() { + return value("request", data); + } + + public String getHtmlFragment() { + return value("html", data); + } + + void again(Object[] arr) { + try { + textArea = arr[0]; + statusArea = arr[1]; + setAttr(textArea, "value", ""); + runTest(); + } catch (Exception ex) { + log(ex.getClass().getName() + ":" + ex.getMessage()); + } + } + + private Object runTest() throws IllegalAccessException, + IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException, + InvocationTargetException, InstantiationException, InterruptedException { + if (this.getHtmlFragment() != null) { + setAttr("bck2brwsr.fragment", "innerHTML", this.getHtmlFragment()); + } + log("Invoking " + this.getClassName() + '.' + this.getMethodName() + " as request: " + this.getRequestId()); + Object result = invokeMethod(this.getClassName(), this.getMethodName()); + setAttr("bck2brwsr.fragment", "innerHTML", ""); + log("Result: " + result); + result = encodeURL("" + result); + log("Sending back: ...?request=" + this.getRequestId() + "&result=" + result); + return result; + } + + private Object invokeMethod(String clazz, String method) + throws ClassNotFoundException, InvocationTargetException, + InterruptedException, IllegalAccessException, IllegalArgumentException, + InstantiationException { + Method found = null; + Class c = Class.forName(clazz); + for (Method m : c.getMethods()) { + if (m.getName().equals(method)) { + found = m; + } + } + Object res; + if (found != null) { + try { + if ((found.getModifiers() & Modifier.STATIC) != 0) { + res = found.invoke(null); + } else { + if (inst == null) { + inst = c.newInstance(); + } + res = found.invoke(inst); + } + } catch (Throwable ex) { + if (ex instanceof InvocationTargetException) { + ex = ((InvocationTargetException) ex).getTargetException(); + } + if (ex instanceof InterruptedException) { + throw (InterruptedException)ex; + } + res = ex.getClass().getName() + ":" + ex.getMessage(); + } + } else { + res = "Can't find method " + method + " in " + clazz; + } + return res; + } + + @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');") + private static native Object toJSON(String s); + + @JavaScriptBody(args = {"p", "d"}, body = + "var v = d[p];\n" + + "if (typeof v === 'undefined') return null;\n" + + "return v.toString();" + ) + private static native String value(String p, Object d); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 launcher/http/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/http/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,43 @@ + + + + + + Bck2Brwsr Harness + + + + + +

Bck2Brwsr Execution Harness

+ +
    +
+ +
+ + + + diff -r c7a085d63ab5 -r 3f7991249a20 launcher/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,19 @@ + + + 4.0.0 + + bck2brwsr + org.apidesign + 0.7-SNAPSHOT + + org.apidesign.bck2brwsr + launcher-pom + 0.7-SNAPSHOT + pom + Launchers + + api + http + fx + + \ No newline at end of file diff -r c7a085d63ab5 -r 3f7991249a20 pom.xml --- a/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -21,6 +21,7 @@ javaquery benchmarks ide + launcher rt @@ -86,7 +87,7 @@ rt/emul/*/src/main/** rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java rt/archetype/src/main/resources/archetype-resources/** - rt/vmtest/src/test/resources/** + rt/emul/compact/src/test/resources/** dew/src/main/resources/org/apidesign/bck2brwsr/dew/** javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout*.js @@ -256,4 +257,4 @@ - \ No newline at end of file + diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/brwsrtest/pom.xml --- a/rt/emul/brwsrtest/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/emul/brwsrtest/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -42,5 +42,11 @@ ${project.version} test + + ${project.groupId} + launcher.http + ${project.version} + provided + diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/pom.xml --- a/rt/emul/compact/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/emul/compact/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -28,6 +28,12 @@ test + ${project.groupId} + launcher.http + ${project.version} + test + + org.netbeans.api org-openide-util-lookup test diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,43 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class AssertionTest { + + @Compare public Object checkAssert() throws ClassNotFoundException { + try { + assert false : "Is assertion status on?"; + return null; + } catch (AssertionError ex) { + return ex.getClass().getName(); + } + } + + @Factory + public static Object[] create() { + return VMTest.create(AssertionTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,57 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.HtmlFragment; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class BrwsrCheckTest { + + @BrwsrTest public void assertWindowObjectIsDefined() { + assert window() != null : "No window object found!"; + } + + + + + @HtmlFragment("

\n" + + "Hello!\n" + + "

\n") + @BrwsrTest public void accessProvidedFragment() { + assert getElementById("hello") != null : "Element with 'hello' ID found"; + } + + @Factory + public static Object[] create() { + return VMTest.create(BrwsrCheckTest.class); + } + + + @JavaScriptBody(args = {}, body = "return window;") + private static native Object window(); + + @JavaScriptBody(args = { "id" }, body = "return window.document.getElementById(id);") + private static native Object getElementById(String id); +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,147 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ByteArithmeticTest { + + private static byte add(byte x, byte y) { + return (byte)(x + y); + } + + private static byte sub(byte x, byte y) { + return (byte)(x - y); + } + + private static byte mul(byte x, byte y) { + return (byte)(x * y); + } + + private static byte div(byte x, byte y) { + return (byte)(x / y); + } + + private static byte mod(byte x, byte y) { + return (byte)(x % y); + } + + @Compare public byte conversion() { + return (byte)123456; + } + + @Compare public byte addOverflow() { + return add(Byte.MAX_VALUE, (byte)1); + } + + @Compare public byte subUnderflow() { + return sub(Byte.MIN_VALUE, (byte)1); + } + + @Compare public byte addMaxByteAndMaxByte() { + return add(Byte.MAX_VALUE, Byte.MAX_VALUE); + } + + @Compare public byte subMinByteAndMinByte() { + return sub(Byte.MIN_VALUE, Byte.MIN_VALUE); + } + + @Compare public byte multiplyMaxByte() { + return mul(Byte.MAX_VALUE, (byte)2); + } + + @Compare public byte multiplyMaxByteAndMaxByte() { + return mul(Byte.MAX_VALUE, Byte.MAX_VALUE); + } + + @Compare public byte multiplyMinByte() { + return mul(Byte.MIN_VALUE, (byte)2); + } + + @Compare public byte multiplyMinByteAndMinByte() { + return mul(Byte.MIN_VALUE, Byte.MIN_VALUE); + } + + @Compare public byte multiplyPrecision() { + return mul((byte)17638, (byte)1103); + } + + @Compare public byte division() { + return div((byte)1, (byte)2); + } + + @Compare public byte divisionReminder() { + return mod((byte)1, (byte)2); + } + + private static int readShort(byte[] byteCodes, int offset) { + int signed = byteCodes[offset]; + byte b0 = (byte)signed; + return (b0 << 8) | (byteCodes[offset + 1] & 0xff); + } + + private static int readShortArg(byte[] byteCodes, int offsetInstruction) { + return readShort(byteCodes, offsetInstruction + 1); + } + + @Compare public int readIntArgs255and156() { + final byte[] arr = new byte[] { (byte)0, (byte)255, (byte)156 }; + + assert arr[1] == -1 : "First byte: " + arr[1]; + assert arr[2] == -100 : "Second byte: " + arr[2]; + final int ret = readShortArg(arr, 0); + assert ret < 65000: "Value: " + ret; + return ret; + } + + @JavaScriptBody(args = { "arr" }, body = "arr[1] = 255; arr[2] = 156; return arr;") + private static byte[] fill255and156(byte[] arr) { + arr[1] = (byte)255; + arr[2] = (byte)156; + return arr; + } + + @Compare public int readIntArgs255and156JSArray() { + final byte[] arr = fill255and156(new byte[] { 0, 0, 0 }); + + final int ret = readShortArg(arr, 0); + assert ret < 65000: "Value: " + ret; + return ret; + } + + @Compare public int readIntArgsMinus1andMinus100() { + final byte[] arr = new byte[] { (byte)0, (byte)-1, (byte)-100 }; + + assert arr[1] == -1 : "First byte: " + arr[1]; + assert arr[2] == -100 : "Second byte: " + arr[2]; + + return readShortArg(arr, 0); + } + + @Factory + public static Object[] create() { + return VMTest.create(ByteArithmeticTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,73 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CloneTest { + private int value; + + @Compare + public Object notSupported() throws CloneNotSupportedException { + return this.clone(); + } + + @Compare public String sameClass() throws CloneNotSupportedException { + return new Clnbl().clone().getClass().getName(); + } + + @Compare public boolean differentInstance() throws CloneNotSupportedException { + Clnbl orig = new Clnbl(); + return orig == orig.clone(); + } + + @Compare public int sameReference() throws CloneNotSupportedException { + CloneTest self = this; + Clnbl orig = new Clnbl(); + self.value = 33; + orig.ref = self; + return ((Clnbl)orig.clone()).ref.value; + } + + @Compare public int sameValue() throws CloneNotSupportedException { + Clnbl orig = new Clnbl(); + orig.value = 10; + return ((Clnbl)orig.clone()).value; + } + + @Factory + public static Object[] create() { + return VMTest.create(CloneTest.class); + } + + public static final class Clnbl implements Cloneable { + public CloneTest ref; + private int value; + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,103 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CompareByteArrayTest { + @Compare public int byteArraySum() { + byte[] arr = createArray(); + return sumByteArr(arr); + } + + @Compare public int countZeros() { + int zeros = 0; + for (Byte b : createArray()) { + if (b == 0) { + zeros++; + } + } + return zeros; + } + + private static int sumByteArr(byte[] arr) { + int sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + } + return sum; + } + + @Compare public String noOutOfBounds() { + return atIndex(1); + } + + @Compare public String outOfBounds() { + return atIndex(5); + } + + @Compare public String outOfBoundsMinus() { + return atIndex(-1); + } + + @Compare public String toOfBounds() { + return toIndex(5); + } + + @Compare public String toOfBoundsMinus() { + return toIndex(-1); + } + + @Compare public int multiArrayLength() { + int[][] arr = new int[1][0]; + return arr[0].length; + } + + @Compare public int multiObjectArrayLength() { + Object[][] arr = new Object[1][0]; + return arr[0].length; + } + + private static final int[] arr = { 0, 1, 2 }; + public static String atIndex(int at) { + return "at@" + arr[at]; + } + public static String toIndex(int at) { + arr[at] = 10; + return "ok"; + } + + + @Factory + public static Object[] create() { + return VMTest.create(CompareByteArrayTest.class); + } + + private byte[] createArray() { + byte[] arr = new byte[10]; + arr[5] = 3; + arr[7] = 8; + return arr; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,50 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CompareHashTest { + @Compare public int hashOfString() { + return "Ahoj".hashCode(); + } + + @Compare public int hashRemainsYieldsZero() { + Object o = new Object(); + return o.hashCode() - o.hashCode(); + } + + @Compare public int initializeInStatic() { + return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode(); + } + + @Compare public int hashOfInt() { + return Integer.valueOf(Integer.MAX_VALUE).hashCode(); + } + + @Factory + public static Object[] create() { + return VMTest.create(CompareHashTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,63 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CompareIntArrayTest { + @Compare public int integerArraySum() { + int[] arr = createArray(); + return sumIntArr(arr); + } + + @Compare public int countZeros() { + int zeros = 0; + for (Integer i : createArray()) { + if (i == 0) { + zeros++; + } + } + return zeros; + } + + private static int sumIntArr(int[] arr) { + int sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + } + return sum; + } + + @Factory + public static Object[] create() { + return VMTest.create(CompareIntArrayTest.class); + } + + private int[] createArray() { + int[] arr = new int[10]; + arr[5] = 3; + arr[7] = 8; + return arr; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,174 @@ +/** + * 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.tck; + +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CompareStringsTest { + @Compare public String firstChar() { + return "" + ("Hello".toCharArray()[0]); + } + + @Compare public String classCast() { + Object o = firstChar(); + return String.class.cast(o); + } + + @Compare public String classCastThrown() { + Object o = null; + return String.class.cast(o); + } + + @Compare public boolean equalToNull() { + return "Ahoj".equals(null); + } + + @Compare public int highByteLenght() { + byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 }; + return new String(arr, 0).length(); + } + + @Compare public String highByte() { + byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 }; + StringBuilder sb = new StringBuilder(); + sb.append("pref:"); + sb.append(new String(arr, 0)); + return sb.toString(); + } + + @Compare public static Object compareURLs() throws MalformedURLException { + return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString(); + } + + @Compare public String deleteLastTwoCharacters() { + StringBuilder sb = new StringBuilder(); + sb.append("453.0"); + if (sb.toString().endsWith(".0")) { + final int l = sb.length(); + sb.delete(l - 2, l); + } + return sb.toString().toString(); + } + + @Compare public String nameOfStringClass() throws Exception { + return Class.forName("java.lang.String").getName(); + } + @Compare public String nameOfArrayClass() throws Exception { + return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName(); + } + + @Compare public String lowerHello() { + return "HeLlO".toLowerCase(); + } + + @Compare public String lowerA() { + return String.valueOf(Character.toLowerCase('A')).toString(); + } + @Compare public String upperHello() { + return "hello".toUpperCase(); + } + + @Compare public String upperA() { + return String.valueOf(Character.toUpperCase('a')).toString(); + } + + @Compare public boolean matchRegExp() throws Exception { + return "58038503".matches("\\d*"); + } + + @Compare public boolean doesNotMatchRegExp() throws Exception { + return "58038503GH".matches("\\d*"); + } + + @Compare public boolean doesNotMatchRegExpFully() throws Exception { + return "Hello".matches("Hell"); + } + + @Compare public String emptyCharArray() { + char[] arr = new char[10]; + return new String(arr); + } + + @Compare public String variousCharacterTests() throws Exception { + StringBuilder sb = new StringBuilder(); + + sb.append(Character.isUpperCase('a')); + sb.append(Character.isUpperCase('A')); + sb.append(Character.isLowerCase('a')); + sb.append(Character.isLowerCase('A')); + + sb.append(Character.isLetter('A')); + sb.append(Character.isLetterOrDigit('9')); + sb.append(Character.isLetterOrDigit('A')); + sb.append(Character.isLetter('0')); + + return sb.toString().toString(); + } + + @Compare + public String nullFieldInitialized() { + NullField nf = new NullField(); + return ("" + nf.name).toString(); + } + @Compare + public String toUTFString() throws UnsupportedEncodingException { + byte[] arr = { + (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91, + (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61, + (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59, + (byte) -120 + }; + return new String(arr, "utf-8"); + } + + @Compare + public int stringToBytesLenght() throws UnsupportedEncodingException { + return "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("utf8").length; + } + + @Compare public String replaceSeq() { + return "Hello World.".replace(".", "!"); + } + @Compare public String replaceSeqAll() { + return "Hello World! Hello World.".replace("World", "Jarda"); + } + @Compare public String replaceSeqAA() { + String res = "aaa".replace("aa", "b"); + assert res.equals("ba") : "Expecting ba: " + res; + return res; + } + + @Factory + public static Object[] create() { + return VMTest.create(CompareStringsTest.class); + } + + private static final class NullField { + + String name; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,65 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class DoubleTest { + @Compare public String integerToString() { + return toStr(1); + } + + @Compare public String integerAndHalfToString() { + return toStr(1.5); + } + + @Compare public double longToAndBack() { + return Double.parseDouble(toStr(Long.MAX_VALUE / 10)); + } + + @Compare public String negativeIntToString() { + return toStr(-10); + } + + @Compare public String negativeIntAndHalfToString() { + return toStr(-10.5); + } + + @Compare public double negativeLongAndBack() { + return Double.parseDouble(toStr(Long.MIN_VALUE / 10)); + } + + @Compare public double canParseExp() { + return Double.parseDouble(toStr(1.7976931348623157e+308)); + } + + private static String toStr(double d) { + return Double.toString(d); + } + + @Factory + public static Object[] create() { + return VMTest.create(DoubleTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,106 @@ +/** + * 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.tck; + +import java.io.InputStream; +import java.net.URL; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.Http; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class HttpResourceTest { + + @Http({ + @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain") + }) + @BrwsrTest + + + public String testReadContentViaXHR() throws Exception { + String msg = read("/xhr"); + assert "Hello Brwsr!".equals(msg) : "The message was " + msg; + return msg; + } + + @Http({ + @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain") + }) + @BrwsrTest + public String testReadContentViaURL() throws Exception { + URL url = new URL("http:/url"); + String msg = (String) url.getContent(); + assert "Hello via URL!".equals(msg) : "The message was " + msg; + return msg; + } + @Http({ + @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain") + }) + @BrwsrTest + public String testReadContentViaURLWithStringParam() throws Exception { + URL url = new URL("http:/url"); + String msg = (String) url.getContent(new Class[] { String.class }); + assert "Hello via URL!".equals(msg) : "The message was " + msg; + return msg; + } + + @Http({ + @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary") + }) + @BrwsrTest + public void testReadByte() throws Exception { + URL url = new URL("http:/bytes"); + final Object res = url.getContent(new Class[] { byte[].class }); + assert res instanceof byte[] : "Expecting byte[]: " + res; + byte[] arr = (byte[]) res; + assert arr.length == 1 : "One byte " + arr.length; + assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]); + } + + @Http({ + @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary") + }) + @BrwsrTest + public void testReadByteViaInputStream() throws Exception { + URL url = new URL("http:/bytes"); + InputStream is = url.openStream(); + byte[] arr = new byte[10]; + int len = is.read(arr); + assert len == 1 : "One byte " + len; + assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]); + } + + @JavaScriptBody(args = { "url" }, body = + "var req = new XMLHttpRequest();\n" + + "req.open('GET', url, false);\n" + + "req.send();\n" + + "return req.responseText;" + ) + private static native String read(String url); + + + @Factory + public static Object[] create() { + return VMTest.create(HttpResourceTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,34 @@ +/** + * 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.tck; + +/** + * + * @author Jaroslav Tulach + */ +public class InheritanceA { + private String name; + + public void setA(String n) { + this.name = n; + } + + public String getA() { + return name; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,34 @@ +/** + * 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.tck; + +/** + * + * @author Jaroslav Tulach + */ +public class InheritanceB extends InheritanceA { + private String name; + + public void setB(String n) { + this.name = n; + } + + public String getB() { + return name; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,41 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class InheritanceTest { + + @Compare public String checkFieldsIndependent() throws ClassNotFoundException { + InheritanceB ib = new InheritanceB(); + ib.setA("A"); + ib.setB("B"); + return "A: " + ib.getA() + " B: " + ib.getB(); + } + + @Factory + public static Object[] create() { + return VMTest.create(InheritanceTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,166 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class IntegerArithmeticTest { + + private static int add(int x, int y) { + return x + y; + } + + private static int sub(int x, int y) { + return x - y; + } + + private static int mul(int x, int y) { + return x * y; + } + + private static int div(int x, int y) { + return x / y; + } + + private static int mod(int x, int y) { + return x % y; + } + + private static int neg(int x) { + return (-x); + } + + private static float fadd(float x, float y) { + return x + y; + } + + private static double dadd(double x, double y) { + return x + y; + } + + @Compare public int addOverflow() { + return add(Integer.MAX_VALUE, 1); + } + + @Compare public int subUnderflow() { + return sub(Integer.MIN_VALUE, 1); + } + + @Compare public int addMaxIntAndMaxInt() { + return add(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Compare public int subMinIntAndMinInt() { + return sub(Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Compare public int multiplyMaxInt() { + return mul(Integer.MAX_VALUE, 2); + } + + @Compare public int multiplyMaxIntAndMaxInt() { + return mul(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Compare public int multiplyMinInt() { + return mul(Integer.MIN_VALUE, 2); + } + + @Compare public int multiplyMinIntAndMinInt() { + return mul(Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Compare public int multiplyPrecision() { + return mul(119106029, 1103515245); + } + + @Compare public int division() { + return div(1, 2); + } + + @Compare public int divisionReminder() { + return mod(1, 2); + } + + @Compare public int negativeDivision() { + return div(-7, 3); + } + + @Compare public int negativeDivisionReminder() { + return mod(-7, 3); + } + + @Compare public int conversionFromFloat() { + return (int) fadd(-2, -0.6f); + } + + @Compare public int conversionFromDouble() { + return (int) dadd(-2, -0.6); + } + + @Compare public boolean divByZeroThrowsArithmeticException() { + try { + div(1, 0); + return false; + } catch (final ArithmeticException e) { + return true; + } + } + + @Compare public boolean modByZeroThrowsArithmeticException() { + try { + mod(1, 0); + return false; + } catch (final ArithmeticException e) { + return true; + } + } + + @Compare public int negate() { + return neg(123456); + } + + @Compare public int negateMaxInt() { + return neg(Integer.MAX_VALUE); + } + + @Compare public int negateMinInt() { + return neg(Integer.MIN_VALUE); + } + + @Compare public int sumTwoDimensions() { + int[][] matrix = createMatrix(4, 3); + matrix[0][0] += 10; + return matrix[0][0]; + } + + static int[][] createMatrix(int x, int y) { + return new int[x][y]; + } + + @Factory + public static Object[] create() { + return VMTest.create(IntegerArithmeticTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,376 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class LongArithmeticTest { + + private static long add(long x, long y) { + return (x + y); + } + + private static long sub(long x, long y) { + return (x - y); + } + + private static long mul(long x, long y) { + return (x * y); + } + + private static long div(long x, long y) { + return (x / y); + } + + private static long mod(long x, long y) { + return (x % y); + } + + private static long neg(long x) { + return (-x); + } + + private static long shl(long x, int b) { + return (x << b); + } + + private static long shr(long x, int b) { + return (x >> b); + } + + private static long ushr(long x, int b) { + return (x >>> b); + } + + private static long and(long x, long y) { + return (x & y); + } + + private static long or(long x, long y) { + return (x | y); + } + + private static long xor(long x, long y) { + return (x ^ y); + } + + private static float fadd(float x, float y) { + return x + y; + } + + private static double dadd(double x, double y) { + return x + y; + } + + public static int compare(long x, long y, int zero) { + final int xyResult = compareL(x, y, zero); + final int yxResult = compareL(y, x, zero); + + return ((xyResult + yxResult) == 0) ? xyResult : -2; + } + + private static int compareL(long x, long y, int zero) { + int result = -2; + int trueCount = 0; + + x += zero; + if (x == y) { + result = 0; + ++trueCount; + } + + x += zero; + if (x < y) { + result = -1; + ++trueCount; + } + + x += zero; + if (x > y) { + result = 1; + ++trueCount; + } + + return (trueCount == 1) ? result : -2; + } + + @Compare public long conversion() { + return Long.MAX_VALUE; + } + + @Compare public long negate1() { + return neg(0x00fa37d7763e0ca1l); + } + + @Compare public long negate2() { + return neg(0x80fa37d7763e0ca1l); + } + + @Compare public long negate3() { + return neg(0xfffffffffffffeddl); + } + + @Compare public long addOverflow() { + return add(Long.MAX_VALUE, 1l); + } + + @Compare public long subUnderflow() { + return sub(Long.MIN_VALUE, 1l); + } + + @Compare public long addMaxLongAndMaxLong() { + return add(Long.MAX_VALUE, Long.MAX_VALUE); + } + + @Compare public long subMinLongAndMinLong() { + return sub(Long.MIN_VALUE, Long.MIN_VALUE); + } + + @Compare public long subMinLongAndMaxLong() { + return sub(Long.MIN_VALUE, Long.MAX_VALUE); + } + + @Compare public long multiplyMaxLong() { + return mul(Long.MAX_VALUE, 2l); + } + + @Compare public long multiplyMaxLongAndMaxLong() { + return mul(Long.MAX_VALUE, Long.MAX_VALUE); + } + + @Compare public long multiplyMinLong() { + return mul(Long.MIN_VALUE, 2l); + } + + @Compare public long multiplyMinLongAndMinLong() { + return mul(Long.MIN_VALUE, Long.MIN_VALUE); + } + + @Compare public long multiplyPrecision() { + return mul(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el); + } + + @Compare public long divideSmallPositiveNumbers() { + return div(0xabcdef, 0x123); + } + + @Compare public long divideSmallNegativeNumbers() { + return div(-0xabcdef, -0x123); + } + + @Compare public long divideSmallMixedNumbers() { + return div(0xabcdef, -0x123); + } + + @Compare public long dividePositiveNumbersOneDigitDenom() { + return div(0xabcdef0102ffffl, 0x654); + } + + @Compare public long divideNegativeNumbersOneDigitDenom() { + return div(-0xabcdef0102ffffl, -0x654); + } + + @Compare public long divideMixedNumbersOneDigitDenom() { + return div(-0xabcdef0102ffffl, 0x654); + } + + @Compare public long dividePositiveNumbersMultiDigitDenom() { + return div(0x7ffefc003322aabbl, 0x89ab1000l); + } + + @Compare public long divideNegativeNumbersMultiDigitDenom() { + return div(-0x7ffefc003322aabbl, -0x123489ab1001l); + } + + @Compare public long divideMixedNumbersMultiDigitDenom() { + return div(0x7ffefc003322aabbl, -0x38f49b0b7574e36l); + } + + @Compare public long divideWithOverflow() { + return div(0x8000fffe0000l, 0x8000ffffl); + } + + @Compare public long divideWithCorrection() { + return div(0x7fff800000000000l, 0x800000000001l); + } + + @Compare public long moduloSmallPositiveNumbers() { + return mod(0xabcdef, 0x123); + } + + @Compare public long moduloSmallNegativeNumbers() { + return mod(-0xabcdef, -0x123); + } + + @Compare public long moduloSmallMixedNumbers() { + return mod(0xabcdef, -0x123); + } + + @Compare public long moduloPositiveNumbersOneDigitDenom() { + return mod(0xabcdef0102ffffl, 0x654); + } + + @Compare public long moduloNegativeNumbersOneDigitDenom() { + return mod(-0xabcdef0102ffffl, -0x654); + } + + @Compare public long moduloMixedNumbersOneDigitDenom() { + return mod(-0xabcdef0102ffffl, 0x654); + } + + @Compare public long moduloPositiveNumbersMultiDigitDenom() { + return mod(0x7ffefc003322aabbl, 0x89ab1000l); + } + + @Compare public long moduloNegativeNumbersMultiDigitDenom() { + return mod(-0x7ffefc003322aabbl, -0x123489ab1001l); + } + + @Compare public long moduloMixedNumbersMultiDigitDenom() { + return mod(0x7ffefc003322aabbl, -0x38f49b0b7574e36l); + } + + @Compare public long moduloWithOverflow() { + return mod(0x8000fffe0000l, 0x8000ffffl); + } + + @Compare public long moduloWithCorrection() { + return mod(0x7fff800000000000l, 0x800000000001l); + } + + @Compare public long conversionFromFloatPositive() { + return (long) fadd(2, 0.6f); + } + + @Compare public long conversionFromFloatNegative() { + return (long) fadd(-2, -0.6f); + } + + @Compare public long conversionFromDoublePositive() { + return (long) dadd(0x20ffff0000L, 0.6); + } + + @Compare public long conversionFromDoubleNegative() { + return (long) dadd(-0x20ffff0000L, -0.6); + } + + @Compare public boolean divByZeroThrowsArithmeticException() { + try { + div(1, 0); + return false; + } catch (final ArithmeticException e) { + return true; + } + } + + @Compare public boolean modByZeroThrowsArithmeticException() { + try { + mod(1, 0); + return false; + } catch (final ArithmeticException e) { + return true; + } + } + + @Compare public long shiftL1() { + return shl(0x00fa37d7763e0ca1l, 5); + } + + @Compare public long shiftL2() { + return shl(0x00fa37d7763e0ca1l, 32); + } + + @Compare public long shiftL3() { + return shl(0x00fa37d7763e0ca1l, 45); + } + + @Compare public long shiftR1() { + return shr(0x00fa37d7763e0ca1l, 5); + } + + @Compare public long shiftR2() { + return shr(0x00fa37d7763e0ca1l, 32); + } + + @Compare public long shiftR3() { + return shr(0x00fa37d7763e0ca1l, 45); + } + + @Compare public long uShiftR1() { + return ushr(0x00fa37d7763e0ca1l, 5); + } + + @Compare public long uShiftR2() { + return ushr(0x00fa37d7763e0ca1l, 45); + } + + @Compare public long uShiftR3() { + return ushr(0xf0fa37d7763e0ca1l, 5); + } + + @Compare public long uShiftR4() { + return ushr(0xf0fa37d7763e0ca1l, 45); + } + + @Compare public long and1() { + return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el); + } + + @Compare public long or1() { + return or(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el); + } + + @Compare public long xor1() { + return xor(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el); + } + + @Compare public long xor2() { + return xor(0x00fa37d7763e0ca1l, 0x00000000ff00123el); + } + + @Compare public long xor3() { + return xor(0x00000000763e0ca1l, 0x00000000ff00123el); + } + + @Compare public int compareSameNumbers() { + return compare(0x0000000000000000l, 0x0000000000000000l, 0); + } + + @Compare public int comparePositiveNumbers() { + return compare(0x0000000000200000l, 0x0000000010000000l, 0); + } + + @Compare public int compareNegativeNumbers() { + return compare(0xffffffffffffffffl, 0xffffffff00000000l, 0); + } + + @Compare public int compareMixedNumbers() { + return compare(0x8000000000000000l, 0x7fffffffffffffffl, 0); + } + + @Factory + public static Object[] create() { + return VMTest.create(LongArithmeticTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,161 @@ +/** + * 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.tck; + +import java.lang.reflect.Array; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ReflectionArrayTest { + @Compare public int lengthOfStringArray() { + String[] arr = (String[]) Array.newInstance(String.class, 10); + return arr.length; + } + + @Compare public int reflectiveLengthOfStringArray() { + Object arr = Array.newInstance(String.class, 10); + return Array.getLength(arr); + } + + @Compare public int reflectiveLengthOneNonArray() { + Object arr = "non-array"; + return Array.getLength(arr); + } + + @Compare public String compTypeOfStringArray() { + String[] arr = (String[]) Array.newInstance(String.class, 10); + return arr.getClass().getComponentType().getName(); + } + + @Compare public Object negativeArrayExcp() { + return Array.newInstance(String.class, -5); + } + + @Compare public int lengthOfIntArray() { + int[] arr = (int[]) Array.newInstance(Integer.TYPE, 10); + return arr.length; + } + + @Compare public int reflectiveLengthOfIntArray() { + Object arr = Array.newInstance(Integer.TYPE, 10); + return Array.getLength(arr); + } + + @Compare public String compTypeOfIntArray() { + int[] arr = (int[]) Array.newInstance(int.class, 10); + return arr.getClass().getComponentType().getName(); + } + + @Compare public Object intNegativeArrayExcp() { + return Array.newInstance(int.class, -5); + } + + @Compare public Integer verifyAutobox() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + return (Integer) Array.get(arr, 0); + } + @Compare public String verifyObjectArray() { + String[] arr = (String[]) Array.newInstance(String.class, 5); + Array.set(arr, 0, "Hello"); + return (String) Array.get(arr, 0); + } + @Compare public int verifyInt() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + return Array.getInt(arr, 0); + } + @Compare public long verifyConvertToLong() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + return Array.getLong(arr, 0); + } + + @Compare public Object verifySetIntToObject() { + try { + Object[] arr = (Object[]) Array.newInstance(Object.class, 5); + Array.setInt(arr, 0, 10); + return Array.get(arr, 0); + } catch (Exception exception) { + return exception.getClass().getName(); + } + } + @Compare public long verifySetShort() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + Array.setShort(arr, 0, (short)10); + return Array.getLong(arr, 0); + } + @Compare public long verifyCantSetLong() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + Array.setLong(arr, 0, 10); + return Array.getLong(arr, 0); + } + @Compare public float verifyLongToFloat() { + Object arr = Array.newInstance(float.class, 5); + Array.setLong(arr, 0, 10); + return Array.getFloat(arr, 0); + } + + @Compare public double verifyConvertToDouble() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + return Array.getDouble(arr, 0); + } + + @Compare public int multiIntArray() { + int[][][] arr = (int[][][]) Array.newInstance(int.class, 3, 3, 3); + return arr[0][1][2] + 5 + arr[2][2][0]; + } + + @Compare public String multiIntArrayCompType() { + return Array.newInstance(int.class, 3, 3, 3).getClass().getName(); + } + + @JavaScriptBody(args = {}, body = "return [1, 2];") + private static native Object crtarr(); + + @JavaScriptBody(args = {}, body = "return new Object();") + private static native Object newobj(); + + @BrwsrTest + public static void toStringArray() { + final Object arr = crtarr(); + final Object real = new Object[2]; + assert arr instanceof Object[] : "Any array is Java array: " + arr; + assert arr.getClass() == real.getClass() : "Same classes " + arr + " and " + real.getClass(); + final String str = arr.toString(); + assert str != null; + assert str.startsWith("[Ljava.lang.Object;@") : str; + } + + @BrwsrTest + public static void objectToString() { + String s = newobj().toString(); + assert s != null : "Some string computed"; + assert s.startsWith("java.lang.Object@") : "Regular object toString(): " + s; + } + + + @Factory + public static Object[] create() { + return VMTest.create(ReflectionArrayTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,272 @@ +/** + * 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.tck; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ReflectionTest { + @Compare public boolean nonNullThis() { + return this == null; + } + + @Compare public String intType() { + return Integer.TYPE.toString(); + } + + @Compare public String voidType() throws Exception { + return void.class.toString(); + } + + @Compare public String longClass() { + return long.class.toString(); + } + + @Compare public boolean isRunnableInterface() { + return Runnable.class.isInterface(); + } + + @Compare public boolean isAssignableToPrimitiveType() { + return boolean.class.isAssignableFrom(Runnable.class); + } + + @Compare public boolean isAssignableFromPrimitiveType() { + return Runnable.class.isAssignableFrom(boolean.class); + } + + @Compare public boolean isAssignableLongFromInt() { + return long.class.isAssignableFrom(int.class); + } + + @Compare public boolean isAssignableIntFromLong() { + return int.class.isAssignableFrom(long.class); + } + + @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException { + return Runnable.class.getMethod("run").getName(); + } + + @Compare public String namesOfMethods() { + StringBuilder sb = new StringBuilder(); + String[] arr = new String[20]; + int i = 0; + for (Method m : StaticUse.class.getMethods()) { + arr[i++] = m.getName(); + } + for (String s : sort(arr, i)) { + sb.append(s).append("\n"); + } + return sb.toString(); + } + + @Compare public String namesOfDeclaringClassesOfMethods() { + StringBuilder sb = new StringBuilder(); + String[] arr = new String[20]; + int i = 0; + for (Method m : StaticUse.class.getMethods()) { + arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName(); + } + for (String s : sort(arr, i)) { + sb.append(s).append("\n"); + } + return sb.toString(); + } + + @Compare public String cannotCallNonStaticMethodWithNull() throws Exception { + StaticUse.class.getMethod("instanceMethod").invoke(null); + return "should not happen"; + } + + @Compare public String classCastException() { + try { + Integer i = (Integer)StaticUseSub.getNonNull(); + return "" + i.intValue(); + } catch (ClassCastException ex) { + return ex.getClass().getName(); + } + } + + @Compare public String methodThatThrowsException() throws Exception { + StaticUse.class.getMethod("instanceMethod").invoke(new StaticUse()); + return "should not happen"; + } + + @Compare public Object voidReturnType() throws Exception { + return StaticUse.class.getMethod("instanceMethod").getReturnType(); + } + + @Retention(RetentionPolicy.RUNTIME) + @interface Ann { + } + + @Compare public String annoClass() throws Exception { + Retention r = Ann.class.getAnnotation(Retention.class); + assert r != null : "Annotation is present"; + assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value(); + return r.annotationType().getName(); + } + + @Compare public boolean isAnnotation() { + return Ann.class.isAnnotation(); + } + @Compare public boolean isNotAnnotation() { + return String.class.isAnnotation(); + } + @Compare public boolean isNotAnnotationEnum() { + return E.class.isAnnotation(); + } + enum E { A, B }; + @Compare public boolean isEnum() { + return E.A.getClass().isEnum(); + } + + @Compare public boolean isNotEnum() { + return "".getClass().isEnum(); + } + + @Compare public String newInstanceFails() throws InstantiationException { + try { + return "success: " + StaticUseSub.class.newInstance(); + } catch (IllegalAccessException ex) { + return ex.getClass().getName(); + } + } + + @Compare public String paramTypes() throws Exception { + Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE); + final Class[] pt = plus.getParameterTypes(); + return pt[0].getName(); + } + @Compare public String paramTypesNotFound() throws Exception { + return StaticUse.class.getMethod("plus", int.class, double.class).toString(); + } + @Compare public int methodWithArgs() throws Exception { + Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE); + return (Integer)plus.invoke(null, 2, 3); + } + + @Compare public String classGetNameForByte() { + return byte.class.getName(); + } + @Compare public String classGetNameForBaseObject() { + return newObject().getClass().getName(); + } + @Compare public String classGetNameForJavaObject() { + return new Object().getClass().getName(); + } + @Compare public String classGetNameForObjectArray() { + return (new Object[3]).getClass().getName(); + } + @Compare public String classGetNameForSimpleIntArray() { + return (new int[3]).getClass().getName(); + } + @Compare public boolean sameClassGetNameForSimpleCharArray() { + return (new char[3]).getClass() == (new char[34]).getClass(); + } + @Compare public String classGetNameForMultiIntArray() { + return (new int[3][4][5][6][7][8][9]).getClass().getName(); + } + @Compare public String classGetNameForMultiIntArrayInner() { + final int[][][][][][][] arr = new int[3][4][5][6][7][8][9]; + int[][][][][][] subarr = arr[0]; + int[][][][][] subsubarr = subarr[0]; + return subsubarr.getClass().getName(); + } + @Compare public String classGetNameForMultiStringArray() { + return (new String[3][4][5][6][7][8][9]).getClass().getName(); + } + + @Compare public String classForByte() throws Exception { + return Class.forName("[Z").getName(); + } + + @Compare public String classForUnknownArray() { + try { + return Class.forName("[W").getName(); + } catch (Exception ex) { + return ex.getClass().getName(); + } + } + + @Compare public String classForUnknownDeepArray() { + try { + return Class.forName("[[[[[W").getName(); + } catch (Exception ex) { + return ex.getClass().getName(); + } + } + + @Compare public String componentGetNameForObjectArray() { + return (new Object[3]).getClass().getComponentType().getName(); + } + @Compare public boolean sameComponentGetNameForObjectArray() { + return (new Object[3]).getClass().getComponentType() == Object.class; + } + @Compare public String componentGetNameForSimpleIntArray() { + return (new int[3]).getClass().getComponentType().getName(); + } + @Compare public String componentGetNameForMultiIntArray() { + return (new int[3][4][5][6][7][8][9]).getClass().getComponentType().getName(); + } + @Compare public String componentGetNameForMultiStringArray() { + Class c = (new String[3][4][5][6][7][8][9]).getClass(); + StringBuilder sb = new StringBuilder(); + for (;;) { + sb.append(c.getName()).append("\n"); + c = c.getComponentType(); + if (c == null) { + break; + } + } + return sb.toString(); + } + + @Compare public boolean isArray() { + return new Object[0].getClass().isArray(); + } + + @JavaScriptBody(args = { "arr", "len" }, body="var a = arr.slice(0, len); a.sort(); return a;") + private static String[] sort(String[] arr, int len) { + List list = Arrays.asList(arr).subList(0, len); + Collections.sort(list); + return list.toArray(new String[0]); + } + + @JavaScriptBody(args = {}, body = "return new Object();") + private static Object newObject() { + return new Object(); + } + + @Factory + public static Object[] create() { + return VMTest.create(ReflectionTest.class); + } + +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,45 @@ +/** + * 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.tck; + +import java.io.InputStream; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ResourcesTest { + + @Compare public String readResourceAsStream() throws Exception { + InputStream is = getClass().getResourceAsStream("Resources.txt"); + byte[] b = new byte[30]; + int len = is.read(b); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < len; i++) { + sb.append((char)b[i]); + } + return sb.toString(); + } + + @Factory public static Object[] create() { + return VMTest.create(ResourcesTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,102 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ShortArithmeticTest { + + private static short add(short x, short y) { + return (short)(x + y); + } + + private static short sub(short x, short y) { + return (short)(x - y); + } + + private static short mul(short x, short y) { + return (short)(x * y); + } + + private static short div(short x, short y) { + return (short)(x / y); + } + + private static short mod(short x, short y) { + return (short)(x % y); + } + + @Compare public short conversion() { + return (short)123456; + } + + @Compare public short addOverflow() { + return add(Short.MAX_VALUE, (short)1); + } + + @Compare public short subUnderflow() { + return sub(Short.MIN_VALUE, (short)1); + } + + @Compare public short addMaxShortAndMaxShort() { + return add(Short.MAX_VALUE, Short.MAX_VALUE); + } + + @Compare public short subMinShortAndMinShort() { + return sub(Short.MIN_VALUE, Short.MIN_VALUE); + } + + @Compare public short multiplyMaxShort() { + return mul(Short.MAX_VALUE, (short)2); + } + + @Compare public short multiplyMaxShortAndMaxShort() { + return mul(Short.MAX_VALUE, Short.MAX_VALUE); + } + + @Compare public short multiplyMinShort() { + return mul(Short.MIN_VALUE, (short)2); + } + + @Compare public short multiplyMinShortAndMinShort() { + return mul(Short.MIN_VALUE, Short.MIN_VALUE); + } + + @Compare public short multiplyPrecision() { + return mul((short)17638, (short)1103); + } + + @Compare public short division() { + return div((short)1, (short)2); + } + + @Compare public short divisionReminder() { + return mod((short)1, (short)2); + } + + @Factory + public static Object[] create() { + return VMTest.create(ShortArithmeticTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,39 @@ +/** + * 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.tck; + +class StaticUse { + public static final Object NON_NULL = new Object(); + public static int cnt; + static { + if (cnt++ != 0) { + throw new IllegalStateException("Multiple initialization of a "); + } + } + + StaticUse() { + } + + public void instanceMethod() { + throw new IllegalStateException(); + } + + public static int plus(int a, int b) { + return a + b; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSub.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,30 @@ +/** + * 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.tck; + +public class StaticUseSub extends StaticUse { + private StaticUseSub() { + } + + public static Object getNonNull() { + return NON_NULL; + } + static Object getNull() { + return null; + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSubTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSubTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,45 @@ +/** + * 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.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class StaticUseSubTest { + @Compare public String staticFieldInitializationInSuperClass() throws Exception { + Object ret = StaticUseSub.getNonNull(); + return ret.getClass().getName(); + } + + @Compare public String isNullPointerTheSame() throws Exception { + try { + return StaticUseSub.getNull().getClass().toString(); + } catch (NullPointerException ex) { + return ex.getClass().getName(); + } + } + + @Factory public static Object[] create() { + return VMTest.create(StaticUseSubTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,41 @@ +/** + * 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.UnsupportedEncodingException; +import java.util.zip.CRC32; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CRC32Test { + + @Compare public long crc1() throws UnsupportedEncodingException { + CRC32 crc = new CRC32(); + crc.update("Hello World!".getBytes("UTF-8")); + return crc.getValue(); + } + + @Factory public static Object[] create() { + return VMTest.create(CRC32Test.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CallMeTwiceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CallMeTwiceTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,43 @@ +/** + * 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.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CallMeTwiceTest { + int cnt; + + @BrwsrTest public void callMeTwice() throws InterruptedException { + if (cnt++ == 0) { + throw new InterruptedException(); + } + int prevCnt = cnt; + cnt = 0; + assert prevCnt == 2 : "We need to receive two calls " + prevCnt; + } + + @Factory public static Object[] create() { + return VMTest.create(CallMeTwiceTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -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.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import org.apidesign.bck2brwsr.emul.zip.FastJar; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * + * @author Jaroslav Tulach + */ +@GenerateZip(name = "five.zip", contents = { + "1.txt", "one", + "2.txt", "duo", + "3.txt", "three", + "4.txt", "four", + "5.txt", "five" +}) +public class ZipEntryTest { + @Test + public void readEntriesEffectively() throws IOException { + InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip"); + byte[] arr = new byte[is.available()]; + int len = is.read(arr); + assertEquals(len, arr.length, "Read fully"); + + FastJar fj = new FastJar(arr); + FastJar.Entry[] entrs = fj.list(); + + assertEquals(5, entrs.length, "Five entries"); + + for (int i = 1; i <= 5; i++) { + FastJar.Entry en = entrs[i - 1]; + assertEquals(en.name, i + ".txt"); +// assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read"); + } + + assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK"); + assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK"); + } + + private static void assertContent(String exp, InputStream is, String msg) throws IOException { + byte[] arr = new byte[512]; + int len = is.read(arr); + String s = new String(arr, 0, len); + assertEquals(exp, s, msg); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,108 @@ +/** + * 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 java.io.InputStream; +import java.util.Objects; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.Http; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +@GenerateZip(name = "readAnEntry.zip", contents = { + "my/main/file.txt", "Hello World!" +}) +public class ZipFileTest { + + @Compare public String readAnEntry() throws IOException { + InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip"); + ZipInputStream zip = new ZipInputStream(is); + ZipEntry entry = zip.getNextEntry(); + assertEquals(entry.getName(), "my/main/file.txt", "Correct entry"); + + byte[] arr = new byte[4096]; + int len = zip.read(arr); + + assertEquals(zip.getNextEntry(), null, "No next entry"); + + final String ret = new String(arr, 0, len, "UTF-8"); + return ret; + } + + @JavaScriptBody(args = { "res", "path" }, body = + "var myvm = bck2brwsr.apply(null, path);\n" + + "var cls = myvm.loadClass('java.lang.String');\n" + + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n" + ) + private static native Object loadVMResource(String res, String...path); + + @Http({ + @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip") + }) + @BrwsrTest public void canVmLoadResourceFromZip() throws IOException { + Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar"); + assert res instanceof InputStream : "Got array of bytes: " + res; + InputStream is = (InputStream)res; + + byte[] arr = new byte[4096]; + int len = is.read(arr); + + final String ret = new String(arr, 0, len, "UTF-8"); + + assertEquals(ret, "Hello World!", "Can read the bytes"); + } + + @GenerateZip(name = "cpattr.zip", contents = { + "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n" + + "Created-By: hand\n" + + "Class-Path: realJar.jar\n\n\n" + }) + @Http({ + @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"), + @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"), + }) + @BrwsrTest public void understandsClassPathAttr() throws IOException { + Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar"); + assert res instanceof InputStream : "Got array of bytes: " + res; + InputStream is = (InputStream)res; + + byte[] arr = new byte[4096]; + int len = is.read(arr); + + final String ret = new String(arr, 0, len, "UTF-8"); + + assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR"); + } + + private static void assertEquals(Object real, Object exp, String msg) { + assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real; + } + + @Factory public static Object[] create() { + return VMTest.create(ZipFileTest.class); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,1 @@ +þ \ No newline at end of file diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,1 @@ +Ahoj diff -r c7a085d63ab5 -r 3f7991249a20 rt/emul/mini/src/main/java/java/lang/ArithmeticException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/mini/src/main/java/java/lang/ArithmeticException.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Thrown when an exceptional arithmetic condition has occurred. For + * example, an integer "divide by zero" throws an + * instance of this class. + * + * {@code ArithmeticException} objects may be constructed by the + * virtual machine as if {@linkplain Throwable#Throwable(String, + * Throwable, boolean, boolean) suppression were disabled and/or the + * stack trace was not writable}. + * + * @author unascribed + * @since JDK1.0 + */ +public class ArithmeticException extends RuntimeException { + private static final long serialVersionUID = 2256477558314496007L; + + /** + * Constructs an {@code ArithmeticException} with no detail + * message. + */ + public ArithmeticException() { + super(); + } + + /** + * Constructs an {@code ArithmeticException} with the specified + * detail message. + * + * @param s the detail message. + */ + public ArithmeticException(String s) { + super(s); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/launcher/pom.xml --- a/rt/launcher/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ - - - 4.0.0 - - org.apidesign.bck2brwsr - rt - 0.7-SNAPSHOT - - org.apidesign.bck2brwsr - launcher - 0.7-SNAPSHOT - Bck2Brwsr Launcher - http://maven.apache.org - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-javadoc-plugin - - org.apidesign.bck2brwsr.launcher.impl - false - - - - - - UTF-8 - - - - junit - junit - 3.8.1 - test - - - org.glassfish.grizzly - grizzly-http-server - 2.2.19 - - - ${project.groupId} - vm4brwsr - ${project.version} - - - diff -r c7a085d63ab5 -r 3f7991249a20 rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,602 +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.launcher; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource; -import org.apidesign.vm4brwsr.Bck2Brwsr; -import org.glassfish.grizzly.PortRange; -import org.glassfish.grizzly.http.server.HttpHandler; -import org.glassfish.grizzly.http.server.HttpServer; -import org.glassfish.grizzly.http.server.NetworkListener; -import org.glassfish.grizzly.http.server.Request; -import org.glassfish.grizzly.http.server.Response; -import org.glassfish.grizzly.http.server.ServerConfiguration; -import org.glassfish.grizzly.http.util.HttpStatus; - -/** - * Lightweight server to launch Bck2Brwsr applications and tests. - * Supports execution in native browser as well as Java's internal - * execution engine. - */ -final class Bck2BrwsrLauncher extends Launcher implements Closeable { - private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName()); - private static final InvocationContext END = new InvocationContext(null, null, null); - private final Set loaders = new LinkedHashSet<>(); - private final BlockingQueue methods = new LinkedBlockingQueue<>(); - private long timeOut; - private final Res resources = new Res(); - private final String cmd; - private Object[] brwsr; - private HttpServer server; - private CountDownLatch wait; - - public Bck2BrwsrLauncher(String cmd) { - this.cmd = cmd; - } - - @Override - InvocationContext runMethod(InvocationContext c) throws IOException { - loaders.add(c.clazz.getClassLoader()); - methods.add(c); - try { - c.await(timeOut); - } catch (InterruptedException ex) { - throw new IOException(ex); - } - return c; - } - - public void setTimeout(long ms) { - timeOut = ms; - } - - public void addClassLoader(ClassLoader url) { - this.loaders.add(url); - } - - public void showURL(String startpage) throws IOException { - if (!startpage.startsWith("/")) { - startpage = "/" + startpage; - } - HttpServer s = initServer(".", true); - int last = startpage.lastIndexOf('/'); - String prefix = startpage.substring(0, last); - String simpleName = startpage.substring(last); - s.getServerConfiguration().addHttpHandler(new SubTree(resources, prefix), "/"); - try { - launchServerAndBrwsr(s, simpleName); - } catch (URISyntaxException | InterruptedException ex) { - throw new IOException(ex); - } - } - - void showDirectory(File dir, String startpage) throws IOException { - if (!startpage.startsWith("/")) { - startpage = "/" + startpage; - } - HttpServer s = initServer(dir.getPath(), false); - try { - launchServerAndBrwsr(s, startpage); - } catch (URISyntaxException | InterruptedException ex) { - throw new IOException(ex); - } - } - - @Override - public void initialize() throws IOException { - try { - executeInBrowser(); - } catch (InterruptedException ex) { - final InterruptedIOException iio = new InterruptedIOException(ex.getMessage()); - iio.initCause(ex); - throw iio; - } catch (Exception ex) { - if (ex instanceof IOException) { - throw (IOException)ex; - } - if (ex instanceof RuntimeException) { - throw (RuntimeException)ex; - } - throw new IOException(ex); - } - } - - private HttpServer initServer(String path, boolean addClasses) throws IOException { - HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535)); - - final ServerConfiguration conf = s.getServerConfiguration(); - if (addClasses) { - conf.addHttpHandler(new VM(resources), "/bck2brwsr.js"); - conf.addHttpHandler(new Classes(resources), "/classes/"); - } - return s; - } - - private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException { - wait = new CountDownLatch(1); - server = initServer(".", true); - final ServerConfiguration conf = server.getServerConfiguration(); - - class DynamicResourceHandler extends HttpHandler { - private final InvocationContext ic; - public DynamicResourceHandler(InvocationContext ic) { - if (ic == null || ic.resources.isEmpty()) { - throw new NullPointerException(); - } - this.ic = ic; - for (Resource r : ic.resources) { - conf.addHttpHandler(this, r.httpPath); - } - } - - public void close() { - conf.removeHttpHandler(this); - } - - @Override - public void service(Request request, Response response) throws Exception { - for (Resource r : ic.resources) { - if (r.httpPath.equals(request.getRequestURI())) { - LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI()); - response.setContentType(r.httpType); - r.httpContent.reset(); - String[] params = null; - if (r.parameters.length != 0) { - params = new String[r.parameters.length]; - for (int i = 0; i < r.parameters.length; i++) { - params[i] = request.getParameter(r.parameters[i]); - } - } - - copyStream(r.httpContent, response.getOutputStream(), null, params); - } - } - } - } - - conf.addHttpHandler(new Page(resources, - "org/apidesign/bck2brwsr/launcher/harness.xhtml" - ), "/execute"); - - conf.addHttpHandler(new HttpHandler() { - int cnt; - List cases = new ArrayList<>(); - DynamicResourceHandler prev; - @Override - public void service(Request request, Response response) throws Exception { - String id = request.getParameter("request"); - String value = request.getParameter("result"); - if (value != null && value.indexOf((char)0xC5) != -1) { - value = toUTF8(value); - } - - - InvocationContext mi = null; - int caseNmbr = -1; - - if (id != null && value != null) { - LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value}); - value = decodeURL(value); - int indx = Integer.parseInt(id); - cases.get(indx).result(value, null); - if (++indx < cases.size()) { - mi = cases.get(indx); - LOG.log(Level.INFO, "Re-executing case {0}", indx); - caseNmbr = indx; - } - } else { - if (!cases.isEmpty()) { - LOG.info("Re-executing test cases"); - mi = cases.get(0); - caseNmbr = 0; - } - } - - if (prev != null) { - prev.close(); - prev = null; - } - - if (mi == null) { - mi = methods.take(); - caseNmbr = cnt++; - } - if (mi == END) { - response.getWriter().write(""); - wait.countDown(); - cnt = 0; - LOG.log(Level.INFO, "End of data reached. Exiting."); - return; - } - - if (!mi.resources.isEmpty()) { - prev = new DynamicResourceHandler(mi); - } - - cases.add(mi); - final String cn = mi.clazz.getName(); - final String mn = mi.methodName; - LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn}); - response.getWriter().write("{" - + "className: '" + cn + "', " - + "methodName: '" + mn + "', " - + "request: " + caseNmbr - ); - if (mi.html != null) { - response.getWriter().write(", html: '"); - response.getWriter().write(encodeJSON(mi.html)); - response.getWriter().write("'"); - } - response.getWriter().write("}"); - } - }, "/data"); - - this.brwsr = launchServerAndBrwsr(server, "/execute"); - } - - private static String encodeJSON(String in) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < in.length(); i++) { - char ch = in.charAt(i); - if (ch < 32 || ch == '\'' || ch == '"') { - sb.append("\\u"); - String hs = "0000" + Integer.toHexString(ch); - hs = hs.substring(hs.length() - 4); - sb.append(hs); - } else { - sb.append(ch); - } - } - return sb.toString(); - } - - @Override - public void shutdown() throws IOException { - methods.offer(END); - for (;;) { - int prev = methods.size(); - try { - if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) { - break; - } - } catch (InterruptedException ex) { - throw new IOException(ex); - } - if (prev == methods.size()) { - LOG.log( - Level.WARNING, - "Timeout and no test has been executed meanwhile (at {0}). Giving up.", - methods.size() - ); - break; - } - LOG.log(Level.INFO, - "Timeout, but tests got from {0} to {1}. Trying again.", - new Object[]{prev, methods.size()} - ); - } - stopServerAndBrwsr(server, brwsr); - } - - static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException { - for (;;) { - int ch = is.read(); - if (ch == -1) { - break; - } - if (ch == '$' && params.length > 0) { - int cnt = is.read() - '0'; - if (baseURL != null && cnt == 'U' - '0') { - os.write(baseURL.getBytes("UTF-8")); - } else { - if (cnt >= 0 && cnt < params.length) { - os.write(params[cnt].getBytes("UTF-8")); - } else { - os.write('$'); - os.write(cnt + '0'); - } - } - } else { - os.write(ch); - } - } - } - - private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException { - server.start(); - NetworkListener listener = server.getListeners().iterator().next(); - int port = listener.getPort(); - - URI uri = new URI("http://localhost:" + port + page); - LOG.log(Level.INFO, "Showing {0}", uri); - if (cmd == null) { - try { - LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] { - System.getProperty("java.vm.name"), - System.getProperty("java.vm.vendor"), - System.getProperty("java.vm.version"), - }); - java.awt.Desktop.getDesktop().browse(uri); - LOG.log(Level.INFO, "Desktop.browse successfully finished"); - return null; - } catch (UnsupportedOperationException ex) { - LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage()); - LOG.log(Level.FINE, null, ex); - } - } - { - String cmdName = cmd == null ? "xdg-open" : cmd; - String[] cmdArr = { - cmdName, uri.toString() - }; - LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr)); - final Process process = Runtime.getRuntime().exec(cmdArr); - return new Object[] { process, null }; - } - } - private static String toUTF8(String value) throws UnsupportedEncodingException { - byte[] arr = new byte[value.length()]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (byte)value.charAt(i); - } - return new String(arr, "UTF-8"); - } - - private static String decodeURL(String s) { - for (;;) { - int pos = s.indexOf('%'); - if (pos == -1) { - return s; - } - int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16); - s = s.substring(0, pos) + (char)i + s.substring(pos + 2); - } - } - - private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException { - if (brwsr == null) { - return; - } - Process process = (Process)brwsr[0]; - - server.stop(); - InputStream stdout = process.getInputStream(); - InputStream stderr = process.getErrorStream(); - drain("StdOut", stdout); - drain("StdErr", stderr); - process.destroy(); - int res; - try { - res = process.waitFor(); - } catch (InterruptedException ex) { - throw new IOException(ex); - } - LOG.log(Level.INFO, "Exit code: {0}", res); - - deleteTree((File)brwsr[1]); - } - - private static void drain(String name, InputStream is) throws IOException { - int av = is.available(); - if (av > 0) { - StringBuilder sb = new StringBuilder(); - sb.append("v== ").append(name).append(" ==v\n"); - while (av-- > 0) { - sb.append((char)is.read()); - } - sb.append("\n^== ").append(name).append(" ==^"); - LOG.log(Level.INFO, sb.toString()); - } - } - - private void deleteTree(File file) { - if (file == null) { - return; - } - File[] arr = file.listFiles(); - if (arr != null) { - for (File s : arr) { - deleteTree(s); - } - } - file.delete(); - } - - @Override - public void close() throws IOException { - shutdown(); - } - - private class Res implements Bck2Brwsr.Resources { - @Override - public InputStream get(String resource) throws IOException { - for (ClassLoader l : loaders) { - URL u = null; - Enumeration en = l.getResources(resource); - while (en.hasMoreElements()) { - u = en.nextElement(); - } - if (u != null) { - return u.openStream(); - } - } - throw new IOException("Can't find " + resource); - } - } - - private static class Page extends HttpHandler { - final String resource; - private final String[] args; - private final Res res; - - public Page(Res res, String resource, String... args) { - this.res = res; - this.resource = resource; - this.args = args.length == 0 ? new String[] { "$0" } : args; - } - - @Override - public void service(Request request, Response response) throws Exception { - String r = computePage(request); - if (r.startsWith("/")) { - r = r.substring(1); - } - String[] replace = {}; - if (r.endsWith(".html")) { - response.setContentType("text/html"); - LOG.info("Content type text/html"); - replace = args; - } - if (r.endsWith(".xhtml")) { - response.setContentType("application/xhtml+xml"); - LOG.info("Content type application/xhtml+xml"); - replace = args; - } - OutputStream os = response.getOutputStream(); - try (InputStream is = res.get(r)) { - copyStream(is, os, request.getRequestURL().toString(), replace); - } catch (IOException ex) { - response.setDetailMessage(ex.getLocalizedMessage()); - response.setError(); - response.setStatus(404); - } - } - - protected String computePage(Request request) { - String r = resource; - if (r == null) { - r = request.getHttpHandlerPath(); - } - return r; - } - } - - private static class SubTree extends Page { - - public SubTree(Res res, String resource, String... args) { - super(res, resource, args); - } - - @Override - protected String computePage(Request request) { - return resource + request.getHttpHandlerPath(); - } - - - } - - private static class VM extends HttpHandler { - private final String bck2brwsr; - - public VM(Res loader) throws IOException { - StringBuilder sb = new StringBuilder(); - Bck2Brwsr.generate(sb, loader); - sb.append( - "(function WrapperVM(global) {" - + " function ldCls(res) {\n" - + " var request = new XMLHttpRequest();\n" - + " request.open('GET', '/classes/' + res, false);\n" - + " request.send();\n" - + " if (request.status !== 200) return null;\n" - + " var arr = eval('(' + request.responseText + ')');\n" - + " return arr;\n" - + " }\n" - + " var prevvm = global.bck2brwsr;\n" - + " global.bck2brwsr = function() {\n" - + " var args = Array.prototype.slice.apply(arguments);\n" - + " args.unshift(ldCls);\n" - + " return prevvm.apply(null, args);\n" - + " };\n" - + "})(this);\n" - ); - this.bck2brwsr = sb.toString(); - } - - @Override - public void service(Request request, Response response) throws Exception { - response.setCharacterEncoding("UTF-8"); - response.setContentType("text/javascript"); - response.getWriter().write(bck2brwsr); - } - } - - private static class Classes extends HttpHandler { - private final Res loader; - - public Classes(Res loader) { - this.loader = loader; - } - - @Override - public void service(Request request, Response response) throws Exception { - String res = request.getHttpHandlerPath(); - if (res.startsWith("/")) { - res = res.substring(1); - } - try (InputStream is = loader.get(res)) { - response.setContentType("text/javascript"); - Writer w = response.getWriter(); - w.append("["); - for (int i = 0;; i++) { - int b = is.read(); - if (b == -1) { - break; - } - if (i > 0) { - w.append(", "); - } - if (i % 20 == 0) { - w.write("\n"); - } - if (b > 127) { - b = b - 256; - } - w.append(Integer.toString(b)); - } - w.append("\n]"); - } catch (IOException ex) { - response.setStatus(HttpStatus.NOT_FOUND_404); - response.setError(); - response.setDetailMessage(ex.getMessage()); - } - } - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +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.launcher; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** Represents individual method invocation, its context and its result. - * - * @author Jaroslav Tulach - */ -public final class InvocationContext { - final CountDownLatch wait = new CountDownLatch(1); - final Class clazz; - final String methodName; - private final Launcher launcher; - private String result; - private Throwable exception; - String html; - final List resources = new ArrayList<>(); - - InvocationContext(Launcher launcher, Class clazz, String methodName) { - this.launcher = launcher; - this.clazz = clazz; - this.methodName = methodName; - } - - /** An HTML fragment to be available for the execution. Useful primarily when - * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}. - * @param html the html fragment - */ - public void setHtmlFragment(String html) { - this.html = html; - } - - /** HTTP resource to be available during execution. An invocation may - * perform an HTTP query and obtain a resource relative to the page. - */ - public void addHttpResource(String relativePath, String mimeType, String[] parameters, InputStream content) { - if (relativePath == null || mimeType == null || content == null || parameters == null) { - throw new NullPointerException(); - } - resources.add(new Resource(content, mimeType, relativePath, parameters)); - } - - /** Invokes the associated method. - * @return the textual result of the invocation - */ - public String invoke() throws IOException { - launcher.runMethod(this); - return toString(); - } - - /** Obtains textual result of the invocation. - * @return text representing the exception or result value - */ - @Override - public String toString() { - if (exception != null) { - return exception.toString(); - } - return result; - } - - /** - * @param timeOut - * @throws InterruptedException - */ - void await(long timeOut) throws InterruptedException { - wait.await(timeOut, TimeUnit.MILLISECONDS); - } - - void result(String r, Throwable e) { - this.result = r; - this.exception = e; - wait.countDown(); - } - - - static final class Resource { - final InputStream httpContent; - final String httpType; - final String httpPath; - final String[] parameters; - - Resource(InputStream httpContent, String httpType, String httpPath, - String[] parameters - ) { - httpContent.mark(Integer.MAX_VALUE); - this.httpContent = httpContent; - this.httpType = httpType; - this.httpPath = httpPath; - this.parameters = parameters; - } - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +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.launcher; - -import org.apidesign.bck2brwsr.launcher.impl.Console; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Enumeration; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import org.apidesign.vm4brwsr.Bck2Brwsr; - -/** - * Tests execution in Java's internal scripting engine. - */ -final class JSLauncher extends Launcher { - private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName()); - private Set loaders = new LinkedHashSet<>(); - private final Res resources = new Res(); - private Invocable code; - private StringBuilder codeSeq; - private Object console; - - - @Override InvocationContext runMethod(InvocationContext mi) { - loaders.add(mi.clazz.getClassLoader()); - try { - long time = System.currentTimeMillis(); - LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName}); - String res = code.invokeMethod( - console, - "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2", - mi.clazz.getName(), mi.methodName).toString(); - time = System.currentTimeMillis() - time; - LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time}); - mi.result(res, null); - } catch (ScriptException | NoSuchMethodException ex) { - mi.result(null, ex); - } - return mi; - } - - public void addClassLoader(ClassLoader url) { - this.loaders.add(url); - } - - @Override - public void initialize() throws IOException { - try { - initRhino(); - } catch (Exception ex) { - if (ex instanceof IOException) { - throw (IOException)ex; - } - if (ex instanceof RuntimeException) { - throw (RuntimeException)ex; - } - throw new IOException(ex); - } - } - - private void initRhino() throws IOException, ScriptException, NoSuchMethodException { - StringBuilder sb = new StringBuilder(); - Bck2Brwsr.generate(sb, new Res()); - - ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine mach = sem.getEngineByExtension("js"); - - sb.append( - "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);" - + "\nfunction initVM() { return vm; };" - + "\n"); - - Object res = mach.eval(sb.toString()); - if (!(mach instanceof Invocable)) { - throw new IOException("It is invocable object: " + res); - } - code = (Invocable) mach; - codeSeq = sb; - - Object vm = code.invokeFunction("initVM"); - console = code.invokeMethod(vm, "loadClass", Console.class.getName()); - } - - @Override - public void shutdown() throws IOException { - } - - @Override - public String toString() { - return codeSeq.toString(); - } - - private class Res implements Bck2Brwsr.Resources { - @Override - public InputStream get(String resource) throws IOException { - for (ClassLoader l : loaders) { - URL u = null; - Enumeration en = l.getResources(resource); - while (en.hasMoreElements()) { - u = en.nextElement(); - } - if (u != null) { - return u.openStream(); - } - } - throw new IOException("Can't find " + resource); - } - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +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.launcher; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import org.apidesign.vm4brwsr.Bck2Brwsr; - -/** An abstraction for executing tests in a Bck2Brwsr virtual machine. - * Either in {@linkm Launcher#createJavaScript JavaScript engine}, - * or in {@linkm Launcher#createBrowser external browser}. - *

- * There also are methods to {@link #showDir(java.io.File, java.lang.String) display pages} - * in an external browser served by internal HTTP server. - * - * @author Jaroslav Tulach - */ -public abstract class Launcher { - - Launcher() { - } - - /** Initializes the launcher. This may mean starting a web browser or - * initializing execution engine. - * @throws IOException if something goes wrong - */ - public abstract void initialize() throws IOException; - - /** Shuts down the launcher. - * @throws IOException if something goes wrong - */ - public abstract void shutdown() throws IOException; - - - /** Builds an invocation context. The context can later be customized - * and {@link InvocationContext#invoke() invoked}. - * - * @param clazz the class to execute method from - * @param method the method to execute - * @return the context pointing to the selected method - */ - public InvocationContext createInvocation(Class clazz, String method) { - return new InvocationContext(this, clazz, method); - } - - - /** Creates launcher that uses internal JavaScript engine (Rhino). - * @return the launcher - */ - public static Launcher createJavaScript() { - final JSLauncher l = new JSLauncher(); - l.addClassLoader(Bck2Brwsr.class.getClassLoader()); - return l; - } - - /** Creates launcher that is using external browser. - * - * @param cmd null to use java.awt.Desktop to show the launcher - * or a string to execute in an external process (with a parameter to the URL) - * @return launcher executing in external browser. - */ - public static Launcher createBrowser(String cmd) { - final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd); - l.addClassLoader(Bck2Brwsr.class.getClassLoader()); - l.setTimeout(180000); - return l; - } - - /** Starts an HTTP server which provides access to classes and resources - * available in the classes URL and shows a start page - * available as {@link ClassLoader#getResource(java.lang.String)} from the - * provide classloader. Opens a browser with URL showing the start page. - * - * @param classes classloader offering access to classes and resources - * @param startpage page to show in the browser - * @return interface that allows one to stop the server - * @throws IOException if something goes wrong - */ - public static Closeable showURL(ClassLoader classes, String startpage) throws IOException { - Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null); - l.addClassLoader(classes); - l.showURL(startpage); - return l; - } - /** Starts an HTTP server which provides access to certain directory. - * The startpage should be relative location inside the root - * directory. Opens a browser with URL showing the start page. - * - * @param directory the root directory on disk - * @param startpage relative path from the root to the page - * @exception IOException if something goes wrong. - */ - public static Closeable showDir(File directory, String startpage) throws IOException { - Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null); - l.showDirectory(directory, startpage); - return l; - } - - abstract InvocationContext runMethod(InvocationContext c) throws IOException; -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,356 +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.launcher.impl; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.net.URL; -import java.util.Enumeration; -import org.apidesign.bck2brwsr.core.JavaScriptBody; - -/** - * - * @author Jaroslav Tulach - */ -public class Console { - private Console() { - } - static { - turnAssetionStatusOn(); - } - - @JavaScriptBody(args = {"id", "attr"}, body = - "return window.document.getElementById(id)[attr].toString();") - private static native Object getAttr(String id, String attr); - @JavaScriptBody(args = {"elem", "attr"}, body = - "return elem[attr].toString();") - private static native Object getAttr(Object elem, String attr); - - @JavaScriptBody(args = {"id", "attr", "value"}, body = - "window.document.getElementById(id)[attr] = value;") - private static native void setAttr(String id, String attr, Object value); - @JavaScriptBody(args = {"elem", "attr", "value"}, body = - "elem[attr] = value;") - private static native void setAttr(Object id, String attr, Object value); - - @JavaScriptBody(args = {}, body = "return; window.close();") - private static native void closeWindow(); - - private static Object textArea; - private static Object statusArea; - - private static void log(String newText) { - if (textArea == null) { - return; - } - String attr = "value"; - setAttr(textArea, attr, getAttr(textArea, attr) + "\n" + newText); - setAttr(textArea, "scrollTop", getAttr(textArea, "scrollHeight")); - } - - private static void beginTest(Case c) { - Object[] arr = new Object[2]; - beginTest(c.getClassName() + "." + c.getMethodName(), c, arr); - textArea = arr[0]; - statusArea = arr[1]; - } - - private static void finishTest(Case c, Object res) { - if ("null".equals(res)) { - setAttr(statusArea, "innerHTML", "Success"); - } else { - setAttr(statusArea, "innerHTML", "Result " + res); - } - statusArea = null; - textArea = null; - } - - @JavaScriptBody(args = { "test", "c", "arr" }, body = - "var ul = window.document.getElementById('bck2brwsr.result');\n" - + "var li = window.document.createElement('li');\n" - + "var span = window.document.createElement('span');" - + "span.innerHTML = test + ' - ';\n" - + "var details = window.document.createElement('a');\n" - + "details.innerHTML = 'Details';\n" - + "details.href = '#';\n" - + "var p = window.document.createElement('p');\n" - + "var status = window.document.createElement('a');\n" - + "status.innerHTML = 'running';" - + "details.onclick = function() { li.appendChild(p); li.removeChild(details); status.innerHTML = 'Run Again'; status.href = '#'; };\n" - + "status.onclick = function() { c.again__V_3Ljava_lang_Object_2(arr); }\n" - + "var pre = window.document.createElement('textarea');\n" - + "pre.cols = 100;" - + "pre.rows = 10;" - + "li.appendChild(span);\n" - + "li.appendChild(status);\n" - + "var span = window.document.createElement('span');" - + "span.innerHTML = ' ';\n" - + "li.appendChild(span);\n" - + "li.appendChild(details);\n" - + "p.appendChild(pre);\n" - + "ul.appendChild(li);\n" - + "arr[0] = pre;\n" - + "arr[1] = status;\n" - ) - private static native void beginTest(String test, Case c, Object[] arr); - - @JavaScriptBody(args = { "url", "callback", "arr" }, body = "" - + "var request = new XMLHttpRequest();\n" - + "request.open('GET', url, true);\n" - + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n" - + "request.onreadystatechange = function() {\n" - + " if (this.readyState!==4) return;\n" - + " arr[0] = this.responseText;\n" - + " callback.run__V();\n" - + "};" - + "request.send();" - ) - private static native void loadText(String url, Runnable callback, String[] arr) throws IOException; - - public static void harness(String url) throws IOException { - log("Connecting to " + url); - Request r = new Request(url); - } - - private static class Request implements Runnable { - private final String[] arr = { null }; - private final String url; - private Case c; - private int retries; - - private Request(String url) throws IOException { - this.url = url; - loadText(url, this, arr); - } - private Request(String url, String u) throws IOException { - this.url = url; - loadText(u, this, arr); - } - - @Override - public void run() { - try { - if (c == null) { - String data = arr[0]; - - if (data == null) { - log("Some error exiting"); - closeWindow(); - return; - } - - if (data.isEmpty()) { - log("No data, exiting"); - closeWindow(); - return; - } - - c = Case.parseData(data); - beginTest(c); - log("Got \"" + data + "\""); - } else { - log("Processing \"" + arr[0] + "\" for " + retries + " time"); - } - Object result = retries++ >= 10 ? "java.lang.InterruptedException:timeout" : c.runTest(); - finishTest(c, result); - - String u = url + "?request=" + c.getRequestId() + "&result=" + result; - new Request(url, u); - } catch (Exception ex) { - if (ex instanceof InterruptedException) { - log("Re-scheduling in 100ms"); - schedule(this, 100); - return; - } - log(ex.getClass().getName() + ":" + ex.getMessage()); - } - } - } - - private static String encodeURL(String r) throws UnsupportedEncodingException { - final String SPECIAL = "%$&+,/:;=?@"; - StringBuilder sb = new StringBuilder(); - byte[] utf8 = r.getBytes("UTF-8"); - for (int i = 0; i < utf8.length; i++) { - int ch = utf8[i] & 0xff; - if (ch < 32 || ch > 127 || SPECIAL.indexOf(ch) >= 0) { - final String numbers = "0" + Integer.toHexString(ch); - sb.append("%").append(numbers.substring(numbers.length() - 2)); - } else { - if (ch == 32) { - sb.append("+"); - } else { - sb.append((char)ch); - } - } - } - return sb.toString(); - } - - static String invoke(String clazz, String method) throws - ClassNotFoundException, InvocationTargetException, IllegalAccessException, - InstantiationException, InterruptedException { - final Object r = new Case(null).invokeMethod(clazz, method); - return r == null ? "null" : r.toString().toString(); - } - - /** Helper method that inspects the classpath and loads given resource - * (usually a class file). Used while running tests in Rhino. - * - * @param name resource name to find - * @return the array of bytes in the given resource - * @throws IOException I/O in case something goes wrong - */ - public static byte[] read(String name) throws IOException { - URL u = null; - Enumeration en = Console.class.getClassLoader().getResources(name); - while (en.hasMoreElements()) { - u = en.nextElement(); - } - if (u == null) { - throw new IOException("Can't find " + name); - } - try (InputStream is = u.openStream()) { - byte[] arr; - arr = new byte[is.available()]; - int offset = 0; - while (offset < arr.length) { - int len = is.read(arr, offset, arr.length - offset); - if (len == -1) { - throw new IOException("Can't read " + name); - } - offset += len; - } - return arr; - } - } - - @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;") - private static void turnAssetionStatusOn() { - } - - @JavaScriptBody(args = {"r", "time"}, body = - "return window.setTimeout(function() { r.run__V(); }, time);") - private static native Object schedule(Runnable r, int time); - - private static final class Case { - private final Object data; - private Object inst; - - private Case(Object data) { - this.data = data; - } - - public static Case parseData(String s) { - return new Case(toJSON(s)); - } - - public String getMethodName() { - return value("methodName", data); - } - - public String getClassName() { - return value("className", data); - } - - public String getRequestId() { - return value("request", data); - } - - public String getHtmlFragment() { - return value("html", data); - } - - void again(Object[] arr) { - try { - textArea = arr[0]; - statusArea = arr[1]; - setAttr(textArea, "value", ""); - runTest(); - } catch (Exception ex) { - log(ex.getClass().getName() + ":" + ex.getMessage()); - } - } - - private Object runTest() throws IllegalAccessException, - IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException, - InvocationTargetException, InstantiationException, InterruptedException { - if (this.getHtmlFragment() != null) { - setAttr("bck2brwsr.fragment", "innerHTML", this.getHtmlFragment()); - } - log("Invoking " + this.getClassName() + '.' + this.getMethodName() + " as request: " + this.getRequestId()); - Object result = invokeMethod(this.getClassName(), this.getMethodName()); - setAttr("bck2brwsr.fragment", "innerHTML", ""); - log("Result: " + result); - result = encodeURL("" + result); - log("Sending back: ...?request=" + this.getRequestId() + "&result=" + result); - return result; - } - - private Object invokeMethod(String clazz, String method) - throws ClassNotFoundException, InvocationTargetException, - InterruptedException, IllegalAccessException, IllegalArgumentException, - InstantiationException { - Method found = null; - Class c = Class.forName(clazz); - for (Method m : c.getMethods()) { - if (m.getName().equals(method)) { - found = m; - } - } - Object res; - if (found != null) { - try { - if ((found.getModifiers() & Modifier.STATIC) != 0) { - res = found.invoke(null); - } else { - if (inst == null) { - inst = c.newInstance(); - } - res = found.invoke(inst); - } - } catch (Throwable ex) { - if (ex instanceof InvocationTargetException) { - ex = ((InvocationTargetException) ex).getTargetException(); - } - if (ex instanceof InterruptedException) { - throw (InterruptedException)ex; - } - res = ex.getClass().getName() + ":" + ex.getMessage(); - } - } else { - res = "Can't find method " + method + " in " + clazz; - } - return res; - } - - @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');") - private static native Object toJSON(String s); - - @JavaScriptBody(args = {"p", "d"}, body = - "var v = d[p];\n" - + "if (typeof v === 'undefined') return null;\n" - + "return v.toString();" - ) - private static native String value(String p, Object d); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml --- a/rt/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ - - - - - - Bck2Brwsr Harness - - - - - -

Bck2Brwsr Execution Harness

- -
    -
- -
- - - - diff -r c7a085d63ab5 -r 3f7991249a20 rt/mojo/pom.xml --- a/rt/mojo/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/mojo/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -81,5 +81,15 @@ launcher ${project.version} + + ${project.groupId} + launcher.http + ${project.version} + + + ${project.groupId} + launcher.fx + ${project.version} + diff -r c7a085d63ab5 -r 3f7991249a20 rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +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.mojo; - -import java.io.Closeable; -import org.apache.maven.plugin.AbstractMojo; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.project.MavenProject; -import org.apidesign.bck2brwsr.launcher.Launcher; - -/** Executes given HTML page in a browser. */ -@Mojo(name="brwsr", defaultPhase=LifecyclePhase.NONE) -public class BrswrMojo extends AbstractMojo { - public BrswrMojo() { - } - /** Resource to show as initial page */ - @Parameter - private String startpage; - - @Parameter(defaultValue="${project}") - private MavenProject prj; - - /** Root of the class files */ - @Parameter(defaultValue="${project.build.directory}/classes") - private File classes; - - /** Root of all pages, and files, etc. */ - @Parameter - private File directory; - - @Override - public void execute() throws MojoExecutionException { - if (startpage == null) { - throw new MojoExecutionException("You have to provide a start page"); - } - - try { - Closeable httpServer; - if (directory != null) { - httpServer = Launcher.showDir(directory, startpage); - } else { - URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts()); - try { - httpServer = Launcher.showURL(url, startpage()); - } catch (Exception ex) { - throw new MojoExecutionException("Can't open " + startpage(), ex); - } - } - System.in.read(); - httpServer.close(); - } catch (IOException ex) { - throw new MojoExecutionException("Can't show the browser", ex); - } - } - - private String startpage() { - return startpage; - } - - private static URLClassLoader buildClassLoader(File root, Collection deps) throws MalformedURLException { - List arr = new ArrayList(); - arr.add(root.toURI().toURL()); - for (Artifact a : deps) { - final File f = a.getFile(); - if (f != null) { - arr.add(f.toURI().toURL()); - } - } - return new URLClassLoader(arr.toArray(new URL[0]), BrswrMojo.class.getClassLoader()); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrwsrMojo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrwsrMojo.java Mon Apr 29 16:32:14 2013 +0200 @@ -0,0 +1,108 @@ +/** + * 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.mojo; + +import java.io.Closeable; +import org.apache.maven.plugin.AbstractMojo; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apidesign.bck2brwsr.launcher.Launcher; + +/** Executes given HTML page in a browser. */ +@Mojo(name="brwsr", defaultPhase=LifecyclePhase.NONE) +public class BrwsrMojo extends AbstractMojo { + public BrwsrMojo() { + } + + /** The identification of a launcher to use. Known values fxbrwsr, + * bck2brwsr, or + * name of an external process to execute. + */ + @Parameter + private String launcher; + + + /** Resource to show as initial page */ + @Parameter + private String startpage; + + @Parameter(defaultValue="${project}") + private MavenProject prj; + + /** Root of the class files */ + @Parameter(defaultValue="${project.build.directory}/classes") + private File classes; + + /** Root of all pages, and files, etc. */ + @Parameter + private File directory; + + @Override + public void execute() throws MojoExecutionException { + if (startpage == null) { + throw new MojoExecutionException("You have to provide a start page"); + } + + try { + Closeable httpServer; + if (directory != null) { + httpServer = Launcher.showDir(directory, startpage); + } else { + URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts()); + try { + httpServer = Launcher.showURL(launcher, url, startpage()); + } catch (Exception ex) { + throw new MojoExecutionException("Can't open " + startpage(), ex); + } + } + System.in.read(); + httpServer.close(); + } catch (IOException ex) { + throw new MojoExecutionException("Can't show the browser", ex); + } + } + + private String startpage() { + return startpage; + } + + private static URLClassLoader buildClassLoader(File root, Collection deps) throws MalformedURLException { + List arr = new ArrayList(); + arr.add(root.toURI().toURL()); + for (Artifact a : deps) { + final File f = a.getFile(); + if (f != null) { + arr.add(f.toURI().toURL()); + } + } + return new URLClassLoader(arr.toArray(new URL[0]), BrwsrMojo.class.getClassLoader()); + } +} diff -r c7a085d63ab5 -r 3f7991249a20 rt/pom.xml --- a/rt/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -14,7 +14,6 @@ core emul - launcher archetype mojo vm diff -r c7a085d63ab5 -r 3f7991249a20 rt/vm/pom.xml --- a/rt/vm/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/vm/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -86,6 +86,7 @@ java + -Dskip.if.exists=true -cp org.apidesign.vm4brwsr.Main diff -r c7a085d63ab5 -r 3f7991249a20 rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Mon Apr 29 16:32:14 2013 +0200 @@ -18,6 +18,7 @@ package org.apidesign.vm4brwsr; import java.io.BufferedWriter; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; @@ -81,7 +82,14 @@ classes = classes.addAndNew(args[i]); } } - try (Writer w = new BufferedWriter(new FileWriter(generateTo))) { + + File gt = new File(generateTo); + if (Boolean.getBoolean("skip.if.exists") && gt.isFile()) { + System.err.println("Skipping as " + gt + " exists."); + System.exit(0); + } + + try (Writer w = new BufferedWriter(new FileWriter(gt))) { Bck2Brwsr.newCompiler(). obfuscation(obfLevel). addRootClasses(classes.toArray()). diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/pom.xml --- a/rt/vmtest/pom.xml Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/vmtest/pom.xml Mon Apr 29 16:32:14 2013 +0200 @@ -50,18 +50,6 @@ ${project.groupId} - vm4brwsr - ${project.version} - jar - - - ${project.groupId} - emul.mini - ${project.version} - test - - - ${project.groupId} launcher ${project.version} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java Mon Apr 29 16:32:14 2013 +0200 @@ -17,6 +17,9 @@ */ package org.apidesign.bck2brwsr.vmtest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.apidesign.bck2brwsr.launcher.Launcher; import org.apidesign.bck2brwsr.vmtest.impl.CompareCase; import org.testng.annotations.Factory; @@ -34,6 +37,9 @@ * @author Jaroslav Tulach */ public final class VMTest { + private final List classes = new ArrayList<>(); + private final List launcher = new ArrayList<>(); + private VMTest() { } @@ -47,10 +53,66 @@ * Each {@link BrwsrTest} annotated method is executed once in {@link Launcher started * browser}. * - * @param clazz the class to inspect + * @param clazz the class (or classes) to inspect * @return the set of created tests */ - public static Object[] create(Class clazz) { - return CompareCase.create(clazz); + public static Object[] create(Class clazz) { + return newTests().withClasses(clazz).build(); + } + + /** Creates new builder for test execution. Continue with methods + * like {@link #withClasses(java.lang.Class[])} or {@link #withLaunchers(java.lang.String[])}. + * Finish the process by calling {@link #build()}. + * + * @return new instance of a builder + * @since 0.7 + */ + public static VMTest newTests() { + return new VMTest(); + } + + /** Adds class (or classes) to the test execution. The classes are inspected + * to contain methods annotated by + * {@link Compare} or {@link BrwsrTest}. Appropriate set of TestNG test + * cases is then created. + *

+ * Each {@link Compare} instance runs the test in different virtual + * machine and at the end they compare the results. + *

+ * Each {@link BrwsrTest} annotated method is executed once in {@link Launcher started + * browser}. + * + * @param classes one or more classes to inspect + * @since 0.7 + */ + public final VMTest withClasses(Class... classes) { + this.classes.addAll(Arrays.asList(classes)); + return this; + } + + /** Adds list of launchers that should be used to execute tests defined + * by {@link Compare} and {@link BrwsrTest} annotations. This value + * can be overrided by using vmtest.brwsrs property. + * List of supported launchers is available in the documentation of + * {@link Launcher}. + * + * @param launcher names of one or more launchers to use for the execution + * of tests + * @since 0.7 + */ + public final VMTest withLaunchers(String... launcher) { + this.launcher.addAll(Arrays.asList(launcher)); + return this; + } + + /** Assembles the provided information into the final array of tests. + * @return array of TestNG tests + * @since 0.7 + */ + public final Object[] build() { + return CompareCase.create( + launcher.toArray(new String[0]), + classes.toArray(new Class[0]) + ); } } diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Fri Apr 26 15:09:59 2013 +0200 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Mon Apr 29 16:32:14 2013 +0200 @@ -53,26 +53,25 @@ * @param clazz the class to inspect * @return the set of created tests */ - public static Object[] create(Class clazz) { - Method[] arr = clazz.getMethods(); + public static Object[] create(String[] brwsr, Class[] classes) { List ret = new ArrayList<>(); final LaunchSetup l = LaunchSetup.INSTANCE; ret.add(l); - String[] brwsr; { String p = System.getProperty("vmtest.brwsrs"); if (p != null) { brwsr = p.split(","); - } else { - brwsr = new String[0]; } } - for (Method m : arr) { - registerCompareCases(m, l, ret, brwsr); - registerBrwsrCases(m, l, ret, brwsr); + for (Class clazz : classes) { + Method[] arr = clazz.getMethods(); + for (Method m : arr) { + registerCompareCases(m, l, ret, brwsr); + registerBrwsrCases(m, l, ret, brwsr); + } } return ret.toArray(); } diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class AssertionTest { - - @Compare public Object checkAssert() throws ClassNotFoundException { - try { - assert false : "Is assertion status on?"; - return null; - } catch (AssertionError ex) { - return ex.getClass().getName(); - } - } - - @Factory - public static Object[] create() { - return VMTest.create(AssertionTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +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.tck; - -import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.apidesign.bck2brwsr.vmtest.BrwsrTest; -import org.apidesign.bck2brwsr.vmtest.HtmlFragment; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class BrwsrCheckTest { - - @BrwsrTest public void assertWindowObjectIsDefined() { - assert window() != null : "No window object found!"; - } - - - - - @HtmlFragment("

\n" - + "Hello!\n" - + "

\n") - @BrwsrTest public void accessProvidedFragment() { - assert getElementById("hello") != null : "Element with 'hello' ID found"; - } - - @Factory - public static Object[] create() { - return VMTest.create(BrwsrCheckTest.class); - } - - - @JavaScriptBody(args = {}, body = "return window;") - private static native Object window(); - - @JavaScriptBody(args = { "id" }, body = "return window.document.getElementById(id);") - private static native Object getElementById(String id); -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +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.tck; - -import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class ByteArithmeticTest { - - private static byte add(byte x, byte y) { - return (byte)(x + y); - } - - private static byte sub(byte x, byte y) { - return (byte)(x - y); - } - - private static byte mul(byte x, byte y) { - return (byte)(x * y); - } - - private static byte div(byte x, byte y) { - return (byte)(x / y); - } - - private static byte mod(byte x, byte y) { - return (byte)(x % y); - } - - @Compare public byte conversion() { - return (byte)123456; - } - - @Compare public byte addOverflow() { - return add(Byte.MAX_VALUE, (byte)1); - } - - @Compare public byte subUnderflow() { - return sub(Byte.MIN_VALUE, (byte)1); - } - - @Compare public byte addMaxByteAndMaxByte() { - return add(Byte.MAX_VALUE, Byte.MAX_VALUE); - } - - @Compare public byte subMinByteAndMinByte() { - return sub(Byte.MIN_VALUE, Byte.MIN_VALUE); - } - - @Compare public byte multiplyMaxByte() { - return mul(Byte.MAX_VALUE, (byte)2); - } - - @Compare public byte multiplyMaxByteAndMaxByte() { - return mul(Byte.MAX_VALUE, Byte.MAX_VALUE); - } - - @Compare public byte multiplyMinByte() { - return mul(Byte.MIN_VALUE, (byte)2); - } - - @Compare public byte multiplyMinByteAndMinByte() { - return mul(Byte.MIN_VALUE, Byte.MIN_VALUE); - } - - @Compare public byte multiplyPrecision() { - return mul((byte)17638, (byte)1103); - } - - @Compare public byte division() { - return div((byte)1, (byte)2); - } - - @Compare public byte divisionReminder() { - return mod((byte)1, (byte)2); - } - - private static int readShort(byte[] byteCodes, int offset) { - int signed = byteCodes[offset]; - byte b0 = (byte)signed; - return (b0 << 8) | (byteCodes[offset + 1] & 0xff); - } - - private static int readShortArg(byte[] byteCodes, int offsetInstruction) { - return readShort(byteCodes, offsetInstruction + 1); - } - - @Compare public int readIntArgs255and156() { - final byte[] arr = new byte[] { (byte)0, (byte)255, (byte)156 }; - - assert arr[1] == -1 : "First byte: " + arr[1]; - assert arr[2] == -100 : "Second byte: " + arr[2]; - final int ret = readShortArg(arr, 0); - assert ret < 65000: "Value: " + ret; - return ret; - } - - @JavaScriptBody(args = { "arr" }, body = "arr[1] = 255; arr[2] = 156; return arr;") - private static byte[] fill255and156(byte[] arr) { - arr[1] = (byte)255; - arr[2] = (byte)156; - return arr; - } - - @Compare public int readIntArgs255and156JSArray() { - final byte[] arr = fill255and156(new byte[] { 0, 0, 0 }); - - final int ret = readShortArg(arr, 0); - assert ret < 65000: "Value: " + ret; - return ret; - } - - @Compare public int readIntArgsMinus1andMinus100() { - final byte[] arr = new byte[] { (byte)0, (byte)-1, (byte)-100 }; - - assert arr[1] == -1 : "First byte: " + arr[1]; - assert arr[2] == -100 : "Second byte: " + arr[2]; - - return readShortArg(arr, 0); - } - - @Factory - public static Object[] create() { - return VMTest.create(ByteArithmeticTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class CloneTest { - private int value; - - @Compare - public Object notSupported() throws CloneNotSupportedException { - return this.clone(); - } - - @Compare public String sameClass() throws CloneNotSupportedException { - return new Clnbl().clone().getClass().getName(); - } - - @Compare public boolean differentInstance() throws CloneNotSupportedException { - Clnbl orig = new Clnbl(); - return orig == orig.clone(); - } - - @Compare public int sameReference() throws CloneNotSupportedException { - CloneTest self = this; - Clnbl orig = new Clnbl(); - self.value = 33; - orig.ref = self; - return ((Clnbl)orig.clone()).ref.value; - } - - @Compare public int sameValue() throws CloneNotSupportedException { - Clnbl orig = new Clnbl(); - orig.value = 10; - return ((Clnbl)orig.clone()).value; - } - - @Factory - public static Object[] create() { - return VMTest.create(CloneTest.class); - } - - public static final class Clnbl implements Cloneable { - public CloneTest ref; - private int value; - - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class CompareByteArrayTest { - @Compare public int byteArraySum() { - byte[] arr = createArray(); - return sumByteArr(arr); - } - - @Compare public int countZeros() { - int zeros = 0; - for (Byte b : createArray()) { - if (b == 0) { - zeros++; - } - } - return zeros; - } - - private static int sumByteArr(byte[] arr) { - int sum = 0; - for (int i = 0; i < arr.length; i++) { - sum += arr[i]; - } - return sum; - } - - @Compare public String noOutOfBounds() { - return atIndex(1); - } - - @Compare public String outOfBounds() { - return atIndex(5); - } - - @Compare public String outOfBoundsMinus() { - return atIndex(-1); - } - - @Compare public String toOfBounds() { - return toIndex(5); - } - - @Compare public String toOfBoundsMinus() { - return toIndex(-1); - } - - @Compare public int multiArrayLength() { - int[][] arr = new int[1][0]; - return arr[0].length; - } - - @Compare public int multiObjectArrayLength() { - Object[][] arr = new Object[1][0]; - return arr[0].length; - } - - private static final int[] arr = { 0, 1, 2 }; - public static String atIndex(int at) { - return "at@" + arr[at]; - } - public static String toIndex(int at) { - arr[at] = 10; - return "ok"; - } - - - @Factory - public static Object[] create() { - return VMTest.create(CompareByteArrayTest.class); - } - - private byte[] createArray() { - byte[] arr = new byte[10]; - arr[5] = 3; - arr[7] = 8; - return arr; - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class CompareHashTest { - @Compare public int hashOfString() { - return "Ahoj".hashCode(); - } - - @Compare public int hashRemainsYieldsZero() { - Object o = new Object(); - return o.hashCode() - o.hashCode(); - } - - @Compare public int initializeInStatic() { - return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode(); - } - - @Compare public int hashOfInt() { - return Integer.valueOf(Integer.MAX_VALUE).hashCode(); - } - - @Factory - public static Object[] create() { - return VMTest.create(CompareHashTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class CompareIntArrayTest { - @Compare public int integerArraySum() { - int[] arr = createArray(); - return sumIntArr(arr); - } - - @Compare public int countZeros() { - int zeros = 0; - for (Integer i : createArray()) { - if (i == 0) { - zeros++; - } - } - return zeros; - } - - private static int sumIntArr(int[] arr) { - int sum = 0; - for (int i = 0; i < arr.length; i++) { - sum += arr[i]; - } - return sum; - } - - @Factory - public static Object[] create() { - return VMTest.create(CompareIntArrayTest.class); - } - - private int[] createArray() { - int[] arr = new int[10]; - arr[5] = 3; - arr[7] = 8; - return arr; - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +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.tck; - -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class CompareStringsTest { - @Compare public String firstChar() { - return "" + ("Hello".toCharArray()[0]); - } - - @Compare public String classCast() { - Object o = firstChar(); - return String.class.cast(o); - } - - @Compare public String classCastThrown() { - Object o = null; - return String.class.cast(o); - } - - @Compare public boolean equalToNull() { - return "Ahoj".equals(null); - } - - @Compare public int highByteLenght() { - byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 }; - return new String(arr, 0).length(); - } - - @Compare public String highByte() { - byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 }; - StringBuilder sb = new StringBuilder(); - sb.append("pref:"); - sb.append(new String(arr, 0)); - return sb.toString(); - } - - @Compare public static Object compareURLs() throws MalformedURLException { - return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString(); - } - - @Compare public String deleteLastTwoCharacters() { - StringBuilder sb = new StringBuilder(); - sb.append("453.0"); - if (sb.toString().endsWith(".0")) { - final int l = sb.length(); - sb.delete(l - 2, l); - } - return sb.toString().toString(); - } - - @Compare public String nameOfStringClass() throws Exception { - return Class.forName("java.lang.String").getName(); - } - @Compare public String nameOfArrayClass() throws Exception { - return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName(); - } - - @Compare public String lowerHello() { - return "HeLlO".toLowerCase(); - } - - @Compare public String lowerA() { - return String.valueOf(Character.toLowerCase('A')).toString(); - } - @Compare public String upperHello() { - return "hello".toUpperCase(); - } - - @Compare public String upperA() { - return String.valueOf(Character.toUpperCase('a')).toString(); - } - - @Compare public boolean matchRegExp() throws Exception { - return "58038503".matches("\\d*"); - } - - @Compare public boolean doesNotMatchRegExp() throws Exception { - return "58038503GH".matches("\\d*"); - } - - @Compare public boolean doesNotMatchRegExpFully() throws Exception { - return "Hello".matches("Hell"); - } - - @Compare public String emptyCharArray() { - char[] arr = new char[10]; - return new String(arr); - } - - @Compare public String variousCharacterTests() throws Exception { - StringBuilder sb = new StringBuilder(); - - sb.append(Character.isUpperCase('a')); - sb.append(Character.isUpperCase('A')); - sb.append(Character.isLowerCase('a')); - sb.append(Character.isLowerCase('A')); - - sb.append(Character.isLetter('A')); - sb.append(Character.isLetterOrDigit('9')); - sb.append(Character.isLetterOrDigit('A')); - sb.append(Character.isLetter('0')); - - return sb.toString().toString(); - } - - @Compare - public String nullFieldInitialized() { - NullField nf = new NullField(); - return ("" + nf.name).toString(); - } - @Compare - public String toUTFString() throws UnsupportedEncodingException { - byte[] arr = { - (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91, - (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61, - (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59, - (byte) -120 - }; - return new String(arr, "utf-8"); - } - - @Compare - public int stringToBytesLenght() throws UnsupportedEncodingException { - return "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("utf8").length; - } - - @Compare public String replaceSeq() { - return "Hello World.".replace(".", "!"); - } - @Compare public String replaceSeqAll() { - return "Hello World! Hello World.".replace("World", "Jarda"); - } - @Compare public String replaceSeqAA() { - String res = "aaa".replace("aa", "b"); - assert res.equals("ba") : "Expecting ba: " + res; - return res; - } - - @Factory - public static Object[] create() { - return VMTest.create(CompareStringsTest.class); - } - - private static final class NullField { - - String name; - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class DoubleTest { - @Compare public String integerToString() { - return toStr(1); - } - - @Compare public String integerAndHalfToString() { - return toStr(1.5); - } - - @Compare public double longToAndBack() { - return Double.parseDouble(toStr(Long.MAX_VALUE / 10)); - } - - @Compare public String negativeIntToString() { - return toStr(-10); - } - - @Compare public String negativeIntAndHalfToString() { - return toStr(-10.5); - } - - @Compare public double negativeLongAndBack() { - return Double.parseDouble(toStr(Long.MIN_VALUE / 10)); - } - - @Compare public double canParseExp() { - return Double.parseDouble(toStr(1.7976931348623157e+308)); - } - - private static String toStr(double d) { - return Double.toString(d); - } - - @Factory - public static Object[] create() { - return VMTest.create(DoubleTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +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.tck; - -import java.io.InputStream; -import java.net.URL; -import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.apidesign.bck2brwsr.vmtest.BrwsrTest; -import org.apidesign.bck2brwsr.vmtest.Http; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class HttpResourceTest { - - @Http({ - @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain") - }) - @BrwsrTest - - - public String testReadContentViaXHR() throws Exception { - String msg = read("/xhr"); - assert "Hello Brwsr!".equals(msg) : "The message was " + msg; - return msg; - } - - @Http({ - @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain") - }) - @BrwsrTest - public String testReadContentViaURL() throws Exception { - URL url = new URL("http:/url"); - String msg = (String) url.getContent(); - assert "Hello via URL!".equals(msg) : "The message was " + msg; - return msg; - } - @Http({ - @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain") - }) - @BrwsrTest - public String testReadContentViaURLWithStringParam() throws Exception { - URL url = new URL("http:/url"); - String msg = (String) url.getContent(new Class[] { String.class }); - assert "Hello via URL!".equals(msg) : "The message was " + msg; - return msg; - } - - @Http({ - @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary") - }) - @BrwsrTest - public void testReadByte() throws Exception { - URL url = new URL("http:/bytes"); - final Object res = url.getContent(new Class[] { byte[].class }); - assert res instanceof byte[] : "Expecting byte[]: " + res; - byte[] arr = (byte[]) res; - assert arr.length == 1 : "One byte " + arr.length; - assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]); - } - - @Http({ - @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary") - }) - @BrwsrTest - public void testReadByteViaInputStream() throws Exception { - URL url = new URL("http:/bytes"); - InputStream is = url.openStream(); - byte[] arr = new byte[10]; - int len = is.read(arr); - assert len == 1 : "One byte " + len; - assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]); - } - - @JavaScriptBody(args = { "url" }, body = - "var req = new XMLHttpRequest();\n" - + "req.open('GET', url, false);\n" - + "req.send();\n" - + "return req.responseText;" - ) - private static native String read(String url); - - - @Factory - public static Object[] create() { - return VMTest.create(HttpResourceTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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.tck; - -/** - * - * @author Jaroslav Tulach - */ -public class InheritanceA { - private String name; - - public void setA(String n) { - this.name = n; - } - - public String getA() { - return name; - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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.tck; - -/** - * - * @author Jaroslav Tulach - */ -public class InheritanceB extends InheritanceA { - private String name; - - public void setB(String n) { - this.name = n; - } - - public String getB() { - return name; - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class InheritanceTest { - - @Compare public String checkFieldsIndependent() throws ClassNotFoundException { - InheritanceB ib = new InheritanceB(); - ib.setA("A"); - ib.setB("B"); - return "A: " + ib.getA() + " B: " + ib.getB(); - } - - @Factory - public static Object[] create() { - return VMTest.create(InheritanceTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class IntegerArithmeticTest { - - private static int add(int x, int y) { - return x + y; - } - - private static int sub(int x, int y) { - return x - y; - } - - private static int mul(int x, int y) { - return x * y; - } - - private static int div(int x, int y) { - return x / y; - } - - private static int mod(int x, int y) { - return x % y; - } - - private static int neg(int x) { - return (-x); - } - - private static float fadd(float x, float y) { - return x + y; - } - - private static double dadd(double x, double y) { - return x + y; - } - - @Compare public int addOverflow() { - return add(Integer.MAX_VALUE, 1); - } - - @Compare public int subUnderflow() { - return sub(Integer.MIN_VALUE, 1); - } - - @Compare public int addMaxIntAndMaxInt() { - return add(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - @Compare public int subMinIntAndMinInt() { - return sub(Integer.MIN_VALUE, Integer.MIN_VALUE); - } - - @Compare public int multiplyMaxInt() { - return mul(Integer.MAX_VALUE, 2); - } - - @Compare public int multiplyMaxIntAndMaxInt() { - return mul(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - @Compare public int multiplyMinInt() { - return mul(Integer.MIN_VALUE, 2); - } - - @Compare public int multiplyMinIntAndMinInt() { - return mul(Integer.MIN_VALUE, Integer.MIN_VALUE); - } - - @Compare public int multiplyPrecision() { - return mul(119106029, 1103515245); - } - - @Compare public int division() { - return div(1, 2); - } - - @Compare public int divisionReminder() { - return mod(1, 2); - } - - @Compare public int negativeDivision() { - return div(-7, 3); - } - - @Compare public int negativeDivisionReminder() { - return mod(-7, 3); - } - - @Compare public int conversionFromFloat() { - return (int) fadd(-2, -0.6f); - } - - @Compare public int conversionFromDouble() { - return (int) dadd(-2, -0.6); - } - - @Compare public boolean divByZeroThrowsArithmeticException() { - try { - div(1, 0); - return false; - } catch (final ArithmeticException e) { - return true; - } - } - - @Compare public boolean modByZeroThrowsArithmeticException() { - try { - mod(1, 0); - return false; - } catch (final ArithmeticException e) { - return true; - } - } - - @Compare public int negate() { - return neg(123456); - } - - @Compare public int negateMaxInt() { - return neg(Integer.MAX_VALUE); - } - - @Compare public int negateMinInt() { - return neg(Integer.MIN_VALUE); - } - - @Compare public int sumTwoDimensions() { - int[][] matrix = createMatrix(4, 3); - matrix[0][0] += 10; - return matrix[0][0]; - } - - static int[][] createMatrix(int x, int y) { - return new int[x][y]; - } - - @Factory - public static Object[] create() { - return VMTest.create(IntegerArithmeticTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,376 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class LongArithmeticTest { - - private static long add(long x, long y) { - return (x + y); - } - - private static long sub(long x, long y) { - return (x - y); - } - - private static long mul(long x, long y) { - return (x * y); - } - - private static long div(long x, long y) { - return (x / y); - } - - private static long mod(long x, long y) { - return (x % y); - } - - private static long neg(long x) { - return (-x); - } - - private static long shl(long x, int b) { - return (x << b); - } - - private static long shr(long x, int b) { - return (x >> b); - } - - private static long ushr(long x, int b) { - return (x >>> b); - } - - private static long and(long x, long y) { - return (x & y); - } - - private static long or(long x, long y) { - return (x | y); - } - - private static long xor(long x, long y) { - return (x ^ y); - } - - private static float fadd(float x, float y) { - return x + y; - } - - private static double dadd(double x, double y) { - return x + y; - } - - public static int compare(long x, long y, int zero) { - final int xyResult = compareL(x, y, zero); - final int yxResult = compareL(y, x, zero); - - return ((xyResult + yxResult) == 0) ? xyResult : -2; - } - - private static int compareL(long x, long y, int zero) { - int result = -2; - int trueCount = 0; - - x += zero; - if (x == y) { - result = 0; - ++trueCount; - } - - x += zero; - if (x < y) { - result = -1; - ++trueCount; - } - - x += zero; - if (x > y) { - result = 1; - ++trueCount; - } - - return (trueCount == 1) ? result : -2; - } - - @Compare public long conversion() { - return Long.MAX_VALUE; - } - - @Compare public long negate1() { - return neg(0x00fa37d7763e0ca1l); - } - - @Compare public long negate2() { - return neg(0x80fa37d7763e0ca1l); - } - - @Compare public long negate3() { - return neg(0xfffffffffffffeddl); - } - - @Compare public long addOverflow() { - return add(Long.MAX_VALUE, 1l); - } - - @Compare public long subUnderflow() { - return sub(Long.MIN_VALUE, 1l); - } - - @Compare public long addMaxLongAndMaxLong() { - return add(Long.MAX_VALUE, Long.MAX_VALUE); - } - - @Compare public long subMinLongAndMinLong() { - return sub(Long.MIN_VALUE, Long.MIN_VALUE); - } - - @Compare public long subMinLongAndMaxLong() { - return sub(Long.MIN_VALUE, Long.MAX_VALUE); - } - - @Compare public long multiplyMaxLong() { - return mul(Long.MAX_VALUE, 2l); - } - - @Compare public long multiplyMaxLongAndMaxLong() { - return mul(Long.MAX_VALUE, Long.MAX_VALUE); - } - - @Compare public long multiplyMinLong() { - return mul(Long.MIN_VALUE, 2l); - } - - @Compare public long multiplyMinLongAndMinLong() { - return mul(Long.MIN_VALUE, Long.MIN_VALUE); - } - - @Compare public long multiplyPrecision() { - return mul(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el); - } - - @Compare public long divideSmallPositiveNumbers() { - return div(0xabcdef, 0x123); - } - - @Compare public long divideSmallNegativeNumbers() { - return div(-0xabcdef, -0x123); - } - - @Compare public long divideSmallMixedNumbers() { - return div(0xabcdef, -0x123); - } - - @Compare public long dividePositiveNumbersOneDigitDenom() { - return div(0xabcdef0102ffffl, 0x654); - } - - @Compare public long divideNegativeNumbersOneDigitDenom() { - return div(-0xabcdef0102ffffl, -0x654); - } - - @Compare public long divideMixedNumbersOneDigitDenom() { - return div(-0xabcdef0102ffffl, 0x654); - } - - @Compare public long dividePositiveNumbersMultiDigitDenom() { - return div(0x7ffefc003322aabbl, 0x89ab1000l); - } - - @Compare public long divideNegativeNumbersMultiDigitDenom() { - return div(-0x7ffefc003322aabbl, -0x123489ab1001l); - } - - @Compare public long divideMixedNumbersMultiDigitDenom() { - return div(0x7ffefc003322aabbl, -0x38f49b0b7574e36l); - } - - @Compare public long divideWithOverflow() { - return div(0x8000fffe0000l, 0x8000ffffl); - } - - @Compare public long divideWithCorrection() { - return div(0x7fff800000000000l, 0x800000000001l); - } - - @Compare public long moduloSmallPositiveNumbers() { - return mod(0xabcdef, 0x123); - } - - @Compare public long moduloSmallNegativeNumbers() { - return mod(-0xabcdef, -0x123); - } - - @Compare public long moduloSmallMixedNumbers() { - return mod(0xabcdef, -0x123); - } - - @Compare public long moduloPositiveNumbersOneDigitDenom() { - return mod(0xabcdef0102ffffl, 0x654); - } - - @Compare public long moduloNegativeNumbersOneDigitDenom() { - return mod(-0xabcdef0102ffffl, -0x654); - } - - @Compare public long moduloMixedNumbersOneDigitDenom() { - return mod(-0xabcdef0102ffffl, 0x654); - } - - @Compare public long moduloPositiveNumbersMultiDigitDenom() { - return mod(0x7ffefc003322aabbl, 0x89ab1000l); - } - - @Compare public long moduloNegativeNumbersMultiDigitDenom() { - return mod(-0x7ffefc003322aabbl, -0x123489ab1001l); - } - - @Compare public long moduloMixedNumbersMultiDigitDenom() { - return mod(0x7ffefc003322aabbl, -0x38f49b0b7574e36l); - } - - @Compare public long moduloWithOverflow() { - return mod(0x8000fffe0000l, 0x8000ffffl); - } - - @Compare public long moduloWithCorrection() { - return mod(0x7fff800000000000l, 0x800000000001l); - } - - @Compare public long conversionFromFloatPositive() { - return (long) fadd(2, 0.6f); - } - - @Compare public long conversionFromFloatNegative() { - return (long) fadd(-2, -0.6f); - } - - @Compare public long conversionFromDoublePositive() { - return (long) dadd(0x20ffff0000L, 0.6); - } - - @Compare public long conversionFromDoubleNegative() { - return (long) dadd(-0x20ffff0000L, -0.6); - } - - @Compare public boolean divByZeroThrowsArithmeticException() { - try { - div(1, 0); - return false; - } catch (final ArithmeticException e) { - return true; - } - } - - @Compare public boolean modByZeroThrowsArithmeticException() { - try { - mod(1, 0); - return false; - } catch (final ArithmeticException e) { - return true; - } - } - - @Compare public long shiftL1() { - return shl(0x00fa37d7763e0ca1l, 5); - } - - @Compare public long shiftL2() { - return shl(0x00fa37d7763e0ca1l, 32); - } - - @Compare public long shiftL3() { - return shl(0x00fa37d7763e0ca1l, 45); - } - - @Compare public long shiftR1() { - return shr(0x00fa37d7763e0ca1l, 5); - } - - @Compare public long shiftR2() { - return shr(0x00fa37d7763e0ca1l, 32); - } - - @Compare public long shiftR3() { - return shr(0x00fa37d7763e0ca1l, 45); - } - - @Compare public long uShiftR1() { - return ushr(0x00fa37d7763e0ca1l, 5); - } - - @Compare public long uShiftR2() { - return ushr(0x00fa37d7763e0ca1l, 45); - } - - @Compare public long uShiftR3() { - return ushr(0xf0fa37d7763e0ca1l, 5); - } - - @Compare public long uShiftR4() { - return ushr(0xf0fa37d7763e0ca1l, 45); - } - - @Compare public long and1() { - return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el); - } - - @Compare public long or1() { - return or(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el); - } - - @Compare public long xor1() { - return xor(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el); - } - - @Compare public long xor2() { - return xor(0x00fa37d7763e0ca1l, 0x00000000ff00123el); - } - - @Compare public long xor3() { - return xor(0x00000000763e0ca1l, 0x00000000ff00123el); - } - - @Compare public int compareSameNumbers() { - return compare(0x0000000000000000l, 0x0000000000000000l, 0); - } - - @Compare public int comparePositiveNumbers() { - return compare(0x0000000000200000l, 0x0000000010000000l, 0); - } - - @Compare public int compareNegativeNumbers() { - return compare(0xffffffffffffffffl, 0xffffffff00000000l, 0); - } - - @Compare public int compareMixedNumbers() { - return compare(0x8000000000000000l, 0x7fffffffffffffffl, 0); - } - - @Factory - public static Object[] create() { - return VMTest.create(LongArithmeticTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +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.tck; - -import java.lang.reflect.Array; -import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.apidesign.bck2brwsr.vmtest.BrwsrTest; -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class ReflectionArrayTest { - @Compare public int lengthOfStringArray() { - String[] arr = (String[]) Array.newInstance(String.class, 10); - return arr.length; - } - - @Compare public int reflectiveLengthOfStringArray() { - Object arr = Array.newInstance(String.class, 10); - return Array.getLength(arr); - } - - @Compare public int reflectiveLengthOneNonArray() { - Object arr = "non-array"; - return Array.getLength(arr); - } - - @Compare public String compTypeOfStringArray() { - String[] arr = (String[]) Array.newInstance(String.class, 10); - return arr.getClass().getComponentType().getName(); - } - - @Compare public Object negativeArrayExcp() { - return Array.newInstance(String.class, -5); - } - - @Compare public int lengthOfIntArray() { - int[] arr = (int[]) Array.newInstance(Integer.TYPE, 10); - return arr.length; - } - - @Compare public int reflectiveLengthOfIntArray() { - Object arr = Array.newInstance(Integer.TYPE, 10); - return Array.getLength(arr); - } - - @Compare public String compTypeOfIntArray() { - int[] arr = (int[]) Array.newInstance(int.class, 10); - return arr.getClass().getComponentType().getName(); - } - - @Compare public Object intNegativeArrayExcp() { - return Array.newInstance(int.class, -5); - } - - @Compare public Integer verifyAutobox() { - int[] arr = (int[]) Array.newInstance(int.class, 5); - return (Integer) Array.get(arr, 0); - } - @Compare public String verifyObjectArray() { - String[] arr = (String[]) Array.newInstance(String.class, 5); - Array.set(arr, 0, "Hello"); - return (String) Array.get(arr, 0); - } - @Compare public int verifyInt() { - int[] arr = (int[]) Array.newInstance(int.class, 5); - return Array.getInt(arr, 0); - } - @Compare public long verifyConvertToLong() { - int[] arr = (int[]) Array.newInstance(int.class, 5); - return Array.getLong(arr, 0); - } - - @Compare public Object verifySetIntToObject() { - try { - Object[] arr = (Object[]) Array.newInstance(Object.class, 5); - Array.setInt(arr, 0, 10); - return Array.get(arr, 0); - } catch (Exception exception) { - return exception.getClass().getName(); - } - } - @Compare public long verifySetShort() { - int[] arr = (int[]) Array.newInstance(int.class, 5); - Array.setShort(arr, 0, (short)10); - return Array.getLong(arr, 0); - } - @Compare public long verifyCantSetLong() { - int[] arr = (int[]) Array.newInstance(int.class, 5); - Array.setLong(arr, 0, 10); - return Array.getLong(arr, 0); - } - @Compare public float verifyLongToFloat() { - Object arr = Array.newInstance(float.class, 5); - Array.setLong(arr, 0, 10); - return Array.getFloat(arr, 0); - } - - @Compare public double verifyConvertToDouble() { - int[] arr = (int[]) Array.newInstance(int.class, 5); - return Array.getDouble(arr, 0); - } - - @Compare public int multiIntArray() { - int[][][] arr = (int[][][]) Array.newInstance(int.class, 3, 3, 3); - return arr[0][1][2] + 5 + arr[2][2][0]; - } - - @Compare public String multiIntArrayCompType() { - return Array.newInstance(int.class, 3, 3, 3).getClass().getName(); - } - - @JavaScriptBody(args = {}, body = "return [1, 2];") - private static native Object crtarr(); - - @JavaScriptBody(args = {}, body = "return new Object();") - private static native Object newobj(); - - @BrwsrTest - public static void toStringArray() { - final Object arr = crtarr(); - final Object real = new Object[2]; - assert arr instanceof Object[] : "Any array is Java array: " + arr; - assert arr.getClass() == real.getClass() : "Same classes " + arr + " and " + real.getClass(); - final String str = arr.toString(); - assert str != null; - assert str.startsWith("[Ljava.lang.Object;@") : str; - } - - @BrwsrTest - public static void objectToString() { - String s = newobj().toString(); - assert s != null : "Some string computed"; - assert s.startsWith("java.lang.Object@") : "Regular object toString(): " + s; - } - - - @Factory - public static Object[] create() { - return VMTest.create(ReflectionArrayTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,272 +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.tck; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class ReflectionTest { - @Compare public boolean nonNullThis() { - return this == null; - } - - @Compare public String intType() { - return Integer.TYPE.toString(); - } - - @Compare public String voidType() throws Exception { - return void.class.toString(); - } - - @Compare public String longClass() { - return long.class.toString(); - } - - @Compare public boolean isRunnableInterface() { - return Runnable.class.isInterface(); - } - - @Compare public boolean isAssignableToPrimitiveType() { - return boolean.class.isAssignableFrom(Runnable.class); - } - - @Compare public boolean isAssignableFromPrimitiveType() { - return Runnable.class.isAssignableFrom(boolean.class); - } - - @Compare public boolean isAssignableLongFromInt() { - return long.class.isAssignableFrom(int.class); - } - - @Compare public boolean isAssignableIntFromLong() { - return int.class.isAssignableFrom(long.class); - } - - @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException { - return Runnable.class.getMethod("run").getName(); - } - - @Compare public String namesOfMethods() { - StringBuilder sb = new StringBuilder(); - String[] arr = new String[20]; - int i = 0; - for (Method m : StaticUse.class.getMethods()) { - arr[i++] = m.getName(); - } - for (String s : sort(arr, i)) { - sb.append(s).append("\n"); - } - return sb.toString(); - } - - @Compare public String namesOfDeclaringClassesOfMethods() { - StringBuilder sb = new StringBuilder(); - String[] arr = new String[20]; - int i = 0; - for (Method m : StaticUse.class.getMethods()) { - arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName(); - } - for (String s : sort(arr, i)) { - sb.append(s).append("\n"); - } - return sb.toString(); - } - - @Compare public String cannotCallNonStaticMethodWithNull() throws Exception { - StaticUse.class.getMethod("instanceMethod").invoke(null); - return "should not happen"; - } - - @Compare public String classCastException() { - try { - Integer i = (Integer)StaticUseSub.getNonNull(); - return "" + i.intValue(); - } catch (ClassCastException ex) { - return ex.getClass().getName(); - } - } - - @Compare public String methodThatThrowsException() throws Exception { - StaticUse.class.getMethod("instanceMethod").invoke(new StaticUse()); - return "should not happen"; - } - - @Compare public Object voidReturnType() throws Exception { - return StaticUse.class.getMethod("instanceMethod").getReturnType(); - } - - @Retention(RetentionPolicy.RUNTIME) - @interface Ann { - } - - @Compare public String annoClass() throws Exception { - Retention r = Ann.class.getAnnotation(Retention.class); - assert r != null : "Annotation is present"; - assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value(); - return r.annotationType().getName(); - } - - @Compare public boolean isAnnotation() { - return Ann.class.isAnnotation(); - } - @Compare public boolean isNotAnnotation() { - return String.class.isAnnotation(); - } - @Compare public boolean isNotAnnotationEnum() { - return E.class.isAnnotation(); - } - enum E { A, B }; - @Compare public boolean isEnum() { - return E.A.getClass().isEnum(); - } - - @Compare public boolean isNotEnum() { - return "".getClass().isEnum(); - } - - @Compare public String newInstanceFails() throws InstantiationException { - try { - return "success: " + StaticUseSub.class.newInstance(); - } catch (IllegalAccessException ex) { - return ex.getClass().getName(); - } - } - - @Compare public String paramTypes() throws Exception { - Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE); - final Class[] pt = plus.getParameterTypes(); - return pt[0].getName(); - } - @Compare public String paramTypesNotFound() throws Exception { - return StaticUse.class.getMethod("plus", int.class, double.class).toString(); - } - @Compare public int methodWithArgs() throws Exception { - Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE); - return (Integer)plus.invoke(null, 2, 3); - } - - @Compare public String classGetNameForByte() { - return byte.class.getName(); - } - @Compare public String classGetNameForBaseObject() { - return newObject().getClass().getName(); - } - @Compare public String classGetNameForJavaObject() { - return new Object().getClass().getName(); - } - @Compare public String classGetNameForObjectArray() { - return (new Object[3]).getClass().getName(); - } - @Compare public String classGetNameForSimpleIntArray() { - return (new int[3]).getClass().getName(); - } - @Compare public boolean sameClassGetNameForSimpleCharArray() { - return (new char[3]).getClass() == (new char[34]).getClass(); - } - @Compare public String classGetNameForMultiIntArray() { - return (new int[3][4][5][6][7][8][9]).getClass().getName(); - } - @Compare public String classGetNameForMultiIntArrayInner() { - final int[][][][][][][] arr = new int[3][4][5][6][7][8][9]; - int[][][][][][] subarr = arr[0]; - int[][][][][] subsubarr = subarr[0]; - return subsubarr.getClass().getName(); - } - @Compare public String classGetNameForMultiStringArray() { - return (new String[3][4][5][6][7][8][9]).getClass().getName(); - } - - @Compare public String classForByte() throws Exception { - return Class.forName("[Z").getName(); - } - - @Compare public String classForUnknownArray() { - try { - return Class.forName("[W").getName(); - } catch (Exception ex) { - return ex.getClass().getName(); - } - } - - @Compare public String classForUnknownDeepArray() { - try { - return Class.forName("[[[[[W").getName(); - } catch (Exception ex) { - return ex.getClass().getName(); - } - } - - @Compare public String componentGetNameForObjectArray() { - return (new Object[3]).getClass().getComponentType().getName(); - } - @Compare public boolean sameComponentGetNameForObjectArray() { - return (new Object[3]).getClass().getComponentType() == Object.class; - } - @Compare public String componentGetNameForSimpleIntArray() { - return (new int[3]).getClass().getComponentType().getName(); - } - @Compare public String componentGetNameForMultiIntArray() { - return (new int[3][4][5][6][7][8][9]).getClass().getComponentType().getName(); - } - @Compare public String componentGetNameForMultiStringArray() { - Class c = (new String[3][4][5][6][7][8][9]).getClass(); - StringBuilder sb = new StringBuilder(); - for (;;) { - sb.append(c.getName()).append("\n"); - c = c.getComponentType(); - if (c == null) { - break; - } - } - return sb.toString(); - } - - @Compare public boolean isArray() { - return new Object[0].getClass().isArray(); - } - - @JavaScriptBody(args = { "arr", "len" }, body="var a = arr.slice(0, len); a.sort(); return a;") - private static String[] sort(String[] arr, int len) { - List list = Arrays.asList(arr).subList(0, len); - Collections.sort(list); - return list.toArray(new String[0]); - } - - @JavaScriptBody(args = {}, body = "return new Object();") - private static Object newObject() { - return new Object(); - } - - @Factory - public static Object[] create() { - return VMTest.create(ReflectionTest.class); - } - -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +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.tck; - -import java.io.InputStream; -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class ResourcesTest { - - @Compare public String readResourceAsStream() throws Exception { - InputStream is = getClass().getResourceAsStream("Resources.txt"); - byte[] b = new byte[30]; - int len = is.read(b); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < len; i++) { - sb.append((char)b[i]); - } - return sb.toString(); - } - - @Factory public static Object[] create() { - return VMTest.create(ResourcesTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class ShortArithmeticTest { - - private static short add(short x, short y) { - return (short)(x + y); - } - - private static short sub(short x, short y) { - return (short)(x - y); - } - - private static short mul(short x, short y) { - return (short)(x * y); - } - - private static short div(short x, short y) { - return (short)(x / y); - } - - private static short mod(short x, short y) { - return (short)(x % y); - } - - @Compare public short conversion() { - return (short)123456; - } - - @Compare public short addOverflow() { - return add(Short.MAX_VALUE, (short)1); - } - - @Compare public short subUnderflow() { - return sub(Short.MIN_VALUE, (short)1); - } - - @Compare public short addMaxShortAndMaxShort() { - return add(Short.MAX_VALUE, Short.MAX_VALUE); - } - - @Compare public short subMinShortAndMinShort() { - return sub(Short.MIN_VALUE, Short.MIN_VALUE); - } - - @Compare public short multiplyMaxShort() { - return mul(Short.MAX_VALUE, (short)2); - } - - @Compare public short multiplyMaxShortAndMaxShort() { - return mul(Short.MAX_VALUE, Short.MAX_VALUE); - } - - @Compare public short multiplyMinShort() { - return mul(Short.MIN_VALUE, (short)2); - } - - @Compare public short multiplyMinShortAndMinShort() { - return mul(Short.MIN_VALUE, Short.MIN_VALUE); - } - - @Compare public short multiplyPrecision() { - return mul((short)17638, (short)1103); - } - - @Compare public short division() { - return div((short)1, (short)2); - } - - @Compare public short divisionReminder() { - return mod((short)1, (short)2); - } - - @Factory - public static Object[] create() { - return VMTest.create(ShortArithmeticTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +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.tck; - -class StaticUse { - public static final Object NON_NULL = new Object(); - public static int cnt; - static { - if (cnt++ != 0) { - throw new IllegalStateException("Multiple initialization of a "); - } - } - - StaticUse() { - } - - public void instanceMethod() { - throw new IllegalStateException(); - } - - public static int plus(int a, int b) { - return a + b; - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSub.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSub.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +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.tck; - -public class StaticUseSub extends StaticUse { - private StaticUseSub() { - } - - public static Object getNonNull() { - return NON_NULL; - } - static Object getNull() { - return null; - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSubTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSubTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +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.tck; - -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class StaticUseSubTest { - @Compare public String staticFieldInitializationInSuperClass() throws Exception { - Object ret = StaticUseSub.getNonNull(); - return ret.getClass().getName(); - } - - @Compare public String isNullPointerTheSame() throws Exception { - try { - return StaticUseSub.getNull().getClass().toString(); - } catch (NullPointerException ex) { - return ex.getClass().getName(); - } - } - - @Factory public static Object[] create() { - return VMTest.create(StaticUseSubTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +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.impl; - -import java.io.UnsupportedEncodingException; -import java.util.zip.CRC32; -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class CRC32Test { - - @Compare public long crc1() throws UnsupportedEncodingException { - CRC32 crc = new CRC32(); - crc.update("Hello World!".getBytes("UTF-8")); - return crc.getValue(); - } - - @Factory public static Object[] create() { - return VMTest.create(CRC32Test.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CallMeTwiceTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CallMeTwiceTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +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.impl; - -import org.apidesign.bck2brwsr.vmtest.BrwsrTest; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -public class CallMeTwiceTest { - int cnt; - - @BrwsrTest public void callMeTwice() throws InterruptedException { - if (cnt++ == 0) { - throw new InterruptedException(); - } - int prevCnt = cnt; - cnt = 0; - assert prevCnt == 2 : "We need to receive two calls " + prevCnt; - } - - @Factory public static Object[] create() { - return VMTest.create(CallMeTwiceTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +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.impl; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import org.apidesign.bck2brwsr.emul.zip.FastJar; -import org.testng.annotations.Test; -import static org.testng.Assert.*; - -/** - * - * @author Jaroslav Tulach - */ -@GenerateZip(name = "five.zip", contents = { - "1.txt", "one", - "2.txt", "duo", - "3.txt", "three", - "4.txt", "four", - "5.txt", "five" -}) -public class ZipEntryTest { - @Test - public void readEntriesEffectively() throws IOException { - InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip"); - byte[] arr = new byte[is.available()]; - int len = is.read(arr); - assertEquals(len, arr.length, "Read fully"); - - FastJar fj = new FastJar(arr); - FastJar.Entry[] entrs = fj.list(); - - assertEquals(5, entrs.length, "Five entries"); - - for (int i = 1; i <= 5; i++) { - FastJar.Entry en = entrs[i - 1]; - assertEquals(en.name, i + ".txt"); -// assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read"); - } - - assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK"); - assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK"); - } - - private static void assertContent(String exp, InputStream is, String msg) throws IOException { - byte[] arr = new byte[512]; - int len = is.read(arr); - String s = new String(arr, 0, len); - assertEquals(exp, s, msg); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +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.impl; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Objects; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.apidesign.bck2brwsr.vmtest.BrwsrTest; -import org.apidesign.bck2brwsr.vmtest.Compare; -import org.apidesign.bck2brwsr.vmtest.Http; -import org.apidesign.bck2brwsr.vmtest.VMTest; -import org.testng.annotations.Factory; - -/** - * - * @author Jaroslav Tulach - */ -@GenerateZip(name = "readAnEntry.zip", contents = { - "my/main/file.txt", "Hello World!" -}) -public class ZipFileTest { - - @Compare public String readAnEntry() throws IOException { - InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip"); - ZipInputStream zip = new ZipInputStream(is); - ZipEntry entry = zip.getNextEntry(); - assertEquals(entry.getName(), "my/main/file.txt", "Correct entry"); - - byte[] arr = new byte[4096]; - int len = zip.read(arr); - - assertEquals(zip.getNextEntry(), null, "No next entry"); - - final String ret = new String(arr, 0, len, "UTF-8"); - return ret; - } - - @JavaScriptBody(args = { "res", "path" }, body = - "var myvm = bck2brwsr.apply(null, path);\n" - + "var cls = myvm.loadClass('java.lang.String');\n" - + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n" - ) - private static native Object loadVMResource(String res, String...path); - - @Http({ - @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip") - }) - @BrwsrTest public void canVmLoadResourceFromZip() throws IOException { - Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar"); - assert res instanceof InputStream : "Got array of bytes: " + res; - InputStream is = (InputStream)res; - - byte[] arr = new byte[4096]; - int len = is.read(arr); - - final String ret = new String(arr, 0, len, "UTF-8"); - - assertEquals(ret, "Hello World!", "Can read the bytes"); - } - - @GenerateZip(name = "cpattr.zip", contents = { - "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n" - + "Created-By: hand\n" - + "Class-Path: realJar.jar\n\n\n" - }) - @Http({ - @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"), - @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"), - }) - @BrwsrTest public void understandsClassPathAttr() throws IOException { - Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar"); - assert res instanceof InputStream : "Got array of bytes: " + res; - InputStream is = (InputStream)res; - - byte[] arr = new byte[4096]; - int len = is.read(arr); - - final String ret = new String(arr, 0, len, "UTF-8"); - - assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR"); - } - - private static void assertEquals(Object real, Object exp, String msg) { - assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real; - } - - @Factory public static Object[] create() { - return VMTest.create(ZipFileTest.class); - } -} diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe --- a/rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -þ \ No newline at end of file diff -r c7a085d63ab5 -r 3f7991249a20 rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt --- a/rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt Fri Apr 26 15:09:59 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Ahoj