Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <limits>
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/strings/string16.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "base/values.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 namespace base {
     14 
     15 TEST(ValuesTest, Basic) {
     16   // Test basic dictionary getting/setting
     17   DictionaryValue settings;
     18   std::string homepage = "http://google.com";
     19   ASSERT_FALSE(settings.GetString("global.homepage", &homepage));
     20   ASSERT_EQ(std::string("http://google.com"), homepage);
     21 
     22   ASSERT_FALSE(settings.Get("global", NULL));
     23   settings.Set("global", new FundamentalValue(true));
     24   ASSERT_TRUE(settings.Get("global", NULL));
     25   settings.SetString("global.homepage", "http://scurvy.com");
     26   ASSERT_TRUE(settings.Get("global", NULL));
     27   homepage = "http://google.com";
     28   ASSERT_TRUE(settings.GetString("global.homepage", &homepage));
     29   ASSERT_EQ(std::string("http://scurvy.com"), homepage);
     30 
     31   // Test storing a dictionary in a list.
     32   ListValue* toolbar_bookmarks;
     33   ASSERT_FALSE(
     34     settings.GetList("global.toolbar.bookmarks", &toolbar_bookmarks));
     35 
     36   toolbar_bookmarks = new ListValue;
     37   settings.Set("global.toolbar.bookmarks", toolbar_bookmarks);
     38   ASSERT_TRUE(settings.GetList("global.toolbar.bookmarks", &toolbar_bookmarks));
     39 
     40   DictionaryValue* new_bookmark = new DictionaryValue;
     41   new_bookmark->SetString("name", "Froogle");
     42   new_bookmark->SetString("url", "http://froogle.com");
     43   toolbar_bookmarks->Append(new_bookmark);
     44 
     45   ListValue* bookmark_list;
     46   ASSERT_TRUE(settings.GetList("global.toolbar.bookmarks", &bookmark_list));
     47   DictionaryValue* bookmark;
     48   ASSERT_EQ(1U, bookmark_list->GetSize());
     49   ASSERT_TRUE(bookmark_list->GetDictionary(0, &bookmark));
     50   std::string bookmark_name = "Unnamed";
     51   ASSERT_TRUE(bookmark->GetString("name", &bookmark_name));
     52   ASSERT_EQ(std::string("Froogle"), bookmark_name);
     53   std::string bookmark_url;
     54   ASSERT_TRUE(bookmark->GetString("url", &bookmark_url));
     55   ASSERT_EQ(std::string("http://froogle.com"), bookmark_url);
     56 }
     57 
     58 TEST(ValuesTest, List) {
     59   scoped_ptr<ListValue> mixed_list(new ListValue());
     60   mixed_list->Set(0, new FundamentalValue(true));
     61   mixed_list->Set(1, new FundamentalValue(42));
     62   mixed_list->Set(2, new FundamentalValue(88.8));
     63   mixed_list->Set(3, new StringValue("foo"));
     64   ASSERT_EQ(4u, mixed_list->GetSize());
     65 
     66   Value *value = NULL;
     67   bool bool_value = false;
     68   int int_value = 0;
     69   double double_value = 0.0;
     70   std::string string_value;
     71 
     72   ASSERT_FALSE(mixed_list->Get(4, &value));
     73 
     74   ASSERT_FALSE(mixed_list->GetInteger(0, &int_value));
     75   ASSERT_EQ(0, int_value);
     76   ASSERT_FALSE(mixed_list->GetBoolean(1, &bool_value));
     77   ASSERT_FALSE(bool_value);
     78   ASSERT_FALSE(mixed_list->GetString(2, &string_value));
     79   ASSERT_EQ("", string_value);
     80   ASSERT_FALSE(mixed_list->GetInteger(2, &int_value));
     81   ASSERT_EQ(0, int_value);
     82   ASSERT_FALSE(mixed_list->GetBoolean(3, &bool_value));
     83   ASSERT_FALSE(bool_value);
     84 
     85   ASSERT_TRUE(mixed_list->GetBoolean(0, &bool_value));
     86   ASSERT_TRUE(bool_value);
     87   ASSERT_TRUE(mixed_list->GetInteger(1, &int_value));
     88   ASSERT_EQ(42, int_value);
     89   // implicit conversion from Integer to Double should be possible.
     90   ASSERT_TRUE(mixed_list->GetDouble(1, &double_value));
     91   ASSERT_EQ(42, double_value);
     92   ASSERT_TRUE(mixed_list->GetDouble(2, &double_value));
     93   ASSERT_EQ(88.8, double_value);
     94   ASSERT_TRUE(mixed_list->GetString(3, &string_value));
     95   ASSERT_EQ("foo", string_value);
     96 
     97   // Try searching in the mixed list.
     98   base::FundamentalValue sought_value(42);
     99   base::FundamentalValue not_found_value(false);
    100 
    101   ASSERT_NE(mixed_list->end(), mixed_list->Find(sought_value));
    102   ASSERT_TRUE((*mixed_list->Find(sought_value))->GetAsInteger(&int_value));
    103   ASSERT_EQ(42, int_value);
    104   ASSERT_EQ(mixed_list->end(), mixed_list->Find(not_found_value));
    105 }
    106 
    107 TEST(ValuesTest, BinaryValue) {
    108   // Default constructor creates a BinaryValue with a null buffer and size 0.
    109   scoped_ptr<BinaryValue> binary(new BinaryValue());
    110   ASSERT_TRUE(binary.get());
    111   ASSERT_EQ(NULL, binary->GetBuffer());
    112   ASSERT_EQ(0U, binary->GetSize());
    113 
    114   // Test the common case of a non-empty buffer
    115   char* buffer = new char[15];
    116   binary.reset(new BinaryValue(scoped_ptr<char[]>(buffer), 15));
    117   ASSERT_TRUE(binary.get());
    118   ASSERT_TRUE(binary->GetBuffer());
    119   ASSERT_EQ(buffer, binary->GetBuffer());
    120   ASSERT_EQ(15U, binary->GetSize());
    121 
    122   char stack_buffer[42];
    123   memset(stack_buffer, '!', 42);
    124   binary.reset(BinaryValue::CreateWithCopiedBuffer(stack_buffer, 42));
    125   ASSERT_TRUE(binary.get());
    126   ASSERT_TRUE(binary->GetBuffer());
    127   ASSERT_NE(stack_buffer, binary->GetBuffer());
    128   ASSERT_EQ(42U, binary->GetSize());
    129   ASSERT_EQ(0, memcmp(stack_buffer, binary->GetBuffer(), binary->GetSize()));
    130 }
    131 
    132 TEST(ValuesTest, StringValue) {
    133   // Test overloaded CreateStringValue.
    134   scoped_ptr<Value> narrow_value(new StringValue("narrow"));
    135   ASSERT_TRUE(narrow_value.get());
    136   ASSERT_TRUE(narrow_value->IsType(Value::TYPE_STRING));
    137   scoped_ptr<Value> utf16_value(new StringValue(ASCIIToUTF16("utf16")));
    138   ASSERT_TRUE(utf16_value.get());
    139   ASSERT_TRUE(utf16_value->IsType(Value::TYPE_STRING));
    140 
    141   // Test overloaded GetString.
    142   std::string narrow = "http://google.com";
    143   string16 utf16 = ASCIIToUTF16("http://google.com");
    144   ASSERT_TRUE(narrow_value->GetAsString(&narrow));
    145   ASSERT_TRUE(narrow_value->GetAsString(&utf16));
    146   ASSERT_EQ(std::string("narrow"), narrow);
    147   ASSERT_EQ(ASCIIToUTF16("narrow"), utf16);
    148 
    149   ASSERT_TRUE(utf16_value->GetAsString(&narrow));
    150   ASSERT_TRUE(utf16_value->GetAsString(&utf16));
    151   ASSERT_EQ(std::string("utf16"), narrow);
    152   ASSERT_EQ(ASCIIToUTF16("utf16"), utf16);
    153 }
    154 
    155 // This is a Value object that allows us to tell if it's been
    156 // properly deleted by modifying the value of external flag on destruction.
    157 class DeletionTestValue : public Value {
    158  public:
    159   explicit DeletionTestValue(bool* deletion_flag) : Value(TYPE_NULL) {
    160     Init(deletion_flag);  // Separate function so that we can use ASSERT_*
    161   }
    162 
    163   void Init(bool* deletion_flag) {
    164     ASSERT_TRUE(deletion_flag);
    165     deletion_flag_ = deletion_flag;
    166     *deletion_flag_ = false;
    167   }
    168 
    169   virtual ~DeletionTestValue() {
    170     *deletion_flag_ = true;
    171   }
    172 
    173  private:
    174   bool* deletion_flag_;
    175 };
    176 
    177 TEST(ValuesTest, ListDeletion) {
    178   bool deletion_flag = true;
    179 
    180   {
    181     ListValue list;
    182     list.Append(new DeletionTestValue(&deletion_flag));
    183     EXPECT_FALSE(deletion_flag);
    184   }
    185   EXPECT_TRUE(deletion_flag);
    186 
    187   {
    188     ListValue list;
    189     list.Append(new DeletionTestValue(&deletion_flag));
    190     EXPECT_FALSE(deletion_flag);
    191     list.Clear();
    192     EXPECT_TRUE(deletion_flag);
    193   }
    194 
    195   {
    196     ListValue list;
    197     list.Append(new DeletionTestValue(&deletion_flag));
    198     EXPECT_FALSE(deletion_flag);
    199     EXPECT_TRUE(list.Set(0, Value::CreateNullValue()));
    200     EXPECT_TRUE(deletion_flag);
    201   }
    202 }
    203 
    204 TEST(ValuesTest, ListRemoval) {
    205   bool deletion_flag = true;
    206   scoped_ptr<Value> removed_item;
    207 
    208   {
    209     ListValue list;
    210     list.Append(new DeletionTestValue(&deletion_flag));
    211     EXPECT_FALSE(deletion_flag);
    212     EXPECT_EQ(1U, list.GetSize());
    213     EXPECT_FALSE(list.Remove(std::numeric_limits<size_t>::max(),
    214                              &removed_item));
    215     EXPECT_FALSE(list.Remove(1, &removed_item));
    216     EXPECT_TRUE(list.Remove(0, &removed_item));
    217     ASSERT_TRUE(removed_item);
    218     EXPECT_EQ(0U, list.GetSize());
    219   }
    220   EXPECT_FALSE(deletion_flag);
    221   removed_item.reset();
    222   EXPECT_TRUE(deletion_flag);
    223 
    224   {
    225     ListValue list;
    226     list.Append(new DeletionTestValue(&deletion_flag));
    227     EXPECT_FALSE(deletion_flag);
    228     EXPECT_TRUE(list.Remove(0, NULL));
    229     EXPECT_TRUE(deletion_flag);
    230     EXPECT_EQ(0U, list.GetSize());
    231   }
    232 
    233   {
    234     ListValue list;
    235     DeletionTestValue* value = new DeletionTestValue(&deletion_flag);
    236     list.Append(value);
    237     EXPECT_FALSE(deletion_flag);
    238     size_t index = 0;
    239     list.Remove(*value, &index);
    240     EXPECT_EQ(0U, index);
    241     EXPECT_TRUE(deletion_flag);
    242     EXPECT_EQ(0U, list.GetSize());
    243   }
    244 }
    245 
    246 TEST(ValuesTest, DictionaryDeletion) {
    247   std::string key = "test";
    248   bool deletion_flag = true;
    249 
    250   {
    251     DictionaryValue dict;
    252     dict.Set(key, new DeletionTestValue(&deletion_flag));
    253     EXPECT_FALSE(deletion_flag);
    254   }
    255   EXPECT_TRUE(deletion_flag);
    256 
    257   {
    258     DictionaryValue dict;
    259     dict.Set(key, new DeletionTestValue(&deletion_flag));
    260     EXPECT_FALSE(deletion_flag);
    261     dict.Clear();
    262     EXPECT_TRUE(deletion_flag);
    263   }
    264 
    265   {
    266     DictionaryValue dict;
    267     dict.Set(key, new DeletionTestValue(&deletion_flag));
    268     EXPECT_FALSE(deletion_flag);
    269     dict.Set(key, Value::CreateNullValue());
    270     EXPECT_TRUE(deletion_flag);
    271   }
    272 }
    273 
    274 TEST(ValuesTest, DictionaryRemoval) {
    275   std::string key = "test";
    276   bool deletion_flag = true;
    277   scoped_ptr<Value> removed_item;
    278 
    279   {
    280     DictionaryValue dict;
    281     dict.Set(key, new DeletionTestValue(&deletion_flag));
    282     EXPECT_FALSE(deletion_flag);
    283     EXPECT_TRUE(dict.HasKey(key));
    284     EXPECT_FALSE(dict.Remove("absent key", &removed_item));
    285     EXPECT_TRUE(dict.Remove(key, &removed_item));
    286     EXPECT_FALSE(dict.HasKey(key));
    287     ASSERT_TRUE(removed_item);
    288   }
    289   EXPECT_FALSE(deletion_flag);
    290   removed_item.reset();
    291   EXPECT_TRUE(deletion_flag);
    292 
    293   {
    294     DictionaryValue dict;
    295     dict.Set(key, new DeletionTestValue(&deletion_flag));
    296     EXPECT_FALSE(deletion_flag);
    297     EXPECT_TRUE(dict.HasKey(key));
    298     EXPECT_TRUE(dict.Remove(key, NULL));
    299     EXPECT_TRUE(deletion_flag);
    300     EXPECT_FALSE(dict.HasKey(key));
    301   }
    302 }
    303 
    304 TEST(ValuesTest, DictionaryWithoutPathExpansion) {
    305   DictionaryValue dict;
    306   dict.Set("this.is.expanded", Value::CreateNullValue());
    307   dict.SetWithoutPathExpansion("this.isnt.expanded", Value::CreateNullValue());
    308 
    309   EXPECT_FALSE(dict.HasKey("this.is.expanded"));
    310   EXPECT_TRUE(dict.HasKey("this"));
    311   Value* value1;
    312   EXPECT_TRUE(dict.Get("this", &value1));
    313   DictionaryValue* value2;
    314   ASSERT_TRUE(dict.GetDictionaryWithoutPathExpansion("this", &value2));
    315   EXPECT_EQ(value1, value2);
    316   EXPECT_EQ(1U, value2->size());
    317 
    318   EXPECT_TRUE(dict.HasKey("this.isnt.expanded"));
    319   Value* value3;
    320   EXPECT_FALSE(dict.Get("this.isnt.expanded", &value3));
    321   Value* value4;
    322   ASSERT_TRUE(dict.GetWithoutPathExpansion("this.isnt.expanded", &value4));
    323   EXPECT_EQ(Value::TYPE_NULL, value4->GetType());
    324 }
    325 
    326 TEST(ValuesTest, DeepCopy) {
    327   DictionaryValue original_dict;
    328   Value* original_null = Value::CreateNullValue();
    329   original_dict.Set("null", original_null);
    330   FundamentalValue* original_bool = new FundamentalValue(true);
    331   original_dict.Set("bool", original_bool);
    332   FundamentalValue* original_int = new FundamentalValue(42);
    333   original_dict.Set("int", original_int);
    334   FundamentalValue* original_double = new FundamentalValue(3.14);
    335   original_dict.Set("double", original_double);
    336   StringValue* original_string = new StringValue("hello");
    337   original_dict.Set("string", original_string);
    338   StringValue* original_string16 = new StringValue(ASCIIToUTF16("hello16"));
    339   original_dict.Set("string16", original_string16);
    340 
    341   scoped_ptr<char[]> original_buffer(new char[42]);
    342   memset(original_buffer.get(), '!', 42);
    343   BinaryValue* original_binary = new BinaryValue(original_buffer.Pass(), 42);
    344   original_dict.Set("binary", original_binary);
    345 
    346   ListValue* original_list = new ListValue();
    347   FundamentalValue* original_list_element_0 = new FundamentalValue(0);
    348   original_list->Append(original_list_element_0);
    349   FundamentalValue* original_list_element_1 = new FundamentalValue(1);
    350   original_list->Append(original_list_element_1);
    351   original_dict.Set("list", original_list);
    352 
    353   DictionaryValue* original_nested_dictionary = new DictionaryValue();
    354   original_nested_dictionary->Set("key", new StringValue("value"));
    355   original_dict.Set("dictionary", original_nested_dictionary);
    356 
    357   scoped_ptr<DictionaryValue> copy_dict(original_dict.DeepCopy());
    358   ASSERT_TRUE(copy_dict.get());
    359   ASSERT_NE(copy_dict.get(), &original_dict);
    360 
    361   Value* copy_null = NULL;
    362   ASSERT_TRUE(copy_dict->Get("null", &copy_null));
    363   ASSERT_TRUE(copy_null);
    364   ASSERT_NE(copy_null, original_null);
    365   ASSERT_TRUE(copy_null->IsType(Value::TYPE_NULL));
    366 
    367   Value* copy_bool = NULL;
    368   ASSERT_TRUE(copy_dict->Get("bool", &copy_bool));
    369   ASSERT_TRUE(copy_bool);
    370   ASSERT_NE(copy_bool, original_bool);
    371   ASSERT_TRUE(copy_bool->IsType(Value::TYPE_BOOLEAN));
    372   bool copy_bool_value = false;
    373   ASSERT_TRUE(copy_bool->GetAsBoolean(&copy_bool_value));
    374   ASSERT_TRUE(copy_bool_value);
    375 
    376   Value* copy_int = NULL;
    377   ASSERT_TRUE(copy_dict->Get("int", &copy_int));
    378   ASSERT_TRUE(copy_int);
    379   ASSERT_NE(copy_int, original_int);
    380   ASSERT_TRUE(copy_int->IsType(Value::TYPE_INTEGER));
    381   int copy_int_value = 0;
    382   ASSERT_TRUE(copy_int->GetAsInteger(&copy_int_value));
    383   ASSERT_EQ(42, copy_int_value);
    384 
    385   Value* copy_double = NULL;
    386   ASSERT_TRUE(copy_dict->Get("double", &copy_double));
    387   ASSERT_TRUE(copy_double);
    388   ASSERT_NE(copy_double, original_double);
    389   ASSERT_TRUE(copy_double->IsType(Value::TYPE_DOUBLE));
    390   double copy_double_value = 0;
    391   ASSERT_TRUE(copy_double->GetAsDouble(&copy_double_value));
    392   ASSERT_EQ(3.14, copy_double_value);
    393 
    394   Value* copy_string = NULL;
    395   ASSERT_TRUE(copy_dict->Get("string", &copy_string));
    396   ASSERT_TRUE(copy_string);
    397   ASSERT_NE(copy_string, original_string);
    398   ASSERT_TRUE(copy_string->IsType(Value::TYPE_STRING));
    399   std::string copy_string_value;
    400   string16 copy_string16_value;
    401   ASSERT_TRUE(copy_string->GetAsString(&copy_string_value));
    402   ASSERT_TRUE(copy_string->GetAsString(&copy_string16_value));
    403   ASSERT_EQ(std::string("hello"), copy_string_value);
    404   ASSERT_EQ(ASCIIToUTF16("hello"), copy_string16_value);
    405 
    406   Value* copy_string16 = NULL;
    407   ASSERT_TRUE(copy_dict->Get("string16", &copy_string16));
    408   ASSERT_TRUE(copy_string16);
    409   ASSERT_NE(copy_string16, original_string16);
    410   ASSERT_TRUE(copy_string16->IsType(Value::TYPE_STRING));
    411   ASSERT_TRUE(copy_string16->GetAsString(&copy_string_value));
    412   ASSERT_TRUE(copy_string16->GetAsString(&copy_string16_value));
    413   ASSERT_EQ(std::string("hello16"), copy_string_value);
    414   ASSERT_EQ(ASCIIToUTF16("hello16"), copy_string16_value);
    415 
    416   Value* copy_binary = NULL;
    417   ASSERT_TRUE(copy_dict->Get("binary", &copy_binary));
    418   ASSERT_TRUE(copy_binary);
    419   ASSERT_NE(copy_binary, original_binary);
    420   ASSERT_TRUE(copy_binary->IsType(Value::TYPE_BINARY));
    421   ASSERT_NE(original_binary->GetBuffer(),
    422     static_cast<BinaryValue*>(copy_binary)->GetBuffer());
    423   ASSERT_EQ(original_binary->GetSize(),
    424     static_cast<BinaryValue*>(copy_binary)->GetSize());
    425   ASSERT_EQ(0, memcmp(original_binary->GetBuffer(),
    426                static_cast<BinaryValue*>(copy_binary)->GetBuffer(),
    427                original_binary->GetSize()));
    428 
    429   Value* copy_value = NULL;
    430   ASSERT_TRUE(copy_dict->Get("list", &copy_value));
    431   ASSERT_TRUE(copy_value);
    432   ASSERT_NE(copy_value, original_list);
    433   ASSERT_TRUE(copy_value->IsType(Value::TYPE_LIST));
    434   ListValue* copy_list = NULL;
    435   ASSERT_TRUE(copy_value->GetAsList(&copy_list));
    436   ASSERT_TRUE(copy_list);
    437   ASSERT_EQ(2U, copy_list->GetSize());
    438 
    439   Value* copy_list_element_0;
    440   ASSERT_TRUE(copy_list->Get(0, &copy_list_element_0));
    441   ASSERT_TRUE(copy_list_element_0);
    442   ASSERT_NE(copy_list_element_0, original_list_element_0);
    443   int copy_list_element_0_value;
    444   ASSERT_TRUE(copy_list_element_0->GetAsInteger(&copy_list_element_0_value));
    445   ASSERT_EQ(0, copy_list_element_0_value);
    446 
    447   Value* copy_list_element_1;
    448   ASSERT_TRUE(copy_list->Get(1, &copy_list_element_1));
    449   ASSERT_TRUE(copy_list_element_1);
    450   ASSERT_NE(copy_list_element_1, original_list_element_1);
    451   int copy_list_element_1_value;
    452   ASSERT_TRUE(copy_list_element_1->GetAsInteger(&copy_list_element_1_value));
    453   ASSERT_EQ(1, copy_list_element_1_value);
    454 
    455   copy_value = NULL;
    456   ASSERT_TRUE(copy_dict->Get("dictionary", &copy_value));
    457   ASSERT_TRUE(copy_value);
    458   ASSERT_NE(copy_value, original_nested_dictionary);
    459   ASSERT_TRUE(copy_value->IsType(Value::TYPE_DICTIONARY));
    460   DictionaryValue* copy_nested_dictionary = NULL;
    461   ASSERT_TRUE(copy_value->GetAsDictionary(&copy_nested_dictionary));
    462   ASSERT_TRUE(copy_nested_dictionary);
    463   EXPECT_TRUE(copy_nested_dictionary->HasKey("key"));
    464 }
    465 
    466 TEST(ValuesTest, Equals) {
    467   Value* null1 = Value::CreateNullValue();
    468   Value* null2 = Value::CreateNullValue();
    469   EXPECT_NE(null1, null2);
    470   EXPECT_TRUE(null1->Equals(null2));
    471 
    472   Value* boolean = new FundamentalValue(false);
    473   EXPECT_FALSE(null1->Equals(boolean));
    474   delete null1;
    475   delete null2;
    476   delete boolean;
    477 
    478   DictionaryValue dv;
    479   dv.SetBoolean("a", false);
    480   dv.SetInteger("b", 2);
    481   dv.SetDouble("c", 2.5);
    482   dv.SetString("d1", "string");
    483   dv.SetString("d2", ASCIIToUTF16("http://google.com"));
    484   dv.Set("e", Value::CreateNullValue());
    485 
    486   scoped_ptr<DictionaryValue> copy;
    487   copy.reset(dv.DeepCopy());
    488   EXPECT_TRUE(dv.Equals(copy.get()));
    489 
    490   ListValue* list = new ListValue;
    491   list->Append(Value::CreateNullValue());
    492   list->Append(new DictionaryValue);
    493   dv.Set("f", list);
    494 
    495   EXPECT_FALSE(dv.Equals(copy.get()));
    496   copy->Set("f", list->DeepCopy());
    497   EXPECT_TRUE(dv.Equals(copy.get()));
    498 
    499   list->Append(new FundamentalValue(true));
    500   EXPECT_FALSE(dv.Equals(copy.get()));
    501 
    502   // Check if Equals detects differences in only the keys.
    503   copy.reset(dv.DeepCopy());
    504   EXPECT_TRUE(dv.Equals(copy.get()));
    505   copy->Remove("a", NULL);
    506   copy->SetBoolean("aa", false);
    507   EXPECT_FALSE(dv.Equals(copy.get()));
    508 }
    509 
    510 TEST(ValuesTest, StaticEquals) {
    511   scoped_ptr<Value> null1(Value::CreateNullValue());
    512   scoped_ptr<Value> null2(Value::CreateNullValue());
    513   EXPECT_TRUE(Value::Equals(null1.get(), null2.get()));
    514   EXPECT_TRUE(Value::Equals(NULL, NULL));
    515 
    516   scoped_ptr<Value> i42(new FundamentalValue(42));
    517   scoped_ptr<Value> j42(new FundamentalValue(42));
    518   scoped_ptr<Value> i17(new FundamentalValue(17));
    519   EXPECT_TRUE(Value::Equals(i42.get(), i42.get()));
    520   EXPECT_TRUE(Value::Equals(j42.get(), i42.get()));
    521   EXPECT_TRUE(Value::Equals(i42.get(), j42.get()));
    522   EXPECT_FALSE(Value::Equals(i42.get(), i17.get()));
    523   EXPECT_FALSE(Value::Equals(i42.get(), NULL));
    524   EXPECT_FALSE(Value::Equals(NULL, i42.get()));
    525 
    526   // NULL and Value::CreateNullValue() are intentionally different: We need
    527   // support for NULL as a return value for "undefined" without caring for
    528   // ownership of the pointer.
    529   EXPECT_FALSE(Value::Equals(null1.get(), NULL));
    530   EXPECT_FALSE(Value::Equals(NULL, null1.get()));
    531 }
    532 
    533 TEST(ValuesTest, DeepCopyCovariantReturnTypes) {
    534   DictionaryValue original_dict;
    535   Value* original_null = Value::CreateNullValue();
    536   original_dict.Set("null", original_null);
    537   FundamentalValue* original_bool = new FundamentalValue(true);
    538   original_dict.Set("bool", original_bool);
    539   FundamentalValue* original_int = new FundamentalValue(42);
    540   original_dict.Set("int", original_int);
    541   FundamentalValue* original_double = new FundamentalValue(3.14);
    542   original_dict.Set("double", original_double);
    543   StringValue* original_string = new StringValue("hello");
    544   original_dict.Set("string", original_string);
    545   StringValue* original_string16 = new StringValue(ASCIIToUTF16("hello16"));
    546   original_dict.Set("string16", original_string16);
    547 
    548   scoped_ptr<char[]> original_buffer(new char[42]);
    549   memset(original_buffer.get(), '!', 42);
    550   BinaryValue* original_binary = new BinaryValue(original_buffer.Pass(), 42);
    551   original_dict.Set("binary", original_binary);
    552 
    553   ListValue* original_list = new ListValue();
    554   FundamentalValue* original_list_element_0 = new FundamentalValue(0);
    555   original_list->Append(original_list_element_0);
    556   FundamentalValue* original_list_element_1 = new FundamentalValue(1);
    557   original_list->Append(original_list_element_1);
    558   original_dict.Set("list", original_list);
    559 
    560   Value* original_dict_value = &original_dict;
    561   Value* original_bool_value = original_bool;
    562   Value* original_int_value = original_int;
    563   Value* original_double_value = original_double;
    564   Value* original_string_value = original_string;
    565   Value* original_string16_value = original_string16;
    566   Value* original_binary_value = original_binary;
    567   Value* original_list_value = original_list;
    568 
    569   scoped_ptr<Value> copy_dict_value(original_dict_value->DeepCopy());
    570   scoped_ptr<Value> copy_bool_value(original_bool_value->DeepCopy());
    571   scoped_ptr<Value> copy_int_value(original_int_value->DeepCopy());
    572   scoped_ptr<Value> copy_double_value(original_double_value->DeepCopy());
    573   scoped_ptr<Value> copy_string_value(original_string_value->DeepCopy());
    574   scoped_ptr<Value> copy_string16_value(original_string16_value->DeepCopy());
    575   scoped_ptr<Value> copy_binary_value(original_binary_value->DeepCopy());
    576   scoped_ptr<Value> copy_list_value(original_list_value->DeepCopy());
    577 
    578   EXPECT_TRUE(original_dict_value->Equals(copy_dict_value.get()));
    579   EXPECT_TRUE(original_bool_value->Equals(copy_bool_value.get()));
    580   EXPECT_TRUE(original_int_value->Equals(copy_int_value.get()));
    581   EXPECT_TRUE(original_double_value->Equals(copy_double_value.get()));
    582   EXPECT_TRUE(original_string_value->Equals(copy_string_value.get()));
    583   EXPECT_TRUE(original_string16_value->Equals(copy_string16_value.get()));
    584   EXPECT_TRUE(original_binary_value->Equals(copy_binary_value.get()));
    585   EXPECT_TRUE(original_list_value->Equals(copy_list_value.get()));
    586 }
    587 
    588 TEST(ValuesTest, RemoveEmptyChildren) {
    589   scoped_ptr<DictionaryValue> root(new DictionaryValue);
    590   // Remove empty lists and dictionaries.
    591   root->Set("empty_dict", new DictionaryValue);
    592   root->Set("empty_list", new ListValue);
    593   root->SetWithoutPathExpansion("a.b.c.d.e", new DictionaryValue);
    594   root.reset(root->DeepCopyWithoutEmptyChildren());
    595   EXPECT_TRUE(root->empty());
    596 
    597   // Make sure we don't prune too much.
    598   root->SetBoolean("bool", true);
    599   root->Set("empty_dict", new DictionaryValue);
    600   root->SetString("empty_string", std::string());
    601   root.reset(root->DeepCopyWithoutEmptyChildren());
    602   EXPECT_EQ(2U, root->size());
    603 
    604   // Should do nothing.
    605   root.reset(root->DeepCopyWithoutEmptyChildren());
    606   EXPECT_EQ(2U, root->size());
    607 
    608   // Nested test cases.  These should all reduce back to the bool and string
    609   // set above.
    610   {
    611     root->Set("a.b.c.d.e", new DictionaryValue);
    612     root.reset(root->DeepCopyWithoutEmptyChildren());
    613     EXPECT_EQ(2U, root->size());
    614   }
    615   {
    616     DictionaryValue* inner = new DictionaryValue;
    617     root->Set("dict_with_emtpy_children", inner);
    618     inner->Set("empty_dict", new DictionaryValue);
    619     inner->Set("empty_list", new ListValue);
    620     root.reset(root->DeepCopyWithoutEmptyChildren());
    621     EXPECT_EQ(2U, root->size());
    622   }
    623   {
    624     ListValue* inner = new ListValue;
    625     root->Set("list_with_empty_children", inner);
    626     inner->Append(new DictionaryValue);
    627     inner->Append(new ListValue);
    628     root.reset(root->DeepCopyWithoutEmptyChildren());
    629     EXPECT_EQ(2U, root->size());
    630   }
    631 
    632   // Nested with siblings.
    633   {
    634     ListValue* inner = new ListValue;
    635     root->Set("list_with_empty_children", inner);
    636     inner->Append(new DictionaryValue);
    637     inner->Append(new ListValue);
    638     DictionaryValue* inner2 = new DictionaryValue;
    639     root->Set("dict_with_empty_children", inner2);
    640     inner2->Set("empty_dict", new DictionaryValue);
    641     inner2->Set("empty_list", new ListValue);
    642     root.reset(root->DeepCopyWithoutEmptyChildren());
    643     EXPECT_EQ(2U, root->size());
    644   }
    645 
    646   // Make sure nested values don't get pruned.
    647   {
    648     ListValue* inner = new ListValue;
    649     root->Set("list_with_empty_children", inner);
    650     ListValue* inner2 = new ListValue;
    651     inner->Append(new DictionaryValue);
    652     inner->Append(inner2);
    653     inner2->Append(new StringValue("hello"));
    654     root.reset(root->DeepCopyWithoutEmptyChildren());
    655     EXPECT_EQ(3U, root->size());
    656     EXPECT_TRUE(root->GetList("list_with_empty_children", &inner));
    657     EXPECT_EQ(1U, inner->GetSize());  // Dictionary was pruned.
    658     EXPECT_TRUE(inner->GetList(0, &inner2));
    659     EXPECT_EQ(1U, inner2->GetSize());
    660   }
    661 }
    662 
    663 TEST(ValuesTest, MergeDictionary) {
    664   scoped_ptr<DictionaryValue> base(new DictionaryValue);
    665   base->SetString("base_key", "base_key_value_base");
    666   base->SetString("collide_key", "collide_key_value_base");
    667   DictionaryValue* base_sub_dict = new DictionaryValue;
    668   base_sub_dict->SetString("sub_base_key", "sub_base_key_value_base");
    669   base_sub_dict->SetString("sub_collide_key", "sub_collide_key_value_base");
    670   base->Set("sub_dict_key", base_sub_dict);
    671 
    672   scoped_ptr<DictionaryValue> merge(new DictionaryValue);
    673   merge->SetString("merge_key", "merge_key_value_merge");
    674   merge->SetString("collide_key", "collide_key_value_merge");
    675   DictionaryValue* merge_sub_dict = new DictionaryValue;
    676   merge_sub_dict->SetString("sub_merge_key", "sub_merge_key_value_merge");
    677   merge_sub_dict->SetString("sub_collide_key", "sub_collide_key_value_merge");
    678   merge->Set("sub_dict_key", merge_sub_dict);
    679 
    680   base->MergeDictionary(merge.get());
    681 
    682   EXPECT_EQ(4U, base->size());
    683   std::string base_key_value;
    684   EXPECT_TRUE(base->GetString("base_key", &base_key_value));
    685   EXPECT_EQ("base_key_value_base", base_key_value); // Base value preserved.
    686   std::string collide_key_value;
    687   EXPECT_TRUE(base->GetString("collide_key", &collide_key_value));
    688   EXPECT_EQ("collide_key_value_merge", collide_key_value); // Replaced.
    689   std::string merge_key_value;
    690   EXPECT_TRUE(base->GetString("merge_key", &merge_key_value));
    691   EXPECT_EQ("merge_key_value_merge", merge_key_value); // Merged in.
    692 
    693   DictionaryValue* res_sub_dict;
    694   EXPECT_TRUE(base->GetDictionary("sub_dict_key", &res_sub_dict));
    695   EXPECT_EQ(3U, res_sub_dict->size());
    696   std::string sub_base_key_value;
    697   EXPECT_TRUE(res_sub_dict->GetString("sub_base_key", &sub_base_key_value));
    698   EXPECT_EQ("sub_base_key_value_base", sub_base_key_value); // Preserved.
    699   std::string sub_collide_key_value;
    700   EXPECT_TRUE(res_sub_dict->GetString("sub_collide_key",
    701                                       &sub_collide_key_value));
    702   EXPECT_EQ("sub_collide_key_value_merge", sub_collide_key_value); // Replaced.
    703   std::string sub_merge_key_value;
    704   EXPECT_TRUE(res_sub_dict->GetString("sub_merge_key", &sub_merge_key_value));
    705   EXPECT_EQ("sub_merge_key_value_merge", sub_merge_key_value); // Merged in.
    706 }
    707 
    708 TEST(ValuesTest, MergeDictionaryDeepCopy) {
    709   DictionaryValue* child = new DictionaryValue;
    710   child->SetString("test", "value");
    711   EXPECT_EQ(1U, child->size());
    712 
    713   std::string value;
    714   EXPECT_TRUE(child->GetString("test", &value));
    715   EXPECT_EQ("value", value);
    716 
    717   scoped_ptr<DictionaryValue> base(new DictionaryValue);
    718   base->Set("dict", child);
    719   EXPECT_EQ(1U, base->size());
    720 
    721   DictionaryValue* ptr;
    722   EXPECT_TRUE(base->GetDictionary("dict", &ptr));
    723   EXPECT_EQ(child, ptr);
    724 
    725   scoped_ptr<DictionaryValue> merged(new DictionaryValue);
    726   merged->MergeDictionary(base.get());
    727   EXPECT_EQ(1U, merged->size());
    728   EXPECT_TRUE(merged->GetDictionary("dict", &ptr));
    729   EXPECT_NE(child, ptr);
    730   EXPECT_TRUE(ptr->GetString("test", &value));
    731   EXPECT_EQ("value", value);
    732 
    733   child->SetString("test", "overwrite");
    734   base.reset();
    735   EXPECT_TRUE(ptr->GetString("test", &value));
    736   EXPECT_EQ("value", value);
    737 }
    738 
    739 TEST(ValuesTest, DictionaryIterator) {
    740   DictionaryValue dict;
    741   for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
    742     ADD_FAILURE();
    743   }
    744 
    745   StringValue value1("value1");
    746   dict.Set("key1", value1.DeepCopy());
    747   bool seen1 = false;
    748   for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
    749     EXPECT_FALSE(seen1);
    750     EXPECT_EQ("key1", it.key());
    751     EXPECT_TRUE(value1.Equals(&it.value()));
    752     seen1 = true;
    753   }
    754   EXPECT_TRUE(seen1);
    755 
    756   StringValue value2("value2");
    757   dict.Set("key2", value2.DeepCopy());
    758   bool seen2 = seen1 = false;
    759   for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
    760     if (it.key() == "key1") {
    761       EXPECT_FALSE(seen1);
    762       EXPECT_TRUE(value1.Equals(&it.value()));
    763       seen1 = true;
    764     } else if (it.key() == "key2") {
    765       EXPECT_FALSE(seen2);
    766       EXPECT_TRUE(value2.Equals(&it.value()));
    767       seen2 = true;
    768     } else {
    769       ADD_FAILURE();
    770     }
    771   }
    772   EXPECT_TRUE(seen1);
    773   EXPECT_TRUE(seen2);
    774 }
    775 
    776 }  // namespace base
    777