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