Runs TCK tests via BrowserBuilder classloader
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 24 Jun 2013 15:34:25 +0200
branchclassloader
changeset 146c899fc4d69dd
parent 145 5f6bda7d957d
child 147 2f6a718b2631
Runs TCK tests via BrowserBuilder
boot/src/main/java/net/java/html/boot/BrowserBuilder.java
ko-fx/pom.xml
ko-fx/src/test/java/org/apidesign/html/kofx/KOFx.java
ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java
ko-fx/src/test/resources/org/apidesign/html/kofx/test.html
     1.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Mon Jun 24 15:32:43 2013 +0200
     1.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java	Mon Jun 24 15:34:25 2013 +0200
     1.3 @@ -36,6 +36,8 @@
     1.4  public final class BrowserBuilder {
     1.5      private String resource;
     1.6      private Class<?> clazz;
     1.7 +    private Class[] browserClass;
     1.8 +    private Runnable onLoad;
     1.9      private BrowserBuilder() {
    1.10      }
    1.11      
    1.12 @@ -54,6 +56,10 @@
    1.13      }
    1.14      
    1.15      public void showAndWait() {
    1.16 +        if (resource == null) {
    1.17 +            throw new IllegalStateException("Need to specify resource via loadPage method");
    1.18 +        }
    1.19 +        
    1.20          FImpl impl = new FImpl(clazz.getClassLoader());
    1.21          URL url = clazz.getResource(resource);
    1.22          if (url == null) {
    1.23 @@ -68,6 +74,12 @@
    1.24                  public void run() {
    1.25                      try {
    1.26                          Class<?> newClazz = Class.forName(clazz.getName(), true, loader);
    1.27 +                        if (browserClass != null) {
    1.28 +                            browserClass[0] = newClazz;
    1.29 +                        }
    1.30 +                        if (onLoad != null) {
    1.31 +                            onLoad.run();
    1.32 +                        }
    1.33                      } catch (ClassNotFoundException ex) {
    1.34                          throw new IllegalStateException(ex);
    1.35                      }
    1.36 @@ -78,6 +90,20 @@
    1.37          }
    1.38          throw new IllegalStateException("Can't find any Fn.Definer");
    1.39      }
    1.40 +
    1.41 +    public BrowserBuilder onClassReady(Class[] browserClass) {
    1.42 +        if (browserClass.length != 1) {
    1.43 +            throw new IllegalStateException("Expecting array of size one");
    1.44 +        }
    1.45 +        this.browserClass = browserClass;
    1.46 +        return this;
    1.47 +    }
    1.48 +
    1.49 +    // callback happens on browser thread
    1.50 +    public BrowserBuilder onLoad(Runnable r) {
    1.51 +        this.onLoad = r;
    1.52 +        return this;
    1.53 +    }
    1.54      
    1.55      private static final class FImpl implements FindResources {
    1.56          final ClassLoader l;
     2.1 --- a/ko-fx/pom.xml	Mon Jun 24 15:32:43 2013 +0200
     2.2 +++ b/ko-fx/pom.xml	Mon Jun 24 15:34:25 2013 +0200
     2.3 @@ -62,23 +62,16 @@
     2.4        <scope>provided</scope>
     2.5      </dependency>
     2.6      <dependency>
     2.7 -      <groupId>org.apidesign.bck2brwsr</groupId>
     2.8 -      <artifactId>launcher.fx</artifactId>
     2.9 -      <version>${bck2brwsr.launcher.version}</version>
    2.10 -      <scope>test</scope>
    2.11 -    </dependency>
    2.12 -    <dependency>
    2.13        <groupId>org.apidesign.html</groupId>
    2.14        <artifactId>net.java.html.boot</artifactId>
    2.15        <version>${project.version}</version>
    2.16        <type>jar</type>
    2.17      </dependency>
    2.18      <dependency>
    2.19 -      <groupId>org.apidesign.bck2brwsr</groupId>
    2.20 -      <artifactId>vmtest</artifactId>
    2.21 -      <version>0.8-SNAPSHOT</version>
    2.22 +      <groupId>${project.groupId}</groupId>
    2.23 +      <artifactId>boot-fx</artifactId>
    2.24 +      <version>${project.version}</version>
    2.25        <scope>test</scope>
    2.26 -      <type>jar</type>
    2.27      </dependency>
    2.28    </dependencies>
    2.29  </project>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/ko-fx/src/test/java/org/apidesign/html/kofx/KOFx.java	Mon Jun 24 15:34:25 2013 +0200
     3.3 @@ -0,0 +1,74 @@
     3.4 +/**
     3.5 + * HTML via Java(tm) Language Bindings
     3.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details. apidesign.org
    3.16 + * designates this particular file as subject to the
    3.17 + * "Classpath" exception as provided by apidesign.org
    3.18 + * in the License file that accompanied this code.
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License
    3.21 + * along with this program. Look for COPYING file in the top folder.
    3.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    3.23 + */
    3.24 +package org.apidesign.html.kofx;
    3.25 +
    3.26 +import java.lang.reflect.Method;
    3.27 +import javafx.application.Platform;
    3.28 +import org.testng.ITest;
    3.29 +import org.testng.annotations.Test;
    3.30 +
    3.31 +/**
    3.32 + *
    3.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.34 + */
    3.35 +public final class KOFx implements ITest, Runnable {
    3.36 +    private final Method m;
    3.37 +    private Object result;
    3.38 +
    3.39 +    KOFx(Method m) {
    3.40 +        this.m = m;
    3.41 +    }
    3.42 +
    3.43 +    @Override
    3.44 +    public String getTestName() {
    3.45 +        return m.getDeclaringClass().getName() + "." + m.getName();
    3.46 +    }
    3.47 +
    3.48 +    @Test
    3.49 +    public synchronized void executeTest() throws Exception {
    3.50 +        if (result == null) {
    3.51 +            Platform.runLater(this);
    3.52 +            wait();
    3.53 +        }
    3.54 +        if (result instanceof Exception) {
    3.55 +            throw (Exception)result;
    3.56 +        }
    3.57 +        if (result instanceof Error) {
    3.58 +            throw (Error)result;
    3.59 +        }
    3.60 +    }
    3.61 +
    3.62 +    @Override
    3.63 +    public synchronized void run() {
    3.64 +        try {
    3.65 +            Object inst = m.getDeclaringClass().newInstance();
    3.66 +            result = m.invoke(inst);
    3.67 +            if (result == null) {
    3.68 +                result = this;
    3.69 +            }
    3.70 +        } catch (Throwable ex) {
    3.71 +            result = ex;
    3.72 +        } finally {
    3.73 +            notifyAll();
    3.74 +        }
    3.75 +    }
    3.76 +    
    3.77 +}
     4.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java	Mon Jun 24 15:32:43 2013 +0200
     4.2 +++ b/ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java	Mon Jun 24 15:34:25 2013 +0200
     4.3 @@ -24,15 +24,20 @@
     4.4  import java.io.IOException;
     4.5  import java.io.InputStreamReader;
     4.6  import java.io.PrintWriter;
     4.7 +import java.lang.annotation.Annotation;
     4.8 +import java.lang.reflect.Method;
     4.9  import java.net.HttpURLConnection;
    4.10  import java.net.URI;
    4.11  import java.net.URISyntaxException;
    4.12  import java.net.URL;
    4.13  import java.net.URLConnection;
    4.14 +import java.util.ArrayList;
    4.15 +import java.util.List;
    4.16  import java.util.Map;
    4.17 +import java.util.concurrent.Executors;
    4.18  import net.java.html.BrwsrCtx;
    4.19 +import net.java.html.boot.BrowserBuilder;
    4.20  import net.java.html.js.JavaScriptBody;
    4.21 -import org.apidesign.bck2brwsr.vmtest.VMTest;
    4.22  import org.apidesign.html.context.spi.Contexts;
    4.23  import org.apidesign.html.json.spi.Technology;
    4.24  import org.apidesign.html.json.spi.Transfer;
    4.25 @@ -42,6 +47,9 @@
    4.26  import org.json.JSONObject;
    4.27  import org.openide.util.lookup.ServiceProvider;
    4.28  import org.testng.annotations.Factory;
    4.29 +import static org.testng.Assert.*;
    4.30 +import org.testng.ITest;
    4.31 +import org.testng.annotations.Test;
    4.32  
    4.33  /**
    4.34   *
    4.35 @@ -52,11 +60,55 @@
    4.36      public KnockoutFXTest() {
    4.37      }
    4.38  
    4.39 -    @Factory public static Object[] compatibilityTests() {
    4.40 -        return VMTest.newTests().
    4.41 -            withClasses(testClasses()).
    4.42 -            withTestAnnotation(KOTest.class).
    4.43 -            withLaunchers("fxbrwsr").build();
    4.44 +    @Factory public static Object[] compatibilityTests() throws Exception {
    4.45 +        Class[] arr = testClasses();
    4.46 +        ClassLoader l = KnockoutFXTest.class.getClassLoader();
    4.47 +        for (int i = 0; i < arr.length; i++) {
    4.48 +            assertEquals(arr[i].getClassLoader(), l, "All classes loaded by the same classloader");
    4.49 +        }
    4.50 +        assertNotNull(l, "At least one class provided");
    4.51 +        
    4.52 +        class R implements Runnable {
    4.53 +            final Class[] browserClass = { null };
    4.54 +            @Override
    4.55 +            public synchronized void run() {
    4.56 +                notifyAll();
    4.57 +            }
    4.58 +            
    4.59 +            synchronized ClassLoader getClassLoader() throws InterruptedException {
    4.60 +                while (browserClass[0] == null) {
    4.61 +                    wait();
    4.62 +                }
    4.63 +                return browserClass[0].getClassLoader();
    4.64 +            }
    4.65 +        }
    4.66 +        R r = new R();
    4.67 +        
    4.68 +        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
    4.69 +            loadPage("test.html").
    4.70 +            onClassReady(r.browserClass).
    4.71 +            onLoad(r);
    4.72 +        Executors.newSingleThreadExecutor().submit(new Runnable() {
    4.73 +            @Override
    4.74 +            public void run() {
    4.75 +                bb.showAndWait();
    4.76 +            }
    4.77 +        });
    4.78 +
    4.79 +        l = r.getClassLoader();
    4.80 +        List<Object> res = new ArrayList<Object>();
    4.81 +        for (int i = 0; i < arr.length; i++) {
    4.82 +            Class<?> c = Class.forName(arr[i].getName(), true, l);
    4.83 +            Class<? extends Annotation> koTest = 
    4.84 +                c.getClassLoader().loadClass(KOTest.class.getName()).
    4.85 +                asSubclass(Annotation.class);
    4.86 +            for (Method m : c.getMethods()) {
    4.87 +                if (m.getAnnotation(koTest) != null) {
    4.88 +                    res.add(new KOFx(m));
    4.89 +                }
    4.90 +            }
    4.91 +        }
    4.92 +        return res.toArray();
    4.93      }
    4.94  
    4.95      @Override
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/ko-fx/src/test/resources/org/apidesign/html/kofx/test.html	Mon Jun 24 15:34:25 2013 +0200
     5.3 @@ -0,0 +1,33 @@
     5.4 +<!--
     5.5 +
     5.6 +    HTML via Java(tm) Language Bindings
     5.7 +    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.8 +
     5.9 +    This program is free software: you can redistribute it and/or modify
    5.10 +    it under the terms of the GNU General Public License as published by
    5.11 +    the Free Software Foundation, version 2 of the License.
    5.12 +
    5.13 +    This program is distributed in the hope that it will be useful,
    5.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.16 +    GNU General Public License for more details. apidesign.org
    5.17 +    designates this particular file as subject to the
    5.18 +    "Classpath" exception as provided by apidesign.org
    5.19 +    in the License file that accompanied this code.
    5.20 +
    5.21 +    You should have received a copy of the GNU General Public License
    5.22 +    along with this program. Look for COPYING file in the top folder.
    5.23 +    If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    5.24 +
    5.25 +-->
    5.26 +<!DOCTYPE html>
    5.27 +<html>
    5.28 +    <head>
    5.29 +        <title>Knockout.fx Execution Harness</title>
    5.30 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    5.31 +        <meta name="viewport" content="width=device-width">
    5.32 +    </head>
    5.33 +    <body>
    5.34 +        <h1>Knockout.fx Execution Harness</h1>
    5.35 +    </body>
    5.36 +</html>