jaroslav@919: /** jaroslav@919: * Back 2 Browser Bytecode Translator jaroslav@919: * Copyright (C) 2012 Jaroslav Tulach jaroslav@919: * jaroslav@919: * This program is free software: you can redistribute it and/or modify jaroslav@919: * it under the terms of the GNU General Public License as published by jaroslav@919: * the Free Software Foundation, version 2 of the License. jaroslav@919: * jaroslav@919: * This program is distributed in the hope that it will be useful, jaroslav@919: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@919: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@919: * GNU General Public License for more details. jaroslav@919: * jaroslav@919: * You should have received a copy of the GNU General Public License jaroslav@919: * along with this program. Look for COPYING file in the top folder. jaroslav@919: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@919: */ jaroslav@919: package org.apidesign.bck2brwsr.htmlpage; jaroslav@919: jaroslav@963: import java.util.Arrays; jaroslav@919: import java.util.Iterator; jaroslav@963: import org.apidesign.bck2brwsr.core.JavaScriptBody; jaroslav@934: import org.apidesign.bck2brwsr.htmlpage.api.OnReceive; jaroslav@934: import org.apidesign.bck2brwsr.htmlpage.api.Page; jaroslav@934: import org.apidesign.bck2brwsr.htmlpage.api.Property; jaroslav@934: import org.apidesign.bck2brwsr.vmtest.BrwsrTest; jaroslav@934: import org.apidesign.bck2brwsr.vmtest.Http; jaroslav@934: import org.apidesign.bck2brwsr.vmtest.VMTest; jaroslav@919: import org.json.JSONException; jaroslav@919: import org.json.JSONObject; jaroslav@919: import org.json.JSONTokener; jaroslav@919: import org.testng.annotations.Test; jaroslav@919: import static org.testng.Assert.*; jaroslav@934: import org.testng.annotations.Factory; jaroslav@919: jaroslav@919: /** Need to verify that models produce reasonable JSON objects. jaroslav@919: * jaroslav@919: * @author Jaroslav Tulach jaroslav@919: */ jaroslav@934: @Page(xhtml = "Empty.html", className = "JSONik", properties = { jaroslav@936: @Property(name = "fetched", type = PersonImpl.class), jaroslav@960: @Property(name = "fetchedCount", type = int.class), jaroslav@960: @Property(name = "fetchedSex", type = Sex.class, array = true) jaroslav@934: }) jaroslav@919: public class JSONTest { jaroslav@941: private JSONik js; jaroslav@963: private Integer orig; jaroslav@919: jaroslav@919: @Test public void personToString() throws JSONException { jaroslav@919: Person p = new Person(); jaroslav@919: p.setSex(Sex.MALE); jaroslav@919: p.setFirstName("Jarda"); jaroslav@919: p.setLastName("Tulach"); jaroslav@919: jaroslav@919: JSONTokener t = new JSONTokener(p.toString()); jaroslav@919: JSONObject o; jaroslav@919: try { jaroslav@919: o = new JSONObject(t); jaroslav@919: } catch (JSONException ex) { jaroslav@919: throw new AssertionError("Can't parse " + p.toString(), ex); jaroslav@919: } jaroslav@919: jaroslav@919: Iterator it = o.sortedKeys(); jaroslav@919: assertEquals(it.next(), "firstName"); jaroslav@919: assertEquals(it.next(), "lastName"); jaroslav@919: assertEquals(it.next(), "sex"); jaroslav@919: jaroslav@919: assertEquals(o.getString("firstName"), "Jarda"); jaroslav@919: assertEquals(o.getString("lastName"), "Tulach"); jaroslav@919: assertEquals(o.getString("sex"), "MALE"); jaroslav@919: } jaroslav@919: jaroslav@1009: @BrwsrTest public void toJSONInABrowser() throws Throwable { jaroslav@1009: Person p = new Person(); jaroslav@1009: p.setSex(Sex.MALE); jaroslav@1009: p.setFirstName("Jarda"); jaroslav@1009: p.setLastName("Tulach"); jaroslav@1009: jaroslav@1009: Object json; jaroslav@1009: try { jaroslav@1009: json = parseJSON(p.toString()); jaroslav@1009: } catch (Throwable ex) { jaroslav@1009: throw new IllegalStateException("Can't parse " + p).initCause(ex); jaroslav@1009: } jaroslav@1009: jaroslav@1009: Person p2 = new Person(json); jaroslav@1009: jaroslav@1009: assert p2.getFirstName().equals(p.getFirstName()) : jaroslav@1009: "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName(); jaroslav@1009: } jaroslav@1009: jaroslav@920: @Test public void personWithWildCharactersAndNulls() throws JSONException { jaroslav@920: Person p = new Person(); jaroslav@920: p.setFirstName("'\"\n"); jaroslav@920: p.setLastName("\t\r\u0002"); jaroslav@920: jaroslav@920: JSONTokener t = new JSONTokener(p.toString()); jaroslav@920: JSONObject o; jaroslav@920: try { jaroslav@920: o = new JSONObject(t); jaroslav@920: } catch (JSONException ex) { jaroslav@920: throw new AssertionError("Can't parse " + p.toString(), ex); jaroslav@920: } jaroslav@920: jaroslav@920: Iterator it = o.sortedKeys(); jaroslav@920: assertEquals(it.next(), "firstName"); jaroslav@920: assertEquals(it.next(), "lastName"); jaroslav@920: assertEquals(it.next(), "sex"); jaroslav@920: jaroslav@920: assertEquals(o.getString("firstName"), p.getFirstName()); jaroslav@920: assertEquals(o.getString("lastName"), p.getLastName()); jaroslav@920: assertEquals(o.get("sex"), JSONObject.NULL); jaroslav@920: } jaroslav@920: jaroslav@921: @Test public void personsInArray() throws JSONException { jaroslav@921: Person p1 = new Person(); jaroslav@921: p1.setFirstName("One"); jaroslav@921: jaroslav@921: Person p2 = new Person(); jaroslav@921: p2.setFirstName("Two"); jaroslav@921: jaroslav@921: People arr = new People(); jaroslav@921: arr.getInfo().add(p1); jaroslav@921: arr.getInfo().add(p2); jaroslav@921: arr.getNicknames().add("Prvn\u00ed k\u016f\u0148"); jaroslav@921: final String n2 = "Druh\u00fd hlem\u00fd\u017e\u010f, star\u0161\u00ed"; jaroslav@921: arr.getNicknames().add(n2); jaroslav@921: arr.getAge().add(33); jaroslav@921: arr.getAge().add(73); jaroslav@921: jaroslav@921: jaroslav@921: final String json = arr.toString(); jaroslav@921: jaroslav@921: JSONTokener t = new JSONTokener(json); jaroslav@921: JSONObject o; jaroslav@921: try { jaroslav@921: o = new JSONObject(t); jaroslav@921: } catch (JSONException ex) { jaroslav@921: throw new AssertionError("Can't parse " + json, ex); jaroslav@921: } jaroslav@921: jaroslav@921: assertEquals(o.getJSONArray("info").getJSONObject(0).getString("firstName"), "One"); jaroslav@921: assertEquals(o.getJSONArray("nicknames").getString(1), n2); jaroslav@921: assertEquals(o.getJSONArray("age").getInt(1), 73); jaroslav@921: } jaroslav@934: jaroslav@934: jaroslav@934: @OnReceive(url="/{url}") jaroslav@934: static void fetch(Person p, JSONik model) { jaroslav@934: model.setFetched(p); jaroslav@934: } jaroslav@936: jaroslav@936: @OnReceive(url="/{url}") jaroslav@936: static void fetchArray(Person[] p, JSONik model) { jaroslav@936: model.setFetchedCount(p.length); jaroslav@936: model.setFetched(p[0]); jaroslav@936: } jaroslav@934: jaroslav@943: @OnReceive(url="/{url}") jaroslav@943: static void fetchPeople(People p, JSONik model) { jaroslav@943: model.setFetchedCount(p.getInfo().size()); jaroslav@943: model.setFetched(p.getInfo().get(0)); jaroslav@943: } jaroslav@944: jaroslav@944: @OnReceive(url="/{url}") jaroslav@944: static void fetchPeopleAge(People p, JSONik model) { jaroslav@944: int sum = 0; jaroslav@944: for (int a : p.getAge()) { jaroslav@944: sum += a; jaroslav@944: } jaroslav@944: model.setFetchedCount(sum); jaroslav@944: } jaroslav@943: jaroslav@934: @Http(@Http.Resource( jaroslav@934: content = "{'firstName': 'Sitar', 'sex': 'MALE'}", jaroslav@934: path="/person.json", jaroslav@934: mimeType = "application/json" jaroslav@934: )) jaroslav@941: @BrwsrTest public void loadAndParseJSON() throws InterruptedException { jaroslav@941: if (js == null) { jaroslav@941: js = new JSONik(); jaroslav@941: js.applyBindings(); jaroslav@941: jaroslav@941: js.fetch("person.json"); jaroslav@941: } jaroslav@941: jaroslav@941: Person p = js.getFetched(); jaroslav@941: if (p == null) { jaroslav@941: throw new InterruptedException(); jaroslav@941: } jaroslav@934: jaroslav@934: assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName(); jaroslav@960: assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex(); jaroslav@934: } jaroslav@954: jaroslav@954: @OnReceive(url="/{url}?callme={me}", jsonp = "me") jaroslav@954: static void fetchViaJSONP(Person p, JSONik model) { jaroslav@954: model.setFetched(p); jaroslav@954: } jaroslav@954: jaroslav@954: @Http(@Http.Resource( jaroslav@954: content = "$0({'firstName': 'Mitar', 'sex': 'MALE'})", jaroslav@954: path="/person.json", jaroslav@954: mimeType = "application/javascript", jaroslav@954: parameters = { "callme" } jaroslav@954: )) jaroslav@954: @BrwsrTest public void loadAndParseJSONP() throws InterruptedException { jaroslav@963: jaroslav@954: if (js == null) { jaroslav@963: orig = scriptElements(); jaroslav@963: assert orig > 0 : "There should be some scripts on the page"; jaroslav@963: jaroslav@954: js = new JSONik(); jaroslav@954: js.applyBindings(); jaroslav@954: jaroslav@954: js.fetchViaJSONP("person.json"); jaroslav@954: } jaroslav@954: jaroslav@954: Person p = js.getFetched(); jaroslav@954: if (p == null) { jaroslav@954: throw new InterruptedException(); jaroslav@954: } jaroslav@954: jaroslav@954: assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName(); jaroslav@960: assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex(); jaroslav@963: jaroslav@963: int now = scriptElements(); jaroslav@963: jaroslav@963: assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig); jaroslav@954: } jaroslav@963: jaroslav@963: @JavaScriptBody(args = { }, body = "return window.document.getElementsByTagName('script').length;") jaroslav@963: private static native int scriptElements(); jaroslav@941: jaroslav@1009: @JavaScriptBody(args = { "s" }, body = "return window.JSON.parse(s);") jaroslav@1009: private static native Object parseJSON(String s); jaroslav@1009: jaroslav@934: @Http(@Http.Resource( jaroslav@936: content = "{'firstName': 'Sitar', 'sex': 'MALE'}", jaroslav@936: path="/person.json", jaroslav@936: mimeType = "application/json" jaroslav@936: )) jaroslav@941: @BrwsrTest public void loadAndParseJSONSentToArray() throws InterruptedException { jaroslav@941: if (js == null) { jaroslav@941: js = new JSONik(); jaroslav@941: js.applyBindings(); jaroslav@941: jaroslav@941: js.fetchArray("person.json"); jaroslav@941: } jaroslav@936: jaroslav@941: Person p = js.getFetched(); jaroslav@941: if (p == null) { jaroslav@941: throw new InterruptedException(); jaroslav@941: } jaroslav@936: jaroslav@936: assert p != null : "We should get our person back: " + p; jaroslav@936: assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName(); jaroslav@960: assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex(); jaroslav@936: } jaroslav@936: jaroslav@936: @Http(@Http.Resource( jaroslav@935: content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]", jaroslav@934: path="/person.json", jaroslav@934: mimeType = "application/json" jaroslav@934: )) jaroslav@941: @BrwsrTest public void loadAndParseJSONArraySingle() throws InterruptedException { jaroslav@941: if (js == null) { jaroslav@941: js = new JSONik(); jaroslav@941: js.applyBindings(); jaroslav@934: jaroslav@941: js.fetch("person.json"); jaroslav@941: } jaroslav@934: jaroslav@941: Person p = js.getFetched(); jaroslav@941: if (p == null) { jaroslav@941: throw new InterruptedException(); jaroslav@934: } jaroslav@941: jaroslav@934: assert p != null : "We should get our person back: " + p; jaroslav@941: assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName(); jaroslav@960: assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex(); jaroslav@934: } jaroslav@934: jaroslav@1412: // @Http(@Http.Resource( jaroslav@1412: // content = "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}", jaroslav@1412: // path="/people.json", jaroslav@1412: // mimeType = "application/json" jaroslav@1412: // )) jaroslav@1412: // @BrwsrTest public void loadAndParseArrayInPeople() throws InterruptedException { jaroslav@1412: // if (js == null) { jaroslav@1412: // js = new JSONik(); jaroslav@1412: // js.applyBindings(); jaroslav@1412: // jaroslav@1412: // js.fetchPeople("people.json"); jaroslav@1412: // } jaroslav@1412: // jaroslav@1412: // if (0 == js.getFetchedCount()) { jaroslav@1412: // throw new InterruptedException(); jaroslav@1412: // } jaroslav@1412: // jaroslav@1412: // assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount(); jaroslav@1412: // jaroslav@1412: // Person p = js.getFetched(); jaroslav@1412: // jaroslav@1412: // assert p != null : "We should get our person back: " + p; jaroslav@1412: // assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName(); jaroslav@1412: // assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex(); jaroslav@1412: // } jaroslav@943: jaroslav@943: @Http(@Http.Resource( jaroslav@944: content = "{'age':[1, 2, 3]}", jaroslav@944: path="/people.json", jaroslav@944: mimeType = "application/json" jaroslav@944: )) jaroslav@944: @BrwsrTest public void loadAndParseArrayOfIntegers() throws InterruptedException { jaroslav@944: if (js == null) { jaroslav@944: js = new JSONik(); jaroslav@944: js.applyBindings(); jaroslav@944: jaroslav@944: js.fetchPeopleAge("people.json"); jaroslav@944: } jaroslav@944: jaroslav@944: if (0 == js.getFetchedCount()) { jaroslav@944: throw new InterruptedException(); jaroslav@944: } jaroslav@944: jaroslav@944: assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount(); jaroslav@944: } jaroslav@944: jaroslav@960: @OnReceive(url="/{url}") jaroslav@960: static void fetchPeopleSex(People p, JSONik model) { jaroslav@960: model.setFetchedCount(1); jaroslav@960: model.getFetchedSex().addAll(p.getSex()); jaroslav@960: } jaroslav@960: jaroslav@960: jaroslav@960: @Http(@Http.Resource( jaroslav@960: content = "{'sex':['FEMALE', 'MALE', 'MALE']}", jaroslav@960: path="/people.json", jaroslav@960: mimeType = "application/json" jaroslav@960: )) jaroslav@960: @BrwsrTest public void loadAndParseArrayOfEnums() throws InterruptedException { jaroslav@960: if (js == null) { jaroslav@960: js = new JSONik(); jaroslav@960: js.applyBindings(); jaroslav@960: jaroslav@960: js.fetchPeopleSex("people.json"); jaroslav@960: } jaroslav@960: jaroslav@960: if (0 == js.getFetchedCount()) { jaroslav@960: throw new InterruptedException(); jaroslav@960: } jaroslav@960: jaroslav@960: assert js.getFetchedCount() == 1 : "Loaded"; jaroslav@960: jaroslav@960: assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex(); jaroslav@960: assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex(); jaroslav@960: assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex(); jaroslav@960: assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex(); jaroslav@960: } jaroslav@960: jaroslav@944: @Http(@Http.Resource( jaroslav@941: content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'}," jaroslav@936: + "{'firstName': 'Peter', 'sex': 'MALE'}" jaroslav@936: + "]", jaroslav@936: path="/person.json", jaroslav@936: mimeType = "application/json" jaroslav@936: )) jaroslav@941: @BrwsrTest public void loadAndParseJSONArray() throws InterruptedException { jaroslav@941: if (js == null) { jaroslav@941: js = new JSONik(); jaroslav@941: js.applyBindings(); jaroslav@941: js.fetchArray("person.json"); jaroslav@941: } jaroslav@936: jaroslav@936: jaroslav@941: Person p = js.getFetched(); jaroslav@941: if (p == null) { jaroslav@941: throw new InterruptedException(); jaroslav@936: } jaroslav@936: jaroslav@936: assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount(); jaroslav@936: assert p != null : "We should get our person back: " + p; jaroslav@941: assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName(); jaroslav@960: assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex(); jaroslav@936: } jaroslav@941: jaroslav@934: @Factory public static Object[] create() { jaroslav@934: return VMTest.create(JSONTest.class); jaroslav@934: } jaroslav@934: jaroslav@919: }