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