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.
5 #include "testing/gtest/include/gtest/gtest.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/tracked_objects.h"
13 #include "chrome/browser/sync/glue/frontend_data_type_controller.h"
14 #include "chrome/browser/sync/glue/frontend_data_type_controller_mock.h"
15 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
16 #include "chrome/browser/sync/profile_sync_service_mock.h"
17 #include "chrome/test/base/profile_mock.h"
18 #include "components/sync_driver/change_processor_mock.h"
19 #include "components/sync_driver/data_type_controller_mock.h"
20 #include "components/sync_driver/model_associator_mock.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
23 using browser_sync::FrontendDataTypeController;
24 using browser_sync::FrontendDataTypeControllerMock;
25 using sync_driver::ChangeProcessorMock;
26 using sync_driver::DataTypeController;
27 using sync_driver::ModelAssociatorMock;
28 using sync_driver::ModelLoadCallbackMock;
29 using sync_driver::StartCallbackMock;
32 using testing::InvokeWithoutArgs;
33 using testing::Return;
34 using testing::SetArgumentPointee;
35 using testing::StrictMock;
37 class FrontendDataTypeControllerFake : public FrontendDataTypeController {
39 FrontendDataTypeControllerFake(
40 ProfileSyncComponentsFactory* profile_sync_factory,
42 ProfileSyncService* sync_service,
43 FrontendDataTypeControllerMock* mock)
44 : FrontendDataTypeController(base::MessageLoopProxy::current(),
50 virtual syncer::ModelType type() const OVERRIDE { return syncer::BOOKMARKS; }
53 virtual void CreateSyncComponents() OVERRIDE {
54 ProfileSyncComponentsFactory::SyncComponents sync_components =
55 profile_sync_factory_->
56 CreateBookmarkSyncComponents(sync_service_, this);
57 model_associator_.reset(sync_components.model_associator);
58 change_processor_.reset(sync_components.change_processor);
61 // We mock the following methods because their default implementations do
62 // nothing, but we still want to make sure they're called appropriately.
63 virtual bool StartModels() OVERRIDE {
64 return mock_->StartModels();
66 virtual void CleanUpState() OVERRIDE {
67 mock_->CleanUpState();
69 virtual void RecordUnrecoverableError(
70 const tracked_objects::Location& from_here,
71 const std::string& message) OVERRIDE {
72 mock_->RecordUnrecoverableError(from_here, message);
74 virtual void RecordAssociationTime(base::TimeDelta time) OVERRIDE {
75 mock_->RecordAssociationTime(time);
77 virtual void RecordStartFailure(
78 DataTypeController::ConfigureResult result) OVERRIDE {
79 mock_->RecordStartFailure(result);
82 virtual ~FrontendDataTypeControllerFake() {}
83 FrontendDataTypeControllerMock* mock_;
86 class SyncFrontendDataTypeControllerTest : public testing::Test {
88 SyncFrontendDataTypeControllerTest()
89 : thread_bundle_(content::TestBrowserThreadBundle::DEFAULT),
90 service_(&profile_) {}
92 virtual void SetUp() {
93 profile_sync_factory_.reset(new ProfileSyncComponentsFactoryMock());
94 dtc_mock_ = new StrictMock<FrontendDataTypeControllerMock>();
96 new FrontendDataTypeControllerFake(profile_sync_factory_.get(),
103 void SetStartExpectations() {
104 EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(true));
105 EXPECT_CALL(model_load_callback_, Run(_, _));
106 model_associator_ = new ModelAssociatorMock();
107 change_processor_ = new ChangeProcessorMock();
108 EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
109 WillOnce(Return(ProfileSyncComponentsFactory::SyncComponents(
110 model_associator_, change_processor_)));
113 void SetAssociateExpectations() {
114 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
115 WillOnce(Return(true));
116 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
117 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
118 EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
119 WillOnce(Return(syncer::SyncError()));
120 EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
123 void SetActivateExpectations(DataTypeController::ConfigureResult result) {
124 EXPECT_CALL(start_callback_, Run(result, _, _));
127 void SetStopExpectations() {
128 EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
129 EXPECT_CALL(service_, DeactivateDataType(_));
130 EXPECT_CALL(*model_associator_, DisassociateModels()).
131 WillOnce(Return(syncer::SyncError()));
134 void SetStartFailExpectations(DataTypeController::ConfigureResult result) {
135 if (DataTypeController::IsUnrecoverableResult(result))
136 EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, _));
137 EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
138 EXPECT_CALL(*dtc_mock_.get(), RecordStartFailure(result));
139 EXPECT_CALL(start_callback_, Run(result, _, _));
143 frontend_dtc_->LoadModels(
144 base::Bind(&ModelLoadCallbackMock::Run,
145 base::Unretained(&model_load_callback_)));
146 frontend_dtc_->StartAssociating(
147 base::Bind(&StartCallbackMock::Run,
148 base::Unretained(&start_callback_)));
151 void PumpLoop() { base::MessageLoop::current()->RunUntilIdle(); }
153 content::TestBrowserThreadBundle thread_bundle_;
154 scoped_refptr<FrontendDataTypeControllerFake> frontend_dtc_;
155 scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
156 scoped_refptr<FrontendDataTypeControllerMock> dtc_mock_;
157 ProfileMock profile_;
158 ProfileSyncServiceMock service_;
159 ModelAssociatorMock* model_associator_;
160 ChangeProcessorMock* change_processor_;
161 StartCallbackMock start_callback_;
162 ModelLoadCallbackMock model_load_callback_;
165 TEST_F(SyncFrontendDataTypeControllerTest, StartOk) {
166 SetStartExpectations();
167 SetAssociateExpectations();
168 SetActivateExpectations(DataTypeController::OK);
169 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
171 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
174 TEST_F(SyncFrontendDataTypeControllerTest, StartFirstRun) {
175 SetStartExpectations();
176 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
177 WillOnce(Return(true));
178 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
179 WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
180 EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
181 WillOnce(Return(syncer::SyncError()));
182 EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
183 SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
184 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
186 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
189 TEST_F(SyncFrontendDataTypeControllerTest, AbortDuringStartModels) {
190 EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(false));
191 EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
192 EXPECT_CALL(model_load_callback_, Run(_, _));
193 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
194 frontend_dtc_->LoadModels(
195 base::Bind(&ModelLoadCallbackMock::Run,
196 base::Unretained(&model_load_callback_)));
197 EXPECT_EQ(DataTypeController::MODEL_STARTING, frontend_dtc_->state());
198 frontend_dtc_->Stop();
199 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
202 TEST_F(SyncFrontendDataTypeControllerTest, StartAssociationFailed) {
203 SetStartExpectations();
204 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
205 WillOnce(Return(true));
206 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
207 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
208 EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
209 WillOnce(Return(syncer::SyncError(FROM_HERE,
210 syncer::SyncError::DATATYPE_ERROR,
212 syncer::BOOKMARKS)));
214 EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
215 SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
216 // Set up association to fail with an association failed error.
217 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
219 EXPECT_EQ(DataTypeController::DISABLED, frontend_dtc_->state());
222 TEST_F(SyncFrontendDataTypeControllerTest,
223 StartAssociationTriggersUnrecoverableError) {
224 SetStartExpectations();
225 SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
226 // Set up association to fail with an unrecoverable error.
227 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
228 WillRepeatedly(Return(true));
229 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
230 WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
231 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
233 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
236 TEST_F(SyncFrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
237 SetStartExpectations();
238 SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
239 // Set up association to fail with a NEEDS_CRYPTO error.
240 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
241 WillRepeatedly(Return(false));
242 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
244 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
247 TEST_F(SyncFrontendDataTypeControllerTest, Stop) {
248 SetStartExpectations();
249 SetAssociateExpectations();
250 SetActivateExpectations(DataTypeController::OK);
251 SetStopExpectations();
252 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
254 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
255 frontend_dtc_->Stop();
256 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());