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