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