metadata_database_unittest.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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 : current_change_id_(kInitialChangeID), 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(++current_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(++current_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(++current_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 current_change_id_, 542 changes.Pass(), CreateResultReceiver(&status)); 543 message_loop_.RunUntilIdle(); 544 return status; 545 } 546 547 SyncStatusCode PopulateFolder(const std::string& folder_id, 548 const FileIDList& listed_children) { 549 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 550 metadata_database_->PopulateFolderByChildList( 551 folder_id, listed_children, 552 CreateResultReceiver(&status)); 553 message_loop_.RunUntilIdle(); 554 return status; 555 } 556 557 SyncStatusCode UpdateTracker(const FileTracker& tracker) { 558 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 559 metadata_database_->UpdateTracker( 560 tracker.tracker_id(), tracker.synced_details(), 561 CreateResultReceiver(&status)); 562 message_loop_.RunUntilIdle(); 563 return status; 564 } 565 566 SyncStatusCode PopulateInitialData( 567 int64 largest_change_id, 568 const google_apis::FileResource& sync_root_folder, 569 const ScopedVector<google_apis::FileResource>& app_root_folders) { 570 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 571 metadata_database_->PopulateInitialData( 572 largest_change_id, 573 sync_root_folder, 574 app_root_folders, 575 CreateResultReceiver(&status)); 576 message_loop_.RunUntilIdle(); 577 return status; 578 } 579 580 void ResetTrackerID(FileTracker* tracker) { 581 tracker->set_tracker_id(GetTrackerIDByFileID(tracker->file_id())); 582 } 583 584 private: 585 base::ScopedTempDir database_dir_; 586 base::MessageLoop message_loop_; 587 588 scoped_ptr<MetadataDatabase> metadata_database_; 589 590 int64 current_change_id_; 591 int64 next_tracker_id_; 592 int64 next_file_id_number_; 593 int64 next_md5_sequence_number_; 594 595 DISALLOW_COPY_AND_ASSIGN(MetadataDatabaseTest); 596}; 597 598TEST_F(MetadataDatabaseTest, InitializationTest_Empty) { 599 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 600 DropDatabase(); 601 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 602} 603 604TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) { 605 TrackedFile sync_root(CreateTrackedSyncRoot()); 606 TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id")); 607 app_root.tracker.set_app_id(app_root.metadata.details().title()); 608 app_root.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT); 609 610 TrackedFile file(CreateTrackedFile(app_root, "file")); 611 TrackedFile folder(CreateTrackedFolder(app_root, "folder")); 612 TrackedFile file_in_folder(CreateTrackedFile(folder, "file_in_folder")); 613 TrackedFile orphaned_file(CreateTrackedFile(sync_root, "orphaned_file")); 614 orphaned_file.metadata.mutable_details()->clear_parent_folder_ids(); 615 orphaned_file.tracker.set_parent_tracker_id(0); 616 617 const TrackedFile* tracked_files[] = { 618 &sync_root, &app_root, &file, &folder, &file_in_folder, &orphaned_file 619 }; 620 621 SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files)); 622 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 623 624 orphaned_file.should_be_absent = true; 625 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 626} 627 628TEST_F(MetadataDatabaseTest, AppManagementTest) { 629 TrackedFile sync_root(CreateTrackedSyncRoot()); 630 TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id")); 631 app_root.tracker.set_app_id(app_root.metadata.details().title()); 632 app_root.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT); 633 634 TrackedFile file(CreateTrackedFile(app_root, "file")); 635 TrackedFile folder(CreateTrackedFolder(sync_root, "folder")); 636 folder.tracker.set_active(false); 637 638 const TrackedFile* tracked_files[] = { 639 &sync_root, &app_root, &file, &folder, 640 }; 641 SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files)); 642 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 643 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 644 645 folder.tracker.set_app_id("foo"); 646 EXPECT_EQ(SYNC_STATUS_OK, RegisterApp( 647 folder.tracker.app_id(), folder.metadata.file_id())); 648 folder.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT); 649 folder.tracker.set_active(true); 650 folder.tracker.set_dirty(true); 651 folder.tracker.set_needs_folder_listing(true); 652 VerifyTrackedFile(folder); 653 VerifyReloadConsistency(); 654 655 EXPECT_EQ(SYNC_STATUS_OK, DisableApp(folder.tracker.app_id())); 656 folder.tracker.set_tracker_kind(TRACKER_KIND_DISABLED_APP_ROOT); 657 VerifyTrackedFile(folder); 658 VerifyReloadConsistency(); 659 660 EXPECT_EQ(SYNC_STATUS_OK, EnableApp(folder.tracker.app_id())); 661 folder.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT); 662 VerifyTrackedFile(folder); 663 VerifyReloadConsistency(); 664 665 EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(folder.tracker.app_id())); 666 folder.tracker.set_app_id(std::string()); 667 folder.tracker.set_tracker_kind(TRACKER_KIND_REGULAR); 668 folder.tracker.set_active(false); 669 VerifyTrackedFile(folder); 670 VerifyReloadConsistency(); 671 672 EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(app_root.tracker.app_id())); 673 app_root.tracker.set_app_id(std::string()); 674 app_root.tracker.set_tracker_kind(TRACKER_KIND_REGULAR); 675 app_root.tracker.set_active(false); 676 app_root.tracker.set_dirty(true); 677 file.should_be_absent = true; 678 VerifyTrackedFile(app_root); 679 VerifyTrackedFile(file); 680 VerifyReloadConsistency(); 681} 682 683TEST_F(MetadataDatabaseTest, BuildPathTest) { 684 FileMetadata sync_root(CreateSyncRootMetadata()); 685 FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root)); 686 687 FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id")); 688 FileTracker app_root_tracker( 689 CreateTracker(sync_root_tracker, app_root)); 690 app_root_tracker.set_app_id(app_root.details().title()); 691 app_root_tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT); 692 693 FileMetadata folder(CreateFolderMetadata(app_root, "folder")); 694 FileTracker folder_tracker(CreateTracker(app_root_tracker, folder)); 695 696 FileMetadata file(CreateFolderMetadata(folder, "file")); 697 FileTracker file_tracker(CreateTracker(folder_tracker, file)); 698 699 FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder")); 700 FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker, 701 inactive_folder)); 702 inactive_folder_tracker.set_active(false); 703 704 { 705 scoped_ptr<leveldb::DB> db = InitializeLevelDB(); 706 ASSERT_TRUE(db); 707 708 EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok()); 709 EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok()); 710 EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok()); 711 EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok()); 712 EXPECT_TRUE(PutFileToDB(db.get(), folder).ok()); 713 EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok()); 714 EXPECT_TRUE(PutFileToDB(db.get(), file).ok()); 715 EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok()); 716 } 717 718 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 719 720 base::FilePath path; 721 EXPECT_FALSE(metadata_database()->BuildPathForTracker( 722 sync_root_tracker.tracker_id(), &path)); 723 EXPECT_TRUE(metadata_database()->BuildPathForTracker( 724 app_root_tracker.tracker_id(), &path)); 725 EXPECT_EQ(base::FilePath(FPL("/")).NormalizePathSeparators(), path); 726 EXPECT_TRUE(metadata_database()->BuildPathForTracker( 727 file_tracker.tracker_id(), &path)); 728 EXPECT_EQ(base::FilePath(FPL("/folder/file")).NormalizePathSeparators(), 729 path); 730} 731 732TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) { 733 TrackedFile sync_root(CreateTrackedSyncRoot()); 734 TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id")); 735 TrackedFile disabled_app_root(CreateTrackedFolder(sync_root, "disabled_app")); 736 TrackedFile file(CreateTrackedFile(app_root, "file")); 737 TrackedFile renamed_file(CreateTrackedFile(app_root, "to be renamed")); 738 TrackedFile folder(CreateTrackedFolder(app_root, "folder")); 739 TrackedFile reorganized_file( 740 CreateTrackedFile(app_root, "to be reorganized")); 741 TrackedFile updated_file( 742 CreateTrackedFile(app_root, "to be updated")); 743 TrackedFile noop_file(CreateTrackedFile(app_root, "has noop change")); 744 TrackedFile new_file(CreateTrackedFile(app_root, "to be added later")); 745 new_file.should_be_absent = true; 746 747 const TrackedFile* tracked_files[] = { 748 &sync_root, &app_root, &disabled_app_root, 749 &file, &renamed_file, &folder, &reorganized_file, &updated_file, &noop_file, 750 &new_file, 751 }; 752 753 SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files)); 754 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 755 756 ApplyRenameChangeToMetadata("renamed", &renamed_file.metadata); 757 ApplyReorganizeChangeToMetadata(folder.metadata.file_id(), 758 &reorganized_file.metadata); 759 ApplyContentChangeToMetadata(&updated_file.metadata); 760 761 ScopedVector<google_apis::ChangeResource> changes; 762 PushToChangeList( 763 CreateChangeResourceFromMetadata(renamed_file.metadata), &changes); 764 PushToChangeList( 765 CreateChangeResourceFromMetadata(reorganized_file.metadata), &changes); 766 PushToChangeList( 767 CreateChangeResourceFromMetadata(updated_file.metadata), &changes); 768 PushToChangeList( 769 CreateChangeResourceFromMetadata(noop_file.metadata), &changes); 770 PushToChangeList( 771 CreateChangeResourceFromMetadata(new_file.metadata), &changes); 772 EXPECT_EQ(SYNC_STATUS_OK, UpdateByChangeList(changes.Pass())); 773 774 renamed_file.tracker.set_dirty(true); 775 reorganized_file.tracker.set_dirty(true); 776 updated_file.tracker.set_dirty(true); 777 noop_file.tracker.set_dirty(true); 778 new_file.tracker.clear_synced_details(); 779 new_file.tracker.set_active(false); 780 new_file.tracker.set_dirty(true); 781 ResetTrackerID(&new_file.tracker); 782 EXPECT_NE(0, new_file.tracker.tracker_id()); 783 784 new_file.should_be_absent = false; 785 786 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 787 VerifyReloadConsistency(); 788} 789 790TEST_F(MetadataDatabaseTest, PopulateFolderTest_RegularFolder) { 791 TrackedFile sync_root(CreateTrackedSyncRoot()); 792 TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_id")); 793 app_root.tracker.set_app_id(app_root.metadata.details().title()); 794 795 TrackedFile folder_to_populate( 796 CreateTrackedFolder(app_root, "folder_to_populate")); 797 folder_to_populate.tracker.set_needs_folder_listing(true); 798 folder_to_populate.tracker.set_dirty(true); 799 800 TrackedFile known_file(CreateTrackedFile(folder_to_populate, "known_file")); 801 TrackedFile new_file(CreateTrackedFile(folder_to_populate, "new_file")); 802 new_file.should_be_absent = true; 803 804 const TrackedFile* tracked_files[] = { 805 &sync_root, &app_root, &folder_to_populate, &known_file, &new_file 806 }; 807 808 SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files)); 809 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 810 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 811 812 FileIDList listed_children; 813 listed_children.push_back(known_file.metadata.file_id()); 814 listed_children.push_back(new_file.metadata.file_id()); 815 816 EXPECT_EQ(SYNC_STATUS_OK, 817 PopulateFolder(folder_to_populate.metadata.file_id(), 818 listed_children)); 819 820 folder_to_populate.tracker.set_dirty(false); 821 folder_to_populate.tracker.set_needs_folder_listing(false); 822 ResetTrackerID(&new_file.tracker); 823 new_file.tracker.set_dirty(true); 824 new_file.tracker.set_active(false); 825 new_file.tracker.clear_synced_details(); 826 new_file.should_be_absent = false; 827 new_file.tracker_only = true; 828 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 829 VerifyReloadConsistency(); 830} 831 832TEST_F(MetadataDatabaseTest, PopulateFolderTest_InactiveFolder) { 833 TrackedFile sync_root(CreateTrackedSyncRoot()); 834 TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_id")); 835 836 TrackedFile inactive_folder(CreateTrackedFolder(app_root, "inactive_folder")); 837 inactive_folder.tracker.set_active(false); 838 inactive_folder.tracker.set_dirty(true); 839 840 TrackedFile new_file( 841 CreateTrackedFile(inactive_folder, "file_in_inactive_folder")); 842 new_file.should_be_absent = true; 843 844 const TrackedFile* tracked_files[] = { 845 &sync_root, &app_root, &inactive_folder, &new_file, 846 }; 847 848 SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files)); 849 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 850 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 851 852 FileIDList listed_children; 853 listed_children.push_back(new_file.metadata.file_id()); 854 855 EXPECT_EQ(SYNC_STATUS_OK, 856 PopulateFolder(inactive_folder.metadata.file_id(), 857 listed_children)); 858 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 859 VerifyReloadConsistency(); 860} 861 862TEST_F(MetadataDatabaseTest, PopulateFolderTest_DisabledAppRoot) { 863 TrackedFile sync_root(CreateTrackedSyncRoot()); 864 TrackedFile disabled_app_root( 865 CreateTrackedAppRoot(sync_root, "disabled_app")); 866 disabled_app_root.tracker.set_dirty(true); 867 disabled_app_root.tracker.set_needs_folder_listing(true); 868 869 TrackedFile known_file(CreateTrackedFile(disabled_app_root, "known_file")); 870 TrackedFile file(CreateTrackedFile(disabled_app_root, "file")); 871 file.should_be_absent = true; 872 873 const TrackedFile* tracked_files[] = { 874 &sync_root, &disabled_app_root, &disabled_app_root, &known_file, &file, 875 }; 876 877 SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files)); 878 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 879 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 880 881 FileIDList disabled_app_children; 882 disabled_app_children.push_back(file.metadata.file_id()); 883 EXPECT_EQ(SYNC_STATUS_OK, PopulateFolder( 884 disabled_app_root.metadata.file_id(), disabled_app_children)); 885 ResetTrackerID(&file.tracker); 886 file.tracker.clear_synced_details(); 887 file.tracker.set_dirty(true); 888 file.tracker.set_active(false); 889 file.should_be_absent = false; 890 file.tracker_only = true; 891 892 disabled_app_root.tracker.set_dirty(false); 893 disabled_app_root.tracker.set_needs_folder_listing(false); 894 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 895 VerifyReloadConsistency(); 896} 897 898TEST_F(MetadataDatabaseTest, UpdateTrackerTest) { 899 TrackedFile sync_root(CreateTrackedSyncRoot()); 900 TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_root")); 901 TrackedFile file(CreateTrackedFile(app_root, "file")); 902 file.tracker.set_dirty(true); 903 file.metadata.mutable_details()->set_title("renamed file");; 904 905 TrackedFile inactive_file(CreateTrackedFile(app_root, "inactive_file")); 906 inactive_file.tracker.set_active(false); 907 inactive_file.tracker.set_dirty(true); 908 inactive_file.metadata.mutable_details()->set_title("renamed inactive file"); 909 inactive_file.metadata.mutable_details()->set_md5("modified_md5"); 910 911 TrackedFile new_conflict(CreateTrackedFile(app_root, "new conflict file")); 912 new_conflict.tracker.set_dirty(true); 913 new_conflict.metadata.mutable_details()->set_title("renamed file"); 914 915 const TrackedFile* tracked_files[] = { 916 &sync_root, &app_root, &file, &inactive_file, &new_conflict 917 }; 918 919 SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files)); 920 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 921 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 922 VerifyReloadConsistency(); 923 924 *file.tracker.mutable_synced_details() = file.metadata.details(); 925 file.tracker.set_dirty(false); 926 EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(file.tracker)); 927 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 928 VerifyReloadConsistency(); 929 930 *inactive_file.tracker.mutable_synced_details() = 931 inactive_file.metadata.details(); 932 inactive_file.tracker.set_dirty(false); 933 inactive_file.tracker.set_active(true); 934 EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(inactive_file.tracker)); 935 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 936 VerifyReloadConsistency(); 937 938 *new_conflict.tracker.mutable_synced_details() = 939 new_conflict.metadata.details(); 940 new_conflict.tracker.set_dirty(false); 941 new_conflict.tracker.set_active(true); 942 file.tracker.set_dirty(true); 943 file.tracker.set_active(false); 944 EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(new_conflict.tracker)); 945 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 946 VerifyReloadConsistency(); 947} 948 949TEST_F(MetadataDatabaseTest, PopulateInitialDataTest) { 950 TrackedFile sync_root(CreateTrackedSyncRoot()); 951 TrackedFile app_root(CreateTrackedFolder(sync_root, "app_root")); 952 app_root.tracker.set_active(false); 953 954 const TrackedFile* tracked_files[] = { 955 &sync_root, &app_root 956 }; 957 958 int64 largest_change_id = 42; 959 scoped_ptr<google_apis::FileResource> sync_root_folder( 960 CreateFileResourceFromMetadata(sync_root.metadata)); 961 scoped_ptr<google_apis::FileResource> app_root_folder( 962 CreateFileResourceFromMetadata(app_root.metadata)); 963 964 ScopedVector<google_apis::FileResource> app_root_folders; 965 app_root_folders.push_back(app_root_folder.release()); 966 967 EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); 968 EXPECT_EQ(SYNC_STATUS_OK, PopulateInitialData( 969 largest_change_id, 970 *sync_root_folder, 971 app_root_folders)); 972 973 ResetTrackerID(&sync_root.tracker); 974 ResetTrackerID(&app_root.tracker); 975 app_root.tracker.set_parent_tracker_id(sync_root.tracker.tracker_id()); 976 977 VerifyTrackedFiles(tracked_files, arraysize(tracked_files)); 978 VerifyReloadConsistency(); 979} 980 981} // namespace drive_backend 982} // namespace sync_file_system 983