blob: be3e07eba2daff044fac7fd65b60a08698824d48 [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
5#include "testing/gtest/include/gtest/gtest.h"
6#include "base/json_reader.h"
aa@chromium.orgca9c79e2008-12-30 04:59:08 +09007#include "base/scoped_ptr.h"
initial.commit3f4a7322008-07-27 06:49:38 +09008#include "base/values.h"
tc@google.comd3bb16f2008-08-09 02:26:42 +09009#include "build/build_config.h"
initial.commit3f4a7322008-07-27 06:49:38 +090010
11TEST(JSONReaderTest, Reading) {
12 // some whitespace checking
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090013 scoped_ptr<Value> root;
14 root.reset(JSONReader().JsonToValue(" null ", false, false));
15 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090016 ASSERT_TRUE(root->IsType(Value::TYPE_NULL));
initial.commit3f4a7322008-07-27 06:49:38 +090017
18 // Invalid JSON string
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090019 root.reset(JSONReader().JsonToValue("nu", false, false));
20 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090021
22 // Simple bool
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090023 root.reset(JSONReader().JsonToValue("true ", false, false));
24 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090025 ASSERT_TRUE(root->IsType(Value::TYPE_BOOLEAN));
initial.commit3f4a7322008-07-27 06:49:38 +090026
munjal@chromium.org124260d2009-07-24 06:34:40 +090027 // Embedded comment
28 root.reset(JSONReader().JsonToValue("/* comment */null", false, false));
29 ASSERT_TRUE(root.get());
30 ASSERT_TRUE(root->IsType(Value::TYPE_NULL));
31 root.reset(JSONReader().JsonToValue("40 /* comment */", false, false));
32 ASSERT_TRUE(root.get());
33 ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
34 root.reset(JSONReader().JsonToValue("true // comment", false, false));
35 ASSERT_TRUE(root.get());
36 ASSERT_TRUE(root->IsType(Value::TYPE_BOOLEAN));
37 root.reset(JSONReader().JsonToValue("/* comment */\"sample string\"",
38 false, false));
39 ASSERT_TRUE(root.get());
40 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
41 std::string value;
42 ASSERT_TRUE(root->GetAsString(&value));
43 ASSERT_EQ("sample string", value);
44
initial.commit3f4a7322008-07-27 06:49:38 +090045 // Test number formats
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090046 root.reset(JSONReader().JsonToValue("43", false, false));
47 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090048 ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
49 int int_val = 0;
50 ASSERT_TRUE(root->GetAsInteger(&int_val));
51 ASSERT_EQ(43, int_val);
initial.commit3f4a7322008-07-27 06:49:38 +090052
53 // According to RFC4627, oct, hex, and leading zeros are invalid JSON.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090054 root.reset(JSONReader().JsonToValue("043", false, false));
55 ASSERT_FALSE(root.get());
56 root.reset(JSONReader().JsonToValue("0x43", false, false));
57 ASSERT_FALSE(root.get());
58 root.reset(JSONReader().JsonToValue("00", false, false));
59 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090060
61 // Test 0 (which needs to be special cased because of the leading zero
62 // clause).
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090063 root.reset(JSONReader().JsonToValue("0", false, false));
64 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090065 ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
66 int_val = 1;
67 ASSERT_TRUE(root->GetAsInteger(&int_val));
68 ASSERT_EQ(0, int_val);
initial.commit3f4a7322008-07-27 06:49:38 +090069
mmentovai@google.com8dcf71c2008-08-08 02:15:41 +090070 // Numbers that overflow ints should succeed, being internally promoted to
71 // storage as doubles
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090072 root.reset(JSONReader().JsonToValue("2147483648", false, false));
73 ASSERT_TRUE(root.get());
tc@google.comd3bb16f2008-08-09 02:26:42 +090074 double real_val;
75#ifdef ARCH_CPU_32_BITS
76 ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
77 real_val = 0.0;
78 ASSERT_TRUE(root->GetAsReal(&real_val));
79 ASSERT_DOUBLE_EQ(2147483648.0, real_val);
80#else
81 ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
82 int_val = 0;
83 ASSERT_TRUE(root->GetAsInteger(&int_val));
84 ASSERT_EQ(2147483648, int_val);
85#endif
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090086 root.reset(JSONReader().JsonToValue("-2147483649", false, false));
87 ASSERT_TRUE(root.get());
tc@google.comd3bb16f2008-08-09 02:26:42 +090088#ifdef ARCH_CPU_32_BITS
89 ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
90 real_val = 0.0;
91 ASSERT_TRUE(root->GetAsReal(&real_val));
92 ASSERT_DOUBLE_EQ(-2147483649.0, real_val);
93#else
94 ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
95 int_val = 0;
96 ASSERT_TRUE(root->GetAsInteger(&int_val));
97 ASSERT_EQ(-2147483649, int_val);
98#endif
initial.commit3f4a7322008-07-27 06:49:38 +090099
100 // Parse a double
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900101 root.reset(JSONReader().JsonToValue("43.1", false, false));
102 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900103 ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
tc@google.comd3bb16f2008-08-09 02:26:42 +0900104 real_val = 0.0;
initial.commit3f4a7322008-07-27 06:49:38 +0900105 ASSERT_TRUE(root->GetAsReal(&real_val));
106 ASSERT_DOUBLE_EQ(43.1, real_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900107
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900108 root.reset(JSONReader().JsonToValue("4.3e-1", false, false));
109 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900110 ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
111 real_val = 0.0;
112 ASSERT_TRUE(root->GetAsReal(&real_val));
113 ASSERT_DOUBLE_EQ(.43, real_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900114
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900115 root.reset(JSONReader().JsonToValue("2.1e0", false, false));
116 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900117 ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
118 real_val = 0.0;
119 ASSERT_TRUE(root->GetAsReal(&real_val));
120 ASSERT_DOUBLE_EQ(2.1, real_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900121
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900122 root.reset(JSONReader().JsonToValue("2.1e+0001", false, false));
123 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900124 ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
125 real_val = 0.0;
126 ASSERT_TRUE(root->GetAsReal(&real_val));
127 ASSERT_DOUBLE_EQ(21.0, real_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900128
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900129 root.reset(JSONReader().JsonToValue("0.01", false, false));
130 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900131 ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
132 real_val = 0.0;
133 ASSERT_TRUE(root->GetAsReal(&real_val));
134 ASSERT_DOUBLE_EQ(0.01, real_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900135
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900136 root.reset(JSONReader().JsonToValue("1.00", false, false));
137 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900138 ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
139 real_val = 0.0;
140 ASSERT_TRUE(root->GetAsReal(&real_val));
141 ASSERT_DOUBLE_EQ(1.0, real_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900142
143 // Fractional parts must have a digit before and after the decimal point.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900144 root.reset(JSONReader().JsonToValue("1.", false, false));
145 ASSERT_FALSE(root.get());
146 root.reset(JSONReader().JsonToValue(".1", false, false));
147 ASSERT_FALSE(root.get());
148 root.reset(JSONReader().JsonToValue("1.e10", false, false));
149 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900150
151 // Exponent must have a digit following the 'e'.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900152 root.reset(JSONReader().JsonToValue("1e", false, false));
153 ASSERT_FALSE(root.get());
154 root.reset(JSONReader().JsonToValue("1E", false, false));
155 ASSERT_FALSE(root.get());
156 root.reset(JSONReader().JsonToValue("1e1.", false, false));
157 ASSERT_FALSE(root.get());
158 root.reset(JSONReader().JsonToValue("1e1.0", false, false));
159 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900160
161 // INF/-INF/NaN are not valid
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900162 root.reset(JSONReader().JsonToValue("1e1000", false, false));
163 ASSERT_FALSE(root.get());
164 root.reset(JSONReader().JsonToValue("-1e1000", false, false));
165 ASSERT_FALSE(root.get());
166 root.reset(JSONReader().JsonToValue("NaN", false, false));
167 ASSERT_FALSE(root.get());
168 root.reset(JSONReader().JsonToValue("nan", false, false));
169 ASSERT_FALSE(root.get());
170 root.reset(JSONReader().JsonToValue("inf", false, false));
171 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900172
173 // Invalid number formats
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900174 root.reset(JSONReader().JsonToValue("4.3.1", false, false));
175 ASSERT_FALSE(root.get());
176 root.reset(JSONReader().JsonToValue("4e3.1", false, false));
177 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900178
179 // Test string parser
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900180 root.reset(JSONReader().JsonToValue("\"hello world\"", false, false));
181 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900182 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
183 std::wstring str_val;
184 ASSERT_TRUE(root->GetAsString(&str_val));
185 ASSERT_EQ(L"hello world", str_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900186
187 // Empty string
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900188 root.reset(JSONReader().JsonToValue("\"\"", false, false));
189 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900190 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
191 str_val.clear();
192 ASSERT_TRUE(root->GetAsString(&str_val));
193 ASSERT_EQ(L"", str_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900194
195 // Test basic string escapes
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900196 root.reset(JSONReader().JsonToValue("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\\v\"",
197 false, false));
198 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900199 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
200 str_val.clear();
201 ASSERT_TRUE(root->GetAsString(&str_val));
sky@google.com0ba93512008-10-02 02:26:06 +0900202 ASSERT_EQ(L" \"\\/\b\f\n\r\t\v", str_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900203
204 // Test hex and unicode escapes including the null character.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900205 root.reset(JSONReader().JsonToValue("\"\\x41\\x00\\u1234\"", false,
tc@google.comce6a78d2008-07-29 09:01:31 +0900206 false));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900207 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900208 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
209 str_val.clear();
210 ASSERT_TRUE(root->GetAsString(&str_val));
211 ASSERT_EQ(std::wstring(L"A\0\x1234", 3), str_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900212
213 // Test invalid strings
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900214 root.reset(JSONReader().JsonToValue("\"no closing quote", false, false));
215 ASSERT_FALSE(root.get());
216 root.reset(JSONReader().JsonToValue("\"\\z invalid escape char\"", false,
217 false));
218 ASSERT_FALSE(root.get());
219 root.reset(JSONReader().JsonToValue("\"\\xAQ invalid hex code\"", false,
220 false));
221 ASSERT_FALSE(root.get());
222 root.reset(JSONReader().JsonToValue("not enough hex chars\\x1\"", false,
223 false));
224 ASSERT_FALSE(root.get());
225 root.reset(JSONReader().JsonToValue("\"not enough escape chars\\u123\"",
226 false, false));
227 ASSERT_FALSE(root.get());
228 root.reset(JSONReader().JsonToValue("\"extra backslash at end of input\\\"",
229 false, false));
230 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900231
232 // Basic array
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900233 root.reset(JSONReader::Read("[true, false, null]", false));
234 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900235 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900236 ListValue* list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900237 ASSERT_EQ(3U, list->GetSize());
tc@google.comce6a78d2008-07-29 09:01:31 +0900238
239 // Test with trailing comma. Should be parsed the same as above.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900240 scoped_ptr<Value> root2;
241 root2.reset(JSONReader::Read("[true, false, null, ]", true));
242 EXPECT_TRUE(root->Equals(root2.get()));
initial.commit3f4a7322008-07-27 06:49:38 +0900243
244 // Empty array
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900245 root.reset(JSONReader::Read("[]", false));
246 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900247 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900248 list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900249 ASSERT_EQ(0U, list->GetSize());
initial.commit3f4a7322008-07-27 06:49:38 +0900250
251 // Nested arrays
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900252 root.reset(JSONReader::Read("[[true], [], [false, [], [null]], null]",
253 false));
254 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900255 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900256 list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900257 ASSERT_EQ(4U, list->GetSize());
tc@google.comce6a78d2008-07-29 09:01:31 +0900258
259 // Lots of trailing commas.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900260 root2.reset(JSONReader::Read("[[true], [], [false, [], [null, ] , ], null,]",
261 true));
262 EXPECT_TRUE(root->Equals(root2.get()));
initial.commit3f4a7322008-07-27 06:49:38 +0900263
264 // Invalid, missing close brace.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900265 root.reset(JSONReader::Read("[[true], [], [false, [], [null]], null", false));
266 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900267
268 // Invalid, too many commas
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900269 root.reset(JSONReader::Read("[true,, null]", false));
270 ASSERT_FALSE(root.get());
271 root.reset(JSONReader::Read("[true,, null]", true));
272 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900273
274 // Invalid, no commas
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900275 root.reset(JSONReader::Read("[true null]", false));
276 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900277
278 // Invalid, trailing comma
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900279 root.reset(JSONReader::Read("[true,]", false));
280 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900281
tc@google.comce6a78d2008-07-29 09:01:31 +0900282 // Valid if we set |allow_trailing_comma| to true.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900283 root.reset(JSONReader::Read("[true,]", true));
284 ASSERT_TRUE(root.get());
tc@google.comce6a78d2008-07-29 09:01:31 +0900285 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900286 list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900287 EXPECT_EQ(1U, list->GetSize());
tc@google.comce6a78d2008-07-29 09:01:31 +0900288 Value* tmp_value = NULL;
289 ASSERT_TRUE(list->Get(0, &tmp_value));
290 EXPECT_TRUE(tmp_value->IsType(Value::TYPE_BOOLEAN));
291 bool bool_value = false;
292 ASSERT_TRUE(tmp_value->GetAsBoolean(&bool_value));
293 EXPECT_TRUE(bool_value);
tc@google.comce6a78d2008-07-29 09:01:31 +0900294
295 // Don't allow empty elements, even if |allow_trailing_comma| is
296 // true.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900297 root.reset(JSONReader::Read("[,]", true));
298 EXPECT_FALSE(root.get());
299 root.reset(JSONReader::Read("[true,,]", true));
300 EXPECT_FALSE(root.get());
301 root.reset(JSONReader::Read("[,true,]", true));
302 EXPECT_FALSE(root.get());
303 root.reset(JSONReader::Read("[true,,false]", true));
304 EXPECT_FALSE(root.get());
tc@google.comce6a78d2008-07-29 09:01:31 +0900305
initial.commit3f4a7322008-07-27 06:49:38 +0900306 // Test objects
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900307 root.reset(JSONReader::Read("{}", false));
308 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900309 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
initial.commit3f4a7322008-07-27 06:49:38 +0900310
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900311 root.reset(JSONReader::Read(
312 "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }",
tc@google.comce6a78d2008-07-29 09:01:31 +0900313 false));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900314 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900315 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900316 DictionaryValue* dict_val = static_cast<DictionaryValue*>(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900317 real_val = 0.0;
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900318 ASSERT_TRUE(dict_val->GetReal(L"number", &real_val));
initial.commit3f4a7322008-07-27 06:49:38 +0900319 ASSERT_DOUBLE_EQ(9.87654321, real_val);
320 Value* null_val = NULL;
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900321 ASSERT_TRUE(dict_val->Get(L"null", &null_val));
initial.commit3f4a7322008-07-27 06:49:38 +0900322 ASSERT_TRUE(null_val->IsType(Value::TYPE_NULL));
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900323 str_val.clear();
324 ASSERT_TRUE(dict_val->GetString(L"S", &str_val));
325 ASSERT_EQ(L"str", str_val);
tc@google.comce6a78d2008-07-29 09:01:31 +0900326
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900327 root2.reset(JSONReader::Read(
328 "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", }", true));
mark@chromium.org95c9ec92009-06-27 06:17:24 +0900329 ASSERT_TRUE(root2.get());
330 EXPECT_TRUE(root->Equals(root2.get()));
331
332 // Test newline equivalence.
333 root2.reset(JSONReader::Read(
334 "{\n"
335 " \"number\":9.87654321,\n"
336 " \"null\":null,\n"
337 " \"\\x53\":\"str\",\n"
338 "}\n", true));
339 ASSERT_TRUE(root2.get());
340 EXPECT_TRUE(root->Equals(root2.get()));
341
342 root2.reset(JSONReader::Read(
343 "{\r\n"
344 " \"number\":9.87654321,\r\n"
345 " \"null\":null,\r\n"
346 " \"\\x53\":\"str\",\r\n"
347 "}\r\n", true));
348 ASSERT_TRUE(root2.get());
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900349 EXPECT_TRUE(root->Equals(root2.get()));
initial.commit3f4a7322008-07-27 06:49:38 +0900350
351 // Test nesting
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900352 root.reset(JSONReader::Read(
353 "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}", false));
354 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900355 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900356 dict_val = static_cast<DictionaryValue*>(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900357 DictionaryValue* inner_dict = NULL;
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900358 ASSERT_TRUE(dict_val->GetDictionary(L"inner", &inner_dict));
initial.commit3f4a7322008-07-27 06:49:38 +0900359 ListValue* inner_array = NULL;
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900360 ASSERT_TRUE(inner_dict->GetList(L"array", &inner_array));
darin@google.comf3272802008-08-15 05:27:29 +0900361 ASSERT_EQ(1U, inner_array->GetSize());
tc@google.comce6a78d2008-07-29 09:01:31 +0900362 bool_value = true;
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900363 ASSERT_TRUE(dict_val->GetBoolean(L"false", &bool_value));
initial.commit3f4a7322008-07-27 06:49:38 +0900364 ASSERT_FALSE(bool_value);
365 inner_dict = NULL;
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900366 ASSERT_TRUE(dict_val->GetDictionary(L"d", &inner_dict));
tc@google.comce6a78d2008-07-29 09:01:31 +0900367
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900368 root2.reset(JSONReader::Read(
369 "{\"inner\": {\"array\":[true] , },\"false\":false,\"d\":{},}", true));
370 EXPECT_TRUE(root->Equals(root2.get()));
initial.commit3f4a7322008-07-27 06:49:38 +0900371
372 // Invalid, no closing brace
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900373 root.reset(JSONReader::Read("{\"a\": true", false));
374 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900375
376 // Invalid, keys must be quoted
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900377 root.reset(JSONReader::Read("{foo:true}", false));
378 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900379
380 // Invalid, trailing comma
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900381 root.reset(JSONReader::Read("{\"a\":true,}", false));
382 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900383
384 // Invalid, too many commas
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900385 root.reset(JSONReader::Read("{\"a\":true,,\"b\":false}", false));
386 ASSERT_FALSE(root.get());
387 root.reset(JSONReader::Read("{\"a\":true,,\"b\":false}", true));
388 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900389
390 // Invalid, no separator
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900391 root.reset(JSONReader::Read("{\"a\" \"b\"}", false));
392 ASSERT_FALSE(root.get());
tc@google.comce6a78d2008-07-29 09:01:31 +0900393
394 // Invalid, lone comma.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900395 root.reset(JSONReader::Read("{,}", false));
396 ASSERT_FALSE(root.get());
397 root.reset(JSONReader::Read("{,}", true));
398 ASSERT_FALSE(root.get());
399 root.reset(JSONReader::Read("{\"a\":true,,}", true));
400 ASSERT_FALSE(root.get());
401 root.reset(JSONReader::Read("{,\"a\":true}", true));
402 ASSERT_FALSE(root.get());
403 root.reset(JSONReader::Read("{\"a\":true,,\"b\":false}", true));
404 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900405
406 // Test stack overflow
initial.commit3f4a7322008-07-27 06:49:38 +0900407 std::string evil(1000000, '[');
408 evil.append(std::string(1000000, ']'));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900409 root.reset(JSONReader::Read(evil, false));
410 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900411
412 // A few thousand adjacent lists is fine.
413 std::string not_evil("[");
414 not_evil.reserve(15010);
415 for (int i = 0; i < 5000; ++i) {
416 not_evil.append("[],");
417 }
418 not_evil.append("[]]");
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900419 root.reset(JSONReader::Read(not_evil, false));
420 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900421 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900422 list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900423 ASSERT_EQ(5001U, list->GetSize());
initial.commit3f4a7322008-07-27 06:49:38 +0900424
425 // Test utf8 encoded input
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900426 root.reset(JSONReader().JsonToValue("\"\xe7\xbd\x91\xe9\xa1\xb5\"",
tc@google.comce6a78d2008-07-29 09:01:31 +0900427 false, false));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900428 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900429 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
430 str_val.clear();
431 ASSERT_TRUE(root->GetAsString(&str_val));
432 ASSERT_EQ(L"\x7f51\x9875", str_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900433
jungshik@google.com37790f32008-09-26 06:42:00 +0900434 // Test invalid utf8 encoded input
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900435 root.reset(JSONReader().JsonToValue("\"345\xb0\xa1\xb0\xa2\"",
436 false, false));
437 ASSERT_FALSE(root.get());
438 root.reset(JSONReader().JsonToValue("\"123\xc0\x81\"",
439 false, false));
440 ASSERT_FALSE(root.get());
jungshik@google.com37790f32008-09-26 06:42:00 +0900441
initial.commit3f4a7322008-07-27 06:49:38 +0900442 // Test invalid root objects.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900443 root.reset(JSONReader::Read("null", false));
444 ASSERT_FALSE(root.get());
445 root.reset(JSONReader::Read("true", false));
446 ASSERT_FALSE(root.get());
447 root.reset(JSONReader::Read("10", false));
448 ASSERT_FALSE(root.get());
449 root.reset(JSONReader::Read("\"root\"", false));
450 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900451}
aa@chromium.org971901c2008-12-06 07:14:46 +0900452
453TEST(JSONReaderTest, ErrorMessages) {
454 // Error strings should not be modified in case of success.
455 std::string error_message;
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900456 scoped_ptr<Value> root;
457 root.reset(JSONReader::ReadAndReturnError("[42]", false, &error_message));
aa@chromium.org09941d42008-12-24 11:07:48 +0900458 EXPECT_TRUE(error_message.empty());
aa@chromium.org971901c2008-12-06 07:14:46 +0900459
460 // Test line and column counting
461 const char* big_json = "[\n0,\n1,\n2,\n3,4,5,6 7,\n8,\n9\n]";
462 // error here --------------------------------^
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900463 root.reset(JSONReader::ReadAndReturnError(big_json, false, &error_message));
464 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900465 EXPECT_EQ(JSONReader::FormatErrorMessage(5, 9, JSONReader::kSyntaxError),
aa@chromium.org971901c2008-12-06 07:14:46 +0900466 error_message);
467
468 // Test each of the error conditions
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900469 root.reset(JSONReader::ReadAndReturnError("{},{}", false, &error_message));
470 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900471 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 3,
aa@chromium.org971901c2008-12-06 07:14:46 +0900472 JSONReader::kUnexpectedDataAfterRoot), error_message);
473
474 std::string nested_json;
475 for (int i = 0; i < 101; ++i) {
476 nested_json.insert(nested_json.begin(), '[');
477 nested_json.append(1, ']');
478 }
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900479 root.reset(JSONReader::ReadAndReturnError(nested_json, false,
480 &error_message));
481 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900482 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 101, JSONReader::kTooMuchNesting),
aa@chromium.org971901c2008-12-06 07:14:46 +0900483 error_message);
484
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900485 root.reset(JSONReader::ReadAndReturnError("42", false, &error_message));
486 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900487 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 1,
aa@chromium.org971901c2008-12-06 07:14:46 +0900488 JSONReader::kBadRootElementType), error_message);
489
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900490 root.reset(JSONReader::ReadAndReturnError("[1,]", false, &error_message));
491 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900492 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 4, JSONReader::kTrailingComma),
aa@chromium.org971901c2008-12-06 07:14:46 +0900493 error_message);
494
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900495 root.reset(JSONReader::ReadAndReturnError("{foo:\"bar\"}", false,
496 &error_message));
497 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900498 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 2,
aa@chromium.org971901c2008-12-06 07:14:46 +0900499 JSONReader::kUnquotedDictionaryKey), error_message);
500
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900501 root.reset(JSONReader::ReadAndReturnError("{\"foo\":\"bar\",}", false,
502 &error_message));
503 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900504 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 14, JSONReader::kTrailingComma),
aa@chromium.org971901c2008-12-06 07:14:46 +0900505 error_message);
506
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900507 root.reset(JSONReader::ReadAndReturnError("[nu]", false, &error_message));
508 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900509 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 2, JSONReader::kSyntaxError),
aa@chromium.org971901c2008-12-06 07:14:46 +0900510 error_message);
511
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900512 root.reset(JSONReader::ReadAndReturnError("[\"xxx\\xq\"]", false,
513 &error_message));
514 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900515 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
aa@chromium.org971901c2008-12-06 07:14:46 +0900516 error_message);
517
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900518 root.reset(JSONReader::ReadAndReturnError("[\"xxx\\uq\"]", false,
519 &error_message));
520 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900521 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
aa@chromium.org971901c2008-12-06 07:14:46 +0900522 error_message);
523
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900524 root.reset(JSONReader::ReadAndReturnError("[\"xxx\\q\"]", false,
525 &error_message));
526 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900527 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
aa@chromium.org971901c2008-12-06 07:14:46 +0900528 error_message);
aa@chromium.org09941d42008-12-24 11:07:48 +0900529
aa@chromium.org971901c2008-12-06 07:14:46 +0900530}