Home | History | Annotate | Download | only in drive_backend
      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/sync_file_system/drive_backend/metadata_database.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/files/scoped_temp_dir.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/message_loop/message_loop_proxy.h"
     11 #include "base/strings/string_number_conversions.h"
     12 #include "chrome/browser/google_apis/drive_api_parser.h"
     13 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "third_party/leveldatabase/src/include/leveldb/db.h"
     16 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
     17 
     18 #define FPL(a) FILE_PATH_LITERAL(a)
     19 
     20 namespace sync_file_system {
     21 namespace drive_backend {
     22 
     23 namespace {
     24 
     25 const int64 kInitialChangeID = 1234;
     26 const int64 kSyncRootTrackerID = 100;
     27 const char kSyncRootFolderID[] = "sync_root_folder_id";
     28 
     29 void ExpectEquivalent(const ServiceMetadata* left,
     30                       const ServiceMetadata* right) {
     31   if (!left) {
     32     ASSERT_FALSE(right);
     33     return;
     34   }
     35   ASSERT_TRUE(right);
     36 
     37   EXPECT_EQ(left->largest_change_id(), right->largest_change_id());
     38   EXPECT_EQ(left->sync_root_tracker_id(), right->sync_root_tracker_id());
     39   EXPECT_EQ(left->next_tracker_id(), right->next_tracker_id());
     40 }
     41 
     42 void ExpectEquivalent(const FileDetails* left, const FileDetails* right) {
     43   if (!left) {
     44     ASSERT_FALSE(right);
     45     return;
     46   }
     47   ASSERT_TRUE(right);
     48 
     49   std::set<std::string> parents;
     50   for (int i = 0; i < left->parent_folder_ids_size(); ++i)
     51     EXPECT_TRUE(parents.insert(left->parent_folder_ids(i)).second);
     52 
     53   for (int i = 0; i < right->parent_folder_ids_size(); ++i)
     54     EXPECT_EQ(1u, parents.erase(left->parent_folder_ids(i)));
     55   EXPECT_TRUE(parents.empty());
     56 
     57   EXPECT_EQ(left->title(), right->title());
     58   EXPECT_EQ(left->file_kind(), right->file_kind());
     59   EXPECT_EQ(left->md5(), right->md5());
     60   EXPECT_EQ(left->etag(), right->etag());
     61   EXPECT_EQ(left->creation_time(), right->creation_time());
     62   EXPECT_EQ(left->modification_time(), right->modification_time());
     63   EXPECT_EQ(left->deleted(), right->deleted());
     64   EXPECT_EQ(left->change_id(), right->change_id());
     65 }
     66 
     67 void ExpectEquivalent(const FileMetadata* left, const FileMetadata* right) {
     68   if (!left) {
     69     ASSERT_FALSE(right);
     70     return;
     71   }
     72   ASSERT_TRUE(right);
     73 
     74   EXPECT_EQ(left->file_id(), right->file_id());
     75   ExpectEquivalent(&left->details(), &right->details());
     76 }
     77 
     78 void ExpectEquivalent(const FileTracker* left, const FileTracker* right) {
     79   if (!left) {
     80     ASSERT_FALSE(right);
     81     return;
     82   }
     83   ASSERT_TRUE(right);
     84 
     85   EXPECT_EQ(left->tracker_id(), right->tracker_id());
     86   EXPECT_EQ(left->parent_tracker_id(), right->parent_tracker_id());
     87   EXPECT_EQ(left->file_id(), right->file_id());
     88   EXPECT_EQ(left->app_id(), right->app_id());
     89   EXPECT_EQ(left->is_app_root(), right->is_app_root());
     90   ExpectEquivalent(&left->synced_details(), &right->synced_details());
     91   EXPECT_EQ(left->dirty(), right->dirty());
     92   EXPECT_EQ(left->active(), right->active());
     93   EXPECT_EQ(left->needs_folder_listing(), right->needs_folder_listing());
     94 }
     95 
     96 template <typename Container>
     97 void ExpectEquivalentMaps(const Container& left, const Container& right);
     98 template <typename Key, typename Value, typename Compare>
     99 void ExpectEquivalent(const std::map<Key, Value, Compare>& left,
    100                       const std::map<Key, Value, Compare>& right) {
    101   ExpectEquivalentMaps(left, right);
    102 }
    103 
    104 template <typename Container>
    105 void ExpectEquivalentSets(const Container& left, const Container& right);
    106 template <typename Value, typename Compare>
    107 void ExpectEquivalent(const std::set<Value, Compare>& left,
    108                       const std::set<Value, Compare>& right) {
    109   return ExpectEquivalentSets(left, right);
    110 }
    111 
    112 void ExpectEquivalent(const TrackerSet& left,
    113                       const TrackerSet& right) {
    114   {
    115     SCOPED_TRACE("Expect equivalent active_tracker");
    116     ExpectEquivalent(left.active_tracker(), right.active_tracker());
    117   }
    118   ExpectEquivalent(left.tracker_set(), right.tracker_set());
    119 }
    120 
    121 template <typename Container>
    122 void ExpectEquivalentMaps(const Container& left, const Container& right) {
    123   ASSERT_EQ(left.size(), right.size());
    124 
    125   typedef typename Container::const_iterator const_iterator;
    126   const_iterator left_itr = left.begin();
    127   const_iterator right_itr = right.begin();
    128   while (left_itr != left.end()) {
    129     EXPECT_EQ(left_itr->first, right_itr->first);
    130     ExpectEquivalent(left_itr->second, right_itr->second);
    131     ++left_itr;
    132     ++right_itr;
    133   }
    134 }
    135 
    136 template <typename Container>
    137 void ExpectEquivalentSets(const Container& left, const Container& right) {
    138   ASSERT_EQ(left.size(), right.size());
    139 
    140   typedef typename Container::const_iterator const_iterator;
    141   const_iterator left_itr = left.begin();
    142   const_iterator right_itr = right.begin();
    143   while (left_itr != left.end()) {
    144     ExpectEquivalent(*left_itr, *right_itr);
    145     ++left_itr;
    146     ++right_itr;
    147   }
    148 }
    149 
    150 void SyncStatusResultCallback(SyncStatusCode* status_out,
    151                               SyncStatusCode status) {
    152   EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out);
    153   *status_out = status;
    154 }
    155 
    156 void DatabaseCreateResultCallback(SyncStatusCode* status_out,
    157                                   scoped_ptr<MetadataDatabase>* database_out,
    158                                   SyncStatusCode status,
    159                                   scoped_ptr<MetadataDatabase> database) {
    160   EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out);
    161   *status_out = status;
    162   *database_out = database.Pass();
    163 }
    164 
    165 }  // namespace
    166 
    167 class MetadataDatabaseTest : public testing::Test {
    168  public:
    169   MetadataDatabaseTest()
    170       : next_change_id_(kInitialChangeID + 1),
    171         next_tracker_id_(kSyncRootTrackerID + 1),
    172         next_file_id_number_(1),
    173         next_md5_sequence_number_(1) {}
    174 
    175   virtual ~MetadataDatabaseTest() {}
    176 
    177   virtual void SetUp() OVERRIDE {
    178     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
    179   }
    180 
    181   virtual void TearDown() OVERRIDE { DropDatabase(); }
    182 
    183  protected:
    184   std::string GenerateFileID() {
    185     return "file_id_" + base::Int64ToString(next_file_id_number_++);
    186   }
    187 
    188   int64 GetTrackerIDByFileID(const std::string& file_id) {
    189     TrackerSet trackers;
    190     if (metadata_database_->FindTrackersByFileID(file_id, &trackers)) {
    191       EXPECT_FALSE(trackers.empty());
    192       return (*trackers.begin())->tracker_id();
    193     }
    194     return 0;
    195   }
    196 
    197   SyncStatusCode InitializeMetadataDatabase() {
    198     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    199     MetadataDatabase::Create(base::MessageLoopProxy::current(),
    200                              database_dir_.path(),
    201                              base::Bind(&DatabaseCreateResultCallback,
    202                                         &status, &metadata_database_));
    203     message_loop_.RunUntilIdle();
    204     return status;
    205   }
    206 
    207   void DropDatabase() {
    208     metadata_database_.reset();
    209     message_loop_.RunUntilIdle();
    210   }
    211 
    212   MetadataDatabase* metadata_database() { return metadata_database_.get(); }
    213 
    214   leveldb::DB* db() {
    215     if (!metadata_database_)
    216       return NULL;
    217     return metadata_database_->db_.get();
    218   }
    219 
    220   scoped_ptr<leveldb::DB> InitializeLevelDB() {
    221     leveldb::DB* db = NULL;
    222     leveldb::Options options;
    223     options.create_if_missing = true;
    224     options.max_open_files = 64;  // Use minimum.
    225     leveldb::Status status =
    226         leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
    227     EXPECT_TRUE(status.ok());
    228 
    229     db->Put(leveldb::WriteOptions(), "VERSION", base::Int64ToString(3));
    230     SetUpServiceMetadata(db);
    231 
    232     return make_scoped_ptr(db);
    233   }
    234 
    235   void SetUpServiceMetadata(leveldb::DB* db) {
    236     ServiceMetadata service_metadata;
    237     service_metadata.set_largest_change_id(kInitialChangeID);
    238     service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
    239     service_metadata.set_next_tracker_id(next_tracker_id_);
    240     std::string value;
    241     ASSERT_TRUE(service_metadata.SerializeToString(&value));
    242     db->Put(leveldb::WriteOptions(), "SERVICE", value);
    243   }
    244 
    245   FileMetadata CreateSyncRootMetadata() {
    246     FileMetadata sync_root;
    247     sync_root.set_file_id(kSyncRootFolderID);
    248     FileDetails* details = sync_root.mutable_details();
    249     details->set_title("Chrome Syncable FileSystem");
    250     details->set_file_kind(FILE_KIND_FOLDER);
    251     return sync_root;
    252   }
    253 
    254   FileMetadata CreateFileMetadata(const FileMetadata& parent,
    255                                   const std::string& title) {
    256     FileMetadata file;
    257     file.set_file_id(GenerateFileID());
    258     FileDetails* details = file.mutable_details();
    259     details->add_parent_folder_ids(parent.file_id());
    260     details->set_title(title);
    261     details->set_file_kind(FILE_KIND_FILE);
    262     details->set_md5(
    263         "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
    264     return file;
    265   }
    266 
    267   FileMetadata CreateFolderMetadata(const FileMetadata& parent,
    268                                     const std::string& title) {
    269     FileMetadata folder;
    270     folder.set_file_id(GenerateFileID());
    271     FileDetails* details = folder.mutable_details();
    272     details->add_parent_folder_ids(parent.file_id());
    273     details->set_title(title);
    274     details->set_file_kind(FILE_KIND_FOLDER);
    275     return folder;
    276   }
    277 
    278   FileTracker CreateSyncRootTracker(const FileMetadata& sync_root) {
    279     FileTracker sync_root_tracker;
    280     sync_root_tracker.set_tracker_id(kSyncRootTrackerID);
    281     sync_root_tracker.set_parent_tracker_id(0);
    282     sync_root_tracker.set_file_id(sync_root.file_id());
    283     sync_root_tracker.set_dirty(false);
    284     sync_root_tracker.set_active(true);
    285     sync_root_tracker.set_needs_folder_listing(false);
    286     *sync_root_tracker.mutable_synced_details() = sync_root.details();
    287     return sync_root_tracker;
    288   }
    289 
    290   FileTracker CreateTracker(const FileTracker& parent_tracker,
    291                             const FileMetadata& file) {
    292     FileTracker tracker;
    293     tracker.set_tracker_id(next_tracker_id_++);
    294     tracker.set_parent_tracker_id(parent_tracker.tracker_id());
    295     tracker.set_file_id(file.file_id());
    296     tracker.set_app_id(parent_tracker.app_id());
    297     tracker.set_is_app_root(false);
    298     tracker.set_dirty(false);
    299     tracker.set_active(true);
    300     tracker.set_needs_folder_listing(false);
    301     *tracker.mutable_synced_details() = file.details();
    302     return tracker;
    303   }
    304 
    305   scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata(
    306       const FileMetadata& file) {
    307     scoped_ptr<google_apis::ChangeResource> change(
    308         new google_apis::ChangeResource);
    309     change->set_change_id(file.details().change_id());
    310     change->set_file_id(file.file_id());
    311     change->set_deleted(file.details().deleted());
    312     if (change->is_deleted())
    313       return change.Pass();
    314 
    315     scoped_ptr<google_apis::FileResource> file_resource(
    316         new google_apis::FileResource);
    317     ScopedVector<google_apis::ParentReference> parents;
    318     for (int i = 0; i < file.details().parent_folder_ids_size(); ++i) {
    319       scoped_ptr<google_apis::ParentReference> parent(
    320           new google_apis::ParentReference);
    321       parent->set_file_id(file.details().parent_folder_ids(i));
    322       parents.push_back(parent.release());
    323     }
    324 
    325     file_resource->set_file_id(file.file_id());
    326     file_resource->set_parents(&parents);
    327     file_resource->set_title(file.details().title());
    328     if (file.details().file_kind() == FILE_KIND_FOLDER)
    329       file_resource->set_mime_type("application/vnd.google-apps.folder");
    330     else if (file.details().file_kind() == FILE_KIND_FILE)
    331       file_resource->set_mime_type("text/plain");
    332     else
    333       file_resource->set_mime_type("application/vnd.google-apps.document");
    334     file_resource->set_md5_checksum(file.details().md5());
    335     file_resource->set_etag(file.details().etag());
    336     file_resource->set_created_date(base::Time::FromInternalValue(
    337         file.details().creation_time()));
    338     file_resource->set_modified_date(base::Time::FromInternalValue(
    339         file.details().modification_time()));
    340 
    341     change->set_file(file_resource.Pass());
    342     return change.Pass();
    343   }
    344 
    345   void ApplyRenameChangeToMetadata(const std::string& new_title,
    346                                    FileMetadata* file) {
    347     FileDetails* details = file->mutable_details();
    348     details->set_title(new_title);
    349     details->set_change_id(next_change_id_++);
    350   }
    351 
    352   void ApplyReorganizeChangeToMetadata(const std::string& new_parent,
    353                                        FileMetadata* file) {
    354     FileDetails* details = file->mutable_details();
    355     details->clear_parent_folder_ids();
    356     details->add_parent_folder_ids(new_parent);
    357     details->set_change_id(next_change_id_++);
    358   }
    359 
    360   void ApplyContentChangeToMetadata(FileMetadata* file) {
    361     FileDetails* details = file->mutable_details();
    362     details->set_md5(
    363         "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
    364     details->set_change_id(next_change_id_++);
    365   }
    366 
    367   void PushToChangeList(scoped_ptr<google_apis::ChangeResource> change,
    368                         ScopedVector<google_apis::ChangeResource>* changes) {
    369     changes->push_back(change.release());
    370   }
    371 
    372   leveldb::Status PutFileToDB(leveldb::DB* db, const FileMetadata& file) {
    373     std::string key = "FILE: " + file.file_id();
    374     std::string value;
    375     file.SerializeToString(&value);
    376     return db->Put(leveldb::WriteOptions(), key, value);
    377   }
    378 
    379   leveldb::Status PutTrackerToDB(leveldb::DB* db,
    380                                  const FileTracker& tracker) {
    381     std::string key = "TRACKER: " + base::Int64ToString(tracker.tracker_id());
    382     std::string value;
    383     tracker.SerializeToString(&value);
    384     return db->Put(leveldb::WriteOptions(), key, value);
    385   }
    386 
    387   void VerifyReloadConsistency() {
    388     scoped_ptr<MetadataDatabase> metadata_database_2;
    389     ASSERT_EQ(SYNC_STATUS_OK,
    390               MetadataDatabase::CreateForTesting(
    391                   metadata_database_->db_.Pass(),
    392                   &metadata_database_2));
    393     metadata_database_->db_ = metadata_database_2->db_.Pass();
    394 
    395     {
    396       SCOPED_TRACE("Expect equivalent service_metadata");
    397       ExpectEquivalent(metadata_database_->service_metadata_.get(),
    398                        metadata_database_2->service_metadata_.get());
    399     }
    400 
    401     {
    402       SCOPED_TRACE("Expect equivalent file_by_id_ contents.");
    403       ExpectEquivalent(metadata_database_->file_by_id_,
    404                        metadata_database_2->file_by_id_);
    405     }
    406 
    407     {
    408       SCOPED_TRACE("Expect equivalent tracker_by_id_ contents.");
    409       ExpectEquivalent(metadata_database_->tracker_by_id_,
    410                        metadata_database_2->tracker_by_id_);
    411     }
    412 
    413     {
    414       SCOPED_TRACE("Expect equivalent trackers_by_file_id_ contents.");
    415       ExpectEquivalent(metadata_database_->trackers_by_file_id_,
    416                        metadata_database_2->trackers_by_file_id_);
    417     }
    418 
    419     {
    420       SCOPED_TRACE("Expect equivalent app_root_by_app_id_ contents.");
    421       ExpectEquivalent(metadata_database_->app_root_by_app_id_,
    422                        metadata_database_2->app_root_by_app_id_);
    423     }
    424 
    425     {
    426       SCOPED_TRACE("Expect equivalent trackers_by_parent_and_title_ contents.");
    427       ExpectEquivalent(metadata_database_->trackers_by_parent_and_title_,
    428                        metadata_database_2->trackers_by_parent_and_title_);
    429     }
    430 
    431     {
    432       SCOPED_TRACE("Expect equivalent dirty_trackers_ contents.");
    433       ExpectEquivalent(metadata_database_->dirty_trackers_,
    434                        metadata_database_2->dirty_trackers_);
    435     }
    436   }
    437 
    438   void VerifyFile(const FileMetadata& file) {
    439     FileMetadata file_in_metadata_database;
    440     ASSERT_TRUE(metadata_database()->FindFileByFileID(
    441         file.file_id(), &file_in_metadata_database));
    442 
    443     SCOPED_TRACE("Expect equivalent " + file.file_id());
    444     ExpectEquivalent(&file, &file_in_metadata_database);
    445   }
    446 
    447   void VerifyTracker(const FileTracker& tracker) {
    448     FileTracker tracker_in_metadata_database;
    449     ASSERT_TRUE(metadata_database()->FindTrackerByTrackerID(
    450         tracker.tracker_id(), &tracker_in_metadata_database));
    451 
    452     SCOPED_TRACE("Expect equivalent tracker[" +
    453                  base::Int64ToString(tracker.tracker_id()) + "]");
    454     ExpectEquivalent(&tracker, &tracker_in_metadata_database);
    455   }
    456 
    457   SyncStatusCode RegisterApp(const std::string& app_id,
    458                              const std::string& folder_id) {
    459     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    460     metadata_database_->RegisterApp(
    461         app_id, folder_id,
    462         base::Bind(&SyncStatusResultCallback, &status));
    463     message_loop_.RunUntilIdle();
    464     return status;
    465   }
    466 
    467   SyncStatusCode DisableApp(const std::string& app_id) {
    468     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    469     metadata_database_->DisableApp(
    470         app_id, base::Bind(&SyncStatusResultCallback, &status));
    471     message_loop_.RunUntilIdle();
    472     return status;
    473   }
    474 
    475   SyncStatusCode EnableApp(const std::string& app_id) {
    476     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    477     metadata_database_->EnableApp(
    478         app_id, base::Bind(&SyncStatusResultCallback, &status));
    479     message_loop_.RunUntilIdle();
    480     return status;
    481   }
    482 
    483   SyncStatusCode UnregisterApp(const std::string& app_id) {
    484     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    485     metadata_database_->UnregisterApp(
    486         app_id, base::Bind(&SyncStatusResultCallback, &status));
    487     message_loop_.RunUntilIdle();
    488     return status;
    489   }
    490 
    491   SyncStatusCode UpdateByChangeList(
    492       ScopedVector<google_apis::ChangeResource> changes) {
    493     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    494     metadata_database_->UpdateByChangeList(
    495         changes.Pass(), base::Bind(&SyncStatusResultCallback, &status));
    496     message_loop_.RunUntilIdle();
    497     return status;
    498   }
    499 
    500  private:
    501   base::ScopedTempDir database_dir_;
    502   base::MessageLoop message_loop_;
    503 
    504   scoped_ptr<MetadataDatabase> metadata_database_;
    505 
    506   int64 next_change_id_;
    507   int64 next_tracker_id_;
    508   int64 next_file_id_number_;
    509   int64 next_md5_sequence_number_;
    510 
    511   DISALLOW_COPY_AND_ASSIGN(MetadataDatabaseTest);
    512 };
    513 
    514 TEST_F(MetadataDatabaseTest, InitializationTest_Empty) {
    515   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    516   DropDatabase();
    517   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    518 }
    519 
    520 TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) {
    521   FileMetadata sync_root(CreateSyncRootMetadata());
    522   FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
    523 
    524   FileMetadata app_root(
    525       CreateFolderMetadata(sync_root, "app_id" /* title */));
    526   FileTracker app_root_tracker(
    527       CreateTracker(sync_root_tracker, app_root));
    528   app_root_tracker.set_app_id(app_root.details().title());
    529   app_root_tracker.set_is_app_root(true);
    530 
    531   FileMetadata file(CreateFileMetadata(app_root, "file"));
    532   FileTracker file_tracker(CreateTracker(app_root_tracker, file));
    533 
    534   FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
    535   FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
    536 
    537   FileMetadata file_in_folder(
    538       CreateFileMetadata(folder, "file_in_folder"));
    539   FileTracker file_in_folder_tracker(
    540       CreateTracker(folder_tracker, file_in_folder));
    541 
    542   FileMetadata orphaned_file(
    543       CreateFileMetadata(sync_root, "orphaned_file"));
    544   orphaned_file.mutable_details()->clear_parent_folder_ids();
    545   FileTracker orphaned_file_tracker(
    546       CreateTracker(sync_root_tracker, orphaned_file));
    547   orphaned_file_tracker.set_parent_tracker_id(0);
    548 
    549   {
    550     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
    551     ASSERT_TRUE(db);
    552 
    553     EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
    554     EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
    555     EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
    556     EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
    557     EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
    558     EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
    559     EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
    560     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
    561     EXPECT_TRUE(PutFileToDB(db.get(), file_in_folder).ok());
    562     EXPECT_TRUE(PutTrackerToDB(db.get(), file_in_folder_tracker).ok());
    563     EXPECT_TRUE(PutFileToDB(db.get(), orphaned_file).ok());
    564     EXPECT_TRUE(PutTrackerToDB(db.get(), orphaned_file_tracker).ok());
    565   }
    566 
    567   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    568 
    569   VerifyFile(sync_root);
    570   VerifyTracker(sync_root_tracker);
    571   VerifyFile(app_root);
    572   VerifyTracker(app_root_tracker);
    573   VerifyFile(file);
    574   VerifyTracker(file_tracker);
    575   VerifyFile(folder);
    576   VerifyTracker(folder_tracker);
    577   VerifyFile(file_in_folder);
    578   VerifyTracker(file_in_folder_tracker);
    579 
    580   EXPECT_FALSE(metadata_database()->FindFileByFileID(
    581       orphaned_file.file_id(), NULL));
    582   EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
    583       orphaned_file_tracker.tracker_id(), NULL));
    584 }
    585 
    586 TEST_F(MetadataDatabaseTest, AppManagementTest) {
    587   FileMetadata sync_root(CreateSyncRootMetadata());
    588   FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
    589 
    590   FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
    591   FileTracker app_root_tracker(
    592       CreateTracker(sync_root_tracker, app_root));
    593   app_root_tracker.set_app_id(app_root.details().title());
    594   app_root_tracker.set_is_app_root(true);
    595 
    596   FileMetadata file(CreateFileMetadata(app_root, "file"));
    597   FileTracker file_tracker(CreateTracker(app_root_tracker, file));
    598 
    599   FileMetadata folder(CreateFolderMetadata(sync_root, "folder"));
    600   FileTracker folder_tracker(CreateTracker(sync_root_tracker, folder));
    601   folder_tracker.set_active(false);
    602 
    603   {
    604     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
    605     ASSERT_TRUE(db);
    606 
    607     EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
    608     EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
    609     EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
    610     EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
    611     EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
    612     EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
    613     EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
    614     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
    615   }
    616 
    617   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    618   VerifyFile(sync_root);
    619   VerifyTracker(sync_root_tracker);
    620   VerifyFile(app_root);
    621   VerifyTracker(app_root_tracker);
    622   VerifyFile(file);
    623   VerifyTracker(file_tracker);
    624   VerifyFile(folder);
    625   VerifyTracker(folder_tracker);
    626 
    627   folder_tracker.set_app_id("foo");
    628   folder_tracker.set_is_app_root(true);
    629   folder_tracker.set_active(true);
    630   folder_tracker.set_dirty(true);
    631   folder_tracker.set_needs_folder_listing(true);
    632   EXPECT_EQ(SYNC_STATUS_OK, RegisterApp(
    633       folder_tracker.app_id(), folder.file_id()));
    634   VerifyFile(folder);
    635   VerifyTracker(folder_tracker);
    636   VerifyReloadConsistency();
    637 
    638   EXPECT_EQ(SYNC_STATUS_OK, DisableApp(folder_tracker.app_id()));
    639   folder_tracker.set_active(false);
    640   VerifyFile(folder);
    641   VerifyTracker(folder_tracker);
    642   VerifyReloadConsistency();
    643 
    644   EXPECT_EQ(SYNC_STATUS_OK, EnableApp(folder_tracker.app_id()));
    645   folder_tracker.set_active(true);
    646   VerifyFile(folder);
    647   VerifyTracker(folder_tracker);
    648   VerifyReloadConsistency();
    649 
    650   EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(folder_tracker.app_id()));
    651   folder_tracker.set_app_id(std::string());
    652   folder_tracker.set_is_app_root(false);
    653   folder_tracker.set_active(false);
    654   VerifyFile(folder);
    655   VerifyTracker(folder_tracker);
    656   VerifyReloadConsistency();
    657 
    658   EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(app_root_tracker.app_id()));
    659   app_root_tracker.set_app_id(std::string());
    660   app_root_tracker.set_is_app_root(false);
    661   app_root_tracker.set_active(false);
    662   app_root_tracker.set_dirty(true);
    663   VerifyFile(app_root);
    664   VerifyTracker(app_root_tracker);
    665   EXPECT_FALSE(metadata_database()->FindFileByFileID(file.file_id(), NULL));
    666   EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
    667       file_tracker.tracker_id(), NULL));
    668   VerifyReloadConsistency();
    669 }
    670 
    671 TEST_F(MetadataDatabaseTest, BuildPathTest) {
    672   FileMetadata sync_root(CreateSyncRootMetadata());
    673   FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
    674 
    675   FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
    676   FileTracker app_root_tracker(
    677       CreateTracker(sync_root_tracker, app_root));
    678   app_root_tracker.set_app_id(app_root.details().title());
    679   app_root_tracker.set_is_app_root(true);
    680 
    681   FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
    682   FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
    683 
    684   FileMetadata file(CreateFolderMetadata(folder, "file"));
    685   FileTracker file_tracker(CreateTracker(folder_tracker, file));
    686 
    687   FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder"));
    688   FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker,
    689                                                           inactive_folder));
    690   inactive_folder_tracker.set_active(false);
    691 
    692   {
    693     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
    694     ASSERT_TRUE(db);
    695 
    696     EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
    697     EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
    698     EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
    699     EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
    700     EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
    701     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
    702     EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
    703     EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
    704   }
    705 
    706   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    707 
    708   base::FilePath path;
    709   EXPECT_FALSE(metadata_database()->BuildPathForTracker(
    710       sync_root_tracker.tracker_id(), &path));
    711   EXPECT_TRUE(metadata_database()->BuildPathForTracker(
    712       app_root_tracker.tracker_id(), &path));
    713   EXPECT_EQ(base::FilePath(FPL("/")).NormalizePathSeparators(), path);
    714   EXPECT_TRUE(metadata_database()->BuildPathForTracker(
    715       file_tracker.tracker_id(), &path));
    716   EXPECT_EQ(base::FilePath(FPL("/folder/file")).NormalizePathSeparators(),
    717             path);
    718 }
    719 
    720 TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) {
    721   FileMetadata sync_root(CreateSyncRootMetadata());
    722   FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
    723 
    724   FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
    725   FileTracker app_root_tracker(
    726       CreateTracker(sync_root_tracker, app_root));
    727 
    728   FileMetadata disabled_app_root(
    729       CreateFolderMetadata(sync_root, "disabled_app"));
    730   FileTracker disabled_app_root_tracker(
    731       CreateTracker(sync_root_tracker, disabled_app_root));
    732 
    733   FileMetadata file(CreateFileMetadata(app_root, "file"));
    734   FileTracker file_tracker(CreateTracker(app_root_tracker, file));
    735 
    736   FileMetadata renamed_file(CreateFileMetadata(app_root, "to be renamed"));
    737   FileTracker renamed_file_tracker(
    738       CreateTracker(app_root_tracker, renamed_file));
    739 
    740   FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
    741   FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
    742 
    743   FileMetadata reorganized_file(
    744       CreateFileMetadata(app_root, "to be reorganized"));
    745   FileTracker reorganized_file_tracker(
    746       CreateTracker(app_root_tracker, reorganized_file));
    747 
    748   FileMetadata updated_file(CreateFileMetadata(app_root, "to be updated"));
    749   FileTracker updated_file_tracker(
    750       CreateTracker(app_root_tracker, updated_file));
    751 
    752   FileMetadata noop_file(CreateFileMetadata(app_root, "have noop change"));
    753   FileTracker noop_file_tracker(
    754       CreateTracker(app_root_tracker, noop_file));
    755 
    756   FileMetadata new_file(CreateFileMetadata(app_root, "to be added later"));
    757 
    758   {
    759     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
    760     ASSERT_TRUE(db);
    761 
    762     EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
    763     EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
    764     EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
    765     EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
    766     EXPECT_TRUE(PutFileToDB(db.get(), disabled_app_root).ok());
    767     EXPECT_TRUE(PutTrackerToDB(db.get(), disabled_app_root_tracker).ok());
    768     EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
    769     EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
    770     EXPECT_TRUE(PutFileToDB(db.get(), renamed_file).ok());
    771     EXPECT_TRUE(PutTrackerToDB(db.get(), renamed_file_tracker).ok());
    772     EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
    773     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
    774     EXPECT_TRUE(PutFileToDB(db.get(), reorganized_file).ok());
    775     EXPECT_TRUE(PutTrackerToDB(db.get(), reorganized_file_tracker).ok());
    776     EXPECT_TRUE(PutFileToDB(db.get(), updated_file).ok());
    777     EXPECT_TRUE(PutTrackerToDB(db.get(), updated_file_tracker).ok());
    778     EXPECT_TRUE(PutFileToDB(db.get(), noop_file).ok());
    779     EXPECT_TRUE(PutTrackerToDB(db.get(), noop_file_tracker).ok());
    780   }
    781 
    782   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    783 
    784   ApplyRenameChangeToMetadata("renamed", &renamed_file);
    785   ApplyReorganizeChangeToMetadata(folder.file_id(), &reorganized_file);
    786   ApplyContentChangeToMetadata(&updated_file);
    787 
    788   ScopedVector<google_apis::ChangeResource> changes;
    789   PushToChangeList(CreateChangeResourceFromMetadata(renamed_file), &changes);
    790   PushToChangeList(CreateChangeResourceFromMetadata(
    791       reorganized_file), &changes);
    792   PushToChangeList(CreateChangeResourceFromMetadata(updated_file), &changes);
    793   PushToChangeList(CreateChangeResourceFromMetadata(noop_file), &changes);
    794   PushToChangeList(CreateChangeResourceFromMetadata(new_file), &changes);
    795 
    796   renamed_file_tracker.set_dirty(true);
    797   reorganized_file_tracker.set_dirty(true);
    798   updated_file_tracker.set_dirty(true);
    799   noop_file_tracker.set_dirty(true);
    800 
    801   EXPECT_EQ(SYNC_STATUS_OK, UpdateByChangeList(changes.Pass()));
    802 
    803   FileTracker new_file_tracker(CreateTracker(app_root_tracker, new_file));
    804   new_file_tracker.set_tracker_id(GetTrackerIDByFileID(new_file.file_id()));
    805   new_file_tracker.clear_synced_details();
    806   new_file_tracker.set_active(false);
    807   new_file_tracker.set_dirty(true);
    808   EXPECT_NE(0, new_file_tracker.tracker_id());
    809 
    810   VerifyFile(sync_root);
    811   VerifyTracker(sync_root_tracker);
    812   VerifyFile(app_root);
    813   VerifyTracker(app_root_tracker);
    814   VerifyFile(disabled_app_root);
    815   VerifyTracker(disabled_app_root_tracker);
    816   VerifyFile(file);
    817   VerifyTracker(file_tracker);
    818   VerifyFile(renamed_file);
    819   VerifyTracker(renamed_file_tracker);
    820   VerifyFile(folder);
    821   VerifyTracker(folder_tracker);
    822   VerifyFile(reorganized_file);
    823   VerifyTracker(reorganized_file_tracker);
    824   VerifyFile(updated_file);
    825   VerifyTracker(updated_file_tracker);
    826   VerifyFile(noop_file);
    827   VerifyTracker(noop_file_tracker);
    828   VerifyFile(new_file);
    829   VerifyTracker(new_file_tracker);
    830 
    831   VerifyReloadConsistency();
    832 }
    833 
    834 }  // namespace drive_backend
    835 }  // namespace sync_file_system
    836