summaryrefslogtreecommitdiffstats
path: root/json/src/test
diff options
context:
space:
mode:
authorJesse Wilson <jessewilson@google.com>2010-02-16 13:50:32 -0800
committerJesse Wilson <jessewilson@google.com>2010-02-17 10:02:32 -0800
commit67f4459a2fcc50cb3378c302b6c663af48f60ff0 (patch)
treeb5084003279d4ac4121f2ae839fda1071f93ded6 /json/src/test
parent6c231cf6815ba6427035e8e47fc36f9d1139d2fb (diff)
downloadlibcore-67f4459a2fcc50cb3378c302b6c663af48f60ff0.zip
libcore-67f4459a2fcc50cb3378c302b6c663af48f60ff0.tar.gz
libcore-67f4459a2fcc50cb3378c302b6c663af48f60ff0.tar.bz2
First round of tests for the subset of the org.json in Android.
Diffstat (limited to 'json/src/test')
-rw-r--r--json/src/test/java/org/json/AllTests.java30
-rw-r--r--json/src/test/java/org/json/JSONArrayTest.java343
-rw-r--r--json/src/test/java/org/json/JSONStringerTest.java361
-rw-r--r--json/src/test/java/org/json/JSONTokenerTest.java567
4 files changed, 1301 insertions, 0 deletions
diff --git a/json/src/test/java/org/json/AllTests.java b/json/src/test/java/org/json/AllTests.java
new file mode 100644
index 0000000..8261a4d
--- /dev/null
+++ b/json/src/test/java/org/json/AllTests.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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.json;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+ public static Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+ suite.addTestSuite(JSONArrayTest.class);
+ suite.addTestSuite(JSONStringerTest.class);
+ suite.addTestSuite(JSONStringerTest.class);
+ return suite;
+ }
+}
diff --git a/json/src/test/java/org/json/JSONArrayTest.java b/json/src/test/java/org/json/JSONArrayTest.java
new file mode 100644
index 0000000..e0c7164
--- /dev/null
+++ b/json/src/test/java/org/json/JSONArrayTest.java
@@ -0,0 +1,343 @@
+/**
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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 android;
+
+import junit.framework.TestCase;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Arrays;
+
+/**
+ * This black box test was written without inspecting the non-free org.json sourcecode.
+ */
+public class JSONArrayTest extends TestCase {
+
+ public void testEmptyArray() throws JSONException {
+ JSONArray array = new JSONArray();
+ assertEquals(0, array.length());
+ assertEquals("", array.join(" AND "));
+ try {
+ array.get(0);
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ array.getBoolean(0);
+ fail();
+ } catch (JSONException e) {
+ }
+
+ assertEquals("[]", array.toString());
+ assertEquals("[]", array.toString(4));
+
+ // out of bounds is co-opted with defaulting
+ assertTrue(array.isNull(0));
+ assertNull(array.opt(0));
+ assertFalse(array.optBoolean(0));
+ assertTrue(array.optBoolean(0, true));
+
+ // bogus (but documented) behaviour: returns null rather than an empty object
+ assertNull(array.toJSONObject(new JSONArray()));
+ }
+
+ public void testEqualsAndHashCode() throws JSONException {
+ JSONArray a = new JSONArray();
+ JSONArray b = new JSONArray();
+ assertTrue(a.equals(b));
+ // bogus behavior: JSONArray overrides equals() but not hashCode().
+ assertEquals(a.hashCode(), b.hashCode());
+
+ a.put(true);
+ a.put(false);
+ b.put(true);
+ b.put(false);
+ assertTrue(a.equals(b));
+ assertEquals(a.hashCode(), b.hashCode());
+
+ b.put(true);
+ assertFalse(a.equals(b));
+ assertTrue(a.hashCode() != b.hashCode());
+ }
+
+ public void testBooleans() throws JSONException {
+ JSONArray array = new JSONArray();
+ array.put(true);
+ array.put(false);
+ array.put(2, false);
+ array.put(3, false);
+ array.put(2, true);
+ assertEquals("[true,false,true,false]", array.toString());
+ assertEquals(4, array.length());
+ assertEquals(Boolean.TRUE, array.get(0));
+ assertEquals(Boolean.FALSE, array.get(1));
+ assertEquals(Boolean.TRUE, array.get(2));
+ assertEquals(Boolean.FALSE, array.get(3));
+ assertFalse(array.isNull(0));
+ assertFalse(array.isNull(1));
+ assertFalse(array.isNull(2));
+ assertFalse(array.isNull(3));
+ assertEquals(true, array.optBoolean(0));
+ assertEquals(false, array.optBoolean(1, true));
+ assertEquals(true, array.optBoolean(2, false));
+ assertEquals(false, array.optBoolean(3));
+ assertEquals("true", array.getString(0));
+ assertEquals("false", array.getString(1));
+ assertEquals("true", array.optString(2));
+ assertEquals("false", array.optString(3, "x"));
+ assertEquals("[\n true,\n false,\n true,\n false\n]", array.toString(5));
+
+ JSONArray other = new JSONArray();
+ other.put(true);
+ other.put(false);
+ other.put(true);
+ other.put(false);
+ assertTrue(array.equals(other));
+ other.put(true);
+ assertFalse(array.equals(other));
+
+ other = new JSONArray();
+ other.put("true");
+ other.put("false");
+ other.put("truE");
+ other.put("FALSE");
+ assertFalse(array.equals(other));
+ assertFalse(other.equals(array));
+ assertEquals(true, other.getBoolean(0));
+ assertEquals(false, other.optBoolean(1, true));
+ assertEquals(true, other.optBoolean(2));
+ assertEquals(false, other.getBoolean(3));
+ }
+
+ public void testNulls() throws JSONException {
+ JSONArray array = new JSONArray();
+ array.put(3, null);
+ array.put(0, JSONObject.NULL);
+ assertEquals(4, array.length());
+ assertEquals("[null,null,null,null]", array.toString());
+
+ // bogus behaviour: there's 2 ways to represent null; each behaves differently!
+ assertEquals(JSONObject.NULL, array.get(0));
+ try {
+ assertEquals(null, array.get(1));
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ assertEquals(null, array.get(2));
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ assertEquals(null, array.get(3));
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals(JSONObject.NULL, array.opt(0));
+ assertEquals(null, array.opt(1));
+ assertEquals(null, array.opt(2));
+ assertEquals(null, array.opt(3));
+ assertTrue(array.isNull(0));
+ assertTrue(array.isNull(1));
+ assertTrue(array.isNull(2));
+ assertTrue(array.isNull(3));
+ assertEquals("null", array.optString(0));
+ assertEquals("", array.optString(1));
+ assertEquals("", array.optString(2));
+ assertEquals("", array.optString(3));
+ }
+
+ public void testNumbers() throws JSONException {
+ JSONArray array = new JSONArray();
+ array.put(Double.MIN_VALUE);
+ array.put(9223372036854775806L);
+ array.put(Double.MAX_VALUE);
+ array.put(-0d);
+ assertEquals(4, array.length());
+
+ // bogus behaviour: toString() and getString(int) return different values for -0d
+ assertEquals("[4.9E-324,9223372036854775806,1.7976931348623157E308,-0]", array.toString());
+
+ assertEquals(Double.MIN_VALUE, array.get(0));
+ assertEquals(9223372036854775806L, array.get(1));
+ assertEquals(Double.MAX_VALUE, array.get(2));
+ assertEquals(-0d, array.get(3));
+ assertEquals(Double.MIN_VALUE, array.getDouble(0));
+ assertEquals(9.223372036854776E18, array.getDouble(1));
+ assertEquals(Double.MAX_VALUE, array.getDouble(2));
+ assertEquals(-0d, array.getDouble(3));
+ assertEquals(0, array.getLong(0));
+ assertEquals(9223372036854775806L, array.getLong(1));
+ assertEquals(Long.MAX_VALUE, array.getLong(2));
+ assertEquals(0, array.getLong(3));
+ assertEquals(0, array.getInt(0));
+ assertEquals(-2, array.getInt(1));
+ assertEquals(Integer.MAX_VALUE, array.getInt(2));
+ assertEquals(0, array.getInt(3));
+ assertEquals(Double.MIN_VALUE, array.opt(0));
+ assertEquals(Double.MIN_VALUE, array.optDouble(0));
+ assertEquals(0, array.optLong(0, 1L));
+ assertEquals(0, array.optInt(0, 1));
+ assertEquals("4.9E-324", array.getString(0));
+ assertEquals("9223372036854775806", array.getString(1));
+ assertEquals("1.7976931348623157E308", array.getString(2));
+ assertEquals("-0.0", array.getString(3));
+
+ JSONArray other = new JSONArray();
+ other.put(Double.MIN_VALUE);
+ other.put(9223372036854775806L);
+ other.put(Double.MAX_VALUE);
+ other.put(-0d);
+ assertTrue(array.equals(other));
+ other.put(0, 0L);
+ assertFalse(array.equals(other));
+ }
+
+ public void testStrings() throws JSONException {
+ JSONArray array = new JSONArray();
+ array.put("true");
+ array.put("5.5");
+ array.put("9223372036854775806");
+ array.put("null");
+ array.put("5\"8' tall");
+ assertEquals(5, array.length());
+ assertEquals("[\"true\",\"5.5\",\"9223372036854775806\",\"null\",\"5\\\"8' tall\"]",
+ array.toString());
+
+ // although the documentation doesn't mention it, join() escapes text and wraps
+ // strings in quotes
+ assertEquals("\"true\" \"5.5\" \"9223372036854775806\" \"null\" \"5\\\"8' tall\"",
+ array.join(" "));
+
+ assertEquals("true", array.get(0));
+ assertEquals("null", array.getString(3));
+ assertEquals("5\"8' tall", array.getString(4));
+ assertEquals("true", array.opt(0));
+ assertEquals("5.5", array.optString(1));
+ assertEquals("9223372036854775806", array.optString(2, null));
+ assertEquals("null", array.optString(3, "-1"));
+ assertFalse(array.isNull(0));
+ assertFalse(array.isNull(3));
+
+ assertEquals(true, array.getBoolean(0));
+ assertEquals(true, array.optBoolean(0));
+ assertEquals(true, array.optBoolean(0, false));
+ assertEquals(0, array.optInt(0));
+ assertEquals(-2, array.optInt(0, -2));
+
+ assertEquals(5.5d, array.getDouble(1));
+ assertEquals(5, array.getLong(1));
+ assertEquals(5, array.getInt(1));
+ assertEquals(5, array.optInt(1, 3));
+
+ // The last digit of the string is a 6 but getLong returns a 7. It's probably parsing as a
+ // double and then converting that to a long. This is consistent with JavaScript.
+ assertEquals(9223372036854775807L, array.getLong(2));
+ assertEquals(9.223372036854776E18, array.getDouble(2));
+ assertEquals(Integer.MAX_VALUE, array.getInt(2));
+
+ assertFalse(array.isNull(3));
+ try {
+ array.getDouble(3);
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals(Double.NaN, array.optDouble(3));
+ assertEquals(-1.0d, array.optDouble(3, -1.0d));
+ }
+
+ public void testToJSONObject() throws JSONException {
+ JSONArray keys = new JSONArray();
+ keys.put("a");
+ keys.put("b");
+
+ JSONArray values = new JSONArray();
+ values.put(5.5d);
+ values.put(false);
+
+ JSONObject object = values.toJSONObject(keys);
+ assertEquals(5.5d, object.get("a"));
+ assertEquals(false, object.get("b"));
+
+ keys.put(0, "a");
+ values.put(0, 11.0d);
+ assertEquals(5.5d, object.get("a"));
+ }
+
+ public void testToJSONObjectWithNulls() throws JSONException {
+ JSONArray keys = new JSONArray();
+ keys.put("a");
+ keys.put("b");
+
+ JSONArray values = new JSONArray();
+ values.put(5.5d);
+ values.put(null);
+
+ // bogus behaviour: null values are stripped
+ JSONObject object = values.toJSONObject(keys);
+ assertEquals(1, object.length());
+ assertFalse(object.has("b"));
+ assertEquals("{\"a\":5.5}", object.toString());
+ }
+
+ public void testPutUnsupportedNumbers() throws JSONException {
+ JSONArray array = new JSONArray();
+
+ try {
+ array.put(Double.NaN);
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ array.put(0, Double.NEGATIVE_INFINITY);
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ array.put(0, Double.POSITIVE_INFINITY);
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+
+ public void testCreateWithUnsupportedNumbers() throws JSONException {
+ JSONArray array = new JSONArray(Arrays.asList(5.5, Double.NaN));
+ assertEquals(2, array.length());
+ assertEquals(5.5, array.getDouble(0));
+ assertEquals(Double.NaN, array.getDouble(1));
+ }
+
+ public void testToStringWithUnsupportedNumbers() throws JSONException {
+ // bogus behaviour: when the array contains an unsupported number, toString returns null
+ JSONArray array = new JSONArray(Arrays.asList(5.5, Double.NaN));
+ assertNull(array.toString());
+ }
+
+ public void testCreate() throws JSONException {
+ JSONArray array = new JSONArray(Arrays.asList(5.5, true));
+ assertEquals(2, array.length());
+ assertEquals(5.5, array.getDouble(0));
+ assertEquals(true, array.get(1));
+ assertEquals("[5.5,true]", array.toString());
+ }
+
+ public void testParsingConstructor() {
+ fail("TODO");
+ }
+}
diff --git a/json/src/test/java/org/json/JSONStringerTest.java b/json/src/test/java/org/json/JSONStringerTest.java
new file mode 100644
index 0000000..e9b4e51
--- /dev/null
+++ b/json/src/test/java/org/json/JSONStringerTest.java
@@ -0,0 +1,361 @@
+/**
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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 android;
+
+import junit.framework.TestCase;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONStringer;
+
+/**
+ * This black box test was written without inspecting the non-free org.json sourcecode.
+ */
+public class JSONStringerTest extends TestCase {
+
+ public void testEmptyStringer() {
+ // bogus behaviour: why isn't this the empty string?
+ assertNull(new JSONStringer().toString());
+ }
+
+ public void testValueJSONNull() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.array();
+ stringer.value(JSONObject.NULL);
+ stringer.endArray();
+ assertEquals("[null]", stringer.toString());
+ }
+
+ public void testEmptyObject() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.object();
+ stringer.endObject();
+ assertEquals("{}", stringer.toString());
+ }
+
+ public void testEmptyArray() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.array();
+ stringer.endArray();
+ assertEquals("[]", stringer.toString());
+ }
+
+ public void testArray() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.array();
+ stringer.value(false);
+ stringer.value(5.0);
+ stringer.value(5L);
+ stringer.value("five");
+ stringer.value(null);
+ stringer.endArray();
+ assertEquals("[false,5,5,\"five\",null]", stringer.toString());
+ }
+
+ public void testKeyValue() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.object();
+ stringer.key("a").value(false);
+ stringer.key("b").value(5.0);
+ stringer.key("c").value(5L);
+ stringer.key("d").value("five");
+ stringer.key("e").value(null);
+ stringer.endObject();
+ assertEquals("{\"a\":false," +
+ "\"b\":5," +
+ "\"c\":5," +
+ "\"d\":\"five\"," +
+ "\"e\":null}", stringer.toString());
+ }
+
+ /**
+ * Test what happens when extreme values are emitted. Such values are likely
+ * to be rounded during parsing.
+ */
+ public void testNumericRepresentations() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.array();
+ stringer.value(Long.MAX_VALUE);
+ stringer.value(Double.MIN_VALUE);
+ stringer.endArray();
+ assertEquals("[9223372036854775807,4.9E-324]", stringer.toString());
+ }
+
+ public void testWeirdNumbers() throws JSONException {
+ try {
+ new JSONStringer().array().value(Double.NaN);
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().array().value(Double.NEGATIVE_INFINITY);
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().array().value(Double.POSITIVE_INFINITY);
+ fail();
+ } catch (JSONException e) {
+ }
+
+ JSONStringer stringer = new JSONStringer();
+ stringer.array();
+ stringer.value(-0.0d);
+ stringer.value(0.0d);
+ stringer.endArray();
+ assertEquals("[-0,0]", stringer.toString());
+ }
+
+ public void testMismatchedScopes() {
+ try {
+ new JSONStringer().key("a");
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().value("a");
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().endObject();
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().endArray();
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().array().endObject();
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().object().endArray();
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().object().key("a").key("a");
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONStringer().object().value(false);
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+
+ public void testNullKey() {
+ try {
+ new JSONStringer().object().key(null);
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+
+ public void testRepeatedKey() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.object();
+ stringer.key("a").value(true);
+ stringer.key("a").value(false);
+ stringer.endObject();
+ // JSONStringer doesn't attempt to detect duplicates
+ assertEquals("{\"a\":true,\"a\":false}", stringer.toString());
+ }
+
+ public void testEmptyKey() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.object();
+ stringer.key("").value(false);
+ stringer.endObject();
+ assertEquals("{\"\":false}", stringer.toString()); // legit behaviour!
+ }
+
+ public void testEscaping() throws JSONException {
+ assertEscapedAllWays("a", "a");
+ assertEscapedAllWays("a\"", "a\\\"");
+ assertEscapedAllWays("\"", "\\\"");
+ assertEscapedAllWays(":", ":");
+ assertEscapedAllWays(",", ",");
+ assertEscapedAllWays("\n", "\\n");
+ assertEscapedAllWays("\t", "\\t");
+ assertEscapedAllWays(" ", " ");
+ assertEscapedAllWays("\\", "\\\\");
+ assertEscapedAllWays("{", "{");
+ assertEscapedAllWays("}", "}");
+ assertEscapedAllWays("[", "[");
+ assertEscapedAllWays("]", "]");
+
+ // how does it decide which characters to escape?
+ assertEscapedAllWays("\0", "\\u0000");
+ assertEscapedAllWays("\u0019", "\\u0019");
+ assertEscapedAllWays("\u0020", " ");
+ }
+
+ private void assertEscapedAllWays(String original, String escaped) throws JSONException {
+ assertEquals("{\"" + escaped + "\":false}",
+ new JSONStringer().object().key(original).value(false).endObject().toString());
+ assertEquals("{\"a\":\"" + escaped + "\"}",
+ new JSONStringer().object().key("a").value(original).endObject().toString());
+ assertEquals("[\"" + escaped + "\"]",
+ new JSONStringer().array().value(original).endArray().toString());
+ }
+
+ public void testJSONArrayAsValue() throws JSONException {
+ JSONArray array = new JSONArray();
+ array.put(false);
+ JSONStringer stringer = new JSONStringer();
+ stringer.array();
+ stringer.value(array);
+ stringer.endArray();
+ assertEquals("[[false]]", stringer.toString());
+ }
+
+ public void testJSONObjectAsValue() throws JSONException {
+ JSONObject object = new JSONObject();
+ object.put("a", false);
+ JSONStringer stringer = new JSONStringer();
+ stringer.object();
+ stringer.key("b").value(object);
+ stringer.endObject();
+ assertEquals("{\"b\":{\"a\":false}}", stringer.toString());
+ }
+
+ public void testArrayNestingMaxDepthIs20() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ for (int i = 0; i < 20; i++) {
+ stringer.array();
+ }
+ for (int i = 0; i < 20; i++) {
+ stringer.endArray();
+ }
+ assertEquals("[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]", stringer.toString());
+
+ stringer = new JSONStringer();
+ for (int i = 0; i < 20; i++) {
+ stringer.array();
+ }
+ try {
+ stringer.array();
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+
+ public void testObjectNestingMaxDepthIs20() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ for (int i = 0; i < 20; i++) {
+ stringer.object();
+ stringer.key("a");
+ }
+ stringer.value(false);
+ for (int i = 0; i < 20; i++) {
+ stringer.endObject();
+ }
+ assertEquals("{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":" +
+ "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":false" +
+ "}}}}}}}}}}}}}}}}}}}}", stringer.toString());
+
+ stringer = new JSONStringer();
+ for (int i = 0; i < 20; i++) {
+ stringer.object();
+ stringer.key("a");
+ }
+ try {
+ stringer.object();
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+
+ public void testMixedMaxDepth() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ for (int i = 0; i < 20; i+=2) {
+ stringer.array();
+ stringer.object();
+ stringer.key("a");
+ }
+ stringer.value(false);
+ for (int i = 0; i < 20; i+=2) {
+ stringer.endObject();
+ stringer.endArray();
+ }
+ assertEquals("[{\"a\":[{\"a\":[{\"a\":[{\"a\":[{\"a\":" +
+ "[{\"a\":[{\"a\":[{\"a\":[{\"a\":[{\"a\":false" +
+ "}]}]}]}]}]}]}]}]}]}]", stringer.toString());
+
+ stringer = new JSONStringer();
+ for (int i = 0; i < 20; i+=2) {
+ stringer.array();
+ stringer.object();
+ stringer.key("a");
+ }
+ try {
+ stringer.array();
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+
+ public void testMaxDepthWithArrayValue() throws JSONException {
+ JSONArray array = new JSONArray();
+ array.put(false);
+
+ JSONStringer stringer = new JSONStringer();
+ for (int i = 0; i < 20; i++) {
+ stringer.array();
+ }
+ stringer.value(array);
+ for (int i = 0; i < 20; i++) {
+ stringer.endArray();
+ }
+ assertEquals("[[[[[[[[[[[[[[[[[[[[[false]]]]]]]]]]]]]]]]]]]]]", stringer.toString());
+ }
+
+ public void testMaxDepthWithObjectValue() throws JSONException {
+ JSONObject object = new JSONObject();
+ object.put("a", false);
+ JSONStringer stringer = new JSONStringer();
+ for (int i = 0; i < 20; i++) {
+ stringer.object();
+ stringer.key("b");
+ }
+ stringer.value(object);
+ for (int i = 0; i < 20; i++) {
+ stringer.endObject();
+ }
+ assertEquals("{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":" +
+ "{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":" +
+ "{\"a\":false}}}}}}}}}}}}}}}}}}}}}", stringer.toString());
+ }
+
+ public void testMultipleRoots() throws JSONException {
+ JSONStringer stringer = new JSONStringer();
+ stringer.array();
+ stringer.endArray();
+ try {
+ stringer.object();
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+}
diff --git a/json/src/test/java/org/json/JSONTokenerTest.java b/json/src/test/java/org/json/JSONTokenerTest.java
new file mode 100644
index 0000000..7d947e3
--- /dev/null
+++ b/json/src/test/java/org/json/JSONTokenerTest.java
@@ -0,0 +1,567 @@
+/**
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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 android;
+
+import junit.framework.TestCase;
+import org.json.JSONException;
+import org.json.JSONTokener;
+
+/**
+ * This black box test was written without inspecting the non-free org.json sourcecode.
+ */
+public class JSONTokenerTest extends TestCase {
+
+ public void testNulls() throws JSONException {
+ // bogus behaviour: JSONTokener accepts null, only to fail later on almost all APIs.
+ new JSONTokener(null).back();
+
+ try {
+ new JSONTokener(null).more();
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).next();
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).next(3);
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).next('A');
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).nextClean();
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).nextString('"');
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).nextTo('A');
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).nextTo("ABC");
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).nextValue();
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).skipPast("ABC");
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new JSONTokener(null).skipTo('A');
+ fail();
+ } catch (NullPointerException e) {
+ }
+
+ assertEquals("foo! at character 0 of null",
+ new JSONTokener(null).syntaxError("foo!").getMessage());
+
+ assertEquals(" at character 0 of null", new JSONTokener(null).toString());
+ }
+
+ public void testEmptyString() throws JSONException {
+ JSONTokener backTokener = new JSONTokener("");
+ backTokener.back();
+ assertEquals(" at character 0 of ", backTokener.toString());
+ assertFalse(new JSONTokener("").more());
+ assertEquals('\0', new JSONTokener("").next());
+ try {
+ new JSONTokener("").next(3);
+ fail();
+ } catch (JSONException expected) {
+ }
+ try {
+ new JSONTokener("").next('A');
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals('\0', new JSONTokener("").nextClean());
+ try {
+ new JSONTokener("").nextString('"');
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals("", new JSONTokener("").nextTo('A'));
+ assertEquals("", new JSONTokener("").nextTo("ABC"));
+ try {
+ new JSONTokener("").nextValue();
+ fail();
+ } catch (JSONException e) {
+ }
+ new JSONTokener("").skipPast("ABC");
+ assertEquals('\0', new JSONTokener("").skipTo('A'));
+ assertEquals("foo! at character 0 of ",
+ new JSONTokener("").syntaxError("foo!").getMessage());
+ assertEquals(" at character 0 of ", new JSONTokener("").toString());
+ }
+
+ public void testCharacterNavigation() throws JSONException {
+ JSONTokener abcdeTokener = new JSONTokener("ABCDE");
+ assertEquals('A', abcdeTokener.next());
+ assertEquals('B', abcdeTokener.next('B'));
+ assertEquals("CD", abcdeTokener.next(2));
+ try {
+ abcdeTokener.next(2);
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals('E', abcdeTokener.nextClean());
+ assertEquals('\0', abcdeTokener.next());
+ try {
+ // bogus behaviour: returning an empty string should be valid
+ abcdeTokener.next(0);
+ fail();
+ } catch (JSONException e) {
+ }
+ assertFalse(abcdeTokener.more());
+ abcdeTokener.back();
+ assertTrue(abcdeTokener.more());
+ assertEquals('E', abcdeTokener.next());
+ }
+
+ public void testBackNextAndMore() throws JSONException {
+ JSONTokener abcTokener = new JSONTokener("ABC");
+ assertTrue(abcTokener.more());
+ abcTokener.next();
+ abcTokener.next();
+ assertTrue(abcTokener.more());
+ abcTokener.next();
+ assertFalse(abcTokener.more());
+ abcTokener.back();
+ assertTrue(abcTokener.more());
+ abcTokener.next();
+ assertFalse(abcTokener.more());
+ abcTokener.back();
+ abcTokener.back();
+ abcTokener.back();
+ abcTokener.back(); // bogus behaviour: you can back up before the beginning of a String
+ assertEquals('A', abcTokener.next());
+ }
+
+ public void testNextMatching() throws JSONException {
+ JSONTokener abcdTokener = new JSONTokener("ABCD");
+ assertEquals('A', abcdTokener.next('A'));
+ try {
+ abcdTokener.next('C'); // although it failed, this op consumes a character of input
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals('C', abcdTokener.next('C'));
+ assertEquals('D', abcdTokener.next('D'));
+ try {
+ abcdTokener.next('E');
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+
+ public void testNextN() throws JSONException {
+ JSONTokener abcdeTokener = new JSONTokener("ABCDEF");
+ assertEquals("", abcdeTokener.next(0));
+ try {
+ abcdeTokener.next(7);
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals("ABC", abcdeTokener.next(3));
+ try {
+ abcdeTokener.next(4);
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ // bogus behaviour: there should be 3 characters left, but there must be an off-by-one
+ // error in the implementation.
+ assertEquals("DEF", abcdeTokener.next(3));
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals("DE", abcdeTokener.next(2));
+ assertEquals('F', abcdeTokener.next());
+ try {
+ // bogus behaviour: returning an empty string should be valid
+ abcdeTokener.next(0);
+ fail();
+ } catch (JSONException e) {
+ }
+ abcdeTokener.back();
+ abcdeTokener.back();
+ abcdeTokener.back();
+ assertEquals("DE", abcdeTokener.next(2));
+ assertEquals('F', abcdeTokener.next());
+ }
+
+ public void testNextCleanComments() throws JSONException {
+ JSONTokener tokener = new JSONTokener(
+ " A /*XX*/B/*XX//XX\n//XX\nXX*/C//X//X//X\nD/*X*///X\n");
+ assertEquals('A', tokener.nextClean());
+ assertEquals('B', tokener.nextClean());
+ assertEquals('C', tokener.nextClean());
+ assertEquals('D', tokener.nextClean());
+ assertEquals('\0', tokener.nextClean());
+ }
+
+ public void testNextCleanTrailingOpenComment() throws JSONException {
+ try {
+ new JSONTokener(" /* ").nextClean();
+ fail();
+ } catch (JSONException e) {
+ }
+ assertEquals('\0', new JSONTokener(" // ").nextClean());
+ }
+
+ public void testNextCleanNewlineDelimiters() throws JSONException {
+ assertEquals('B', new JSONTokener(" // \r\n B ").nextClean());
+ assertEquals('B', new JSONTokener(" // \n B ").nextClean());
+ assertEquals('B', new JSONTokener(" // \r B ").nextClean());
+ }
+
+ /**
+ * Tests which characters tokener treats as ignorable whitespace. See Kevin Bourrillion's
+ * <a href="https://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">list
+ * of whitespace characters</a>.
+ */
+ public void testNextCleanWhitespace() throws JSONException {
+ // This behaviour contradicts the JSON spec. It claims the only space
+ // characters are space, tab, newline and carriage return. But it treats
+ // many characters like whitespace! These are the same whitespace
+ // characters used by String.trim(), with the exception of '\0'.
+ assertEquals("character tabulation", 'A', new JSONTokener("\u0009A").nextClean());
+ assertEquals("line feed", 'A', new JSONTokener("\nA").nextClean());
+ assertEquals("line tabulation", 'A', new JSONTokener("\u000bA").nextClean());
+ assertEquals("form feed", 'A', new JSONTokener("\u000cA").nextClean());
+ assertEquals("carriage return", 'A', new JSONTokener("\rA").nextClean());
+ assertEquals("information separator 4", 'A', new JSONTokener("\u001cA").nextClean());
+ assertEquals("information separator 3", 'A', new JSONTokener("\u001dA").nextClean());
+ assertEquals("information separator 2", 'A', new JSONTokener("\u001eA").nextClean());
+ assertEquals("information separator 1", 'A', new JSONTokener("\u001fA").nextClean());
+ assertEquals("space", 'A', new JSONTokener("\u0020A").nextClean());
+ for (char c = '\u0002'; c < ' '; c++) {
+ assertEquals('A', new JSONTokener(new String(new char[] { ' ', c, 'A' })).nextClean());
+ }
+
+ // These characters are neither whitespace in the JSON spec nor the implementation
+ assertEquals("null", '\u0000', new JSONTokener("\u0000A").nextClean());
+ assertEquals("next line", '\u0085', new JSONTokener("\u0085A").nextClean());
+ assertEquals("non-breaking space", '\u00a0', new JSONTokener("\u00a0A").nextClean());
+ assertEquals("ogham space mark", '\u1680', new JSONTokener("\u1680A").nextClean());
+ assertEquals("mongolian vowel separator", '\u180e', new JSONTokener("\u180eA").nextClean());
+ assertEquals("en quad", '\u2000', new JSONTokener("\u2000A").nextClean());
+ assertEquals("em quad", '\u2001', new JSONTokener("\u2001A").nextClean());
+ assertEquals("en space", '\u2002', new JSONTokener("\u2002A").nextClean());
+ assertEquals("em space", '\u2003', new JSONTokener("\u2003A").nextClean());
+ assertEquals("three-per-em space", '\u2004', new JSONTokener("\u2004A").nextClean());
+ assertEquals("four-per-em space", '\u2005', new JSONTokener("\u2005A").nextClean());
+ assertEquals("six-per-em space", '\u2006', new JSONTokener("\u2006A").nextClean());
+ assertEquals("figure space", '\u2007', new JSONTokener("\u2007A").nextClean());
+ assertEquals("punctuation space", '\u2008', new JSONTokener("\u2008A").nextClean());
+ assertEquals("thin space", '\u2009', new JSONTokener("\u2009A").nextClean());
+ assertEquals("hair space", '\u200a', new JSONTokener("\u200aA").nextClean());
+ assertEquals("zero-width space", '\u200b', new JSONTokener("\u200bA").nextClean());
+ assertEquals("left-to-right mark", '\u200e', new JSONTokener("\u200eA").nextClean());
+ assertEquals("right-to-left mark", '\u200f', new JSONTokener("\u200fA").nextClean());
+ assertEquals("line separator", '\u2028', new JSONTokener("\u2028A").nextClean());
+ assertEquals("paragraph separator", '\u2029', new JSONTokener("\u2029A").nextClean());
+ assertEquals("narrow non-breaking space", '\u202f', new JSONTokener("\u202fA").nextClean());
+ assertEquals("medium mathematical space", '\u205f', new JSONTokener("\u205fA").nextClean());
+ assertEquals("ideographic space", '\u3000', new JSONTokener("\u3000A").nextClean());
+ }
+
+ public void testNextString() throws JSONException {
+ assertEquals("", new JSONTokener("'").nextString('\''));
+ assertEquals("", new JSONTokener("\"").nextString('\"'));
+ assertEquals("ABC", new JSONTokener("ABC'DEF").nextString('\''));
+ assertEquals("ABC", new JSONTokener("ABC'''DEF").nextString('\''));
+
+ // nextString permits slash-escaping of arbitrary characters!
+ assertEquals("ABC", new JSONTokener("A\\B\\C'DEF").nextString('\''));
+
+ JSONTokener tokener = new JSONTokener(" 'abc' 'def' \"ghi\"");
+ tokener.next();
+ assertEquals('\'', tokener.next());
+ assertEquals("abc", tokener.nextString('\''));
+ tokener.next();
+ assertEquals('\'', tokener.next());
+ assertEquals("def", tokener.nextString('\''));
+ tokener.next();
+ assertEquals('"', tokener.next());
+ assertEquals("ghi", tokener.nextString('\"'));
+ assertFalse(tokener.more());
+ }
+
+ public void testNextStringNoDelimiter() throws JSONException {
+ try {
+ new JSONTokener("").nextString('\'');
+ fail();
+ } catch (JSONException e) {
+ }
+
+ JSONTokener tokener = new JSONTokener(" 'abc");
+ tokener.next();
+ tokener.next();
+ try {
+ tokener.next('\'');
+ fail();
+ } catch (JSONException e) {
+ }
+ }
+
+ public void testNextStringEscapedQuote() throws JSONException {
+ try {
+ new JSONTokener("abc\\").nextString('"');
+ fail();
+ } catch (JSONException e) {
+ }
+
+ // we're mixing Java escaping like \" and JavaScript escaping like \\\"
+ // which makes these tests extra tricky to read!
+ assertEquals("abc\"def", new JSONTokener("abc\\\"def\"ghi").nextString('"'));
+ assertEquals("abc\\def", new JSONTokener("abc\\\\def\"ghi").nextString('"'));
+ assertEquals("abc/def", new JSONTokener("abc\\/def\"ghi").nextString('"'));
+ assertEquals("abc\bdef", new JSONTokener("abc\\bdef\"ghi").nextString('"'));
+ assertEquals("abc\fdef", new JSONTokener("abc\\fdef\"ghi").nextString('"'));
+ assertEquals("abc\ndef", new JSONTokener("abc\\ndef\"ghi").nextString('"'));
+ assertEquals("abc\rdef", new JSONTokener("abc\\rdef\"ghi").nextString('"'));
+ assertEquals("abc\tdef", new JSONTokener("abc\\tdef\"ghi").nextString('"'));
+ }
+
+ public void testNextStringUnicodeEscaped() throws JSONException {
+ // we're mixing Java escaping like \\ and JavaScript escaping like \\u
+ assertEquals("abc def", new JSONTokener("abc\\u0020def\"ghi").nextString('"'));
+ assertEquals("abcU0020def", new JSONTokener("abc\\U0020def\"ghi").nextString('"'));
+
+ // JSON requires 4 hex characters after a unicode escape
+ try {
+ new JSONTokener("abc\\u002\"").nextString('"');
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONTokener("abc\\u").nextString('"');
+ fail();
+ } catch (JSONException e) {
+ }
+ try {
+ new JSONTokener("abc\\u \"").nextString('"');
+ fail();
+ } catch (NumberFormatException e) {
+ }
+ assertEquals("abc\"def", new JSONTokener("abc\\u0022def\"ghi").nextString('"'));
+ try {
+ new JSONTokener("abc\\u000G\"").nextString('"');
+ fail();
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ public void testNextStringNonQuote() throws JSONException {
+ assertEquals("AB", new JSONTokener("ABC").nextString('C'));
+ assertEquals("ABCD", new JSONTokener("AB\\CDC").nextString('C'));
+ assertEquals("AB\nC", new JSONTokener("AB\\nCn").nextString('n'));
+ }
+
+ public void testNextTo() throws JSONException {
+ assertEquals("ABC", new JSONTokener("ABCDEFG").nextTo("DHI"));
+ assertEquals("ABCDEF", new JSONTokener("ABCDEF").nextTo(""));
+
+ JSONTokener tokener = new JSONTokener("ABC\rDEF\nGHI\r\nJKL");
+ assertEquals("ABC", tokener.nextTo("M"));
+ assertEquals('\r', tokener.next());
+ assertEquals("DEF", tokener.nextTo("M"));
+ assertEquals('\n', tokener.next());
+ assertEquals("GHI", tokener.nextTo("M"));
+ assertEquals('\r', tokener.next());
+ assertEquals('\n', tokener.next());
+ assertEquals("JKL", tokener.nextTo("M"));
+
+ tokener = new JSONTokener("ABCDEFGHI");
+ assertEquals("ABC", tokener.nextTo("DEF"));
+ assertEquals("", tokener.nextTo("DEF"));
+ assertEquals('D', tokener.next());
+ assertEquals("", tokener.nextTo("DEF"));
+ assertEquals('E', tokener.next());
+ assertEquals("", tokener.nextTo("DEF"));
+ assertEquals('F', tokener.next());
+ assertEquals("GHI", tokener.nextTo("DEF"));
+ assertEquals("", tokener.nextTo("DEF"));
+
+ tokener = new JSONTokener(" \t \fABC \t DEF");
+ assertEquals("ABC", tokener.nextTo("DEF"));
+ assertEquals('D', tokener.next());
+
+ tokener = new JSONTokener(" \t \fABC \n DEF");
+ assertEquals("ABC", tokener.nextTo("\n"));
+ assertEquals("", tokener.nextTo("\n"));
+
+ // Bogus behaviour: the tokener stops after \0 always
+ tokener = new JSONTokener(" \0\t \fABC \n DEF");
+ assertEquals("", tokener.nextTo("D"));
+ assertEquals('\t', tokener.next());
+ assertEquals("ABC", tokener.nextTo("D"));
+ tokener = new JSONTokener("ABC\0DEF");
+ assertEquals("ABC", tokener.nextTo("\0"));
+ assertEquals("DEF", tokener.nextTo("\0"));
+
+ tokener = new JSONTokener("");
+ try {
+ tokener.nextTo(null);
+ fail();
+ } catch (NullPointerException e) {
+ }
+ }
+
+ public void testSkipPast() {
+ JSONTokener tokener = new JSONTokener("ABCDEF");
+ tokener.skipPast("ABC");
+ assertEquals('D', tokener.next());
+ tokener.skipPast("EF");
+ assertEquals('\0', tokener.next());
+
+ tokener = new JSONTokener("ABCDEF");
+ tokener.skipPast("ABCDEF");
+ assertEquals('\0', tokener.next());
+
+ tokener = new JSONTokener("ABCDEF");
+ tokener.skipPast("G");
+ assertEquals('\0', tokener.next());
+
+ tokener = new JSONTokener("ABC\0ABC");
+ tokener.skipPast("ABC");
+ assertEquals('\0', tokener.next());
+ assertEquals('A', tokener.next());
+
+ tokener = new JSONTokener("\0ABC");
+ tokener.skipPast("ABC");
+ assertEquals('\0', tokener.next());
+
+ tokener = new JSONTokener("ABC\nDEF");
+ tokener.skipPast("DEF");
+ assertEquals('\0', tokener.next());
+
+ tokener = new JSONTokener("ABC");
+ tokener.skipPast("ABCDEF");
+ assertEquals('\0', tokener.next());
+
+ tokener = new JSONTokener("ABCDABCDABCD");
+ tokener.skipPast("ABC");
+ assertEquals('D', tokener.next());
+ tokener.skipPast("ABC");
+ assertEquals('D', tokener.next());
+ tokener.skipPast("ABC");
+ assertEquals('D', tokener.next());
+
+ tokener = new JSONTokener("");
+ try {
+ tokener.skipPast(null);
+ fail();
+ } catch (NullPointerException e) {
+ }
+ }
+
+ public void testSkipTo() {
+ JSONTokener tokener = new JSONTokener("ABCDEF");
+ tokener.skipTo('A');
+ assertEquals('A', tokener.next());
+ tokener.skipTo('D');
+ assertEquals('D', tokener.next());
+ tokener.skipTo('G');
+ assertEquals('E', tokener.next());
+ tokener.skipTo('A');
+ assertEquals('F', tokener.next());
+
+ tokener = new JSONTokener("ABC\0DEF");
+ tokener.skipTo('F');
+ // bogus behaviour: skipTo gives up when it sees '\0'
+ assertEquals('A', tokener.next());
+
+ tokener = new JSONTokener("ABC\nDEF");
+ tokener.skipTo('F');
+ assertEquals('F', tokener.next());
+
+ tokener = new JSONTokener("ABCfDEF");
+ tokener.skipTo('F');
+ assertEquals('F', tokener.next());
+
+ tokener = new JSONTokener("ABC/* DEF */");
+ tokener.skipTo('D');
+ assertEquals('D', tokener.next());
+ }
+
+ public void testDehexchar() {
+ assertEquals( 0, JSONTokener.dehexchar('0'));
+ assertEquals( 1, JSONTokener.dehexchar('1'));
+ assertEquals( 2, JSONTokener.dehexchar('2'));
+ assertEquals( 3, JSONTokener.dehexchar('3'));
+ assertEquals( 4, JSONTokener.dehexchar('4'));
+ assertEquals( 5, JSONTokener.dehexchar('5'));
+ assertEquals( 6, JSONTokener.dehexchar('6'));
+ assertEquals( 7, JSONTokener.dehexchar('7'));
+ assertEquals( 8, JSONTokener.dehexchar('8'));
+ assertEquals( 9, JSONTokener.dehexchar('9'));
+ assertEquals(10, JSONTokener.dehexchar('A'));
+ assertEquals(11, JSONTokener.dehexchar('B'));
+ assertEquals(12, JSONTokener.dehexchar('C'));
+ assertEquals(13, JSONTokener.dehexchar('D'));
+ assertEquals(14, JSONTokener.dehexchar('E'));
+ assertEquals(15, JSONTokener.dehexchar('F'));
+ assertEquals(10, JSONTokener.dehexchar('a'));
+ assertEquals(11, JSONTokener.dehexchar('b'));
+ assertEquals(12, JSONTokener.dehexchar('c'));
+ assertEquals(13, JSONTokener.dehexchar('d'));
+ assertEquals(14, JSONTokener.dehexchar('e'));
+ assertEquals(15, JSONTokener.dehexchar('f'));
+
+ for (int c = 0; c <= 0xFFFF; c++) {
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
+ continue;
+ }
+ assertEquals("dehexchar " + c, -1, JSONTokener.dehexchar((char) c));
+ }
+ }
+
+ public void testNextValue() {
+ fail("TODO");
+ }
+}