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/change_processor_mock.h"
14 #include "chrome/browser/sync/glue/frontend_data_type_controller.h"
15 #include "chrome/browser/sync/glue/frontend_data_type_controller_mock.h"
16 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
17 #include "chrome/browser/sync/profile_sync_service_mock.h"
18 #include "chrome/test/base/profile_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.h"
23 using browser_sync::ChangeProcessorMock;
24 using browser_sync::DataTypeController;
25 using browser_sync::FrontendDataTypeController;
26 using browser_sync::FrontendDataTypeControllerMock;
27 using browser_sync::ModelAssociatorMock;
28 using browser_sync::ModelLoadCallbackMock;
29 using browser_sync::StartCallbackMock;
30 using content::BrowserThread;
33 using testing::InvokeWithoutArgs;
34 using testing::Return;
35 using testing::SetArgumentPointee;
36 using testing::StrictMock;
38 class FrontendDataTypeControllerFake : public FrontendDataTypeController {
40 FrontendDataTypeControllerFake(
41 ProfileSyncComponentsFactory* profile_sync_factory,
43 ProfileSyncService* sync_service,
44 FrontendDataTypeControllerMock* mock)
45 : FrontendDataTypeController(base::MessageLoopProxy::current(),
51 virtual syncer::ModelType type() const OVERRIDE { return syncer::BOOKMARKS; }
54 virtual void CreateSyncComponents() OVERRIDE {
55 ProfileSyncComponentsFactory::SyncComponents sync_components =
56 profile_sync_factory_->
57 CreateBookmarkSyncComponents(sync_service_, this);
58 model_associator_.reset(sync_components.model_associator);
59 change_processor_.reset(sync_components.change_processor);
62 // We mock the following methods because their default implementations do
63 // nothing, but we still want to make sure they're called appropriately.
64 virtual bool StartModels() OVERRIDE {
65 return mock_->StartModels();
67 virtual void CleanUpState() OVERRIDE {
68 mock_->CleanUpState();
70 virtual void RecordUnrecoverableError(
71 const tracked_objects::Location& from_here,
72 const std::string& message) OVERRIDE {
73 mock_->RecordUnrecoverableError(from_here, message);
75 virtual void RecordAssociationTime(base::TimeDelta time) OVERRIDE {
76 mock_->RecordAssociationTime(time);
78 virtual void RecordStartFailure(
79 DataTypeController::StartResult result) OVERRIDE {
80 mock_->RecordStartFailure(result);
83 virtual ~FrontendDataTypeControllerFake() {}
84 FrontendDataTypeControllerMock* mock_;
87 class SyncFrontendDataTypeControllerTest : public testing::Test {
89 SyncFrontendDataTypeControllerTest()
90 : ui_thread_(BrowserThread::UI, &message_loop_),
91 service_(&profile_) {}
93 virtual void SetUp() {
94 profile_sync_factory_.reset(new ProfileSyncComponentsFactoryMock());
95 dtc_mock_ = new StrictMock<FrontendDataTypeControllerMock>();
97 new FrontendDataTypeControllerFake(profile_sync_factory_.get(),
104 void SetStartExpectations() {
105 EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(true));
106 EXPECT_CALL(model_load_callback_, Run(_, _));
107 model_associator_ = new ModelAssociatorMock();
108 change_processor_ = new ChangeProcessorMock();
109 EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
110 WillOnce(Return(ProfileSyncComponentsFactory::SyncComponents(
111 model_associator_, change_processor_)));
114 void SetAssociateExpectations() {
115 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
116 WillOnce(Return(true));
117 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
118 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
119 EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
120 WillOnce(Return(syncer::SyncError()));
121 EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
124 void SetActivateExpectations(DataTypeController::StartResult result) {
125 EXPECT_CALL(service_, ActivateDataType(_, _, _));
126 EXPECT_CALL(start_callback_, Run(result, _, _));
129 void SetStopExpectations() {
130 EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
131 EXPECT_CALL(service_, DeactivateDataType(_));
132 EXPECT_CALL(*model_associator_, DisassociateModels()).
133 WillOnce(Return(syncer::SyncError()));
136 void SetStartFailExpectations(DataTypeController::StartResult result) {
137 if (DataTypeController::IsUnrecoverableResult(result))
138 EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, _));
139 EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
140 EXPECT_CALL(*dtc_mock_.get(), RecordStartFailure(result));
141 EXPECT_CALL(start_callback_, Run(result, _, _));
145 frontend_dtc_->LoadModels(
146 base::Bind(&ModelLoadCallbackMock::Run,
147 base::Unretained(&model_load_callback_)));
148 frontend_dtc_->StartAssociating(
149 base::Bind(&StartCallbackMock::Run,
150 base::Unretained(&start_callback_)));
154 message_loop_.RunUntilIdle();
157 base::MessageLoopForUI message_loop_;
158 content::TestBrowserThread ui_thread_;
159 scoped_refptr<FrontendDataTypeControllerFake> frontend_dtc_;
160 scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
161 scoped_refptr<FrontendDataTypeControllerMock> dtc_mock_;
162 ProfileMock profile_;
163 ProfileSyncServiceMock service_;
164 ModelAssociatorMock* model_associator_;
165 ChangeProcessorMock* change_processor_;
166 StartCallbackMock start_callback_;
167 ModelLoadCallbackMock model_load_callback_;
170 TEST_F(SyncFrontendDataTypeControllerTest, StartOk) {
171 SetStartExpectations();
172 SetAssociateExpectations();
173 SetActivateExpectations(DataTypeController::OK);
174 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
176 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
179 TEST_F(SyncFrontendDataTypeControllerTest, StartFirstRun) {
180 SetStartExpectations();
181 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
182 WillOnce(Return(true));
183 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
184 WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
185 EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
186 WillOnce(Return(syncer::SyncError()));
187 EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
188 SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
189 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
191 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
194 TEST_F(SyncFrontendDataTypeControllerTest, AbortDuringStartModels) {
195 EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(false));
196 EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
197 EXPECT_CALL(model_load_callback_, Run(_, _));
198 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
199 frontend_dtc_->LoadModels(
200 base::Bind(&ModelLoadCallbackMock::Run,
201 base::Unretained(&model_load_callback_)));
202 EXPECT_EQ(DataTypeController::MODEL_STARTING, frontend_dtc_->state());
203 frontend_dtc_->Stop();
204 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
207 TEST_F(SyncFrontendDataTypeControllerTest, StartAssociationFailed) {
208 SetStartExpectations();
209 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
210 WillOnce(Return(true));
211 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
212 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
213 EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
214 WillOnce(Return(syncer::SyncError(FROM_HERE,
215 syncer::SyncError::DATATYPE_ERROR,
217 syncer::BOOKMARKS)));
219 EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
220 SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
221 // Set up association to fail with an association failed error.
222 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
224 EXPECT_EQ(DataTypeController::DISABLED, frontend_dtc_->state());
227 TEST_F(SyncFrontendDataTypeControllerTest,
228 StartAssociationTriggersUnrecoverableError) {
229 SetStartExpectations();
230 SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
231 // Set up association to fail with an unrecoverable error.
232 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
233 WillRepeatedly(Return(true));
234 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
235 WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
236 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
238 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
241 TEST_F(SyncFrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
242 SetStartExpectations();
243 SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
244 // Set up association to fail with a NEEDS_CRYPTO error.
245 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
246 WillRepeatedly(Return(false));
247 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
249 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
252 TEST_F(SyncFrontendDataTypeControllerTest, Stop) {
253 SetStartExpectations();
254 SetAssociateExpectations();
255 SetActivateExpectations(DataTypeController::OK);
256 SetStopExpectations();
257 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
259 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
260 frontend_dtc_->Stop();
261 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
264 TEST_F(SyncFrontendDataTypeControllerTest, OnSingleDatatypeUnrecoverableError) {
265 SetStartExpectations();
266 SetAssociateExpectations();
267 SetActivateExpectations(DataTypeController::OK);
268 EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, "Test"));
269 EXPECT_CALL(service_, DisableBrokenDatatype(_, _, _))
270 .WillOnce(InvokeWithoutArgs(frontend_dtc_.get(),
271 &FrontendDataTypeController::Stop));
272 SetStopExpectations();
273 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
275 EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
276 // This should cause frontend_dtc_->Stop() to be called.
277 frontend_dtc_->OnSingleDatatypeUnrecoverableError(FROM_HERE, "Test");
279 EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());