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/sync_file_system/drive_backend/drive_backend_constants.h"
     13 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
     14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
     15 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
     16 #include "chrome/browser/sync_file_system/drive_backend/metadata_database_index.h"
     17 #include "chrome/browser/sync_file_system/drive_backend/metadata_database_index_interface.h"
     18 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
     19 #include "google_apis/drive/drive_api_parser.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
     22 #include "third_party/leveldatabase/src/include/leveldb/db.h"
     23 #include "third_party/leveldatabase/src/include/leveldb/env.h"
     24 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
     25 
     26 #define FPL(a) FILE_PATH_LITERAL(a)
     27 
     28 namespace sync_file_system {
     29 namespace drive_backend {
     30 
     31 namespace {
     32 
     33 typedef MetadataDatabase::FileIDList FileIDList;
     34 
     35 const int64 kInitialChangeID = 1234;
     36 const int64 kSyncRootTrackerID = 100;
     37 const char kSyncRootFolderID[] = "sync_root_folder_id";
     38 
     39 // This struct is used to setup initial state of the database in the test and
     40 // also used to match to the modified content of the database as the
     41 // expectation.
     42 struct TrackedFile {
     43   // Holds the latest remote metadata which may be not-yet-synced to |tracker|.
     44   FileMetadata metadata;
     45   FileTracker tracker;
     46 
     47   // Implies the file should not in the database.
     48   bool should_be_absent;
     49 
     50   // Implies the file should have a tracker in the database but should have no
     51   // metadata.
     52   bool tracker_only;
     53 
     54   TrackedFile() : should_be_absent(false), tracker_only(false) {}
     55 };
     56 
     57 void ExpectEquivalent(const ServiceMetadata* left,
     58                       const ServiceMetadata* right) {
     59   test_util::ExpectEquivalentServiceMetadata(*left, *right);
     60 }
     61 
     62 void ExpectEquivalent(const FileMetadata* left, const FileMetadata* right) {
     63   if (!left) {
     64     ASSERT_FALSE(right);
     65     return;
     66   }
     67   ASSERT_TRUE(right);
     68   test_util::ExpectEquivalentMetadata(*left, *right);
     69 }
     70 
     71 void ExpectEquivalent(const FileTracker* left, const FileTracker* right) {
     72   if (!left) {
     73     ASSERT_FALSE(right);
     74     return;
     75   }
     76   ASSERT_TRUE(right);
     77   test_util::ExpectEquivalentTrackers(*left, *right);
     78 }
     79 
     80 void ExpectEquivalent(int64 left, int64 right) {
     81   EXPECT_EQ(left, right);
     82 }
     83 
     84 template <typename Container>
     85 void ExpectEquivalentMaps(const Container& left, const Container& right);
     86 
     87 template <typename Key, typename Value>
     88 void ExpectEquivalent(const std::map<Key, Value>& left,
     89                       const std::map<Key, Value>& right) {
     90   ExpectEquivalentMaps(left, right);
     91 }
     92 
     93 template <typename Key, typename Value>
     94 void ExpectEquivalent(const base::hash_map<Key, Value>& left,
     95                       const base::hash_map<Key, Value>& right) {
     96   ExpectEquivalentMaps(std::map<Key, Value>(left.begin(), left.end()),
     97                        std::map<Key, Value>(right.begin(), right.end()));
     98 }
     99 
    100 template <typename Key, typename Value>
    101 void ExpectEquivalent(const base::ScopedPtrHashMap<Key, Value>& left,
    102                       const base::ScopedPtrHashMap<Key, Value>& right) {
    103   ExpectEquivalentMaps(std::map<Key, Value*>(left.begin(), left.end()),
    104                        std::map<Key, Value*>(right.begin(), right.end()));
    105 }
    106 
    107 template <typename Container>
    108 void ExpectEquivalentSets(const Container& left, const Container& right);
    109 
    110 template <typename Value, typename Comparator>
    111 void ExpectEquivalent(const std::set<Value, Comparator>& left,
    112                       const std::set<Value, Comparator>& right) {
    113   return ExpectEquivalentSets(left, right);
    114 }
    115 
    116 template <typename Value>
    117 void ExpectEquivalent(const base::hash_set<Value>& left,
    118                       const base::hash_set<Value>& right) {
    119   return ExpectEquivalentSets(std::set<Value>(left.begin(), left.end()),
    120                               std::set<Value>(right.begin(), right.end()));
    121 }
    122 
    123 void ExpectEquivalent(const TrackerIDSet& left,
    124                       const TrackerIDSet& right) {
    125   {
    126     SCOPED_TRACE("Expect equivalent active_tracker");
    127     EXPECT_EQ(left.active_tracker(), right.active_tracker());
    128   }
    129   ExpectEquivalent(left.tracker_set(), right.tracker_set());
    130 }
    131 
    132 template <typename Container>
    133 void ExpectEquivalentMaps(const Container& left, const Container& right) {
    134   ASSERT_EQ(left.size(), right.size());
    135 
    136   typedef typename Container::const_iterator const_iterator;
    137   const_iterator left_itr = left.begin();
    138   const_iterator right_itr = right.begin();
    139   while (left_itr != left.end()) {
    140     EXPECT_EQ(left_itr->first, right_itr->first);
    141     ExpectEquivalent(left_itr->second, right_itr->second);
    142     ++left_itr;
    143     ++right_itr;
    144   }
    145 }
    146 
    147 template <typename Container>
    148 void ExpectEquivalentSets(const Container& left, const Container& right) {
    149   ASSERT_EQ(left.size(), right.size());
    150 
    151   typedef typename Container::const_iterator const_iterator;
    152   const_iterator left_itr = left.begin();
    153   const_iterator right_itr = right.begin();
    154   while (left_itr != left.end()) {
    155     ExpectEquivalent(*left_itr, *right_itr);
    156     ++left_itr;
    157     ++right_itr;
    158   }
    159 }
    160 
    161 base::FilePath CreateNormalizedPath(const base::FilePath::StringType& path) {
    162   return base::FilePath(path).NormalizePathSeparators();
    163 }
    164 
    165 }  // namespace
    166 
    167 class MetadataDatabaseTest : public testing::Test {
    168  public:
    169   MetadataDatabaseTest()
    170       : current_change_id_(kInitialChangeID),
    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     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
    180   }
    181 
    182   virtual void TearDown() OVERRIDE { DropDatabase(); }
    183 
    184  protected:
    185   std::string GenerateFileID() {
    186     return "file_id_" + base::Int64ToString(next_file_id_number_++);
    187   }
    188 
    189   int64 GetTrackerIDByFileID(const std::string& file_id) {
    190     TrackerIDSet trackers;
    191     if (metadata_database_->FindTrackersByFileID(file_id, &trackers)) {
    192       EXPECT_FALSE(trackers.empty());
    193       return *trackers.begin();
    194     }
    195     return 0;
    196   }
    197 
    198   SyncStatusCode InitializeMetadataDatabase() {
    199     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    200     MetadataDatabase::Create(base::MessageLoopProxy::current(),
    201                              base::MessageLoopProxy::current(),
    202                              database_dir_.path(),
    203                              in_memory_env_.get(),
    204                              CreateResultReceiver(&status,
    205                                                   &metadata_database_));
    206     message_loop_.RunUntilIdle();
    207     return status;
    208   }
    209 
    210   void DropDatabase() {
    211     metadata_database_.reset();
    212     message_loop_.RunUntilIdle();
    213   }
    214 
    215   void SetUpDatabaseByTrackedFiles(const TrackedFile** tracked_files,
    216                                    int size) {
    217     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
    218     ASSERT_TRUE(db);
    219 
    220     for (int i = 0; i < size; ++i) {
    221       const TrackedFile* file = tracked_files[i];
    222       if (file->should_be_absent)
    223         continue;
    224       if (!file->tracker_only)
    225         EXPECT_TRUE(PutFileToDB(db.get(), file->metadata).ok());
    226       EXPECT_TRUE(PutTrackerToDB(db.get(), file->tracker).ok());
    227     }
    228   }
    229 
    230   void VerifyTrackedFile(const TrackedFile& file) {
    231     if (!file.should_be_absent) {
    232       if (file.tracker_only) {
    233         EXPECT_FALSE(metadata_database()->FindFileByFileID(
    234             file.metadata.file_id(), NULL));
    235       } else {
    236         VerifyFile(file.metadata);
    237       }
    238       VerifyTracker(file.tracker);
    239       return;
    240     }
    241 
    242     EXPECT_FALSE(metadata_database()->FindFileByFileID(
    243         file.metadata.file_id(), NULL));
    244     EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
    245         file.tracker.tracker_id(), NULL));
    246   }
    247 
    248   void VerifyTrackedFiles(const TrackedFile** tracked_files, int size) {
    249     for (int i = 0; i < size; ++i)
    250       VerifyTrackedFile(*tracked_files[i]);
    251   }
    252 
    253   MetadataDatabase* metadata_database() { return metadata_database_.get(); }
    254 
    255   scoped_ptr<leveldb::DB> InitializeLevelDB() {
    256     leveldb::DB* db = NULL;
    257     leveldb::Options options;
    258     options.create_if_missing = true;
    259     options.max_open_files = 0;  // Use minimum.
    260     options.env = in_memory_env_.get();
    261     leveldb::Status status =
    262         leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
    263     EXPECT_TRUE(status.ok());
    264 
    265     db->Put(leveldb::WriteOptions(),
    266             kDatabaseVersionKey,
    267             base::Int64ToString(3));
    268     SetUpServiceMetadata(db);
    269 
    270     return make_scoped_ptr(db);
    271   }
    272 
    273   void SetUpServiceMetadata(leveldb::DB* db) {
    274     ServiceMetadata service_metadata;
    275     service_metadata.set_largest_change_id(kInitialChangeID);
    276     service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
    277     service_metadata.set_next_tracker_id(next_tracker_id_);
    278     leveldb::WriteBatch batch;
    279     PutServiceMetadataToBatch(service_metadata, &batch);
    280     EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
    281   }
    282 
    283   FileMetadata CreateSyncRootMetadata() {
    284     FileMetadata sync_root;
    285     sync_root.set_file_id(kSyncRootFolderID);
    286     FileDetails* details = sync_root.mutable_details();
    287     details->set_title(kSyncRootFolderTitle);
    288     details->set_file_kind(FILE_KIND_FOLDER);
    289     details->set_change_id(current_change_id_);
    290     return sync_root;
    291   }
    292 
    293   FileMetadata CreateFileMetadata(const FileMetadata& parent,
    294                                   const std::string& title) {
    295     FileMetadata file;
    296     file.set_file_id(GenerateFileID());
    297     FileDetails* details = file.mutable_details();
    298     details->add_parent_folder_ids(parent.file_id());
    299     details->set_title(title);
    300     details->set_file_kind(FILE_KIND_FILE);
    301     details->set_md5(
    302         "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
    303     details->set_change_id(current_change_id_);
    304     return file;
    305   }
    306 
    307   FileMetadata CreateFolderMetadata(const FileMetadata& parent,
    308                                     const std::string& title) {
    309     FileMetadata folder;
    310     folder.set_file_id(GenerateFileID());
    311     FileDetails* details = folder.mutable_details();
    312     details->add_parent_folder_ids(parent.file_id());
    313     details->set_title(title);
    314     details->set_file_kind(FILE_KIND_FOLDER);
    315     details->set_change_id(current_change_id_);
    316     return folder;
    317   }
    318 
    319   FileTracker CreateSyncRootTracker(const FileMetadata& sync_root) {
    320     FileTracker sync_root_tracker;
    321     sync_root_tracker.set_tracker_id(kSyncRootTrackerID);
    322     sync_root_tracker.set_parent_tracker_id(0);
    323     sync_root_tracker.set_file_id(sync_root.file_id());
    324     sync_root_tracker.set_dirty(false);
    325     sync_root_tracker.set_active(true);
    326     sync_root_tracker.set_needs_folder_listing(false);
    327     *sync_root_tracker.mutable_synced_details() = sync_root.details();
    328     return sync_root_tracker;
    329   }
    330 
    331   FileTracker CreateTracker(const FileTracker& parent_tracker,
    332                             const FileMetadata& file) {
    333     FileTracker tracker;
    334     tracker.set_tracker_id(next_tracker_id_++);
    335     tracker.set_parent_tracker_id(parent_tracker.tracker_id());
    336     tracker.set_file_id(file.file_id());
    337     tracker.set_app_id(parent_tracker.app_id());
    338     tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
    339     tracker.set_dirty(false);
    340     tracker.set_active(true);
    341     tracker.set_needs_folder_listing(false);
    342     *tracker.mutable_synced_details() = file.details();
    343     return tracker;
    344   }
    345 
    346   TrackedFile CreateTrackedSyncRoot() {
    347     TrackedFile sync_root;
    348     sync_root.metadata = CreateSyncRootMetadata();
    349     sync_root.tracker = CreateSyncRootTracker(sync_root.metadata);
    350     return sync_root;
    351   }
    352 
    353   TrackedFile CreateTrackedAppRoot(const TrackedFile& sync_root,
    354                                    const std::string& app_id) {
    355     TrackedFile app_root(CreateTrackedFolder(sync_root, app_id));
    356     app_root.tracker.set_app_id(app_id);
    357     app_root.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
    358     return app_root;
    359   }
    360 
    361   TrackedFile CreateTrackedFile(const TrackedFile& parent,
    362                                 const std::string& title) {
    363     TrackedFile file;
    364     file.metadata = CreateFileMetadata(parent.metadata, title);
    365     file.tracker = CreateTracker(parent.tracker, file.metadata);
    366     return file;
    367   }
    368 
    369   TrackedFile CreateTrackedFolder(const TrackedFile& parent,
    370                                   const std::string& title) {
    371     TrackedFile folder;
    372     folder.metadata = CreateFolderMetadata(parent.metadata, title);
    373     folder.tracker = CreateTracker(parent.tracker, folder.metadata);
    374     return folder;
    375   }
    376 
    377   scoped_ptr<google_apis::FileResource> CreateFileResourceFromMetadata(
    378       const FileMetadata& file) {
    379     scoped_ptr<google_apis::FileResource> file_resource(
    380         new google_apis::FileResource);
    381     for (int i = 0; i < file.details().parent_folder_ids_size(); ++i) {
    382       google_apis::ParentReference parent;
    383       parent.set_file_id(file.details().parent_folder_ids(i));
    384       file_resource->mutable_parents()->push_back(parent);
    385     }
    386 
    387     file_resource->set_file_id(file.file_id());
    388     file_resource->set_title(file.details().title());
    389     if (file.details().file_kind() == FILE_KIND_FOLDER)
    390       file_resource->set_mime_type("application/vnd.google-apps.folder");
    391     else if (file.details().file_kind() == FILE_KIND_FILE)
    392       file_resource->set_mime_type("text/plain");
    393     else
    394       file_resource->set_mime_type("application/vnd.google-apps.document");
    395     file_resource->set_md5_checksum(file.details().md5());
    396     file_resource->set_etag(file.details().etag());
    397     file_resource->set_created_date(base::Time::FromInternalValue(
    398         file.details().creation_time()));
    399     file_resource->set_modified_date(base::Time::FromInternalValue(
    400         file.details().modification_time()));
    401 
    402     return file_resource.Pass();
    403   }
    404 
    405   scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata(
    406       const FileMetadata& file) {
    407     scoped_ptr<google_apis::ChangeResource> change(
    408         new google_apis::ChangeResource);
    409     change->set_change_id(file.details().change_id());
    410     change->set_file_id(file.file_id());
    411     change->set_deleted(file.details().missing());
    412     if (change->is_deleted())
    413       return change.Pass();
    414 
    415     change->set_file(CreateFileResourceFromMetadata(file));
    416     return change.Pass();
    417   }
    418 
    419   void ApplyRenameChangeToMetadata(const std::string& new_title,
    420                                    FileMetadata* file) {
    421     FileDetails* details = file->mutable_details();
    422     details->set_title(new_title);
    423     details->set_change_id(++current_change_id_);
    424   }
    425 
    426   void ApplyReorganizeChangeToMetadata(const std::string& new_parent,
    427                                        FileMetadata* file) {
    428     FileDetails* details = file->mutable_details();
    429     details->clear_parent_folder_ids();
    430     details->add_parent_folder_ids(new_parent);
    431     details->set_change_id(++current_change_id_);
    432   }
    433 
    434   void ApplyContentChangeToMetadata(FileMetadata* file) {
    435     FileDetails* details = file->mutable_details();
    436     details->set_md5(
    437         "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
    438     details->set_change_id(++current_change_id_);
    439   }
    440 
    441   void ApplyNoopChangeToMetadata(FileMetadata* file) {
    442     file->mutable_details()->set_change_id(++current_change_id_);
    443   }
    444 
    445   void PushToChangeList(scoped_ptr<google_apis::ChangeResource> change,
    446                         ScopedVector<google_apis::ChangeResource>* changes) {
    447     changes->push_back(change.release());
    448   }
    449 
    450   leveldb::Status PutFileToDB(leveldb::DB* db, const FileMetadata& file) {
    451     leveldb::WriteBatch batch;
    452     PutFileMetadataToBatch(file, &batch);
    453     return db->Write(leveldb::WriteOptions(), &batch);
    454   }
    455 
    456   leveldb::Status PutTrackerToDB(leveldb::DB* db,
    457                                  const FileTracker& tracker) {
    458     leveldb::WriteBatch batch;
    459     PutFileTrackerToBatch(tracker, &batch);
    460     return db->Write(leveldb::WriteOptions(), &batch);
    461   }
    462 
    463   void VerifyReloadConsistency() {
    464     scoped_ptr<MetadataDatabase> metadata_database_2;
    465     ASSERT_EQ(SYNC_STATUS_OK,
    466               MetadataDatabase::CreateForTesting(
    467                   metadata_database_->db_.Pass(),
    468                   &metadata_database_2));
    469     metadata_database_->db_ = metadata_database_2->db_.Pass();
    470 
    471     const MetadataDatabaseIndex* on_memory =
    472         static_cast<MetadataDatabaseIndex*>(metadata_database_->index_.get());
    473     const MetadataDatabaseIndex* reloaded =
    474         static_cast<MetadataDatabaseIndex*>(metadata_database_2->index_.get());
    475 
    476     {
    477       SCOPED_TRACE("Expect equivalent service_metadata");
    478       ExpectEquivalent(metadata_database_->service_metadata_.get(),
    479                        metadata_database_2->service_metadata_.get());
    480     }
    481 
    482     {
    483       SCOPED_TRACE("Expect equivalent metadata_by_id_ contents.");
    484       ExpectEquivalent(on_memory->metadata_by_id_,
    485                        reloaded->metadata_by_id_);
    486     }
    487 
    488     {
    489       SCOPED_TRACE("Expect equivalent tracker_by_id_ contents.");
    490       ExpectEquivalent(on_memory->tracker_by_id_,
    491                        reloaded->tracker_by_id_);
    492     }
    493 
    494     {
    495       SCOPED_TRACE("Expect equivalent trackers_by_file_id_ contents.");
    496       ExpectEquivalent(on_memory->trackers_by_file_id_,
    497                        reloaded->trackers_by_file_id_);
    498     }
    499 
    500     {
    501       SCOPED_TRACE("Expect equivalent app_root_by_app_id_ contents.");
    502       ExpectEquivalent(on_memory->app_root_by_app_id_,
    503                        reloaded->app_root_by_app_id_);
    504     }
    505 
    506     {
    507       SCOPED_TRACE("Expect equivalent trackers_by_parent_and_title_ contents.");
    508       ExpectEquivalent(on_memory->trackers_by_parent_and_title_,
    509                        reloaded->trackers_by_parent_and_title_);
    510     }
    511 
    512     {
    513       SCOPED_TRACE("Expect equivalent dirty_trackers_ contents.");
    514       ExpectEquivalent(on_memory->dirty_trackers_,
    515                        reloaded->dirty_trackers_);
    516     }
    517   }
    518 
    519   void VerifyFile(const FileMetadata& file) {
    520     FileMetadata file_in_metadata_database;
    521     ASSERT_TRUE(metadata_database()->FindFileByFileID(
    522         file.file_id(), &file_in_metadata_database));
    523 
    524     SCOPED_TRACE("Expect equivalent " + file.file_id());
    525     ExpectEquivalent(&file, &file_in_metadata_database);
    526   }
    527 
    528   void VerifyTracker(const FileTracker& tracker) {
    529     FileTracker tracker_in_metadata_database;
    530     ASSERT_TRUE(metadata_database()->FindTrackerByTrackerID(
    531         tracker.tracker_id(), &tracker_in_metadata_database));
    532 
    533     SCOPED_TRACE("Expect equivalent tracker[" +
    534                  base::Int64ToString(tracker.tracker_id()) + "]");
    535     ExpectEquivalent(&tracker, &tracker_in_metadata_database);
    536   }
    537 
    538   SyncStatusCode RegisterApp(const std::string& app_id,
    539                              const std::string& folder_id) {
    540     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    541     metadata_database_->RegisterApp(
    542         app_id, folder_id,
    543         CreateResultReceiver(&status));
    544     message_loop_.RunUntilIdle();
    545     return status;
    546   }
    547 
    548   SyncStatusCode DisableApp(const std::string& app_id) {
    549     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    550     metadata_database_->DisableApp(
    551         app_id, CreateResultReceiver(&status));
    552     message_loop_.RunUntilIdle();
    553     return status;
    554   }
    555 
    556   SyncStatusCode EnableApp(const std::string& app_id) {
    557     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    558     metadata_database_->EnableApp(
    559         app_id, CreateResultReceiver(&status));
    560     message_loop_.RunUntilIdle();
    561     return status;
    562   }
    563 
    564   SyncStatusCode UnregisterApp(const std::string& app_id) {
    565     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    566     metadata_database_->UnregisterApp(
    567         app_id, CreateResultReceiver(&status));
    568     message_loop_.RunUntilIdle();
    569     return status;
    570   }
    571 
    572   SyncStatusCode UpdateByChangeList(
    573       ScopedVector<google_apis::ChangeResource> changes) {
    574     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    575     metadata_database_->UpdateByChangeList(
    576         current_change_id_,
    577         changes.Pass(), CreateResultReceiver(&status));
    578     message_loop_.RunUntilIdle();
    579     return status;
    580   }
    581 
    582   SyncStatusCode PopulateFolder(const std::string& folder_id,
    583                                 const FileIDList& listed_children) {
    584     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    585     metadata_database_->PopulateFolderByChildList(
    586         folder_id, listed_children,
    587         CreateResultReceiver(&status));
    588     message_loop_.RunUntilIdle();
    589     return status;
    590   }
    591 
    592   SyncStatusCode UpdateTracker(const FileTracker& tracker) {
    593     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    594     metadata_database_->UpdateTracker(
    595         tracker.tracker_id(), tracker.synced_details(),
    596         CreateResultReceiver(&status));
    597     message_loop_.RunUntilIdle();
    598     return status;
    599   }
    600 
    601   SyncStatusCode PopulateInitialData(
    602       int64 largest_change_id,
    603       const google_apis::FileResource& sync_root_folder,
    604       const ScopedVector<google_apis::FileResource>& app_root_folders) {
    605     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    606     metadata_database_->PopulateInitialData(
    607         largest_change_id,
    608         sync_root_folder,
    609         app_root_folders,
    610         CreateResultReceiver(&status));
    611     message_loop_.RunUntilIdle();
    612     return status;
    613   }
    614 
    615   void ResetTrackerID(FileTracker* tracker) {
    616     tracker->set_tracker_id(GetTrackerIDByFileID(tracker->file_id()));
    617   }
    618 
    619   int64 current_change_id() const {
    620     return current_change_id_;
    621   }
    622 
    623  private:
    624   base::ScopedTempDir database_dir_;
    625   base::MessageLoop message_loop_;
    626 
    627   scoped_ptr<leveldb::Env> in_memory_env_;
    628   scoped_ptr<MetadataDatabase> metadata_database_;
    629 
    630   int64 current_change_id_;
    631   int64 next_tracker_id_;
    632   int64 next_file_id_number_;
    633   int64 next_md5_sequence_number_;
    634 
    635   DISALLOW_COPY_AND_ASSIGN(MetadataDatabaseTest);
    636 };
    637 
    638 TEST_F(MetadataDatabaseTest, InitializationTest_Empty) {
    639   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    640   DropDatabase();
    641   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    642 }
    643 
    644 TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) {
    645   TrackedFile sync_root(CreateTrackedSyncRoot());
    646   TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id"));
    647   app_root.tracker.set_app_id(app_root.metadata.details().title());
    648   app_root.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
    649 
    650   TrackedFile file(CreateTrackedFile(app_root, "file"));
    651   TrackedFile folder(CreateTrackedFolder(app_root, "folder"));
    652   TrackedFile file_in_folder(CreateTrackedFile(folder, "file_in_folder"));
    653   TrackedFile orphaned_file(CreateTrackedFile(sync_root, "orphaned_file"));
    654   orphaned_file.metadata.mutable_details()->clear_parent_folder_ids();
    655   orphaned_file.tracker.set_parent_tracker_id(0);
    656 
    657   const TrackedFile* tracked_files[] = {
    658     &sync_root, &app_root, &file, &folder, &file_in_folder, &orphaned_file
    659   };
    660 
    661   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
    662   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    663 
    664   orphaned_file.should_be_absent = true;
    665   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
    666 }
    667 
    668 TEST_F(MetadataDatabaseTest, AppManagementTest) {
    669   TrackedFile sync_root(CreateTrackedSyncRoot());
    670   TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id"));
    671   app_root.tracker.set_app_id(app_root.metadata.details().title());
    672   app_root.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
    673 
    674   TrackedFile file(CreateTrackedFile(app_root, "file"));
    675   TrackedFile folder(CreateTrackedFolder(sync_root, "folder"));
    676   folder.tracker.set_active(false);
    677 
    678   const TrackedFile* tracked_files[] = {
    679     &sync_root, &app_root, &file, &folder,
    680   };
    681   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
    682   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    683   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
    684 
    685   folder.tracker.set_app_id("foo");
    686   EXPECT_EQ(SYNC_STATUS_OK, RegisterApp(
    687       folder.tracker.app_id(), folder.metadata.file_id()));
    688   folder.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
    689   folder.tracker.set_active(true);
    690   folder.tracker.set_dirty(true);
    691   folder.tracker.set_needs_folder_listing(true);
    692   VerifyTrackedFile(folder);
    693   VerifyReloadConsistency();
    694 
    695   EXPECT_EQ(SYNC_STATUS_OK, DisableApp(folder.tracker.app_id()));
    696   folder.tracker.set_tracker_kind(TRACKER_KIND_DISABLED_APP_ROOT);
    697   VerifyTrackedFile(folder);
    698   VerifyReloadConsistency();
    699 
    700   EXPECT_EQ(SYNC_STATUS_OK, EnableApp(folder.tracker.app_id()));
    701   folder.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
    702   VerifyTrackedFile(folder);
    703   VerifyReloadConsistency();
    704 
    705   EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(folder.tracker.app_id()));
    706   folder.tracker.set_app_id(std::string());
    707   folder.tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
    708   folder.tracker.set_active(false);
    709   VerifyTrackedFile(folder);
    710   VerifyReloadConsistency();
    711 
    712   EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(app_root.tracker.app_id()));
    713   app_root.tracker.set_app_id(std::string());
    714   app_root.tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
    715   app_root.tracker.set_active(false);
    716   app_root.tracker.set_dirty(true);
    717   file.should_be_absent = true;
    718   VerifyTrackedFile(app_root);
    719   VerifyTrackedFile(file);
    720   VerifyReloadConsistency();
    721 }
    722 
    723 TEST_F(MetadataDatabaseTest, BuildPathTest) {
    724   FileMetadata sync_root(CreateSyncRootMetadata());
    725   FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
    726 
    727   FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
    728   FileTracker app_root_tracker(
    729       CreateTracker(sync_root_tracker, app_root));
    730   app_root_tracker.set_app_id(app_root.details().title());
    731   app_root_tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
    732 
    733   FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
    734   FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
    735 
    736   FileMetadata file(CreateFileMetadata(folder, "file"));
    737   FileTracker file_tracker(CreateTracker(folder_tracker, file));
    738 
    739   FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder"));
    740   FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker,
    741                                                     inactive_folder));
    742   inactive_folder_tracker.set_active(false);
    743 
    744   {
    745     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
    746     ASSERT_TRUE(db);
    747 
    748     EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
    749     EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
    750     EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
    751     EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
    752     EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
    753     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
    754     EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
    755     EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
    756   }
    757 
    758   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    759 
    760   base::FilePath path;
    761   EXPECT_FALSE(metadata_database()->BuildPathForTracker(
    762       sync_root_tracker.tracker_id(), &path));
    763   EXPECT_TRUE(metadata_database()->BuildPathForTracker(
    764       app_root_tracker.tracker_id(), &path));
    765   EXPECT_EQ(base::FilePath(FPL("/")).NormalizePathSeparators(), path);
    766   EXPECT_TRUE(metadata_database()->BuildPathForTracker(
    767       file_tracker.tracker_id(), &path));
    768   EXPECT_EQ(base::FilePath(FPL("/folder/file")).NormalizePathSeparators(),
    769             path);
    770 }
    771 
    772 TEST_F(MetadataDatabaseTest, FindNearestActiveAncestorTest) {
    773   const std::string kAppID = "app_id";
    774 
    775   FileMetadata sync_root(CreateSyncRootMetadata());
    776   FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
    777 
    778   FileMetadata app_root(CreateFolderMetadata(sync_root, kAppID));
    779   FileTracker app_root_tracker(
    780       CreateTracker(sync_root_tracker, app_root));
    781   app_root_tracker.set_app_id(app_root.details().title());
    782   app_root_tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
    783 
    784   // Create directory structure like this: "/folder1/folder2/file"
    785   FileMetadata folder1(CreateFolderMetadata(app_root, "folder1"));
    786   FileTracker folder_tracker1(CreateTracker(app_root_tracker, folder1));
    787   FileMetadata folder2(CreateFolderMetadata(folder1, "folder2"));
    788   FileTracker folder_tracker2(CreateTracker(folder_tracker1, folder2));
    789   FileMetadata file(CreateFileMetadata(folder2, "file"));
    790   FileTracker file_tracker(CreateTracker(folder_tracker2, file));
    791 
    792   FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder1"));
    793   FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker,
    794                                                     inactive_folder));
    795   inactive_folder_tracker.set_active(false);
    796 
    797   {
    798     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
    799     ASSERT_TRUE(db);
    800 
    801     EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
    802     EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
    803     EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
    804     EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
    805     EXPECT_TRUE(PutFileToDB(db.get(), folder1).ok());
    806     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker1).ok());
    807     EXPECT_TRUE(PutFileToDB(db.get(), folder2).ok());
    808     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker2).ok());
    809     EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
    810     EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
    811     EXPECT_TRUE(PutFileToDB(db.get(), inactive_folder).ok());
    812     EXPECT_TRUE(PutTrackerToDB(db.get(), inactive_folder_tracker).ok());
    813   }
    814 
    815   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    816 
    817   {
    818     base::FilePath path;
    819     FileTracker tracker;
    820     EXPECT_FALSE(metadata_database()->FindNearestActiveAncestor(
    821         "non_registered_app_id",
    822         CreateNormalizedPath(FPL("folder1/folder2/file")),
    823         &tracker, &path));
    824   }
    825 
    826   {
    827     base::FilePath path;
    828     FileTracker tracker;
    829     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
    830         kAppID, CreateNormalizedPath(FPL("")), &tracker, &path));
    831     EXPECT_EQ(app_root_tracker.tracker_id(), tracker.tracker_id());
    832     EXPECT_EQ(CreateNormalizedPath(FPL("")), path);
    833   }
    834 
    835   {
    836     base::FilePath path;
    837     FileTracker tracker;
    838     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
    839         kAppID, CreateNormalizedPath(FPL("folder1/folder2")),
    840         &tracker, &path));
    841     EXPECT_EQ(folder_tracker2.tracker_id(), tracker.tracker_id());
    842     EXPECT_EQ(CreateNormalizedPath(FPL("folder1/folder2")), path);
    843   }
    844 
    845   {
    846     base::FilePath path;
    847     FileTracker tracker;
    848     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
    849         kAppID, CreateNormalizedPath(FPL("folder1/folder2/file")),
    850         &tracker, &path));
    851     EXPECT_EQ(file_tracker.tracker_id(), tracker.tracker_id());
    852     EXPECT_EQ(CreateNormalizedPath(FPL("folder1/folder2/file")), path);
    853   }
    854 
    855   {
    856     base::FilePath path;
    857     FileTracker tracker;
    858     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
    859         kAppID,
    860         CreateNormalizedPath(FPL("folder1/folder2/folder3/folder4/file")),
    861         &tracker, &path));
    862     EXPECT_EQ(folder_tracker2.tracker_id(), tracker.tracker_id());
    863     EXPECT_EQ(CreateNormalizedPath(FPL("folder1/folder2")), path);
    864   }
    865 
    866   {
    867     base::FilePath path;
    868     FileTracker tracker;
    869     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
    870         kAppID, CreateNormalizedPath(FPL("folder1/folder2/file/folder4/file")),
    871         &tracker, &path));
    872     EXPECT_EQ(folder_tracker2.tracker_id(), tracker.tracker_id());
    873     EXPECT_EQ(CreateNormalizedPath(FPL("folder1/folder2")), path);
    874   }
    875 }
    876 
    877 TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) {
    878   TrackedFile sync_root(CreateTrackedSyncRoot());
    879   TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id"));
    880   TrackedFile disabled_app_root(CreateTrackedFolder(sync_root, "disabled_app"));
    881   TrackedFile file(CreateTrackedFile(app_root, "file"));
    882   TrackedFile renamed_file(CreateTrackedFile(app_root, "to be renamed"));
    883   TrackedFile folder(CreateTrackedFolder(app_root, "folder"));
    884   TrackedFile reorganized_file(
    885       CreateTrackedFile(app_root, "to be reorganized"));
    886   TrackedFile updated_file(
    887       CreateTrackedFile(app_root, "to be updated"));
    888   TrackedFile noop_file(CreateTrackedFile(app_root, "has noop change"));
    889   TrackedFile new_file(CreateTrackedFile(app_root, "to be added later"));
    890   new_file.should_be_absent = true;
    891 
    892   const TrackedFile* tracked_files[] = {
    893     &sync_root, &app_root, &disabled_app_root,
    894     &file, &renamed_file, &folder, &reorganized_file, &updated_file, &noop_file,
    895     &new_file,
    896   };
    897 
    898   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
    899   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    900 
    901   ApplyRenameChangeToMetadata("renamed", &renamed_file.metadata);
    902   ApplyReorganizeChangeToMetadata(folder.metadata.file_id(),
    903                                   &reorganized_file.metadata);
    904   ApplyContentChangeToMetadata(&updated_file.metadata);
    905 
    906   // Update change ID.
    907   ApplyNoopChangeToMetadata(&noop_file.metadata);
    908 
    909   ScopedVector<google_apis::ChangeResource> changes;
    910   PushToChangeList(
    911       CreateChangeResourceFromMetadata(renamed_file.metadata), &changes);
    912   PushToChangeList(
    913       CreateChangeResourceFromMetadata(reorganized_file.metadata), &changes);
    914   PushToChangeList(
    915       CreateChangeResourceFromMetadata(updated_file.metadata), &changes);
    916   PushToChangeList(
    917       CreateChangeResourceFromMetadata(noop_file.metadata), &changes);
    918   PushToChangeList(
    919       CreateChangeResourceFromMetadata(new_file.metadata), &changes);
    920   EXPECT_EQ(SYNC_STATUS_OK, UpdateByChangeList(changes.Pass()));
    921 
    922   renamed_file.tracker.set_dirty(true);
    923   reorganized_file.tracker.set_dirty(true);
    924   updated_file.tracker.set_dirty(true);
    925   noop_file.tracker.set_dirty(true);
    926   new_file.tracker.mutable_synced_details()->set_missing(true);
    927   new_file.tracker.mutable_synced_details()->clear_md5();
    928   new_file.tracker.set_active(false);
    929   new_file.tracker.set_dirty(true);
    930   ResetTrackerID(&new_file.tracker);
    931   EXPECT_NE(0, new_file.tracker.tracker_id());
    932 
    933   new_file.should_be_absent = false;
    934 
    935   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
    936   VerifyReloadConsistency();
    937 }
    938 
    939 TEST_F(MetadataDatabaseTest, PopulateFolderTest_RegularFolder) {
    940   TrackedFile sync_root(CreateTrackedSyncRoot());
    941   TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_id"));
    942   app_root.tracker.set_app_id(app_root.metadata.details().title());
    943 
    944   TrackedFile folder_to_populate(
    945       CreateTrackedFolder(app_root, "folder_to_populate"));
    946   folder_to_populate.tracker.set_needs_folder_listing(true);
    947   folder_to_populate.tracker.set_dirty(true);
    948 
    949   TrackedFile known_file(CreateTrackedFile(folder_to_populate, "known_file"));
    950   TrackedFile new_file(CreateTrackedFile(folder_to_populate, "new_file"));
    951   new_file.should_be_absent = true;
    952 
    953   const TrackedFile* tracked_files[] = {
    954     &sync_root, &app_root, &folder_to_populate, &known_file, &new_file
    955   };
    956 
    957   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
    958   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    959   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
    960 
    961   FileIDList listed_children;
    962   listed_children.push_back(known_file.metadata.file_id());
    963   listed_children.push_back(new_file.metadata.file_id());
    964 
    965   EXPECT_EQ(SYNC_STATUS_OK,
    966             PopulateFolder(folder_to_populate.metadata.file_id(),
    967                            listed_children));
    968 
    969   folder_to_populate.tracker.set_dirty(false);
    970   folder_to_populate.tracker.set_needs_folder_listing(false);
    971   ResetTrackerID(&new_file.tracker);
    972   new_file.tracker.set_dirty(true);
    973   new_file.tracker.set_active(false);
    974   new_file.tracker.clear_synced_details();
    975   new_file.should_be_absent = false;
    976   new_file.tracker_only = true;
    977   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
    978   VerifyReloadConsistency();
    979 }
    980 
    981 TEST_F(MetadataDatabaseTest, PopulateFolderTest_InactiveFolder) {
    982   TrackedFile sync_root(CreateTrackedSyncRoot());
    983   TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_id"));
    984 
    985   TrackedFile inactive_folder(CreateTrackedFolder(app_root, "inactive_folder"));
    986   inactive_folder.tracker.set_active(false);
    987   inactive_folder.tracker.set_dirty(true);
    988 
    989   TrackedFile new_file(
    990       CreateTrackedFile(inactive_folder, "file_in_inactive_folder"));
    991   new_file.should_be_absent = true;
    992 
    993   const TrackedFile* tracked_files[] = {
    994     &sync_root, &app_root, &inactive_folder, &new_file,
    995   };
    996 
    997   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
    998   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
    999   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1000 
   1001   FileIDList listed_children;
   1002   listed_children.push_back(new_file.metadata.file_id());
   1003 
   1004   EXPECT_EQ(SYNC_STATUS_OK,
   1005             PopulateFolder(inactive_folder.metadata.file_id(),
   1006                            listed_children));
   1007   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1008   VerifyReloadConsistency();
   1009 }
   1010 
   1011 TEST_F(MetadataDatabaseTest, PopulateFolderTest_DisabledAppRoot) {
   1012   TrackedFile sync_root(CreateTrackedSyncRoot());
   1013   TrackedFile disabled_app_root(
   1014       CreateTrackedAppRoot(sync_root, "disabled_app"));
   1015   disabled_app_root.tracker.set_dirty(true);
   1016   disabled_app_root.tracker.set_needs_folder_listing(true);
   1017 
   1018   TrackedFile known_file(CreateTrackedFile(disabled_app_root, "known_file"));
   1019   TrackedFile file(CreateTrackedFile(disabled_app_root, "file"));
   1020   file.should_be_absent = true;
   1021 
   1022   const TrackedFile* tracked_files[] = {
   1023     &sync_root, &disabled_app_root, &disabled_app_root, &known_file, &file,
   1024   };
   1025 
   1026   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
   1027   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
   1028   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1029 
   1030   FileIDList disabled_app_children;
   1031   disabled_app_children.push_back(file.metadata.file_id());
   1032   EXPECT_EQ(SYNC_STATUS_OK, PopulateFolder(
   1033       disabled_app_root.metadata.file_id(), disabled_app_children));
   1034   ResetTrackerID(&file.tracker);
   1035   file.tracker.clear_synced_details();
   1036   file.tracker.set_dirty(true);
   1037   file.tracker.set_active(false);
   1038   file.should_be_absent = false;
   1039   file.tracker_only = true;
   1040 
   1041   disabled_app_root.tracker.set_dirty(false);
   1042   disabled_app_root.tracker.set_needs_folder_listing(false);
   1043   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1044   VerifyReloadConsistency();
   1045 }
   1046 
   1047 // TODO(tzik): Fix expectation and re-enable this test.
   1048 TEST_F(MetadataDatabaseTest, DISABLED_UpdateTrackerTest) {
   1049   TrackedFile sync_root(CreateTrackedSyncRoot());
   1050   TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_root"));
   1051   TrackedFile file(CreateTrackedFile(app_root, "file"));
   1052   file.tracker.set_dirty(true);
   1053   file.metadata.mutable_details()->set_title("renamed file");
   1054 
   1055   TrackedFile inactive_file(CreateTrackedFile(app_root, "inactive_file"));
   1056   inactive_file.tracker.set_active(false);
   1057   inactive_file.tracker.set_dirty(true);
   1058   inactive_file.metadata.mutable_details()->set_title("renamed inactive file");
   1059   inactive_file.metadata.mutable_details()->set_md5("modified_md5");
   1060 
   1061   TrackedFile new_conflict(CreateTrackedFile(app_root, "new conflict file"));
   1062   new_conflict.tracker.set_dirty(true);
   1063   new_conflict.metadata.mutable_details()->set_title("renamed file");
   1064 
   1065   const TrackedFile* tracked_files[] = {
   1066     &sync_root, &app_root, &file, &inactive_file, &new_conflict
   1067   };
   1068 
   1069   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
   1070   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
   1071   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1072   VerifyReloadConsistency();
   1073 
   1074   *file.tracker.mutable_synced_details() = file.metadata.details();
   1075   file.tracker.set_dirty(false);
   1076   EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(file.tracker));
   1077   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1078   VerifyReloadConsistency();
   1079 
   1080   *inactive_file.tracker.mutable_synced_details() =
   1081        inactive_file.metadata.details();
   1082   inactive_file.tracker.set_dirty(false);
   1083   inactive_file.tracker.set_active(true);
   1084   EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(inactive_file.tracker));
   1085   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1086   VerifyReloadConsistency();
   1087 
   1088   *new_conflict.tracker.mutable_synced_details() =
   1089        new_conflict.metadata.details();
   1090   new_conflict.tracker.set_dirty(false);
   1091   new_conflict.tracker.set_active(true);
   1092   file.tracker.set_dirty(true);
   1093   file.tracker.set_active(false);
   1094   EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(new_conflict.tracker));
   1095   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1096   VerifyReloadConsistency();
   1097 }
   1098 
   1099 TEST_F(MetadataDatabaseTest, PopulateInitialDataTest) {
   1100   TrackedFile sync_root(CreateTrackedSyncRoot());
   1101   TrackedFile app_root(CreateTrackedFolder(sync_root, "app_root"));
   1102   app_root.tracker.set_active(false);
   1103 
   1104   const TrackedFile* tracked_files[] = {
   1105     &sync_root, &app_root
   1106   };
   1107 
   1108   scoped_ptr<google_apis::FileResource> sync_root_folder(
   1109       CreateFileResourceFromMetadata(sync_root.metadata));
   1110   scoped_ptr<google_apis::FileResource> app_root_folder(
   1111       CreateFileResourceFromMetadata(app_root.metadata));
   1112 
   1113   ScopedVector<google_apis::FileResource> app_root_folders;
   1114   app_root_folders.push_back(app_root_folder.release());
   1115 
   1116   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
   1117   EXPECT_EQ(SYNC_STATUS_OK, PopulateInitialData(
   1118       current_change_id(),
   1119       *sync_root_folder,
   1120       app_root_folders));
   1121 
   1122   ResetTrackerID(&sync_root.tracker);
   1123   ResetTrackerID(&app_root.tracker);
   1124   app_root.tracker.set_parent_tracker_id(sync_root.tracker.tracker_id());
   1125 
   1126   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1127   VerifyReloadConsistency();
   1128 }
   1129 
   1130 TEST_F(MetadataDatabaseTest, DumpFiles) {
   1131   TrackedFile sync_root(CreateTrackedSyncRoot());
   1132   TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_id"));
   1133   app_root.tracker.set_app_id(app_root.metadata.details().title());
   1134 
   1135   TrackedFile folder_0(CreateTrackedFolder(app_root, "folder_0"));
   1136   TrackedFile file_0(CreateTrackedFile(folder_0, "file_0"));
   1137 
   1138   const TrackedFile* tracked_files[] = {
   1139     &sync_root, &app_root, &folder_0, &file_0
   1140   };
   1141 
   1142   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
   1143   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
   1144   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
   1145 
   1146   scoped_ptr<base::ListValue> files =
   1147       metadata_database()->DumpFiles(app_root.tracker.app_id());
   1148   ASSERT_EQ(2u, files->GetSize());
   1149 
   1150   base::DictionaryValue* file = NULL;
   1151   std::string str;
   1152 
   1153   ASSERT_TRUE(files->GetDictionary(0, &file));
   1154   EXPECT_TRUE(file->GetString("title", &str) && str == "folder_0");
   1155   EXPECT_TRUE(file->GetString("type", &str) && str == "folder");
   1156   EXPECT_TRUE(file->HasKey("details"));
   1157 
   1158   ASSERT_TRUE(files->GetDictionary(1, &file));
   1159   EXPECT_TRUE(file->GetString("title", &str) && str == "file_0");
   1160   EXPECT_TRUE(file->GetString("type", &str) && str == "file");
   1161   EXPECT_TRUE(file->HasKey("details"));
   1162 }
   1163 
   1164 }  // namespace drive_backend
   1165 }  // namespace sync_file_system
   1166