blob: 9436a3edb1b4878c244027927f665e047d7da42c [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*******************************************************************************/
package org.ofbiz.base.json.test;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import org.ofbiz.base.json.JSON;
import org.ofbiz.base.json.JSONConstants;
import org.ofbiz.base.json.JSONWriter;
import org.ofbiz.base.json.ParseException;
import org.ofbiz.base.json.Token;
import org.ofbiz.base.json.TokenMgrError;
import org.ofbiz.base.lang.SourceMonitored;
import org.ofbiz.base.test.GenericTestCaseBase;
import org.ofbiz.base.util.IndentingWriter;
@SourceMonitored
public class JSONTests extends GenericTestCaseBase {
public JSONTests(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
protected Object parseJSON(String value, boolean allowResolve) throws Exception {
return new JSON(new StringReader(value)).allowResolve(allowResolve).JSONValue();
}
protected String getJSON(Object object, boolean allowResolve) throws Exception {
StringWriter writer = new StringWriter();
JSONWriter jsonWriter;
if (allowResolve) {
jsonWriter = new JSONWriter(writer, JSONWriter.ResolvingFallbackHandler);
} else {
jsonWriter = new JSONWriter(writer);
}
assertTrue("writer is IndentingWriter", jsonWriter.getWriter() instanceof IndentingWriter);
jsonWriter.write(object);
return writer.toString();
}
protected void assertSimpleJSONByte(byte n, String json) throws Exception {
assertSimpleJSON("integer - byte", new Byte(n), json, new Long(n));
assertSimpleJSONShort(n, json);
}
protected void assertSimpleJSONShort(short n, String json) throws Exception {
assertSimpleJSON("integer - short", new Integer(n), json, new Long(n));
assertSimpleJSONInteger(n, json);
}
protected void assertSimpleJSONInteger(int n, String json) throws Exception {
assertSimpleJSON("integer - int", new Short((short) n), json, new Long(n));
assertSimpleJSONLong(n, json);
}
protected void assertSimpleJSONLong(long n, String json) throws Exception {
assertSimpleJSON("integer - long", new Long(n), json, new Long(n));
}
protected void assertSimpleJSONFloat(float n, String json) throws Exception {
assertSimpleJSON("float - float", new Float(n), json, new Double(n));
assertSimpleJSONDouble(n, json);
}
protected void assertSimpleJSONDouble(double n, String json) throws Exception {
assertSimpleJSON("float - double", new Double(n), json);
}
protected void assertSimpleJSON(String type, Object object, String json) throws Exception {
assertSimpleJSON(type, object, json, object);
}
protected void assertSimpleJSON(String type, Object before, String json, Object after) throws Exception {
assertEquals("write " + type, json, getJSON(before, false));
assertEquals("parse " + type, after, parseJSON(json, false));
}
protected void assertResolveJSON(String type, Object obj, String json) throws Exception {
assertEquals("write " + type, json, getJSON(obj, true));
assertEquals("parse " + type, obj, parseJSON(json, true));
}
public void testClose() throws Exception {
JSONWriter writer = new JSONWriter(new OutputStreamWriter(new ByteArrayOutputStream()));
writer.close();
IOException caught = null;
try {
writer.write("");
} catch (IOException e) {
caught = e;
} finally {
assertNotNull("write after close", caught);
}
}
public void testString() throws Exception {
StringBuilder wanted = new StringBuilder();
StringBuilder json = new StringBuilder().append('"');
for (int i = 0; i < 5120; i++) {
wanted.append((char) i);
if (i == '\b') {
json.append("\\b");
} else if (i == '\f') {
json.append("\\f");
} else if (i == '\t') {
json.append("\\t");
} else if (i == '\n') {
json.append("\\n");
} else if (i == '\r') {
json.append("\\r");
} else if (i == '"') {
json.append("\\\"");
} else if (i == '\\') {
json.append("\\\\");
} else if (i == '/') {
json.append("\\/");
} else if (i < 32 || i >= 256) {
json.append("\\u");
if (i < 16) json.append('0');
if (i < 256) json.append('0');
if (i < 4096) json.append('0');
json.append(Integer.toString(i, 16));
} else {
json.append((char) i);
}
}
json.append('"');
assertSimpleJSON("string", wanted.toString(), json.toString());
}
public void testParseBasicTypes() throws Exception {
assertSimpleJSON("character", new Character('c'), "\"c\"", "c");
assertSimpleJSON("false", Boolean.FALSE, "false");
assertSimpleJSON("null", null, "null");
assertSimpleJSON("true", Boolean.TRUE, "true");
assertSimpleJSON("simple string", "foo", "\"foo\"");
assertSimpleJSONByte((byte) 42, "42");
assertSimpleJSONFloat(Float.valueOf("1.0625"), "1.0625");
assertSimpleJSON(
"complex string",
"quote(\") backslash(\\) forwardslash(/) backspace(\b) formfeed(\f) newline(\n) carriagereturn(\r) tab(\t) trademark(\u2122)",
"\"quote(\\\") backslash(\\\\) forwardslash(\\/) backspace(\\b) formfeed(\\f) newline(\\n) carriagereturn(\\r) tab(\\t) trademark(\\u2122)\""
);
}
public void testParseComplexTypes() throws Exception {
assertEquals(
"parse simple array",
list(new Object[] {"foo", new Long(1234), new Double(5.678)}),
parseJSON("[, ,\t,\r,\n,\r\n,\"foo\", 1234, 5.678,]", false)
);
assertSimpleJSON(
"simple empty list",
list(new Object[] {}),
"[]"
);
assertSimpleJSON(
"simple empty array",
new Object[] {},
"[]",
list(new Object[] {})
);
assertSimpleJSON(
"simple array->list",
new Object[] {"foo", new Long(1234), new Double(5.678)},
"[\n \"foo\",\n 1234,\n 5.678\n]",
list(new Object[] {"foo", new Long(1234), new Double(5.678)})
);
assertSimpleJSON(
"simple array",
list(new Object[] {"foo", new Long(1234), new Double(5.678)}),
"[\n \"foo\",\n 1234,\n 5.678\n]",
list(new Object[] {"foo", new Long(1234), new Double(5.678)})
);
assertEquals(
"parse simple map",
map(new Object[] {"foo", new Long(1234), "bar", new Double(5.678)}),
parseJSON("{, ,\t,\r,\n,\r\n,\"foo\": 1234, \"bar\": 5.678,}", false)
);
assertSimpleJSON(
"parse map",
map(new Object[] {"foo", new Long(1234), "bar", new Double(5.678)}),
"{\n \"foo\": 1234,\n \"bar\": 5.678\n}"
);
assertSimpleJSON(
"parse empty map",
map(new Object[] {}),
"{}"
);
assertEquals(
"parse nested map",
map(new Object[] {
"string", "this is a string",
"integer", new Long(5000),
"double", new Double(3.1415926),
"array", new Object[] {
"string",
new Long(6000)
},
"list", list(new Object[] {
"nested string",
"something",
}),
"empty-list", new ArrayList<String>(),
"empty-array", new String[0],
"empty-map", new HashMap<String, Object>(),
}),
parseJSON("{\"string\": \"this is a string\", \"integer\": 5000, \"double\": 3.1415926, \"array\": [\"string\", 6000], \"list\": [\"nested string\", \"something\"], \"empty-list\": [], \"empty-array\": [], \"empty-map\": {}}", false)
);
}
public void testParseErrors() throws Exception {
for (char c = 1; c < 1024; c++) {
if (c == '\t') {
doWhitespaceExceptionTest(Character.toString(c), 8);
} else if (c == '\n' || c == '\r' || c == ' ') {
doWhitespaceExceptionTest(Character.toString(c), 1);
} else if (c == '"') {
doParseExceptionTest("\"", JSONConstants.EOF);
} else if (c == ',') {
doParseExceptionTest(",", JSONConstants.ITEM_SEP);
} else if (c == '-' || c == '.' || (c >= '0' && c <= '9')) {
// numbers
} else if (c == ':') {
doParseExceptionTest(":", JSONConstants.KEY_SEP);
} else if (c == '[') {
doParseExceptionTest("[:", JSONConstants.KEY_SEP);
} else if (c == ']') {
doParseExceptionTest("]", JSONConstants.ARRAY_END);
} else if (c == 't') {
doParseExceptionTest("true:", JSONConstants.KEY_SEP);
} else if (c == 'f') {
doParseExceptionTest("false:", JSONConstants.KEY_SEP);
} else if (c == 'n') {
doParseExceptionTest("null:", JSONConstants.KEY_SEP);
} else if (c == '{') {
doParseExceptionTest("{:", JSONConstants.KEY_SEP);
} else if (c == '}') {
doParseExceptionTest("}", JSONConstants.OBJECT_END);
} else {
doTokenMgrErrorTest(c);
}
}
}
protected void doWhitespaceExceptionTest(String s, int column) {
ParseException caught = null;
try {
new JSON(new StringReader(s)).JSONValue();
} catch (ParseException e) {
caught = e;
} finally {
assertNotNull("caught exception", caught);
assertNotNull("next token(" + s + ")", caught.currentToken);
Token next = caught.currentToken.next;
assertEquals("next token(" + s + ") is eof", 0, next.kind);
assertEquals("begin line(" + s + ")", 1, next.beginLine);
assertEquals("begin column(" + s + ")", column, next.beginColumn);
}
}
protected void doParseExceptionTest(String s, int nextKind) {
ParseException caught = null;
try {
new JSON(new StringReader(s)).JSONValue();
} catch (ParseException e) {
caught = e;
} finally {
assertNotNull("caught exception", caught);
assertNotNull("exception message(" + s + ")", caught.getMessage());
assertNotNull("next token(" + s + ")", caught.currentToken);
Token next = caught.currentToken.next;
assertEquals("next token(" + s + ") is correct", nextKind, next.kind);
assertEquals("begin line(" + s + ")", 1, next.beginLine);
assertEquals("begin column(" + s + ")", s.length(), next.beginColumn);
}
}
protected void doTokenMgrErrorTest(char c) throws Exception {
TokenMgrError caught = null;
try {
parseJSON(c + "\"string\"", false);
} catch (TokenMgrError e) {
caught = e;
} finally {
assertNotNull("No TokenMgrError thrown for character(" + ((int) c) + ")", caught);
// FIXME: maybe extend javacc to return more info in TokenMgrError
}
}
public void testResolve() throws Exception {
assertResolveJSON("url", new URL("http://ofbiz.apache.org"), "resolve(\"java.net.URL:http:\\/\\/ofbiz.apache.org\")");
IOException caught = null;
try {
getJSON(new URL("http://ofbiz.apache.org"), false);
} catch (IOException e) {
caught = e;
} finally {
assertNotNull("url not allowed", caught);
}
}
}