1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.json; 18 19 import java.util.ArrayList; 20 import java.util.Arrays; 21 import java.util.HashMap; 22 import java.util.Iterator; 23 import java.util.List; 24 import java.util.Map; 25 import junit.framework.TestCase; 26 27 public class ParsingTest extends TestCase { 28 testParsingNoObjects()29 public void testParsingNoObjects() { 30 try { 31 new JSONTokener("").nextValue(); 32 fail(); 33 } catch (JSONException e) { 34 } 35 } 36 testParsingLiterals()37 public void testParsingLiterals() throws JSONException { 38 assertParsed(Boolean.TRUE, "true"); 39 assertParsed(Boolean.FALSE, "false"); 40 assertParsed(JSONObject.NULL, "null"); 41 assertParsed(JSONObject.NULL, "NULL"); 42 assertParsed(Boolean.FALSE, "False"); 43 assertParsed(Boolean.TRUE, "truE"); 44 } 45 testParsingQuotedStrings()46 public void testParsingQuotedStrings() throws JSONException { 47 assertParsed("abc", "\"abc\""); 48 assertParsed("123", "\"123\""); 49 assertParsed("foo\nbar", "\"foo\\nbar\""); 50 assertParsed("foo bar", "\"foo\\u0020bar\""); 51 assertParsed("\"{}[]/\\:,=;#", "\"\\\"{}[]/\\\\:,=;#\""); 52 } 53 testParsingSingleQuotedStrings()54 public void testParsingSingleQuotedStrings() throws JSONException { 55 assertParsed("abc", "'abc'"); 56 assertParsed("123", "'123'"); 57 assertParsed("foo\nbar", "'foo\\nbar'"); 58 assertParsed("foo bar", "'foo\\u0020bar'"); 59 assertParsed("\"{}[]/\\:,=;#", "'\\\"{}[]/\\\\:,=;#'"); 60 } 61 testParsingUnquotedStrings()62 public void testParsingUnquotedStrings() throws JSONException { 63 assertParsed("abc", "abc"); 64 assertParsed("123abc", "123abc"); 65 assertParsed("123e0x", "123e0x"); 66 assertParsed("123e", "123e"); 67 assertParsed("123ee21", "123ee21"); 68 assertParsed("0xFFFFFFFFFFFFFFFFF", "0xFFFFFFFFFFFFFFFFF"); 69 } 70 71 /** 72 * Unfortunately the original implementation attempts to figure out what 73 * Java number type best suits an input value. 74 */ testParsingNumbersThatAreBestRepresentedAsLongs()75 public void testParsingNumbersThatAreBestRepresentedAsLongs() throws JSONException { 76 assertParsed(9223372036854775807L, "9223372036854775807"); 77 assertParsed(9223372036854775806L, "9223372036854775806"); 78 assertParsed(-9223372036854775808L, "-9223372036854775808"); 79 assertParsed(-9223372036854775807L, "-9223372036854775807"); 80 } 81 testParsingNumbersThatAreBestRepresentedAsIntegers()82 public void testParsingNumbersThatAreBestRepresentedAsIntegers() throws JSONException { 83 assertParsed(0, "0"); 84 assertParsed(5, "5"); 85 assertParsed(-2147483648, "-2147483648"); 86 assertParsed(2147483647, "2147483647"); 87 } 88 testParsingNegativeZero()89 public void testParsingNegativeZero() throws JSONException { 90 assertParsed(0, "-0"); 91 } 92 testParsingIntegersWithAdditionalPrecisionYieldDoubles()93 public void testParsingIntegersWithAdditionalPrecisionYieldDoubles() throws JSONException { 94 assertParsed(1d, "1.00"); 95 assertParsed(1d, "1.0"); 96 assertParsed(0d, "0.0"); 97 assertParsed(-0d, "-0.0"); 98 } 99 testParsingNumbersThatAreBestRepresentedAsDoubles()100 public void testParsingNumbersThatAreBestRepresentedAsDoubles() throws JSONException { 101 assertParsed(9.223372036854776E18, "9223372036854775808"); 102 assertParsed(-9.223372036854776E18, "-9223372036854775809"); 103 assertParsed(1.7976931348623157E308, "1.7976931348623157e308"); 104 assertParsed(2.2250738585072014E-308, "2.2250738585072014E-308"); 105 assertParsed(4.9E-324, "4.9E-324"); 106 assertParsed(4.9E-324, "4.9e-324"); 107 } 108 testParsingOctalNumbers()109 public void testParsingOctalNumbers() throws JSONException { 110 assertParsed(5, "05"); 111 assertParsed(8, "010"); 112 assertParsed(1046, "02026"); 113 } 114 testParsingHexNumbers()115 public void testParsingHexNumbers() throws JSONException { 116 assertParsed(5, "0x5"); 117 assertParsed(16, "0x10"); 118 assertParsed(8230, "0x2026"); 119 assertParsed(180150010, "0xABCDEFA"); 120 assertParsed(2077093803, "0x7BCDEFAB"); 121 } 122 testParsingLargeHexValues()123 public void testParsingLargeHexValues() throws JSONException { 124 assertParsed(Integer.MAX_VALUE, "0x7FFFFFFF"); 125 String message = "Hex values are parsed as Strings if their signed " + 126 "value is greater than Integer.MAX_VALUE."; 127 assertParsed(message, 0x80000000L, "0x80000000"); 128 } 129 test64BitHexValues()130 public void test64BitHexValues() throws JSONException { 131 assertParsed("Large hex longs shouldn't be yield ints or strings", 132 -1L, "0xFFFFFFFFFFFFFFFF"); 133 } 134 testParsingWithCommentsAndWhitespace()135 public void testParsingWithCommentsAndWhitespace() throws JSONException { 136 assertParsed("baz", " // foo bar \n baz"); 137 assertParsed("baz", " // foo bar \r baz"); 138 assertParsed("baz", " // foo bar \r\n baz"); 139 assertParsed("baz", " # foo bar \n baz"); 140 assertParsed("baz", " # foo bar \r baz"); 141 assertParsed("baz", " # foo bar \r\n baz"); 142 assertParsed(5, " /* foo bar \n baz */ 5"); 143 assertParsed(5, " /* foo bar \n baz */ 5 // quux"); 144 assertParsed(5, " 5 "); 145 assertParsed(5, " 5 \r\n\t "); 146 assertParsed(5, "\r\n\t 5 "); 147 } 148 testParsingArrays()149 public void testParsingArrays() throws JSONException { 150 assertParsed(array(), "[]"); 151 assertParsed(array(5, 6, true), "[5,6,true]"); 152 assertParsed(array(5, 6, array()), "[5,6,[]]"); 153 assertParsed(array(5, 6, 7), "[5;6;7]"); 154 assertParsed(array(5, 6, 7), "[5 , 6 \t; \r\n 7\n]"); 155 assertParsed(array(5, 6, 7, null), "[5,6,7,]"); 156 assertParsed(array(null, null), "[,]"); 157 assertParsed(array(5, null, null, null, 5), "[5,,,,5]"); 158 assertParsed(array(null, 5), "[,5]"); 159 assertParsed(array(null, null, null), "[,,]"); 160 assertParsed(array(null, null, null, 5), "[,,,5]"); 161 } 162 testParsingObjects()163 public void testParsingObjects() throws JSONException { 164 assertParsed(object("foo", 5), "{\"foo\": 5}"); 165 assertParsed(object("foo", 5), "{foo: 5}"); 166 assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\": 5, \"bar\": \"baz\"}"); 167 assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\": 5; \"bar\": \"baz\"}"); 168 assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\"= 5; \"bar\"= \"baz\"}"); 169 assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\"=> 5; \"bar\"=> \"baz\"}"); 170 assertParsed(object("foo", object(), "bar", array()), "{\"foo\"=> {}; \"bar\"=> []}"); 171 assertParsed(object("foo", object("foo", array(5, 6))), "{\"foo\": {\"foo\": [5, 6]}}"); 172 assertParsed(object("foo", object("foo", array(5, 6))), "{\"foo\":\n\t{\t \"foo\":[5,\r6]}}"); 173 } 174 testSyntaxProblemUnterminatedObject()175 public void testSyntaxProblemUnterminatedObject() { 176 assertParseFail("{"); 177 assertParseFail("{\"foo\""); 178 assertParseFail("{\"foo\":"); 179 assertParseFail("{\"foo\":bar"); 180 assertParseFail("{\"foo\":bar,"); 181 assertParseFail("{\"foo\":bar,\"baz\""); 182 assertParseFail("{\"foo\":bar,\"baz\":"); 183 assertParseFail("{\"foo\":bar,\"baz\":true"); 184 assertParseFail("{\"foo\":bar,\"baz\":true,"); 185 } 186 testSyntaxProblemEmptyString()187 public void testSyntaxProblemEmptyString() { 188 assertParseFail(""); 189 } 190 testSyntaxProblemUnterminatedArray()191 public void testSyntaxProblemUnterminatedArray() { 192 assertParseFail("["); 193 assertParseFail("[,"); 194 assertParseFail("[,,"); 195 assertParseFail("[true"); 196 assertParseFail("[true,"); 197 assertParseFail("[true,,"); 198 } 199 testSyntaxProblemMalformedObject()200 public void testSyntaxProblemMalformedObject() { 201 assertParseFail("{:}"); 202 assertParseFail("{\"key\":}"); 203 assertParseFail("{:true}"); 204 assertParseFail("{\"key\":true:}"); 205 assertParseFail("{null:true}"); 206 assertParseFail("{true:true}"); 207 assertParseFail("{0xFF:true}"); 208 } 209 assertParseFail(String malformedJson)210 private void assertParseFail(String malformedJson) { 211 try { 212 new JSONTokener(malformedJson).nextValue(); 213 fail("Successfully parsed: \"" + malformedJson + "\""); 214 } catch (JSONException e) { 215 } catch (StackOverflowError e) { 216 fail("Stack overflowed on input: \"" + malformedJson + "\""); 217 } 218 } 219 array(Object... elements)220 private JSONArray array(Object... elements) { 221 return new JSONArray(Arrays.asList(elements)); 222 } 223 object(Object... keyValuePairs)224 private JSONObject object(Object... keyValuePairs) throws JSONException { 225 JSONObject result = new JSONObject(); 226 for (int i = 0; i < keyValuePairs.length; i+=2) { 227 result.put((String) keyValuePairs[i], keyValuePairs[i+1]); 228 } 229 return result; 230 } 231 assertParsed(String message, Object expected, String json)232 private void assertParsed(String message, Object expected, String json) throws JSONException { 233 Object actual = new JSONTokener(json).nextValue(); 234 actual = canonicalize(actual); 235 expected = canonicalize(expected); 236 assertEquals("For input \"" + json + "\" " + message, expected, actual); 237 } 238 assertParsed(Object expected, String json)239 private void assertParsed(Object expected, String json) throws JSONException { 240 assertParsed("", expected, json); 241 } 242 243 /** 244 * Since they don't implement equals or hashCode properly, this recursively 245 * replaces JSONObjects with an equivalent HashMap, and JSONArrays with the 246 * equivalent ArrayList. 247 */ canonicalize(Object input)248 private Object canonicalize(Object input) throws JSONException { 249 if (input instanceof JSONArray) { 250 JSONArray array = (JSONArray) input; 251 List<Object> result = new ArrayList<Object>(); 252 for (int i = 0; i < array.length(); i++) { 253 result.add(canonicalize(array.opt(i))); 254 } 255 return result; 256 } else if (input instanceof JSONObject) { 257 JSONObject object = (JSONObject) input; 258 Map<String, Object> result = new HashMap<String, Object>(); 259 for (Iterator<?> i = object.keys(); i.hasNext(); ) { 260 String key = (String) i.next(); 261 result.put(key, canonicalize(object.get(key))); 262 } 263 return result; 264 } else if (input == null || input.equals(JSONObject.NULL)) { 265 return JSONObject.NULL; 266 } else { 267 return input; 268 } 269 } 270 } 271