1 // Copyright 2013 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 "chrome/browser/chromeos/drive/resource_metadata_storage.h" 6 7 #include <algorithm> 8 9 #include "base/file_util.h" 10 #include "base/files/scoped_temp_dir.h" 11 #include "chrome/browser/chromeos/drive/drive.pb.h" 12 #include "chrome/browser/chromeos/drive/test_util.h" 13 #include "chrome/browser/drive/drive_api_util.h" 14 #include "content/public/test/test_browser_thread_bundle.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "third_party/leveldatabase/src/include/leveldb/db.h" 17 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 18 19 namespace drive { 20 namespace internal { 21 22 class ResourceMetadataStorageTest : public testing::Test { 23 protected: 24 virtual void SetUp() OVERRIDE { 25 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 26 27 storage_.reset(new ResourceMetadataStorage( 28 temp_dir_.path(), base::MessageLoopProxy::current().get())); 29 ASSERT_TRUE(storage_->Initialize()); 30 } 31 32 // Overwrites |storage_|'s version. 33 void SetDBVersion(int version) { 34 ResourceMetadataHeader header; 35 ASSERT_TRUE(storage_->GetHeader(&header)); 36 header.set_version(version); 37 EXPECT_TRUE(storage_->PutHeader(header)); 38 } 39 40 bool CheckValidity() { 41 return storage_->CheckValidity(); 42 } 43 44 leveldb::DB* resource_map() { return storage_->resource_map_.get(); } 45 46 // Puts a child entry. 47 void PutChild(const std::string& parent_id, 48 const std::string& child_base_name, 49 const std::string& child_id) { 50 storage_->resource_map_->Put( 51 leveldb::WriteOptions(), 52 ResourceMetadataStorage::GetChildEntryKey(parent_id, child_base_name), 53 child_id); 54 } 55 56 // Removes a child entry. 57 void RemoveChild(const std::string& parent_id, 58 const std::string& child_base_name) { 59 storage_->resource_map_->Delete( 60 leveldb::WriteOptions(), 61 ResourceMetadataStorage::GetChildEntryKey(parent_id, child_base_name)); 62 } 63 64 content::TestBrowserThreadBundle thread_bundle_; 65 base::ScopedTempDir temp_dir_; 66 scoped_ptr<ResourceMetadataStorage, 67 test_util::DestroyHelperForTests> storage_; 68 }; 69 70 TEST_F(ResourceMetadataStorageTest, LargestChangestamp) { 71 const int64 kLargestChangestamp = 1234567890; 72 EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp)); 73 EXPECT_EQ(kLargestChangestamp, storage_->GetLargestChangestamp()); 74 } 75 76 TEST_F(ResourceMetadataStorageTest, PutEntry) { 77 const std::string key1 = "abcdefg"; 78 const std::string key2 = "abcd"; 79 const std::string key3 = "efgh"; 80 const std::string name2 = "ABCD"; 81 const std::string name3 = "EFGH"; 82 83 // key1 not found. 84 ResourceEntry result; 85 EXPECT_FALSE(storage_->GetEntry(key1, &result)); 86 87 // Put entry1. 88 ResourceEntry entry1; 89 entry1.set_local_id(key1); 90 EXPECT_TRUE(storage_->PutEntry(entry1)); 91 92 // key1 found. 93 EXPECT_TRUE(storage_->GetEntry(key1, &result)); 94 95 // key2 not found. 96 EXPECT_FALSE(storage_->GetEntry(key2, &result)); 97 98 // Put entry2 as a child of entry1. 99 ResourceEntry entry2; 100 entry2.set_local_id(key2); 101 entry2.set_parent_local_id(key1); 102 entry2.set_base_name(name2); 103 EXPECT_TRUE(storage_->PutEntry(entry2)); 104 105 // key2 found. 106 EXPECT_TRUE(storage_->GetEntry(key2, &result)); 107 EXPECT_EQ(key2, storage_->GetChild(key1, name2)); 108 109 // Put entry3 as a child of entry2. 110 ResourceEntry entry3; 111 entry3.set_local_id(key3); 112 entry3.set_parent_local_id(key2); 113 entry3.set_base_name(name3); 114 EXPECT_TRUE(storage_->PutEntry(entry3)); 115 116 // key3 found. 117 EXPECT_TRUE(storage_->GetEntry(key3, &result)); 118 EXPECT_EQ(key3, storage_->GetChild(key2, name3)); 119 120 // Change entry3's parent to entry1. 121 entry3.set_parent_local_id(key1); 122 EXPECT_TRUE(storage_->PutEntry(entry3)); 123 124 // entry3 is a child of entry1 now. 125 EXPECT_TRUE(storage_->GetChild(key2, name3).empty()); 126 EXPECT_EQ(key3, storage_->GetChild(key1, name3)); 127 128 // Remove entries. 129 EXPECT_TRUE(storage_->RemoveEntry(key3)); 130 EXPECT_FALSE(storage_->GetEntry(key3, &result)); 131 EXPECT_TRUE(storage_->RemoveEntry(key2)); 132 EXPECT_FALSE(storage_->GetEntry(key2, &result)); 133 EXPECT_TRUE(storage_->RemoveEntry(key1)); 134 EXPECT_FALSE(storage_->GetEntry(key1, &result)); 135 } 136 137 TEST_F(ResourceMetadataStorageTest, Iterator) { 138 // Prepare data. 139 std::vector<std::string> keys; 140 141 keys.push_back("entry1"); 142 keys.push_back("entry2"); 143 keys.push_back("entry3"); 144 keys.push_back("entry4"); 145 146 for (size_t i = 0; i < keys.size(); ++i) { 147 ResourceEntry entry; 148 entry.set_local_id(keys[i]); 149 EXPECT_TRUE(storage_->PutEntry(entry)); 150 } 151 152 // Insert some cache entries. 153 std::map<std::string, FileCacheEntry> cache_entries; 154 cache_entries[keys[0]].set_md5("aaaaaa"); 155 cache_entries[keys[1]].set_md5("bbbbbb"); 156 for (std::map<std::string, FileCacheEntry>::iterator it = 157 cache_entries.begin(); it != cache_entries.end(); ++it) 158 EXPECT_TRUE(storage_->PutCacheEntry(it->first, it->second)); 159 160 // Iterate and check the result. 161 std::map<std::string, ResourceEntry> found_entries; 162 std::map<std::string, FileCacheEntry> found_cache_entries; 163 scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator(); 164 ASSERT_TRUE(it); 165 for (; !it->IsAtEnd(); it->Advance()) { 166 const ResourceEntry& entry = it->GetValue(); 167 found_entries[it->GetID()] = entry; 168 169 FileCacheEntry cache_entry; 170 if (it->GetCacheEntry(&cache_entry)) 171 found_cache_entries[it->GetID()] = cache_entry; 172 } 173 EXPECT_FALSE(it->HasError()); 174 175 EXPECT_EQ(keys.size(), found_entries.size()); 176 for (size_t i = 0; i < keys.size(); ++i) 177 EXPECT_EQ(1U, found_entries.count(keys[i])); 178 179 EXPECT_EQ(cache_entries.size(), found_cache_entries.size()); 180 for (std::map<std::string, FileCacheEntry>::iterator it = 181 cache_entries.begin(); it != cache_entries.end(); ++it) { 182 ASSERT_EQ(1U, found_cache_entries.count(it->first)); 183 EXPECT_EQ(it->second.md5(), found_cache_entries[it->first].md5()); 184 } 185 } 186 187 TEST_F(ResourceMetadataStorageTest, PutCacheEntry) { 188 FileCacheEntry entry; 189 const std::string key1 = "abcdefg"; 190 const std::string key2 = "abcd"; 191 const std::string md5_1 = "foo"; 192 const std::string md5_2 = "bar"; 193 194 // Put cache entries. 195 entry.set_md5(md5_1); 196 EXPECT_TRUE(storage_->PutCacheEntry(key1, entry)); 197 entry.set_md5(md5_2); 198 EXPECT_TRUE(storage_->PutCacheEntry(key2, entry)); 199 200 // Get cache entires. 201 EXPECT_TRUE(storage_->GetCacheEntry(key1, &entry)); 202 EXPECT_EQ(md5_1, entry.md5()); 203 EXPECT_TRUE(storage_->GetCacheEntry(key2, &entry)); 204 EXPECT_EQ(md5_2, entry.md5()); 205 206 // Remove cache entries. 207 EXPECT_TRUE(storage_->RemoveCacheEntry(key1)); 208 EXPECT_FALSE(storage_->GetCacheEntry(key1, &entry)); 209 210 EXPECT_TRUE(storage_->RemoveCacheEntry(key2)); 211 EXPECT_FALSE(storage_->GetCacheEntry(key2, &entry)); 212 } 213 214 TEST_F(ResourceMetadataStorageTest, CacheEntryIterator) { 215 // Prepare data. 216 std::map<std::string, FileCacheEntry> entries; 217 FileCacheEntry cache_entry; 218 219 cache_entry.set_md5("aA"); 220 entries["entry1"] = cache_entry; 221 cache_entry.set_md5("bB"); 222 entries["entry2"] = cache_entry; 223 cache_entry.set_md5("cC"); 224 entries["entry3"] = cache_entry; 225 cache_entry.set_md5("dD"); 226 entries["entry4"] = cache_entry; 227 228 for (std::map<std::string, FileCacheEntry>::iterator it = entries.begin(); 229 it != entries.end(); ++it) 230 EXPECT_TRUE(storage_->PutCacheEntry(it->first, it->second)); 231 232 // Insert some dummy entries. 233 ResourceEntry entry; 234 entry.set_local_id("entry1"); 235 EXPECT_TRUE(storage_->PutEntry(entry)); 236 entry.set_local_id("entry2"); 237 EXPECT_TRUE(storage_->PutEntry(entry)); 238 239 // Iterate and check the result. 240 scoped_ptr<ResourceMetadataStorage::CacheEntryIterator> it = 241 storage_->GetCacheEntryIterator(); 242 ASSERT_TRUE(it); 243 size_t num_entries = 0; 244 for (; !it->IsAtEnd(); it->Advance()) { 245 EXPECT_EQ(1U, entries.count(it->GetID())); 246 EXPECT_EQ(entries[it->GetID()].md5(), it->GetValue().md5()); 247 ++num_entries; 248 } 249 EXPECT_FALSE(it->HasError()); 250 EXPECT_EQ(entries.size(), num_entries); 251 } 252 253 TEST_F(ResourceMetadataStorageTest, GetIdByResourceId) { 254 const std::string local_id = "local_id"; 255 const std::string resource_id = "resource_id"; 256 257 // Resource ID to local ID mapping is not stored yet. 258 std::string id; 259 EXPECT_FALSE(storage_->GetIdByResourceId(resource_id, &id)); 260 261 // Put an entry with the resource ID. 262 ResourceEntry entry; 263 entry.set_local_id(local_id); 264 entry.set_resource_id(resource_id); 265 EXPECT_TRUE(storage_->PutEntry(entry)); 266 267 // Can get local ID by resource ID. 268 EXPECT_TRUE(storage_->GetIdByResourceId(resource_id, &id)); 269 EXPECT_EQ(local_id, id); 270 271 // Resource ID to local ID mapping is removed. 272 EXPECT_TRUE(storage_->RemoveEntry(local_id)); 273 EXPECT_FALSE(storage_->GetIdByResourceId(resource_id, &id)); 274 } 275 276 TEST_F(ResourceMetadataStorageTest, GetChildren) { 277 const std::string parents_id[] = { "mercury", "venus", "mars", "jupiter", 278 "saturn" }; 279 std::vector<std::vector<std::pair<std::string, std::string> > > 280 children_name_id(arraysize(parents_id)); 281 // Skip children_name_id[0/1] here because Mercury and Venus have no moon. 282 children_name_id[2].push_back(std::make_pair("phobos", "mars_i")); 283 children_name_id[2].push_back(std::make_pair("deimos", "mars_ii")); 284 children_name_id[3].push_back(std::make_pair("io", "jupiter_i")); 285 children_name_id[3].push_back(std::make_pair("europa", "jupiter_ii")); 286 children_name_id[3].push_back(std::make_pair("ganymede", "jupiter_iii")); 287 children_name_id[3].push_back(std::make_pair("calisto", "jupiter_iv")); 288 children_name_id[4].push_back(std::make_pair("mimas", "saturn_i")); 289 children_name_id[4].push_back(std::make_pair("enceladus", "saturn_ii")); 290 children_name_id[4].push_back(std::make_pair("tethys", "saturn_iii")); 291 children_name_id[4].push_back(std::make_pair("dione", "saturn_iv")); 292 children_name_id[4].push_back(std::make_pair("rhea", "saturn_v")); 293 children_name_id[4].push_back(std::make_pair("titan", "saturn_vi")); 294 children_name_id[4].push_back(std::make_pair("iapetus", "saturn_vii")); 295 296 // Put parents. 297 for (size_t i = 0; i < arraysize(parents_id); ++i) { 298 ResourceEntry entry; 299 entry.set_local_id(parents_id[i]); 300 EXPECT_TRUE(storage_->PutEntry(entry)); 301 } 302 303 // Put children. 304 for (size_t i = 0; i < children_name_id.size(); ++i) { 305 for (size_t j = 0; j < children_name_id[i].size(); ++j) { 306 ResourceEntry entry; 307 entry.set_local_id(children_name_id[i][j].second); 308 entry.set_parent_local_id(parents_id[i]); 309 entry.set_base_name(children_name_id[i][j].first); 310 EXPECT_TRUE(storage_->PutEntry(entry)); 311 } 312 } 313 314 // Put some dummy cache entries. 315 for (size_t i = 0; i < arraysize(parents_id); ++i) { 316 FileCacheEntry cache_entry; 317 EXPECT_TRUE(storage_->PutCacheEntry(parents_id[i], cache_entry)); 318 } 319 320 // Try to get children. 321 for (size_t i = 0; i < children_name_id.size(); ++i) { 322 std::vector<std::string> children; 323 storage_->GetChildren(parents_id[i], &children); 324 EXPECT_EQ(children_name_id[i].size(), children.size()); 325 for (size_t j = 0; j < children_name_id[i].size(); ++j) { 326 EXPECT_EQ(1, std::count(children.begin(), 327 children.end(), 328 children_name_id[i][j].second)); 329 } 330 } 331 } 332 333 TEST_F(ResourceMetadataStorageTest, OpenExistingDB) { 334 const std::string parent_id1 = "abcdefg"; 335 const std::string child_name1 = "WXYZABC"; 336 const std::string child_id1 = "qwerty"; 337 338 ResourceEntry entry1; 339 entry1.set_local_id(parent_id1); 340 ResourceEntry entry2; 341 entry2.set_local_id(child_id1); 342 entry2.set_parent_local_id(parent_id1); 343 entry2.set_base_name(child_name1); 344 345 // Put some data. 346 EXPECT_TRUE(storage_->PutEntry(entry1)); 347 EXPECT_TRUE(storage_->PutEntry(entry2)); 348 349 // Close DB and reopen. 350 storage_.reset(new ResourceMetadataStorage( 351 temp_dir_.path(), base::MessageLoopProxy::current().get())); 352 ASSERT_TRUE(storage_->Initialize()); 353 354 // Can read data. 355 ResourceEntry result; 356 EXPECT_TRUE(storage_->GetEntry(parent_id1, &result)); 357 358 EXPECT_TRUE(storage_->GetEntry(child_id1, &result)); 359 EXPECT_EQ(parent_id1, result.parent_local_id()); 360 EXPECT_EQ(child_name1, result.base_name()); 361 362 EXPECT_EQ(child_id1, storage_->GetChild(parent_id1, child_name1)); 363 } 364 365 TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M29) { 366 const int64 kLargestChangestamp = 1234567890; 367 368 // Construct M29 version DB. 369 SetDBVersion(6); 370 EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp)); 371 372 leveldb::WriteBatch batch; 373 374 // Put a file entry and its cache entry. 375 ResourceEntry entry; 376 std::string serialized_entry; 377 entry.set_resource_id("file:abcd"); 378 EXPECT_TRUE(entry.SerializeToString(&serialized_entry)); 379 batch.Put("file:abcd", serialized_entry); 380 381 FileCacheEntry cache_entry; 382 EXPECT_TRUE(cache_entry.SerializeToString(&serialized_entry)); 383 batch.Put(std::string("file:abcd") + '\0' + "CACHE", serialized_entry); 384 385 EXPECT_TRUE(resource_map()->Write(leveldb::WriteOptions(), &batch).ok()); 386 387 // Upgrade and reopen. 388 storage_.reset(); 389 EXPECT_TRUE(ResourceMetadataStorage::UpgradeOldDB( 390 temp_dir_.path(), base::Bind(&util::CanonicalizeResourceId))); 391 storage_.reset(new ResourceMetadataStorage( 392 temp_dir_.path(), base::MessageLoopProxy::current().get())); 393 ASSERT_TRUE(storage_->Initialize()); 394 395 // Resource-ID-to-local-ID mapping is added. 396 std::string id; 397 EXPECT_TRUE(storage_->GetIdByResourceId("abcd", &id)); // "file:" is dropped. 398 399 // Data is erased, except cache entries. 400 EXPECT_EQ(0, storage_->GetLargestChangestamp()); 401 EXPECT_FALSE(storage_->GetEntry(id, &entry)); 402 EXPECT_TRUE(storage_->GetCacheEntry(id, &cache_entry)); 403 } 404 405 TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M32) { 406 const int64 kLargestChangestamp = 1234567890; 407 const std::string resource_id = "abcd"; 408 const std::string local_id = "local-abcd"; 409 410 // Construct M32 version DB. 411 SetDBVersion(11); 412 EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp)); 413 414 leveldb::WriteBatch batch; 415 416 // Put a file entry and its cache and id entry. 417 ResourceEntry entry; 418 std::string serialized_entry; 419 entry.set_resource_id(resource_id); 420 EXPECT_TRUE(entry.SerializeToString(&serialized_entry)); 421 batch.Put(local_id, serialized_entry); 422 423 FileCacheEntry cache_entry; 424 EXPECT_TRUE(cache_entry.SerializeToString(&serialized_entry)); 425 batch.Put(local_id + '\0' + "CACHE", serialized_entry); 426 427 batch.Put('\0' + std::string("ID") + '\0' + resource_id, local_id); 428 429 EXPECT_TRUE(resource_map()->Write(leveldb::WriteOptions(), &batch).ok()); 430 431 // Upgrade and reopen. 432 storage_.reset(); 433 EXPECT_TRUE(ResourceMetadataStorage::UpgradeOldDB( 434 temp_dir_.path(), base::Bind(&util::CanonicalizeResourceId))); 435 storage_.reset(new ResourceMetadataStorage( 436 temp_dir_.path(), base::MessageLoopProxy::current().get())); 437 ASSERT_TRUE(storage_->Initialize()); 438 439 // Data is erased, except cache and id mapping entries. 440 std::string id; 441 EXPECT_TRUE(storage_->GetIdByResourceId(resource_id, &id)); 442 EXPECT_EQ(local_id, id); 443 EXPECT_EQ(0, storage_->GetLargestChangestamp()); 444 EXPECT_FALSE(storage_->GetEntry(id, &entry)); 445 EXPECT_TRUE(storage_->GetCacheEntry(id, &cache_entry)); 446 } 447 448 TEST_F(ResourceMetadataStorageTest, IncompatibleDB_Unknown) { 449 const int64 kLargestChangestamp = 1234567890; 450 const std::string key1 = "abcd"; 451 452 // Put some data. 453 EXPECT_TRUE(storage_->SetLargestChangestamp(kLargestChangestamp)); 454 ResourceEntry entry; 455 entry.set_local_id(key1); 456 EXPECT_TRUE(storage_->PutEntry(entry)); 457 FileCacheEntry cache_entry; 458 EXPECT_TRUE(storage_->PutCacheEntry(key1, cache_entry)); 459 460 // Set newer version, upgrade and reopen DB. 461 SetDBVersion(ResourceMetadataStorage::kDBVersion + 1); 462 storage_.reset(); 463 EXPECT_FALSE(ResourceMetadataStorage::UpgradeOldDB( 464 temp_dir_.path(), base::Bind(&util::CanonicalizeResourceId))); 465 storage_.reset(new ResourceMetadataStorage( 466 temp_dir_.path(), base::MessageLoopProxy::current().get())); 467 ASSERT_TRUE(storage_->Initialize()); 468 469 // Data is erased because of the incompatible version. 470 EXPECT_EQ(0, storage_->GetLargestChangestamp()); 471 EXPECT_FALSE(storage_->GetEntry(key1, &entry)); 472 EXPECT_FALSE(storage_->GetCacheEntry(key1, &cache_entry)); 473 } 474 475 TEST_F(ResourceMetadataStorageTest, WrongPath) { 476 // Create a file. 477 base::FilePath path; 478 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path)); 479 480 storage_.reset(new ResourceMetadataStorage( 481 path, base::MessageLoopProxy::current().get())); 482 // Cannot initialize DB beacause the path does not point a directory. 483 ASSERT_FALSE(storage_->Initialize()); 484 } 485 486 TEST_F(ResourceMetadataStorageTest, RecoverCacheEntriesFromTrashedResourceMap) { 487 // Put some cache entries. 488 FileCacheEntry cache_entry; 489 cache_entry.set_md5("md5_foo"); 490 EXPECT_TRUE(storage_->PutCacheEntry("id_foo", cache_entry)); 491 cache_entry.set_md5("md5_bar"); 492 cache_entry.set_is_dirty(true); 493 EXPECT_TRUE(storage_->PutCacheEntry("id_bar", cache_entry)); 494 495 // Put entry with id_foo. 496 ResourceEntry entry; 497 entry.set_local_id("id_foo"); 498 entry.set_base_name("foo"); 499 entry.set_title("foo"); 500 EXPECT_TRUE(storage_->PutEntry(entry)); 501 502 // Put entry with id_bar as a id_foo's child. 503 entry.set_local_id("id_bar"); 504 entry.set_parent_local_id("id_foo"); 505 entry.set_base_name("bar"); 506 entry.set_title("bar"); 507 EXPECT_TRUE(storage_->PutEntry(entry)); 508 509 // Remove parent-child relationship to make the DB invalid. 510 RemoveChild("id_foo", "bar"); 511 EXPECT_FALSE(CheckValidity()); 512 513 // Reopen. This should result in trashing the DB. 514 storage_.reset(new ResourceMetadataStorage( 515 temp_dir_.path(), base::MessageLoopProxy::current().get())); 516 ASSERT_TRUE(storage_->Initialize()); 517 518 // Recover cache entries from the trashed DB. 519 ResourceMetadataStorage::RecoveredCacheInfoMap recovered_cache_info; 520 storage_->RecoverCacheInfoFromTrashedResourceMap(&recovered_cache_info); 521 EXPECT_EQ(2U, recovered_cache_info.size()); 522 EXPECT_FALSE(recovered_cache_info["id_foo"].is_dirty); 523 EXPECT_EQ("md5_foo", recovered_cache_info["id_foo"].md5); 524 EXPECT_EQ("foo", recovered_cache_info["id_foo"].title); 525 EXPECT_TRUE(recovered_cache_info["id_bar"].is_dirty); 526 EXPECT_EQ("md5_bar", recovered_cache_info["id_bar"].md5); 527 EXPECT_EQ("bar", recovered_cache_info["id_bar"].title); 528 } 529 530 TEST_F(ResourceMetadataStorageTest, CheckValidity) { 531 const std::string key1 = "foo"; 532 const std::string name1 = "hoge"; 533 const std::string key2 = "bar"; 534 const std::string name2 = "fuga"; 535 const std::string key3 = "boo"; 536 const std::string name3 = "piyo"; 537 538 // Empty storage is valid. 539 EXPECT_TRUE(CheckValidity()); 540 541 // Put entry with key1. 542 ResourceEntry entry; 543 entry.set_local_id(key1); 544 entry.set_base_name(name1); 545 EXPECT_TRUE(storage_->PutEntry(entry)); 546 EXPECT_TRUE(CheckValidity()); 547 548 // Put entry with key2 under key1. 549 entry.set_local_id(key2); 550 entry.set_parent_local_id(key1); 551 entry.set_base_name(name2); 552 EXPECT_TRUE(storage_->PutEntry(entry)); 553 EXPECT_TRUE(CheckValidity()); 554 555 RemoveChild(key1, name2); 556 EXPECT_FALSE(CheckValidity()); // Missing parent-child relationship. 557 558 // Add back parent-child relationship between key1 and key2. 559 PutChild(key1, name2, key2); 560 EXPECT_TRUE(CheckValidity()); 561 562 // Add parent-child relationship between key2 and key3. 563 PutChild(key2, name3, key3); 564 EXPECT_FALSE(CheckValidity()); // key3 is not stored in the storage. 565 566 // Put entry with key3 under key2. 567 entry.set_local_id(key3); 568 entry.set_parent_local_id(key2); 569 entry.set_base_name(name3); 570 EXPECT_TRUE(storage_->PutEntry(entry)); 571 EXPECT_TRUE(CheckValidity()); 572 573 // Parent-child relationship with wrong name. 574 RemoveChild(key2, name3); 575 EXPECT_FALSE(CheckValidity()); 576 PutChild(key2, name2, key3); 577 EXPECT_FALSE(CheckValidity()); 578 579 // Fix up the relationship between key2 and key3. 580 RemoveChild(key2, name2); 581 EXPECT_FALSE(CheckValidity()); 582 PutChild(key2, name3, key3); 583 EXPECT_TRUE(CheckValidity()); 584 585 // Add some cache entries. 586 FileCacheEntry cache_entry; 587 EXPECT_TRUE(storage_->PutCacheEntry(key1, cache_entry)); 588 EXPECT_TRUE(storage_->PutCacheEntry(key2, cache_entry)); 589 590 // Remove key2. 591 RemoveChild(key1, name2); 592 EXPECT_FALSE(CheckValidity()); 593 EXPECT_TRUE(storage_->RemoveEntry(key2)); 594 EXPECT_FALSE(CheckValidity()); 595 596 // Remove key3. 597 RemoveChild(key2, name3); 598 EXPECT_FALSE(CheckValidity()); 599 EXPECT_TRUE(storage_->RemoveEntry(key3)); 600 EXPECT_TRUE(CheckValidity()); 601 602 // Remove key1. 603 EXPECT_TRUE(storage_->RemoveEntry(key1)); 604 EXPECT_TRUE(CheckValidity()); 605 } 606 607 } // namespace internal 608 } // namespace drive 609