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