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