1 // Copyright 2012 The Chromium Authors
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 "base/values.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <functional>
11 #include <iterator>
12 #include <limits>
13 #include <memory>
14 #include <string>
15 #include <type_traits>
16 #include <utility>
17 #include <vector>
18
19 #include "base/bits.h"
20 #include "base/containers/adapters.h"
21 #include "base/containers/contains.h"
22 #include "base/strings/string_piece.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/test/gtest_util.h"
25 #include "build/build_config.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 #if BUILDFLAG(ENABLE_BASE_TRACING)
30 #include <optional>
31
32 #include "third_party/perfetto/include/perfetto/test/traced_value_test_support.h" // no-presubmit-check nogncheck
33 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
34
35 namespace base {
36
37 #ifdef NDEBUG
38 // `Value` should have a (relatively) small size to avoid creating excess
39 // overhead, e.g. for lists of values that are all ints.
40 //
41 // This test is limited to NDEBUG builds, since some containers may require
42 // extra storage for supporting debug checks for things like iterators.
TEST(ValuesTest,SizeOfValue)43 TEST(ValuesTest, SizeOfValue) {
44 #if defined(__GLIBCXX__)
45 // libstdc++ std::string takes already 4 machine words, so the absl::variant
46 // takes 5
47 constexpr size_t kExpectedSize = 5 * sizeof(void*);
48 #else // !defined(__GLIBCXX__)
49 // libc++'s std::string and std::vector both take 3 machine words. An
50 // additional word is used by absl::variant for the type index.
51 constexpr size_t kExpectedSize = 4 * sizeof(void*);
52 #endif // defined(__GLIBCXX__)
53
54 // Use std::integral_constant so the compiler error message includes the
55 // evaluated size. In future versions of clang, it should be possible to
56 // simplify this to an equality comparison (i.e. newer clangs print out
57 // "comparison reduces to '(1 == 2)'").
58 static_assert(std::is_same_v<std::integral_constant<size_t, sizeof(Value)>,
59 std::integral_constant<size_t, kExpectedSize>>,
60 "base::Value has an unexpected size!");
61 }
62 #endif
63
TEST(ValuesTest,TestNothrow)64 TEST(ValuesTest, TestNothrow) {
65 static_assert(std::is_nothrow_move_constructible_v<Value>,
66 "IsNothrowMoveConstructible");
67 static_assert(std::is_nothrow_default_constructible_v<Value>,
68 "IsNothrowDefaultConstructible");
69 static_assert(std::is_nothrow_constructible_v<Value, std::string&&>,
70 "IsNothrowMoveConstructibleFromString");
71 static_assert(std::is_nothrow_constructible_v<Value, Value::BlobStorage&&>,
72 "IsNothrowMoveConstructibleFromBlob");
73 static_assert(std::is_nothrow_move_assignable_v<Value>,
74 "IsNothrowMoveAssignable");
75 }
76
TEST(ValuesTest,EmptyValue)77 TEST(ValuesTest, EmptyValue) {
78 Value value;
79 EXPECT_EQ(Value::Type::NONE, value.type());
80 EXPECT_EQ(std::nullopt, value.GetIfBool());
81 EXPECT_EQ(std::nullopt, value.GetIfInt());
82 EXPECT_EQ(std::nullopt, value.GetIfDouble());
83 EXPECT_EQ(nullptr, value.GetIfString());
84 EXPECT_EQ(nullptr, value.GetIfBlob());
85 }
86
87 // Group of tests for the value constructors.
TEST(ValuesTest,ConstructBool)88 TEST(ValuesTest, ConstructBool) {
89 Value true_value(true);
90 EXPECT_EQ(Value::Type::BOOLEAN, true_value.type());
91 EXPECT_THAT(true_value.GetIfBool(), testing::Optional(true));
92 EXPECT_TRUE(true_value.GetBool());
93
94 Value false_value(false);
95 EXPECT_EQ(Value::Type::BOOLEAN, false_value.type());
96 EXPECT_THAT(false_value.GetIfBool(), testing::Optional(false));
97 EXPECT_FALSE(false_value.GetBool());
98 }
99
TEST(ValuesTest,ConstructFromPtrs)100 TEST(ValuesTest, ConstructFromPtrs) {
101 static_assert(!std::is_constructible_v<Value, int*>, "");
102 static_assert(!std::is_constructible_v<Value, const int*>, "");
103 static_assert(!std::is_constructible_v<Value, wchar_t*>, "");
104 static_assert(!std::is_constructible_v<Value, const wchar_t*>, "");
105
106 static_assert(std::is_constructible_v<Value, char*>, "");
107 static_assert(std::is_constructible_v<Value, const char*>, "");
108 static_assert(std::is_constructible_v<Value, char16_t*>, "");
109 static_assert(std::is_constructible_v<Value, const char16_t*>, "");
110 }
111
TEST(ValuesTest,ConstructInt)112 TEST(ValuesTest, ConstructInt) {
113 Value value(-37);
114 EXPECT_EQ(Value::Type::INTEGER, value.type());
115 EXPECT_THAT(value.GetIfInt(), testing::Optional(-37));
116 EXPECT_EQ(-37, value.GetInt());
117
118 EXPECT_THAT(value.GetIfDouble(), testing::Optional(-37.0));
119 EXPECT_EQ(-37.0, value.GetDouble());
120 }
121
TEST(ValuesTest,ConstructDouble)122 TEST(ValuesTest, ConstructDouble) {
123 Value value(-4.655);
124 EXPECT_EQ(Value::Type::DOUBLE, value.type());
125 EXPECT_THAT(value.GetIfDouble(), testing::Optional(-4.655));
126 EXPECT_EQ(-4.655, value.GetDouble());
127 }
128
TEST(ValuesTest,ConstructStringFromConstCharPtr)129 TEST(ValuesTest, ConstructStringFromConstCharPtr) {
130 const char* str = "foobar";
131 Value value(str);
132 EXPECT_EQ(Value::Type::STRING, value.type());
133 EXPECT_THAT(value.GetIfString(), testing::Pointee(std::string("foobar")));
134 EXPECT_EQ("foobar", value.GetString());
135 }
136
TEST(ValuesTest,ConstructStringFromStringPiece)137 TEST(ValuesTest, ConstructStringFromStringPiece) {
138 std::string str = "foobar";
139 Value value{StringPiece(str)};
140 EXPECT_EQ(Value::Type::STRING, value.type());
141 EXPECT_THAT(value.GetIfString(), testing::Pointee(std::string("foobar")));
142 EXPECT_EQ("foobar", value.GetString());
143 }
144
TEST(ValuesTest,ConstructStringFromStdStringRRef)145 TEST(ValuesTest, ConstructStringFromStdStringRRef) {
146 std::string str = "foobar";
147 Value value(std::move(str));
148 EXPECT_EQ(Value::Type::STRING, value.type());
149 EXPECT_THAT(value.GetIfString(), testing::Pointee(std::string("foobar")));
150 EXPECT_EQ("foobar", value.GetString());
151 }
152
TEST(ValuesTest,ConstructStringFromConstChar16Ptr)153 TEST(ValuesTest, ConstructStringFromConstChar16Ptr) {
154 std::u16string str = u"foobar";
155 Value value(str.c_str());
156 EXPECT_EQ(Value::Type::STRING, value.type());
157 EXPECT_THAT(value.GetIfString(), testing::Pointee(std::string("foobar")));
158 EXPECT_EQ("foobar", value.GetString());
159 }
160
TEST(ValuesTest,ConstructStringFromStringPiece16)161 TEST(ValuesTest, ConstructStringFromStringPiece16) {
162 std::u16string str = u"foobar";
163 Value value{StringPiece16(str)};
164 EXPECT_EQ(Value::Type::STRING, value.type());
165 EXPECT_THAT(value.GetIfString(), testing::Pointee(std::string("foobar")));
166 EXPECT_EQ("foobar", value.GetString());
167 }
168
TEST(ValuesTest,ConstructBinary)169 TEST(ValuesTest, ConstructBinary) {
170 Value::BlobStorage blob = {0xF, 0x0, 0x0, 0xB, 0xA, 0x2};
171 Value value(blob);
172 EXPECT_EQ(Value::Type::BINARY, value.type());
173 EXPECT_THAT(value.GetIfBlob(), testing::Pointee(blob));
174 EXPECT_EQ(blob, value.GetBlob());
175 }
176
TEST(ValuesTest,ConstructDict)177 TEST(ValuesTest, ConstructDict) {
178 Value::Dict value;
179 EXPECT_EQ(Value::Type::DICT, Value(std::move(value)).type());
180 }
181
TEST(ValuesTest,ConstructDictFromValueDict)182 TEST(ValuesTest, ConstructDictFromValueDict) {
183 Value::Dict dict;
184 dict.Set("foo", "bar");
185 {
186 Value value(dict.Clone());
187 EXPECT_EQ(Value::Type::DICT, value.type());
188 EXPECT_TRUE(value.GetIfDict());
189 EXPECT_TRUE(value.GetDict().FindString("foo"));
190 EXPECT_EQ("bar", *value.GetDict().FindString("foo"));
191 }
192
193 dict.Set("foo", "baz");
194 {
195 Value value(std::move(dict));
196 EXPECT_EQ(Value::Type::DICT, value.type());
197 EXPECT_TRUE(value.GetIfDict());
198 EXPECT_TRUE(value.GetDict().FindString("foo"));
199 EXPECT_EQ("baz", *value.GetDict().FindString("foo"));
200 }
201 }
202
TEST(ValuesTest,ConstructList)203 TEST(ValuesTest, ConstructList) {
204 Value value(Value::List{});
205 EXPECT_EQ(Value::Type::LIST, value.type());
206 }
207
TEST(ValuesTest,UseTestingEachOnValueList)208 TEST(ValuesTest, UseTestingEachOnValueList) {
209 Value::List list;
210 list.Append(true);
211 list.Append(true);
212
213 // This will only work if `Value::List::value_type` is defined.
214 EXPECT_THAT(list, testing::Each(testing::ResultOf(
215 [](const Value& value) { return value.GetBool(); },
216 testing::Eq(true))));
217 }
218
TEST(ValuesTest,ConstructListFromValueList)219 TEST(ValuesTest, ConstructListFromValueList) {
220 Value::List list;
221 list.Append("foo");
222 {
223 Value value(list.Clone());
224 EXPECT_EQ(Value::Type::LIST, value.type());
225 EXPECT_EQ(1u, value.GetList().size());
226 EXPECT_EQ(Value::Type::STRING, value.GetList()[0].type());
227 EXPECT_EQ("foo", value.GetList()[0].GetString());
228 }
229
230 list.back() = base::Value("bar");
231 {
232 Value value(std::move(list));
233 EXPECT_EQ(Value::Type::LIST, value.type());
234 EXPECT_EQ(1u, value.GetList().size());
235 EXPECT_EQ(Value::Type::STRING, value.GetList()[0].type());
236 EXPECT_EQ("bar", value.GetList()[0].GetString());
237 }
238 }
239
TEST(ValuesTest,HardenTests)240 TEST(ValuesTest, HardenTests) {
241 Value value;
242 ASSERT_EQ(value.type(), Value::Type::NONE);
243 EXPECT_DEATH_IF_SUPPORTED(value.GetBool(), "");
244 EXPECT_DEATH_IF_SUPPORTED(value.GetInt(), "");
245 EXPECT_DEATH_IF_SUPPORTED(value.GetDouble(), "");
246 EXPECT_DEATH_IF_SUPPORTED(value.GetString(), "");
247 EXPECT_DEATH_IF_SUPPORTED(value.GetBlob(), "");
248 }
249
250 // Group of tests for the copy constructors and copy-assigmnent. For equality
251 // checks comparisons of the interesting fields are done instead of relying on
252 // Equals being correct.
TEST(ValuesTest,CopyBool)253 TEST(ValuesTest, CopyBool) {
254 Value true_value(true);
255 Value copied_true_value(true_value.Clone());
256 EXPECT_EQ(true_value.type(), copied_true_value.type());
257 EXPECT_EQ(true_value.GetBool(), copied_true_value.GetBool());
258
259 Value false_value(false);
260 Value copied_false_value(false_value.Clone());
261 EXPECT_EQ(false_value.type(), copied_false_value.type());
262 EXPECT_EQ(false_value.GetBool(), copied_false_value.GetBool());
263
264 Value blank;
265
266 blank = true_value.Clone();
267 EXPECT_EQ(true_value.type(), blank.type());
268 EXPECT_EQ(true_value.GetBool(), blank.GetBool());
269
270 blank = false_value.Clone();
271 EXPECT_EQ(false_value.type(), blank.type());
272 EXPECT_EQ(false_value.GetBool(), blank.GetBool());
273 }
274
TEST(ValuesTest,CopyInt)275 TEST(ValuesTest, CopyInt) {
276 Value value(74);
277 Value copied_value(value.Clone());
278 EXPECT_EQ(value.type(), copied_value.type());
279 EXPECT_EQ(value.GetInt(), copied_value.GetInt());
280
281 Value blank;
282
283 blank = value.Clone();
284 EXPECT_EQ(value.type(), blank.type());
285 EXPECT_EQ(value.GetInt(), blank.GetInt());
286 }
287
TEST(ValuesTest,CopyDouble)288 TEST(ValuesTest, CopyDouble) {
289 Value value(74.896);
290 Value copied_value(value.Clone());
291 EXPECT_EQ(value.type(), copied_value.type());
292 EXPECT_EQ(value.GetDouble(), copied_value.GetDouble());
293
294 Value blank;
295
296 blank = value.Clone();
297 EXPECT_EQ(value.type(), blank.type());
298 EXPECT_EQ(value.GetDouble(), blank.GetDouble());
299 }
300
TEST(ValuesTest,CopyString)301 TEST(ValuesTest, CopyString) {
302 Value value("foobar");
303 Value copied_value(value.Clone());
304 EXPECT_EQ(value.type(), copied_value.type());
305 EXPECT_EQ(value.GetString(), copied_value.GetString());
306
307 Value blank;
308
309 blank = value.Clone();
310 EXPECT_EQ(value.type(), blank.type());
311 EXPECT_EQ(value.GetString(), blank.GetString());
312 }
313
TEST(ValuesTest,CopyBinary)314 TEST(ValuesTest, CopyBinary) {
315 Value value(Value::BlobStorage({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}));
316 Value copied_value(value.Clone());
317 EXPECT_EQ(value.type(), copied_value.type());
318 EXPECT_EQ(value.GetBlob(), copied_value.GetBlob());
319
320 Value blank;
321
322 blank = value.Clone();
323 EXPECT_EQ(value.type(), blank.type());
324 EXPECT_EQ(value.GetBlob(), blank.GetBlob());
325 }
326
TEST(ValuesTest,CopyDictionary)327 TEST(ValuesTest, CopyDictionary) {
328 Value::Dict dict;
329 dict.Set("Int", 123);
330 Value value(std::move(dict));
331
332 Value copied_value(value.Clone());
333 EXPECT_EQ(value, copied_value);
334
335 Value blank;
336 blank = value.Clone();
337 EXPECT_EQ(value, blank);
338 }
339
TEST(ValuesTest,CopyList)340 TEST(ValuesTest, CopyList) {
341 Value::List list;
342 list.Append(123);
343 Value value(std::move(list));
344
345 Value copied_value(value.Clone());
346 EXPECT_EQ(value, copied_value);
347
348 Value blank;
349 blank = value.Clone();
350 EXPECT_EQ(value, blank);
351 }
352
353 // Group of tests for the move constructors and move-assigmnent.
TEST(ValuesTest,MoveBool)354 TEST(ValuesTest, MoveBool) {
355 Value true_value(true);
356 Value moved_true_value(std::move(true_value));
357 EXPECT_EQ(Value::Type::BOOLEAN, moved_true_value.type());
358 EXPECT_TRUE(moved_true_value.GetBool());
359
360 Value false_value(false);
361 Value moved_false_value(std::move(false_value));
362 EXPECT_EQ(Value::Type::BOOLEAN, moved_false_value.type());
363 EXPECT_FALSE(moved_false_value.GetBool());
364
365 Value blank;
366
367 blank = Value(true);
368 EXPECT_EQ(Value::Type::BOOLEAN, blank.type());
369 EXPECT_TRUE(blank.GetBool());
370
371 blank = Value(false);
372 EXPECT_EQ(Value::Type::BOOLEAN, blank.type());
373 EXPECT_FALSE(blank.GetBool());
374 }
375
TEST(ValuesTest,MoveInt)376 TEST(ValuesTest, MoveInt) {
377 Value value(74);
378 Value moved_value(std::move(value));
379 EXPECT_EQ(Value::Type::INTEGER, moved_value.type());
380 EXPECT_EQ(74, moved_value.GetInt());
381
382 Value blank;
383
384 blank = Value(47);
385 EXPECT_EQ(Value::Type::INTEGER, blank.type());
386 EXPECT_EQ(47, blank.GetInt());
387 }
388
TEST(ValuesTest,MoveDouble)389 TEST(ValuesTest, MoveDouble) {
390 Value value(74.896);
391 Value moved_value(std::move(value));
392 EXPECT_EQ(Value::Type::DOUBLE, moved_value.type());
393 EXPECT_EQ(74.896, moved_value.GetDouble());
394
395 Value blank;
396
397 blank = Value(654.38);
398 EXPECT_EQ(Value::Type::DOUBLE, blank.type());
399 EXPECT_EQ(654.38, blank.GetDouble());
400 }
401
TEST(ValuesTest,MoveString)402 TEST(ValuesTest, MoveString) {
403 Value value("foobar");
404 Value moved_value(std::move(value));
405 EXPECT_EQ(Value::Type::STRING, moved_value.type());
406 EXPECT_EQ("foobar", moved_value.GetString());
407
408 Value blank;
409
410 blank = Value("foobar");
411 EXPECT_EQ(Value::Type::STRING, blank.type());
412 EXPECT_EQ("foobar", blank.GetString());
413 }
414
TEST(ValuesTest,MoveBinary)415 TEST(ValuesTest, MoveBinary) {
416 const Value::BlobStorage buffer = {0xF, 0x0, 0x0, 0xB, 0xA, 0x2};
417 Value value(buffer);
418 Value moved_value(std::move(value));
419 EXPECT_EQ(Value::Type::BINARY, moved_value.type());
420 EXPECT_EQ(buffer, moved_value.GetBlob());
421
422 Value blank;
423
424 blank = Value(buffer);
425 EXPECT_EQ(Value::Type::BINARY, blank.type());
426 EXPECT_EQ(buffer, blank.GetBlob());
427 }
428
TEST(ValuesTest,MoveConstructDictionary)429 TEST(ValuesTest, MoveConstructDictionary) {
430 Value::Dict dict;
431 dict.Set("Int", 123);
432
433 Value value(std::move(dict));
434 Value moved_value(std::move(value));
435 EXPECT_EQ(Value::Type::DICT, moved_value.type());
436 EXPECT_EQ(123, moved_value.GetDict().Find("Int")->GetInt());
437 }
438
TEST(ValuesTest,MoveAssignDictionary)439 TEST(ValuesTest, MoveAssignDictionary) {
440 Value::Dict dict;
441 dict.Set("Int", 123);
442
443 Value blank;
444 blank = Value(std::move(dict));
445 EXPECT_EQ(Value::Type::DICT, blank.type());
446 EXPECT_EQ(123, blank.GetDict().Find("Int")->GetInt());
447 }
448
TEST(ValuesTest,ConstructDictWithIterators)449 TEST(ValuesTest, ConstructDictWithIterators) {
450 std::vector<std::pair<std::string, Value>> values;
451 values.emplace_back(std::make_pair("Int", 123));
452
453 Value blank;
454 blank = Value(Value::Dict(std::make_move_iterator(values.begin()),
455 std::make_move_iterator(values.end())));
456 EXPECT_EQ(Value::Type::DICT, blank.type());
457 EXPECT_EQ(123, blank.GetDict().Find("Int")->GetInt());
458 }
459
TEST(ValuesTest,MoveList)460 TEST(ValuesTest, MoveList) {
461 Value::List list;
462 list.Append(123);
463 Value value(list.Clone());
464 Value moved_value(std::move(value));
465 EXPECT_EQ(Value::Type::LIST, moved_value.type());
466 EXPECT_EQ(123, moved_value.GetList().back().GetInt());
467
468 Value blank;
469 blank = Value(std::move(list));
470 EXPECT_EQ(Value::Type::LIST, blank.type());
471 EXPECT_EQ(123, blank.GetList().back().GetInt());
472 }
473
TEST(ValuesTest,Append)474 TEST(ValuesTest, Append) {
475 Value::List list;
476 list.Append(true);
477 EXPECT_TRUE(list.back().is_bool());
478
479 list.Append(123);
480 EXPECT_TRUE(list.back().is_int());
481
482 list.Append(3.14);
483 EXPECT_TRUE(list.back().is_double());
484
485 std::string str = "foo";
486 list.Append(str.c_str());
487 EXPECT_TRUE(list.back().is_string());
488
489 list.Append(StringPiece(str));
490 EXPECT_TRUE(list.back().is_string());
491
492 list.Append(std::move(str));
493 EXPECT_TRUE(list.back().is_string());
494
495 std::u16string str16 = u"bar";
496 list.Append(str16.c_str());
497 EXPECT_TRUE(list.back().is_string());
498
499 list.Append(base::StringPiece16(str16));
500 EXPECT_TRUE(list.back().is_string());
501
502 list.Append(Value());
503 EXPECT_TRUE(list.back().is_none());
504
505 list.Append(Value::Dict());
506 EXPECT_TRUE(list.back().is_dict());
507
508 list.Append(Value::List());
509 EXPECT_TRUE(list.back().is_list());
510 }
511
TEST(ValuesTest,ListInsert)512 TEST(ValuesTest, ListInsert) {
513 Value::List list;
514 const Value::List& const_list = list;
515
516 auto iter = list.Insert(list.end(), Value(true));
517 EXPECT_TRUE(list.begin() == iter);
518 EXPECT_EQ(*iter, true);
519
520 iter = list.Insert(const_list.begin(), Value(123));
521 EXPECT_TRUE(const_list.begin() == iter);
522 EXPECT_EQ(*iter, 123);
523
524 iter = list.Insert(list.begin() + 1, Value("Hello world!"));
525 EXPECT_TRUE(list.begin() + 1 == iter);
526 EXPECT_EQ(*iter, "Hello world!");
527 }
528
TEST(ValuesTest,ListResize)529 TEST(ValuesTest, ListResize) {
530 auto list = base::Value::List().Append("Hello world!");
531 EXPECT_EQ(list.size(), 1U);
532
533 list.resize(2);
534 // Adds an empty entry to the back to match the size.
535 EXPECT_EQ(list.size(), 2U);
536 EXPECT_TRUE(list[0].is_string());
537 EXPECT_TRUE(list[1].is_none());
538
539 list.resize(1);
540 // Shrinks the list and kicks the new entry out.
541 EXPECT_EQ(list.size(), 1U);
542 EXPECT_TRUE(list[0].is_string());
543
544 list.resize(0);
545 // Removes the remaining entry too.
546 EXPECT_EQ(list.size(), 0U);
547 }
548
TEST(ValuesTest,ReverseIter)549 TEST(ValuesTest, ReverseIter) {
550 Value::List list;
551 const Value::List& const_list = list;
552
553 list.Append(Value(true));
554 list.Append(Value(123));
555 list.Append(Value("Hello world!"));
556
557 auto iter = list.rbegin();
558 EXPECT_TRUE(const_list.rbegin() == iter);
559 EXPECT_EQ(*iter, "Hello world!");
560
561 ++iter;
562 EXPECT_EQ(*iter, 123);
563
564 ++iter;
565 EXPECT_EQ(*iter, true);
566
567 ++iter;
568 EXPECT_TRUE(list.rend() == iter);
569 EXPECT_TRUE(const_list.rend() == iter);
570 }
571
572 // Test all three behaviors of EnsureDict() (Create a new dict where no
573 // matchining values exist, return an existing dict, create a dict overwriting
574 // a value of another type).
TEST(ValuesTest,DictEnsureDict)575 TEST(ValuesTest, DictEnsureDict) {
576 Value::Dict root;
577
578 // This call should create a new nested dictionary.
579 Value::Dict* foo_dict = root.EnsureDict("foo");
580 EXPECT_TRUE(foo_dict->empty());
581 foo_dict->Set("a", "b");
582
583 // This call should retrieve the dictionary created above, rather than
584 // creating a new one.
585 std::string* a_string = root.EnsureDict("foo")->FindString("a");
586 ASSERT_NE(nullptr, a_string);
587 EXPECT_EQ(*a_string, "b");
588
589 // Use EnsureDict() to overwrite an existing non-dictionary value.
590 root.Set("bar", 3);
591 Value::Dict* bar_dict = root.EnsureDict("bar");
592 EXPECT_TRUE(bar_dict->empty());
593 bar_dict->Set("b", "c");
594
595 // Test that the above call created a "bar" entry.
596 bar_dict = root.FindDict("bar");
597 ASSERT_NE(nullptr, bar_dict);
598 std::string* b_string = bar_dict->FindString("b");
599 ASSERT_NE(nullptr, b_string);
600 EXPECT_EQ(*b_string, "c");
601 }
602
603 // Test all three behaviors of EnsureList() (Create a new list where no
604 // matchining value exists, return an existing list, create a list overwriting
605 // a value of another type).
TEST(ValuesTest,DictEnsureList)606 TEST(ValuesTest, DictEnsureList) {
607 Value::Dict root;
608
609 // This call should create a new list.
610 Value::List* foo_list = root.EnsureList("foo");
611 EXPECT_TRUE(foo_list->empty());
612 foo_list->Append("a");
613
614 // This call should retrieve the list created above, rather than creating a
615 // new one.
616 foo_list = root.EnsureList("foo");
617 ASSERT_EQ(1u, foo_list->size());
618 EXPECT_EQ((*foo_list)[0], Value("a"));
619
620 // Use EnsureList() to overwrite an existing non-list value.
621 root.Set("bar", 3);
622 Value::List* bar_list = root.EnsureList("bar");
623 EXPECT_TRUE(bar_list->empty());
624 bar_list->Append("b");
625
626 // Test that the above call created a "bar" entry.
627 bar_list = root.FindList("bar");
628 ASSERT_NE(nullptr, bar_list);
629 ASSERT_EQ(1u, bar_list->size());
630 EXPECT_EQ((*bar_list)[0], Value("b"));
631 }
632
633 // TODO(dcheng): Add more tests directly exercising the updated dictionary and
634 // list APIs. For now, most of the updated APIs are tested indirectly via the
635 // legacy APIs that are largely backed by the updated APIs.
TEST(ValuesTest,DictFindByDottedPath)636 TEST(ValuesTest, DictFindByDottedPath) {
637 Value::Dict dict;
638
639 EXPECT_EQ(nullptr, dict.FindByDottedPath("a.b.c"));
640
641 Value::Dict& a_dict = dict.Set("a", Value::Dict())->GetDict();
642 EXPECT_EQ(nullptr, dict.FindByDottedPath("a.b.c"));
643
644 Value::Dict& b_dict = a_dict.Set("b", Value::Dict())->GetDict();
645 EXPECT_EQ(nullptr, dict.FindByDottedPath("a.b.c"));
646
647 b_dict.Set("c", true);
648 const Value* value = dict.FindByDottedPath("a.b.c");
649 ASSERT_NE(nullptr, value);
650 EXPECT_TRUE(value->GetBool());
651 }
652
TEST(ValuesTest,DictSetByDottedPath)653 TEST(ValuesTest, DictSetByDottedPath) {
654 Value::Dict dict;
655
656 Value* c = dict.SetByDottedPath("a.b.c", Value());
657 ASSERT_TRUE(c);
658
659 Value::Dict* a = dict.FindDict("a");
660 ASSERT_TRUE(a);
661 EXPECT_EQ(1U, a->size());
662
663 Value::Dict* b = a->FindDict("b");
664 ASSERT_TRUE(b);
665 EXPECT_EQ(1U, b->size());
666
667 EXPECT_EQ(c, b->Find("c"));
668 }
669
TEST(ValuesTest,RvalueDictSetByDottedPath)670 TEST(ValuesTest, RvalueDictSetByDottedPath) {
671 Value::Dict dict =
672 Value::Dict()
673 .SetByDottedPath("nested.dictionary.null", Value())
674 .SetByDottedPath("nested.dictionary.bool", false)
675 .SetByDottedPath("nested.dictionary.int", 42)
676 .SetByDottedPath("nested.dictionary.double", 1.2)
677 .SetByDottedPath("nested.dictionary.string", "value")
678 .SetByDottedPath("nested.dictionary.u16-string", u"u16-value")
679 .SetByDottedPath("nested.dictionary.std-string",
680 std::string("std-value"))
681 .SetByDottedPath("nested.dictionary.blob", Value::BlobStorage({1, 2}))
682 .SetByDottedPath("nested.dictionary.list",
683 Value::List().Append("value in list"))
684 .SetByDottedPath("nested.dictionary.dict",
685 Value::Dict().Set("key", "value"));
686
687 Value::Dict expected =
688 Value::Dict() //
689 .Set("nested",
690 base::Value::Dict() //
691 .Set("dictionary",
692 base::Value::Dict()
693 .Set("null", Value())
694 .Set("bool", false)
695 .Set("int", 42)
696 .Set("double", 1.2)
697 .Set("string", "value")
698 .Set("u16-string", u"u16-value")
699 .Set("std-string", std::string("std-value"))
700 .Set("blob", Value::BlobStorage({1, 2}))
701 .Set("list", Value::List().Append("value in list"))
702 .Set("dict", Value::Dict().Set("key", "value"))));
703
704 EXPECT_EQ(dict, expected);
705 }
706
TEST(ValuesTest,DictSetWithDottedKey)707 TEST(ValuesTest, DictSetWithDottedKey) {
708 Value::Dict dict;
709
710 Value* abc = dict.Set("a.b.c", Value());
711 ASSERT_TRUE(abc);
712
713 EXPECT_FALSE(dict.FindByDottedPath("a"));
714 EXPECT_FALSE(dict.FindByDottedPath("a.b"));
715 EXPECT_FALSE(dict.FindByDottedPath("a.b.c"));
716
717 EXPECT_EQ(abc, dict.Find("a.b.c"));
718 }
719
TEST(ValuesTest,ListFront)720 TEST(ValuesTest, ListFront) {
721 Value::List list;
722 const Value::List& const_list = list;
723
724 list.Append(1);
725 list.Append(2);
726 list.Append(3);
727
728 EXPECT_EQ(Value(1), list.front());
729 EXPECT_EQ(Value(1), const_list.front());
730 }
731
TEST(ValuesTest,ListFrontWhenEmpty)732 TEST(ValuesTest, ListFrontWhenEmpty) {
733 Value::List list;
734 const Value::List& const_list = list;
735
736 EXPECT_CHECK_DEATH(list.front());
737 EXPECT_CHECK_DEATH(const_list.front());
738 }
739
TEST(ValuesTest,ListBack)740 TEST(ValuesTest, ListBack) {
741 Value::List list;
742 const Value::List& const_list = list;
743
744 list.Append(1);
745 list.Append(2);
746 list.Append(3);
747
748 EXPECT_EQ(Value(3), list.back());
749 EXPECT_EQ(Value(3), const_list.back());
750 }
751
TEST(ValuesTest,ListBackWhenEmpty)752 TEST(ValuesTest, ListBackWhenEmpty) {
753 Value::List list;
754 const Value::List& const_list = list;
755
756 EXPECT_CHECK_DEATH(list.back());
757 EXPECT_CHECK_DEATH(const_list.back());
758 }
759
TEST(ValuesTest,ListErase)760 TEST(ValuesTest, ListErase) {
761 Value::List list;
762 list.Append(1);
763 list.Append(2);
764 list.Append(3);
765
766 auto next_it = list.erase(list.begin() + 1);
767 ASSERT_EQ(2u, list.size());
768 EXPECT_EQ(list[0], Value(1));
769 EXPECT_EQ(list[1], Value(3));
770 EXPECT_EQ(*next_it, Value(3));
771 EXPECT_EQ(next_it + 1, list.end());
772 }
773
TEST(ValuesTest,ListEraseRange)774 TEST(ValuesTest, ListEraseRange) {
775 Value::List list;
776 list.Append(1);
777 list.Append(2);
778 list.Append(3);
779 list.Append(4);
780
781 auto next_it = list.erase(list.begin() + 1, list.begin() + 3);
782 ASSERT_EQ(2u, list.size());
783 EXPECT_EQ(list[0], Value(1));
784 EXPECT_EQ(list[1], Value(4));
785 EXPECT_EQ(*next_it, Value(4));
786 EXPECT_EQ(next_it + 1, list.end());
787
788 next_it = list.erase(list.begin() + 1, list.begin() + 1);
789 ASSERT_EQ(2u, list.size());
790 EXPECT_EQ(list[0], Value(1));
791 EXPECT_EQ(list[1], Value(4));
792 EXPECT_EQ(*next_it, Value(4));
793 EXPECT_EQ(next_it + 1, list.end());
794
795 next_it = list.erase(list.begin() + 1, list.end());
796 ASSERT_EQ(1u, list.size());
797 EXPECT_EQ(list[0], Value(1));
798 EXPECT_EQ(next_it, list.end());
799
800 list.clear();
801 next_it = list.erase(list.begin(), list.begin());
802 ASSERT_EQ(0u, list.size());
803 EXPECT_EQ(next_it, list.begin());
804 EXPECT_EQ(next_it, list.end());
805 }
806
TEST(ValuesTest,ListEraseValue)807 TEST(ValuesTest, ListEraseValue) {
808 Value::List list;
809 list.Append(1);
810 list.Append(2);
811 list.Append(2);
812 list.Append(3);
813
814 EXPECT_EQ(2u, list.EraseValue(Value(2)));
815 EXPECT_EQ(2u, list.size());
816 EXPECT_EQ(1, list[0]);
817 EXPECT_EQ(3, list[1]);
818
819 EXPECT_EQ(1u, list.EraseValue(Value(1)));
820 EXPECT_EQ(1u, list.size());
821 EXPECT_EQ(3, list[0]);
822
823 EXPECT_EQ(1u, list.EraseValue(Value(3)));
824 EXPECT_TRUE(list.empty());
825
826 EXPECT_EQ(0u, list.EraseValue(Value(3)));
827 }
828
TEST(ValuesTest,ListEraseIf)829 TEST(ValuesTest, ListEraseIf) {
830 Value::List list;
831 list.Append(1);
832 list.Append(2);
833 list.Append(2);
834 list.Append(3);
835
836 EXPECT_EQ(3u, list.EraseIf([](const auto& val) { return val >= Value(2); }));
837 EXPECT_EQ(1u, list.size());
838 EXPECT_EQ(1, list[0]);
839
840 EXPECT_EQ(1u, list.EraseIf([](const auto& val) { return true; }));
841 EXPECT_TRUE(list.empty());
842
843 EXPECT_EQ(0u, list.EraseIf([](const auto& val) { return true; }));
844 }
845
TEST(ValuesTest,ClearList)846 TEST(ValuesTest, ClearList) {
847 Value::List list;
848 list.Append(1);
849 list.Append(2);
850 list.Append(3);
851 EXPECT_EQ(3u, list.size());
852 EXPECT_FALSE(list.empty());
853
854 list.clear();
855 EXPECT_EQ(0u, list.size());
856 EXPECT_TRUE(list.empty());
857
858 // list.clear() should be idempotent.
859 list.clear();
860 EXPECT_EQ(0u, list.size());
861 EXPECT_TRUE(list.empty());
862 }
863
TEST(ValuesTest,FindKey)864 TEST(ValuesTest, FindKey) {
865 Value::Dict dict;
866 dict.Set("foo", "bar");
867 Value value(std::move(dict));
868 EXPECT_NE(nullptr, value.GetDict().Find("foo"));
869 EXPECT_EQ(nullptr, value.GetDict().Find("baz"));
870 }
871
TEST(ValuesTest,FindKeyChangeValue)872 TEST(ValuesTest, FindKeyChangeValue) {
873 Value::Dict dict;
874 dict.Set("foo", "bar");
875 Value* found = dict.Find("foo");
876 ASSERT_NE(nullptr, found);
877 EXPECT_EQ("bar", found->GetString());
878
879 *found = Value(123);
880 EXPECT_EQ(123, dict.Find("foo")->GetInt());
881 }
882
TEST(ValuesTest,FindKeyConst)883 TEST(ValuesTest, FindKeyConst) {
884 Value::Dict dict;
885 dict.Set("foo", "bar");
886 const Value value(std::move(dict));
887 EXPECT_NE(nullptr, value.GetDict().Find("foo"));
888 EXPECT_EQ(nullptr, value.GetDict().Find("baz"));
889 }
890
TEST(ValuesTest,FindBoolKey)891 TEST(ValuesTest, FindBoolKey) {
892 Value::Dict dict;
893 dict.Set("null", Value());
894 dict.Set("bool", false);
895 dict.Set("int", 0);
896 dict.Set("double", 0.0);
897 dict.Set("string", std::string());
898 dict.Set("blob", Value(Value::BlobStorage()));
899 dict.Set("list", Value::List());
900 dict.Set("dict", Value::Dict());
901
902 EXPECT_EQ(std::nullopt, dict.FindBool("null"));
903 EXPECT_NE(std::nullopt, dict.FindBool("bool"));
904 EXPECT_EQ(std::nullopt, dict.FindBool("int"));
905 EXPECT_EQ(std::nullopt, dict.FindBool("double"));
906 EXPECT_EQ(std::nullopt, dict.FindBool("string"));
907 EXPECT_EQ(std::nullopt, dict.FindBool("blob"));
908 EXPECT_EQ(std::nullopt, dict.FindBool("list"));
909 EXPECT_EQ(std::nullopt, dict.FindBool("dict"));
910 }
911
TEST(ValuesTest,FindIntKey)912 TEST(ValuesTest, FindIntKey) {
913 Value::Dict dict;
914 dict.Set("null", Value());
915 dict.Set("bool", false);
916 dict.Set("int", 0);
917 dict.Set("double", 0.0);
918 dict.Set("string", std::string());
919 dict.Set("blob", Value(Value::BlobStorage()));
920 dict.Set("list", Value::List());
921 dict.Set("dict", Value::Dict());
922
923 EXPECT_EQ(std::nullopt, dict.FindInt("null"));
924 EXPECT_EQ(std::nullopt, dict.FindInt("bool"));
925 EXPECT_NE(std::nullopt, dict.FindInt("int"));
926 EXPECT_EQ(std::nullopt, dict.FindInt("double"));
927 EXPECT_EQ(std::nullopt, dict.FindInt("string"));
928 EXPECT_EQ(std::nullopt, dict.FindInt("blob"));
929 EXPECT_EQ(std::nullopt, dict.FindInt("list"));
930 EXPECT_EQ(std::nullopt, dict.FindInt("dict"));
931 }
932
TEST(ValuesTest,FindStringKey)933 TEST(ValuesTest, FindStringKey) {
934 Value::Dict dict;
935 dict.Set("null", Value());
936 dict.Set("bool", false);
937 dict.Set("int", 0);
938 dict.Set("double", 0.0);
939 dict.Set("string", std::string());
940 dict.Set("blob", Value(Value::BlobStorage()));
941 dict.Set("list", Value::List());
942 dict.Set("dict", Value::Dict());
943
944 EXPECT_EQ(nullptr, dict.FindString("null"));
945 EXPECT_EQ(nullptr, dict.FindString("bool"));
946 EXPECT_EQ(nullptr, dict.FindString("int"));
947 EXPECT_EQ(nullptr, dict.FindString("double"));
948 EXPECT_NE(nullptr, dict.FindString("string"));
949 EXPECT_EQ(nullptr, dict.FindString("blob"));
950 EXPECT_EQ(nullptr, dict.FindString("list"));
951 EXPECT_EQ(nullptr, dict.FindString("dict"));
952 }
953
TEST(ValuesTest,MutableFindStringKey)954 TEST(ValuesTest, MutableFindStringKey) {
955 Value::Dict dict;
956 dict.Set("string", "foo");
957
958 *(dict.FindString("string")) = "bar";
959
960 Value::Dict expected_dict;
961 expected_dict.Set("string", "bar");
962
963 EXPECT_EQ(expected_dict, dict);
964
965 Value value(std::move(dict));
966 Value expected_value(std::move(expected_dict));
967 EXPECT_EQ(expected_value, value);
968 }
969
TEST(ValuesTest,FindDictKey)970 TEST(ValuesTest, FindDictKey) {
971 Value::Dict dict;
972 dict.Set("null", Value());
973 dict.Set("bool", false);
974 dict.Set("int", 0);
975 dict.Set("double", 0.0);
976 dict.Set("string", std::string());
977 dict.Set("blob", Value(Value::BlobStorage()));
978 dict.Set("list", Value::List());
979 dict.Set("dict", Value::Dict());
980
981 EXPECT_EQ(nullptr, dict.FindDict("null"));
982 EXPECT_EQ(nullptr, dict.FindDict("bool"));
983 EXPECT_EQ(nullptr, dict.FindDict("int"));
984 EXPECT_EQ(nullptr, dict.FindDict("double"));
985 EXPECT_EQ(nullptr, dict.FindDict("string"));
986 EXPECT_EQ(nullptr, dict.FindDict("blob"));
987 EXPECT_EQ(nullptr, dict.FindDict("list"));
988 EXPECT_NE(nullptr, dict.FindDict("dict"));
989 }
990
TEST(ValuesTest,FindListKey)991 TEST(ValuesTest, FindListKey) {
992 Value::Dict dict;
993 dict.Set("null", Value());
994 dict.Set("bool", false);
995 dict.Set("int", 0);
996 dict.Set("double", 0.0);
997 dict.Set("string", std::string());
998 dict.Set("blob", Value(Value::BlobStorage()));
999 dict.Set("list", Value::List());
1000 dict.Set("dict", Value::Dict());
1001
1002 EXPECT_EQ(nullptr, dict.FindList("null"));
1003 EXPECT_EQ(nullptr, dict.FindList("bool"));
1004 EXPECT_EQ(nullptr, dict.FindList("int"));
1005 EXPECT_EQ(nullptr, dict.FindList("double"));
1006 EXPECT_EQ(nullptr, dict.FindList("string"));
1007 EXPECT_EQ(nullptr, dict.FindList("blob"));
1008 EXPECT_NE(nullptr, dict.FindList("list"));
1009 EXPECT_EQ(nullptr, dict.FindList("dict"));
1010 }
1011
TEST(ValuesTest,FindBlob)1012 TEST(ValuesTest, FindBlob) {
1013 Value::Dict dict;
1014 dict.Set("null", Value());
1015 dict.Set("bool", false);
1016 dict.Set("int", 0);
1017 dict.Set("double", 0.0);
1018 dict.Set("string", std::string());
1019 dict.Set("blob", Value(Value::BlobStorage()));
1020 dict.Set("list", Value::List());
1021 dict.Set("dict", Value::Dict());
1022
1023 EXPECT_EQ(nullptr, dict.FindBlob("null"));
1024 EXPECT_EQ(nullptr, dict.FindBlob("bool"));
1025 EXPECT_EQ(nullptr, dict.FindBlob("int"));
1026 EXPECT_EQ(nullptr, dict.FindBlob("double"));
1027 EXPECT_EQ(nullptr, dict.FindBlob("string"));
1028 EXPECT_NE(nullptr, dict.FindBlob("blob"));
1029 EXPECT_EQ(nullptr, dict.FindBlob("list"));
1030 EXPECT_EQ(nullptr, dict.FindBlob("dict"));
1031 }
1032
TEST(ValuesTest,SetKey)1033 TEST(ValuesTest, SetKey) {
1034 Value::Dict dict;
1035 dict.Set("null", Value());
1036 dict.Set("bool", false);
1037 dict.Set("int", 0);
1038 dict.Set("double", 0.0);
1039 dict.Set("string", std::string());
1040 dict.Set("blob", Value(Value::BlobStorage()));
1041 dict.Set("list", Value::List());
1042 dict.Set("dict", Value::Dict());
1043
1044 Value::Dict dict2;
1045 dict2.Set(StringPiece("null"), Value(Value::Type::NONE));
1046 dict2.Set(StringPiece("bool"), Value(Value::Type::BOOLEAN));
1047 dict2.Set(std::string("int"), Value(Value::Type::INTEGER));
1048 dict2.Set(std::string("double"), Value(Value::Type::DOUBLE));
1049 dict2.Set(std::string("string"), Value(Value::Type::STRING));
1050 dict2.Set("blob", Value(Value::Type::BINARY));
1051 dict2.Set("list", Value(Value::Type::LIST));
1052 dict2.Set("dict", Value(Value::Type::DICT));
1053
1054 EXPECT_EQ(dict, dict2);
1055 EXPECT_EQ(Value(std::move(dict)), Value(std::move(dict2)));
1056 }
1057
TEST(ValuesTest,SetBoolKey)1058 TEST(ValuesTest, SetBoolKey) {
1059 std::optional<bool> value;
1060
1061 Value::Dict dict;
1062 dict.Set("true_key", true);
1063 dict.Set("false_key", false);
1064
1065 value = dict.FindBool("true_key");
1066 ASSERT_TRUE(value);
1067 ASSERT_TRUE(*value);
1068
1069 value = dict.FindBool("false_key");
1070 ASSERT_TRUE(value);
1071 ASSERT_FALSE(*value);
1072
1073 value = dict.FindBool("missing_key");
1074 ASSERT_FALSE(value);
1075 }
1076
TEST(ValuesTest,SetIntKey)1077 TEST(ValuesTest, SetIntKey) {
1078 std::optional<int> value;
1079
1080 Value::Dict dict;
1081 dict.Set("one_key", 1);
1082 dict.Set("minus_one_key", -1);
1083
1084 value = dict.FindInt("one_key");
1085 ASSERT_TRUE(value);
1086 ASSERT_EQ(1, *value);
1087
1088 value = dict.FindInt("minus_one_key");
1089 ASSERT_TRUE(value);
1090 ASSERT_EQ(-1, *value);
1091
1092 value = dict.FindInt("missing_key");
1093 ASSERT_FALSE(value);
1094 }
1095
TEST(ValuesTest,SetDoubleKey)1096 TEST(ValuesTest, SetDoubleKey) {
1097 Value::Dict dict;
1098 dict.Set("one_key", 1.0);
1099 dict.Set("minus_one_key", -1.0);
1100 dict.Set("pi_key", 3.1415);
1101
1102 const Value* value;
1103
1104 value = dict.Find("one_key");
1105 ASSERT_TRUE(value);
1106 EXPECT_TRUE(value->is_double());
1107 EXPECT_EQ(1.0, value->GetDouble());
1108
1109 value = dict.Find("minus_one_key");
1110 ASSERT_TRUE(value);
1111 EXPECT_TRUE(value->is_double());
1112 EXPECT_EQ(-1.0, value->GetDouble());
1113
1114 value = dict.Find("pi_key");
1115 ASSERT_TRUE(value);
1116 EXPECT_TRUE(value->is_double());
1117 EXPECT_EQ(3.1415, value->GetDouble());
1118 }
1119
TEST(ValuesTest,SetStringKey)1120 TEST(ValuesTest, SetStringKey) {
1121 Value::Dict dict;
1122 dict.Set("one_key", "one");
1123 dict.Set("hello_key", "hello world");
1124
1125 std::string movable_value("movable_value");
1126 dict.Set("movable_key", std::move(movable_value));
1127 ASSERT_TRUE(movable_value.empty());
1128
1129 const std::string* value;
1130
1131 value = dict.FindString("one_key");
1132 ASSERT_TRUE(value);
1133 ASSERT_EQ("one", *value);
1134
1135 value = dict.FindString("hello_key");
1136 ASSERT_TRUE(value);
1137 ASSERT_EQ("hello world", *value);
1138
1139 value = dict.FindString("movable_key");
1140 ASSERT_TRUE(value);
1141 ASSERT_EQ("movable_value", *value);
1142
1143 value = dict.FindString("missing_key");
1144 ASSERT_FALSE(value);
1145 }
1146
TEST(ValuesTest,RvalueSet)1147 TEST(ValuesTest, RvalueSet) {
1148 Value::Dict dict = Value::Dict()
1149 .Set("null", Value())
1150 .Set("bool", false)
1151 .Set("int", 42)
1152 .Set("double", 1.2)
1153 .Set("string", "value")
1154 .Set("u16-string", u"u16-value")
1155 .Set("std-string", std::string("std-value"))
1156 .Set("blob", Value::BlobStorage({1, 2}))
1157 .Set("list", Value::List().Append("value in list"))
1158 .Set("dict", Value::Dict().Set("key", "value"));
1159
1160 Value::Dict expected;
1161 expected.Set("null", Value());
1162 expected.Set("bool", false);
1163 expected.Set("int", 42);
1164 expected.Set("double", 1.2);
1165 expected.Set("string", "value");
1166 expected.Set("u16-string", u"u16-value");
1167 expected.Set("std-string", std::string("std-value"));
1168 expected.Set("blob", Value::BlobStorage({1, 2}));
1169 Value::List nested_list;
1170 nested_list.Append("value in list");
1171 expected.Set("list", std::move(nested_list));
1172 Value::Dict nested_dict;
1173 nested_dict.Set("key", "value");
1174 expected.Set("dict", std::move(nested_dict));
1175
1176 EXPECT_EQ(dict, expected);
1177 }
1178
TEST(ValuesTest,FindPath)1179 TEST(ValuesTest, FindPath) {
1180 // Construct a dictionary path {root}.foo.bar = 123
1181 Value::Dict foo;
1182 foo.Set("bar", Value(123));
1183
1184 Value::Dict root;
1185 root.Set("foo", std::move(foo));
1186
1187 // Double key, second not found.
1188 Value* found = root.FindByDottedPath("foo.notfound");
1189 EXPECT_FALSE(found);
1190
1191 // Double key, found.
1192 found = root.FindByDottedPath("foo.bar");
1193 EXPECT_TRUE(found);
1194 EXPECT_TRUE(found->is_int());
1195 EXPECT_EQ(123, found->GetInt());
1196 }
1197
TEST(ValuesTest,SetByDottedPath)1198 TEST(ValuesTest, SetByDottedPath) {
1199 Value::Dict root;
1200
1201 Value* inserted = root.SetByDottedPath("one.two", Value(123));
1202 Value* found = root.FindByDottedPath("one.two");
1203 ASSERT_TRUE(found);
1204 EXPECT_EQ(found->type(), Value::Type::INTEGER);
1205 EXPECT_EQ(inserted, found);
1206 EXPECT_EQ(123, found->GetInt());
1207
1208 inserted = root.SetByDottedPath("foo.bar", Value(123));
1209 found = root.FindByDottedPath("foo.bar");
1210 ASSERT_TRUE(found);
1211 EXPECT_EQ(found->type(), Value::Type::INTEGER);
1212 EXPECT_EQ(inserted, found);
1213 EXPECT_EQ(123, found->GetInt());
1214
1215 // Overwrite with a different value.
1216 root.SetByDottedPath("foo.bar", Value("hello"));
1217 found = root.FindByDottedPath("foo.bar");
1218 ASSERT_TRUE(found);
1219 EXPECT_EQ(found->type(), Value::Type::STRING);
1220 EXPECT_EQ("hello", found->GetString());
1221
1222 // Can't change existing non-dictionary keys to dictionaries.
1223 found = root.SetByDottedPath("foo.bar.baz", Value(123));
1224 EXPECT_FALSE(found);
1225 }
1226
TEST(ValuesTest,SetBoolPath)1227 TEST(ValuesTest, SetBoolPath) {
1228 Value::Dict root;
1229 Value* inserted = root.SetByDottedPath("foo.bar", true);
1230 Value* found = root.FindByDottedPath("foo.bar");
1231 ASSERT_TRUE(found);
1232 EXPECT_EQ(inserted, found);
1233 ASSERT_TRUE(found->is_bool());
1234 EXPECT_TRUE(found->GetBool());
1235
1236 // Overwrite with a different value.
1237 root.SetByDottedPath("foo.bar", false);
1238 found = root.FindByDottedPath("foo.bar");
1239 ASSERT_TRUE(found);
1240 ASSERT_TRUE(found->is_bool());
1241 EXPECT_FALSE(found->GetBool());
1242
1243 // Can't change existing non-dictionary keys.
1244 ASSERT_FALSE(root.SetByDottedPath("foo.bar.zoo", true));
1245 }
1246
TEST(ValuesTest,SetIntPath)1247 TEST(ValuesTest, SetIntPath) {
1248 Value::Dict root;
1249 Value* inserted = root.SetByDottedPath("foo.bar", 123);
1250 Value* found = root.FindByDottedPath("foo.bar");
1251 ASSERT_TRUE(found);
1252 EXPECT_EQ(inserted, found);
1253 ASSERT_TRUE(found->is_int());
1254 EXPECT_EQ(123, found->GetInt());
1255
1256 // Overwrite with a different value.
1257 root.SetByDottedPath("foo.bar", 234);
1258 found = root.FindByDottedPath("foo.bar");
1259 ASSERT_TRUE(found);
1260 ASSERT_TRUE(found->is_int());
1261 EXPECT_EQ(234, found->GetInt());
1262
1263 // Can't change existing non-dictionary keys.
1264 ASSERT_FALSE(root.SetByDottedPath("foo.bar.zoo", 567));
1265 }
1266
TEST(ValuesTest,SetDoublePath)1267 TEST(ValuesTest, SetDoublePath) {
1268 Value::Dict root;
1269 Value* inserted = root.SetByDottedPath("foo.bar", 1.23);
1270 Value* found = root.FindByDottedPath("foo.bar");
1271 ASSERT_TRUE(found);
1272 EXPECT_EQ(inserted, found);
1273 ASSERT_TRUE(found->is_double());
1274 EXPECT_EQ(1.23, found->GetDouble());
1275
1276 // Overwrite with a different value.
1277 root.SetByDottedPath("foo.bar", 2.34);
1278 found = root.FindByDottedPath("foo.bar");
1279 ASSERT_TRUE(found);
1280 ASSERT_TRUE(found->is_double());
1281 EXPECT_EQ(2.34, found->GetDouble());
1282
1283 // Can't change existing non-dictionary keys.
1284 ASSERT_FALSE(root.SetByDottedPath("foo.bar.zoo", 5.67));
1285 }
1286
TEST(ValuesTest,SetStringPath)1287 TEST(ValuesTest, SetStringPath) {
1288 Value::Dict root;
1289 Value* inserted = root.SetByDottedPath("foo.bar", "hello world");
1290 Value* found = root.FindByDottedPath("foo.bar");
1291 ASSERT_TRUE(found);
1292 EXPECT_EQ(inserted, found);
1293 ASSERT_TRUE(found->is_string());
1294 EXPECT_EQ("hello world", found->GetString());
1295
1296 // Overwrite with a different value.
1297 root.SetByDottedPath("foo.bar", "bonjour monde");
1298 found = root.FindByDottedPath("foo.bar");
1299 ASSERT_TRUE(found);
1300 ASSERT_TRUE(found->is_string());
1301 EXPECT_EQ("bonjour monde", found->GetString());
1302
1303 ASSERT_TRUE(root.SetByDottedPath("foo.bar", StringPiece("rah rah")));
1304 ASSERT_TRUE(root.SetByDottedPath("foo.bar", std::string("temp string")));
1305 ASSERT_TRUE(root.SetByDottedPath("foo.bar", u"temp string"));
1306
1307 // Can't change existing non-dictionary keys.
1308 ASSERT_FALSE(root.SetByDottedPath("foo.bar.zoo", "ola mundo"));
1309 }
1310
TEST(ValuesTest,Remove)1311 TEST(ValuesTest, Remove) {
1312 Value::Dict root;
1313 root.Set("one", Value(123));
1314
1315 // Removal of missing key should fail.
1316 EXPECT_FALSE(root.Remove("two"));
1317
1318 // Removal of existing key should succeed.
1319 EXPECT_TRUE(root.Remove("one"));
1320
1321 // Second removal of previously existing key should fail.
1322 EXPECT_FALSE(root.Remove("one"));
1323 }
1324
TEST(ValuesTest,Extract)1325 TEST(ValuesTest, Extract) {
1326 Value::Dict root;
1327 root.Set("one", Value(123));
1328
1329 // Extraction of missing key should fail.
1330 EXPECT_EQ(std::nullopt, root.Extract("two"));
1331
1332 // Extraction of existing key should succeed.
1333 EXPECT_EQ(Value(123), root.Extract("one"));
1334
1335 // Second extraction of previously existing key should fail.
1336 EXPECT_EQ(std::nullopt, root.Extract("one"));
1337 }
1338
TEST(ValuesTest,RemoveByDottedPath)1339 TEST(ValuesTest, RemoveByDottedPath) {
1340 Value::Dict root;
1341 root.SetByDottedPath("one.two.three", Value(123));
1342
1343 // Removal of missing key should fail.
1344 EXPECT_FALSE(root.RemoveByDottedPath("one.two.four"));
1345
1346 // Removal of existing key should succeed.
1347 EXPECT_TRUE(root.RemoveByDottedPath("one.two.three"));
1348
1349 // Second removal of previously existing key should fail.
1350 EXPECT_FALSE(root.RemoveByDottedPath("one.two.three"));
1351
1352 // Intermediate empty dictionaries should be cleared.
1353 EXPECT_EQ(nullptr, root.Find("one"));
1354
1355 root.SetByDottedPath("one.two.three", Value(123));
1356 root.SetByDottedPath("one.two.four", Value(124));
1357
1358 EXPECT_TRUE(root.RemoveByDottedPath("one.two.three"));
1359 // Intermediate non-empty dictionaries should be kept.
1360 EXPECT_NE(nullptr, root.Find("one"));
1361 EXPECT_NE(nullptr, root.FindByDottedPath("one.two"));
1362 EXPECT_NE(nullptr, root.FindByDottedPath("one.two.four"));
1363 }
1364
TEST(ValuesTest,ExtractByDottedPath)1365 TEST(ValuesTest, ExtractByDottedPath) {
1366 Value::Dict root;
1367 root.SetByDottedPath("one.two.three", Value(123));
1368
1369 // Extraction of missing key should fail.
1370 EXPECT_EQ(std::nullopt, root.ExtractByDottedPath("one.two.four"));
1371
1372 // Extraction of existing key should succeed.
1373 EXPECT_EQ(Value(123), root.ExtractByDottedPath("one.two.three"));
1374
1375 // Second extraction of previously existing key should fail.
1376 EXPECT_EQ(std::nullopt, root.ExtractByDottedPath("one.two.three"));
1377
1378 // Intermediate empty dictionaries should be cleared.
1379 EXPECT_EQ(nullptr, root.Find("one"));
1380
1381 root.SetByDottedPath("one.two.three", Value(123));
1382 root.SetByDottedPath("one.two.four", Value(124));
1383
1384 EXPECT_EQ(Value(123), root.ExtractByDottedPath("one.two.three"));
1385 // Intermediate non-empty dictionaries should be kept.
1386 EXPECT_NE(nullptr, root.Find("one"));
1387 EXPECT_NE(nullptr, root.FindByDottedPath("one.two"));
1388 EXPECT_NE(nullptr, root.FindByDottedPath("one.two.four"));
1389 }
1390
TEST(ValuesTest,Basic)1391 TEST(ValuesTest, Basic) {
1392 // Test basic dictionary getting/setting
1393 Value::Dict settings;
1394 ASSERT_FALSE(settings.FindByDottedPath("global.homepage"));
1395
1396 ASSERT_FALSE(settings.Find("global"));
1397 settings.Set("global", Value(true));
1398 ASSERT_TRUE(settings.Find("global"));
1399 settings.Remove("global");
1400 settings.SetByDottedPath("global.homepage", Value("http://scurvy.com"));
1401 ASSERT_TRUE(settings.Find("global"));
1402 const std::string* homepage =
1403 settings.FindStringByDottedPath("global.homepage");
1404 ASSERT_TRUE(homepage);
1405 ASSERT_EQ(std::string("http://scurvy.com"), *homepage);
1406
1407 // Test storing a dictionary in a list.
1408 ASSERT_FALSE(settings.FindByDottedPath("global.toolbar.bookmarks"));
1409
1410 Value::List new_toolbar_bookmarks;
1411 settings.SetByDottedPath("global.toolbar.bookmarks",
1412 std::move(new_toolbar_bookmarks));
1413 Value::List* toolbar_bookmarks =
1414 settings.FindListByDottedPath("global.toolbar.bookmarks");
1415 ASSERT_TRUE(toolbar_bookmarks);
1416
1417 Value::Dict new_bookmark;
1418 new_bookmark.Set("name", Value("Froogle"));
1419 new_bookmark.Set("url", Value("http://froogle.com"));
1420 toolbar_bookmarks->Append(std::move(new_bookmark));
1421
1422 Value* bookmark_list = settings.FindByDottedPath("global.toolbar.bookmarks");
1423 ASSERT_TRUE(bookmark_list);
1424 ASSERT_EQ(1U, bookmark_list->GetList().size());
1425 Value* bookmark = &bookmark_list->GetList()[0];
1426 ASSERT_TRUE(bookmark);
1427 ASSERT_TRUE(bookmark->is_dict());
1428 const std::string* bookmark_name = bookmark->GetDict().FindString("name");
1429 ASSERT_TRUE(bookmark_name);
1430 ASSERT_EQ(std::string("Froogle"), *bookmark_name);
1431 const std::string* bookmark_url = bookmark->GetDict().FindString("url");
1432 ASSERT_TRUE(bookmark_url);
1433 ASSERT_EQ(std::string("http://froogle.com"), *bookmark_url);
1434 }
1435
TEST(ValuesTest,List)1436 TEST(ValuesTest, List) {
1437 Value::List mixed_list;
1438 mixed_list.Append(true);
1439 mixed_list.Append(42);
1440 mixed_list.Append(88.8);
1441 mixed_list.Append("foo");
1442
1443 ASSERT_EQ(4u, mixed_list.size());
1444
1445 EXPECT_EQ(true, mixed_list[0]);
1446 EXPECT_EQ(42, mixed_list[1]);
1447 EXPECT_EQ(88.8, mixed_list[2]);
1448 EXPECT_EQ("foo", mixed_list[3]);
1449
1450 // Try searching in the mixed list.
1451 ASSERT_TRUE(Contains(mixed_list, 42));
1452 ASSERT_FALSE(Contains(mixed_list, false));
1453 }
1454
TEST(ValuesTest,RvalueAppend)1455 TEST(ValuesTest, RvalueAppend) {
1456 Value::List list = Value::List()
1457 .Append(Value())
1458 .Append(false)
1459 .Append(42)
1460 .Append(1.2)
1461 .Append("value")
1462 .Append(u"u16-value")
1463 .Append(std::string("std-value"))
1464 .Append(Value::BlobStorage({1, 2}))
1465 .Append(Value::List().Append("value in list"))
1466 .Append(Value::Dict().Set("key", "value"));
1467
1468 Value::List expected;
1469 expected.Append(Value());
1470 expected.Append(false);
1471 expected.Append(42);
1472 expected.Append(1.2);
1473 expected.Append("value");
1474 expected.Append(u"u16-value");
1475 expected.Append(std::string("std-value"));
1476 expected.Append(Value::BlobStorage({1, 2}));
1477 Value::List nested_list;
1478 nested_list.Append("value in list");
1479 expected.Append(std::move(nested_list));
1480 Value::Dict nested_dict;
1481 nested_dict.Set("key", "value");
1482 expected.Append(std::move(nested_dict));
1483
1484 EXPECT_EQ(list, expected);
1485 }
1486
TEST(ValuesTest,ListWithCapacity)1487 TEST(ValuesTest, ListWithCapacity) {
1488 Value::List list_with_capacity =
1489 Value::List::with_capacity(3).Append(true).Append(42).Append(88.8);
1490
1491 ASSERT_EQ(3u, list_with_capacity.size());
1492 }
1493
TEST(ValuesTest,BinaryValue)1494 TEST(ValuesTest, BinaryValue) {
1495 // Default constructor creates a BinaryValue with a buffer of size 0.
1496 Value binary(Value::Type::BINARY);
1497 ASSERT_TRUE(binary.GetBlob().empty());
1498
1499 // Test the common case of a non-empty buffer
1500 Value::BlobStorage buffer(15);
1501 uint8_t* original_buffer = buffer.data();
1502 binary = Value(std::move(buffer));
1503 ASSERT_TRUE(binary.GetBlob().data());
1504 ASSERT_EQ(original_buffer, binary.GetBlob().data());
1505 ASSERT_EQ(15U, binary.GetBlob().size());
1506
1507 char stack_buffer[42];
1508 memset(stack_buffer, '!', 42);
1509 binary = Value(Value::BlobStorage(stack_buffer, stack_buffer + 42));
1510 ASSERT_TRUE(binary.GetBlob().data());
1511 ASSERT_NE(stack_buffer,
1512 reinterpret_cast<const char*>(binary.GetBlob().data()));
1513 ASSERT_EQ(42U, binary.GetBlob().size());
1514 ASSERT_EQ(0, memcmp(stack_buffer, binary.GetBlob().data(),
1515 binary.GetBlob().size()));
1516 }
1517
TEST(ValuesTest,StringValue)1518 TEST(ValuesTest, StringValue) {
1519 // Test overloaded StringValue constructor.
1520 std::unique_ptr<Value> narrow_value(new Value("narrow"));
1521 ASSERT_TRUE(narrow_value.get());
1522 ASSERT_TRUE(narrow_value->is_string());
1523 std::unique_ptr<Value> utf16_value(new Value(u"utf16"));
1524 ASSERT_TRUE(utf16_value.get());
1525 ASSERT_TRUE(utf16_value->is_string());
1526
1527 ASSERT_TRUE(narrow_value->is_string());
1528 ASSERT_EQ(std::string("narrow"), narrow_value->GetString());
1529
1530 ASSERT_TRUE(utf16_value->is_string());
1531 ASSERT_EQ(std::string("utf16"), utf16_value->GetString());
1532 }
1533
TEST(ValuesTest,DictionaryDeletion)1534 TEST(ValuesTest, DictionaryDeletion) {
1535 std::string key = "test";
1536 Value::Dict dict;
1537 dict.Set(key, Value());
1538 EXPECT_FALSE(dict.empty());
1539 EXPECT_EQ(1U, dict.size());
1540 dict.clear();
1541 EXPECT_TRUE(dict.empty());
1542 EXPECT_TRUE(dict.empty());
1543 EXPECT_EQ(0U, dict.size());
1544 }
1545
TEST(ValuesTest,DictionarySetReturnsPointer)1546 TEST(ValuesTest, DictionarySetReturnsPointer) {
1547 {
1548 Value::Dict dict;
1549 Value* blank_ptr = dict.Set("foo.bar", Value());
1550 EXPECT_EQ(Value::Type::NONE, blank_ptr->type());
1551 }
1552
1553 {
1554 Value::Dict dict;
1555 Value* blank_ptr = dict.Set("foo.bar", Value());
1556 EXPECT_EQ(Value::Type::NONE, blank_ptr->type());
1557 }
1558
1559 {
1560 Value::Dict dict;
1561 Value* int_ptr = dict.Set("foo.bar", 42);
1562 EXPECT_EQ(Value::Type::INTEGER, int_ptr->type());
1563 EXPECT_EQ(42, int_ptr->GetInt());
1564 }
1565
1566 {
1567 Value::Dict dict;
1568 Value* string_ptr = dict.Set("foo.bar", "foo");
1569 EXPECT_EQ(Value::Type::STRING, string_ptr->type());
1570 EXPECT_EQ("foo", string_ptr->GetString());
1571 }
1572
1573 {
1574 Value::Dict dict;
1575 Value* string16_ptr = dict.Set("foo.bar", u"baz");
1576 EXPECT_EQ(Value::Type::STRING, string16_ptr->type());
1577 EXPECT_EQ("baz", string16_ptr->GetString());
1578 }
1579
1580 {
1581 Value::Dict dict;
1582 Value* dict_ptr = dict.Set("foo.bar", Value::Dict());
1583 EXPECT_EQ(Value::Type::DICT, dict_ptr->type());
1584 }
1585
1586 {
1587 Value::Dict dict;
1588 Value* list_ptr = dict.Set("foo.bar", Value::List());
1589 EXPECT_EQ(Value::Type::LIST, list_ptr->type());
1590 }
1591 }
1592
TEST(ValuesTest,Clone)1593 TEST(ValuesTest, Clone) {
1594 Value original_null;
1595 Value original_bool(true);
1596 Value original_int(42);
1597 Value original_double(3.14);
1598 Value original_string("hello");
1599 Value original_string16(u"hello16");
1600 Value original_binary(Value::BlobStorage(42, '!'));
1601
1602 Value::List list;
1603 list.Append(0);
1604 list.Append(1);
1605 Value original_list(std::move(list));
1606
1607 Value original_dict(Value::Dict()
1608 .Set("null", original_null.Clone())
1609 .Set("bool", original_bool.Clone())
1610 .Set("int", original_int.Clone())
1611 .Set("double", original_double.Clone())
1612 .Set("string", original_string.Clone())
1613 .Set("string16", original_string16.Clone())
1614 .Set("binary", original_binary.Clone())
1615 .Set("list", original_list.Clone()));
1616
1617 Value copy_value = original_dict.Clone();
1618 const Value::Dict& copy_dict = copy_value.GetDict();
1619 EXPECT_EQ(original_dict, copy_dict);
1620 EXPECT_EQ(original_null, *copy_dict.Find("null"));
1621 EXPECT_EQ(original_bool, *copy_dict.Find("bool"));
1622 EXPECT_EQ(original_int, *copy_dict.Find("int"));
1623 EXPECT_EQ(original_double, *copy_dict.Find("double"));
1624 EXPECT_EQ(original_string, *copy_dict.Find("string"));
1625 EXPECT_EQ(original_string16, *copy_dict.Find("string16"));
1626 EXPECT_EQ(original_binary, *copy_dict.Find("binary"));
1627 EXPECT_EQ(original_list, *copy_dict.Find("list"));
1628 }
1629
TEST(ValuesTest,TakeString)1630 TEST(ValuesTest, TakeString) {
1631 Value value("foo");
1632 std::string taken = std::move(value).TakeString();
1633 EXPECT_EQ(taken, "foo");
1634 }
1635
1636 // Check that the value can still be used after `TakeString()` was called, as
1637 // long as a new value was assigned to it.
TEST(ValuesTest,PopulateAfterTakeString)1638 TEST(ValuesTest, PopulateAfterTakeString) {
1639 Value value("foo");
1640 std::string taken = std::move(value).TakeString();
1641
1642 value = Value(false);
1643 EXPECT_EQ(value, Value(false));
1644 }
1645
TEST(ValuesTest,TakeDict)1646 TEST(ValuesTest, TakeDict) {
1647 Value::Dict dict;
1648 dict.Set("foo", 123);
1649 Value value(std::move(dict));
1650 Value clone = value.Clone();
1651
1652 Value::Dict taken = std::move(value).TakeDict();
1653 EXPECT_EQ(taken, clone);
1654 }
1655
1656 // Check that the value can still be used after `TakeDict()` was called, as long
1657 // as a new value was assigned to it.
TEST(ValuesTest,PopulateAfterTakeDict)1658 TEST(ValuesTest, PopulateAfterTakeDict) {
1659 Value::Dict dict;
1660 dict.Set("foo", 123);
1661 Value value(std::move(dict));
1662 Value::Dict taken = std::move(value).TakeDict();
1663
1664 value = Value(false);
1665 EXPECT_EQ(value, Value(false));
1666 }
1667
TEST(ValuesTest,TakeList)1668 TEST(ValuesTest, TakeList) {
1669 Value::List list;
1670 list.Append(true);
1671 list.Append(123);
1672 Value value(std::move(list));
1673 Value clone = value.Clone();
1674
1675 Value::List taken = std::move(value).TakeList();
1676 EXPECT_EQ(taken, clone);
1677 }
1678
1679 // Check that the value can still be used after `TakeList()` was called, as long
1680 // as a new value was assigned to it.
TEST(ValuesTest,PopulateAfterTakeList)1681 TEST(ValuesTest, PopulateAfterTakeList) {
1682 Value::List list;
1683 list.Append("hello");
1684 Value value(std::move(list));
1685 Value::List taken = std::move(value).TakeList();
1686
1687 value = Value(false);
1688 EXPECT_EQ(value, Value(false));
1689 }
1690
TEST(ValuesTest,SpecializedEquals)1691 TEST(ValuesTest, SpecializedEquals) {
1692 std::vector<Value> values;
1693 values.emplace_back(false);
1694 values.emplace_back(true);
1695 values.emplace_back(0);
1696 values.emplace_back(1);
1697 values.emplace_back(1.0);
1698 values.emplace_back(2.0);
1699 values.emplace_back("hello");
1700 values.emplace_back("world");
1701 base::Value::Dict dict;
1702 dict.Set("hello", "world");
1703 values.emplace_back(std::move(dict));
1704 base::Value::Dict dict2;
1705 dict2.Set("world", "hello");
1706 values.emplace_back(std::move(dict2));
1707 base::Value::List list;
1708 list.Append("hello");
1709 list.Append("world");
1710 values.emplace_back(std::move(list));
1711 base::Value::List list2;
1712 list2.Append("world");
1713 list2.Append("hello");
1714 values.emplace_back(std::move(list2));
1715
1716 for (const Value& outer_value : values) {
1717 for (const Value& inner_value : values) {
1718 SCOPED_TRACE(::testing::Message()
1719 << "Outer: " << outer_value << "Inner: " << inner_value);
1720 const bool should_be_equal = &outer_value == &inner_value;
1721 if (should_be_equal) {
1722 EXPECT_EQ(outer_value, inner_value);
1723 EXPECT_EQ(inner_value, outer_value);
1724 EXPECT_FALSE(outer_value != inner_value);
1725 EXPECT_FALSE(inner_value != outer_value);
1726 } else {
1727 EXPECT_NE(outer_value, inner_value);
1728 EXPECT_NE(inner_value, outer_value);
1729 EXPECT_FALSE(outer_value == inner_value);
1730 EXPECT_FALSE(inner_value == outer_value);
1731 }
1732 // Also test the various overloads for operator== against concrete
1733 // subtypes.
1734 outer_value.Visit([&](const auto& outer_member) {
1735 using T = std::decay_t<decltype(outer_member)>;
1736 if constexpr (!std::is_same_v<T, absl::monostate> &&
1737 !std::is_same_v<T, Value::BlobStorage>) {
1738 if (should_be_equal) {
1739 EXPECT_EQ(outer_member, inner_value);
1740 EXPECT_EQ(inner_value, outer_member);
1741 EXPECT_FALSE(outer_member != inner_value);
1742 EXPECT_FALSE(inner_value != outer_member);
1743 } else {
1744 EXPECT_NE(outer_member, inner_value);
1745 EXPECT_NE(inner_value, outer_member);
1746 EXPECT_FALSE(outer_member == inner_value);
1747 EXPECT_FALSE(inner_value == outer_member);
1748 }
1749 }
1750 });
1751 }
1752
1753 // A copy of a Value should also compare equal to itself.
1754 Value copied_value = outer_value.Clone();
1755 EXPECT_EQ(outer_value, copied_value);
1756 EXPECT_EQ(copied_value, outer_value);
1757 EXPECT_FALSE(outer_value != copied_value);
1758 EXPECT_FALSE(copied_value != outer_value);
1759 }
1760 }
1761
1762 // Test that a literal string comparison does not end up using the bool (!!)
1763 // overload.
TEST(ValuesTest,LiteralStringEquals)1764 TEST(ValuesTest, LiteralStringEquals) {
1765 EXPECT_EQ("hello world", base::Value("hello world"));
1766 EXPECT_EQ(base::Value("hello world"), "hello world");
1767 EXPECT_NE("hello world", base::Value(true));
1768 EXPECT_NE(base::Value(true), "hello world");
1769 }
1770
TEST(ValuesTest,Equals)1771 TEST(ValuesTest, Equals) {
1772 auto null1 = std::make_unique<Value>();
1773 auto null2 = std::make_unique<Value>();
1774 EXPECT_NE(null1.get(), null2.get());
1775 EXPECT_EQ(*null1, *null2);
1776
1777 Value boolean(false);
1778 EXPECT_NE(*null1, boolean);
1779
1780 Value::Dict dv;
1781 dv.Set("a", false);
1782 dv.Set("b", 2);
1783 dv.Set("c", 2.5);
1784 dv.Set("d1", "string");
1785 dv.Set("d2", u"http://google.com");
1786 dv.Set("e", Value());
1787
1788 Value::Dict copy = dv.Clone();
1789 EXPECT_EQ(dv, copy);
1790
1791 Value::List list;
1792 list.Append(Value());
1793 list.Append(Value(Value::Type::DICT));
1794 Value::List list_copy(list.Clone());
1795
1796 Value* list_weak = dv.Set("f", std::move(list));
1797 EXPECT_NE(dv, copy);
1798 copy.Set("f", std::move(list_copy));
1799 EXPECT_EQ(dv, copy);
1800
1801 list_weak->GetList().Append(true);
1802 EXPECT_NE(dv, copy);
1803
1804 // Check if Equals detects differences in only the keys.
1805 copy = dv.Clone();
1806 EXPECT_EQ(dv, copy);
1807 copy.Remove("a");
1808 copy.Set("aa", false);
1809 EXPECT_NE(dv, copy);
1810 }
1811
TEST(ValuesTest,Comparisons)1812 TEST(ValuesTest, Comparisons) {
1813 // Test None Values.
1814 Value null1;
1815 Value null2;
1816 EXPECT_EQ(null1, null2);
1817 EXPECT_FALSE(null1 != null2);
1818 EXPECT_FALSE(null1 < null2);
1819 EXPECT_FALSE(null1 > null2);
1820 EXPECT_LE(null1, null2);
1821 EXPECT_GE(null1, null2);
1822
1823 // Test Bool Values.
1824 Value bool1(false);
1825 Value bool2(true);
1826 EXPECT_FALSE(bool1 == bool2);
1827 EXPECT_NE(bool1, bool2);
1828 EXPECT_LT(bool1, bool2);
1829 EXPECT_FALSE(bool1 > bool2);
1830 EXPECT_LE(bool1, bool2);
1831 EXPECT_FALSE(bool1 >= bool2);
1832
1833 // Test Int Values.
1834 Value int1(1);
1835 Value int2(2);
1836 EXPECT_FALSE(int1 == int2);
1837 EXPECT_NE(int1, int2);
1838 EXPECT_LT(int1, int2);
1839 EXPECT_FALSE(int1 > int2);
1840 EXPECT_LE(int1, int2);
1841 EXPECT_FALSE(int1 >= int2);
1842
1843 // Test Double Values.
1844 Value double1(1.0);
1845 Value double2(2.0);
1846 EXPECT_FALSE(double1 == double2);
1847 EXPECT_NE(double1, double2);
1848 EXPECT_LT(double1, double2);
1849 EXPECT_FALSE(double1 > double2);
1850 EXPECT_LE(double1, double2);
1851 EXPECT_FALSE(double1 >= double2);
1852
1853 // Test String Values.
1854 Value string1("1");
1855 Value string2("2");
1856 EXPECT_FALSE(string1 == string2);
1857 EXPECT_NE(string1, string2);
1858 EXPECT_LT(string1, string2);
1859 EXPECT_FALSE(string1 > string2);
1860 EXPECT_LE(string1, string2);
1861 EXPECT_FALSE(string1 >= string2);
1862
1863 // Test Binary Values.
1864 Value binary1(Value::BlobStorage{0x01});
1865 Value binary2(Value::BlobStorage{0x02});
1866 EXPECT_FALSE(binary1 == binary2);
1867 EXPECT_NE(binary1, binary2);
1868 EXPECT_LT(binary1, binary2);
1869 EXPECT_FALSE(binary1 > binary2);
1870 EXPECT_LE(binary1, binary2);
1871 EXPECT_FALSE(binary1 >= binary2);
1872
1873 // Test Empty List Values.
1874 Value::List null_list1;
1875 Value::List null_list2;
1876 EXPECT_EQ(null_list1, null_list2);
1877 EXPECT_FALSE(null_list1 != null_list2);
1878 EXPECT_FALSE(null_list1 < null_list2);
1879 EXPECT_FALSE(null_list1 > null_list2);
1880 EXPECT_LE(null_list1, null_list2);
1881 EXPECT_GE(null_list1, null_list2);
1882
1883 // Test Non Empty List Values.
1884 Value::List int_list1;
1885 Value::List int_list2;
1886 int_list1.Append(1);
1887 int_list2.Append(2);
1888 EXPECT_FALSE(int_list1 == int_list2);
1889 EXPECT_NE(int_list1, int_list2);
1890 EXPECT_LT(int_list1, int_list2);
1891 EXPECT_FALSE(int_list1 > int_list2);
1892 EXPECT_LE(int_list1, int_list2);
1893 EXPECT_FALSE(int_list1 >= int_list2);
1894
1895 // Test Empty Dict Values.
1896 Value::Dict null_dict1;
1897 Value::Dict null_dict2;
1898 EXPECT_EQ(null_dict1, null_dict2);
1899 EXPECT_FALSE(null_dict1 != null_dict2);
1900 EXPECT_FALSE(null_dict1 < null_dict2);
1901 EXPECT_FALSE(null_dict1 > null_dict2);
1902 EXPECT_LE(null_dict1, null_dict2);
1903 EXPECT_GE(null_dict1, null_dict2);
1904
1905 // Test Non Empty Dict Values.
1906 Value::Dict int_dict1;
1907 Value::Dict int_dict2;
1908 int_dict1.Set("key", 1);
1909 int_dict2.Set("key", 2);
1910 EXPECT_FALSE(int_dict1 == int_dict2);
1911 EXPECT_NE(int_dict1, int_dict2);
1912 EXPECT_LT(int_dict1, int_dict2);
1913 EXPECT_FALSE(int_dict1 > int_dict2);
1914 EXPECT_LE(int_dict1, int_dict2);
1915 EXPECT_FALSE(int_dict1 >= int_dict2);
1916
1917 // Test Values of different types.
1918 std::vector<Value> values;
1919 values.emplace_back(std::move(null1));
1920 values.emplace_back(std::move(bool1));
1921 values.emplace_back(std::move(int1));
1922 values.emplace_back(std::move(double1));
1923 values.emplace_back(std::move(string1));
1924 values.emplace_back(std::move(binary1));
1925 values.emplace_back(std::move(int_dict1));
1926 values.emplace_back(std::move(int_list1));
1927 for (size_t i = 0; i < values.size(); ++i) {
1928 for (size_t j = i + 1; j < values.size(); ++j) {
1929 EXPECT_FALSE(values[i] == values[j]);
1930 EXPECT_NE(values[i], values[j]);
1931 EXPECT_LT(values[i], values[j]);
1932 EXPECT_FALSE(values[i] > values[j]);
1933 EXPECT_LE(values[i], values[j]);
1934 EXPECT_FALSE(values[i] >= values[j]);
1935 }
1936 }
1937 }
1938
TEST(ValuesTest,Merge)1939 TEST(ValuesTest, Merge) {
1940 Value::Dict base;
1941 base.Set("base_key", "base_key_value_base");
1942 base.Set("collide_key", "collide_key_value_base");
1943 Value::Dict base_sub_dict;
1944 base_sub_dict.Set("sub_base_key", "sub_base_key_value_base");
1945 base_sub_dict.Set("sub_collide_key", "sub_collide_key_value_base");
1946 base.Set("sub_dict_key", std::move(base_sub_dict));
1947
1948 Value::Dict merge;
1949 merge.Set("merge_key", "merge_key_value_merge");
1950 merge.Set("collide_key", "collide_key_value_merge");
1951 Value::Dict merge_sub_dict;
1952 merge_sub_dict.Set("sub_merge_key", "sub_merge_key_value_merge");
1953 merge_sub_dict.Set("sub_collide_key", "sub_collide_key_value_merge");
1954 merge.Set("sub_dict_key", std::move(merge_sub_dict));
1955
1956 base.Merge(std::move(merge));
1957
1958 EXPECT_EQ(4U, base.size());
1959 const std::string* base_key_value = base.FindString("base_key");
1960 ASSERT_TRUE(base_key_value);
1961 EXPECT_EQ("base_key_value_base", *base_key_value); // Base value preserved.
1962 const std::string* collide_key_value = base.FindString("collide_key");
1963 ASSERT_TRUE(collide_key_value);
1964 EXPECT_EQ("collide_key_value_merge", *collide_key_value); // Replaced.
1965 const std::string* merge_key_value = base.FindString("merge_key");
1966 ASSERT_TRUE(merge_key_value);
1967 EXPECT_EQ("merge_key_value_merge", *merge_key_value); // Merged in.
1968
1969 Value::Dict* res_sub_dict = base.FindDict("sub_dict_key");
1970 ASSERT_TRUE(res_sub_dict);
1971 EXPECT_EQ(3U, res_sub_dict->size());
1972 const std::string* sub_base_key_value =
1973 res_sub_dict->FindString("sub_base_key");
1974 ASSERT_TRUE(sub_base_key_value);
1975 EXPECT_EQ("sub_base_key_value_base", *sub_base_key_value); // Preserved.
1976 const std::string* sub_collide_key_value =
1977 res_sub_dict->FindString("sub_collide_key");
1978 ASSERT_TRUE(sub_collide_key_value);
1979 EXPECT_EQ("sub_collide_key_value_merge",
1980 *sub_collide_key_value); // Replaced.
1981 const std::string* sub_merge_key_value =
1982 res_sub_dict->FindString("sub_merge_key");
1983 ASSERT_TRUE(sub_merge_key_value);
1984 EXPECT_EQ("sub_merge_key_value_merge", *sub_merge_key_value); // Merged in.
1985 }
1986
TEST(ValuesTest,DictionaryIterator)1987 TEST(ValuesTest, DictionaryIterator) {
1988 Value::Dict dict;
1989 for (Value::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
1990 ADD_FAILURE();
1991 }
1992
1993 Value value1("value1");
1994 dict.Set("key1", value1.Clone());
1995 bool seen1 = false;
1996 for (Value::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
1997 EXPECT_FALSE(seen1);
1998 EXPECT_EQ("key1", it->first);
1999 EXPECT_EQ(value1, it->second);
2000 seen1 = true;
2001 }
2002 EXPECT_TRUE(seen1);
2003
2004 Value value2("value2");
2005 dict.Set("key2", value2.Clone());
2006 bool seen2 = seen1 = false;
2007 for (Value::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
2008 if (it->first == "key1") {
2009 EXPECT_FALSE(seen1);
2010 EXPECT_EQ(value1, it->second);
2011 seen1 = true;
2012 } else if (it->first == "key2") {
2013 EXPECT_FALSE(seen2);
2014 EXPECT_EQ(value2, it->second);
2015 seen2 = true;
2016 } else {
2017 ADD_FAILURE();
2018 }
2019 }
2020 EXPECT_TRUE(seen1);
2021 EXPECT_TRUE(seen2);
2022 }
2023
TEST(ValuesTest,MutatingCopiedPairsInDictMutatesUnderlyingValues)2024 TEST(ValuesTest, MutatingCopiedPairsInDictMutatesUnderlyingValues) {
2025 Value::Dict dict;
2026 dict.Set("key", Value("initial value"));
2027
2028 // Because the non-const dict iterates over <const std::string&, Value&>
2029 // pairs, it's possible to alter iterated-over values in place even when
2030 // "copying" the key-value pair:
2031 for (auto kv : dict) {
2032 kv.second.GetString() = "replacement";
2033 }
2034
2035 std::string* found = dict.FindString("key");
2036 ASSERT_TRUE(found);
2037 EXPECT_EQ(*found, "replacement");
2038 }
2039
TEST(ValuesTest,StdDictionaryIterator)2040 TEST(ValuesTest, StdDictionaryIterator) {
2041 Value::Dict dict;
2042 for (auto it = dict.begin(); it != dict.end(); ++it) {
2043 ADD_FAILURE();
2044 }
2045
2046 Value value1("value1");
2047 dict.Set("key1", value1.Clone());
2048 bool seen1 = false;
2049 for (auto it : dict) {
2050 EXPECT_FALSE(seen1);
2051 EXPECT_EQ("key1", it.first);
2052 EXPECT_EQ(value1, it.second);
2053 seen1 = true;
2054 }
2055 EXPECT_TRUE(seen1);
2056
2057 Value value2("value2");
2058 dict.Set("key2", value2.Clone());
2059 bool seen2 = seen1 = false;
2060 for (auto it : dict) {
2061 if (it.first == "key1") {
2062 EXPECT_FALSE(seen1);
2063 EXPECT_EQ(value1, it.second);
2064 seen1 = true;
2065 } else if (it.first == "key2") {
2066 EXPECT_FALSE(seen2);
2067 EXPECT_EQ(value2, it.second);
2068 seen2 = true;
2069 } else {
2070 ADD_FAILURE();
2071 }
2072 }
2073 EXPECT_TRUE(seen1);
2074 EXPECT_TRUE(seen2);
2075 }
2076
TEST(ValuesTest,SelfSwap)2077 TEST(ValuesTest, SelfSwap) {
2078 base::Value test(1);
2079 std::swap(test, test);
2080 EXPECT_EQ(1, test.GetInt());
2081 }
2082
TEST(ValuesTest,FromToUniquePtrValue)2083 TEST(ValuesTest, FromToUniquePtrValue) {
2084 std::unique_ptr<Value> dict = std::make_unique<Value>(Value::Type::DICT);
2085 dict->GetDict().Set("name", "Froogle");
2086 dict->GetDict().Set("url", "http://froogle.com");
2087 Value dict_copy = dict->Clone();
2088
2089 Value dict_converted = Value::FromUniquePtrValue(std::move(dict));
2090 EXPECT_EQ(dict_copy, dict_converted);
2091
2092 std::unique_ptr<Value> val =
2093 Value::ToUniquePtrValue(std::move(dict_converted));
2094 EXPECT_EQ(dict_copy, *val);
2095 }
2096
TEST(ValuesTest,MutableFindStringPath)2097 TEST(ValuesTest, MutableFindStringPath) {
2098 Value::Dict dict;
2099 dict.SetByDottedPath("foo.bar", "value");
2100
2101 *(dict.FindStringByDottedPath("foo.bar")) = "new_value";
2102
2103 Value::Dict expected_dict;
2104 expected_dict.SetByDottedPath("foo.bar", "new_value");
2105
2106 EXPECT_EQ(expected_dict, dict);
2107 }
2108
TEST(ValuesTest,MutableGetString)2109 TEST(ValuesTest, MutableGetString) {
2110 Value value("value");
2111 value.GetString() = "new_value";
2112 EXPECT_EQ("new_value", value.GetString());
2113 }
2114
2115 #if BUILDFLAG(ENABLE_BASE_TRACING)
TEST(ValuesTest,TracingSupport)2116 TEST(ValuesTest, TracingSupport) {
2117 EXPECT_EQ(perfetto::TracedValueToString(Value(false)), "false");
2118 EXPECT_EQ(perfetto::TracedValueToString(Value(1)), "1");
2119 EXPECT_EQ(perfetto::TracedValueToString(Value(1.5)), "1.5");
2120 EXPECT_EQ(perfetto::TracedValueToString(Value("value")), "value");
2121 EXPECT_EQ(perfetto::TracedValueToString(Value(Value::Type::NONE)), "<none>");
2122 {
2123 Value::List list;
2124 EXPECT_EQ(perfetto::TracedValueToString(list), "{}");
2125 list.Append(2);
2126 list.Append(3);
2127 EXPECT_EQ(perfetto::TracedValueToString(list), "[2,3]");
2128 EXPECT_EQ(perfetto::TracedValueToString(Value(std::move(list))), "[2,3]");
2129 }
2130 {
2131 Value::Dict dict;
2132 EXPECT_EQ(perfetto::TracedValueToString(dict), "{}");
2133 dict.Set("key", "value");
2134 EXPECT_EQ(perfetto::TracedValueToString(dict), "{key:value}");
2135 EXPECT_EQ(perfetto::TracedValueToString(Value(std::move(dict))),
2136 "{key:value}");
2137 }
2138 }
2139 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
2140
TEST(ValueViewTest,BasicConstruction)2141 TEST(ValueViewTest, BasicConstruction) {
2142 {
2143 ValueView v = true;
2144 EXPECT_EQ(true, absl::get<bool>(v.data_view_for_test()));
2145 }
2146 {
2147 ValueView v = 25;
2148 EXPECT_EQ(25, absl::get<int>(v.data_view_for_test()));
2149 }
2150 {
2151 ValueView v = 3.14;
2152 EXPECT_DOUBLE_EQ(3.14, absl::get<ValueView::DoubleStorageForTest>(
2153 v.data_view_for_test()));
2154 }
2155 {
2156 ValueView v = StringPiece("hello world");
2157 EXPECT_EQ("hello world", absl::get<StringPiece>(v.data_view_for_test()));
2158 }
2159 {
2160 ValueView v = "hello world";
2161 EXPECT_EQ("hello world", absl::get<StringPiece>(v.data_view_for_test()));
2162 }
2163 {
2164 std::string str = "hello world";
2165 ValueView v = str;
2166 EXPECT_EQ("hello world", absl::get<StringPiece>(v.data_view_for_test()));
2167 }
2168 {
2169 Value::Dict dict;
2170 dict.Set("hello", "world");
2171 ValueView v = dict;
2172 EXPECT_EQ(dict, absl::get<std::reference_wrapper<const Value::Dict>>(
2173 v.data_view_for_test()));
2174 }
2175 {
2176 Value::List list;
2177 list.Append("hello");
2178 list.Append("world");
2179 ValueView v = list;
2180 EXPECT_EQ(list, absl::get<std::reference_wrapper<const Value::List>>(
2181 v.data_view_for_test()));
2182 }
2183 }
2184
TEST(ValueViewTest,ValueConstruction)2185 TEST(ValueViewTest, ValueConstruction) {
2186 {
2187 Value val(true);
2188 ValueView v = val;
2189 EXPECT_EQ(true, absl::get<bool>(v.data_view_for_test()));
2190 }
2191 {
2192 Value val(25);
2193 ValueView v = val;
2194 EXPECT_EQ(25, absl::get<int>(v.data_view_for_test()));
2195 }
2196 {
2197 Value val(3.14);
2198 ValueView v = val;
2199 EXPECT_DOUBLE_EQ(3.14, absl::get<ValueView::DoubleStorageForTest>(
2200 v.data_view_for_test()));
2201 }
2202 {
2203 Value val("hello world");
2204 ValueView v = val;
2205 EXPECT_EQ("hello world", absl::get<StringPiece>(v.data_view_for_test()));
2206 }
2207 {
2208 Value::Dict dict;
2209 dict.Set("hello", "world");
2210 Value val(dict.Clone());
2211 ValueView v = val;
2212 EXPECT_EQ(dict, absl::get<std::reference_wrapper<const Value::Dict>>(
2213 v.data_view_for_test()));
2214 }
2215 {
2216 Value::List list;
2217 list.Append("hello");
2218 list.Append("world");
2219 Value val(list.Clone());
2220 ValueView v = val;
2221 EXPECT_EQ(list, absl::get<std::reference_wrapper<const Value::List>>(
2222 v.data_view_for_test()));
2223 }
2224 }
2225
TEST(ValueViewTest,ToValue)2226 TEST(ValueViewTest, ToValue) {
2227 {
2228 Value val(true);
2229 Value to_val = ValueView(val).ToValue();
2230 EXPECT_EQ(val, to_val);
2231 }
2232 {
2233 Value val(25);
2234 Value to_val = ValueView(val).ToValue();
2235 EXPECT_EQ(val, to_val);
2236 }
2237 {
2238 Value val(3.14);
2239 Value to_val = ValueView(val).ToValue();
2240 EXPECT_EQ(val, to_val);
2241 }
2242 {
2243 Value val("hello world");
2244 Value to_val = ValueView(val).ToValue();
2245 EXPECT_EQ(val, to_val);
2246 }
2247 {
2248 Value::Dict dict;
2249 dict.Set("hello", "world");
2250 Value val(dict.Clone());
2251 Value to_val = ValueView(val).ToValue();
2252 EXPECT_EQ(val, to_val);
2253 }
2254 {
2255 Value::List list;
2256 list.Append("hello");
2257 list.Append("world");
2258 Value val(list.Clone());
2259 Value to_val = ValueView(val).ToValue();
2260 EXPECT_EQ(val, to_val);
2261 }
2262 }
2263
2264 } // namespace base
2265