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