boot-script/src/test/java/net/java/html/boot/script/ko4j/KnockoutEnvJSTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 26 Aug 2014 18:13:30 +0200
changeset 838 bdc3d696dd4a
parent 827 410ac5c0f39a
child 866 3499df087dc3
permissions -rw-r--r--
During the API review process (bug 246133) the reviewers decided that in order to include html4j to NetBeans Platform, we need to stop using org.apidesign namespace and switch to NetBeans one. Repackaging all SPI packages into org.netbeans.html.smthng.spi.
     1 /**
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     5  *
     6  * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
     7  * Other names may be trademarks of their respective owners.
     8  *
     9  * The contents of this file are subject to the terms of either the GNU
    10  * General Public License Version 2 only ("GPL") or the Common
    11  * Development and Distribution License("CDDL") (collectively, the
    12  * "License"). You may not use this file except in compliance with the
    13  * License. You can obtain a copy of the License at
    14  * http://www.netbeans.org/cddl-gplv2.html
    15  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    16  * specific language governing permissions and limitations under the
    17  * License.  When distributing the software, include this License Header
    18  * Notice in each file and include the License file at
    19  * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    20  * particular file as subject to the "Classpath" exception as provided
    21  * by Oracle in the GPL Version 2 section of the License file that
    22  * accompanied this code. If applicable, add the following below the
    23  * License Header, with the fields enclosed by brackets [] replaced by
    24  * your own identifying information:
    25  * "Portions Copyrighted [year] [name of copyright owner]"
    26  *
    27  * Contributor(s):
    28  *
    29  * The Original Software is NetBeans. The Initial Developer of the Original
    30  * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    31  *
    32  * If you wish your version of this file to be governed by only the CDDL
    33  * or only the GPL Version 2, indicate your decision by adding
    34  * "[Contributor] elects to include this software in this distribution
    35  * under the [CDDL or GPL Version 2] license." If you do not indicate a
    36  * single choice of license, a recipient has the option to distribute
    37  * your version of this file under either the CDDL, the GPL Version 2 or
    38  * to extend the choice of license to its licensees as provided above.
    39  * However, if you add GPL Version 2 code and therefore, elected the GPL
    40  * Version 2 license, then the option applies only if the new code is
    41  * made subject to such option by the copyright holder.
    42  */
    43 package net.java.html.boot.script.ko4j;
    44 
    45 import java.io.BufferedReader;
    46 import java.io.IOException;
    47 import java.io.InputStream;
    48 import java.io.InputStreamReader;
    49 import java.lang.annotation.Annotation;
    50 import java.lang.reflect.Method;
    51 import java.net.URI;
    52 import java.net.URISyntaxException;
    53 import java.net.URL;
    54 import java.net.URLConnection;
    55 import java.util.ArrayList;
    56 import java.util.List;
    57 import java.util.Map;
    58 import java.util.concurrent.Executor;
    59 import java.util.concurrent.Executors;
    60 import net.java.html.BrwsrCtx;
    61 import net.java.html.boot.BrowserBuilder;
    62 import net.java.html.boot.script.Scripts;
    63 import net.java.html.js.JavaScriptBody;
    64 import org.netbeans.html.boot.spi.Fn;
    65 import org.netbeans.html.context.spi.Contexts;
    66 import org.netbeans.html.json.spi.Technology;
    67 import org.netbeans.html.json.spi.Transfer;
    68 import org.netbeans.html.json.tck.KOTest;
    69 import org.netbeans.html.json.tck.KnockoutTCK;
    70 import org.netbeans.html.ko4j.KO4J;
    71 import org.netbeans.html.wstyrus.TyrusContext;
    72 import org.openide.util.lookup.ServiceProvider;
    73 import org.testng.Assert;
    74 import static org.testng.Assert.*;
    75 import org.testng.annotations.Factory;
    76 
    77 /**
    78  *
    79  * @author Jaroslav Tulach
    80  */
    81 @ServiceProvider(service = KnockoutTCK.class)
    82 public final class KnockoutEnvJSTest extends KnockoutTCK {
    83     private static Class<?> browserClass;
    84     private static Fn.Presenter browserContext;
    85     private static URI baseUri;
    86     
    87     public KnockoutEnvJSTest() {
    88     }
    89     
    90     @Factory public static Object[] compatibilityTests() throws Exception {
    91         try {
    92             Class.forName("java.lang.FunctionalInterface");
    93         } catch (ClassNotFoundException ex) {
    94             // only runs on JDK8
    95             return new Object[0];
    96         }
    97         
    98         
    99         Class[] arr = testClasses();
   100         for (int i = 0; i < arr.length; i++) {
   101             assertEquals(
   102                 arr[i].getClassLoader(),
   103                 KnockoutEnvJSTest.class.getClassLoader(),
   104                 "All classes loaded by the same classloader"
   105             );
   106         }
   107         
   108         baseUri = DynamicHTTP.initServer();
   109         
   110         final Fn.Presenter p = Scripts.createPresenter(KOCase.JS);
   111         InputStream is = KnockoutEnvJSTest.class.getResourceAsStream("env.nashorn.1.2-debug.js");
   112         p.loadScript(new InputStreamReader(is));
   113         is.close();
   114 
   115         final BrowserBuilder bb = BrowserBuilder.newBrowser(p).
   116             loadClass(KnockoutEnvJSTest.class).
   117             loadPage(baseUri.toString()).
   118             invoke("initialized");
   119         
   120         Executors.newSingleThreadExecutor().submit(new Runnable() {
   121             @Override
   122             public void run() {
   123                 bb.showAndWait();
   124             }
   125         });
   126         
   127         ClassLoader l = getClassLoader();
   128         List<Object> res = new ArrayList<Object>();
   129         for (int i = 0; i < arr.length; i++) {
   130             Class<?> c = Class.forName(arr[i].getName(), true, l);
   131             seekKOTests(c, res);
   132         }
   133         return res.toArray();
   134     }
   135 
   136     private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
   137         Class<? extends Annotation> koTest =
   138             c.getClassLoader().loadClass(KOTest.class.getName()).
   139             asSubclass(Annotation.class);
   140         for (Method m : c.getMethods()) {
   141             if (m.getAnnotation(koTest) != null) {
   142                 res.add(new KOCase(browserContext, m, skipMsg(m.getName())));
   143             }
   144         }
   145     }
   146     
   147     private static String skipMsg(String methodName) {
   148         final String ver = System.getProperty("java.runtime.version"); // NOI18N
   149         if (
   150             !"1.8.0_05-b13".equals(ver) &&
   151             !"1.8.0_11-b12".equals(ver) 
   152         ) {
   153             // we know that 1.8.0_05 and 1.8.0_11 are broken, 
   154             // let's not speculate about anything else
   155             return null;
   156         }
   157         switch (methodName) {
   158             case "paintTheGridOnClick":
   159             case "displayContentOfArrayOfPeople":
   160             case "connectUsingWebSocket":
   161             case "selectWorksOnModels":
   162             case "archetypeArrayModificationVisible":
   163                 return "Does not work on JDK8, due to JDK-8046013";
   164         }
   165         return null;
   166     }
   167 
   168     static synchronized ClassLoader getClassLoader() throws InterruptedException {
   169         while (browserClass == null) {
   170             KnockoutEnvJSTest.class.wait();
   171         }
   172         return browserClass.getClassLoader();
   173     }
   174     
   175     public static synchronized void initialized(Class<?> browserCls) throws Exception {
   176         browserClass = browserCls;
   177         browserContext = Fn.activePresenter();
   178         KnockoutEnvJSTest.class.notifyAll();
   179     }
   180     
   181     public static void initialized() throws Exception {
   182         Assert.assertSame(
   183             KnockoutEnvJSTest.class.getClassLoader(),
   184             ClassLoader.getSystemClassLoader(),
   185             "No special classloaders"
   186         );
   187         KnockoutEnvJSTest.initialized(KnockoutEnvJSTest.class);
   188         browserContext = Fn.activePresenter();
   189     }
   190     
   191     @Override
   192     public BrwsrCtx createContext() {
   193         KO4J fx = new KO4J(browserContext);
   194         TyrusContext tc = new TyrusContext();
   195         Contexts.Builder cb = Contexts.newBuilder().
   196             register(Technology.class, fx.knockout(), 10).
   197             register(Transfer.class, tc, 10);
   198         cb.register(Fn.Presenter.class, browserContext, 10);
   199         cb.register(Executor.class, (Executor)browserContext, 10);
   200         BrwsrCtx ctx = cb.build();
   201         return ctx;
   202     }
   203 
   204     @Override
   205     public Object createJSON(Map<String, Object> values) {
   206         Object json = createJSON();
   207         for (Map.Entry<String, Object> entry : values.entrySet()) {
   208             setProperty(json, entry.getKey(), entry.getValue());
   209         }
   210         return json;
   211     }
   212     
   213     @JavaScriptBody(args = {}, body = "return new Object();")
   214     private static native Object createJSON();
   215     @JavaScriptBody(args = { "json", "key", "value" }, body = "json[key] = value;")
   216     private static native void setProperty(Object json, String key, Object value);
   217 
   218     @Override
   219     @JavaScriptBody(args = { "s", "args" }, body = "\n"
   220         + "var f = new Function(s);\n"
   221         + "return f.apply(null, args);\n"
   222     )
   223     public native Object executeScript(String script, Object[] arguments);
   224 
   225     private static String findBaseURL() {
   226         return baseUri.toString();
   227     }
   228     
   229     @Override
   230     public URI prepareURL(String content, String mimeType, String[] parameters) {
   231         try {
   232             final URL baseURL = new URL(findBaseURL());
   233             StringBuilder sb = new StringBuilder();
   234             sb.append("/dynamic?mimeType=").append(mimeType);
   235             for (int i = 0; i < parameters.length; i++) {
   236                 sb.append("&param" + i).append("=").append(parameters[i]);
   237             }
   238             String mangle = content.replace("\n", "%0a")
   239                 .replace("\"", "\\\"").replace(" ", "%20");
   240             sb.append("&content=").append(mangle);
   241 
   242             URL query = new URL(baseURL, sb.toString());
   243             URLConnection c = query.openConnection();
   244             BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
   245             URI connectTo = new URI(br.readLine());
   246             return connectTo;
   247         } catch (IOException ex) {
   248             throw new IllegalStateException(ex);
   249         } catch (URISyntaxException ex) {
   250             throw new IllegalStateException(ex);
   251         }
   252     }
   253 
   254     @Override
   255     public boolean canFailWebSocketTest() {
   256         return true;
   257     }
   258 }