1 // Copyright 2014 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.
5 #include "components/sync_driver/data_type_manager_impl.h"
7 #include "base/compiler_specific.h"
8 #include "base/message_loop/message_loop.h"
9 #include "components/sync_driver/backend_data_type_configurer.h"
10 #include "components/sync_driver/data_type_controller.h"
11 #include "components/sync_driver/data_type_encryption_handler.h"
12 #include "components/sync_driver/data_type_manager_observer.h"
13 #include "components/sync_driver/data_type_status_table.h"
14 #include "components/sync_driver/fake_data_type_controller.h"
15 #include "sync/internal_api/public/base/model_type.h"
16 #include "sync/internal_api/public/configure_reason.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace sync_driver {
21 using syncer::SyncError;
22 using syncer::ModelType;
23 using syncer::ModelTypeSet;
24 using syncer::ModelTypeToString;
25 using syncer::BOOKMARKS;
27 using syncer::PASSWORDS;
28 using syncer::PREFERENCES;
33 // Helper for unioning with priority types.
34 ModelTypeSet AddHighPriorityTypesTo(ModelTypeSet types) {
35 ModelTypeSet result = syncer::ControlTypes();
40 DataTypeStatusTable BuildStatusTable(ModelTypeSet crypto_errors,
41 ModelTypeSet association_errors,
42 ModelTypeSet unready_errors,
43 ModelTypeSet unrecoverable_errors) {
44 DataTypeStatusTable::TypeErrorMap error_map;
45 for (ModelTypeSet::Iterator iter = crypto_errors.First(); iter.Good();
47 error_map[iter.Get()] = SyncError(FROM_HERE,
48 SyncError::CRYPTO_ERROR,
49 "crypto error expected",
52 for (ModelTypeSet::Iterator iter = association_errors.First(); iter.Good();
54 error_map[iter.Get()] = SyncError(FROM_HERE,
55 SyncError::DATATYPE_ERROR,
56 "association error expected",
59 for (ModelTypeSet::Iterator iter = unready_errors.First(); iter.Good();
61 error_map[iter.Get()] = SyncError(FROM_HERE,
62 SyncError::UNREADY_ERROR,
63 "unready error expected",
66 for (ModelTypeSet::Iterator iter = unrecoverable_errors.First(); iter.Good();
68 error_map[iter.Get()] = SyncError(FROM_HERE,
69 SyncError::UNRECOVERABLE_ERROR,
70 "unrecoverable error expected",
73 DataTypeStatusTable status_table;
74 status_table.UpdateFailedDataTypes(error_map);
78 // Fake BackendDataTypeConfigurer implementation that simply stores away the
79 // callback passed into ConfigureDataTypes.
80 class FakeBackendDataTypeConfigurer : public BackendDataTypeConfigurer {
82 FakeBackendDataTypeConfigurer() {}
83 virtual ~FakeBackendDataTypeConfigurer() {}
85 virtual void ConfigureDataTypes(
86 syncer::ConfigureReason reason,
87 const DataTypeConfigStateMap& config_state_map,
88 const base::Callback<void(ModelTypeSet,
89 ModelTypeSet)>& ready_task,
90 const base::Callback<void()>& retry_callback) OVERRIDE {
91 last_ready_task_ = ready_task;
93 if (!expected_configure_types_.Empty()) {
95 expected_configure_types_.Equals(
96 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map)))
97 << ModelTypeSetToString(expected_configure_types_)
99 << ModelTypeSetToString(
100 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map));
104 virtual void ActivateDataType(
105 syncer::ModelType type, syncer::ModelSafeGroup group,
106 ChangeProcessor* change_processor) OVERRIDE {
107 activated_types_.Put(type);
109 virtual void DeactivateDataType(syncer::ModelType type) OVERRIDE {
110 activated_types_.Remove(type);
113 base::Callback<void(ModelTypeSet, ModelTypeSet)> last_ready_task() const {
114 return last_ready_task_;
117 void set_expected_configure_types(ModelTypeSet types) {
118 expected_configure_types_ = types;
121 const ModelTypeSet activated_types() { return activated_types_; }
124 base::Callback<void(ModelTypeSet, ModelTypeSet)> last_ready_task_;
125 ModelTypeSet expected_configure_types_;
126 ModelTypeSet activated_types_;
129 // DataTypeManagerObserver implementation.
130 class FakeDataTypeManagerObserver : public DataTypeManagerObserver {
132 FakeDataTypeManagerObserver() { ResetExpectations(); }
133 virtual ~FakeDataTypeManagerObserver() {
134 EXPECT_FALSE(start_expected_);
135 DataTypeManager::ConfigureResult default_result;
136 EXPECT_EQ(done_expectation_.status, default_result.status);
138 done_expectation_.data_type_status_table.GetFailedTypes().Empty());
142 start_expected_ = true;
144 void ExpectDone(const DataTypeManager::ConfigureResult& result) {
145 done_expectation_ = result;
147 void ResetExpectations() {
148 start_expected_ = false;
149 done_expectation_ = DataTypeManager::ConfigureResult();
152 virtual void OnConfigureDone(
153 const DataTypeManager::ConfigureResult& result) OVERRIDE {
154 EXPECT_EQ(done_expectation_.status, result.status);
155 DataTypeStatusTable::TypeErrorMap errors =
156 result.data_type_status_table.GetAllErrors();
157 DataTypeStatusTable::TypeErrorMap expected_errors =
158 done_expectation_.data_type_status_table.GetAllErrors();
159 ASSERT_EQ(expected_errors.size(), errors.size());
160 for (DataTypeStatusTable::TypeErrorMap::const_iterator iter =
161 expected_errors.begin();
162 iter != expected_errors.end();
164 ASSERT_TRUE(errors.find(iter->first) != errors.end());
165 ASSERT_EQ(iter->second.error_type(),
166 errors.find(iter->first)->second.error_type());
168 done_expectation_ = DataTypeManager::ConfigureResult();
171 virtual void OnConfigureRetry() OVERRIDE{
175 virtual void OnConfigureStart() OVERRIDE {
176 EXPECT_TRUE(start_expected_);
177 start_expected_ = false;
181 bool start_expected_ = true;
182 DataTypeManager::ConfigureResult done_expectation_;
185 class FakeDataTypeEncryptionHandler : public DataTypeEncryptionHandler {
187 FakeDataTypeEncryptionHandler();
188 virtual ~FakeDataTypeEncryptionHandler();
190 virtual bool IsPassphraseRequired() const OVERRIDE;
191 virtual ModelTypeSet GetEncryptedDataTypes() const OVERRIDE;
193 void set_passphrase_required(bool passphrase_required) {
194 passphrase_required_ = passphrase_required;
196 void set_encrypted_types(ModelTypeSet encrypted_types) {
197 encrypted_types_ = encrypted_types;
200 bool passphrase_required_;
201 ModelTypeSet encrypted_types_;
204 FakeDataTypeEncryptionHandler::FakeDataTypeEncryptionHandler()
205 : passphrase_required_(false) {}
206 FakeDataTypeEncryptionHandler::~FakeDataTypeEncryptionHandler() {}
208 bool FakeDataTypeEncryptionHandler::IsPassphraseRequired() const {
209 return passphrase_required_;
213 FakeDataTypeEncryptionHandler::GetEncryptedDataTypes() const {
214 return encrypted_types_;
219 class TestDataTypeManager : public DataTypeManagerImpl {
222 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
224 BackendDataTypeConfigurer* configurer,
225 const DataTypeController::TypeMap* controllers,
226 const DataTypeEncryptionHandler* encryption_handler,
227 DataTypeManagerObserver* observer)
228 : DataTypeManagerImpl(base::Closure(),
234 custom_priority_types_(syncer::ControlTypes()) {}
236 void set_priority_types(const ModelTypeSet& priority_types) {
237 custom_priority_types_ = priority_types;
240 DataTypeManager::ConfigureResult configure_result() const {
241 return configure_result_;
244 virtual void OnModelAssociationDone(
245 const DataTypeManager::ConfigureResult& result) OVERRIDE {
246 configure_result_ = result;
247 DataTypeManagerImpl::OnModelAssociationDone(result);
251 virtual ModelTypeSet GetPriorityTypes() const OVERRIDE {
252 return custom_priority_types_;
255 ModelTypeSet custom_priority_types_;
256 DataTypeManager::ConfigureResult configure_result_;
259 // The actual test harness class, parametrized on nigori state (i.e., tests are
260 // run both configuring with nigori, and configuring without).
261 class SyncDataTypeManagerImplTest : public testing::Test {
263 SyncDataTypeManagerImplTest() {}
265 virtual ~SyncDataTypeManagerImplTest() {
269 virtual void SetUp() {
271 new TestDataTypeManager(
272 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(),
275 &encryption_handler_,
279 void SetConfigureStartExpectation() {
280 observer_.ExpectStart();
283 void SetConfigureDoneExpectation(DataTypeManager::ConfigureStatus status,
284 const DataTypeStatusTable& status_table) {
285 DataTypeManager::ConfigureResult result;
286 result.status = status;
287 result.data_type_status_table = status_table;
288 observer_.ExpectDone(result);
291 // Configure the given DTM with the given desired types.
292 void Configure(DataTypeManagerImpl* dtm,
293 const ModelTypeSet& desired_types) {
294 dtm->Configure(desired_types, syncer::CONFIGURE_REASON_RECONFIGURATION);
297 // Finish downloading for the given DTM. Should be done only after
298 // a call to Configure().
299 void FinishDownload(const DataTypeManager& dtm,
300 ModelTypeSet types_to_configure,
301 ModelTypeSet failed_download_types) {
302 EXPECT_TRUE(DataTypeManager::DOWNLOAD_PENDING == dtm.state() ||
303 DataTypeManager::CONFIGURING == dtm.state());
304 ASSERT_FALSE(configurer_.last_ready_task().is_null());
305 configurer_.last_ready_task().Run(
306 syncer::Difference(types_to_configure, failed_download_types),
307 failed_download_types);
310 // Adds a fake controller for the given type to |controllers_|.
311 // Should be called only before setting up the DTM.
312 void AddController(ModelType model_type) {
313 controllers_[model_type] = new FakeDataTypeController(model_type);
316 // Gets the fake controller for the given type, which should have
317 // been previously added via AddController().
318 scoped_refptr<FakeDataTypeController> GetController(
319 ModelType model_type) const {
320 DataTypeController::TypeMap::const_iterator it =
321 controllers_.find(model_type);
322 if (it == controllers_.end()) {
325 return make_scoped_refptr(
326 static_cast<FakeDataTypeController*>(it->second.get()));
329 void FailEncryptionFor(ModelTypeSet encrypted_types) {
330 encryption_handler_.set_passphrase_required(true);
331 encryption_handler_.set_encrypted_types(encrypted_types);
334 base::MessageLoopForUI ui_loop_;
335 DataTypeController::TypeMap controllers_;
336 FakeBackendDataTypeConfigurer configurer_;
337 FakeDataTypeManagerObserver observer_;
338 scoped_ptr<TestDataTypeManager> dtm_;
339 FakeDataTypeEncryptionHandler encryption_handler_;
342 // Set up a DTM with no controllers, configure it, finish downloading,
344 TEST_F(SyncDataTypeManagerImplTest, NoControllers) {
345 SetConfigureStartExpectation();
346 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
348 Configure(dtm_.get(), ModelTypeSet());
349 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
351 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
352 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
355 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
358 // Set up a DTM with a single controller, configure it, finish
359 // downloading, finish starting the controller, and then stop the DTM.
360 TEST_F(SyncDataTypeManagerImplTest, ConfigureOne) {
361 AddController(BOOKMARKS);
363 SetConfigureStartExpectation();
364 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
366 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
367 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
369 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
370 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
371 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
373 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
374 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
375 EXPECT_EQ(1U, configurer_.activated_types().Size());
378 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
379 EXPECT_TRUE(configurer_.activated_types().Empty());
382 // Set up a DTM with a single controller, configure it, but stop it
383 // before finishing the download. It should still be safe to run the
384 // download callback even after the DTM is stopped and destroyed.
385 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileDownloadPending) {
386 AddController(BOOKMARKS);
389 SetConfigureStartExpectation();
390 SetConfigureDoneExpectation(DataTypeManager::ABORTED,
391 DataTypeStatusTable());
393 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
394 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
397 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
400 configurer_.last_ready_task().Run(ModelTypeSet(BOOKMARKS), ModelTypeSet());
401 EXPECT_TRUE(configurer_.activated_types().Empty());
404 // Set up a DTM with a single controller, configure it, finish
405 // downloading, but stop the DTM before the controller finishes
406 // starting up. It should still be safe to finish starting up the
407 // controller even after the DTM is stopped and destroyed.
408 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileStartingModel) {
409 AddController(BOOKMARKS);
412 SetConfigureStartExpectation();
413 SetConfigureDoneExpectation(DataTypeManager::ABORTED,
414 DataTypeStatusTable());
416 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
417 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
419 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
420 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
421 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
424 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
428 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
429 EXPECT_TRUE(configurer_.activated_types().Empty());
432 // Set up a DTM with a single controller, configure it, finish
433 // downloading, start the controller's model, but stop the DTM before
434 // the controller finishes starting up. It should still be safe to
435 // finish starting up the controller even after the DTM is stopped and
437 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneStopWhileAssociating) {
438 AddController(BOOKMARKS);
441 SetConfigureStartExpectation();
442 SetConfigureDoneExpectation(DataTypeManager::ABORTED,
443 DataTypeStatusTable());
445 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
446 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
448 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
449 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
450 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
451 EXPECT_TRUE(configurer_.activated_types().Empty());
454 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
458 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
459 EXPECT_TRUE(configurer_.activated_types().Empty());
462 // Set up a DTM with a single controller. Then:
465 // 2) Finish the download for step 1.
466 // 3) Finish starting the controller with the NEEDS_CRYPTO status.
467 // 4) Complete download for the reconfiguration without the controller.
469 TEST_F(SyncDataTypeManagerImplTest, OneWaitingForCrypto) {
470 AddController(PASSWORDS);
472 SetConfigureStartExpectation();
473 SetConfigureDoneExpectation(DataTypeManager::OK,
474 BuildStatusTable(ModelTypeSet(PASSWORDS),
479 const ModelTypeSet types(PASSWORDS);
480 dtm_->set_priority_types(AddHighPriorityTypesTo(types));
483 Configure(dtm_.get(), types);
484 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
487 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
488 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
491 FailEncryptionFor(types);
492 GetController(PASSWORDS)->FinishStart(DataTypeController::NEEDS_CRYPTO);
493 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
496 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
497 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
501 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
504 // Set up a DTM with two controllers. Then:
506 // 1) Configure with first controller.
507 // 2) Finish the download for step 1.
508 // 3) Finish starting the first controller.
509 // 4) Configure with both controllers.
510 // 5) Finish the download for step 4.
511 // 6) Finish starting the second controller.
513 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneThenBoth) {
514 AddController(BOOKMARKS);
515 AddController(PREFERENCES);
517 SetConfigureStartExpectation();
518 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
521 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
522 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
525 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
526 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
527 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
530 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
531 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
533 observer_.ResetExpectations();
534 SetConfigureStartExpectation();
535 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
538 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
539 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
542 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
543 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
544 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
547 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
548 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
549 EXPECT_EQ(2U, configurer_.activated_types().Size());
553 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
554 EXPECT_TRUE(configurer_.activated_types().Empty());
557 // Set up a DTM with two controllers. Then:
559 // 1) Configure with first controller.
560 // 2) Finish the download for step 1.
561 // 3) Finish starting the first controller.
562 // 4) Configure with second controller.
563 // 5) Finish the download for step 4.
564 // 6) Finish starting the second controller.
566 TEST_F(SyncDataTypeManagerImplTest, ConfigureOneThenSwitch) {
567 AddController(BOOKMARKS);
568 AddController(PREFERENCES);
570 SetConfigureStartExpectation();
571 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
574 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
575 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
578 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
579 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
580 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
583 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
584 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
586 observer_.ResetExpectations();
587 SetConfigureStartExpectation();
588 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
591 Configure(dtm_.get(), ModelTypeSet(PREFERENCES));
592 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
595 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
596 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
597 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
600 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
601 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
602 EXPECT_EQ(1U, configurer_.activated_types().Size());
606 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
607 EXPECT_TRUE(configurer_.activated_types().Empty());
610 // Set up a DTM with two controllers. Then:
612 // 1) Configure with first controller.
613 // 2) Finish the download for step 1.
614 // 3) Configure with both controllers.
615 // 4) Finish starting the first controller.
616 // 5) Finish the download for step 3.
617 // 6) Finish starting the second controller.
619 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileOneInFlight) {
620 AddController(BOOKMARKS);
621 AddController(PREFERENCES);
623 SetConfigureStartExpectation();
624 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
627 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
628 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
631 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
632 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
633 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
636 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
637 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
640 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
641 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
644 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
645 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
646 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
649 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
650 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
651 EXPECT_EQ(2U, configurer_.activated_types().Size());
655 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
656 EXPECT_TRUE(configurer_.activated_types().Empty());
659 // Set up a DTM with one controller. Then configure, finish
660 // downloading, and start the controller with an unrecoverable error.
661 // The unrecoverable error should cause the DTM to stop.
662 TEST_F(SyncDataTypeManagerImplTest, OneFailingController) {
663 AddController(BOOKMARKS);
665 SetConfigureStartExpectation();
666 SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR,
667 BuildStatusTable(ModelTypeSet(),
670 ModelTypeSet(BOOKMARKS)));
672 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
673 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
675 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
676 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
677 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
678 EXPECT_TRUE(configurer_.activated_types().Empty());
680 GetController(BOOKMARKS)->FinishStart(
681 DataTypeController::UNRECOVERABLE_ERROR);
682 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
683 EXPECT_TRUE(configurer_.activated_types().Empty());
686 // Set up a DTM with two controllers. Then:
688 // 1) Configure with both controllers.
689 // 2) Finish the download for step 1.
690 // 3) Finish starting the first controller successfully.
691 // 4) Finish starting the second controller with an unrecoverable error.
693 // The failure from step 4 should cause the DTM to stop.
694 TEST_F(SyncDataTypeManagerImplTest, SecondControllerFails) {
695 AddController(BOOKMARKS);
696 AddController(PREFERENCES);
698 SetConfigureStartExpectation();
699 SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR,
700 BuildStatusTable(ModelTypeSet(),
703 ModelTypeSet(PREFERENCES)));
706 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
707 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
710 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
711 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
712 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
715 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
716 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
719 GetController(PREFERENCES)->FinishStart(
720 DataTypeController::UNRECOVERABLE_ERROR);
721 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
724 // Set up a DTM with two controllers. Then:
726 // 1) Configure with both controllers.
727 // 2) Finish the download for step 1.
728 // 3) Finish starting the first controller successfully.
729 // 4) Finish starting the second controller with an association failure.
730 // 5) Finish the purge/reconfigure without the failed type.
733 // The association failure from step 3 should be ignored.
735 // TODO(akalin): Check that the data type that failed association is
736 // recorded in the CONFIGURE_DONE notification.
737 TEST_F(SyncDataTypeManagerImplTest, OneControllerFailsAssociation) {
738 AddController(BOOKMARKS);
739 AddController(PREFERENCES);
741 SetConfigureStartExpectation();
742 SetConfigureDoneExpectation(DataTypeManager::OK,
743 BuildStatusTable(ModelTypeSet(),
744 ModelTypeSet(PREFERENCES),
749 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
750 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
753 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
754 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
755 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
758 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
759 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
762 GetController(PREFERENCES)->FinishStart(
763 DataTypeController::ASSOCIATION_FAILED);
764 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
767 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
768 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
769 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
770 EXPECT_EQ(1U, configurer_.activated_types().Size());
774 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
775 EXPECT_TRUE(configurer_.activated_types().Empty());
778 // Set up a DTM with two controllers. Then:
780 // 1) Configure with first controller.
781 // 2) Configure with both controllers.
782 // 3) Finish the download for step 1.
783 // 4) Finish the download for step 2.
784 // 5) Finish starting both controllers.
786 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileDownloadPending) {
787 AddController(BOOKMARKS);
788 AddController(PREFERENCES);
790 SetConfigureStartExpectation();
791 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
794 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
795 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
798 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
799 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
802 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
803 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
806 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
807 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
808 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
811 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
812 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
813 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
814 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
818 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
821 // Set up a DTM with two controllers. Then:
823 // 1) Configure with first controller.
824 // 2) Configure with both controllers.
825 // 3) Finish the download for step 1 with a failed data type.
826 // 4) Finish the download for step 2 successfully.
827 // 5) Finish starting both controllers.
830 // The failure from step 3 should be ignored since there's a
831 // reconfigure pending from step 2.
832 TEST_F(SyncDataTypeManagerImplTest, ConfigureWhileDownloadPendingWithFailure) {
833 AddController(BOOKMARKS);
834 AddController(PREFERENCES);
836 SetConfigureStartExpectation();
837 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
840 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
841 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
842 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
845 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
846 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
849 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
850 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
851 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
854 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
855 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
858 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
859 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
860 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
861 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
865 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
868 // Tests a Purge then Configure. This is similar to the sequence of
869 // operations that would be invoked by the BackendMigrator.
870 TEST_F(SyncDataTypeManagerImplTest, MigrateAll) {
871 AddController(BOOKMARKS);
872 dtm_->set_priority_types(AddHighPriorityTypesTo(ModelTypeSet(BOOKMARKS)));
874 SetConfigureStartExpectation();
875 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
878 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
879 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
880 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
882 // We've now configured bookmarks and (implicitly) the control types.
883 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
884 observer_.ResetExpectations();
886 // Pretend we were told to migrate all types.
887 ModelTypeSet to_migrate;
888 to_migrate.Put(BOOKMARKS);
889 to_migrate.PutAll(syncer::ControlTypes());
891 SetConfigureStartExpectation();
892 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
893 dtm_->PurgeForMigration(to_migrate,
894 syncer::CONFIGURE_REASON_MIGRATION);
895 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
897 // The DTM will call ConfigureDataTypes(), even though it is unnecessary.
898 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
899 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
900 observer_.ResetExpectations();
902 // Re-enable the migrated types.
903 SetConfigureStartExpectation();
904 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
905 Configure(dtm_.get(), to_migrate);
906 FinishDownload(*dtm_, to_migrate, ModelTypeSet());
907 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
908 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
911 // Test receipt of a Configure request while a purge is in flight.
912 TEST_F(SyncDataTypeManagerImplTest, ConfigureDuringPurge) {
913 AddController(BOOKMARKS);
914 AddController(PREFERENCES);
916 // Initial configure.
917 SetConfigureStartExpectation();
918 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
919 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
920 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
921 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
922 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
923 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
924 observer_.ResetExpectations();
926 // Purge the Nigori type.
927 SetConfigureStartExpectation();
928 dtm_->PurgeForMigration(ModelTypeSet(NIGORI),
929 syncer::CONFIGURE_REASON_MIGRATION);
930 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
931 observer_.ResetExpectations();
933 // Before the backend configuration completes, ask for a different
934 // set of types. This request asks for
935 // - BOOKMARKS: which is redundant because it was already enabled,
936 // - PREFERENCES: which is new and will need to be downloaded, and
937 // - NIGORI: (added implicitly because it is a control type) which
938 // the DTM is part-way through purging.
939 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
940 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
942 // Invoke the callback we've been waiting for since we asked to purge NIGORI.
943 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
944 observer_.ResetExpectations();
946 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
947 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
949 // Now invoke the callback for the second configure request.
950 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
951 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, PREFERENCES), ModelTypeSet());
952 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
954 // Start the preferences controller. We don't need to start controller for
955 // the NIGORI because it has none. We don't need to start the controller for
956 // the BOOKMARKS because it was never stopped.
957 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
958 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
961 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfiguration) {
962 AddController(BOOKMARKS);
963 AddController(PREFERENCES);
965 dtm_->set_priority_types(
966 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
968 // Initial configure.
969 SetConfigureStartExpectation();
970 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
972 // Initially only PREFERENCES is configured.
973 configurer_.set_expected_configure_types(
974 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
975 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
976 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
978 // BOOKMARKS is configured after download of PREFERENCES finishes.
979 configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
980 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
981 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
983 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
984 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
985 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
987 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
988 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
991 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationReconfigure) {
992 AddController(BOOKMARKS);
993 AddController(PREFERENCES);
996 dtm_->set_priority_types(
997 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
999 // Initial configure.
1000 SetConfigureStartExpectation();
1001 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
1003 // Reconfigure while associating PREFERENCES and downloading BOOKMARKS.
1004 configurer_.set_expected_configure_types(
1005 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1006 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
1007 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1009 configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
1010 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
1011 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1013 // Enable syncing for APPS.
1014 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES, APPS));
1015 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1017 // Reconfiguration starts after downloading and association of previous
1019 configurer_.set_expected_configure_types(
1020 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1021 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1022 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
1023 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1025 configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS, APPS));
1026 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
1027 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1029 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS, APPS), ModelTypeSet());
1030 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1032 // Skip calling FinishStart() for PREFENCES because it's already started in
1033 // first configuration.
1034 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
1035 GetController(APPS)->FinishStart(DataTypeController::OK);
1036 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1039 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationStop) {
1040 AddController(BOOKMARKS);
1041 AddController(PREFERENCES);
1043 dtm_->set_priority_types(
1044 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1046 // Initial configure.
1047 SetConfigureStartExpectation();
1048 SetConfigureDoneExpectation(DataTypeManager::ABORTED, DataTypeStatusTable());
1050 // Initially only PREFERENCES is configured.
1051 configurer_.set_expected_configure_types(
1052 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1053 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
1054 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1056 // BOOKMARKS is configured after download of PREFERENCES finishes.
1057 configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
1058 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
1059 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1061 // PREFERENCES controller is associating while BOOKMARKS is downloading.
1062 EXPECT_EQ(DataTypeController::ASSOCIATING,
1063 GetController(PREFERENCES)->state());
1064 EXPECT_EQ(DataTypeController::MODEL_LOADED,
1065 GetController(BOOKMARKS)->state());
1068 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
1069 EXPECT_EQ(DataTypeController::NOT_RUNNING,
1070 GetController(PREFERENCES)->state());
1071 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
1074 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfigurationDownloadError) {
1075 AddController(BOOKMARKS);
1076 AddController(PREFERENCES);
1078 dtm_->set_priority_types(
1079 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1081 // Initial configure.
1082 SetConfigureStartExpectation();
1083 SetConfigureDoneExpectation(DataTypeManager::UNRECOVERABLE_ERROR,
1084 BuildStatusTable(ModelTypeSet(),
1087 ModelTypeSet(BOOKMARKS)));
1089 // Initially only PREFERENCES is configured.
1090 configurer_.set_expected_configure_types(
1091 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1092 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
1093 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1095 // BOOKMARKS is configured after download of PREFERENCES finishes.
1096 configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
1097 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
1098 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1100 // PREFERENCES controller is associating while BOOKMARKS is downloading.
1101 EXPECT_EQ(DataTypeController::ASSOCIATING,
1102 GetController(PREFERENCES)->state());
1103 EXPECT_EQ(DataTypeController::MODEL_LOADED,
1104 GetController(BOOKMARKS)->state());
1106 // Make BOOKMARKS download fail.
1107 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet(BOOKMARKS));
1108 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
1109 EXPECT_EQ(DataTypeController::NOT_RUNNING,
1110 GetController(PREFERENCES)->state());
1111 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
1114 TEST_F(SyncDataTypeManagerImplTest, HighPriorityAssociationFailure) {
1115 AddController(PREFERENCES); // Will fail.
1116 AddController(BOOKMARKS); // Will succeed.
1118 dtm_->set_priority_types(
1119 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1121 // Initial configure.
1122 SetConfigureStartExpectation();
1123 SetConfigureDoneExpectation(DataTypeManager::OK,
1124 BuildStatusTable(ModelTypeSet(),
1125 ModelTypeSet(PREFERENCES),
1129 // Initially only PREFERENCES is configured.
1130 configurer_.set_expected_configure_types(
1131 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1132 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
1133 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1135 // BOOKMARKS is configured after download of PREFERENCES finishes.
1136 configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
1137 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
1138 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1140 // PREFERENCES controller is associating while BOOKMARKS is downloading.
1141 EXPECT_EQ(DataTypeController::ASSOCIATING,
1142 GetController(PREFERENCES)->state());
1143 EXPECT_EQ(DataTypeController::MODEL_LOADED,
1144 GetController(BOOKMARKS)->state());
1146 // Make PREFERENCES association fail.
1147 GetController(PREFERENCES)->FinishStart(
1148 DataTypeController::ASSOCIATION_FAILED);
1149 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1151 // Reconfigure without PREFERENCES after the BOOKMARKS download completes,
1152 // then reconfigure with BOOKMARKS.
1153 configurer_.set_expected_configure_types(syncer::ControlTypes());
1154 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1155 configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
1156 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1158 // Reconfigure with BOOKMARKS.
1159 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1160 EXPECT_EQ(DataTypeController::ASSOCIATING,
1161 GetController(BOOKMARKS)->state());
1162 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
1164 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1165 EXPECT_EQ(DataTypeController::NOT_RUNNING,
1166 GetController(PREFERENCES)->state());
1167 EXPECT_EQ(DataTypeController::RUNNING, GetController(BOOKMARKS)->state());
1170 TEST_F(SyncDataTypeManagerImplTest, LowPriorityAssociationFailure) {
1171 AddController(PREFERENCES); // Will succeed.
1172 AddController(BOOKMARKS); // Will fail.
1174 dtm_->set_priority_types(
1175 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1177 // Initial configure.
1178 SetConfigureStartExpectation();
1179 SetConfigureDoneExpectation(DataTypeManager::OK,
1180 BuildStatusTable(ModelTypeSet(),
1181 ModelTypeSet(BOOKMARKS),
1185 // Initially only PREFERENCES is configured.
1186 configurer_.set_expected_configure_types(
1187 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1188 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
1189 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1191 // BOOKMARKS is configured after download of PREFERENCES finishes.
1192 configurer_.set_expected_configure_types(ModelTypeSet(BOOKMARKS));
1193 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
1194 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1196 // PREFERENCES controller is associating while BOOKMARKS is downloading.
1197 EXPECT_EQ(DataTypeController::ASSOCIATING,
1198 GetController(PREFERENCES)->state());
1199 EXPECT_EQ(DataTypeController::MODEL_LOADED,
1200 GetController(BOOKMARKS)->state());
1202 // BOOKMARKS finishes downloading and PREFERENCES finishes associating.
1203 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1204 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
1205 EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state());
1207 // Make BOOKMARKS association fail, which triggers reconfigure with only
1209 configurer_.set_expected_configure_types(
1210 AddHighPriorityTypesTo(ModelTypeSet(PREFERENCES)));
1211 GetController(BOOKMARKS)->FinishStart(DataTypeController::ASSOCIATION_FAILED);
1212 EXPECT_EQ(DataTypeController::NOT_RUNNING,
1213 GetController(BOOKMARKS)->state());
1214 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1216 // Finish configuration with only PREFERENCES.
1217 configurer_.set_expected_configure_types(ModelTypeSet());
1218 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES), ModelTypeSet());
1219 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1220 EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state());
1221 EXPECT_EQ(DataTypeController::NOT_RUNNING,
1222 GetController(BOOKMARKS)->state());
1225 TEST_F(SyncDataTypeManagerImplTest, FilterDesiredTypes) {
1226 AddController(BOOKMARKS);
1228 ModelTypeSet types(BOOKMARKS, APPS);
1229 dtm_->set_priority_types(AddHighPriorityTypesTo(types));
1231 SetConfigureStartExpectation();
1232 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
1234 ModelTypeSet expected_types = syncer::ControlTypes();
1235 expected_types.Put(BOOKMARKS);
1236 // APPS is filtered out because there's no controller for it.
1237 configurer_.set_expected_configure_types(expected_types);
1238 Configure(dtm_.get(), types);
1239 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1240 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
1243 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
1246 TEST_F(SyncDataTypeManagerImplTest, ConfigureForBackupRollback) {
1247 AddController(BOOKMARKS);
1249 SetConfigureStartExpectation();
1251 ModelTypeSet expected_types = syncer::ControlTypes();
1252 expected_types.Put(BOOKMARKS);
1253 configurer_.set_expected_configure_types(expected_types);
1254 dtm_->set_priority_types(expected_types);
1256 dtm_->Configure(ModelTypeSet(BOOKMARKS),
1257 syncer::CONFIGURE_REASON_BACKUP_ROLLBACK);
1260 TEST_F(SyncDataTypeManagerImplTest, ReenableAfterDataTypeError) {
1261 AddController(PREFERENCES); // Will succeed.
1262 AddController(BOOKMARKS); // Will be disabled due to datatype error.
1264 SetConfigureStartExpectation();
1265 SetConfigureDoneExpectation(DataTypeManager::OK,
1266 BuildStatusTable(ModelTypeSet(),
1267 ModelTypeSet(BOOKMARKS),
1271 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS, PREFERENCES));
1272 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1273 FinishDownload(*dtm_, ModelTypeSet(PREFERENCES, BOOKMARKS), ModelTypeSet());
1274 GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
1275 GetController(BOOKMARKS)
1276 ->FinishStart(DataTypeController::ASSOCIATION_FAILED);
1277 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); // Reconfig for error.
1278 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); // Reconfig for error.
1279 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1280 EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state());
1281 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
1283 observer_.ResetExpectations();
1285 // Re-enable bookmarks.
1286 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
1287 dtm_->ReenableType(syncer::BOOKMARKS);
1289 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1290 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1291 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1292 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1293 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
1294 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1295 EXPECT_EQ(DataTypeController::RUNNING, GetController(PREFERENCES)->state());
1296 EXPECT_EQ(DataTypeController::RUNNING, GetController(BOOKMARKS)->state());
1298 // Should do nothing.
1299 dtm_->ReenableType(syncer::BOOKMARKS);
1302 TEST_F(SyncDataTypeManagerImplTest, UnreadyType) {
1303 AddController(BOOKMARKS);
1304 GetController(BOOKMARKS)->SetReadyForStart(false);
1306 // Bookmarks is never started due to being unready.
1307 SetConfigureStartExpectation();
1308 SetConfigureDoneExpectation(DataTypeManager::OK,
1309 BuildStatusTable(ModelTypeSet(),
1311 ModelTypeSet(BOOKMARKS),
1313 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
1314 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1315 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
1316 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1317 EXPECT_EQ(0U, configurer_.activated_types().Size());
1318 observer_.ResetExpectations();
1320 // Bookmarks should start normally now.
1321 GetController(BOOKMARKS)->SetReadyForStart(true);
1322 SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
1323 dtm_->ReenableType(BOOKMARKS);
1324 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1326 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1327 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1328 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1330 GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
1331 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1332 EXPECT_EQ(1U, configurer_.activated_types().Size());
1334 // Should do nothing.
1335 observer_.ResetExpectations();
1336 dtm_->ReenableType(BOOKMARKS);
1339 EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
1340 EXPECT_TRUE(configurer_.activated_types().Empty());
1343 TEST_F(SyncDataTypeManagerImplTest, ModelLoadError) {
1344 AddController(BOOKMARKS);
1345 GetController(BOOKMARKS)->SetModelLoadError(syncer::SyncError(
1346 FROM_HERE, SyncError::DATATYPE_ERROR, "load error", BOOKMARKS));
1348 // Bookmarks is never started due to hitting a model load error.
1349 SetConfigureStartExpectation();
1350 SetConfigureDoneExpectation(DataTypeManager::OK,
1351 BuildStatusTable(ModelTypeSet(),
1352 ModelTypeSet(BOOKMARKS),
1355 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
1356 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1357 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1358 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1359 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
1361 EXPECT_EQ(0U, configurer_.activated_types().Size());
1365 TEST_F(SyncDataTypeManagerImplTest, ErrorBeforeAssociation) {
1366 AddController(BOOKMARKS);
1368 // Bookmarks is never started due to hitting a datatype error while the DTM
1369 // is still downloading types.
1370 SetConfigureStartExpectation();
1371 SetConfigureDoneExpectation(DataTypeManager::OK,
1372 BuildStatusTable(ModelTypeSet(),
1373 ModelTypeSet(BOOKMARKS),
1376 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
1377 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1378 GetController(BOOKMARKS)->OnSingleDataTypeUnrecoverableError(
1379 syncer::SyncError(FROM_HERE,
1380 SyncError::DATATYPE_ERROR,
1383 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1384 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet()); // Reconfig for error.
1385 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1386 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
1388 EXPECT_EQ(0U, configurer_.activated_types().Size());
1391 TEST_F(SyncDataTypeManagerImplTest, AssociationNeverCompletes) {
1392 AddController(BOOKMARKS);
1394 // Bookmarks times out during association and so it's never started.
1395 SetConfigureStartExpectation();
1396 SetConfigureDoneExpectation(DataTypeManager::OK,
1397 BuildStatusTable(ModelTypeSet(),
1398 ModelTypeSet(BOOKMARKS),
1401 Configure(dtm_.get(), ModelTypeSet(BOOKMARKS));
1403 GetController(BOOKMARKS)->SetDelayModelLoad();
1404 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1405 FinishDownload(*dtm_, ModelTypeSet(BOOKMARKS), ModelTypeSet());
1407 EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
1409 // Simulate timeout by firing the timer.
1410 dtm_->GetModelAssociationManagerForTesting()
1411 ->GetTimerForTesting()
1414 EXPECT_EQ(DataTypeManager::DOWNLOAD_PENDING, dtm_->state());
1415 EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
1417 FinishDownload(*dtm_, ModelTypeSet(), ModelTypeSet());
1419 EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
1420 EXPECT_EQ(0U, configurer_.activated_types().Size());
1423 } // namespace sync_driver