Home | History | Annotate | Download | only in glue
      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