1 // Copyright 2014 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 "extensions/browser/value_store/value_store_unittest.h" 6 7 #include "base/json/json_writer.h" 8 #include "base/memory/linked_ptr.h" 9 #include "base/values.h" 10 11 using content::BrowserThread; 12 13 namespace { 14 15 // To save typing ValueStore::DEFAULTS everywhere. 16 const ValueStore::WriteOptions DEFAULTS = ValueStore::DEFAULTS; 17 18 // Gets the pretty-printed JSON for a value. 19 std::string GetJSON(const base::Value& value) { 20 std::string json; 21 base::JSONWriter::WriteWithOptions(&value, 22 base::JSONWriter::OPTIONS_PRETTY_PRINT, 23 &json); 24 return json; 25 } 26 27 } // namespace 28 29 // Compares two possibly NULL values for equality, filling |error| with an 30 // appropriate error message if they're different. 31 bool ValuesEqual(const base::Value* expected, 32 const base::Value* actual, 33 std::string* error) { 34 if (expected == actual) { 35 return true; 36 } 37 if (expected && !actual) { 38 *error = "Expected: " + GetJSON(*expected) + ", actual: NULL"; 39 return false; 40 } 41 if (actual && !expected) { 42 *error = "Expected: NULL, actual: " + GetJSON(*actual); 43 return false; 44 } 45 if (!expected->Equals(actual)) { 46 *error = 47 "Expected: " + GetJSON(*expected) + ", actual: " + GetJSON(*actual); 48 return false; 49 } 50 return true; 51 } 52 53 // Returns whether the read result of a storage operation has the expected 54 // settings. 55 testing::AssertionResult SettingsEq( 56 const char* _1, const char* _2, 57 const base::DictionaryValue& expected, 58 ValueStore::ReadResult actual_result) { 59 if (actual_result->HasError()) { 60 return testing::AssertionFailure() << 61 "Result has error: " << actual_result->error().message; 62 } 63 64 std::string error; 65 if (!ValuesEqual(&expected, &actual_result->settings(), &error)) { 66 return testing::AssertionFailure() << error; 67 } 68 69 return testing::AssertionSuccess(); 70 } 71 72 // Returns whether the write result of a storage operation has the expected 73 // changes. 74 testing::AssertionResult ChangesEq( 75 const char* _1, const char* _2, 76 const ValueStoreChangeList& expected, 77 ValueStore::WriteResult actual_result) { 78 if (actual_result->HasError()) { 79 return testing::AssertionFailure() << 80 "Result has error: " << actual_result->error().message; 81 } 82 83 const ValueStoreChangeList& actual = actual_result->changes(); 84 if (expected.size() != actual.size()) { 85 return testing::AssertionFailure() << 86 "Actual has wrong size, expecting " << expected.size() << 87 " but was " << actual.size(); 88 } 89 90 std::map<std::string, linked_ptr<ValueStoreChange> > expected_as_map; 91 for (ValueStoreChangeList::const_iterator it = expected.begin(); 92 it != expected.end(); ++it) { 93 expected_as_map[it->key()] = 94 linked_ptr<ValueStoreChange>(new ValueStoreChange(*it)); 95 } 96 97 std::set<std::string> keys_seen; 98 99 for (ValueStoreChangeList::const_iterator it = actual.begin(); 100 it != actual.end(); ++it) { 101 if (keys_seen.count(it->key())) { 102 return testing::AssertionFailure() << 103 "Multiple changes seen for key: " << it->key(); 104 } 105 keys_seen.insert(it->key()); 106 107 if (!expected_as_map.count(it->key())) { 108 return testing::AssertionFailure() << 109 "Actual has unexpected change for key: " << it->key(); 110 } 111 112 ValueStoreChange expected_change = *expected_as_map[it->key()]; 113 std::string error; 114 if (!ValuesEqual(expected_change.new_value(), it->new_value(), &error)) { 115 return testing::AssertionFailure() << 116 "New value for " << it->key() << " was unexpected: " << error; 117 } 118 if (!ValuesEqual(expected_change.old_value(), it->old_value(), &error)) { 119 return testing::AssertionFailure() << 120 "Old value for " << it->key() << " was unexpected: " << error; 121 } 122 } 123 124 return testing::AssertionSuccess(); 125 } 126 127 ValueStoreTest::ValueStoreTest() 128 : key1_("foo"), 129 key2_("bar"), 130 key3_("baz"), 131 empty_dict_(new base::DictionaryValue()), 132 dict1_(new base::DictionaryValue()), 133 dict3_(new base::DictionaryValue()), 134 dict12_(new base::DictionaryValue()), 135 dict123_(new base::DictionaryValue()), 136 ui_thread_(BrowserThread::UI, base::MessageLoop::current()), 137 file_thread_(BrowserThread::FILE, base::MessageLoop::current()) { 138 val1_.reset(base::Value::CreateStringValue(key1_ + "Value")); 139 val2_.reset(base::Value::CreateStringValue(key2_ + "Value")); 140 val3_.reset(base::Value::CreateStringValue(key3_ + "Value")); 141 142 list1_.push_back(key1_); 143 list2_.push_back(key2_); 144 list3_.push_back(key3_); 145 list12_.push_back(key1_); 146 list12_.push_back(key2_); 147 list13_.push_back(key1_); 148 list13_.push_back(key3_); 149 list123_.push_back(key1_); 150 list123_.push_back(key2_); 151 list123_.push_back(key3_); 152 153 set1_.insert(list1_.begin(), list1_.end()); 154 set2_.insert(list2_.begin(), list2_.end()); 155 set3_.insert(list3_.begin(), list3_.end()); 156 set12_.insert(list12_.begin(), list12_.end()); 157 set13_.insert(list13_.begin(), list13_.end()); 158 set123_.insert(list123_.begin(), list123_.end()); 159 160 dict1_->Set(key1_, val1_->DeepCopy()); 161 dict3_->Set(key3_, val3_->DeepCopy()); 162 dict12_->Set(key1_, val1_->DeepCopy()); 163 dict12_->Set(key2_, val2_->DeepCopy()); 164 dict123_->Set(key1_, val1_->DeepCopy()); 165 dict123_->Set(key2_, val2_->DeepCopy()); 166 dict123_->Set(key3_, val3_->DeepCopy()); 167 } 168 169 ValueStoreTest::~ValueStoreTest() {} 170 171 void ValueStoreTest::SetUp() { 172 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 173 storage_.reset((GetParam())(temp_dir_.path().AppendASCII("dbName"))); 174 ASSERT_TRUE(storage_.get()); 175 } 176 177 void ValueStoreTest::TearDown() { 178 storage_.reset(); 179 } 180 181 TEST_P(ValueStoreTest, GetWhenEmpty) { 182 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_)); 183 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_)); 184 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_)); 185 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get()); 186 } 187 188 TEST_P(ValueStoreTest, GetWithSingleValue) { 189 { 190 ValueStoreChangeList changes; 191 changes.push_back(ValueStoreChange(key1_, NULL, val1_->DeepCopy())); 192 EXPECT_PRED_FORMAT2(ChangesEq, 193 changes, storage_->Set(DEFAULTS, key1_, *val1_)); 194 } 195 196 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_)); 197 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key2_)); 198 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_)); 199 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_)); 200 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list123_)); 201 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get()); 202 } 203 204 TEST_P(ValueStoreTest, GetWithMultipleValues) { 205 { 206 ValueStoreChangeList changes; 207 changes.push_back(ValueStoreChange(key1_, NULL, val1_->DeepCopy())); 208 changes.push_back(ValueStoreChange(key2_, NULL, val2_->DeepCopy())); 209 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_)); 210 } 211 212 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_)); 213 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_)); 214 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_)); 215 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_)); 216 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get()); 217 } 218 219 TEST_P(ValueStoreTest, RemoveWhenEmpty) { 220 EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), 221 storage_->Remove(key1_)); 222 223 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_)); 224 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_)); 225 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get()); 226 } 227 228 TEST_P(ValueStoreTest, RemoveWithSingleValue) { 229 storage_->Set(DEFAULTS, *dict1_); 230 { 231 ValueStoreChangeList changes; 232 changes.push_back(ValueStoreChange(key1_, val1_->DeepCopy(), NULL)); 233 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key1_)); 234 } 235 236 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_)); 237 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key2_)); 238 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_)); 239 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list12_)); 240 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get()); 241 } 242 243 TEST_P(ValueStoreTest, RemoveWithMultipleValues) { 244 storage_->Set(DEFAULTS, *dict123_); 245 { 246 ValueStoreChangeList changes; 247 changes.push_back(ValueStoreChange(key3_, val3_->DeepCopy(), NULL)); 248 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key3_)); 249 } 250 251 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_)); 252 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_)); 253 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_)); 254 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list1_)); 255 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list12_)); 256 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list13_)); 257 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_)); 258 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get()); 259 260 { 261 ValueStoreChangeList changes; 262 changes.push_back(ValueStoreChange(key1_, val1_->DeepCopy(), NULL)); 263 changes.push_back(ValueStoreChange(key2_, val2_->DeepCopy(), NULL)); 264 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(list12_)); 265 } 266 267 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_)); 268 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_)); 269 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_)); 270 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list1_)); 271 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list12_)); 272 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list13_)); 273 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_)); 274 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get()); 275 } 276 277 TEST_P(ValueStoreTest, SetWhenOverwriting) { 278 storage_->Set(DEFAULTS, key1_, *val2_); 279 { 280 ValueStoreChangeList changes; 281 changes.push_back( 282 ValueStoreChange(key1_, val2_->DeepCopy(), val1_->DeepCopy())); 283 changes.push_back(ValueStoreChange(key2_, NULL, val2_->DeepCopy())); 284 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_)); 285 } 286 287 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(key1_)); 288 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key3_)); 289 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_)); 290 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list1_)); 291 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list12_)); 292 EXPECT_PRED_FORMAT2(SettingsEq, *dict1_, storage_->Get(list13_)); 293 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get(list123_)); 294 EXPECT_PRED_FORMAT2(SettingsEq, *dict12_, storage_->Get()); 295 } 296 297 TEST_P(ValueStoreTest, ClearWhenEmpty) { 298 EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear()); 299 300 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_)); 301 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_)); 302 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_)); 303 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get()); 304 } 305 306 TEST_P(ValueStoreTest, ClearWhenNotEmpty) { 307 storage_->Set(DEFAULTS, *dict12_); 308 { 309 ValueStoreChangeList changes; 310 changes.push_back(ValueStoreChange(key1_, val1_->DeepCopy(), NULL)); 311 changes.push_back(ValueStoreChange(key2_, val2_->DeepCopy(), NULL)); 312 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear()); 313 } 314 315 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(key1_)); 316 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(empty_list_)); 317 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(list123_)); 318 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get()); 319 } 320 321 // Dots should be allowed in key names; they shouldn't be interpreted as 322 // indexing into a dictionary. 323 TEST_P(ValueStoreTest, DotsInKeyNames) { 324 std::string dot_key("foo.bar"); 325 base::StringValue dot_value("baz.qux"); 326 std::vector<std::string> dot_list; 327 dot_list.push_back(dot_key); 328 base::DictionaryValue dot_dict; 329 dot_dict.SetWithoutPathExpansion(dot_key, dot_value.DeepCopy()); 330 331 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(dot_key)); 332 333 { 334 ValueStoreChangeList changes; 335 changes.push_back( 336 ValueStoreChange(dot_key, NULL, dot_value.DeepCopy())); 337 EXPECT_PRED_FORMAT2(ChangesEq, 338 changes, storage_->Set(DEFAULTS, dot_key, dot_value)); 339 } 340 EXPECT_PRED_FORMAT2(ChangesEq, 341 ValueStoreChangeList(), storage_->Set(DEFAULTS, dot_key, dot_value)); 342 343 EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get(dot_key)); 344 345 { 346 ValueStoreChangeList changes; 347 changes.push_back( 348 ValueStoreChange(dot_key, dot_value.DeepCopy(), NULL)); 349 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(dot_key)); 350 } 351 EXPECT_PRED_FORMAT2(ChangesEq, 352 ValueStoreChangeList(), storage_->Remove(dot_key)); 353 { 354 ValueStoreChangeList changes; 355 changes.push_back( 356 ValueStoreChange(dot_key, NULL, dot_value.DeepCopy())); 357 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, dot_dict)); 358 } 359 360 EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get(dot_list)); 361 EXPECT_PRED_FORMAT2(SettingsEq, dot_dict, storage_->Get()); 362 363 { 364 ValueStoreChangeList changes; 365 changes.push_back( 366 ValueStoreChange(dot_key, dot_value.DeepCopy(), NULL)); 367 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(dot_list)); 368 } 369 370 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get(dot_key)); 371 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get()); 372 } 373 374 TEST_P(ValueStoreTest, DotsInKeyNamesWithDicts) { 375 base::DictionaryValue outer_dict; 376 base::DictionaryValue* inner_dict = new base::DictionaryValue(); 377 outer_dict.Set("foo", inner_dict); 378 inner_dict->SetString("bar", "baz"); 379 380 { 381 ValueStoreChangeList changes; 382 changes.push_back( 383 ValueStoreChange("foo", NULL, inner_dict->DeepCopy())); 384 EXPECT_PRED_FORMAT2(ChangesEq, 385 changes, storage_->Set(DEFAULTS, outer_dict)); 386 } 387 388 EXPECT_PRED_FORMAT2(SettingsEq, outer_dict, storage_->Get("foo")); 389 EXPECT_PRED_FORMAT2(SettingsEq, *empty_dict_, storage_->Get("foo.bar")); 390 } 391 392 TEST_P(ValueStoreTest, ComplexChangedKeysScenarios) { 393 // Test: 394 // - Setting over missing/changed/same keys, combinations. 395 // - Removing over missing and present keys, combinations. 396 // - Clearing. 397 std::vector<std::string> complex_list; 398 base::DictionaryValue complex_changed_dict; 399 400 storage_->Set(DEFAULTS, key1_, *val1_); 401 EXPECT_PRED_FORMAT2(ChangesEq, 402 ValueStoreChangeList(), storage_->Set(DEFAULTS, key1_, *val1_)); 403 { 404 ValueStoreChangeList changes; 405 changes.push_back(ValueStoreChange( 406 key1_, val1_->DeepCopy(), val2_->DeepCopy())); 407 EXPECT_PRED_FORMAT2(ChangesEq, 408 changes, storage_->Set(DEFAULTS, key1_, *val2_)); 409 } 410 { 411 ValueStoreChangeList changes; 412 changes.push_back(ValueStoreChange(key1_, val2_->DeepCopy(), NULL)); 413 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key1_)); 414 EXPECT_PRED_FORMAT2(ChangesEq, 415 ValueStoreChangeList(), storage_->Remove(key1_)); 416 } 417 { 418 ValueStoreChangeList changes; 419 changes.push_back(ValueStoreChange(key1_, NULL, val1_->DeepCopy())); 420 EXPECT_PRED_FORMAT2(ChangesEq, 421 changes, storage_->Set(DEFAULTS, key1_, *val1_)); 422 } 423 { 424 ValueStoreChangeList changes; 425 changes.push_back(ValueStoreChange(key1_, val1_->DeepCopy(), NULL)); 426 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear()); 427 EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear()); 428 } 429 430 { 431 ValueStoreChangeList changes; 432 changes.push_back(ValueStoreChange(key1_, NULL, val1_->DeepCopy())); 433 changes.push_back(ValueStoreChange(key2_, NULL, val2_->DeepCopy())); 434 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_)); 435 EXPECT_PRED_FORMAT2(ChangesEq, 436 ValueStoreChangeList(), storage_->Set(DEFAULTS, *dict12_)); 437 } 438 { 439 ValueStoreChangeList changes; 440 changes.push_back(ValueStoreChange(key3_, NULL, val3_->DeepCopy())); 441 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict123_)); 442 } 443 { 444 base::DictionaryValue to_set; 445 to_set.Set(key1_, val2_->DeepCopy()); 446 to_set.Set(key2_, val2_->DeepCopy()); 447 to_set.Set("asdf", val1_->DeepCopy()); 448 to_set.Set("qwerty", val3_->DeepCopy()); 449 450 ValueStoreChangeList changes; 451 changes.push_back( 452 ValueStoreChange(key1_, val1_->DeepCopy(), val2_->DeepCopy())); 453 changes.push_back(ValueStoreChange("asdf", NULL, val1_->DeepCopy())); 454 changes.push_back( 455 ValueStoreChange("qwerty", NULL, val3_->DeepCopy())); 456 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, to_set)); 457 } 458 { 459 ValueStoreChangeList changes; 460 changes.push_back(ValueStoreChange(key1_, val2_->DeepCopy(), NULL)); 461 changes.push_back(ValueStoreChange(key2_, val2_->DeepCopy(), NULL)); 462 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(list12_)); 463 } 464 { 465 std::vector<std::string> to_remove; 466 to_remove.push_back(key1_); 467 to_remove.push_back("asdf"); 468 469 ValueStoreChangeList changes; 470 changes.push_back(ValueStoreChange("asdf", val1_->DeepCopy(), NULL)); 471 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(to_remove)); 472 } 473 { 474 ValueStoreChangeList changes; 475 changes.push_back(ValueStoreChange(key3_, val3_->DeepCopy(), NULL)); 476 changes.push_back( 477 ValueStoreChange("qwerty", val3_->DeepCopy(), NULL)); 478 EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear()); 479 EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear()); 480 } 481 } 482