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