1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <memory>
6 #include <string>
7
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/json/json_file_value_serializer.h"
11 #include "base/json/json_reader.h"
12 #include "base/json/json_string_value_serializer.h"
13 #include "base/json/json_writer.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_piece.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/values.h"
19 #include "build/build_config.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace base {
23
24 namespace {
25
26 // Some proper JSON to test with:
27 const char kProperJSON[] =
28 "{\n"
29 " \"compound\": {\n"
30 " \"a\": 1,\n"
31 " \"b\": 2\n"
32 " },\n"
33 " \"some_String\": \"1337\",\n"
34 " \"some_int\": 42,\n"
35 " \"the_list\": [ \"val1\", \"val2\" ]\n"
36 "}\n";
37
38 // Some proper JSON with trailing commas:
39 const char kProperJSONWithCommas[] =
40 "{\n"
41 "\t\"some_int\": 42,\n"
42 "\t\"some_String\": \"1337\",\n"
43 "\t\"the_list\": [\"val1\", \"val2\", ],\n"
44 "\t\"compound\": { \"a\": 1, \"b\": 2, },\n"
45 "}\n";
46
47 // kProperJSON with a few misc characters at the begin and end.
48 const char kProperJSONPadded[] =
49 ")]}'\n"
50 "{\n"
51 " \"compound\": {\n"
52 " \"a\": 1,\n"
53 " \"b\": 2\n"
54 " },\n"
55 " \"some_String\": \"1337\",\n"
56 " \"some_int\": 42,\n"
57 " \"the_list\": [ \"val1\", \"val2\" ]\n"
58 "}\n"
59 "?!ab\n";
60
61 const char kWinLineEnds[] = "\r\n";
62 const char kLinuxLineEnds[] = "\n";
63
64 // Verifies the generated JSON against the expected output.
CheckJSONIsStillTheSame(const Value & value)65 void CheckJSONIsStillTheSame(const Value& value) {
66 // Serialize back the output.
67 std::string serialized_json;
68 JSONStringValueSerializer str_serializer(&serialized_json);
69 str_serializer.set_pretty_print(true);
70 ASSERT_TRUE(str_serializer.Serialize(value));
71 // Unify line endings between platforms.
72 ReplaceSubstringsAfterOffset(&serialized_json, 0,
73 kWinLineEnds, kLinuxLineEnds);
74 // Now compare the input with the output.
75 ASSERT_EQ(kProperJSON, serialized_json);
76 }
77
ValidateJsonList(const std::string & json)78 void ValidateJsonList(const std::string& json) {
79 std::unique_ptr<ListValue> list = ListValue::From(JSONReader::Read(json));
80 ASSERT_TRUE(list);
81 ASSERT_EQ(1U, list->GetSize());
82 Value* elt = nullptr;
83 ASSERT_TRUE(list->Get(0, &elt));
84 int value = 0;
85 ASSERT_TRUE(elt && elt->GetAsInteger(&value));
86 ASSERT_EQ(1, value);
87 }
88
89 // Test proper JSON deserialization from string is working.
TEST(JSONValueDeserializerTest,ReadProperJSONFromString)90 TEST(JSONValueDeserializerTest, ReadProperJSONFromString) {
91 // Try to deserialize it through the serializer.
92 JSONStringValueDeserializer str_deserializer(kProperJSON);
93
94 int error_code = 0;
95 std::string error_message;
96 std::unique_ptr<Value> value =
97 str_deserializer.Deserialize(&error_code, &error_message);
98 ASSERT_TRUE(value);
99 ASSERT_EQ(0, error_code);
100 ASSERT_TRUE(error_message.empty());
101 // Verify if the same JSON is still there.
102 CheckJSONIsStillTheSame(*value);
103 }
104
105 // Test proper JSON deserialization from a StringPiece substring.
TEST(JSONValueDeserializerTest,ReadProperJSONFromStringPiece)106 TEST(JSONValueDeserializerTest, ReadProperJSONFromStringPiece) {
107 // Create a StringPiece for the substring of kProperJSONPadded that matches
108 // kProperJSON.
109 StringPiece proper_json(kProperJSONPadded);
110 proper_json = proper_json.substr(5, proper_json.length() - 10);
111 JSONStringValueDeserializer str_deserializer(proper_json);
112
113 int error_code = 0;
114 std::string error_message;
115 std::unique_ptr<Value> value =
116 str_deserializer.Deserialize(&error_code, &error_message);
117 ASSERT_TRUE(value);
118 ASSERT_EQ(0, error_code);
119 ASSERT_TRUE(error_message.empty());
120 // Verify if the same JSON is still there.
121 CheckJSONIsStillTheSame(*value);
122 }
123
124 // Test that trialing commas are only properly deserialized from string when
125 // the proper flag for that is set.
TEST(JSONValueDeserializerTest,ReadJSONWithTrailingCommasFromString)126 TEST(JSONValueDeserializerTest, ReadJSONWithTrailingCommasFromString) {
127 // Try to deserialize it through the serializer.
128 JSONStringValueDeserializer str_deserializer(kProperJSONWithCommas);
129
130 int error_code = 0;
131 std::string error_message;
132 std::unique_ptr<Value> value =
133 str_deserializer.Deserialize(&error_code, &error_message);
134 ASSERT_FALSE(value);
135 ASSERT_NE(0, error_code);
136 ASSERT_FALSE(error_message.empty());
137 // Repeat with commas allowed.
138 JSONStringValueDeserializer str_deserializer2(kProperJSONWithCommas,
139 JSON_ALLOW_TRAILING_COMMAS);
140 value = str_deserializer2.Deserialize(&error_code, &error_message);
141 ASSERT_TRUE(value);
142 ASSERT_EQ(JSONReader::JSON_TRAILING_COMMA, error_code);
143 // Verify if the same JSON is still there.
144 CheckJSONIsStillTheSame(*value);
145 }
146
147 // Test proper JSON deserialization from file is working.
TEST(JSONValueDeserializerTest,ReadProperJSONFromFile)148 TEST(JSONValueDeserializerTest, ReadProperJSONFromFile) {
149 ScopedTempDir tempdir;
150 ASSERT_TRUE(tempdir.CreateUniqueTempDir());
151 // Write it down in the file.
152 FilePath temp_file(tempdir.GetPath().AppendASCII("test.json"));
153 ASSERT_EQ(static_cast<int>(strlen(kProperJSON)),
154 WriteFile(temp_file, kProperJSON, strlen(kProperJSON)));
155
156 // Try to deserialize it through the serializer.
157 JSONFileValueDeserializer file_deserializer(temp_file);
158
159 int error_code = 0;
160 std::string error_message;
161 std::unique_ptr<Value> value =
162 file_deserializer.Deserialize(&error_code, &error_message);
163 ASSERT_TRUE(value);
164 ASSERT_EQ(0, error_code);
165 ASSERT_TRUE(error_message.empty());
166 // Verify if the same JSON is still there.
167 CheckJSONIsStillTheSame(*value);
168 }
169
170 // Test that trialing commas are only properly deserialized from file when
171 // the proper flag for that is set.
TEST(JSONValueDeserializerTest,ReadJSONWithCommasFromFile)172 TEST(JSONValueDeserializerTest, ReadJSONWithCommasFromFile) {
173 ScopedTempDir tempdir;
174 ASSERT_TRUE(tempdir.CreateUniqueTempDir());
175 // Write it down in the file.
176 FilePath temp_file(tempdir.GetPath().AppendASCII("test.json"));
177 ASSERT_EQ(static_cast<int>(strlen(kProperJSONWithCommas)),
178 WriteFile(temp_file, kProperJSONWithCommas,
179 strlen(kProperJSONWithCommas)));
180
181 // Try to deserialize it through the serializer.
182 JSONFileValueDeserializer file_deserializer(temp_file);
183 // This must fail without the proper flag.
184 int error_code = 0;
185 std::string error_message;
186 std::unique_ptr<Value> value =
187 file_deserializer.Deserialize(&error_code, &error_message);
188 ASSERT_FALSE(value);
189 ASSERT_NE(0, error_code);
190 ASSERT_FALSE(error_message.empty());
191 // Repeat with commas allowed.
192 JSONFileValueDeserializer file_deserializer2(temp_file,
193 JSON_ALLOW_TRAILING_COMMAS);
194 value = file_deserializer2.Deserialize(&error_code, &error_message);
195 ASSERT_TRUE(value);
196 ASSERT_EQ(JSONReader::JSON_TRAILING_COMMA, error_code);
197 // Verify if the same JSON is still there.
198 CheckJSONIsStillTheSame(*value);
199 }
200
TEST(JSONValueDeserializerTest,AllowTrailingComma)201 TEST(JSONValueDeserializerTest, AllowTrailingComma) {
202 static const char kTestWithCommas[] = "{\"key\": [true,],}";
203 static const char kTestNoCommas[] = "{\"key\": [true]}";
204
205 JSONStringValueDeserializer deserializer(kTestWithCommas,
206 JSON_ALLOW_TRAILING_COMMAS);
207 JSONStringValueDeserializer deserializer_expected(kTestNoCommas);
208 std::unique_ptr<Value> root = deserializer.Deserialize(nullptr, nullptr);
209 ASSERT_TRUE(root);
210 std::unique_ptr<Value> root_expected;
211 root_expected = deserializer_expected.Deserialize(nullptr, nullptr);
212 ASSERT_TRUE(root_expected);
213 ASSERT_TRUE(root->Equals(root_expected.get()));
214 }
215
TEST(JSONValueSerializerTest,Roundtrip)216 TEST(JSONValueSerializerTest, Roundtrip) {
217 static const char kOriginalSerialization[] =
218 "{\"bool\":true,\"double\":3.14,\"int\":42,\"list\":[1,2],\"null\":null}";
219 JSONStringValueDeserializer deserializer(kOriginalSerialization);
220 std::unique_ptr<DictionaryValue> root_dict =
221 DictionaryValue::From(deserializer.Deserialize(nullptr, nullptr));
222 ASSERT_TRUE(root_dict);
223
224 Value* null_value = nullptr;
225 ASSERT_TRUE(root_dict->Get("null", &null_value));
226 ASSERT_TRUE(null_value);
227 ASSERT_TRUE(null_value->is_none());
228
229 bool bool_value = false;
230 ASSERT_TRUE(root_dict->GetBoolean("bool", &bool_value));
231 ASSERT_TRUE(bool_value);
232
233 int int_value = 0;
234 ASSERT_TRUE(root_dict->GetInteger("int", &int_value));
235 ASSERT_EQ(42, int_value);
236
237 double double_value = 0.0;
238 ASSERT_TRUE(root_dict->GetDouble("double", &double_value));
239 ASSERT_DOUBLE_EQ(3.14, double_value);
240
241 std::string test_serialization;
242 JSONStringValueSerializer mutable_serializer(&test_serialization);
243 ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
244 ASSERT_EQ(kOriginalSerialization, test_serialization);
245
246 mutable_serializer.set_pretty_print(true);
247 ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
248 // JSON output uses a different newline style on Windows than on other
249 // platforms.
250 #if defined(OS_WIN)
251 #define JSON_NEWLINE "\r\n"
252 #else
253 #define JSON_NEWLINE "\n"
254 #endif
255 const std::string pretty_serialization =
256 "{" JSON_NEWLINE
257 " \"bool\": true," JSON_NEWLINE
258 " \"double\": 3.14," JSON_NEWLINE
259 " \"int\": 42," JSON_NEWLINE
260 " \"list\": [ 1, 2 ]," JSON_NEWLINE
261 " \"null\": null" JSON_NEWLINE
262 "}" JSON_NEWLINE;
263 #undef JSON_NEWLINE
264 ASSERT_EQ(pretty_serialization, test_serialization);
265 }
266
TEST(JSONValueSerializerTest,StringEscape)267 TEST(JSONValueSerializerTest, StringEscape) {
268 string16 all_chars;
269 for (int i = 1; i < 256; ++i) {
270 all_chars += static_cast<char16>(i);
271 }
272 // Generated in in Firefox using the following js (with an extra backslash for
273 // double quote):
274 // var s = '';
275 // for (var i = 1; i < 256; ++i) { s += String.fromCharCode(i); }
276 // uneval(s).replace(/\\/g, "\\\\");
277 std::string all_chars_expected =
278 "\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000B\\f\\r"
279 "\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017"
280 "\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F !\\\"#$%&'()*+,"
281 "-./0123456789:;\\u003C=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcde"
282 "fghijklmnopqrstuvwxyz{|}~\x7F\xC2\x80\xC2\x81\xC2\x82\xC2\x83\xC2\x84"
283 "\xC2\x85\xC2\x86\xC2\x87\xC2\x88\xC2\x89\xC2\x8A\xC2\x8B\xC2\x8C\xC2\x8D"
284 "\xC2\x8E\xC2\x8F\xC2\x90\xC2\x91\xC2\x92\xC2\x93\xC2\x94\xC2\x95\xC2\x96"
285 "\xC2\x97\xC2\x98\xC2\x99\xC2\x9A\xC2\x9B\xC2\x9C\xC2\x9D\xC2\x9E\xC2\x9F"
286 "\xC2\xA0\xC2\xA1\xC2\xA2\xC2\xA3\xC2\xA4\xC2\xA5\xC2\xA6\xC2\xA7\xC2\xA8"
287 "\xC2\xA9\xC2\xAA\xC2\xAB\xC2\xAC\xC2\xAD\xC2\xAE\xC2\xAF\xC2\xB0\xC2\xB1"
288 "\xC2\xB2\xC2\xB3\xC2\xB4\xC2\xB5\xC2\xB6\xC2\xB7\xC2\xB8\xC2\xB9\xC2\xBA"
289 "\xC2\xBB\xC2\xBC\xC2\xBD\xC2\xBE\xC2\xBF\xC3\x80\xC3\x81\xC3\x82\xC3\x83"
290 "\xC3\x84\xC3\x85\xC3\x86\xC3\x87\xC3\x88\xC3\x89\xC3\x8A\xC3\x8B\xC3\x8C"
291 "\xC3\x8D\xC3\x8E\xC3\x8F\xC3\x90\xC3\x91\xC3\x92\xC3\x93\xC3\x94\xC3\x95"
292 "\xC3\x96\xC3\x97\xC3\x98\xC3\x99\xC3\x9A\xC3\x9B\xC3\x9C\xC3\x9D\xC3\x9E"
293 "\xC3\x9F\xC3\xA0\xC3\xA1\xC3\xA2\xC3\xA3\xC3\xA4\xC3\xA5\xC3\xA6\xC3\xA7"
294 "\xC3\xA8\xC3\xA9\xC3\xAA\xC3\xAB\xC3\xAC\xC3\xAD\xC3\xAE\xC3\xAF\xC3\xB0"
295 "\xC3\xB1\xC3\xB2\xC3\xB3\xC3\xB4\xC3\xB5\xC3\xB6\xC3\xB7\xC3\xB8\xC3\xB9"
296 "\xC3\xBA\xC3\xBB\xC3\xBC\xC3\xBD\xC3\xBE\xC3\xBF";
297
298 std::string expected_output = "{\"all_chars\":\"" + all_chars_expected +
299 "\"}";
300 // Test JSONWriter interface
301 std::string output_js;
302 DictionaryValue valueRoot;
303 valueRoot.SetString("all_chars", all_chars);
304 JSONWriter::Write(valueRoot, &output_js);
305 ASSERT_EQ(expected_output, output_js);
306
307 // Test JSONValueSerializer interface (uses JSONWriter).
308 JSONStringValueSerializer serializer(&output_js);
309 ASSERT_TRUE(serializer.Serialize(valueRoot));
310 ASSERT_EQ(expected_output, output_js);
311 }
312
TEST(JSONValueSerializerTest,UnicodeStrings)313 TEST(JSONValueSerializerTest, UnicodeStrings) {
314 // unicode string json -> escaped ascii text
315 DictionaryValue root;
316 string16 test(WideToUTF16(L"\x7F51\x9875"));
317 root.SetString("web", test);
318
319 static const char kExpected[] = "{\"web\":\"\xE7\xBD\x91\xE9\xA1\xB5\"}";
320
321 std::string actual;
322 JSONStringValueSerializer serializer(&actual);
323 ASSERT_TRUE(serializer.Serialize(root));
324 ASSERT_EQ(kExpected, actual);
325
326 // escaped ascii text -> json
327 JSONStringValueDeserializer deserializer(kExpected);
328 std::unique_ptr<Value> deserial_root =
329 deserializer.Deserialize(nullptr, nullptr);
330 ASSERT_TRUE(deserial_root);
331 DictionaryValue* dict_root =
332 static_cast<DictionaryValue*>(deserial_root.get());
333 string16 web_value;
334 ASSERT_TRUE(dict_root->GetString("web", &web_value));
335 ASSERT_EQ(test, web_value);
336 }
337
TEST(JSONValueSerializerTest,HexStrings)338 TEST(JSONValueSerializerTest, HexStrings) {
339 // hex string json -> escaped ascii text
340 DictionaryValue root;
341 string16 test(WideToUTF16(L"\x01\x02"));
342 root.SetString("test", test);
343
344 static const char kExpected[] = "{\"test\":\"\\u0001\\u0002\"}";
345
346 std::string actual;
347 JSONStringValueSerializer serializer(&actual);
348 ASSERT_TRUE(serializer.Serialize(root));
349 ASSERT_EQ(kExpected, actual);
350
351 // escaped ascii text -> json
352 JSONStringValueDeserializer deserializer(kExpected);
353 std::unique_ptr<Value> deserial_root =
354 deserializer.Deserialize(nullptr, nullptr);
355 ASSERT_TRUE(deserial_root);
356 DictionaryValue* dict_root =
357 static_cast<DictionaryValue*>(deserial_root.get());
358 string16 test_value;
359 ASSERT_TRUE(dict_root->GetString("test", &test_value));
360 ASSERT_EQ(test, test_value);
361
362 // Test converting escaped regular chars
363 static const char kEscapedChars[] = "{\"test\":\"\\u0067\\u006f\"}";
364 JSONStringValueDeserializer deserializer2(kEscapedChars);
365 deserial_root = deserializer2.Deserialize(nullptr, nullptr);
366 ASSERT_TRUE(deserial_root);
367 dict_root = static_cast<DictionaryValue*>(deserial_root.get());
368 ASSERT_TRUE(dict_root->GetString("test", &test_value));
369 ASSERT_EQ(ASCIIToUTF16("go"), test_value);
370 }
371
TEST(JSONValueSerializerTest,JSONReaderComments)372 TEST(JSONValueSerializerTest, JSONReaderComments) {
373 ValidateJsonList("[ // 2, 3, ignore me ] \n1 ]");
374 ValidateJsonList("[ /* 2, \n3, ignore me ]*/ \n1 ]");
375 ValidateJsonList("//header\n[ // 2, \n// 3, \n1 ]// footer");
376 ValidateJsonList("/*\n[ // 2, \n// 3, \n1 ]*/[1]");
377 ValidateJsonList("[ 1 /* one */ ] /* end */");
378 ValidateJsonList("[ 1 //// ,2\r\n ]");
379
380 // It's ok to have a comment in a string.
381 std::unique_ptr<ListValue> list =
382 ListValue::From(JSONReader::Read("[\"// ok\\n /* foo */ \"]"));
383 ASSERT_TRUE(list);
384 ASSERT_EQ(1U, list->GetSize());
385 Value* elt = nullptr;
386 ASSERT_TRUE(list->Get(0, &elt));
387 std::string value;
388 ASSERT_TRUE(elt && elt->GetAsString(&value));
389 ASSERT_EQ("// ok\n /* foo */ ", value);
390
391 // You can't nest comments.
392 ASSERT_FALSE(JSONReader::Read("/* /* inner */ outer */ [ 1 ]"));
393
394 // Not a open comment token.
395 ASSERT_FALSE(JSONReader::Read("/ * * / [1]"));
396 }
397
398 class JSONFileValueSerializerTest : public testing::Test {
399 protected:
SetUp()400 void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
401
402 ScopedTempDir temp_dir_;
403 };
404
TEST_F(JSONFileValueSerializerTest,DISABLED_Roundtrip)405 TEST_F(JSONFileValueSerializerTest, DISABLED_Roundtrip) {
406 FilePath original_file_path;
407 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
408 original_file_path = original_file_path.AppendASCII("serializer_test.json");
409
410 ASSERT_TRUE(PathExists(original_file_path));
411
412 JSONFileValueDeserializer deserializer(original_file_path);
413 std::unique_ptr<DictionaryValue> root_dict =
414 DictionaryValue::From(deserializer.Deserialize(nullptr, nullptr));
415 ASSERT_TRUE(root_dict);
416
417 Value* null_value = nullptr;
418 ASSERT_TRUE(root_dict->Get("null", &null_value));
419 ASSERT_TRUE(null_value);
420 ASSERT_TRUE(null_value->is_none());
421
422 bool bool_value = false;
423 ASSERT_TRUE(root_dict->GetBoolean("bool", &bool_value));
424 ASSERT_TRUE(bool_value);
425
426 int int_value = 0;
427 ASSERT_TRUE(root_dict->GetInteger("int", &int_value));
428 ASSERT_EQ(42, int_value);
429
430 std::string string_value;
431 ASSERT_TRUE(root_dict->GetString("string", &string_value));
432 ASSERT_EQ("hello", string_value);
433
434 // Now try writing.
435 const FilePath written_file_path =
436 temp_dir_.GetPath().AppendASCII("test_output.js");
437
438 ASSERT_FALSE(PathExists(written_file_path));
439 JSONFileValueSerializer serializer(written_file_path);
440 ASSERT_TRUE(serializer.Serialize(*root_dict));
441 ASSERT_TRUE(PathExists(written_file_path));
442
443 // Now compare file contents.
444 EXPECT_TRUE(TextContentsEqual(original_file_path, written_file_path));
445 EXPECT_TRUE(DeleteFile(written_file_path, false));
446 }
447
TEST_F(JSONFileValueSerializerTest,DISABLED_RoundtripNested)448 TEST_F(JSONFileValueSerializerTest, DISABLED_RoundtripNested) {
449 FilePath original_file_path;
450 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
451 original_file_path =
452 original_file_path.AppendASCII("serializer_nested_test.json");
453
454 ASSERT_TRUE(PathExists(original_file_path));
455
456 JSONFileValueDeserializer deserializer(original_file_path);
457 std::unique_ptr<Value> root = deserializer.Deserialize(nullptr, nullptr);
458 ASSERT_TRUE(root);
459
460 // Now try writing.
461 FilePath written_file_path =
462 temp_dir_.GetPath().AppendASCII("test_output.json");
463
464 ASSERT_FALSE(PathExists(written_file_path));
465 JSONFileValueSerializer serializer(written_file_path);
466 ASSERT_TRUE(serializer.Serialize(*root));
467 ASSERT_TRUE(PathExists(written_file_path));
468
469 // Now compare file contents.
470 EXPECT_TRUE(TextContentsEqual(original_file_path, written_file_path));
471 EXPECT_TRUE(DeleteFile(written_file_path, false));
472 }
473
TEST_F(JSONFileValueSerializerTest,DISABLED_NoWhitespace)474 TEST_F(JSONFileValueSerializerTest, DISABLED_NoWhitespace) {
475 FilePath source_file_path;
476 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &source_file_path));
477 source_file_path =
478 source_file_path.AppendASCII("serializer_test_nowhitespace.json");
479 ASSERT_TRUE(PathExists(source_file_path));
480 JSONFileValueDeserializer deserializer(source_file_path);
481 std::unique_ptr<Value> root = deserializer.Deserialize(nullptr, nullptr);
482 ASSERT_TRUE(root);
483 }
484
485 } // namespace
486
487 } // namespace base
488