blob: 9f34c62fd2a6e3c73f070f86107df5fa3bbd9674 [file] [log] [blame]
[email protected]c378cca2010-05-14 13:17:401// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
[email protected]836061b2008-08-13 14:57:515#include <limits>
6
[email protected]f82fb4952009-01-20 21:05:327#include "base/scoped_ptr.h"
[email protected]9101ef1e2010-01-15 20:09:038#include "base/string16.h"
[email protected]be1ce6a72010-08-03 14:35:229#include "base/utf_string_conversions.h"
[email protected]9101ef1e2010-01-15 20:09:0310#include "base/values.h"
initial.commitd7cae122008-07-26 21:49:3811#include "testing/gtest/include/gtest/gtest.h"
12
13class ValuesTest: public testing::Test {
[email protected]4aeb94082010-08-04 08:44:3514 protected:
15 void CompareDictionariesAndCheckResult(
16 const DictionaryValue* dict1,
17 const DictionaryValue* dict2,
18 const char* expected_paths[],
19 size_t expected_paths_count) {
20 std::vector<std::string> differing_paths;
21 std::vector<std::string> expected_paths_vector(expected_paths,
22 expected_paths+expected_paths_count);
23 // All comparisons should be commutative, check dict1 against dict2
24 // and vice-versa.
25 dict1->GetDifferingPaths(dict2, &differing_paths);
26 ASSERT_EQ(expected_paths_count, differing_paths.size());
27 EXPECT_TRUE(equal(differing_paths.begin(), differing_paths.end(),
28 expected_paths_vector.begin()));
29 dict2->GetDifferingPaths(dict1, &differing_paths);
30 ASSERT_EQ(expected_paths_count, differing_paths.size());
31 EXPECT_TRUE(equal(differing_paths.begin(), differing_paths.end(),
32 expected_paths_vector.begin()));
33 }
initial.commitd7cae122008-07-26 21:49:3834};
35
[email protected]4aeb94082010-08-04 08:44:3536TEST_F(ValuesTest, Basic) {
initial.commitd7cae122008-07-26 21:49:3837 // Test basic dictionary getting/setting
38 DictionaryValue settings;
[email protected]9e4cda7332010-07-31 04:56:1439 std::string homepage = "http://google.com";
40 ASSERT_FALSE(settings.GetString("global.homepage", &homepage));
41 ASSERT_EQ(std::string("http://google.com"), homepage);
42
43 ASSERT_FALSE(settings.Get("global", NULL));
44 settings.Set("global", Value::CreateBooleanValue(true));
45 ASSERT_TRUE(settings.Get("global", NULL));
46 settings.SetString("global.homepage", "http://scurvy.com");
47 ASSERT_TRUE(settings.Get("global", NULL));
48 homepage = "http://google.com";
49 ASSERT_TRUE(settings.GetString("global.homepage", &homepage));
50 ASSERT_EQ(std::string("http://scurvy.com"), homepage);
51
52 // Test storing a dictionary in a list.
53 ListValue* toolbar_bookmarks;
54 ASSERT_FALSE(
55 settings.GetList("global.toolbar.bookmarks", &toolbar_bookmarks));
56
57 toolbar_bookmarks = new ListValue;
58 settings.Set("global.toolbar.bookmarks", toolbar_bookmarks);
59 ASSERT_TRUE(settings.GetList("global.toolbar.bookmarks", &toolbar_bookmarks));
60
61 DictionaryValue* new_bookmark = new DictionaryValue;
62 new_bookmark->SetString("name", "Froogle");
63 new_bookmark->SetString("url", "http://froogle.com");
64 toolbar_bookmarks->Append(new_bookmark);
65
66 ListValue* bookmark_list;
67 ASSERT_TRUE(settings.GetList("global.toolbar.bookmarks", &bookmark_list));
68 DictionaryValue* bookmark;
69 ASSERT_EQ(1U, bookmark_list->GetSize());
70 ASSERT_TRUE(bookmark_list->GetDictionary(0, &bookmark));
71 std::string bookmark_name = "Unnamed";
72 ASSERT_TRUE(bookmark->GetString("name", &bookmark_name));
73 ASSERT_EQ(std::string("Froogle"), bookmark_name);
74 std::string bookmark_url;
75 ASSERT_TRUE(bookmark->GetString("url", &bookmark_url));
76 ASSERT_EQ(std::string("http://froogle.com"), bookmark_url);
77}
78
[email protected]4aeb94082010-08-04 08:44:3579TEST_F(ValuesTest, List) {
[email protected]f82fb4952009-01-20 21:05:3280 scoped_ptr<ListValue> mixed_list(new ListValue());
81 mixed_list->Set(0, Value::CreateBooleanValue(true));
82 mixed_list->Set(1, Value::CreateIntegerValue(42));
83 mixed_list->Set(2, Value::CreateRealValue(88.8));
84 mixed_list->Set(3, Value::CreateStringValue("foo"));
85 ASSERT_EQ(4u, mixed_list->GetSize());
[email protected]52a261f2009-03-03 15:01:1286
[email protected]f82fb4952009-01-20 21:05:3287 Value *value = NULL;
88 bool bool_value = false;
89 int int_value = 0;
90 double double_value = 0.0;
91 std::string string_value;
92
93 ASSERT_FALSE(mixed_list->Get(4, &value));
94
95 ASSERT_FALSE(mixed_list->GetInteger(0, &int_value));
96 ASSERT_EQ(0, int_value);
97 ASSERT_FALSE(mixed_list->GetReal(1, &double_value));
98 ASSERT_EQ(0.0, double_value);
99 ASSERT_FALSE(mixed_list->GetString(2, &string_value));
100 ASSERT_EQ("", string_value);
101 ASSERT_FALSE(mixed_list->GetBoolean(3, &bool_value));
[email protected]74e3af72010-10-03 21:44:39102 ASSERT_FALSE(bool_value);
[email protected]f82fb4952009-01-20 21:05:32103
104 ASSERT_TRUE(mixed_list->GetBoolean(0, &bool_value));
[email protected]74e3af72010-10-03 21:44:39105 ASSERT_TRUE(bool_value);
[email protected]f82fb4952009-01-20 21:05:32106 ASSERT_TRUE(mixed_list->GetInteger(1, &int_value));
107 ASSERT_EQ(42, int_value);
108 ASSERT_TRUE(mixed_list->GetReal(2, &double_value));
109 ASSERT_EQ(88.8, double_value);
110 ASSERT_TRUE(mixed_list->GetString(3, &string_value));
111 ASSERT_EQ("foo", string_value);
112}
113
[email protected]4aeb94082010-08-04 08:44:35114TEST_F(ValuesTest, BinaryValue) {
initial.commitd7cae122008-07-26 21:49:38115 char* buffer = NULL;
116 // Passing a null buffer pointer doesn't yield a BinaryValue
[email protected]0a9a0fc2009-03-24 23:37:14117 scoped_ptr<BinaryValue> binary(BinaryValue::Create(buffer, 0));
118 ASSERT_FALSE(binary.get());
initial.commitd7cae122008-07-26 21:49:38119
120 // If you want to represent an empty binary value, use a zero-length buffer.
[email protected]cd679232008-08-13 02:39:51121 buffer = new char[1];
initial.commitd7cae122008-07-26 21:49:38122 ASSERT_TRUE(buffer);
[email protected]0a9a0fc2009-03-24 23:37:14123 binary.reset(BinaryValue::Create(buffer, 0));
124 ASSERT_TRUE(binary.get());
initial.commitd7cae122008-07-26 21:49:38125 ASSERT_TRUE(binary->GetBuffer());
126 ASSERT_EQ(buffer, binary->GetBuffer());
[email protected]f297d182008-08-21 16:24:51127 ASSERT_EQ(0U, binary->GetSize());
initial.commitd7cae122008-07-26 21:49:38128
129 // Test the common case of a non-empty buffer
130 buffer = new char[15];
[email protected]0a9a0fc2009-03-24 23:37:14131 binary.reset(BinaryValue::Create(buffer, 15));
132 ASSERT_TRUE(binary.get());
initial.commitd7cae122008-07-26 21:49:38133 ASSERT_TRUE(binary->GetBuffer());
134 ASSERT_EQ(buffer, binary->GetBuffer());
[email protected]f297d182008-08-21 16:24:51135 ASSERT_EQ(15U, binary->GetSize());
initial.commitd7cae122008-07-26 21:49:38136
137 char stack_buffer[42];
138 memset(stack_buffer, '!', 42);
[email protected]0a9a0fc2009-03-24 23:37:14139 binary.reset(BinaryValue::CreateWithCopiedBuffer(stack_buffer, 42));
140 ASSERT_TRUE(binary.get());
initial.commitd7cae122008-07-26 21:49:38141 ASSERT_TRUE(binary->GetBuffer());
142 ASSERT_NE(stack_buffer, binary->GetBuffer());
[email protected]f297d182008-08-21 16:24:51143 ASSERT_EQ(42U, binary->GetSize());
initial.commitd7cae122008-07-26 21:49:38144 ASSERT_EQ(0, memcmp(stack_buffer, binary->GetBuffer(), binary->GetSize()));
initial.commitd7cae122008-07-26 21:49:38145}
146
[email protected]4aeb94082010-08-04 08:44:35147TEST_F(ValuesTest, StringValue) {
[email protected]4cd5f6a2008-12-11 01:23:17148 // Test overloaded CreateStringValue.
[email protected]0a9a0fc2009-03-24 23:37:14149 scoped_ptr<Value> narrow_value(Value::CreateStringValue("narrow"));
150 ASSERT_TRUE(narrow_value.get());
[email protected]4cd5f6a2008-12-11 01:23:17151 ASSERT_TRUE(narrow_value->IsType(Value::TYPE_STRING));
[email protected]e2e593d2010-08-03 15:42:58152 scoped_ptr<Value> utf16_value(
153 Value::CreateStringValue(ASCIIToUTF16("utf16")));
154 ASSERT_TRUE(utf16_value.get());
155 ASSERT_TRUE(utf16_value->IsType(Value::TYPE_STRING));
156
157 // Test overloaded GetString.
158 std::string narrow = "http://google.com";
159 string16 utf16 = ASCIIToUTF16("http://google.com");
160 ASSERT_TRUE(narrow_value->GetAsString(&narrow));
161 ASSERT_TRUE(narrow_value->GetAsString(&utf16));
162 ASSERT_EQ(std::string("narrow"), narrow);
163 ASSERT_EQ(ASCIIToUTF16("narrow"), utf16);
164
165 ASSERT_TRUE(utf16_value->GetAsString(&narrow));
166 ASSERT_TRUE(utf16_value->GetAsString(&utf16));
167 ASSERT_EQ(std::string("utf16"), narrow);
168 ASSERT_EQ(ASCIIToUTF16("utf16"), utf16);
169}
170
initial.commitd7cae122008-07-26 21:49:38171// This is a Value object that allows us to tell if it's been
172// properly deleted by modifying the value of external flag on destruction.
173class DeletionTestValue : public Value {
[email protected]8ab4809b2009-07-03 02:28:55174 public:
[email protected]2fdc86a2010-01-26 23:08:02175 explicit DeletionTestValue(bool* deletion_flag) : Value(TYPE_NULL) {
initial.commitd7cae122008-07-26 21:49:38176 Init(deletion_flag); // Separate function so that we can use ASSERT_*
177 }
178
179 void Init(bool* deletion_flag) {
180 ASSERT_TRUE(deletion_flag);
181 deletion_flag_ = deletion_flag;
182 *deletion_flag_ = false;
183 }
184
185 ~DeletionTestValue() {
186 *deletion_flag_ = true;
187 }
188
[email protected]8ab4809b2009-07-03 02:28:55189 private:
initial.commitd7cae122008-07-26 21:49:38190 bool* deletion_flag_;
191};
192
[email protected]4aeb94082010-08-04 08:44:35193TEST_F(ValuesTest, ListDeletion) {
initial.commitd7cae122008-07-26 21:49:38194 bool deletion_flag = true;
195
196 {
197 ListValue list;
198 list.Append(new DeletionTestValue(&deletion_flag));
199 EXPECT_FALSE(deletion_flag);
200 }
201 EXPECT_TRUE(deletion_flag);
202
203 {
204 ListValue list;
205 list.Append(new DeletionTestValue(&deletion_flag));
206 EXPECT_FALSE(deletion_flag);
207 list.Clear();
208 EXPECT_TRUE(deletion_flag);
209 }
210
211 {
212 ListValue list;
213 list.Append(new DeletionTestValue(&deletion_flag));
214 EXPECT_FALSE(deletion_flag);
215 EXPECT_TRUE(list.Set(0, Value::CreateNullValue()));
216 EXPECT_TRUE(deletion_flag);
217 }
218}
219
[email protected]4aeb94082010-08-04 08:44:35220TEST_F(ValuesTest, ListRemoval) {
initial.commitd7cae122008-07-26 21:49:38221 bool deletion_flag = true;
222 Value* removed_item = NULL;
223
224 {
225 ListValue list;
226 list.Append(new DeletionTestValue(&deletion_flag));
227 EXPECT_FALSE(deletion_flag);
[email protected]f297d182008-08-21 16:24:51228 EXPECT_EQ(1U, list.GetSize());
[email protected]836061b2008-08-13 14:57:51229 EXPECT_FALSE(list.Remove(std::numeric_limits<size_t>::max(),
230 &removed_item));
initial.commitd7cae122008-07-26 21:49:38231 EXPECT_FALSE(list.Remove(1, &removed_item));
232 EXPECT_TRUE(list.Remove(0, &removed_item));
233 ASSERT_TRUE(removed_item);
[email protected]f297d182008-08-21 16:24:51234 EXPECT_EQ(0U, list.GetSize());
initial.commitd7cae122008-07-26 21:49:38235 }
236 EXPECT_FALSE(deletion_flag);
237 delete removed_item;
238 removed_item = NULL;
239 EXPECT_TRUE(deletion_flag);
240
241 {
242 ListValue list;
243 list.Append(new DeletionTestValue(&deletion_flag));
244 EXPECT_FALSE(deletion_flag);
245 EXPECT_TRUE(list.Remove(0, NULL));
246 EXPECT_TRUE(deletion_flag);
[email protected]f297d182008-08-21 16:24:51247 EXPECT_EQ(0U, list.GetSize());
initial.commitd7cae122008-07-26 21:49:38248 }
[email protected]6832cbe2009-11-30 19:59:11249
250 {
251 ListValue list;
252 DeletionTestValue* value = new DeletionTestValue(&deletion_flag);
253 list.Append(value);
254 EXPECT_FALSE(deletion_flag);
255 EXPECT_EQ(0, list.Remove(*value));
256 EXPECT_TRUE(deletion_flag);
257 EXPECT_EQ(0U, list.GetSize());
258 }
initial.commitd7cae122008-07-26 21:49:38259}
260
[email protected]4aeb94082010-08-04 08:44:35261TEST_F(ValuesTest, DictionaryDeletion) {
[email protected]9e4cda7332010-07-31 04:56:14262 std::string key = "test";
263 bool deletion_flag = true;
264
265 {
266 DictionaryValue dict;
267 dict.Set(key, new DeletionTestValue(&deletion_flag));
268 EXPECT_FALSE(deletion_flag);
269 }
270 EXPECT_TRUE(deletion_flag);
271
272 {
273 DictionaryValue dict;
274 dict.Set(key, new DeletionTestValue(&deletion_flag));
275 EXPECT_FALSE(deletion_flag);
276 dict.Clear();
277 EXPECT_TRUE(deletion_flag);
278 }
279
280 {
281 DictionaryValue dict;
282 dict.Set(key, new DeletionTestValue(&deletion_flag));
283 EXPECT_FALSE(deletion_flag);
284 dict.Set(key, Value::CreateNullValue());
285 EXPECT_TRUE(deletion_flag);
286 }
287}
288
[email protected]4aeb94082010-08-04 08:44:35289TEST_F(ValuesTest, DictionaryRemoval) {
[email protected]9e4cda7332010-07-31 04:56:14290 std::string key = "test";
291 bool deletion_flag = true;
292 Value* removed_item = NULL;
293
294 {
295 DictionaryValue dict;
296 dict.Set(key, new DeletionTestValue(&deletion_flag));
297 EXPECT_FALSE(deletion_flag);
298 EXPECT_TRUE(dict.HasKey(key));
299 EXPECT_FALSE(dict.Remove("absent key", &removed_item));
300 EXPECT_TRUE(dict.Remove(key, &removed_item));
301 EXPECT_FALSE(dict.HasKey(key));
302 ASSERT_TRUE(removed_item);
303 }
304 EXPECT_FALSE(deletion_flag);
305 delete removed_item;
306 removed_item = NULL;
307 EXPECT_TRUE(deletion_flag);
308
309 {
310 DictionaryValue dict;
311 dict.Set(key, new DeletionTestValue(&deletion_flag));
312 EXPECT_FALSE(deletion_flag);
313 EXPECT_TRUE(dict.HasKey(key));
314 EXPECT_TRUE(dict.Remove(key, NULL));
315 EXPECT_TRUE(deletion_flag);
316 EXPECT_FALSE(dict.HasKey(key));
317 }
318}
319
[email protected]4aeb94082010-08-04 08:44:35320TEST_F(ValuesTest, DictionaryWithoutPathExpansion) {
[email protected]4dad9ad82009-11-25 20:47:52321 DictionaryValue dict;
[email protected]9e4cda7332010-07-31 04:56:14322 dict.Set("this.is.expanded", Value::CreateNullValue());
323 dict.SetWithoutPathExpansion("this.isnt.expanded", Value::CreateNullValue());
324
325 EXPECT_FALSE(dict.HasKey("this.is.expanded"));
326 EXPECT_TRUE(dict.HasKey("this"));
327 Value* value1;
328 EXPECT_TRUE(dict.Get("this", &value1));
329 DictionaryValue* value2;
330 ASSERT_TRUE(dict.GetDictionaryWithoutPathExpansion("this", &value2));
331 EXPECT_EQ(value1, value2);
332 EXPECT_EQ(1U, value2->size());
333
334 EXPECT_TRUE(dict.HasKey("this.isnt.expanded"));
335 Value* value3;
336 EXPECT_FALSE(dict.Get("this.isnt.expanded", &value3));
337 Value* value4;
338 ASSERT_TRUE(dict.GetWithoutPathExpansion("this.isnt.expanded", &value4));
339 EXPECT_EQ(Value::TYPE_NULL, value4->GetType());
340}
341
[email protected]4aeb94082010-08-04 08:44:35342TEST_F(ValuesTest, DeepCopy) {
initial.commitd7cae122008-07-26 21:49:38343 DictionaryValue original_dict;
344 Value* original_null = Value::CreateNullValue();
[email protected]9e4cda7332010-07-31 04:56:14345 original_dict.Set("null", original_null);
346 Value* original_bool = Value::CreateBooleanValue(true);
347 original_dict.Set("bool", original_bool);
348 Value* original_int = Value::CreateIntegerValue(42);
349 original_dict.Set("int", original_int);
350 Value* original_real = Value::CreateRealValue(3.14);
351 original_dict.Set("real", original_real);
352 Value* original_string = Value::CreateStringValue("hello");
353 original_dict.Set("string", original_string);
[email protected]e2e593d2010-08-03 15:42:58354 Value* original_string16 = Value::CreateStringValue(ASCIIToUTF16("hello16"));
355 original_dict.Set("string16", original_string16);
[email protected]9e4cda7332010-07-31 04:56:14356
357 char* original_buffer = new char[42];
358 memset(original_buffer, '!', 42);
359 BinaryValue* original_binary = Value::CreateBinaryValue(original_buffer, 42);
360 original_dict.Set("binary", original_binary);
361
362 ListValue* original_list = new ListValue();
363 Value* original_list_element_0 = Value::CreateIntegerValue(0);
364 original_list->Append(original_list_element_0);
365 Value* original_list_element_1 = Value::CreateIntegerValue(1);
366 original_list->Append(original_list_element_1);
367 original_dict.Set("list", original_list);
368
369 scoped_ptr<DictionaryValue> copy_dict(
370 static_cast<DictionaryValue*>(original_dict.DeepCopy()));
371 ASSERT_TRUE(copy_dict.get());
372 ASSERT_NE(copy_dict.get(), &original_dict);
373
374 Value* copy_null = NULL;
375 ASSERT_TRUE(copy_dict->Get("null", &copy_null));
376 ASSERT_TRUE(copy_null);
377 ASSERT_NE(copy_null, original_null);
378 ASSERT_TRUE(copy_null->IsType(Value::TYPE_NULL));
379
380 Value* copy_bool = NULL;
381 ASSERT_TRUE(copy_dict->Get("bool", &copy_bool));
382 ASSERT_TRUE(copy_bool);
383 ASSERT_NE(copy_bool, original_bool);
384 ASSERT_TRUE(copy_bool->IsType(Value::TYPE_BOOLEAN));
385 bool copy_bool_value = false;
386 ASSERT_TRUE(copy_bool->GetAsBoolean(&copy_bool_value));
387 ASSERT_TRUE(copy_bool_value);
388
389 Value* copy_int = NULL;
390 ASSERT_TRUE(copy_dict->Get("int", &copy_int));
391 ASSERT_TRUE(copy_int);
392 ASSERT_NE(copy_int, original_int);
393 ASSERT_TRUE(copy_int->IsType(Value::TYPE_INTEGER));
394 int copy_int_value = 0;
395 ASSERT_TRUE(copy_int->GetAsInteger(&copy_int_value));
396 ASSERT_EQ(42, copy_int_value);
397
398 Value* copy_real = NULL;
399 ASSERT_TRUE(copy_dict->Get("real", &copy_real));
400 ASSERT_TRUE(copy_real);
401 ASSERT_NE(copy_real, original_real);
402 ASSERT_TRUE(copy_real->IsType(Value::TYPE_REAL));
403 double copy_real_value = 0;
404 ASSERT_TRUE(copy_real->GetAsReal(&copy_real_value));
405 ASSERT_EQ(3.14, copy_real_value);
406
407 Value* copy_string = NULL;
408 ASSERT_TRUE(copy_dict->Get("string", &copy_string));
409 ASSERT_TRUE(copy_string);
410 ASSERT_NE(copy_string, original_string);
411 ASSERT_TRUE(copy_string->IsType(Value::TYPE_STRING));
412 std::string copy_string_value;
[email protected]e2e593d2010-08-03 15:42:58413 string16 copy_string16_value;
[email protected]9e4cda7332010-07-31 04:56:14414 ASSERT_TRUE(copy_string->GetAsString(&copy_string_value));
[email protected]e2e593d2010-08-03 15:42:58415 ASSERT_TRUE(copy_string->GetAsString(&copy_string16_value));
[email protected]9e4cda7332010-07-31 04:56:14416 ASSERT_EQ(std::string("hello"), copy_string_value);
[email protected]e2e593d2010-08-03 15:42:58417 ASSERT_EQ(ASCIIToUTF16("hello"), copy_string16_value);
[email protected]9e4cda7332010-07-31 04:56:14418
[email protected]e2e593d2010-08-03 15:42:58419 Value* copy_string16 = NULL;
420 ASSERT_TRUE(copy_dict->Get("string16", &copy_string16));
421 ASSERT_TRUE(copy_string16);
422 ASSERT_NE(copy_string16, original_string16);
423 ASSERT_TRUE(copy_string16->IsType(Value::TYPE_STRING));
424 ASSERT_TRUE(copy_string16->GetAsString(&copy_string_value));
425 ASSERT_TRUE(copy_string16->GetAsString(&copy_string16_value));
[email protected]9e4cda7332010-07-31 04:56:14426 ASSERT_EQ(std::string("hello16"), copy_string_value);
[email protected]e2e593d2010-08-03 15:42:58427 ASSERT_EQ(ASCIIToUTF16("hello16"), copy_string16_value);
[email protected]9e4cda7332010-07-31 04:56:14428
429 Value* copy_binary = NULL;
430 ASSERT_TRUE(copy_dict->Get("binary", &copy_binary));
431 ASSERT_TRUE(copy_binary);
432 ASSERT_NE(copy_binary, original_binary);
433 ASSERT_TRUE(copy_binary->IsType(Value::TYPE_BINARY));
434 ASSERT_NE(original_binary->GetBuffer(),
435 static_cast<BinaryValue*>(copy_binary)->GetBuffer());
436 ASSERT_EQ(original_binary->GetSize(),
437 static_cast<BinaryValue*>(copy_binary)->GetSize());
438 ASSERT_EQ(0, memcmp(original_binary->GetBuffer(),
439 static_cast<BinaryValue*>(copy_binary)->GetBuffer(),
440 original_binary->GetSize()));
441
442 Value* copy_value = NULL;
443 ASSERT_TRUE(copy_dict->Get("list", &copy_value));
444 ASSERT_TRUE(copy_value);
445 ASSERT_NE(copy_value, original_list);
446 ASSERT_TRUE(copy_value->IsType(Value::TYPE_LIST));
447 ListValue* copy_list = static_cast<ListValue*>(copy_value);
448 ASSERT_EQ(2U, copy_list->GetSize());
449
450 Value* copy_list_element_0;
451 ASSERT_TRUE(copy_list->Get(0, &copy_list_element_0));
452 ASSERT_TRUE(copy_list_element_0);
453 ASSERT_NE(copy_list_element_0, original_list_element_0);
454 int copy_list_element_0_value;
455 ASSERT_TRUE(copy_list_element_0->GetAsInteger(&copy_list_element_0_value));
456 ASSERT_EQ(0, copy_list_element_0_value);
457
458 Value* copy_list_element_1;
459 ASSERT_TRUE(copy_list->Get(1, &copy_list_element_1));
460 ASSERT_TRUE(copy_list_element_1);
461 ASSERT_NE(copy_list_element_1, original_list_element_1);
462 int copy_list_element_1_value;
463 ASSERT_TRUE(copy_list_element_1->GetAsInteger(&copy_list_element_1_value));
464 ASSERT_EQ(1, copy_list_element_1_value);
465}
466
[email protected]4aeb94082010-08-04 08:44:35467TEST_F(ValuesTest, Equals) {
initial.commitd7cae122008-07-26 21:49:38468 Value* null1 = Value::CreateNullValue();
469 Value* null2 = Value::CreateNullValue();
470 EXPECT_NE(null1, null2);
471 EXPECT_TRUE(null1->Equals(null2));
472
473 Value* boolean = Value::CreateBooleanValue(false);
474 EXPECT_FALSE(null1->Equals(boolean));
475 delete null1;
476 delete null2;
477 delete boolean;
478
479 DictionaryValue dv;
[email protected]9e4cda7332010-07-31 04:56:14480 dv.SetBoolean("a", false);
481 dv.SetInteger("b", 2);
482 dv.SetReal("c", 2.5);
483 dv.SetString("d1", "string");
[email protected]ff4c1d82010-08-04 16:58:12484 dv.SetString("d2", ASCIIToUTF16("http://google.com"));
[email protected]9e4cda7332010-07-31 04:56:14485 dv.Set("e", Value::CreateNullValue());
486
[email protected]dc1f2442010-08-18 16:23:40487 scoped_ptr<DictionaryValue> copy;
488 copy.reset(static_cast<DictionaryValue*>(dv.DeepCopy()));
489 EXPECT_TRUE(dv.Equals(copy.get()));
[email protected]9e4cda7332010-07-31 04:56:14490
491 ListValue* list = new ListValue;
492 list->Append(Value::CreateNullValue());
493 list->Append(new DictionaryValue);
494 dv.Set("f", list);
495
[email protected]dc1f2442010-08-18 16:23:40496 EXPECT_FALSE(dv.Equals(copy.get()));
[email protected]9e4cda7332010-07-31 04:56:14497 copy->Set("f", list->DeepCopy());
[email protected]dc1f2442010-08-18 16:23:40498 EXPECT_TRUE(dv.Equals(copy.get()));
[email protected]9e4cda7332010-07-31 04:56:14499
500 list->Append(Value::CreateBooleanValue(true));
[email protected]dc1f2442010-08-18 16:23:40501 EXPECT_FALSE(dv.Equals(copy.get()));
502
503 // Check if Equals detects differences in only the keys.
504 copy.reset(static_cast<DictionaryValue*>(dv.DeepCopy()));
505 EXPECT_TRUE(dv.Equals(copy.get()));
506 copy->Remove("a", NULL);
507 copy->SetBoolean("aa", false);
508 EXPECT_FALSE(dv.Equals(copy.get()));
[email protected]9e4cda7332010-07-31 04:56:14509}
510
[email protected]4aeb94082010-08-04 08:44:35511TEST_F(ValuesTest, RemoveEmptyChildren) {
[email protected]ec330b52009-12-02 00:20:32512 scoped_ptr<DictionaryValue> root(new DictionaryValue);
513 // Remove empty lists and dictionaries.
[email protected]9e4cda7332010-07-31 04:56:14514 root->Set("empty_dict", new DictionaryValue);
515 root->Set("empty_list", new ListValue);
516 root->SetWithoutPathExpansion("a.b.c.d.e", new DictionaryValue);
517 root.reset(root->DeepCopyWithoutEmptyChildren());
518 EXPECT_TRUE(root->empty());
519
520 // Make sure we don't prune too much.
521 root->SetBoolean("bool", true);
522 root->Set("empty_dict", new DictionaryValue);
523 root->SetString("empty_string", "");
524 root.reset(root->DeepCopyWithoutEmptyChildren());
525 EXPECT_EQ(2U, root->size());
526
527 // Should do nothing.
528 root.reset(root->DeepCopyWithoutEmptyChildren());
529 EXPECT_EQ(2U, root->size());
530
531 // Nested test cases. These should all reduce back to the bool and string
532 // set above.
533 {
534 root->Set("a.b.c.d.e", new DictionaryValue);
535 root.reset(root->DeepCopyWithoutEmptyChildren());
536 EXPECT_EQ(2U, root->size());
537 }
538 {
539 DictionaryValue* inner = new DictionaryValue;
540 root->Set("dict_with_emtpy_children", inner);
541 inner->Set("empty_dict", new DictionaryValue);
542 inner->Set("empty_list", new ListValue);
543 root.reset(root->DeepCopyWithoutEmptyChildren());
544 EXPECT_EQ(2U, root->size());
545 }
546 {
547 ListValue* inner = new ListValue;
548 root->Set("list_with_empty_children", inner);
549 inner->Append(new DictionaryValue);
550 inner->Append(new ListValue);
551 root.reset(root->DeepCopyWithoutEmptyChildren());
552 EXPECT_EQ(2U, root->size());
553 }
554
555 // Nested with siblings.
556 {
557 ListValue* inner = new ListValue;
558 root->Set("list_with_empty_children", inner);
559 inner->Append(new DictionaryValue);
560 inner->Append(new ListValue);
561 DictionaryValue* inner2 = new DictionaryValue;
562 root->Set("dict_with_empty_children", inner2);
563 inner2->Set("empty_dict", new DictionaryValue);
564 inner2->Set("empty_list", new ListValue);
565 root.reset(root->DeepCopyWithoutEmptyChildren());
566 EXPECT_EQ(2U, root->size());
567 }
568
569 // Make sure nested values don't get pruned.
570 {
571 ListValue* inner = new ListValue;
572 root->Set("list_with_empty_children", inner);
573 ListValue* inner2 = new ListValue;
574 inner->Append(new DictionaryValue);
575 inner->Append(inner2);
576 inner2->Append(Value::CreateStringValue("hello"));
577 root.reset(root->DeepCopyWithoutEmptyChildren());
578 EXPECT_EQ(3U, root->size());
579 EXPECT_TRUE(root->GetList("list_with_empty_children", &inner));
580 EXPECT_EQ(1U, inner->GetSize()); // Dictionary was pruned.
581 EXPECT_TRUE(inner->GetList(0, &inner2));
582 EXPECT_EQ(1U, inner2->GetSize());
583 }
584}
585
[email protected]4aeb94082010-08-04 08:44:35586TEST_F(ValuesTest, MergeDictionary) {
[email protected]c378cca2010-05-14 13:17:40587 scoped_ptr<DictionaryValue> base(new DictionaryValue);
[email protected]9e4cda7332010-07-31 04:56:14588 base->SetString("base_key", "base_key_value_base");
589 base->SetString("collide_key", "collide_key_value_base");
590 DictionaryValue* base_sub_dict = new DictionaryValue;
591 base_sub_dict->SetString("sub_base_key", "sub_base_key_value_base");
592 base_sub_dict->SetString("sub_collide_key", "sub_collide_key_value_base");
593 base->Set("sub_dict_key", base_sub_dict);
594
595 scoped_ptr<DictionaryValue> merge(new DictionaryValue);
596 merge->SetString("merge_key", "merge_key_value_merge");
597 merge->SetString("collide_key", "collide_key_value_merge");
598 DictionaryValue* merge_sub_dict = new DictionaryValue;
599 merge_sub_dict->SetString("sub_merge_key", "sub_merge_key_value_merge");
600 merge_sub_dict->SetString("sub_collide_key", "sub_collide_key_value_merge");
601 merge->Set("sub_dict_key", merge_sub_dict);
602
603 base->MergeDictionary(merge.get());
604
605 EXPECT_EQ(4U, base->size());
606 std::string base_key_value;
607 EXPECT_TRUE(base->GetString("base_key", &base_key_value));
608 EXPECT_EQ("base_key_value_base", base_key_value); // Base value preserved.
609 std::string collide_key_value;
610 EXPECT_TRUE(base->GetString("collide_key", &collide_key_value));
611 EXPECT_EQ("collide_key_value_merge", collide_key_value); // Replaced.
612 std::string merge_key_value;
613 EXPECT_TRUE(base->GetString("merge_key", &merge_key_value));
614 EXPECT_EQ("merge_key_value_merge", merge_key_value); // Merged in.
615
616 DictionaryValue* res_sub_dict;
617 EXPECT_TRUE(base->GetDictionary("sub_dict_key", &res_sub_dict));
618 EXPECT_EQ(3U, res_sub_dict->size());
619 std::string sub_base_key_value;
620 EXPECT_TRUE(res_sub_dict->GetString("sub_base_key", &sub_base_key_value));
621 EXPECT_EQ("sub_base_key_value_base", sub_base_key_value); // Preserved.
622 std::string sub_collide_key_value;
623 EXPECT_TRUE(res_sub_dict->GetString("sub_collide_key",
624 &sub_collide_key_value));
625 EXPECT_EQ("sub_collide_key_value_merge", sub_collide_key_value); // Replaced.
626 std::string sub_merge_key_value;
627 EXPECT_TRUE(res_sub_dict->GetString("sub_merge_key", &sub_merge_key_value));
628 EXPECT_EQ("sub_merge_key_value_merge", sub_merge_key_value); // Merged in.
629}
630
[email protected]4aeb94082010-08-04 08:44:35631TEST_F(ValuesTest, GetDifferingPaths) {
632 scoped_ptr<DictionaryValue> dict1(new DictionaryValue());
633 scoped_ptr<DictionaryValue> dict2(new DictionaryValue());
634 std::vector<std::string> differing_paths;
635
636 // Test comparing empty dictionaries.
637 dict1->GetDifferingPaths(dict2.get(), &differing_paths);
638 EXPECT_EQ(differing_paths.size(), 0UL);
639
640 // Compare an empty dictionary with various non-empty dictionaries.
641 static const char* expected_paths1[] = {
642 "segment1"
643 };
644 dict1->SetString("segment1", "value1");
645 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths1,
646 arraysize(expected_paths1));
647
648 static const char* expected_paths2[] = {
649 "segment1",
650 "segment2",
651 "segment2.segment3"
652 };
653 dict1->SetString("segment2.segment3", "value2");
654 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths2,
655 arraysize(expected_paths2));
656
657 static const char* expected_paths3[] = {
658 "segment1",
659 "segment2",
660 "segment2.segment3",
661 "segment4",
662 "segment4.segment5"
663 };
664 dict1->SetString("segment4.segment5", "value3");
665 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths3,
666 arraysize(expected_paths3));
667
668 // Now various tests with two populated dictionaries.
669 static const char* expected_paths4[] = {
670 "segment1",
671 "segment2",
672 "segment2.segment3",
673 "segment4",
674 "segment4.segment5"
675 };
676 dict2->Set("segment2", new DictionaryValue());
677 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths4,
678 arraysize(expected_paths4));
679
680 static const char* expected_paths5[] = {
681 "segment1",
682 "segment4",
683 "segment4.segment5"
684 };
685 dict2->SetString("segment2.segment3", "value2");
686 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths5,
687 arraysize(expected_paths5));
688
689 dict2->SetBoolean("segment2.segment3", true);
690 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths4,
691 arraysize(expected_paths4));
692
693 // Test two identical dictionaries.
694 dict2.reset(static_cast<DictionaryValue*>(dict1->DeepCopy()));
695 dict2->GetDifferingPaths(dict1.get(), &differing_paths);
696 EXPECT_EQ(differing_paths.size(), 0UL);
697
698 // Test a deep dictionary structure.
699 static const char* expected_paths6[] = {
700 "s1",
701 "s1.s2",
702 "s1.s2.s3",
703 "s1.s2.s3.s4",
704 "s1.s2.s3.s4.s5"
705 };
706 dict1.reset(new DictionaryValue());
707 dict2.reset(new DictionaryValue());
708 dict1->Set("s1.s2.s3.s4.s5", new DictionaryValue());
709 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths6,
710 arraysize(expected_paths6));
711
712 // Make sure disjoint dictionaries generate the right differing path list.
713 static const char* expected_paths7[] = {
714 "a",
715 "b",
716 "c",
717 "d"
718 };
719 dict1.reset(new DictionaryValue());
720 dict1->SetBoolean("a", true);
721 dict1->SetBoolean("c", true);
722 dict2.reset(new DictionaryValue());
723 dict1->SetBoolean("b", true);
724 dict1->SetBoolean("d", true);
725 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths7,
726 arraysize(expected_paths7));
727
728 // For code coverage completeness. Make sure that all branches
729 // that were not covered are executed.
730 static const char* expected_paths8[] = {
731 "s1",
732 "s1.s2"
733 };
734 dict1.reset(new DictionaryValue());
735 dict1->Set("s1.s2", new DictionaryValue());
736 dict2.reset(new DictionaryValue());
737 dict2->SetInteger("s1", 1);
738 CompareDictionariesAndCheckResult(dict1.get(), dict2.get(), expected_paths8,
739 arraysize(expected_paths8));
740}