xref: /aosp_15_r20/external/cronet/base/json/json_reader_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/json/json_reader.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <cmath>
10*6777b538SAndroid Build Coastguard Worker #include <string_view>
11*6777b538SAndroid Build Coastguard Worker #include <utility>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include "base/base_paths.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/features.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/path_service.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/rust_buildflags.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/test/gmock_expected_support.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/test/metrics/histogram_tester.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/test/scoped_feature_list.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/values.h"
25*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
26*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
27*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker namespace {
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker // MSan will do a better job detecting over-read errors if the input is not
32*6777b538SAndroid Build Coastguard Worker // nul-terminated on the heap. This will copy |input| to a new buffer owned by
33*6777b538SAndroid Build Coastguard Worker // |owner|, returning a std::string_view to |owner|.
MakeNotNullTerminatedInput(const char * input,std::unique_ptr<char[]> * owner)34*6777b538SAndroid Build Coastguard Worker std::string_view MakeNotNullTerminatedInput(const char* input,
35*6777b538SAndroid Build Coastguard Worker                                             std::unique_ptr<char[]>* owner) {
36*6777b538SAndroid Build Coastguard Worker   size_t str_len = strlen(input);
37*6777b538SAndroid Build Coastguard Worker   owner->reset(new char[str_len]);
38*6777b538SAndroid Build Coastguard Worker   memcpy(owner->get(), input, str_len);
39*6777b538SAndroid Build Coastguard Worker   return std::string_view(owner->get(), str_len);
40*6777b538SAndroid Build Coastguard Worker }
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker }  // namespace
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker namespace base {
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker class JSONReaderTest : public testing::TestWithParam<bool> {
47*6777b538SAndroid Build Coastguard Worker  public:
SetUp()48*6777b538SAndroid Build Coastguard Worker   void SetUp() override {
49*6777b538SAndroid Build Coastguard Worker     feature_list_.InitWithFeatureState(base::features::kUseRustJsonParser,
50*6777b538SAndroid Build Coastguard Worker                                        using_rust_);
51*6777b538SAndroid Build Coastguard Worker   }
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker  protected:
54*6777b538SAndroid Build Coastguard Worker   bool using_rust_ = GetParam();
55*6777b538SAndroid Build Coastguard Worker   base::test::ScopedFeatureList feature_list_;
56*6777b538SAndroid Build Coastguard Worker };
57*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,Whitespace)58*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, Whitespace) {
59*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("   null   ");
60*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
61*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_none());
62*6777b538SAndroid Build Coastguard Worker }
63*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,InvalidString)64*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidString) {
65*6777b538SAndroid Build Coastguard Worker   // These are invalid because they do not represent a JSON value,
66*6777b538SAndroid Build Coastguard Worker   // see https://tools.ietf.org/rfc/rfc8259.txt
67*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read(""));
68*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("nu"));
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,SimpleBool)71*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, SimpleBool) {
72*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(BUILD_RUST_JSON_READER)
73*6777b538SAndroid Build Coastguard Worker   base::HistogramTester histograms;
74*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(BUILD_RUST_JSON_READER)
75*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("true  ");
76*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
77*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_bool());
78*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(BUILD_RUST_JSON_READER)
79*6777b538SAndroid Build Coastguard Worker   histograms.ExpectTotalCount("Security.JSONParser.ParsingTime", 1);
80*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(BUILD_RUST_JSON_READER)
81*6777b538SAndroid Build Coastguard Worker }
82*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,EmbeddedComments)83*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, EmbeddedComments) {
84*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("/* comment */null");
85*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
86*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_none());
87*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("40 /* comment */");
88*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
89*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_int());
90*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("true // comment");
91*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
92*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_bool());
93*6777b538SAndroid Build Coastguard Worker   // Comments in different contexts.
94*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("{   \"cheese\": 3\n\n   // Here's a comment\n}");
95*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
96*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_dict());
97*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("{   \"cheese\": 3// Here's a comment\n}");
98*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
99*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_dict());
100*6777b538SAndroid Build Coastguard Worker   // Multiple comment markers.
101*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read(
102*6777b538SAndroid Build Coastguard Worker       "{   \"cheese\": 3// Here's a comment // and another\n}");
103*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
104*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_dict());
105*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("/* comment */\"sample string\"");
106*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
107*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
108*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("sample string", root->GetString());
109*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("[1, /* comment, 2 ] */ \n 3]");
110*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
111*6777b538SAndroid Build Coastguard Worker   Value::List* list = root->GetIfList();
112*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
113*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(2u, list->size());
114*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE((*list)[0].is_int());
115*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, (*list)[0].GetInt());
116*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE((*list)[1].is_int());
117*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3, (*list)[1].GetInt());
118*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("[1, /*a*/2, 3]");
119*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
120*6777b538SAndroid Build Coastguard Worker   list = root->GetIfList();
121*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
122*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3u, (*list).size());
123*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("/* comment **/42");
124*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
125*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_int());
126*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(42, root->GetInt());
127*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read(
128*6777b538SAndroid Build Coastguard Worker       "/* comment **/\n"
129*6777b538SAndroid Build Coastguard Worker       "// */ 43\n"
130*6777b538SAndroid Build Coastguard Worker       "44");
131*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
132*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_int());
133*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(44, root->GetInt());
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker   // At one point, this parsed successfully as the value three.
136*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("/33"));
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,Ints)139*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, Ints) {
140*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("43");
141*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
142*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_int());
143*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(43, root->GetInt());
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,NonDecimalNumbers)146*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, NonDecimalNumbers) {
147*6777b538SAndroid Build Coastguard Worker   // According to RFC 8259, oct, hex, and leading zeros are invalid JSON.
148*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("043"));
149*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("0x43"));
150*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("00"));
151*6777b538SAndroid Build Coastguard Worker }
152*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,NumberZero)153*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, NumberZero) {
154*6777b538SAndroid Build Coastguard Worker   // Test 0 (which needs to be special cased because of the leading zero
155*6777b538SAndroid Build Coastguard Worker   // clause).
156*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("0");
157*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
158*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_int());
159*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, root->GetInt());
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,LargeIntPromotion)162*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, LargeIntPromotion) {
163*6777b538SAndroid Build Coastguard Worker   // Numbers that overflow ints should succeed, being internally promoted to
164*6777b538SAndroid Build Coastguard Worker   // storage as doubles
165*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("2147483648");
166*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
167*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
168*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(2147483648.0, root->GetDouble());
169*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("-2147483649");
170*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
171*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
172*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(-2147483649.0, root->GetDouble());
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,LargerIntIsLossy)175*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, LargerIntIsLossy) {
176*6777b538SAndroid Build Coastguard Worker   // Parse LONG_MAX as a JSON number (not a JSON string). The result of the
177*6777b538SAndroid Build Coastguard Worker   // parse is a base::Value, either a (32-bit) int or a (64-bit) double.
178*6777b538SAndroid Build Coastguard Worker   // LONG_MAX would overflow an int and can only be approximated by a double.
179*6777b538SAndroid Build Coastguard Worker   // In this case, parsing is lossy.
180*6777b538SAndroid Build Coastguard Worker   const char* etc807 = "9223372036854775807";
181*6777b538SAndroid Build Coastguard Worker   const char* etc808 = "9223372036854775808.000000";
182*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read(etc807);
183*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
184*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(root->is_int());
185*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_double());
186*6777b538SAndroid Build Coastguard Worker   // We use StringPrintf instead of NumberToString, because the NumberToString
187*6777b538SAndroid Build Coastguard Worker   // function does not let you specify the precision, and its default output,
188*6777b538SAndroid Build Coastguard Worker   // "9.223372036854776e+18", isn't precise enough to see the lossiness.
189*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(std::string(etc808), StringPrintf("%f", root->GetDouble()));
190*6777b538SAndroid Build Coastguard Worker }
191*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,Doubles)192*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, Doubles) {
193*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("43.1");
194*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
195*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
196*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(43.1, root->GetDouble());
197*6777b538SAndroid Build Coastguard Worker 
198*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("4.3e-1");
199*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
200*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
201*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(.43, root->GetDouble());
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("2.1e0");
204*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
205*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
206*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(2.1, root->GetDouble());
207*6777b538SAndroid Build Coastguard Worker 
208*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("2.1e+0001");
209*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
210*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
211*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(21.0, root->GetDouble());
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("0.01");
214*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
215*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
216*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.01, root->GetDouble());
217*6777b538SAndroid Build Coastguard Worker 
218*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("1.00");
219*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
220*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
221*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1.0, root->GetDouble());
222*6777b538SAndroid Build Coastguard Worker 
223*6777b538SAndroid Build Coastguard Worker   // Some "parse to float64" implementations find this one tricky.
224*6777b538SAndroid Build Coastguard Worker   // https://github.com/serde-rs/json/issues/707
225*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("122.416294033786585");
226*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
227*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
228*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(122.416294033786585, root->GetDouble());
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker   // This is syntaxtically valid, but out of range of a double.
231*6777b538SAndroid Build Coastguard Worker   auto value =
232*6777b538SAndroid Build Coastguard Worker       JSONReader::ReadAndReturnValueWithError("1e1000", JSON_PARSE_RFC);
233*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(value.has_value());
234*6777b538SAndroid Build Coastguard Worker }
235*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,FractionalNumbers)236*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, FractionalNumbers) {
237*6777b538SAndroid Build Coastguard Worker   // Fractional parts must have a digit before and after the decimal point.
238*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("1."));
239*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read(".1"));
240*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("1.e10"));
241*6777b538SAndroid Build Coastguard Worker }
242*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,ExponentialNumbers)243*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ExponentialNumbers) {
244*6777b538SAndroid Build Coastguard Worker   // Exponent must have a digit following the 'e'.
245*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("1e"));
246*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("1E"));
247*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("1e1."));
248*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("1e1.0"));
249*6777b538SAndroid Build Coastguard Worker }
250*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,InvalidInfNAN)251*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidInfNAN) {
252*6777b538SAndroid Build Coastguard Worker   // The largest finite double is roughly 1.8e308.
253*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("1e1000"));
254*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("-1e1000"));
255*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("NaN"));
256*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("nan"));
257*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("inf"));
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,InvalidNumbers)260*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidNumbers) {
261*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("4.3"));
262*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("4."));
263*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("4.3.1"));
264*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("4e3.1"));
265*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("4.a"));
266*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("42a"));
267*6777b538SAndroid Build Coastguard Worker }
268*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,Zeroes)269*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, Zeroes) {
270*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("0");
271*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
272*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_int());
273*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0, root->GetInt());
274*6777b538SAndroid Build Coastguard Worker 
275*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("0.0");
276*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
277*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
278*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.0, root->GetDouble());
279*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(std::signbit(root->GetDouble()));
280*6777b538SAndroid Build Coastguard Worker 
281*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("-0");
282*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
283*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
284*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.0, root->GetDouble());
285*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(std::signbit(root->GetDouble()));
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("-0.0");
288*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
289*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_double());
290*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(-0.0, root->GetDouble());
291*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(std::signbit(root->GetDouble()));
292*6777b538SAndroid Build Coastguard Worker }
293*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,SimpleString)294*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, SimpleString) {
295*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("\"hello world\"");
296*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
297*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
298*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("hello world", root->GetString());
299*6777b538SAndroid Build Coastguard Worker }
300*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,EmptyString)301*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, EmptyString) {
302*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("\"\"");
303*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
304*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
305*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("", root->GetString());
306*6777b538SAndroid Build Coastguard Worker }
307*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,BasicStringEscapes)308*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, BasicStringEscapes) {
309*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root =
310*6777b538SAndroid Build Coastguard Worker       JSONReader::Read("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\"");
311*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
312*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
313*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(" \"\\/\b\f\n\r\t", root->GetString());
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,UnicodeEscapes)316*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, UnicodeEscapes) {
317*6777b538SAndroid Build Coastguard Worker   // Test hex and unicode escapes including the null character.
318*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root =
319*6777b538SAndroid Build Coastguard Worker       JSONReader::Read("\"\\x41\\xFF\\x00\\u1234\\u0000\"");
320*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
321*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
322*6777b538SAndroid Build Coastguard Worker   const std::string& str_val = root->GetString();
323*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(std::wstring(L"A\x00FF\0\x1234\0", 5), UTF8ToWide(str_val));
324*6777b538SAndroid Build Coastguard Worker 
325*6777b538SAndroid Build Coastguard Worker   // The contents of a Unicode escape may only be four hex chars. Previously the
326*6777b538SAndroid Build Coastguard Worker   // parser accepted things like "0x01" and "0X01".
327*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"\\u0x12\""));
328*6777b538SAndroid Build Coastguard Worker 
329*6777b538SAndroid Build Coastguard Worker   // Surrogate pairs are allowed in JSON.
330*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("\"\\uD834\\uDD1E\""));  // U+1D11E
331*6777b538SAndroid Build Coastguard Worker }
332*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,InvalidStrings)333*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidStrings) {
334*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"no closing quote"));
335*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"\\z invalid escape char\""));
336*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"\\xAQ invalid hex code\""));
337*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("not enough hex chars\\x1\""));
338*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"not enough escape chars\\u123\""));
339*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"extra backslash at end of input\\\""));
340*6777b538SAndroid Build Coastguard Worker }
341*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,BasicArray)342*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, BasicArray) {
343*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("[true, false, null]");
344*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
345*6777b538SAndroid Build Coastguard Worker   Value::List* list = root->GetIfList();
346*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
347*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3U, list->size());
348*6777b538SAndroid Build Coastguard Worker 
349*6777b538SAndroid Build Coastguard Worker   // Test with trailing comma.  Should be parsed the same as above.
350*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root2 =
351*6777b538SAndroid Build Coastguard Worker       JSONReader::Read("[true, false, null, ]", JSON_ALLOW_TRAILING_COMMAS);
352*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2);
353*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(*list, *root2);
354*6777b538SAndroid Build Coastguard Worker }
355*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,EmptyArray)356*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, EmptyArray) {
357*6777b538SAndroid Build Coastguard Worker   std::optional<Value> value = JSONReader::Read("[]");
358*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
359*6777b538SAndroid Build Coastguard Worker   Value::List* list = value->GetIfList();
360*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
361*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(list->empty());
362*6777b538SAndroid Build Coastguard Worker }
363*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,CompleteArray)364*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, CompleteArray) {
365*6777b538SAndroid Build Coastguard Worker   std::optional<Value> value = JSONReader::Read("[\"a\", 3, 4.56, null]");
366*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
367*6777b538SAndroid Build Coastguard Worker   Value::List* list = value->GetIfList();
368*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
369*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(4U, list->size());
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,NestedArrays)372*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, NestedArrays) {
373*6777b538SAndroid Build Coastguard Worker   std::optional<Value> value = JSONReader::Read(
374*6777b538SAndroid Build Coastguard Worker       "[[true], [], {\"smell\": \"nice\",\"taste\": \"yummy\" }, [false, [], "
375*6777b538SAndroid Build Coastguard Worker       "[null]], null]");
376*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
377*6777b538SAndroid Build Coastguard Worker   Value::List* list = value->GetIfList();
378*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
379*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(5U, list->size());
380*6777b538SAndroid Build Coastguard Worker 
381*6777b538SAndroid Build Coastguard Worker   // Lots of trailing commas.
382*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root2 = JSONReader::Read(
383*6777b538SAndroid Build Coastguard Worker       "[[true], [], {\"smell\": \"nice\",\"taste\": \"yummy\" }, [false, [], "
384*6777b538SAndroid Build Coastguard Worker       "[null, ]  , ], null,]",
385*6777b538SAndroid Build Coastguard Worker       JSON_ALLOW_TRAILING_COMMAS);
386*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2);
387*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(*list, *root2);
388*6777b538SAndroid Build Coastguard Worker }
389*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,InvalidArrays)390*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidArrays) {
391*6777b538SAndroid Build Coastguard Worker   // Missing close brace.
392*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[[true], [], [false, [], [null]], null"));
393*6777b538SAndroid Build Coastguard Worker 
394*6777b538SAndroid Build Coastguard Worker   // Too many commas.
395*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[true,, null]"));
396*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[true,, null]", JSON_ALLOW_TRAILING_COMMAS));
397*6777b538SAndroid Build Coastguard Worker 
398*6777b538SAndroid Build Coastguard Worker   // No commas.
399*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[true null]"));
400*6777b538SAndroid Build Coastguard Worker 
401*6777b538SAndroid Build Coastguard Worker   // Trailing comma.
402*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[true,]"));
403*6777b538SAndroid Build Coastguard Worker }
404*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,ArrayTrailingComma)405*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ArrayTrailingComma) {
406*6777b538SAndroid Build Coastguard Worker   // Valid if we set |allow_trailing_comma| to true.
407*6777b538SAndroid Build Coastguard Worker   std::optional<Value> value =
408*6777b538SAndroid Build Coastguard Worker       JSONReader::Read("[true,]", JSON_ALLOW_TRAILING_COMMAS);
409*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
410*6777b538SAndroid Build Coastguard Worker   Value::List* list = value->GetIfList();
411*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
412*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(1U, list->size());
413*6777b538SAndroid Build Coastguard Worker   const Value& value1 = (*list)[0];
414*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value1.is_bool());
415*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(value1.GetBool());
416*6777b538SAndroid Build Coastguard Worker }
417*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,ArrayTrailingCommaNoEmptyElements)418*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ArrayTrailingCommaNoEmptyElements) {
419*6777b538SAndroid Build Coastguard Worker   // Don't allow empty elements, even if |allow_trailing_comma| is
420*6777b538SAndroid Build Coastguard Worker   // true.
421*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[,]", JSON_ALLOW_TRAILING_COMMAS));
422*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[true,,]", JSON_ALLOW_TRAILING_COMMAS));
423*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[,true,]", JSON_ALLOW_TRAILING_COMMAS));
424*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[true,,false]", JSON_ALLOW_TRAILING_COMMAS));
425*6777b538SAndroid Build Coastguard Worker }
426*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,EmptyDictionary)427*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, EmptyDictionary) {
428*6777b538SAndroid Build Coastguard Worker   std::optional<Value> dict_val = JSONReader::Read("{}");
429*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(dict_val);
430*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(dict_val->is_dict());
431*6777b538SAndroid Build Coastguard Worker }
432*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,CompleteDictionary)433*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, CompleteDictionary) {
434*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root1 = JSONReader::Read(
435*6777b538SAndroid Build Coastguard Worker       "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", \"bool\": "
436*6777b538SAndroid Build Coastguard Worker       "false, \"more\": {} }");
437*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root1);
438*6777b538SAndroid Build Coastguard Worker   const Value::Dict* root1_dict = root1->GetIfDict();
439*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root1_dict);
440*6777b538SAndroid Build Coastguard Worker   auto double_val = root1_dict->FindDouble("number");
441*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(double_val);
442*6777b538SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(9.87654321, *double_val);
443*6777b538SAndroid Build Coastguard Worker   const Value* null_val = root1_dict->Find("null");
444*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(null_val);
445*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(null_val->is_none());
446*6777b538SAndroid Build Coastguard Worker   const std::string* str_val = root1_dict->FindString("S");
447*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(str_val);
448*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("str", *str_val);
449*6777b538SAndroid Build Coastguard Worker   auto bool_val = root1_dict->FindBool("bool");
450*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(bool_val);
451*6777b538SAndroid Build Coastguard Worker   ASSERT_FALSE(*bool_val);
452*6777b538SAndroid Build Coastguard Worker 
453*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root2 = JSONReader::Read(
454*6777b538SAndroid Build Coastguard Worker       "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", \"bool\": "
455*6777b538SAndroid Build Coastguard Worker       "false, \"more\": {},}",
456*6777b538SAndroid Build Coastguard Worker       JSON_PARSE_CHROMIUM_EXTENSIONS | JSON_ALLOW_TRAILING_COMMAS);
457*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2);
458*6777b538SAndroid Build Coastguard Worker   Value::Dict* root2_dict = root2->GetIfDict();
459*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2_dict);
460*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(*root1_dict, *root2_dict);
461*6777b538SAndroid Build Coastguard Worker 
462*6777b538SAndroid Build Coastguard Worker   // Test newline equivalence.
463*6777b538SAndroid Build Coastguard Worker   root2 = JSONReader::Read(
464*6777b538SAndroid Build Coastguard Worker       "{\n"
465*6777b538SAndroid Build Coastguard Worker       "  \"number\":9.87654321,\n"
466*6777b538SAndroid Build Coastguard Worker       "  \"null\":null,\n"
467*6777b538SAndroid Build Coastguard Worker       "  \"\\x53\":\"str\",\n"
468*6777b538SAndroid Build Coastguard Worker       "  \"bool\": false,\n"
469*6777b538SAndroid Build Coastguard Worker       "  \"more\": {},\n"
470*6777b538SAndroid Build Coastguard Worker       "}\n",
471*6777b538SAndroid Build Coastguard Worker       JSON_PARSE_CHROMIUM_EXTENSIONS | JSON_ALLOW_TRAILING_COMMAS);
472*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2);
473*6777b538SAndroid Build Coastguard Worker   root2_dict = root2->GetIfDict();
474*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2);
475*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(*root1_dict, *root2_dict);
476*6777b538SAndroid Build Coastguard Worker 
477*6777b538SAndroid Build Coastguard Worker   root2 = JSONReader::Read(
478*6777b538SAndroid Build Coastguard Worker       "{\r\n"
479*6777b538SAndroid Build Coastguard Worker       "  \"number\":9.87654321,\r\n"
480*6777b538SAndroid Build Coastguard Worker       "  \"null\":null,\r\n"
481*6777b538SAndroid Build Coastguard Worker       "  \"\\x53\":\"str\",\r\n"
482*6777b538SAndroid Build Coastguard Worker       "  \"bool\": false,\r\n"
483*6777b538SAndroid Build Coastguard Worker       "  \"more\": {},\r\n"
484*6777b538SAndroid Build Coastguard Worker       "}\r\n",
485*6777b538SAndroid Build Coastguard Worker       JSON_PARSE_CHROMIUM_EXTENSIONS | JSON_ALLOW_TRAILING_COMMAS);
486*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2);
487*6777b538SAndroid Build Coastguard Worker   root2_dict = root2->GetIfDict();
488*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2_dict);
489*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(*root1_dict, *root2_dict);
490*6777b538SAndroid Build Coastguard Worker }
491*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,NestedDictionaries)492*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, NestedDictionaries) {
493*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root1 = JSONReader::Read(
494*6777b538SAndroid Build Coastguard Worker       "{\"inner\":{\"array\":[true, 3, 4.56, null]},\"false\":false,\"d\":{}}");
495*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root1);
496*6777b538SAndroid Build Coastguard Worker   const base::Value::Dict* root1_dict = root1->GetIfDict();
497*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root1_dict);
498*6777b538SAndroid Build Coastguard Worker   const Value::Dict* inner_dict = root1_dict->FindDict("inner");
499*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(inner_dict);
500*6777b538SAndroid Build Coastguard Worker   const Value::List* inner_array = inner_dict->FindList("array");
501*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(inner_array);
502*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(4U, inner_array->size());
503*6777b538SAndroid Build Coastguard Worker   auto bool_value = root1_dict->FindBool("false");
504*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(bool_value);
505*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(*bool_value);
506*6777b538SAndroid Build Coastguard Worker   inner_dict = root1_dict->FindDict("d");
507*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(inner_dict);
508*6777b538SAndroid Build Coastguard Worker 
509*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root2 = JSONReader::Read(
510*6777b538SAndroid Build Coastguard Worker       "{\"inner\": {\"array\":[true, 3, 4.56, null] , "
511*6777b538SAndroid Build Coastguard Worker       "},\"false\":false,\"d\":{},}",
512*6777b538SAndroid Build Coastguard Worker       JSON_ALLOW_TRAILING_COMMAS);
513*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root2);
514*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(*root1_dict, *root2);
515*6777b538SAndroid Build Coastguard Worker }
516*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,DictionaryKeysWithPeriods)517*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, DictionaryKeysWithPeriods) {
518*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root =
519*6777b538SAndroid Build Coastguard Worker       JSONReader::Read("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}");
520*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
521*6777b538SAndroid Build Coastguard Worker   Value::Dict* root_dict = root->GetIfDict();
522*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root_dict);
523*6777b538SAndroid Build Coastguard Worker 
524*6777b538SAndroid Build Coastguard Worker   auto integer_value = root_dict->FindInt("a.b");
525*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(integer_value);
526*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3, *integer_value);
527*6777b538SAndroid Build Coastguard Worker   integer_value = root_dict->FindInt("c");
528*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(integer_value);
529*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, *integer_value);
530*6777b538SAndroid Build Coastguard Worker   const Value::Dict* inner_dict = root_dict->FindDict("d.e.f");
531*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(inner_dict);
532*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1U, inner_dict->size());
533*6777b538SAndroid Build Coastguard Worker   integer_value = inner_dict->FindInt("g.h.i.j");
534*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(integer_value);
535*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, *integer_value);
536*6777b538SAndroid Build Coastguard Worker 
537*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("{\"a\":{\"b\":2},\"a.b\":1}");
538*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
539*6777b538SAndroid Build Coastguard Worker   root_dict = root->GetIfDict();
540*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root_dict);
541*6777b538SAndroid Build Coastguard Worker   const Value* integer_path_value = root_dict->FindByDottedPath("a.b");
542*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(integer_path_value);
543*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, integer_path_value->GetInt());
544*6777b538SAndroid Build Coastguard Worker   integer_value = root_dict->FindInt("a.b");
545*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(integer_value);
546*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, *integer_value);
547*6777b538SAndroid Build Coastguard Worker }
548*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,DuplicateKeys)549*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, DuplicateKeys) {
550*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("{\"x\":1,\"x\":2,\"y\":3}");
551*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
552*6777b538SAndroid Build Coastguard Worker   const Value::Dict* root_dict = root->GetIfDict();
553*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root_dict);
554*6777b538SAndroid Build Coastguard Worker 
555*6777b538SAndroid Build Coastguard Worker   auto integer_value = root_dict->FindInt("x");
556*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(integer_value);
557*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2, *integer_value);
558*6777b538SAndroid Build Coastguard Worker }
559*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,InvalidDictionaries)560*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidDictionaries) {
561*6777b538SAndroid Build Coastguard Worker   // No closing brace.
562*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{\"a\": true"));
563*6777b538SAndroid Build Coastguard Worker 
564*6777b538SAndroid Build Coastguard Worker   // Keys must be quoted strings.
565*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{foo:true}"));
566*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{1234: false}"));
567*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{:false}"));
568*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{ , }"));
569*6777b538SAndroid Build Coastguard Worker 
570*6777b538SAndroid Build Coastguard Worker   // Trailing comma.
571*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{\"a\":true,}"));
572*6777b538SAndroid Build Coastguard Worker 
573*6777b538SAndroid Build Coastguard Worker   // Too many commas.
574*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}"));
575*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}",
576*6777b538SAndroid Build Coastguard Worker                                 JSON_ALLOW_TRAILING_COMMAS));
577*6777b538SAndroid Build Coastguard Worker 
578*6777b538SAndroid Build Coastguard Worker   // No separator.
579*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{\"a\" \"b\"}"));
580*6777b538SAndroid Build Coastguard Worker 
581*6777b538SAndroid Build Coastguard Worker   // Lone comma.
582*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{,}"));
583*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{,}", JSON_ALLOW_TRAILING_COMMAS));
584*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{\"a\":true,,}", JSON_ALLOW_TRAILING_COMMAS));
585*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{,\"a\":true}", JSON_ALLOW_TRAILING_COMMAS));
586*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}",
587*6777b538SAndroid Build Coastguard Worker                                 JSON_ALLOW_TRAILING_COMMAS));
588*6777b538SAndroid Build Coastguard Worker }
589*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,StackOverflow)590*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, StackOverflow) {
591*6777b538SAndroid Build Coastguard Worker   std::string evil(1000000, '[');
592*6777b538SAndroid Build Coastguard Worker   evil.append(std::string(1000000, ']'));
593*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read(evil));
594*6777b538SAndroid Build Coastguard Worker 
595*6777b538SAndroid Build Coastguard Worker   // A few thousand adjacent lists is fine.
596*6777b538SAndroid Build Coastguard Worker   std::string not_evil("[");
597*6777b538SAndroid Build Coastguard Worker   not_evil.reserve(15010);
598*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < 5000; ++i)
599*6777b538SAndroid Build Coastguard Worker     not_evil.append("[],");
600*6777b538SAndroid Build Coastguard Worker   not_evil.append("[]]");
601*6777b538SAndroid Build Coastguard Worker   std::optional<Value> value = JSONReader::Read(not_evil);
602*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
603*6777b538SAndroid Build Coastguard Worker   Value::List* list = value->GetIfList();
604*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
605*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(5001U, list->size());
606*6777b538SAndroid Build Coastguard Worker }
607*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,UTF8Input)608*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, UTF8Input) {
609*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("\"\xe7\xbd\x91\xe9\xa1\xb5\"");
610*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
611*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
612*6777b538SAndroid Build Coastguard Worker   const std::string& str_val = root->GetString();
613*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(L"\x7f51\x9875", UTF8ToWide(str_val));
614*6777b538SAndroid Build Coastguard Worker 
615*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("{\"path\": \"/tmp/\xc3\xa0\xc3\xa8\xc3\xb2.png\"}");
616*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
617*6777b538SAndroid Build Coastguard Worker   const Value::Dict* root_dict = root->GetIfDict();
618*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root_dict);
619*6777b538SAndroid Build Coastguard Worker   const std::string* maybe_string = root_dict->FindString("path");
620*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(maybe_string);
621*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("/tmp/\xC3\xA0\xC3\xA8\xC3\xB2.png", *maybe_string);
622*6777b538SAndroid Build Coastguard Worker 
623*6777b538SAndroid Build Coastguard Worker   // JSON can encode non-characters.
624*6777b538SAndroid Build Coastguard Worker   const char* const noncharacters[] = {
625*6777b538SAndroid Build Coastguard Worker       "\"\xEF\xB7\x90\"",      // U+FDD0
626*6777b538SAndroid Build Coastguard Worker       "\"\xEF\xB7\x9F\"",      // U+FDDF
627*6777b538SAndroid Build Coastguard Worker       "\"\xEF\xB7\xAF\"",      // U+FDEF
628*6777b538SAndroid Build Coastguard Worker       "\"\xEF\xBF\xBE\"",      // U+FFFE
629*6777b538SAndroid Build Coastguard Worker       "\"\xEF\xBF\xBF\"",      // U+FFFF
630*6777b538SAndroid Build Coastguard Worker       "\"\xF0\x9F\xBF\xBE\"",  // U+01FFFE
631*6777b538SAndroid Build Coastguard Worker       "\"\xF0\x9F\xBF\xBF\"",  // U+01FFFF
632*6777b538SAndroid Build Coastguard Worker       "\"\xF0\xAF\xBF\xBE\"",  // U+02FFFE
633*6777b538SAndroid Build Coastguard Worker       "\"\xF0\xAF\xBF\xBF\"",  // U+02FFFF
634*6777b538SAndroid Build Coastguard Worker       "\"\xF0\xBF\xBF\xBE\"",  // U+03FFFE
635*6777b538SAndroid Build Coastguard Worker       "\"\xF0\xBF\xBF\xBF\"",  // U+03FFFF
636*6777b538SAndroid Build Coastguard Worker       "\"\xF1\x8F\xBF\xBE\"",  // U+04FFFE
637*6777b538SAndroid Build Coastguard Worker       "\"\xF1\x8F\xBF\xBF\"",  // U+04FFFF
638*6777b538SAndroid Build Coastguard Worker       "\"\xF1\x9F\xBF\xBE\"",  // U+05FFFE
639*6777b538SAndroid Build Coastguard Worker       "\"\xF1\x9F\xBF\xBF\"",  // U+05FFFF
640*6777b538SAndroid Build Coastguard Worker       "\"\xF1\xAF\xBF\xBE\"",  // U+06FFFE
641*6777b538SAndroid Build Coastguard Worker       "\"\xF1\xAF\xBF\xBF\"",  // U+06FFFF
642*6777b538SAndroid Build Coastguard Worker       "\"\xF1\xBF\xBF\xBE\"",  // U+07FFFE
643*6777b538SAndroid Build Coastguard Worker       "\"\xF1\xBF\xBF\xBF\"",  // U+07FFFF
644*6777b538SAndroid Build Coastguard Worker       "\"\xF2\x8F\xBF\xBE\"",  // U+08FFFE
645*6777b538SAndroid Build Coastguard Worker       "\"\xF2\x8F\xBF\xBF\"",  // U+08FFFF
646*6777b538SAndroid Build Coastguard Worker       "\"\xF2\x9F\xBF\xBE\"",  // U+09FFFE
647*6777b538SAndroid Build Coastguard Worker       "\"\xF2\x9F\xBF\xBF\"",  // U+09FFFF
648*6777b538SAndroid Build Coastguard Worker       "\"\xF2\xAF\xBF\xBE\"",  // U+0AFFFE
649*6777b538SAndroid Build Coastguard Worker       "\"\xF2\xAF\xBF\xBF\"",  // U+0AFFFF
650*6777b538SAndroid Build Coastguard Worker       "\"\xF2\xBF\xBF\xBE\"",  // U+0BFFFE
651*6777b538SAndroid Build Coastguard Worker       "\"\xF2\xBF\xBF\xBF\"",  // U+0BFFFF
652*6777b538SAndroid Build Coastguard Worker       "\"\xF3\x8F\xBF\xBE\"",  // U+0CFFFE
653*6777b538SAndroid Build Coastguard Worker       "\"\xF3\x8F\xBF\xBF\"",  // U+0CFFFF
654*6777b538SAndroid Build Coastguard Worker       "\"\xF3\x9F\xBF\xBE\"",  // U+0DFFFE
655*6777b538SAndroid Build Coastguard Worker       "\"\xF3\x9F\xBF\xBF\"",  // U+0DFFFF
656*6777b538SAndroid Build Coastguard Worker       "\"\xF3\xAF\xBF\xBE\"",  // U+0EFFFE
657*6777b538SAndroid Build Coastguard Worker       "\"\xF3\xAF\xBF\xBF\"",  // U+0EFFFF
658*6777b538SAndroid Build Coastguard Worker       "\"\xF3\xBF\xBF\xBE\"",  // U+0FFFFE
659*6777b538SAndroid Build Coastguard Worker       "\"\xF3\xBF\xBF\xBF\"",  // U+0FFFFF
660*6777b538SAndroid Build Coastguard Worker       "\"\xF4\x8F\xBF\xBE\"",  // U+10FFFE
661*6777b538SAndroid Build Coastguard Worker       "\"\xF4\x8F\xBF\xBF\"",  // U+10FFFF
662*6777b538SAndroid Build Coastguard Worker   };
663*6777b538SAndroid Build Coastguard Worker   for (auto* noncharacter : noncharacters) {
664*6777b538SAndroid Build Coastguard Worker     root = JSONReader::Read(noncharacter);
665*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(root);
666*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(root->is_string());
667*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(std::string(noncharacter + 1, strlen(noncharacter) - 2),
668*6777b538SAndroid Build Coastguard Worker               root->GetString());
669*6777b538SAndroid Build Coastguard Worker   }
670*6777b538SAndroid Build Coastguard Worker }
671*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,InvalidUTF8Input)672*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidUTF8Input) {
673*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"345\xb0\xa1\xb0\xa2\""));
674*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"123\xc0\x81\""));
675*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("\"abc\xc0\xae\""));
676*6777b538SAndroid Build Coastguard Worker }
677*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,UTF16Escapes)678*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, UTF16Escapes) {
679*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("\"\\u20ac3,14\"");
680*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
681*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
682*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(
683*6777b538SAndroid Build Coastguard Worker       "\xe2\x82\xac"
684*6777b538SAndroid Build Coastguard Worker       "3,14",
685*6777b538SAndroid Build Coastguard Worker       root->GetString());
686*6777b538SAndroid Build Coastguard Worker 
687*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("\"\\ud83d\\udca9\\ud83d\\udc6c\"");
688*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
689*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
690*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("\xf0\x9f\x92\xa9\xf0\x9f\x91\xac", root->GetString());
691*6777b538SAndroid Build Coastguard Worker }
692*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,InvalidUTF16Escapes)693*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidUTF16Escapes) {
694*6777b538SAndroid Build Coastguard Worker   const char* const cases[] = {
695*6777b538SAndroid Build Coastguard Worker       "\"\\u123\"",          // Invalid scalar.
696*6777b538SAndroid Build Coastguard Worker       "\"\\ud83d\"",         // Invalid scalar.
697*6777b538SAndroid Build Coastguard Worker       "\"\\u$%@!\"",         // Invalid scalar.
698*6777b538SAndroid Build Coastguard Worker       "\"\\uzz89\"",         // Invalid scalar.
699*6777b538SAndroid Build Coastguard Worker       "\"\\ud83d\\udca\"",   // Invalid lower surrogate.
700*6777b538SAndroid Build Coastguard Worker       "\"\\ud83d\\ud83d\"",  // Invalid lower surrogate.
701*6777b538SAndroid Build Coastguard Worker       "\"\\ud83d\\uaaaZ\"",  // Invalid lower surrogate.
702*6777b538SAndroid Build Coastguard Worker       "\"\\ud83foo\"",       // No lower surrogate.
703*6777b538SAndroid Build Coastguard Worker       "\"\\ud83d\\foo\"",    // No lower surrogate.
704*6777b538SAndroid Build Coastguard Worker       "\"\\ud83\\foo\"",     // Invalid upper surrogate.
705*6777b538SAndroid Build Coastguard Worker       "\"\\ud83d\\u1\"",     // No lower surrogate.
706*6777b538SAndroid Build Coastguard Worker       "\"\\ud83\\u1\"",      // Invalid upper surrogate.
707*6777b538SAndroid Build Coastguard Worker   };
708*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root;
709*6777b538SAndroid Build Coastguard Worker   for (auto* i : cases) {
710*6777b538SAndroid Build Coastguard Worker     root = JSONReader::Read(i);
711*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(root) << i;
712*6777b538SAndroid Build Coastguard Worker   }
713*6777b538SAndroid Build Coastguard Worker }
714*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,LiteralRoots)715*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, LiteralRoots) {
716*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read("null");
717*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
718*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->is_none());
719*6777b538SAndroid Build Coastguard Worker 
720*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("true");
721*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
722*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_bool());
723*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(root->GetBool());
724*6777b538SAndroid Build Coastguard Worker 
725*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("10");
726*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
727*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_int());
728*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(10, root->GetInt());
729*6777b538SAndroid Build Coastguard Worker 
730*6777b538SAndroid Build Coastguard Worker   root = JSONReader::Read("\"root\"");
731*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
732*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root->is_string());
733*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("root", root->GetString());
734*6777b538SAndroid Build Coastguard Worker }
735*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,ReadFromFile)736*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ReadFromFile) {
737*6777b538SAndroid Build Coastguard Worker   FilePath path;
738*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &path));
739*6777b538SAndroid Build Coastguard Worker   path = path.AppendASCII("json");
740*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(base::PathExists(path));
741*6777b538SAndroid Build Coastguard Worker 
742*6777b538SAndroid Build Coastguard Worker   std::string input;
743*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(ReadFileToString(path.AppendASCII("bom_feff.json"), &input));
744*6777b538SAndroid Build Coastguard Worker 
745*6777b538SAndroid Build Coastguard Worker   EXPECT_THAT(
746*6777b538SAndroid Build Coastguard Worker       JSONReader::ReadAndReturnValueWithError(input),
747*6777b538SAndroid Build Coastguard Worker       base::test::ValueIs(::testing::Property(&base::Value::is_dict, true)));
748*6777b538SAndroid Build Coastguard Worker }
749*6777b538SAndroid Build Coastguard Worker 
750*6777b538SAndroid Build Coastguard Worker // Tests that the root of a JSON object can be deleted safely while its
751*6777b538SAndroid Build Coastguard Worker // children outlive it.
TEST_P(JSONReaderTest,StringOptimizations)752*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, StringOptimizations) {
753*6777b538SAndroid Build Coastguard Worker   Value dict_literal_0;
754*6777b538SAndroid Build Coastguard Worker   Value dict_literal_1;
755*6777b538SAndroid Build Coastguard Worker   Value dict_string_0;
756*6777b538SAndroid Build Coastguard Worker   Value dict_string_1;
757*6777b538SAndroid Build Coastguard Worker   Value list_value_0;
758*6777b538SAndroid Build Coastguard Worker   Value list_value_1;
759*6777b538SAndroid Build Coastguard Worker 
760*6777b538SAndroid Build Coastguard Worker   {
761*6777b538SAndroid Build Coastguard Worker     std::optional<Value> root = JSONReader::Read(
762*6777b538SAndroid Build Coastguard Worker         "{"
763*6777b538SAndroid Build Coastguard Worker         "  \"test\": {"
764*6777b538SAndroid Build Coastguard Worker         "    \"foo\": true,"
765*6777b538SAndroid Build Coastguard Worker         "    \"bar\": 3.14,"
766*6777b538SAndroid Build Coastguard Worker         "    \"baz\": \"bat\","
767*6777b538SAndroid Build Coastguard Worker         "    \"moo\": \"cow\""
768*6777b538SAndroid Build Coastguard Worker         "  },"
769*6777b538SAndroid Build Coastguard Worker         "  \"list\": ["
770*6777b538SAndroid Build Coastguard Worker         "    \"a\","
771*6777b538SAndroid Build Coastguard Worker         "    \"b\""
772*6777b538SAndroid Build Coastguard Worker         "  ]"
773*6777b538SAndroid Build Coastguard Worker         "}",
774*6777b538SAndroid Build Coastguard Worker         JSON_PARSE_RFC);
775*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(root);
776*6777b538SAndroid Build Coastguard Worker     Value::Dict* root_dict = root->GetIfDict();
777*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(root_dict);
778*6777b538SAndroid Build Coastguard Worker 
779*6777b538SAndroid Build Coastguard Worker     Value::Dict* dict = root_dict->FindDict("test");
780*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(dict);
781*6777b538SAndroid Build Coastguard Worker     Value::List* list = root_dict->FindList("list");
782*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(list);
783*6777b538SAndroid Build Coastguard Worker 
784*6777b538SAndroid Build Coastguard Worker     Value* to_move = dict->Find("foo");
785*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(to_move);
786*6777b538SAndroid Build Coastguard Worker     dict_literal_0 = std::move(*to_move);
787*6777b538SAndroid Build Coastguard Worker     to_move = dict->Find("bar");
788*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(to_move);
789*6777b538SAndroid Build Coastguard Worker     dict_literal_1 = std::move(*to_move);
790*6777b538SAndroid Build Coastguard Worker     to_move = dict->Find("baz");
791*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(to_move);
792*6777b538SAndroid Build Coastguard Worker     dict_string_0 = std::move(*to_move);
793*6777b538SAndroid Build Coastguard Worker     to_move = dict->Find("moo");
794*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(to_move);
795*6777b538SAndroid Build Coastguard Worker     dict_string_1 = std::move(*to_move);
796*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(dict->Remove("foo"));
797*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(dict->Remove("bar"));
798*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(dict->Remove("baz"));
799*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(dict->Remove("moo"));
800*6777b538SAndroid Build Coastguard Worker 
801*6777b538SAndroid Build Coastguard Worker     ASSERT_EQ(2u, list->size());
802*6777b538SAndroid Build Coastguard Worker     list_value_0 = std::move((*list)[0]);
803*6777b538SAndroid Build Coastguard Worker     list_value_1 = std::move((*list)[1]);
804*6777b538SAndroid Build Coastguard Worker     list->clear();
805*6777b538SAndroid Build Coastguard Worker   }
806*6777b538SAndroid Build Coastguard Worker 
807*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(dict_literal_0.is_bool());
808*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(dict_literal_0.GetBool());
809*6777b538SAndroid Build Coastguard Worker 
810*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(dict_literal_1.is_double());
811*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(3.14, dict_literal_1.GetDouble());
812*6777b538SAndroid Build Coastguard Worker 
813*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(dict_string_0.is_string());
814*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("bat", dict_string_0.GetString());
815*6777b538SAndroid Build Coastguard Worker 
816*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(dict_string_1.is_string());
817*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("cow", dict_string_1.GetString());
818*6777b538SAndroid Build Coastguard Worker 
819*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list_value_0.is_string());
820*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("a", list_value_0.GetString());
821*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list_value_1.is_string());
822*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("b", list_value_1.GetString());
823*6777b538SAndroid Build Coastguard Worker }
824*6777b538SAndroid Build Coastguard Worker 
825*6777b538SAndroid Build Coastguard Worker // A smattering of invalid JSON designed to test specific portions of the
826*6777b538SAndroid Build Coastguard Worker // parser implementation against buffer overflow. Best run with DCHECKs so
827*6777b538SAndroid Build Coastguard Worker // that the one in NextChar fires.
TEST_P(JSONReaderTest,InvalidSanity)828*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, InvalidSanity) {
829*6777b538SAndroid Build Coastguard Worker   const char* const kInvalidJson[] = {
830*6777b538SAndroid Build Coastguard Worker       "/* test *", "{\"foo\"", "{\"foo\":", "  [", "\"\\u123g\"", "{\n\"eh:\n}",
831*6777b538SAndroid Build Coastguard Worker   };
832*6777b538SAndroid Build Coastguard Worker 
833*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < std::size(kInvalidJson); ++i) {
834*6777b538SAndroid Build Coastguard Worker     LOG(INFO) << "Sanity test " << i << ": <" << kInvalidJson[i] << ">";
835*6777b538SAndroid Build Coastguard Worker     auto root = JSONReader::ReadAndReturnValueWithError(kInvalidJson[i]);
836*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(root.has_value());
837*6777b538SAndroid Build Coastguard Worker     EXPECT_NE("", root.error().message);
838*6777b538SAndroid Build Coastguard Worker   }
839*6777b538SAndroid Build Coastguard Worker }
840*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,IllegalTrailingNull)841*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, IllegalTrailingNull) {
842*6777b538SAndroid Build Coastguard Worker   const char json[] = {'"', 'n', 'u', 'l', 'l', '"', '\0'};
843*6777b538SAndroid Build Coastguard Worker   std::string json_string(json, sizeof(json));
844*6777b538SAndroid Build Coastguard Worker   auto root = JSONReader::ReadAndReturnValueWithError(json_string);
845*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(root.has_value());
846*6777b538SAndroid Build Coastguard Worker   EXPECT_NE("", root.error().message);
847*6777b538SAndroid Build Coastguard Worker }
848*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,ASCIIControlCodes)849*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ASCIIControlCodes) {
850*6777b538SAndroid Build Coastguard Worker   // A literal NUL byte or a literal new line, in a JSON string, should be
851*6777b538SAndroid Build Coastguard Worker   // rejected. RFC 8259 section 7 says "the characters that MUST be escaped
852*6777b538SAndroid Build Coastguard Worker   // [include]... the control characters (U+0000 through U+001F)".
853*6777b538SAndroid Build Coastguard Worker   //
854*6777b538SAndroid Build Coastguard Worker   // Currently, we accept \r and \n in JSON strings because they are widely used
855*6777b538SAndroid Build Coastguard Worker   // and somewhat useful (especially when nesting JSON messages), but reject all
856*6777b538SAndroid Build Coastguard Worker   // other control characters.
857*6777b538SAndroid Build Coastguard Worker   {
858*6777b538SAndroid Build Coastguard Worker     const char json[] = "\"a\rn\nc\"";
859*6777b538SAndroid Build Coastguard Worker     auto root = JSONReader::Read(json);
860*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(root);
861*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(root->is_string());
862*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(5u, root->GetString().length());
863*6777b538SAndroid Build Coastguard Worker   }
864*6777b538SAndroid Build Coastguard Worker 
865*6777b538SAndroid Build Coastguard Worker   {
866*6777b538SAndroid Build Coastguard Worker     // Replace the \r with a disallowed \f, and require parsing to fail:
867*6777b538SAndroid Build Coastguard Worker     const char json[] = "\"a\fn\nc\"";
868*6777b538SAndroid Build Coastguard Worker     auto root = JSONReader::ReadAndReturnValueWithError(json);
869*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(root.has_value());
870*6777b538SAndroid Build Coastguard Worker     EXPECT_NE("", root.error().message);
871*6777b538SAndroid Build Coastguard Worker   }
872*6777b538SAndroid Build Coastguard Worker }
873*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,MaxNesting)874*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, MaxNesting) {
875*6777b538SAndroid Build Coastguard Worker   std::string json(R"({"outer": { "inner": {"foo": true}}})");
876*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read(json, JSON_PARSE_RFC, 3));
877*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read(json, JSON_PARSE_RFC, 4));
878*6777b538SAndroid Build Coastguard Worker }
879*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,Decode4ByteUtf8Char)880*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, Decode4ByteUtf8Char) {
881*6777b538SAndroid Build Coastguard Worker   // kUtf8Data contains a 4 byte unicode character (a smiley!) that JSONReader
882*6777b538SAndroid Build Coastguard Worker   // should be able to handle. The UTF-8 encoding of U+1F607 SMILING FACE WITH
883*6777b538SAndroid Build Coastguard Worker   // HALO is "\xF0\x9F\x98\x87".
884*6777b538SAndroid Build Coastguard Worker   const char kUtf8Data[] = "[\"��\",[],[],[],{\"google:suggesttype\":[]}]";
885*6777b538SAndroid Build Coastguard Worker   std::optional<Value> root = JSONReader::Read(kUtf8Data, JSON_PARSE_RFC);
886*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(root);
887*6777b538SAndroid Build Coastguard Worker   Value::List* list = root->GetIfList();
888*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(list);
889*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(5u, list->size());
890*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE((*list)[0].is_string());
891*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("\xF0\x9F\x98\x87", (*list)[0].GetString());
892*6777b538SAndroid Build Coastguard Worker }
893*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,DecodeUnicodeNonCharacter)894*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, DecodeUnicodeNonCharacter) {
895*6777b538SAndroid Build Coastguard Worker   // Tests Unicode code points (encoded as escaped UTF-16) that are not valid
896*6777b538SAndroid Build Coastguard Worker   // characters.
897*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uFDD0\"]"));         // U+FDD0
898*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uFDDF\"]"));         // U+FDDF
899*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uFDEF\"]"));         // U+FDEF
900*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uFFFE\"]"));         // U+FFFE
901*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uFFFF\"]"));         // U+FFFF
902*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD83F\\uDFFE\"]"));  // U+01FFFE
903*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD83F\\uDFFF\"]"));  // U+01FFFF
904*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD87F\\uDFFE\"]"));  // U+02FFFE
905*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD87F\\uDFFF\"]"));  // U+02FFFF
906*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD8BF\\uDFFE\"]"));  // U+03FFFE
907*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD8BF\\uDFFF\"]"));  // U+03FFFF
908*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD8FF\\uDFFE\"]"));  // U+04FFFE
909*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD8FF\\uDFFF\"]"));  // U+04FFFF
910*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD93F\\uDFFE\"]"));  // U+05FFFE
911*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD93F\\uDFFF\"]"));  // U+05FFFF
912*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD97F\\uDFFE\"]"));  // U+06FFFE
913*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD97F\\uDFFF\"]"));  // U+06FFFF
914*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD9BF\\uDFFE\"]"));  // U+07FFFE
915*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD9BF\\uDFFF\"]"));  // U+07FFFF
916*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD9FF\\uDFFE\"]"));  // U+08FFFE
917*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uD9FF\\uDFFF\"]"));  // U+08FFFF
918*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDA3F\\uDFFE\"]"));  // U+09FFFE
919*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDA3F\\uDFFF\"]"));  // U+09FFFF
920*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDA7F\\uDFFE\"]"));  // U+0AFFFE
921*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDA7F\\uDFFF\"]"));  // U+0AFFFF
922*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDABF\\uDFFE\"]"));  // U+0BFFFE
923*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDABF\\uDFFF\"]"));  // U+0BFFFF
924*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDAFF\\uDFFE\"]"));  // U+0CFFFE
925*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDAFF\\uDFFF\"]"));  // U+0CFFFF
926*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDB3F\\uDFFE\"]"));  // U+0DFFFE
927*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDB3F\\uDFFF\"]"));  // U+0DFFFF
928*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDB7F\\uDFFE\"]"));  // U+0EFFFE
929*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDB7F\\uDFFF\"]"));  // U+0EFFFF
930*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDBBF\\uDFFE\"]"));  // U+0FFFFE
931*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDBBF\\uDFFF\"]"));  // U+0FFFFF
932*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDBFF\\uDFFE\"]"));  // U+10FFFE
933*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(JSONReader::Read("[\"\\uDBFF\\uDFFF\"]"));  // U+10FFFF
934*6777b538SAndroid Build Coastguard Worker }
935*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,DecodeNegativeEscapeSequence)936*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, DecodeNegativeEscapeSequence) {
937*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[\"\\x-A\"]"));
938*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(JSONReader::Read("[\"\\u-00A\"]"));
939*6777b538SAndroid Build Coastguard Worker }
940*6777b538SAndroid Build Coastguard Worker 
941*6777b538SAndroid Build Coastguard Worker // Verifies invalid code points are replaced.
TEST_P(JSONReaderTest,ReplaceInvalidCharacters)942*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ReplaceInvalidCharacters) {
943*6777b538SAndroid Build Coastguard Worker   // U+D800 is a lone high surrogate.
944*6777b538SAndroid Build Coastguard Worker   const std::string invalid_high = "\"\xED\xA0\x80\"";
945*6777b538SAndroid Build Coastguard Worker   std::optional<Value> value =
946*6777b538SAndroid Build Coastguard Worker       JSONReader::Read(invalid_high, JSON_REPLACE_INVALID_CHARACTERS);
947*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
948*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value->is_string());
949*6777b538SAndroid Build Coastguard Worker   // Expect three U+FFFD (one for each UTF-8 byte in the invalid code point).
950*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD", value->GetString());
951*6777b538SAndroid Build Coastguard Worker 
952*6777b538SAndroid Build Coastguard Worker   // U+DFFF is a lone low surrogate.
953*6777b538SAndroid Build Coastguard Worker   const std::string invalid_low = "\"\xED\xBF\xBF\"";
954*6777b538SAndroid Build Coastguard Worker   value = JSONReader::Read(invalid_low, JSON_REPLACE_INVALID_CHARACTERS);
955*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
956*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value->is_string());
957*6777b538SAndroid Build Coastguard Worker   // Expect three U+FFFD (one for each UTF-8 byte in the invalid code point).
958*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD", value->GetString());
959*6777b538SAndroid Build Coastguard Worker }
960*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,ReplaceInvalidUTF16EscapeSequence)961*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ReplaceInvalidUTF16EscapeSequence) {
962*6777b538SAndroid Build Coastguard Worker   // U+D800 is a lone high surrogate.
963*6777b538SAndroid Build Coastguard Worker   const std::string invalid_high = "\"_\\uD800_\"";
964*6777b538SAndroid Build Coastguard Worker   std::optional<Value> value =
965*6777b538SAndroid Build Coastguard Worker       JSONReader::Read(invalid_high, JSON_REPLACE_INVALID_CHARACTERS);
966*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
967*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value->is_string());
968*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("_\xEF\xBF\xBD_", value->GetString());
969*6777b538SAndroid Build Coastguard Worker 
970*6777b538SAndroid Build Coastguard Worker   // U+DFFF is a lone low surrogate.
971*6777b538SAndroid Build Coastguard Worker   const std::string invalid_low = "\"_\\uDFFF_\"";
972*6777b538SAndroid Build Coastguard Worker   value = JSONReader::Read(invalid_low, JSON_REPLACE_INVALID_CHARACTERS);
973*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value);
974*6777b538SAndroid Build Coastguard Worker   ASSERT_TRUE(value->is_string());
975*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ("_\xEF\xBF\xBD_", value->GetString());
976*6777b538SAndroid Build Coastguard Worker }
977*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,ParseNumberErrors)978*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ParseNumberErrors) {
979*6777b538SAndroid Build Coastguard Worker   const struct {
980*6777b538SAndroid Build Coastguard Worker     const char* input;
981*6777b538SAndroid Build Coastguard Worker     bool parse_success;
982*6777b538SAndroid Build Coastguard Worker     double value;
983*6777b538SAndroid Build Coastguard Worker   } kCases[] = {
984*6777b538SAndroid Build Coastguard Worker       // clang-format off
985*6777b538SAndroid Build Coastguard Worker       {"1", true, 1},
986*6777b538SAndroid Build Coastguard Worker       {"2.", false, 0},
987*6777b538SAndroid Build Coastguard Worker       {"42", true, 42},
988*6777b538SAndroid Build Coastguard Worker       {"6e", false, 0},
989*6777b538SAndroid Build Coastguard Worker       {"43e2", true, 4300},
990*6777b538SAndroid Build Coastguard Worker       {"43e-", false, 0},
991*6777b538SAndroid Build Coastguard Worker       {"9e-3", true, 0.009},
992*6777b538SAndroid Build Coastguard Worker       {"2e+", false, 0},
993*6777b538SAndroid Build Coastguard Worker       {"2e+2", true, 200},
994*6777b538SAndroid Build Coastguard Worker       // clang-format on
995*6777b538SAndroid Build Coastguard Worker   };
996*6777b538SAndroid Build Coastguard Worker 
997*6777b538SAndroid Build Coastguard Worker   for (unsigned int i = 0; i < std::size(kCases); ++i) {
998*6777b538SAndroid Build Coastguard Worker     auto test_case = kCases[i];
999*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case.input));
1000*6777b538SAndroid Build Coastguard Worker 
1001*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<char[]> input_owner;
1002*6777b538SAndroid Build Coastguard Worker     std::string_view input =
1003*6777b538SAndroid Build Coastguard Worker         MakeNotNullTerminatedInput(test_case.input, &input_owner);
1004*6777b538SAndroid Build Coastguard Worker 
1005*6777b538SAndroid Build Coastguard Worker     std::optional<Value> result = JSONReader::Read(input);
1006*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(test_case.parse_success, result.has_value());
1007*6777b538SAndroid Build Coastguard Worker 
1008*6777b538SAndroid Build Coastguard Worker     if (!result)
1009*6777b538SAndroid Build Coastguard Worker       continue;
1010*6777b538SAndroid Build Coastguard Worker 
1011*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(result->is_double() || result->is_int());
1012*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(test_case.value, result->GetDouble());
1013*6777b538SAndroid Build Coastguard Worker   }
1014*6777b538SAndroid Build Coastguard Worker }
1015*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,UnterminatedInputs)1016*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, UnterminatedInputs) {
1017*6777b538SAndroid Build Coastguard Worker   const char* const kCases[] = {
1018*6777b538SAndroid Build Coastguard Worker       // clang-format off
1019*6777b538SAndroid Build Coastguard Worker       "/",
1020*6777b538SAndroid Build Coastguard Worker       "//",
1021*6777b538SAndroid Build Coastguard Worker       "/*",
1022*6777b538SAndroid Build Coastguard Worker       "\"xxxxxx",
1023*6777b538SAndroid Build Coastguard Worker       "\"",
1024*6777b538SAndroid Build Coastguard Worker       "{   ",
1025*6777b538SAndroid Build Coastguard Worker       "[\t",
1026*6777b538SAndroid Build Coastguard Worker       "tru",
1027*6777b538SAndroid Build Coastguard Worker       "fals",
1028*6777b538SAndroid Build Coastguard Worker       "nul",
1029*6777b538SAndroid Build Coastguard Worker       "\"\\x",
1030*6777b538SAndroid Build Coastguard Worker       "\"\\x2",
1031*6777b538SAndroid Build Coastguard Worker       "\"\\u123",
1032*6777b538SAndroid Build Coastguard Worker       "\"\\uD803\\u",
1033*6777b538SAndroid Build Coastguard Worker       "\"\\",
1034*6777b538SAndroid Build Coastguard Worker       "\"\\/",
1035*6777b538SAndroid Build Coastguard Worker       // clang-format on
1036*6777b538SAndroid Build Coastguard Worker   };
1037*6777b538SAndroid Build Coastguard Worker 
1038*6777b538SAndroid Build Coastguard Worker   for (unsigned int i = 0; i < std::size(kCases); ++i) {
1039*6777b538SAndroid Build Coastguard Worker     auto* test_case = kCases[i];
1040*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case));
1041*6777b538SAndroid Build Coastguard Worker 
1042*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<char[]> input_owner;
1043*6777b538SAndroid Build Coastguard Worker     std::string_view input =
1044*6777b538SAndroid Build Coastguard Worker         MakeNotNullTerminatedInput(test_case, &input_owner);
1045*6777b538SAndroid Build Coastguard Worker 
1046*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(JSONReader::Read(input));
1047*6777b538SAndroid Build Coastguard Worker   }
1048*6777b538SAndroid Build Coastguard Worker }
1049*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,LineColumnCounting)1050*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, LineColumnCounting) {
1051*6777b538SAndroid Build Coastguard Worker   const struct {
1052*6777b538SAndroid Build Coastguard Worker     const char* input;
1053*6777b538SAndroid Build Coastguard Worker     int error_line;
1054*6777b538SAndroid Build Coastguard Worker     int error_column;
1055*6777b538SAndroid Build Coastguard Worker   } kCases[] = {
1056*6777b538SAndroid Build Coastguard Worker       // For all but the "q_is_not_etc" case, the error (indicated by ^ in the
1057*6777b538SAndroid Build Coastguard Worker       // comments) is seeing a digit when expecting ',' or ']'.
1058*6777b538SAndroid Build Coastguard Worker       {
1059*6777b538SAndroid Build Coastguard Worker           // Line and column counts are 1-based, not 0-based.
1060*6777b538SAndroid Build Coastguard Worker           "q_is_not_the_start_of_any_valid_JSON_token",
1061*6777b538SAndroid Build Coastguard Worker           1,
1062*6777b538SAndroid Build Coastguard Worker           1,
1063*6777b538SAndroid Build Coastguard Worker       },
1064*6777b538SAndroid Build Coastguard Worker       {
1065*6777b538SAndroid Build Coastguard Worker           "[2,4,6 8",
1066*6777b538SAndroid Build Coastguard Worker           // -----^
1067*6777b538SAndroid Build Coastguard Worker           1,
1068*6777b538SAndroid Build Coastguard Worker           8,
1069*6777b538SAndroid Build Coastguard Worker       },
1070*6777b538SAndroid Build Coastguard Worker       {
1071*6777b538SAndroid Build Coastguard Worker           "[2,4,6\t8",
1072*6777b538SAndroid Build Coastguard Worker           // ------^
1073*6777b538SAndroid Build Coastguard Worker           1,
1074*6777b538SAndroid Build Coastguard Worker           8,
1075*6777b538SAndroid Build Coastguard Worker       },
1076*6777b538SAndroid Build Coastguard Worker       {
1077*6777b538SAndroid Build Coastguard Worker           "[2,4,6\n8",
1078*6777b538SAndroid Build Coastguard Worker           // ------^
1079*6777b538SAndroid Build Coastguard Worker           2,
1080*6777b538SAndroid Build Coastguard Worker           1,
1081*6777b538SAndroid Build Coastguard Worker       },
1082*6777b538SAndroid Build Coastguard Worker       {
1083*6777b538SAndroid Build Coastguard Worker           "[\n0,\n1,\n2,\n3,4,5,6 7,\n8,\n9\n]",
1084*6777b538SAndroid Build Coastguard Worker           // ---------------------^
1085*6777b538SAndroid Build Coastguard Worker           5,
1086*6777b538SAndroid Build Coastguard Worker           9,
1087*6777b538SAndroid Build Coastguard Worker       },
1088*6777b538SAndroid Build Coastguard Worker       {
1089*6777b538SAndroid Build Coastguard Worker           // Same as the previous example, but with "\r\n"s instead of "\n"s.
1090*6777b538SAndroid Build Coastguard Worker           "[\r\n0,\r\n1,\r\n2,\r\n3,4,5,6 7,\r\n8,\r\n9\r\n]",
1091*6777b538SAndroid Build Coastguard Worker           // -----------------------------^
1092*6777b538SAndroid Build Coastguard Worker           5,
1093*6777b538SAndroid Build Coastguard Worker           9,
1094*6777b538SAndroid Build Coastguard Worker       },
1095*6777b538SAndroid Build Coastguard Worker       // The JSON spec forbids unescaped ASCII control characters (including
1096*6777b538SAndroid Build Coastguard Worker       // line breaks) within a string, but our implementation is more lenient.
1097*6777b538SAndroid Build Coastguard Worker       {
1098*6777b538SAndroid Build Coastguard Worker           "[\"3\n1\" 4",
1099*6777b538SAndroid Build Coastguard Worker           // --------^
1100*6777b538SAndroid Build Coastguard Worker           2,
1101*6777b538SAndroid Build Coastguard Worker           4,
1102*6777b538SAndroid Build Coastguard Worker       },
1103*6777b538SAndroid Build Coastguard Worker       {
1104*6777b538SAndroid Build Coastguard Worker           "[\"3\r\n1\" 4",
1105*6777b538SAndroid Build Coastguard Worker           // ----------^
1106*6777b538SAndroid Build Coastguard Worker           2,
1107*6777b538SAndroid Build Coastguard Worker           4,
1108*6777b538SAndroid Build Coastguard Worker       },
1109*6777b538SAndroid Build Coastguard Worker   };
1110*6777b538SAndroid Build Coastguard Worker 
1111*6777b538SAndroid Build Coastguard Worker   for (unsigned int i = 0; i < std::size(kCases); ++i) {
1112*6777b538SAndroid Build Coastguard Worker     auto test_case = kCases[i];
1113*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case.input));
1114*6777b538SAndroid Build Coastguard Worker 
1115*6777b538SAndroid Build Coastguard Worker     auto root = JSONReader::ReadAndReturnValueWithError(
1116*6777b538SAndroid Build Coastguard Worker         test_case.input, JSON_PARSE_RFC | JSON_ALLOW_NEWLINES_IN_STRINGS);
1117*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(root.has_value());
1118*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(test_case.error_line, root.error().line);
1119*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(test_case.error_column, root.error().column);
1120*6777b538SAndroid Build Coastguard Worker   }
1121*6777b538SAndroid Build Coastguard Worker }
1122*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,ChromiumExtensions)1123*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, ChromiumExtensions) {
1124*6777b538SAndroid Build Coastguard Worker   // All of these cases should parse with JSON_PARSE_CHROMIUM_EXTENSIONS but
1125*6777b538SAndroid Build Coastguard Worker   // fail with JSON_PARSE_RFC.
1126*6777b538SAndroid Build Coastguard Worker   const struct {
1127*6777b538SAndroid Build Coastguard Worker     // The JSON input.
1128*6777b538SAndroid Build Coastguard Worker     const char* input;
1129*6777b538SAndroid Build Coastguard Worker     // What JSON_* option permits this extension.
1130*6777b538SAndroid Build Coastguard Worker     int option;
1131*6777b538SAndroid Build Coastguard Worker   } kCases[] = {
1132*6777b538SAndroid Build Coastguard Worker       {"{ /* comment */ \"foo\": 3 }", JSON_ALLOW_COMMENTS},
1133*6777b538SAndroid Build Coastguard Worker       {"{ // comment\n \"foo\": 3 }", JSON_ALLOW_COMMENTS},
1134*6777b538SAndroid Build Coastguard Worker       {"[\"\\xAB\"]", JSON_ALLOW_X_ESCAPES},
1135*6777b538SAndroid Build Coastguard Worker       {"[\"\n\"]", JSON_ALLOW_NEWLINES_IN_STRINGS},
1136*6777b538SAndroid Build Coastguard Worker       {"[\"\r\"]", JSON_ALLOW_NEWLINES_IN_STRINGS},
1137*6777b538SAndroid Build Coastguard Worker   };
1138*6777b538SAndroid Build Coastguard Worker 
1139*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < std::size(kCases); ++i) {
1140*6777b538SAndroid Build Coastguard Worker     SCOPED_TRACE(testing::Message() << "case " << i);
1141*6777b538SAndroid Build Coastguard Worker     const auto& test_case = kCases[i];
1142*6777b538SAndroid Build Coastguard Worker 
1143*6777b538SAndroid Build Coastguard Worker     auto result = JSONReader::ReadAndReturnValueWithError(test_case.input,
1144*6777b538SAndroid Build Coastguard Worker                                                           JSON_PARSE_RFC);
1145*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(result.has_value());
1146*6777b538SAndroid Build Coastguard Worker 
1147*6777b538SAndroid Build Coastguard Worker     result = JSONReader::ReadAndReturnValueWithError(
1148*6777b538SAndroid Build Coastguard Worker         test_case.input, JSON_PARSE_RFC | test_case.option);
1149*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(result.has_value());
1150*6777b538SAndroid Build Coastguard Worker 
1151*6777b538SAndroid Build Coastguard Worker     result = JSONReader::ReadAndReturnValueWithError(
1152*6777b538SAndroid Build Coastguard Worker         test_case.input, JSON_PARSE_CHROMIUM_EXTENSIONS);
1153*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(result.has_value());
1154*6777b538SAndroid Build Coastguard Worker 
1155*6777b538SAndroid Build Coastguard Worker     result = JSONReader::ReadAndReturnValueWithError(
1156*6777b538SAndroid Build Coastguard Worker         test_case.input, JSON_PARSE_CHROMIUM_EXTENSIONS & ~test_case.option);
1157*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(result.has_value());
1158*6777b538SAndroid Build Coastguard Worker   }
1159*6777b538SAndroid Build Coastguard Worker }
1160*6777b538SAndroid Build Coastguard Worker 
1161*6777b538SAndroid Build Coastguard Worker // For every control character, place it unescaped in a string and ensure that:
1162*6777b538SAndroid Build Coastguard Worker // a) It doesn't parse with JSON_PARSE_RFC
1163*6777b538SAndroid Build Coastguard Worker // b) It doesn't parse with JSON_PARSE_CHROMIUM_EXTENSIONS
1164*6777b538SAndroid Build Coastguard Worker // c) It does parse with JSON_ALLOW_CONTROL_CHARS
TEST_P(JSONReaderTest,UnescapedControls)1165*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, UnescapedControls) {
1166*6777b538SAndroid Build Coastguard Worker   std::string input = "\"foo\"";
1167*6777b538SAndroid Build Coastguard Worker   // ECMA-404 (JSON standard) section 9: characters from 0x00 to 0x1f must be
1168*6777b538SAndroid Build Coastguard Worker   // escaped.
1169*6777b538SAndroid Build Coastguard Worker   for (char c = 0x00; c <= 0x1f; c++) {
1170*6777b538SAndroid Build Coastguard Worker     input[1] = c;
1171*6777b538SAndroid Build Coastguard Worker 
1172*6777b538SAndroid Build Coastguard Worker     auto result = JSONReader::Read(input, JSON_PARSE_RFC);
1173*6777b538SAndroid Build Coastguard Worker     EXPECT_FALSE(result.has_value());
1174*6777b538SAndroid Build Coastguard Worker 
1175*6777b538SAndroid Build Coastguard Worker     bool should_parse_with_extensions = (c == '\r' || c == '\n');
1176*6777b538SAndroid Build Coastguard Worker     result = JSONReader::Read(input, JSON_PARSE_CHROMIUM_EXTENSIONS);
1177*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(should_parse_with_extensions, result.has_value());
1178*6777b538SAndroid Build Coastguard Worker 
1179*6777b538SAndroid Build Coastguard Worker     result = JSONReader::Read(input, JSON_ALLOW_CONTROL_CHARS);
1180*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(result.has_value());
1181*6777b538SAndroid Build Coastguard Worker     ASSERT_TRUE(result->is_string());
1182*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(result->GetString().length(), input.length() - 2);
1183*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(result->GetString()[0], c);
1184*6777b538SAndroid Build Coastguard Worker   }
1185*6777b538SAndroid Build Coastguard Worker }
1186*6777b538SAndroid Build Coastguard Worker 
TEST_P(JSONReaderTest,UsingRust)1187*6777b538SAndroid Build Coastguard Worker TEST_P(JSONReaderTest, UsingRust) {
1188*6777b538SAndroid Build Coastguard Worker   ASSERT_EQ(JSONReader::UsingRust(), using_rust_);
1189*6777b538SAndroid Build Coastguard Worker }
1190*6777b538SAndroid Build Coastguard Worker 
1191*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(All,
1192*6777b538SAndroid Build Coastguard Worker                          JSONReaderTest,
1193*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(BUILD_RUST_JSON_READER)
1194*6777b538SAndroid Build Coastguard Worker                          testing::Bool(),
1195*6777b538SAndroid Build Coastguard Worker #else   // BUILDFLAG(BUILD_RUST_JSON_READER)
1196*6777b538SAndroid Build Coastguard Worker                          testing::Values(false),
1197*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(BUILD_RUST_JSON_READER)
__anon1805e2530502(const testing::TestParamInfo<bool>& info) 1198*6777b538SAndroid Build Coastguard Worker                          [](const testing::TestParamInfo<bool>& info) {
1199*6777b538SAndroid Build Coastguard Worker                            return info.param ? "Rust" : "Cpp";
1200*6777b538SAndroid Build Coastguard Worker                          });
1201*6777b538SAndroid Build Coastguard Worker 
1202*6777b538SAndroid Build Coastguard Worker }  // namespace base
1203