json-tck/src/main/java/net/java/html/json/tests/JSONTest.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 16 Dec 2013 16:59:43 +0100
branchnetbeans
changeset 362 92fb71afdc0e
parent 358 80702021b851
child 365 5c93ad8c7a15
permissions -rw-r--r--
Moving implementation classes into org.netbeans.html namespace
     1 /**
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 1997-2010 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-2013 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.json.tests;
    44 
    45 import java.io.ByteArrayInputStream;
    46 import net.java.html.BrwsrCtx;
    47 import net.java.html.json.Model;
    48 import net.java.html.json.ModelOperation;
    49 import net.java.html.json.Models;
    50 import net.java.html.json.OnReceive;
    51 import net.java.html.json.Property;
    52 import org.netbeans.html.json.impl.JSON;
    53 import org.apidesign.html.json.tck.KOTest;
    54 
    55 /** Need to verify that models produce reasonable JSON objects.
    56  *
    57  * @author Jaroslav Tulach <jtulach@netbeans.org>
    58  */
    59 @Model(className = "JSONik", properties = {
    60     @Property(name = "fetched", type = Person.class),
    61     @Property(name = "fetchedCount", type = int.class),
    62     @Property(name = "fetchedResponse", type = String.class),
    63     @Property(name = "fetchedSex", type = Sex.class, array = true)
    64 })
    65 public final class JSONTest {
    66     private JSONik js;
    67     private Integer orig;
    68     private String url;
    69     
    70     @ModelOperation static void assignFetched(JSONik m, Person p) {
    71         m.setFetched(p);
    72     }
    73     
    74     @KOTest public void toJSONInABrowser() throws Throwable {
    75         Person p = Models.bind(new Person(), newContext());
    76         p.setSex(Sex.MALE);
    77         p.setFirstName("Jarda");
    78         p.setLastName("Tulach");
    79 
    80         Object json;
    81         try {
    82             json = parseJSON(p.toString());
    83         } catch (Throwable ex) {
    84             throw new IllegalStateException("Can't parse " + p).initCause(ex);
    85         }
    86         
    87         Person p2 = JSON.read(newContext(), Person.class, json);
    88         
    89         assert p2.getFirstName().equals(p.getFirstName()) : 
    90             "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
    91     }
    92     
    93     @KOTest public void toJSONWithEscapeCharactersInABrowser() throws Throwable {
    94         Person p = Models.bind(new Person(), newContext());
    95         p.setSex(Sex.MALE);
    96         p.setFirstName("/*\n * Copyright (c) 2013");
    97 
    98         
    99         final String txt = p.toString();
   100         Object json;
   101         try {
   102             json = parseJSON(txt);
   103         } catch (Throwable ex) {
   104             throw new IllegalStateException("Can't parse " + txt).initCause(ex);
   105         }
   106         
   107         Person p2 = JSON.read(newContext(), Person.class, json);
   108         
   109         assert p2.getFirstName().equals(p.getFirstName()) : 
   110             "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
   111     }
   112     
   113     @KOTest public void toJSONWithDoubleSlashInABrowser() throws Throwable {
   114         Person p = Models.bind(new Person(), newContext());
   115         p.setSex(Sex.MALE);
   116         p.setFirstName("/*\\n * Copyright (c) 2013");
   117 
   118         
   119         final String txt = p.toString();
   120         Object json;
   121         try {
   122             json = parseJSON(txt);
   123         } catch (Throwable ex) {
   124             throw new IllegalStateException("Can't parse " + txt).initCause(ex);
   125         }
   126         
   127         Person p2 = JSON.read(newContext(), Person.class, json);
   128         
   129         assert p2.getFirstName().equals(p.getFirstName()) : 
   130             "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
   131     }
   132     
   133     @KOTest public void toJSONWithApostrophInABrowser() throws Throwable {
   134         Person p = Models.bind(new Person(), newContext());
   135         p.setSex(Sex.MALE);
   136         p.setFirstName("Jimmy 'Jim' Rambo");
   137 
   138         
   139         final String txt = p.toString();
   140         Object json;
   141         try {
   142             json = parseJSON(txt);
   143         } catch (Throwable ex) {
   144             throw new IllegalStateException("Can't parse " + txt).initCause(ex);
   145         }
   146         
   147         Person p2 = JSON.read(newContext(), Person.class, json);
   148         
   149         assert p2.getFirstName().equals(p.getFirstName()) : 
   150             "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
   151     }
   152     
   153     @OnReceive(url="{url}")
   154     static void fetch(Person p, JSONik model) {
   155         model.setFetched(p);
   156     }
   157 
   158     @OnReceive(url="{url}", onError = "setMessage")
   159     static void fetchArray(Person[] p, JSONik model) {
   160         model.setFetchedCount(p.length);
   161         model.setFetched(p[0]);
   162     }
   163     
   164     static void setMessage(JSONik m, Exception t) {
   165         assert t != null;
   166         m.setFetchedResponse("Exception");
   167     }
   168     
   169     @OnReceive(url="{url}")
   170     static void fetchPeople(People p, JSONik model) {
   171         model.setFetchedCount(p.getInfo().size());
   172         model.setFetched(p.getInfo().get(0));
   173     }
   174 
   175     @OnReceive(url="{url}")
   176     static void fetchPeopleAge(People p, JSONik model) {
   177         int sum = 0;
   178         for (int a : p.getAge()) {
   179             sum += a;
   180         }
   181         model.setFetchedCount(sum);
   182     }
   183     
   184     @KOTest public void loadAndParseJSON() throws InterruptedException {
   185         if (js == null) {
   186             url = Utils.prepareURL(
   187                 JSONTest.class, "{'firstName': 'Sitar', 'sex': 'MALE'}",
   188                 "application/json"
   189             );
   190             js = Models.bind(new JSONik(), newContext());
   191             js.applyBindings();
   192 
   193             js.setFetched(null);
   194             js.fetch(url);
   195         }
   196     
   197         Person p = js.getFetched();
   198         if (p == null) {
   199             throw new InterruptedException();
   200         }
   201         
   202         assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
   203         assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
   204     }
   205     
   206     @OnReceive(url="{url}?callme={me}", jsonp = "me")
   207     static void fetchViaJSONP(Person p, JSONik model) {
   208         model.setFetched(p);
   209     }
   210     
   211     @KOTest public void loadAndParseJSONP() throws InterruptedException, Exception {
   212         if (js == null) {
   213             url = Utils.prepareURL(
   214                 JSONTest.class, "$0({'firstName': 'Mitar', 'sex': 'MALE'})", 
   215                 "application/javascript",
   216                 "callme"
   217             );
   218             orig = scriptElements();
   219             assert orig > 0 : "There should be some scripts on the page";
   220             
   221             js = Models.bind(new JSONik(), newContext());
   222             js.applyBindings();
   223 
   224             js.setFetched(null);
   225             js.fetchViaJSONP(url);
   226         }
   227     
   228         Person p = js.getFetched();
   229         if (p == null) {
   230             throw new InterruptedException();
   231         }
   232         
   233         assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
   234         assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
   235         
   236         int now = scriptElements();
   237         
   238         assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
   239     }
   240     
   241     
   242     
   243     @OnReceive(url="{url}", method = "PUT", data = Person.class)
   244     static void putPerson(JSONik model, String reply) {
   245         model.setFetchedCount(1);
   246         model.setFetchedResponse(reply);
   247     }
   248 
   249     @KOTest public void putPeopleUsesRightMethod() throws InterruptedException, Exception {
   250         if (js == null) {
   251             url = Utils.prepareURL(
   252                 JSONTest.class, "$0\n$1", 
   253                 "text/plain",
   254                 "http.method", "http.requestBody"
   255             );
   256             orig = scriptElements();
   257             assert orig > 0 : "There should be some scripts on the page";
   258             
   259             js = Models.bind(new JSONik(), newContext());
   260             js.applyBindings();
   261 
   262             Person p = Models.bind(new Person(), BrwsrCtx.EMPTY);
   263             p.setFirstName("Jarda");
   264             js.putPerson(url, p);
   265         }
   266     
   267         int cnt = js.getFetchedCount();
   268         if (cnt == 0) {
   269             throw new InterruptedException();
   270         }
   271         String res = js.getFetchedResponse();
   272         int line = res.indexOf('\n');
   273         String msg;
   274         if (line >= 0) {
   275             msg = res.substring(line + 1);
   276             res = res.substring(0, line);
   277         } else {
   278             msg = res;
   279         }
   280         
   281         assert "PUT".equals(res) : "Server was queried with PUT method: " + js.getFetchedResponse();
   282         
   283         assert msg.contains("Jarda") : "Data transferred to the server: " + msg;
   284     }
   285     
   286     private static int scriptElements() throws Exception {
   287         return ((Number)Utils.executeScript(
   288             JSONTest.class, 
   289             "return window.document.getElementsByTagName('script').length;")).intValue();
   290     }
   291 
   292     private static Object parseJSON(String s) throws Exception {
   293         return Utils.executeScript(
   294             JSONTest.class, 
   295             "return window.JSON.parse(arguments[0]);", s);
   296     }
   297     
   298     @KOTest public void loadAndParseJSONSentToArray() throws InterruptedException {
   299         if (js == null) {
   300             url = Utils.prepareURL(
   301                 JSONTest.class, "{'firstName': 'Sitar', 'sex': 'MALE'}", 
   302                 "application/json"
   303             );
   304             
   305             js = Models.bind(new JSONik(), newContext());
   306             js.applyBindings();
   307 
   308             js.setFetched(null);
   309             js.fetchArray(url);
   310         }
   311         
   312         Person p = js.getFetched();
   313         if (p == null) {
   314             throw new InterruptedException();
   315         }
   316         
   317         assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
   318         assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
   319     }
   320     
   321     @KOTest public void loadAndParseJSONArraySingle() throws InterruptedException {
   322         if (js == null) {
   323             url = Utils.prepareURL(
   324                 JSONTest.class, "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]", 
   325                 "application/json"
   326             );
   327             js = Models.bind(new JSONik(), newContext());
   328             js.applyBindings();
   329         
   330             js.setFetched(null);
   331             js.fetch(url);
   332         }
   333         
   334         Person p = js.getFetched();
   335         if (p == null) {
   336             throw new InterruptedException();
   337         }
   338         
   339         assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
   340         assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
   341     }
   342     
   343     @KOTest public void loadAndParseArrayInPeople() throws InterruptedException {
   344         if (js == null) {
   345             url = Utils.prepareURL(
   346                 JSONTest.class, "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}", 
   347                 "application/json"
   348             );
   349             js = Models.bind(new JSONik(), newContext());
   350             js.applyBindings();
   351         
   352             js.fetchPeople(url);
   353         }
   354         
   355         if (0 == js.getFetchedCount()) {
   356             throw new InterruptedException();
   357         }
   358 
   359         assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
   360         
   361         Person p = js.getFetched();
   362         
   363         assert p != null : "We should get our person back: " + p;
   364         assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
   365         assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
   366     }
   367     
   368     @KOTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
   369         if (js == null) {
   370             url = Utils.prepareURL(
   371                 JSONTest.class, "{'age':[1, 2, 3]}", 
   372                 "application/json"
   373             );
   374             js = Models.bind(new JSONik(), newContext());
   375             js.applyBindings();
   376         
   377             js.fetchPeopleAge(url);
   378         }
   379         
   380         if (0 == js.getFetchedCount()) {
   381             throw new InterruptedException();
   382         }
   383 
   384         assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
   385     }
   386     
   387     @OnReceive(url="{url}")
   388     static void fetchPeopleSex(People p, JSONik model) {
   389         model.setFetchedCount(1);
   390         model.getFetchedSex().addAll(p.getSex());
   391     }
   392     
   393     @KOTest public void loadAndParseArrayOfEnums() throws InterruptedException {
   394         if (js == null) {
   395             url = Utils.prepareURL(
   396                 JSONTest.class, "{'sex':['FEMALE', 'MALE', 'MALE']}", 
   397                 "application/json"
   398             );
   399             js = Models.bind(new JSONik(), newContext());
   400             js.applyBindings();
   401         
   402             js.fetchPeopleSex(url);
   403         }
   404         
   405         if (0 == js.getFetchedCount()) {
   406             throw new InterruptedException();
   407         }
   408 
   409         assert js.getFetchedCount() == 1 : "Loaded";
   410         
   411         assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
   412         assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
   413         assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
   414         assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
   415     }
   416     
   417     @KOTest public void loadAndParseJSONArray() throws InterruptedException {
   418         if (js == null) {
   419             url = Utils.prepareURL(
   420                 JSONTest.class, "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
   421                 + "{'firstName': 'Peter', 'sex': 'MALE'}"
   422                 + "]", 
   423                 "application/json"
   424             );
   425             js = Models.bind(new JSONik(), newContext());
   426             js.applyBindings();
   427             js.setFetched(null);
   428             
   429             js.fetchArray(url);
   430         }
   431         
   432         
   433         Person p = js.getFetched();
   434         if (p == null) {
   435             throw new InterruptedException();
   436         }
   437         
   438         assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
   439         assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
   440         assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
   441     }
   442     
   443     @KOTest public void loadError() throws InterruptedException {
   444         if (js == null) {
   445             js = Models.bind(new JSONik(), newContext());
   446             js.applyBindings();
   447             js.setFetched(null);
   448             
   449             js.fetchArray("http://127.0.0.1:54253/does/not/exist.txt");
   450         }
   451         
   452         
   453         if (js.getFetchedResponse() == null) {
   454             throw new InterruptedException();
   455         }
   456 
   457         assert "Exception".equals(js.getFetchedResponse()) : js.getFetchedResponse();
   458     }
   459     
   460     @Model(className = "NameAndValue", properties = {
   461         @Property(name = "name", type = String.class),
   462         @Property(name = "value", type = long.class),
   463         @Property(name = "small", type = byte.class)
   464     })
   465     static class NandV {
   466     }
   467     
   468     @KOTest public void parseNullNumber() throws Exception {
   469         String txt = "{ \"name\":\"M\" }";
   470         ByteArrayInputStream is = new ByteArrayInputStream(txt.getBytes("UTF-8"));
   471         NameAndValue v = Models.parse(newContext(), NameAndValue.class, is);
   472         assert "M".equals(v.getName()) : "Name is 'M': " + v.getName();
   473         assert 0 == v.getValue() : "Value is empty: " + v.getValue();
   474         assert 0 == v.getSmall() : "Small value is empty: " + v.getSmall();
   475     }
   476 
   477     @KOTest public void deserializeWrongEnum() throws Exception {
   478         String str = "{ \"sex\" : \"unknown\" }";
   479         ByteArrayInputStream is = new ByteArrayInputStream(str.getBytes("UTF-8"));
   480         Person p = Models.parse(newContext(), Person.class, is);
   481         assert p.getSex() == null : "Wrong sex means null, but was: " + p.getSex();
   482     }
   483 
   484     
   485     private static BrwsrCtx newContext() {
   486         return Utils.newContext(JSONTest.class);
   487     }
   488     
   489 }