1 // Copyright (c) 2012 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/glue/data_type_manager_impl.h" 6 7 #include "base/compiler_specific.h" 8 #include "base/message_loop/message_loop.h" 9 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/sync/glue/backend_data_type_configurer.h" 11 #include "chrome/browser/sync/glue/data_type_controller.h" 12 #include "chrome/browser/sync/glue/data_type_encryption_handler.h" 13 #include "chrome/browser/sync/glue/data_type_manager_observer.h" 14 #include "chrome/browser/sync/glue/failed_data_types_handler.h" 15 #include "chrome/browser/sync/glue/fake_data_type_controller.h" 16 #include "content/public/test/test_browser_thread.h" 17 #include "sync/internal_api/public/base/model_type.h" 18 #include "sync/internal_api/public/configure_reason.h" 19 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 namespace browser_sync { 23 24 using syncer::ModelType; 25 using syncer::ModelTypeSet; 26 using syncer::ModelTypeToString; 27 using syncer::BOOKMARKS; 28 using syncer::APPS; 29 using syncer::PASSWORDS; 30 using syncer::PREFERENCES; 31 using syncer::NIGORI; 32 using testing::_; 33 using testing::Mock; 34 using testing::ResultOf; 35 36 namespace { 37 38 // Used by SetConfigureDoneExpectation. 39 DataTypeManager::ConfigureStatus GetStatus( 40 const DataTypeManager::ConfigureResult& result) { 41 return result.status; 42 } 43 44 // Those types that are priority AND always configured. 45 syncer::ModelTypeSet HighPriorityTypes() { 46 syncer::ModelTypeSet result = syncer::PriorityCoreTypes(); 47 return result; 48 } 49 50 // Helper for unioning with priority types. 51 syncer::ModelTypeSet AddHighPriorityTypesTo(syncer::ModelTypeSet types) { 52 syncer::ModelTypeSet result = HighPriorityTypes(); 53 result.PutAll(types); 54 return result; 55 } 56 57 // Helper for unioning with core types. 58 syncer::ModelTypeSet AddLowPriorityCoreTypesTo(syncer::ModelTypeSet types) { 59 syncer::ModelTypeSet result = syncer::Difference(syncer::CoreTypes(), 60 syncer::PriorityCoreTypes()); 61 result.PutAll(types); 62 return result; 63 } 64 65 // Fake BackendDataTypeConfigurer implementation that simply stores away the 66 // callback passed into ConfigureDataTypes. 67 class FakeBackendDataTypeConfigurer : public BackendDataTypeConfigurer { 68 public: 69 FakeBackendDataTypeConfigurer() {} 70 virtual ~FakeBackendDataTypeConfigurer() {} 71 72 virtual void ConfigureDataTypes( 73 syncer::ConfigureReason reason, 74 const DataTypeConfigStateMap& config_state_map, 75 const base::Callback<void(ModelTypeSet, 76 ModelTypeSet)>& ready_task, 77 const base::Callback<void()>& retry_callback) OVERRIDE { 78 last_ready_task_ = ready_task; 79 80 if (!expected_configure_types_.Empty()) { 81 EXPECT_TRUE( 82 expected_configure_types_.Equals( 83 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map))) 84 << syncer::ModelTypeSetToString(expected_configure_types_) 85 << " v.s. " 86 << syncer::ModelTypeSetToString( 87 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map)); 88 } 89 } 90 91 base::Callback<void(ModelTypeSet, ModelTypeSet)> last_ready_task() const { 92 return last_ready_task_; 93 } 94 95 void set_expected_configure_types(syncer::ModelTypeSet types) { 96 expected_configure_types_ = types; 97 } 98 99 private: 100 base::Callback<void(ModelTypeSet, ModelTypeSet)> last_ready_task_; 101 syncer::ModelTypeSet expected_configure_types_; 102 }; 103 104 // Mock DataTypeManagerObserver implementation. 105 class DataTypeManagerObserverMock : public DataTypeManagerObserver { 106 public: 107 DataTypeManagerObserverMock() {} 108 virtual ~DataTypeManagerObserverMock() {} 109 110 MOCK_METHOD1(OnConfigureDone, 111 void(const browser_sync::DataTypeManager::ConfigureResult&)); 112 MOCK_METHOD0(OnConfigureRetry, void()); 113 MOCK_METHOD0(OnConfigureStart, void()); 114 }; 115 116 class FakeDataTypeEncryptionHandler : public DataTypeEncryptionHandler { 117 public: 118 FakeDataTypeEncryptionHandler(); 119 virtual ~FakeDataTypeEncryptionHandler(); 120 121 virtual bool IsPassphraseRequired() const OVERRIDE; 122 virtual syncer::ModelTypeSet GetEncryptedDataTypes() const OVERRIDE; 123 124 void set_passphrase_required(bool passphrase_required) { 125 passphrase_required_ = passphrase_required; 126 } 127 void set_encrypted_types(syncer::ModelTypeSet encrypted_types) { 128 encrypted_types_ = encrypted_types; 129 } 130 private: 131 bool passphrase_required_; 132 syncer::ModelTypeSet encrypted_types_; 133 }; 134 135 FakeDataTypeEncryptionHandler::FakeDataTypeEncryptionHandler() 136 : passphrase_required_(false) {} 137 FakeDataTypeEncryptionHandler::~FakeDataTypeEncryptionHandler() {} 138 139 bool FakeDataTypeEncryptionHandler::IsPassphraseRequired() const { 140 return passphrase_required_; 141 } 142 143 syncer::ModelTypeSet 144 FakeDataTypeEncryptionHandler::GetEncryptedDataTypes() const { 145 return encrypted_types_; 146 } 147 148 } // namespace 149 150 class TestDataTypeManager : public DataTypeManagerImpl { 151 public: 152 TestDataTypeManager( 153 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& 154 debug_info_listener, 155 BackendDataTypeConfigurer* configurer, 156 const DataTypeController::TypeMap* controllers, 157 const DataTypeEncryptionHandler* encryption_handler, 158 DataTypeManagerObserver* observer, 159 FailedDataTypesHandler* failed_data_types_handler) 160 : DataTypeManagerImpl(debug_info_listener, 161 controllers, 162 encryption_handler, 163 configurer, 164 observer, 165 failed_data_types_handler), 166 custom_priority_types_(HighPriorityTypes()) {} 167 168 void set_priority_types(const syncer::ModelTypeSet& priority_types) { 169 custom_priority_types_ = priority_types; 170 } 171 172 DataTypeManager::ConfigureResult configure_result() const { 173 return configure_result_; 174 } 175 176 virtual void OnModelAssociationDone( 177 const DataTypeManager::ConfigureResult& result) OVERRIDE { 178 configure_result_ = result; 179 DataTypeManagerImpl::OnModelAssociationDone(result); 180 } 181 182 private: 183 virtual syncer::ModelTypeSet GetPriorityTypes() const OVERRIDE { 184 return custom_priority_types_; 185 } 186 187 syncer::ModelTypeSet custom_priority_types_; 188 DataTypeManager::ConfigureResult configure_result_; 189 }; 190 191 // The actual test harness class, parametrized on nigori state (i.e., tests are 192 // run both configuring with nigori, and configuring without). 193 class SyncDataTypeManagerImplTest : public testing::Test { 194 public: 195 SyncDataTypeManagerImplTest() 196 : ui_thread_(content::BrowserThread::UI, &ui_loop_) {} 197 198 virtual ~SyncDataTypeManagerImplTest() { 199 } 200 201 protected: 202 virtual void SetUp() { 203 dtm_.reset( 204 new TestDataTypeManager( 205 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), 206 &configurer_, 207 &controllers_, 208 &encryption_handler_, 209 &observer_, 210 &failed_data_types_handler_)); 211 } 212 213 void SetConfigureStartExpectation() { 214 EXPECT_CALL(observer_, OnConfigureStart()); 215 } 216 217 void SetConfigureDoneExpectation(DataTypeManager::ConfigureStatus status) { 218 EXPECT_CALL(observer_, OnConfigureDone(ResultOf(&GetStatus, status))); 219 } 220 221 // Configure the given DTM with the given desired types. 222 void Configure(DataTypeManagerImpl* dtm, 223 const syncer::ModelTypeSet& desired_types) { 224 dtm->Configure(desired_types, syncer::CONFIGURE_REASON_RECONFIGURATION); 225 } 226 227 // Finish downloading for the given DTM. Should be done only after 228 // a call to Configure(). 229 void FinishDownload(const DataTypeManager& dtm, 230 ModelTypeSet types_to_configure, 231 ModelTypeSet failed_download_types) { 232 EXPECT_TRUE(DataTypeManager::DOWNLOAD_PENDING == dtm.state() || 233 DataTypeManager::CONFIGURING == dtm.state()); 234 ASSERT_FALSE(configurer_.last_ready_task().is_null()); 235 configurer_.last_ready_task().Run( 236 syncer::Difference(types_to_configure, failed_download_types), 237 failed_download_types); 238 } 239 240 // Adds a fake controller for the given type to |controllers_|. 241 // Should be called only before setting up the DTM. 242 void AddController(ModelType model_type) { 243 controllers_[model_type] = new FakeDataTypeController(model_type); 244 } 245 246 // Gets the fake controller for the given type, which should have 247 // been previously added via AddController(). 248 scoped_refptr<FakeDataTypeController> GetController( 249 ModelType model_type) const { 250 DataTypeController::TypeMap::const_iterator it = 251 controllers_.find(model_type); 252 if (it == controllers_.end()) { 253 return NULL; 254 } 255 return make_scoped_refptr( 256 static_cast<FakeDataTypeController*>(it->second.get())); 257 } 258 259 void FailEncryptionFor(syncer::ModelTypeSet encrypted_types) { 260 encryption_handler_.set_passphrase_required(true); 261 encryption_handler_.set_encrypted_types(encrypted_types); 262 } 263 264 base::MessageLoopForUI ui_loop_; 265 content::TestBrowserThread ui_thread_; 266 DataTypeController::TypeMap controllers_; 267 FakeBackendDataTypeConfigurer configurer_; 268 DataTypeManagerObserverMock observer_; 269 scoped_ptr<TestDataTypeManager> dtm_; 270 FailedDataTypesHandler failed_data_types_handler_; 271 FakeDataTypeEncryptionHandler encryption_handler_; 272 }; 273 274 // Set up a DTM with no controllers, configure it, finish downloading, 275 // and then stop it. 276 TEST_F(SyncDataTypeManagerImplTest, NoControllers) { 277 SetConfigureStartExpectation(); 278 SetConfigureDoneExpectation(DataTypeManager::OK); 279 280 Configure(dtm_.get(), ModelTypeSet()); 281 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 282 283 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 284 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 285 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 286 287 dtm_->Stop(); 288 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 289 } 290 291 // Set up a DTM with a single controller, configure it, finish 292 // downloading, finish starting the controller, and then stop the DTM. 293 TEST_F(SyncDataTypeManagerImplTest, ConfigureOne) { 294 AddController(BOOKMARKS); 295 296 SetConfigureStartExpectation(); 297 SetConfigureDoneExpectation(DataTypeManager::OK); 298 299 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 300 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 301 302 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 303 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 304 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 305 306 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 307 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 308 309 dtm_->Stop(); 310 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 311 } 312 313 // Set up a DTM with a single controller, configure it, but stop it 314 // before finishing the download. It should still be safe to run the 315 // download callback even after the DTM is stopped and destroyed. 316 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileDownloadPending) { 317 AddController(BOOKMARKS); 318 319 { 320 SetConfigureStartExpectation(); 321 SetConfigureDoneExpectation(DataTypeManager::ABORTED); 322 323 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 324 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 325 326 dtm_->Stop(); 327 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 328 } 329 330 configurer_.last_ready_task().Run(ModelTypeSet(BOOKMARKS), ModelTypeSet()); 331 } 332 333 // Set up a DTM with a single controller, configure it, finish 334 // downloading, but stop the DTM before the controller finishes 335 // starting up. It should still be safe to finish starting up the 336 // controller even after the DTM is stopped and destroyed. 337 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileStartingModel) { 338 AddController(BOOKMARKS); 339 340 { 341 SetConfigureStartExpectation(); 342 SetConfigureDoneExpectation(DataTypeManager::ABORTED); 343 344 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 345 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 346 347 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 348 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 349 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 350 351 dtm_->Stop(); 352 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 353 dtm_.reset(); 354 } 355 356 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 357 } 358 359 // Set up a DTM with a single controller, configure it, finish 360 // downloading, start the controller's model, but stop the DTM before 361 // the controller finishes starting up. It should still be safe to 362 // finish starting up the controller even after the DTM is stopped and 363 // destroyed. 364 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileAssociating) { 365 AddController(BOOKMARKS); 366 367 { 368 SetConfigureStartExpectation(); 369 SetConfigureDoneExpectation(DataTypeManager::ABORTED); 370 371 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 372 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 373 374 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 375 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 376 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 377 378 dtm_->Stop(); 379 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 380 dtm_.reset(); 381 } 382 383 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 384 } 385 386 // Set up a DTM with a single controller. Then: 387 // 388 // 1) Configure. 389 // 2) Finish the download for step 1. 390 // 3) Finish starting the controller with the NEEDS_CRYPTO status. 391 // 4) Complete download for the reconfiguration without the controller. 392 // 5) Stop the DTM. 393 TEST_F(SyncDataTypeManagerImplTest, OneWaitingForCrypto) { 394 AddController(PASSWORDS); 395 396 SetConfigureStartExpectation(); 397 SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS); 398 399 const ModelTypeSet types(PASSWORDS); 400 401 // Step 1. 402 Configure(dtm_.get(), types); 403 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 404 405 // Step 2. 406 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 407 FinishDownload(*dtm_, types, ModelTypeSet()); 408 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 409 410 // Step 3. 411 FailEncryptionFor(types); 412 GetController(PASSWORDS)->FinishStart(DataTypeController::NEEDS_CRYPTO); 413 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 414 415 // Step 4. 416 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 417 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 418 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 419 420 // Step 5. 421 dtm_->Stop(); 422 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 423 } 424 425 // Set up a DTM with two controllers. Then: 426 // 427 // 1) Configure with first controller. 428 // 2) Finish the download for step 1. 429 // 3) Finish starting the first controller. 430 // 4) Configure with both controllers. 431 // 5) Finish the download for step 4. 432 // 6) Finish starting the second controller. 433 // 7) Stop the DTM. 434 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneThenBoth) { 435 AddController(BOOKMARKS); 436 AddController(PREFERENCES); 437 438 SetConfigureStartExpectation(); 439 SetConfigureDoneExpectation(DataTypeManager::OK); 440 441 // Step 1. 442 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 443 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 444 445 // Step 2. 446 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 447 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 448 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 449 450 // Step 3. 451 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 452 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 453 454 Mock::VerifyAndClearExpectations(&observer_); 455 SetConfigureStartExpectation(); 456 SetConfigureDoneExpectation(DataTypeManager::OK); 457 458 // Step 4. 459 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 460 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 461 462 // Step 5. 463 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 464 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet()); 465 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 466 467 // Step 6. 468 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 469 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 470 471 // Step 7. 472 dtm_->Stop(); 473 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 474 } 475 476 // Set up a DTM with two controllers. Then: 477 // 478 // 1) Configure with first controller. 479 // 2) Finish the download for step 1. 480 // 3) Finish starting the first controller. 481 // 4) Configure with second controller. 482 // 5) Finish the download for step 4. 483 // 6) Finish starting the second controller. 484 // 7) Stop the DTM. 485 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneThenSwitch) { 486 AddController(BOOKMARKS); 487 AddController(PREFERENCES); 488 489 SetConfigureStartExpectation(); 490 SetConfigureDoneExpectation(DataTypeManager::OK); 491 492 // Step 1. 493 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 494 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 495 496 // Step 2. 497 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 498 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 499 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 500 501 // Step 3. 502 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 503 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 504 505 Mock::VerifyAndClearExpectations(&observer_); 506 SetConfigureStartExpectation(); 507 SetConfigureDoneExpectation(DataTypeManager::OK); 508 509 // Step 4. 510 Configure(dtm_.get(), ModelTypeSet(PREFERENCES)); 511 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 512 513 // Step 5. 514 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 515 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 516 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 517 518 // Step 6. 519 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 520 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 521 522 // Step 7. 523 dtm_->Stop(); 524 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 525 } 526 527 // Set up a DTM with two controllers. Then: 528 // 529 // 1) Configure with first controller. 530 // 2) Finish the download for step 1. 531 // 3) Configure with both controllers. 532 // 4) Finish starting the first controller. 533 // 5) Finish the download for step 3. 534 // 6) Finish starting the second controller. 535 // 7) Stop the DTM. 536 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileOneInFlight) { 537 AddController(BOOKMARKS); 538 AddController(PREFERENCES); 539 540 SetConfigureStartExpectation(); 541 SetConfigureDoneExpectation(DataTypeManager::OK); 542 543 // Step 1. 544 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 545 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 546 547 // Step 2. 548 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 549 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 550 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 551 552 // Step 3. 553 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 554 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 555 556 // Step 4. 557 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 558 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 559 560 // Step 5. 561 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 562 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet()); 563 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 564 565 // Step 6. 566 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 567 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 568 569 // Step 7. 570 dtm_->Stop(); 571 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 572 } 573 574 // Set up a DTM with one controller. Then configure, finish 575 // downloading, and start the controller with an unrecoverable error. 576 // The unrecoverable error should cause the DTM to stop. 577 TEST_F(SyncDataTypeManagerImplTest, OneFailingController) { 578 AddController(BOOKMARKS); 579 580 SetConfigureStartExpectation(); 581 SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR); 582 583 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 584 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 585 586 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 587 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 588 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 589 590 GetController(BOOKMARKS)->FinishStart( 591 DataTypeController::UNRECOVERABLE_ERROR); 592 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 593 } 594 595 // Set up a DTM with two controllers. Then: 596 // 597 // 1) Configure with both controllers. 598 // 2) Finish the download for step 1. 599 // 3) Finish starting the first controller successfully. 600 // 4) Finish starting the second controller with an unrecoverable error. 601 // 602 // The failure from step 4 should cause the DTM to stop. 603 TEST_F(SyncDataTypeManagerImplTest, SecondControllerFails) { 604 AddController(BOOKMARKS); 605 AddController(PREFERENCES); 606 607 SetConfigureStartExpectation(); 608 SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR); 609 610 // Step 1. 611 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 612 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 613 614 // Step 2. 615 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 616 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet()); 617 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 618 619 // Step 3. 620 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 621 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 622 623 // Step 4. 624 GetController(PREFERENCES)->FinishStart( 625 DataTypeController::UNRECOVERABLE_ERROR); 626 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 627 } 628 629 // Set up a DTM with two controllers. Then: 630 // 631 // 1) Configure with both controllers. 632 // 2) Finish the download for step 1. 633 // 3) Finish starting the first controller successfully. 634 // 4) Finish starting the second controller with an association failure. 635 // 5) Finish the purge/reconfigure without the failed type. 636 // 6) Stop the DTM. 637 // 638 // The association failure from step 3 should be ignored. 639 // 640 // TODO(akalin): Check that the data type that failed association is 641 // recorded in the CONFIGURE_DONE notification. 642 TEST_F(SyncDataTypeManagerImplTest, OneControllerFailsAssociation) { 643 AddController(BOOKMARKS); 644 AddController(PREFERENCES); 645 646 SetConfigureStartExpectation(); 647 SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS); 648 649 // Step 1. 650 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 651 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 652 653 // Step 2. 654 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 655 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet()); 656 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 657 658 // Step 3. 659 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 660 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 661 662 // Step 4. 663 GetController(PREFERENCES)->FinishStart( 664 DataTypeController::ASSOCIATION_FAILED); 665 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 666 667 // Step 5. 668 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 669 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 670 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 671 672 // Step 6. 673 dtm_->Stop(); 674 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 675 } 676 677 // Set up a DTM with two controllers. Then: 678 // 679 // 1) Configure with first controller. 680 // 2) Configure with both controllers. 681 // 3) Finish the download for step 1. 682 // 4) Finish the download for step 2. 683 // 5) Finish starting both controllers. 684 // 6) Stop the DTM. 685 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileDownloadPending) { 686 AddController(BOOKMARKS); 687 AddController(PREFERENCES); 688 689 SetConfigureStartExpectation(); 690 SetConfigureDoneExpectation(DataTypeManager::OK); 691 692 // Step 1. 693 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 694 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 695 696 // Step 2. 697 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 698 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 699 700 // Step 3. 701 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 702 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 703 704 // Step 4. 705 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 706 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet()); 707 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 708 709 // Step 5. 710 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 711 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 712 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 713 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 714 715 // Step 6. 716 dtm_->Stop(); 717 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 718 } 719 720 // Set up a DTM with two controllers. Then: 721 // 722 // 1) Configure with first controller. 723 // 2) Configure with both controllers. 724 // 3) Finish the download for step 1 with a failed data type. 725 // 4) Finish the download for step 2 successfully. 726 // 5) Finish starting both controllers. 727 // 6) Stop the DTM. 728 // 729 // The failure from step 3 should be ignored since there's a 730 // reconfigure pending from step 2. 731 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileDownloadPendingWithFailure) { 732 AddController(BOOKMARKS); 733 AddController(PREFERENCES); 734 735 SetConfigureStartExpectation(); 736 SetConfigureDoneExpectation(DataTypeManager::OK); 737 738 // Step 1. 739 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 740 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 741 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 742 743 // Step 2. 744 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 745 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 746 747 // Step 3. 748 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 749 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 750 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 751 752 // Step 4. 753 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet()); 754 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 755 756 // Step 5. 757 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 758 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 759 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 760 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 761 762 // Step 6. 763 dtm_->Stop(); 764 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 765 } 766 767 // Tests a Purge then Configure. This is similar to the sequence of 768 // operations that would be invoked by the BackendMigrator. 769 TEST_F(SyncDataTypeManagerImplTest, MigrateAll) { 770 AddController(BOOKMARKS); 771 772 SetConfigureStartExpectation(); 773 SetConfigureDoneExpectation(DataTypeManager::OK); 774 775 // Initial setup. 776 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 777 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 778 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 779 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 780 781 // We've now configured bookmarks and (implicitly) the control types. 782 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 783 Mock::VerifyAndClearExpectations(&observer_); 784 785 // Pretend we were told to migrate all types. 786 ModelTypeSet to_migrate; 787 to_migrate.Put(BOOKMARKS); 788 to_migrate.PutAll(syncer::ControlTypes()); 789 790 SetConfigureStartExpectation(); 791 SetConfigureDoneExpectation(DataTypeManager::OK); 792 dtm_->PurgeForMigration(to_migrate, 793 syncer::CONFIGURE_REASON_MIGRATION); 794 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 795 796 // The DTM will call ConfigureDataTypes(), even though it is unnecessary. 797 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 798 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 799 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 800 Mock::VerifyAndClearExpectations(&observer_); 801 802 // Re-enable the migrated types. 803 SetConfigureStartExpectation(); 804 SetConfigureDoneExpectation(DataTypeManager::OK); 805 Configure(dtm_.get(), to_migrate); 806 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 807 FinishDownload(*dtm_, to_migrate, ModelTypeSet()); 808 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 809 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 810 } 811 812 // Test receipt of a Configure request while a purge is in flight. 813 TEST_F(SyncDataTypeManagerImplTest, ConfigureDuringPurge) { 814 AddController(BOOKMARKS); 815 AddController(PREFERENCES); 816 817 // Initial configure. 818 SetConfigureStartExpectation(); 819 SetConfigureDoneExpectation(DataTypeManager::OK); 820 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS)); 821 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 822 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 823 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 824 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 825 Mock::VerifyAndClearExpectations(&observer_); 826 827 // Purge the Nigori type. 828 SetConfigureStartExpectation(); 829 dtm_->PurgeForMigration(ModelTypeSet(NIGORI), 830 syncer::CONFIGURE_REASON_MIGRATION); 831 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 832 Mock::VerifyAndClearExpectations(&observer_); 833 834 // Before the backend configuration completes, ask for a different 835 // set of types. This request asks for 836 // - BOOKMARKS: which is redundant because it was already enabled, 837 // - PREFERENCES: which is new and will need to be downloaded, and 838 // - NIGORI: (added implicitly because it is a control type) which 839 // the DTM is part-way through purging. 840 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 841 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 842 843 // Invoke the callback we've been waiting for since we asked to purge NIGORI. 844 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 845 Mock::VerifyAndClearExpectations(&observer_); 846 847 SetConfigureDoneExpectation(DataTypeManager::OK); 848 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 849 850 // Now invoke the callback for the second configure request. 851 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 852 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet()); 853 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 854 855 // Start the preferences controller. We don't need to start controller for 856 // the NIGORI because it has none. We don't need to start the controller for 857 // the BOOKMARKS because it was never stopped. 858 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 859 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 860 } 861 862 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfiguration) { 863 AddController(BOOKMARKS); 864 AddController(PREFERENCES); 865 866 dtm_->set_priority_types( 867 AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES))); 868 869 // Initial configure. 870 SetConfigureStartExpectation(); 871 SetConfigureDoneExpectation(DataTypeManager::OK); 872 873 // Initially only PREFERENCES is configured. 874 configurer_.set_expected_configure_types( 875 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES))); 876 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 877 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 878 879 // BOOKMARKS is configured after download of PREFERENCES finishes. 880 configurer_.set_expected_configure_types( 881 AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS))); 882 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 883 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 884 885 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 886 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 887 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 888 889 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 890 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 891 } 892 893 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationReconfigure) { 894 AddController(BOOKMARKS); 895 AddController(PREFERENCES); 896 AddController(APPS); 897 898 dtm_->set_priority_types( 899 AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES))); 900 901 // Initial configure. 902 SetConfigureStartExpectation(); 903 SetConfigureDoneExpectation(DataTypeManager::OK); 904 905 // Reconfigure while associating PREFERENCES and downloading BOOKMARKS. 906 configurer_.set_expected_configure_types( 907 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES))); 908 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 909 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 910 911 configurer_.set_expected_configure_types( 912 AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS))); 913 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 914 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 915 916 // Enable syncing for APPS. 917 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES, APPS)); 918 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 919 920 // Reconfiguration starts after downloading and association of previous 921 // types finish. 922 configurer_.set_expected_configure_types( 923 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES))); 924 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 925 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 926 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 927 928 configurer_.set_expected_configure_types( 929 AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS, APPS))); 930 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 931 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 932 933 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, APPS), ModelTypeSet()); 934 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 935 936 // Skip calling FinishStart() for PREFENCES because it's already started in 937 // first configuration. 938 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 939 GetController(APPS)->FinishStart(DataTypeController::OK); 940 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 941 } 942 943 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationStop) { 944 AddController(BOOKMARKS); 945 AddController(PREFERENCES); 946 947 dtm_->set_priority_types( 948 AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES))); 949 950 // Initial configure. 951 SetConfigureStartExpectation(); 952 SetConfigureDoneExpectation(DataTypeManager::ABORTED); 953 954 // Initially only PREFERENCES is configured. 955 configurer_.set_expected_configure_types( 956 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES))); 957 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 958 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 959 960 // BOOKMARKS is configured after download of PREFERENCES finishes. 961 configurer_.set_expected_configure_types( 962 AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS))); 963 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 964 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 965 966 // PERFERENCES controller is associating while BOOKMARKS is downloading. 967 EXPECT_EQ(DataTypeController::ASSOCIATING, 968 GetController(PREFERENCES)->state()); 969 EXPECT_EQ(DataTypeController::MODEL_LOADED, 970 GetController(BOOKMARKS)->state()); 971 972 dtm_->Stop(); 973 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 974 EXPECT_EQ(DataTypeController::NOT_RUNNING, 975 GetController(PREFERENCES)->state()); 976 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state()); 977 } 978 979 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationDownloadError) { 980 AddController(BOOKMARKS); 981 AddController(PREFERENCES); 982 983 dtm_->set_priority_types( 984 AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES))); 985 986 // Initial configure. 987 SetConfigureStartExpectation(); 988 SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR); 989 990 // Initially only PREFERENCES is configured. 991 configurer_.set_expected_configure_types( 992 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES))); 993 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 994 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 995 996 // BOOKMARKS is configured after download of PREFERENCES finishes. 997 configurer_.set_expected_configure_types( 998 AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS))); 999 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 1000 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 1001 1002 // PERFERENCES controller is associating while BOOKMARKS is downloading. 1003 EXPECT_EQ(DataTypeController::ASSOCIATING, 1004 GetController(PREFERENCES)->state()); 1005 EXPECT_EQ(DataTypeController::MODEL_LOADED, 1006 GetController(BOOKMARKS)->state()); 1007 1008 // Make BOOKMARKS download fail. 1009 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet(BOOKMARKS)); 1010 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state()); 1011 EXPECT_EQ(DataTypeController::NOT_RUNNING, 1012 GetController(PREFERENCES)->state()); 1013 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state()); 1014 } 1015 1016 TEST_F(SyncDataTypeManagerImplTest, HighPriorityAssociationFailure) { 1017 AddController(PREFERENCES); // Will fail. 1018 AddController(BOOKMARKS); // Will succeed. 1019 1020 dtm_->set_priority_types( 1021 AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES))); 1022 1023 // Initial configure. 1024 SetConfigureStartExpectation(); 1025 SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS); 1026 1027 // Initially only PREFERENCES is configured. 1028 configurer_.set_expected_configure_types( 1029 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES))); 1030 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 1031 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 1032 1033 // BOOKMARKS is configured after download of PREFERENCES finishes. 1034 configurer_.set_expected_configure_types( 1035 AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS))); 1036 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 1037 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 1038 1039 // PERFERENCES controller is associating while BOOKMARKS is downloading. 1040 EXPECT_EQ(DataTypeController::ASSOCIATING, 1041 GetController(PREFERENCES)->state()); 1042 EXPECT_EQ(DataTypeController::MODEL_LOADED, 1043 GetController(BOOKMARKS)->state()); 1044 1045 // Make PREFERENCES association fail. 1046 GetController(PREFERENCES)->FinishStart( 1047 DataTypeController::ASSOCIATION_FAILED); 1048 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 1049 1050 // Reconfigure without PREFERENCES after the BOOKMARKS download completes, 1051 // then reconfigure with BOOKMARKS. 1052 configurer_.set_expected_configure_types(HighPriorityTypes()); 1053 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 1054 configurer_.set_expected_configure_types( 1055 AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS))); 1056 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 1057 1058 // Reconfigure with BOOKMARKS. 1059 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 1060 EXPECT_EQ(DataTypeController::ASSOCIATING, 1061 GetController(BOOKMARKS)->state()); 1062 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK); 1063 1064 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 1065 EXPECT_EQ(DataTypeController::NOT_RUNNING, 1066 GetController(PREFERENCES)->state()); 1067 EXPECT_EQ(DataTypeController::RUNNING, GetController(BOOKMARKS)->state()); 1068 } 1069 1070 TEST_F(SyncDataTypeManagerImplTest, LowPriorityAssociationFailure) { 1071 AddController(PREFERENCES); // Will succeed. 1072 AddController(BOOKMARKS); // Will fail. 1073 1074 dtm_->set_priority_types( 1075 AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES))); 1076 1077 // Initial configure. 1078 SetConfigureStartExpectation(); 1079 SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS); 1080 1081 // Initially only PREFERENCES is configured. 1082 configurer_.set_expected_configure_types( 1083 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES))); 1084 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES)); 1085 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 1086 1087 // BOOKMARKS is configured after download of PREFERENCES finishes. 1088 configurer_.set_expected_configure_types( 1089 AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS))); 1090 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 1091 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state()); 1092 1093 // PERFERENCES controller is associating while BOOKMARKS is downloading. 1094 EXPECT_EQ(DataTypeController::ASSOCIATING, 1095 GetController(PREFERENCES)->state()); 1096 EXPECT_EQ(DataTypeController::MODEL_LOADED, 1097 GetController(BOOKMARKS)->state()); 1098 1099 // BOOKMARKS finishes downloading and PREFERENCES finishes associating. 1100 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet()); 1101 GetController(PREFERENCES)->FinishStart(DataTypeController::OK); 1102 EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state()); 1103 1104 // Make BOOKMARKS association fail, which triggers reconfigure with only 1105 // PREFERENCES. 1106 configurer_.set_expected_configure_types( 1107 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES))); 1108 GetController(BOOKMARKS)->FinishStart(DataTypeController::ASSOCIATION_FAILED); 1109 EXPECT_EQ(DataTypeController::NOT_RUNNING, 1110 GetController(BOOKMARKS)->state()); 1111 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state()); 1112 1113 // Finish configuration with only PREFERENCES. 1114 configurer_.set_expected_configure_types( 1115 AddLowPriorityCoreTypesTo(ModelTypeSet())); 1116 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet()); 1117 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); 1118 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state()); 1119 EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state()); 1120 EXPECT_EQ(DataTypeController::NOT_RUNNING, 1121 GetController(BOOKMARKS)->state()); 1122 } 1123 1124 } // namespace browser_sync 1125