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