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