2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
6 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7 * Other names may be trademarks of their respective owners.
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]"
29 * The Original Software is NetBeans. The Initial Developer of the Original
30 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
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.
43 package net.java.html.json.tests;
45 import java.io.ByteArrayInputStream;
46 import java.io.ByteArrayOutputStream;
47 import java.io.PrintStream;
48 import net.java.html.BrwsrCtx;
49 import net.java.html.json.Model;
50 import net.java.html.json.ModelOperation;
51 import net.java.html.json.Models;
52 import net.java.html.json.OnReceive;
53 import net.java.html.json.Property;
54 import org.apidesign.html.json.tck.KOTest;
56 /** Need to verify that models produce reasonable JSON objects.
58 * @author Jaroslav Tulach <jtulach@netbeans.org>
60 @Model(className = "JSONik", properties = {
61 @Property(name = "fetched", type = Person.class),
62 @Property(name = "fetchedCount", type = int.class),
63 @Property(name = "fetchedResponse", type = String.class),
64 @Property(name = "fetchedSex", type = Sex.class, array = true)
66 public final class JSONTest {
71 @ModelOperation static void assignFetched(JSONik m, Person p) {
75 @KOTest public void toJSONInABrowser() throws Throwable {
76 Person p = Models.bind(new Person(), newContext());
78 p.setFirstName("Jarda");
79 p.setLastName("Tulach");
83 json = parseJSON(p.toString());
84 } catch (Throwable ex) {
85 throw new IllegalStateException("Can't parse " + p).initCause(ex);
88 Person p2 = Models.fromRaw(newContext(), Person.class, json);
90 assert p2.getFirstName().equals(p.getFirstName()) :
91 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
94 @KOTest public void toJSONWithEscapeCharactersInABrowser() throws Throwable {
95 Person p = Models.bind(new Person(), newContext());
97 p.setFirstName("/*\n * Copyright (c) 2013");
100 final String txt = p.toString();
103 json = parseJSON(txt);
104 } catch (Throwable ex) {
105 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
108 Person p2 = Models.fromRaw(newContext(), Person.class, json);
110 assert p2.getFirstName().equals(p.getFirstName()) :
111 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
114 @KOTest public void toJSONWithDoubleSlashInABrowser() throws Throwable {
115 Person p = Models.bind(new Person(), newContext());
117 p.setFirstName("/*\\n * Copyright (c) 2013");
120 final String txt = p.toString();
123 json = parseJSON(txt);
124 } catch (Throwable ex) {
125 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
128 Person p2 = Models.fromRaw(newContext(), Person.class, json);
130 assert p2.getFirstName().equals(p.getFirstName()) :
131 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
134 @KOTest public void toJSONWithApostrophInABrowser() throws Throwable {
135 Person p = Models.bind(new Person(), newContext());
137 p.setFirstName("Jimmy 'Jim' Rambo");
140 final String txt = p.toString();
143 json = parseJSON(txt);
144 } catch (Throwable ex) {
145 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
148 Person p2 = Models.fromRaw(newContext(), Person.class, json);
150 assert p2.getFirstName().equals(p.getFirstName()) :
151 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
154 @OnReceive(url="{url}")
155 static void fetch(Person p, JSONik model) {
159 @OnReceive(url="{url}", onError = "setMessage")
160 static void fetchArray(Person[] p, JSONik model) {
161 model.setFetchedCount(p.length);
162 model.setFetched(p[0]);
165 static void setMessage(JSONik m, Exception t) {
167 m.setFetchedResponse("Exception");
170 @OnReceive(url="{url}")
171 static void fetchPeople(People p, JSONik model) {
172 final int size = p.getInfo().size();
174 model.setFetched(p.getInfo().get(0));
176 model.setFetchedCount(size);
179 @OnReceive(url="{url}")
180 static void fetchPeopleAge(People p, JSONik model) {
182 for (int a : p.getAge()) {
185 model.setFetchedCount(sum);
188 @KOTest public void loadAndParseJSON() throws InterruptedException {
190 url = Utils.prepareURL(
191 JSONTest.class, "{'firstName': 'Sitar', 'sex': 'MALE'}",
194 js = Models.bind(new JSONik(), newContext());
201 Person p = js.getFetched();
203 throw new InterruptedException();
206 assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
207 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
210 @OnReceive(url="{url}?callme={me}", jsonp = "me")
211 static void fetchViaJSONP(Person p, JSONik model) {
215 @KOTest public void loadAndParseJSONP() throws InterruptedException, Exception {
217 url = Utils.prepareURL(
218 JSONTest.class, "$0({'firstName': 'Mitar', 'sex': 'MALE'})",
219 "application/javascript",
222 orig = scriptElements();
223 assert orig > 0 : "There should be some scripts on the page";
225 js = Models.bind(new JSONik(), newContext());
229 js.fetchViaJSONP(url);
232 Person p = js.getFetched();
234 throw new InterruptedException();
237 assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
238 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
240 int now = scriptElements();
242 assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
247 @OnReceive(url="{url}", method = "PUT", data = Person.class)
248 static void putPerson(JSONik model, String reply) {
249 model.setFetchedCount(1);
250 model.setFetchedResponse(reply);
253 @KOTest public void putPeopleUsesRightMethod() throws InterruptedException, Exception {
255 url = Utils.prepareURL(
256 JSONTest.class, "$0\n$1",
258 "http.method", "http.requestBody"
260 orig = scriptElements();
261 assert orig > 0 : "There should be some scripts on the page";
263 js = Models.bind(new JSONik(), newContext());
266 Person p = Models.bind(new Person(), BrwsrCtx.EMPTY);
267 p.setFirstName("Jarda");
268 js.putPerson(url, p);
271 int cnt = js.getFetchedCount();
273 throw new InterruptedException();
275 String res = js.getFetchedResponse();
276 int line = res.indexOf('\n');
279 msg = res.substring(line + 1);
280 res = res.substring(0, line);
285 assert "PUT".equals(res) : "Server was queried with PUT method: " + js.getFetchedResponse();
287 assert msg.contains("Jarda") : "Data transferred to the server: " + msg;
290 private static int scriptElements() throws Exception {
291 return ((Number)Utils.executeScript(
293 "return window.document.getElementsByTagName('script').length;")).intValue();
296 private static Object parseJSON(String s) throws Exception {
297 return Utils.executeScript(
299 "return window.JSON.parse(arguments[0]);", s);
302 @KOTest public void loadAndParseJSONSentToArray() throws InterruptedException {
304 url = Utils.prepareURL(
305 JSONTest.class, "{'firstName': 'Sitar', 'sex': 'MALE'}",
309 js = Models.bind(new JSONik(), newContext());
316 Person p = js.getFetched();
318 throw new InterruptedException();
321 assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
322 assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
325 @KOTest public void loadAndParseJSONArraySingle() throws InterruptedException {
327 url = Utils.prepareURL(
328 JSONTest.class, "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]",
331 js = Models.bind(new JSONik(), newContext());
338 Person p = js.getFetched();
340 throw new InterruptedException();
343 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
344 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
347 @KOTest public void loadAndParseArrayInPeople() throws InterruptedException {
349 url = Utils.prepareURL(
350 JSONTest.class, "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}",
353 js = Models.bind(new JSONik(), newContext());
359 if (0 == js.getFetchedCount()) {
360 throw new InterruptedException();
363 assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
365 Person p = js.getFetched();
367 assert p != null : "We should get our person back: " + p;
368 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
369 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
372 @KOTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
374 url = Utils.prepareURL(
375 JSONTest.class, "{'age':[1, 2, 3]}",
378 js = Models.bind(new JSONik(), newContext());
381 js.fetchPeopleAge(url);
384 if (0 == js.getFetchedCount()) {
385 throw new InterruptedException();
388 assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
391 @OnReceive(url="{url}")
392 static void fetchPeopleSex(People p, JSONik model) {
393 model.setFetchedCount(1);
394 model.getFetchedSex().addAll(p.getSex());
397 @KOTest public void loadAndParseArrayOfEnums() throws InterruptedException {
399 url = Utils.prepareURL(
400 JSONTest.class, "{'sex':['FEMALE', 'MALE', 'MALE']}",
403 js = Models.bind(new JSONik(), newContext());
406 js.fetchPeopleSex(url);
409 if (0 == js.getFetchedCount()) {
410 throw new InterruptedException();
413 assert js.getFetchedCount() == 1 : "Loaded";
415 assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
416 assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
417 assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
418 assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
421 @KOTest public void loadAndParseJSONArray() throws InterruptedException {
423 url = Utils.prepareURL(
424 JSONTest.class, "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
425 + "{'firstName': 'Peter', 'sex': 'MALE'}"
429 js = Models.bind(new JSONik(), newContext());
437 Person p = js.getFetched();
439 throw new InterruptedException();
442 assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
443 assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
444 assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
447 @KOTest public void loadError() throws InterruptedException {
449 js = Models.bind(new JSONik(), newContext());
453 js.fetchArray("http://127.0.0.1:54253/does/not/exist.txt");
457 if (js.getFetchedResponse() == null) {
458 throw new InterruptedException();
461 assert "Exception".equals(js.getFetchedResponse()) : js.getFetchedResponse();
464 @Model(className = "NameAndValue", properties = {
465 @Property(name = "name", type = String.class),
466 @Property(name = "value", type = long.class),
467 @Property(name = "small", type = byte.class)
472 @KOTest public void parseNullNumber() throws Exception {
473 String txt = "{ \"name\":\"M\" }";
474 ByteArrayInputStream is = new ByteArrayInputStream(txt.getBytes("UTF-8"));
475 NameAndValue v = Models.parse(newContext(), NameAndValue.class, is);
476 assert "M".equals(v.getName()) : "Name is 'M': " + v.getName();
477 assert 0 == v.getValue() : "Value is empty: " + v.getValue();
478 assert 0 == v.getSmall() : "Small value is empty: " + v.getSmall();
481 @KOTest public void deserializeWrongEnum() throws Exception {
482 PrintStream prev = null;
483 ByteArrayOutputStream err = new ByteArrayOutputStream();
486 System.setErr(new PrintStream(err));
487 } catch (SecurityException e) {
490 } catch (LinkageError e) {
495 String str = "{ \"sex\" : \"unknown\" }";
496 ByteArrayInputStream is = new ByteArrayInputStream(str.getBytes("UTF-8"));
497 Person p = Models.parse(newContext(), Person.class, is);
498 assert p.getSex() == null : "Wrong sex means null, but was: " + p.getSex();
501 assert err.toString().contains("unknown") && err.toString().contains("Sex"): "Expecting error: " + err.toString();
506 } catch (LinkageError e) {
513 private static BrwsrCtx newContext() {
514 return Utils.newContext(JSONTest.class);