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