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