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  private:
    173   virtual syncer::ModelTypeSet GetPriorityTypes() const OVERRIDE {
    174     return custom_priority_types_;
    175   }
    176 
    177   syncer::ModelTypeSet custom_priority_types_;
    178 };
    179 
    180 // The actual test harness class, parametrized on nigori state (i.e., tests are
    181 // run both configuring with nigori, and configuring without).
    182 class SyncDataTypeManagerImplTest : public testing::Test {
    183  public:
    184   SyncDataTypeManagerImplTest()
    185       : ui_thread_(content::BrowserThread::UI, &ui_loop_) {}
    186 
    187   virtual ~SyncDataTypeManagerImplTest() {
    188   }
    189 
    190  protected:
    191   virtual void SetUp() {
    192    dtm_.reset(
    193        new TestDataTypeManager(
    194            syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
    195            &configurer_,
    196            &controllers_,
    197            &encryption_handler_,
    198            &observer_,
    199            &failed_data_types_handler_));
    200   }
    201 
    202   void SetConfigureStartExpectation() {
    203     EXPECT_CALL(observer_, OnConfigureStart());
    204   }
    205 
    206   void SetConfigureDoneExpectation(DataTypeManager::ConfigureStatus status) {
    207     EXPECT_CALL(observer_, OnConfigureDone(ResultOf(&GetStatus, status)));
    208   }
    209 
    210   // Configure the given DTM with the given desired types.
    211   void Configure(DataTypeManagerImpl* dtm,
    212                  const syncer::ModelTypeSet& desired_types) {
    213     dtm->Configure(desired_types, syncer::CONFIGURE_REASON_RECONFIGURATION);
    214   }
    215 
    216   // Finish downloading for the given DTM. Should be done only after
    217   // a call to Configure().
    218   void FinishDownload(const DataTypeManager& dtm,
    219                       ModelTypeSet types_to_configure,
    220                       ModelTypeSet failed_download_types) {
    221     EXPECT_TRUE(DataTypeManager::DOWNLOAD_PENDING == dtm.state() ||
    222                 DataTypeManager::CONFIGURING == dtm.state());
    223     ASSERT_FALSE(configurer_.last_ready_task().is_null());
    224     configurer_.last_ready_task().Run(
    225         syncer::Difference(types_to_configure, failed_download_types),
    226         failed_download_types);
    227   }
    228 
    229   // Adds a fake controller for the given type to |controllers_|.
    230   // Should be called only before setting up the DTM.
    231   void AddController(ModelType model_type) {
    232     controllers_[model_type] = new FakeDataTypeController(model_type);
    233   }
    234 
    235   // Gets the fake controller for the given type, which should have
    236   // been previously added via AddController().
    237   scoped_refptr<FakeDataTypeController> GetController(
    238       ModelType model_type) const {
    239     DataTypeController::TypeMap::const_iterator it =
    240         controllers_.find(model_type);
    241     if (it == controllers_.end()) {
    242       return NULL;
    243     }
    244     return make_scoped_refptr(
    245         static_cast<FakeDataTypeController*>(it->second.get()));
    246   }
    247 
    248   void FailEncryptionFor(syncer::ModelTypeSet encrypted_types) {
    249     encryption_handler_.set_passphrase_required(true);
    250     encryption_handler_.set_encrypted_types(encrypted_types);
    251   }
    252 
    253   base::MessageLoopForUI ui_loop_;
    254   content::TestBrowserThread ui_thread_;
    255   DataTypeController::TypeMap controllers_;
    256   FakeBackendDataTypeConfigurer configurer_;
    257   DataTypeManagerObserverMock observer_;
    258   scoped_ptr<TestDataTypeManager> dtm_;
    259   FailedDataTypesHandler failed_data_types_handler_;
    260   FakeDataTypeEncryptionHandler encryption_handler_;
    261 };
    262 
    263 // Set up a DTM with no controllers, configure it, finish downloading,
    264 // and then stop it.
    265 TEST_F(SyncDataTypeManagerImplTest, NoControllers) {
    266   SetConfigureStartExpectation();
    267   SetConfigureDoneExpectation(DataTypeManager::OK);
    268 
    269   Configure(dtm_.get(), ModelTypeSet());
    270   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    271 
    272   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    273   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    274   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    275 
    276   dtm_->Stop();
    277   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    278 }
    279 
    280 // Set up a DTM with a single controller, configure it, finish
    281 // downloading, finish starting the controller, and then stop the DTM.
    282 TEST_F(SyncDataTypeManagerImplTest, ConfigureOne) {
    283   AddController(BOOKMARKS);
    284 
    285   SetConfigureStartExpectation();
    286   SetConfigureDoneExpectation(DataTypeManager::OK);
    287 
    288   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    289   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    290 
    291   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    292   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    293   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    294 
    295   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    296   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    297 
    298   dtm_->Stop();
    299   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    300 }
    301 
    302 // Set up a DTM with 2 controllers. configure it. One of them finishes loading
    303 // after the  timeout. Make sure eventually all are configured.
    304 TEST_F(SyncDataTypeManagerImplTest, ConfigureSlowLoadingType) {
    305   AddController(BOOKMARKS);
    306   AddController(APPS);
    307 
    308   GetController(BOOKMARKS)->SetDelayModelLoad();
    309 
    310   SetConfigureStartExpectation();
    311   SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
    312 
    313   syncer::ModelTypeSet types;
    314   types.Put(BOOKMARKS);
    315   types.Put(APPS);
    316 
    317   Configure(dtm_.get(), types);
    318   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    319 
    320   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    321   FinishDownload(*dtm_, types, ModelTypeSet());
    322   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    323 
    324   base::OneShotTimer<ModelAssociationManager>* timer =
    325     dtm_->GetModelAssociationManagerForTesting()->GetTimerForTesting();
    326 
    327   base::Closure task = timer->user_task();
    328   timer->Stop();
    329   task.Run();
    330 
    331   SetConfigureDoneExpectation(DataTypeManager::OK);
    332   GetController(APPS)->FinishStart(DataTypeController::OK);
    333 
    334   SetConfigureStartExpectation();
    335   GetController(BOOKMARKS)->SimulateModelLoadFinishing();
    336 
    337   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    338   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    339   GetController(BOOKMARKS)->SimulateModelLoadFinishing();
    340 
    341   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    342   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    343 
    344   dtm_->Stop();
    345   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    346 }
    347 
    348 
    349 // Set up a DTM with a single controller, configure it, but stop it
    350 // before finishing the download.  It should still be safe to run the
    351 // download callback even after the DTM is stopped and destroyed.
    352 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileDownloadPending) {
    353   AddController(BOOKMARKS);
    354 
    355   {
    356     SetConfigureStartExpectation();
    357     SetConfigureDoneExpectation(DataTypeManager::ABORTED);
    358 
    359     Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    360     EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    361 
    362     dtm_->Stop();
    363     EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    364   }
    365 
    366   configurer_.last_ready_task().Run(ModelTypeSet(BOOKMARKS), ModelTypeSet());
    367 }
    368 
    369 // Set up a DTM with a single controller, configure it, finish
    370 // downloading, but stop the DTM before the controller finishes
    371 // starting up.  It should still be safe to finish starting up the
    372 // controller even after the DTM is stopped and destroyed.
    373 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileStartingModel) {
    374   AddController(BOOKMARKS);
    375 
    376   {
    377     SetConfigureStartExpectation();
    378     SetConfigureDoneExpectation(DataTypeManager::ABORTED);
    379 
    380     Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    381     EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    382 
    383     FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    384     FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    385     EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    386 
    387     dtm_->Stop();
    388     EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    389     dtm_.reset();
    390   }
    391 
    392   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    393 }
    394 
    395 // Set up a DTM with a single controller, configure it, finish
    396 // downloading, start the controller's model, but stop the DTM before
    397 // the controller finishes starting up.  It should still be safe to
    398 // finish starting up the controller even after the DTM is stopped and
    399 // destroyed.
    400 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileAssociating) {
    401   AddController(BOOKMARKS);
    402 
    403   {
    404     SetConfigureStartExpectation();
    405     SetConfigureDoneExpectation(DataTypeManager::ABORTED);
    406 
    407     Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    408     EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    409 
    410     FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    411     FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    412     EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    413 
    414     dtm_->Stop();
    415     EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    416     dtm_.reset();
    417   }
    418 
    419   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    420 }
    421 
    422 // Set up a DTM with a single controller.  Then:
    423 //
    424 //   1) Configure.
    425 //   2) Finish the download for step 1.
    426 //   3) Finish starting the controller with the NEEDS_CRYPTO status.
    427 //   4) Complete download for the reconfiguration without the controller.
    428 //   5) Stop the DTM.
    429 TEST_F(SyncDataTypeManagerImplTest, OneWaitingForCrypto) {
    430   AddController(PASSWORDS);
    431 
    432   SetConfigureStartExpectation();
    433   SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
    434 
    435   const ModelTypeSet types(PASSWORDS);
    436 
    437   // Step 1.
    438   Configure(dtm_.get(), types);
    439   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    440 
    441   // Step 2.
    442   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    443   FinishDownload(*dtm_, types, ModelTypeSet());
    444   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    445 
    446   // Step 3.
    447   FailEncryptionFor(types);
    448   GetController(PASSWORDS)->FinishStart(DataTypeController::NEEDS_CRYPTO);
    449   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    450 
    451   // Step 4.
    452   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    453   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    454   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    455 
    456   // Step 5.
    457   dtm_->Stop();
    458   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    459 }
    460 
    461 // Set up a DTM with two controllers.  Then:
    462 //
    463 //   1) Configure with first controller.
    464 //   2) Finish the download for step 1.
    465 //   3) Finish starting the first controller.
    466 //   4) Configure with both controllers.
    467 //   5) Finish the download for step 4.
    468 //   6) Finish starting the second controller.
    469 //   7) Stop the DTM.
    470 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneThenBoth) {
    471   AddController(BOOKMARKS);
    472   AddController(PREFERENCES);
    473 
    474   SetConfigureStartExpectation();
    475   SetConfigureDoneExpectation(DataTypeManager::OK);
    476 
    477   // Step 1.
    478   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    479   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    480 
    481   // Step 2.
    482   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    483   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    484   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    485 
    486   // Step 3.
    487   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    488   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    489 
    490   Mock::VerifyAndClearExpectations(&observer_);
    491   SetConfigureStartExpectation();
    492   SetConfigureDoneExpectation(DataTypeManager::OK);
    493 
    494   // Step 4.
    495   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    496   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    497 
    498   // Step 5.
    499   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    500   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
    501   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    502 
    503   // Step 6.
    504   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
    505   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    506 
    507   // Step 7.
    508   dtm_->Stop();
    509   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    510 }
    511 
    512 // Set up a DTM with two controllers.  Then:
    513 //
    514 //   1) Configure with first controller.
    515 //   2) Finish the download for step 1.
    516 //   3) Finish starting the first controller.
    517 //   4) Configure with second controller.
    518 //   5) Finish the download for step 4.
    519 //   6) Finish starting the second controller.
    520 //   7) Stop the DTM.
    521 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneThenSwitch) {
    522   AddController(BOOKMARKS);
    523   AddController(PREFERENCES);
    524 
    525   SetConfigureStartExpectation();
    526   SetConfigureDoneExpectation(DataTypeManager::OK);
    527 
    528   // Step 1.
    529   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    530   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    531 
    532   // Step 2.
    533   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    534   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    535   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    536 
    537   // Step 3.
    538   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    539   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    540 
    541   Mock::VerifyAndClearExpectations(&observer_);
    542   SetConfigureStartExpectation();
    543   SetConfigureDoneExpectation(DataTypeManager::OK);
    544 
    545   // Step 4.
    546   Configure(dtm_.get(), ModelTypeSet(PREFERENCES));
    547   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    548 
    549   // Step 5.
    550   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    551   FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
    552   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    553 
    554   // Step 6.
    555   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
    556   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    557 
    558   // Step 7.
    559   dtm_->Stop();
    560   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    561 }
    562 
    563 // Set up a DTM with two controllers.  Then:
    564 //
    565 //   1) Configure with first controller.
    566 //   2) Finish the download for step 1.
    567 //   3) Configure with both controllers.
    568 //   4) Finish starting the first controller.
    569 //   5) Finish the download for step 3.
    570 //   6) Finish starting the second controller.
    571 //   7) Stop the DTM.
    572 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileOneInFlight) {
    573   AddController(BOOKMARKS);
    574   AddController(PREFERENCES);
    575 
    576   SetConfigureStartExpectation();
    577   SetConfigureDoneExpectation(DataTypeManager::OK);
    578 
    579   // Step 1.
    580   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    581   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    582 
    583   // Step 2.
    584   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    585   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    586   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    587 
    588   // Step 3.
    589   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    590   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    591 
    592   // Step 4.
    593   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    594   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    595 
    596   // Step 5.
    597   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    598   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
    599   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    600 
    601   // Step 6.
    602   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
    603   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    604 
    605   // Step 7.
    606   dtm_->Stop();
    607   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    608 }
    609 
    610 // Set up a DTM with one controller.  Then configure, finish
    611 // downloading, and start the controller with an unrecoverable error.
    612 // The unrecoverable error should cause the DTM to stop.
    613 TEST_F(SyncDataTypeManagerImplTest, OneFailingController) {
    614   AddController(BOOKMARKS);
    615 
    616   SetConfigureStartExpectation();
    617   SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
    618 
    619   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    620   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    621 
    622   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    623   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    624   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    625 
    626   GetController(BOOKMARKS)->FinishStart(
    627       DataTypeController::UNRECOVERABLE_ERROR);
    628   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    629 }
    630 
    631 // Set up a DTM with two controllers.  Then:
    632 //
    633 //   1) Configure with both controllers.
    634 //   2) Finish the download for step 1.
    635 //   3) Finish starting the first controller successfully.
    636 //   4) Finish starting the second controller with an unrecoverable error.
    637 //
    638 // The failure from step 4 should cause the DTM to stop.
    639 TEST_F(SyncDataTypeManagerImplTest, SecondControllerFails) {
    640   AddController(BOOKMARKS);
    641   AddController(PREFERENCES);
    642 
    643   SetConfigureStartExpectation();
    644   SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
    645 
    646   // Step 1.
    647   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    648   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    649 
    650   // Step 2.
    651   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    652   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
    653   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    654 
    655   // Step 3.
    656   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    657   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    658 
    659   // Step 4.
    660   GetController(PREFERENCES)->FinishStart(
    661       DataTypeController::UNRECOVERABLE_ERROR);
    662   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    663 }
    664 
    665 // Set up a DTM with two controllers.  Then:
    666 //
    667 //   1) Configure with both controllers.
    668 //   2) Finish the download for step 1.
    669 //   3) Finish starting the first controller successfully.
    670 //   4) Finish starting the second controller with an association failure.
    671 //   5) Finish the purge/reconfigure without the failed type.
    672 //   6) Stop the DTM.
    673 //
    674 // The association failure from step 3 should be ignored.
    675 //
    676 // TODO(akalin): Check that the data type that failed association is
    677 // recorded in the CONFIGURE_DONE notification.
    678 TEST_F(SyncDataTypeManagerImplTest, OneControllerFailsAssociation) {
    679   AddController(BOOKMARKS);
    680   AddController(PREFERENCES);
    681 
    682   SetConfigureStartExpectation();
    683   SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
    684 
    685   // Step 1.
    686   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    687   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    688 
    689   // Step 2.
    690   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    691   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
    692   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    693 
    694   // Step 3.
    695   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    696   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    697 
    698   // Step 4.
    699   GetController(PREFERENCES)->FinishStart(
    700       DataTypeController::ASSOCIATION_FAILED);
    701   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    702 
    703   // Step 5.
    704   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    705   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    706   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    707 
    708   // Step 6.
    709   dtm_->Stop();
    710   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    711 }
    712 
    713 // Set up a DTM with two controllers.  Then:
    714 //
    715 //   1) Configure with first controller.
    716 //   2) Configure with both controllers.
    717 //   3) Finish the download for step 1.
    718 //   4) Finish the download for step 2.
    719 //   5) Finish starting both controllers.
    720 //   6) Stop the DTM.
    721 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileDownloadPending) {
    722   AddController(BOOKMARKS);
    723   AddController(PREFERENCES);
    724 
    725   SetConfigureStartExpectation();
    726   SetConfigureDoneExpectation(DataTypeManager::OK);
    727 
    728   // Step 1.
    729   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    730   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    731 
    732   // Step 2.
    733   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    734   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    735 
    736   // Step 3.
    737   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    738   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    739 
    740   // Step 4.
    741   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    742   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
    743   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    744 
    745   // Step 5.
    746   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    747   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    748   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
    749   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    750 
    751   // Step 6.
    752   dtm_->Stop();
    753   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    754 }
    755 
    756 // Set up a DTM with two controllers.  Then:
    757 //
    758 //   1) Configure with first controller.
    759 //   2) Configure with both controllers.
    760 //   3) Finish the download for step 1 with a failed data type.
    761 //   4) Finish the download for step 2 successfully.
    762 //   5) Finish starting both controllers.
    763 //   6) Stop the DTM.
    764 //
    765 // The failure from step 3 should be ignored since there's a
    766 // reconfigure pending from step 2.
    767 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileDownloadPendingWithFailure) {
    768   AddController(BOOKMARKS);
    769   AddController(PREFERENCES);
    770 
    771   SetConfigureStartExpectation();
    772   SetConfigureDoneExpectation(DataTypeManager::OK);
    773 
    774   // Step 1.
    775   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    776   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    777   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    778 
    779   // Step 2.
    780   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    781   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    782 
    783   // Step 3.
    784   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    785   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    786   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    787 
    788   // Step 4.
    789   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
    790   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    791 
    792   // Step 5.
    793   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    794   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    795   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
    796   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    797 
    798   // Step 6.
    799   dtm_->Stop();
    800   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
    801 }
    802 
    803 // Tests a Purge then Configure.  This is similar to the sequence of
    804 // operations that would be invoked by the BackendMigrator.
    805 TEST_F(SyncDataTypeManagerImplTest, MigrateAll) {
    806   AddController(BOOKMARKS);
    807 
    808   SetConfigureStartExpectation();
    809   SetConfigureDoneExpectation(DataTypeManager::OK);
    810 
    811   // Initial setup.
    812   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    813   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    814   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    815   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    816 
    817   // We've now configured bookmarks and (implicitly) the control types.
    818   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    819   Mock::VerifyAndClearExpectations(&observer_);
    820 
    821   // Pretend we were told to migrate all types.
    822   ModelTypeSet to_migrate;
    823   to_migrate.Put(BOOKMARKS);
    824   to_migrate.PutAll(syncer::ControlTypes());
    825 
    826   SetConfigureStartExpectation();
    827   SetConfigureDoneExpectation(DataTypeManager::OK);
    828   dtm_->PurgeForMigration(to_migrate,
    829                           syncer::CONFIGURE_REASON_MIGRATION);
    830   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    831 
    832   // The DTM will call ConfigureDataTypes(), even though it is unnecessary.
    833   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    834   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    835   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    836   Mock::VerifyAndClearExpectations(&observer_);
    837 
    838   // Re-enable the migrated types.
    839   SetConfigureStartExpectation();
    840   SetConfigureDoneExpectation(DataTypeManager::OK);
    841   Configure(dtm_.get(), to_migrate);
    842   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    843   FinishDownload(*dtm_, to_migrate, ModelTypeSet());
    844   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    845   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    846 }
    847 
    848 // Test receipt of a Configure request while a purge is in flight.
    849 TEST_F(SyncDataTypeManagerImplTest, ConfigureDuringPurge) {
    850   AddController(BOOKMARKS);
    851   AddController(PREFERENCES);
    852 
    853   // Initial configure.
    854   SetConfigureStartExpectation();
    855   SetConfigureDoneExpectation(DataTypeManager::OK);
    856   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
    857   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    858   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    859   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    860   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    861   Mock::VerifyAndClearExpectations(&observer_);
    862 
    863   // Purge the Nigori type.
    864   SetConfigureStartExpectation();
    865   dtm_->PurgeForMigration(ModelTypeSet(NIGORI),
    866                           syncer::CONFIGURE_REASON_MIGRATION);
    867   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    868   Mock::VerifyAndClearExpectations(&observer_);
    869 
    870   // Before the backend configuration completes, ask for a different
    871   // set of types.  This request asks for
    872   // - BOOKMARKS: which is redundant because it was already enabled,
    873   // - PREFERENCES: which is new and will need to be downloaded, and
    874   // - NIGORI: (added implicitly because it is a control type) which
    875   //   the DTM is part-way through purging.
    876   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    877   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    878 
    879   // Invoke the callback we've been waiting for since we asked to purge NIGORI.
    880   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    881   Mock::VerifyAndClearExpectations(&observer_);
    882 
    883   SetConfigureDoneExpectation(DataTypeManager::OK);
    884   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    885 
    886   // Now invoke the callback for the second configure request.
    887   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
    888   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
    889   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    890 
    891   // Start the preferences controller.  We don't need to start controller for
    892   // the NIGORI because it has none.  We don't need to start the controller for
    893   // the BOOKMARKS because it was never stopped.
    894   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
    895   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    896 }
    897 
    898 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfiguration) {
    899   AddController(BOOKMARKS);
    900   AddController(PREFERENCES);
    901 
    902   dtm_->set_priority_types(
    903       AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
    904 
    905   // Initial configure.
    906   SetConfigureStartExpectation();
    907   SetConfigureDoneExpectation(DataTypeManager::OK);
    908 
    909   // Initially only PREFERENCES is configured.
    910   configurer_.set_expected_configure_types(
    911       AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
    912   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    913   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    914 
    915   // BOOKMARKS is configured after download of PREFERENCES finishes.
    916   configurer_.set_expected_configure_types(
    917       AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS)));
    918   FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
    919   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    920 
    921   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    922   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
    923   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    924 
    925   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    926   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    927 }
    928 
    929 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationReconfigure) {
    930   AddController(BOOKMARKS);
    931   AddController(PREFERENCES);
    932   AddController(APPS);
    933 
    934   dtm_->set_priority_types(
    935       AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
    936 
    937   // Initial configure.
    938   SetConfigureStartExpectation();
    939   SetConfigureDoneExpectation(DataTypeManager::OK);
    940 
    941   // Reconfigure while associating PREFERENCES and downloading BOOKMARKS.
    942   configurer_.set_expected_configure_types(
    943       AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
    944   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
    945   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    946 
    947   configurer_.set_expected_configure_types(
    948       AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS)));
    949   FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
    950   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    951 
    952   // Enable syncing for APPS.
    953   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES, APPS));
    954   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    955 
    956   // Reconfiguration starts after downloading and association of previous
    957   // types finish.
    958   configurer_.set_expected_configure_types(
    959       AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
    960   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
    961   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
    962   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
    963 
    964   configurer_.set_expected_configure_types(
    965       AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS, APPS)));
    966   FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
    967   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    968 
    969   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, APPS), ModelTypeSet());
    970   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
    971 
    972   // Skip calling FinishStart() for PREFENCES because it's already started in
    973   // first configuration.
    974   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
    975   GetController(APPS)->FinishStart(DataTypeController::OK);
    976   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
    977 }
    978 
    979 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationStop) {
    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::ABORTED);
    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::NOT_RUNNING, GetController(BOOKMARKS)->state());
   1006 
   1007   dtm_->Stop();
   1008   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
   1009   EXPECT_EQ(DataTypeController::NOT_RUNNING,
   1010             GetController(PREFERENCES)->state());
   1011   EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
   1012 }
   1013 
   1014 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationDownloadError) {
   1015   AddController(BOOKMARKS);
   1016   AddController(PREFERENCES);
   1017 
   1018   dtm_->set_priority_types(
   1019       AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
   1020 
   1021   // Initial configure.
   1022   SetConfigureStartExpectation();
   1023   SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR);
   1024 
   1025   // Initially only PREFERENCES is configured.
   1026   configurer_.set_expected_configure_types(
   1027       AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   1028   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
   1029   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
   1030 
   1031   // BOOKMARKS is configured after download of PREFERENCES finishes.
   1032   configurer_.set_expected_configure_types(
   1033       AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS)));
   1034   FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
   1035   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   1036 
   1037   // PERFERENCES controller is associating while BOOKMARKS is downloading.
   1038   EXPECT_EQ(DataTypeController::ASSOCIATING,
   1039             GetController(PREFERENCES)->state());
   1040   EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
   1041 
   1042   // Make BOOKMARKS download fail.
   1043   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet(BOOKMARKS));
   1044   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
   1045   EXPECT_EQ(DataTypeController::NOT_RUNNING,
   1046             GetController(PREFERENCES)->state());
   1047   EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
   1048 }
   1049 
   1050 TEST_F(SyncDataTypeManagerImplTest, HighPriorityAssociationFailure) {
   1051   AddController(PREFERENCES);   // Will fail.
   1052   AddController(BOOKMARKS);     // Will succeed.
   1053 
   1054   dtm_->set_priority_types(
   1055       AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
   1056 
   1057   // Initial configure.
   1058   SetConfigureStartExpectation();
   1059   SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
   1060 
   1061   // Initially only PREFERENCES is configured.
   1062   configurer_.set_expected_configure_types(
   1063       AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   1064   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
   1065   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
   1066 
   1067   // BOOKMARKS is configured after download of PREFERENCES finishes.
   1068   configurer_.set_expected_configure_types(
   1069       AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS)));
   1070   FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
   1071   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   1072 
   1073   // PERFERENCES controller is associating while BOOKMARKS is downloading.
   1074   EXPECT_EQ(DataTypeController::ASSOCIATING,
   1075             GetController(PREFERENCES)->state());
   1076   EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
   1077 
   1078   // Make PREFERENCES association fail.
   1079   GetController(PREFERENCES)->FinishStart(
   1080       DataTypeController::ASSOCIATION_FAILED);
   1081   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   1082 
   1083   // Reconfigure without PREFERENCES after the BOOKMARKS download completes,
   1084   // then reconfigure with BOOKMARKS.
   1085   configurer_.set_expected_configure_types(HighPriorityTypes());
   1086   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
   1087   configurer_.set_expected_configure_types(
   1088       AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS)));
   1089   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
   1090 
   1091   // Reconfigure with BOOKMARKS.
   1092   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
   1093   EXPECT_EQ(DataTypeController::ASSOCIATING,
   1094             GetController(BOOKMARKS)->state());
   1095   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
   1096 
   1097   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
   1098   EXPECT_EQ(DataTypeController::NOT_RUNNING,
   1099             GetController(PREFERENCES)->state());
   1100   EXPECT_EQ(DataTypeController::RUNNING, GetController(BOOKMARKS)->state());
   1101 }
   1102 
   1103 TEST_F(SyncDataTypeManagerImplTest, LowPriorityAssociationFailure) {
   1104   AddController(PREFERENCES);  // Will succeed.
   1105   AddController(BOOKMARKS);    // Will fail.
   1106 
   1107   dtm_->set_priority_types(
   1108       AddHighPriorityTypesTo(syncer::ModelTypeSet(PREFERENCES)));
   1109 
   1110   // Initial configure.
   1111   SetConfigureStartExpectation();
   1112   SetConfigureDoneExpectation(DataTypeManager::PARTIAL_SUCCESS);
   1113 
   1114   // Initially only PREFERENCES is configured.
   1115   configurer_.set_expected_configure_types(
   1116       AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   1117   Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
   1118   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
   1119 
   1120   // BOOKMARKS is configured after download of PREFERENCES finishes.
   1121   configurer_.set_expected_configure_types(
   1122       AddLowPriorityCoreTypesTo(ModelTypeSet(BOOKMARKS)));
   1123   FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
   1124   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   1125 
   1126   // PERFERENCES controller is associating while BOOKMARKS is downloading.
   1127   EXPECT_EQ(DataTypeController::ASSOCIATING,
   1128             GetController(PREFERENCES)->state());
   1129   EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
   1130 
   1131   // BOOKMARKS finishes downloading and PREFERENCES finishes associating.
   1132   FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
   1133   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
   1134   EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state());
   1135 
   1136   // Make BOOKMARKS association fail, which triggers reconfigure with only
   1137   // PREFERENCES.
   1138   configurer_.set_expected_configure_types(
   1139       AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
   1140   GetController(BOOKMARKS)->FinishStart(DataTypeController::ASSOCIATION_FAILED);
   1141   EXPECT_EQ(DataTypeController::NOT_RUNNING,
   1142             GetController(BOOKMARKS)->state());
   1143   EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
   1144 
   1145   // Finish configuration with only PREFERENCES.
   1146   configurer_.set_expected_configure_types(
   1147       AddLowPriorityCoreTypesTo(ModelTypeSet()));
   1148   FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
   1149   FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
   1150   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
   1151   EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state());
   1152   EXPECT_EQ(DataTypeController::NOT_RUNNING,
   1153             GetController(BOOKMARKS)->state());
   1154 }
   1155 
   1156 }  // namespace browser_sync
   1157