blob: a7aeaf0f5569fb7ca776af264d2a4eb2d99f97f2 [file] [log] [blame]
levin@chromium.org5c528682011-03-28 10:54:15 +09001// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botf003cfe2008-08-24 09:55:55 +09002// 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"
brettw@chromium.org7cd41eb2009-10-24 05:00:20 +09006#include "base/json/json_reader.h"
levin@chromium.org5c528682011-03-28 10:54:15 +09007#include "base/memory/scoped_ptr.h"
viettrungluu@chromium.org68354652010-08-16 16:13:53 +09008#include "base/string_piece.h"
9#include "base/utf_string_conversions.h"
initial.commit3f4a7322008-07-27 06:49:38 +090010#include "base/values.h"
tc@google.comd3bb16f2008-08-09 02:26:42 +090011#include "build/build_config.h"
initial.commit3f4a7322008-07-27 06:49:38 +090012
brettw@chromium.org7cd41eb2009-10-24 05:00:20 +090013namespace base {
14
initial.commit3f4a7322008-07-27 06:49:38 +090015TEST(JSONReaderTest, Reading) {
16 // some whitespace checking
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090017 scoped_ptr<Value> root;
18 root.reset(JSONReader().JsonToValue(" null ", false, false));
19 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090020 ASSERT_TRUE(root->IsType(Value::TYPE_NULL));
initial.commit3f4a7322008-07-27 06:49:38 +090021
22 // Invalid JSON string
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090023 root.reset(JSONReader().JsonToValue("nu", false, false));
24 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090025
26 // Simple bool
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090027 root.reset(JSONReader().JsonToValue("true ", false, false));
28 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090029 ASSERT_TRUE(root->IsType(Value::TYPE_BOOLEAN));
initial.commit3f4a7322008-07-27 06:49:38 +090030
munjal@chromium.org124260d2009-07-24 06:34:40 +090031 // Embedded comment
32 root.reset(JSONReader().JsonToValue("/* comment */null", false, false));
33 ASSERT_TRUE(root.get());
34 ASSERT_TRUE(root->IsType(Value::TYPE_NULL));
35 root.reset(JSONReader().JsonToValue("40 /* comment */", false, false));
36 ASSERT_TRUE(root.get());
37 ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
38 root.reset(JSONReader().JsonToValue("true // comment", false, false));
39 ASSERT_TRUE(root.get());
40 ASSERT_TRUE(root->IsType(Value::TYPE_BOOLEAN));
41 root.reset(JSONReader().JsonToValue("/* comment */\"sample string\"",
42 false, false));
43 ASSERT_TRUE(root.get());
44 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
45 std::string value;
46 ASSERT_TRUE(root->GetAsString(&value));
47 ASSERT_EQ("sample string", value);
48
initial.commit3f4a7322008-07-27 06:49:38 +090049 // Test number formats
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090050 root.reset(JSONReader().JsonToValue("43", false, false));
51 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090052 ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
53 int int_val = 0;
54 ASSERT_TRUE(root->GetAsInteger(&int_val));
55 ASSERT_EQ(43, int_val);
initial.commit3f4a7322008-07-27 06:49:38 +090056
57 // According to RFC4627, oct, hex, and leading zeros are invalid JSON.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090058 root.reset(JSONReader().JsonToValue("043", false, false));
59 ASSERT_FALSE(root.get());
60 root.reset(JSONReader().JsonToValue("0x43", false, false));
61 ASSERT_FALSE(root.get());
62 root.reset(JSONReader().JsonToValue("00", false, false));
63 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090064
65 // Test 0 (which needs to be special cased because of the leading zero
66 // clause).
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090067 root.reset(JSONReader().JsonToValue("0", false, false));
68 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +090069 ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
70 int_val = 1;
71 ASSERT_TRUE(root->GetAsInteger(&int_val));
72 ASSERT_EQ(0, int_val);
initial.commit3f4a7322008-07-27 06:49:38 +090073
mmentovai@google.com8dcf71c2008-08-08 02:15:41 +090074 // Numbers that overflow ints should succeed, being internally promoted to
75 // storage as doubles
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090076 root.reset(JSONReader().JsonToValue("2147483648", false, false));
77 ASSERT_TRUE(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +090078 double double_val;
79 ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
80 double_val = 0.0;
81 ASSERT_TRUE(root->GetAsDouble(&double_val));
82 ASSERT_DOUBLE_EQ(2147483648.0, double_val);
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090083 root.reset(JSONReader().JsonToValue("-2147483649", false, false));
84 ASSERT_TRUE(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +090085 ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
86 double_val = 0.0;
87 ASSERT_TRUE(root->GetAsDouble(&double_val));
88 ASSERT_DOUBLE_EQ(-2147483649.0, double_val);
initial.commit3f4a7322008-07-27 06:49:38 +090089
90 // Parse a double
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090091 root.reset(JSONReader().JsonToValue("43.1", false, false));
92 ASSERT_TRUE(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +090093 ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
94 double_val = 0.0;
95 ASSERT_TRUE(root->GetAsDouble(&double_val));
96 ASSERT_DOUBLE_EQ(43.1, double_val);
initial.commit3f4a7322008-07-27 06:49:38 +090097
aa@chromium.orgca9c79e2008-12-30 04:59:08 +090098 root.reset(JSONReader().JsonToValue("4.3e-1", false, false));
99 ASSERT_TRUE(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +0900100 ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
101 double_val = 0.0;
102 ASSERT_TRUE(root->GetAsDouble(&double_val));
103 ASSERT_DOUBLE_EQ(.43, double_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900104
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900105 root.reset(JSONReader().JsonToValue("2.1e0", false, false));
106 ASSERT_TRUE(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +0900107 ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
108 double_val = 0.0;
109 ASSERT_TRUE(root->GetAsDouble(&double_val));
110 ASSERT_DOUBLE_EQ(2.1, double_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900111
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900112 root.reset(JSONReader().JsonToValue("2.1e+0001", false, false));
113 ASSERT_TRUE(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +0900114 ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
115 double_val = 0.0;
116 ASSERT_TRUE(root->GetAsDouble(&double_val));
117 ASSERT_DOUBLE_EQ(21.0, double_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900118
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900119 root.reset(JSONReader().JsonToValue("0.01", false, false));
120 ASSERT_TRUE(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +0900121 ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
122 double_val = 0.0;
123 ASSERT_TRUE(root->GetAsDouble(&double_val));
124 ASSERT_DOUBLE_EQ(0.01, double_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900125
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900126 root.reset(JSONReader().JsonToValue("1.00", false, false));
127 ASSERT_TRUE(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +0900128 ASSERT_TRUE(root->IsType(Value::TYPE_DOUBLE));
129 double_val = 0.0;
130 ASSERT_TRUE(root->GetAsDouble(&double_val));
131 ASSERT_DOUBLE_EQ(1.0, double_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900132
133 // Fractional parts must have a digit before and after the decimal point.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900134 root.reset(JSONReader().JsonToValue("1.", false, false));
135 ASSERT_FALSE(root.get());
136 root.reset(JSONReader().JsonToValue(".1", false, false));
137 ASSERT_FALSE(root.get());
138 root.reset(JSONReader().JsonToValue("1.e10", false, false));
139 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900140
141 // Exponent must have a digit following the 'e'.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900142 root.reset(JSONReader().JsonToValue("1e", false, false));
143 ASSERT_FALSE(root.get());
144 root.reset(JSONReader().JsonToValue("1E", false, false));
145 ASSERT_FALSE(root.get());
146 root.reset(JSONReader().JsonToValue("1e1.", false, false));
147 ASSERT_FALSE(root.get());
148 root.reset(JSONReader().JsonToValue("1e1.0", false, false));
149 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900150
151 // INF/-INF/NaN are not valid
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900152 root.reset(JSONReader().JsonToValue("1e1000", false, false));
153 ASSERT_FALSE(root.get());
154 root.reset(JSONReader().JsonToValue("-1e1000", false, false));
155 ASSERT_FALSE(root.get());
156 root.reset(JSONReader().JsonToValue("NaN", false, false));
157 ASSERT_FALSE(root.get());
158 root.reset(JSONReader().JsonToValue("nan", false, false));
159 ASSERT_FALSE(root.get());
160 root.reset(JSONReader().JsonToValue("inf", false, false));
161 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900162
163 // Invalid number formats
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900164 root.reset(JSONReader().JsonToValue("4.3.1", false, false));
165 ASSERT_FALSE(root.get());
166 root.reset(JSONReader().JsonToValue("4e3.1", false, false));
167 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900168
169 // Test string parser
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900170 root.reset(JSONReader().JsonToValue("\"hello world\"", false, false));
171 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900172 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
viettrungluu@chromium.org68354652010-08-16 16:13:53 +0900173 std::string str_val;
initial.commit3f4a7322008-07-27 06:49:38 +0900174 ASSERT_TRUE(root->GetAsString(&str_val));
viettrungluu@chromium.org68354652010-08-16 16:13:53 +0900175 ASSERT_EQ("hello world", str_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900176
177 // Empty string
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900178 root.reset(JSONReader().JsonToValue("\"\"", false, false));
179 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900180 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
181 str_val.clear();
182 ASSERT_TRUE(root->GetAsString(&str_val));
viettrungluu@chromium.org68354652010-08-16 16:13:53 +0900183 ASSERT_EQ("", str_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900184
185 // Test basic string escapes
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900186 root.reset(JSONReader().JsonToValue("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\\v\"",
187 false, false));
188 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900189 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
190 str_val.clear();
191 ASSERT_TRUE(root->GetAsString(&str_val));
viettrungluu@chromium.org68354652010-08-16 16:13:53 +0900192 ASSERT_EQ(" \"\\/\b\f\n\r\t\v", str_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900193
194 // Test hex and unicode escapes including the null character.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900195 root.reset(JSONReader().JsonToValue("\"\\x41\\x00\\u1234\"", false,
tc@google.comce6a78d2008-07-29 09:01:31 +0900196 false));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900197 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900198 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
199 str_val.clear();
200 ASSERT_TRUE(root->GetAsString(&str_val));
viettrungluu@chromium.org68354652010-08-16 16:13:53 +0900201 ASSERT_EQ(std::wstring(L"A\0\x1234", 3), UTF8ToWide(str_val));
initial.commit3f4a7322008-07-27 06:49:38 +0900202
203 // Test invalid strings
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900204 root.reset(JSONReader().JsonToValue("\"no closing quote", false, false));
205 ASSERT_FALSE(root.get());
206 root.reset(JSONReader().JsonToValue("\"\\z invalid escape char\"", false,
207 false));
208 ASSERT_FALSE(root.get());
209 root.reset(JSONReader().JsonToValue("\"\\xAQ invalid hex code\"", false,
210 false));
211 ASSERT_FALSE(root.get());
212 root.reset(JSONReader().JsonToValue("not enough hex chars\\x1\"", false,
213 false));
214 ASSERT_FALSE(root.get());
215 root.reset(JSONReader().JsonToValue("\"not enough escape chars\\u123\"",
216 false, false));
217 ASSERT_FALSE(root.get());
218 root.reset(JSONReader().JsonToValue("\"extra backslash at end of input\\\"",
219 false, false));
220 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900221
222 // Basic array
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900223 root.reset(JSONReader::Read("[true, false, null]", false));
224 ASSERT_TRUE(root.get());
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900225 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
226 ListValue* list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900227 ASSERT_EQ(3U, list->GetSize());
tc@google.comce6a78d2008-07-29 09:01:31 +0900228
229 // Test with trailing comma. Should be parsed the same as above.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900230 scoped_ptr<Value> root2;
231 root2.reset(JSONReader::Read("[true, false, null, ]", true));
232 EXPECT_TRUE(root->Equals(root2.get()));
initial.commit3f4a7322008-07-27 06:49:38 +0900233
234 // Empty array
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900235 root.reset(JSONReader::Read("[]", false));
236 ASSERT_TRUE(root.get());
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900237 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
238 list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900239 ASSERT_EQ(0U, list->GetSize());
initial.commit3f4a7322008-07-27 06:49:38 +0900240
241 // Nested arrays
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900242 root.reset(JSONReader::Read("[[true], [], [false, [], [null]], null]",
243 false));
244 ASSERT_TRUE(root.get());
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900245 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
246 list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900247 ASSERT_EQ(4U, list->GetSize());
tc@google.comce6a78d2008-07-29 09:01:31 +0900248
249 // Lots of trailing commas.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900250 root2.reset(JSONReader::Read("[[true], [], [false, [], [null, ] , ], null,]",
251 true));
252 EXPECT_TRUE(root->Equals(root2.get()));
initial.commit3f4a7322008-07-27 06:49:38 +0900253
254 // Invalid, missing close brace.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900255 root.reset(JSONReader::Read("[[true], [], [false, [], [null]], null", false));
256 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900257
258 // Invalid, too many commas
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900259 root.reset(JSONReader::Read("[true,, null]", false));
260 ASSERT_FALSE(root.get());
261 root.reset(JSONReader::Read("[true,, null]", true));
262 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900263
264 // Invalid, no commas
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900265 root.reset(JSONReader::Read("[true null]", false));
266 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900267
268 // Invalid, trailing comma
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900269 root.reset(JSONReader::Read("[true,]", false));
270 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900271
tc@google.comce6a78d2008-07-29 09:01:31 +0900272 // Valid if we set |allow_trailing_comma| to true.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900273 root.reset(JSONReader::Read("[true,]", true));
274 ASSERT_TRUE(root.get());
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900275 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
276 list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900277 EXPECT_EQ(1U, list->GetSize());
tc@google.comce6a78d2008-07-29 09:01:31 +0900278 Value* tmp_value = NULL;
279 ASSERT_TRUE(list->Get(0, &tmp_value));
280 EXPECT_TRUE(tmp_value->IsType(Value::TYPE_BOOLEAN));
281 bool bool_value = false;
282 ASSERT_TRUE(tmp_value->GetAsBoolean(&bool_value));
283 EXPECT_TRUE(bool_value);
tc@google.comce6a78d2008-07-29 09:01:31 +0900284
285 // Don't allow empty elements, even if |allow_trailing_comma| is
286 // true.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900287 root.reset(JSONReader::Read("[,]", true));
288 EXPECT_FALSE(root.get());
289 root.reset(JSONReader::Read("[true,,]", true));
290 EXPECT_FALSE(root.get());
291 root.reset(JSONReader::Read("[,true,]", true));
292 EXPECT_FALSE(root.get());
293 root.reset(JSONReader::Read("[true,,false]", true));
294 EXPECT_FALSE(root.get());
tc@google.comce6a78d2008-07-29 09:01:31 +0900295
initial.commit3f4a7322008-07-27 06:49:38 +0900296 // Test objects
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900297 root.reset(JSONReader::Read("{}", false));
298 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900299 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
initial.commit3f4a7322008-07-27 06:49:38 +0900300
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900301 root.reset(JSONReader::Read(
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900302 "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }", false));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900303 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900304 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900305 DictionaryValue* dict_val = static_cast<DictionaryValue*>(root.get());
arv@chromium.org13413eb2011-02-01 10:02:07 +0900306 double_val = 0.0;
307 ASSERT_TRUE(dict_val->GetDouble("number", &double_val));
308 ASSERT_DOUBLE_EQ(9.87654321, double_val);
initial.commit3f4a7322008-07-27 06:49:38 +0900309 Value* null_val = NULL;
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900310 ASSERT_TRUE(dict_val->Get("null", &null_val));
initial.commit3f4a7322008-07-27 06:49:38 +0900311 ASSERT_TRUE(null_val->IsType(Value::TYPE_NULL));
nsylvain@chromium.org12426672009-03-04 07:59:43 +0900312 str_val.clear();
viettrungluu@chromium.org68354652010-08-16 16:13:53 +0900313 ASSERT_TRUE(dict_val->GetString("S", &str_val));
314 ASSERT_EQ("str", str_val);
tc@google.comce6a78d2008-07-29 09:01:31 +0900315
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900316 root2.reset(JSONReader::Read(
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900317 "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", }", true));
mark@chromium.org95c9ec92009-06-27 06:17:24 +0900318 ASSERT_TRUE(root2.get());
319 EXPECT_TRUE(root->Equals(root2.get()));
320
321 // Test newline equivalence.
322 root2.reset(JSONReader::Read(
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900323 "{\n"
324 " \"number\":9.87654321,\n"
325 " \"null\":null,\n"
326 " \"\\x53\":\"str\",\n"
327 "}\n", true));
mark@chromium.org95c9ec92009-06-27 06:17:24 +0900328 ASSERT_TRUE(root2.get());
329 EXPECT_TRUE(root->Equals(root2.get()));
330
331 root2.reset(JSONReader::Read(
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900332 "{\r\n"
333 " \"number\":9.87654321,\r\n"
334 " \"null\":null,\r\n"
335 " \"\\x53\":\"str\",\r\n"
336 "}\r\n", true));
mark@chromium.org95c9ec92009-06-27 06:17:24 +0900337 ASSERT_TRUE(root2.get());
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900338 EXPECT_TRUE(root->Equals(root2.get()));
initial.commit3f4a7322008-07-27 06:49:38 +0900339
340 // Test nesting
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900341 root.reset(JSONReader::Read(
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900342 "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}", false));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900343 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900344 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900345 dict_val = static_cast<DictionaryValue*>(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900346 DictionaryValue* inner_dict = NULL;
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900347 ASSERT_TRUE(dict_val->GetDictionary("inner", &inner_dict));
initial.commit3f4a7322008-07-27 06:49:38 +0900348 ListValue* inner_array = NULL;
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900349 ASSERT_TRUE(inner_dict->GetList("array", &inner_array));
darin@google.comf3272802008-08-15 05:27:29 +0900350 ASSERT_EQ(1U, inner_array->GetSize());
tc@google.comce6a78d2008-07-29 09:01:31 +0900351 bool_value = true;
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900352 ASSERT_TRUE(dict_val->GetBoolean("false", &bool_value));
initial.commit3f4a7322008-07-27 06:49:38 +0900353 ASSERT_FALSE(bool_value);
354 inner_dict = NULL;
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900355 ASSERT_TRUE(dict_val->GetDictionary("d", &inner_dict));
tc@google.comce6a78d2008-07-29 09:01:31 +0900356
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900357 root2.reset(JSONReader::Read(
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900358 "{\"inner\": {\"array\":[true] , },\"false\":false,\"d\":{},}", true));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900359 EXPECT_TRUE(root->Equals(root2.get()));
initial.commit3f4a7322008-07-27 06:49:38 +0900360
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900361 // Test keys with periods
362 root.reset(JSONReader::Read(
363 "{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}", false));
364 ASSERT_TRUE(root.get());
365 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
366 dict_val = static_cast<DictionaryValue*>(root.get());
367 int integer_value = 0;
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900368 EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion("a.b", &integer_value));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900369 EXPECT_EQ(3, integer_value);
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900370 EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion("c", &integer_value));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900371 EXPECT_EQ(2, integer_value);
372 inner_dict = NULL;
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900373 ASSERT_TRUE(dict_val->GetDictionaryWithoutPathExpansion("d.e.f",
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900374 &inner_dict));
375 ASSERT_EQ(1U, inner_dict->size());
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900376 EXPECT_TRUE(inner_dict->GetIntegerWithoutPathExpansion("g.h.i.j",
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900377 &integer_value));
378 EXPECT_EQ(1, integer_value);
379
380 root.reset(JSONReader::Read("{\"a\":{\"b\":2},\"a.b\":1}", false));
381 ASSERT_TRUE(root.get());
382 ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
383 dict_val = static_cast<DictionaryValue*>(root.get());
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900384 EXPECT_TRUE(dict_val->GetInteger("a.b", &integer_value));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900385 EXPECT_EQ(2, integer_value);
viettrungluu@chromium.org4603a8d2010-08-14 10:49:14 +0900386 EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion("a.b", &integer_value));
pkasting@chromium.org36515db2009-11-26 05:47:52 +0900387 EXPECT_EQ(1, integer_value);
388
initial.commit3f4a7322008-07-27 06:49:38 +0900389 // Invalid, no closing brace
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900390 root.reset(JSONReader::Read("{\"a\": true", false));
391 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900392
393 // Invalid, keys must be quoted
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900394 root.reset(JSONReader::Read("{foo:true}", false));
395 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900396
397 // Invalid, trailing comma
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900398 root.reset(JSONReader::Read("{\"a\":true,}", false));
399 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900400
401 // Invalid, too many commas
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900402 root.reset(JSONReader::Read("{\"a\":true,,\"b\":false}", false));
403 ASSERT_FALSE(root.get());
404 root.reset(JSONReader::Read("{\"a\":true,,\"b\":false}", true));
405 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900406
407 // Invalid, no separator
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900408 root.reset(JSONReader::Read("{\"a\" \"b\"}", false));
409 ASSERT_FALSE(root.get());
tc@google.comce6a78d2008-07-29 09:01:31 +0900410
411 // Invalid, lone comma.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900412 root.reset(JSONReader::Read("{,}", false));
413 ASSERT_FALSE(root.get());
414 root.reset(JSONReader::Read("{,}", true));
415 ASSERT_FALSE(root.get());
416 root.reset(JSONReader::Read("{\"a\":true,,}", true));
417 ASSERT_FALSE(root.get());
418 root.reset(JSONReader::Read("{,\"a\":true}", true));
419 ASSERT_FALSE(root.get());
420 root.reset(JSONReader::Read("{\"a\":true,,\"b\":false}", true));
421 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900422
423 // Test stack overflow
initial.commit3f4a7322008-07-27 06:49:38 +0900424 std::string evil(1000000, '[');
425 evil.append(std::string(1000000, ']'));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900426 root.reset(JSONReader::Read(evil, false));
427 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900428
429 // A few thousand adjacent lists is fine.
430 std::string not_evil("[");
431 not_evil.reserve(15010);
432 for (int i = 0; i < 5000; ++i) {
433 not_evil.append("[],");
434 }
435 not_evil.append("[]]");
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900436 root.reset(JSONReader::Read(not_evil, false));
437 ASSERT_TRUE(root.get());
stevenjb@google.comf4f58272011-08-26 10:54:00 +0900438 ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
439 list = static_cast<ListValue*>(root.get());
darin@google.comf3272802008-08-15 05:27:29 +0900440 ASSERT_EQ(5001U, list->GetSize());
initial.commit3f4a7322008-07-27 06:49:38 +0900441
442 // Test utf8 encoded input
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900443 root.reset(JSONReader().JsonToValue("\"\xe7\xbd\x91\xe9\xa1\xb5\"",
tc@google.comce6a78d2008-07-29 09:01:31 +0900444 false, false));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900445 ASSERT_TRUE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900446 ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
447 str_val.clear();
448 ASSERT_TRUE(root->GetAsString(&str_val));
viettrungluu@chromium.org68354652010-08-16 16:13:53 +0900449 ASSERT_EQ(L"\x7f51\x9875", UTF8ToWide(str_val));
initial.commit3f4a7322008-07-27 06:49:38 +0900450
jungshik@google.com37790f32008-09-26 06:42:00 +0900451 // Test invalid utf8 encoded input
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900452 root.reset(JSONReader().JsonToValue("\"345\xb0\xa1\xb0\xa2\"",
453 false, false));
454 ASSERT_FALSE(root.get());
455 root.reset(JSONReader().JsonToValue("\"123\xc0\x81\"",
456 false, false));
457 ASSERT_FALSE(root.get());
jungshik@google.com37790f32008-09-26 06:42:00 +0900458
initial.commit3f4a7322008-07-27 06:49:38 +0900459 // Test invalid root objects.
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900460 root.reset(JSONReader::Read("null", false));
461 ASSERT_FALSE(root.get());
462 root.reset(JSONReader::Read("true", false));
463 ASSERT_FALSE(root.get());
464 root.reset(JSONReader::Read("10", false));
465 ASSERT_FALSE(root.get());
466 root.reset(JSONReader::Read("\"root\"", false));
467 ASSERT_FALSE(root.get());
initial.commit3f4a7322008-07-27 06:49:38 +0900468}
aa@chromium.org971901c2008-12-06 07:14:46 +0900469
470TEST(JSONReaderTest, ErrorMessages) {
471 // Error strings should not be modified in case of success.
472 std::string error_message;
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900473 int error_code = 0;
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900474 scoped_ptr<Value> root;
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900475 root.reset(JSONReader::ReadAndReturnError("[42]", false,
476 &error_code, &error_message));
aa@chromium.org09941d42008-12-24 11:07:48 +0900477 EXPECT_TRUE(error_message.empty());
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900478 EXPECT_EQ(0, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900479
480 // Test line and column counting
481 const char* big_json = "[\n0,\n1,\n2,\n3,4,5,6 7,\n8,\n9\n]";
482 // error here --------------------------------^
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900483 root.reset(JSONReader::ReadAndReturnError(big_json, false,
484 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900485 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900486 EXPECT_EQ(JSONReader::FormatErrorMessage(5, 9, JSONReader::kSyntaxError),
aa@chromium.org971901c2008-12-06 07:14:46 +0900487 error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900488 EXPECT_EQ(JSONReader::JSON_SYNTAX_ERROR, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900489
490 // Test each of the error conditions
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900491 root.reset(JSONReader::ReadAndReturnError("{},{}", false,
492 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900493 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900494 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 3,
aa@chromium.org971901c2008-12-06 07:14:46 +0900495 JSONReader::kUnexpectedDataAfterRoot), error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900496 EXPECT_EQ(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900497
498 std::string nested_json;
499 for (int i = 0; i < 101; ++i) {
500 nested_json.insert(nested_json.begin(), '[');
501 nested_json.append(1, ']');
502 }
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900503 root.reset(JSONReader::ReadAndReturnError(nested_json, false,
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900504 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900505 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900506 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 101, JSONReader::kTooMuchNesting),
aa@chromium.org971901c2008-12-06 07:14:46 +0900507 error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900508 EXPECT_EQ(JSONReader::JSON_TOO_MUCH_NESTING, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900509
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900510 root.reset(JSONReader::ReadAndReturnError("42", false,
511 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900512 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900513 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 1,
aa@chromium.org971901c2008-12-06 07:14:46 +0900514 JSONReader::kBadRootElementType), error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900515 EXPECT_EQ(JSONReader::JSON_BAD_ROOT_ELEMENT_TYPE, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900516
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900517 root.reset(JSONReader::ReadAndReturnError("[1,]", false,
518 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900519 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900520 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 4, JSONReader::kTrailingComma),
aa@chromium.org971901c2008-12-06 07:14:46 +0900521 error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900522 EXPECT_EQ(JSONReader::JSON_TRAILING_COMMA, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900523
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900524 root.reset(JSONReader::ReadAndReturnError("{foo:\"bar\"}", false,
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900525 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900526 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900527 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 2,
aa@chromium.org971901c2008-12-06 07:14:46 +0900528 JSONReader::kUnquotedDictionaryKey), error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900529 EXPECT_EQ(JSONReader::JSON_UNQUOTED_DICTIONARY_KEY, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900530
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900531 root.reset(JSONReader::ReadAndReturnError("{\"foo\":\"bar\",}", false,
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900532 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900533 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900534 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 14, JSONReader::kTrailingComma),
aa@chromium.org971901c2008-12-06 07:14:46 +0900535 error_message);
536
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900537 root.reset(JSONReader::ReadAndReturnError("[nu]", false,
538 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900539 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900540 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 2, JSONReader::kSyntaxError),
aa@chromium.org971901c2008-12-06 07:14:46 +0900541 error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900542 EXPECT_EQ(JSONReader::JSON_SYNTAX_ERROR, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900543
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900544 root.reset(JSONReader::ReadAndReturnError("[\"xxx\\xq\"]", false,
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900545 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900546 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900547 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
aa@chromium.org971901c2008-12-06 07:14:46 +0900548 error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900549 EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900550
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900551 root.reset(JSONReader::ReadAndReturnError("[\"xxx\\uq\"]", false,
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900552 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900553 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900554 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
aa@chromium.org971901c2008-12-06 07:14:46 +0900555 error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900556 EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900557
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900558 root.reset(JSONReader::ReadAndReturnError("[\"xxx\\q\"]", false,
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900559 &error_code, &error_message));
aa@chromium.orgca9c79e2008-12-30 04:59:08 +0900560 EXPECT_FALSE(root.get());
aa@chromium.org09941d42008-12-24 11:07:48 +0900561 EXPECT_EQ(JSONReader::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
aa@chromium.org971901c2008-12-06 07:14:46 +0900562 error_message);
erikkay@chromium.org64b2cf42010-04-07 00:42:39 +0900563 EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code);
aa@chromium.org971901c2008-12-06 07:14:46 +0900564}
brettw@chromium.org7cd41eb2009-10-24 05:00:20 +0900565
566} // namespace base