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 "base/callback.h"
6 #include "base/message_loop/message_loop.h"
7 #include "components/sync_driver/fake_data_type_controller.h"
8 #include "components/sync_driver/model_association_manager.h"
9 #include "testing/gmock/include/gmock/gmock.h"
10 #include "testing/gtest/include/gtest/gtest.h"
14 namespace sync_driver
{
16 class MockModelAssociationManagerDelegate
:
17 public ModelAssociationManagerDelegate
{
19 MockModelAssociationManagerDelegate() {}
20 ~MockModelAssociationManagerDelegate() {}
21 MOCK_METHOD2(OnSingleDataTypeAssociationDone
,
22 void(syncer::ModelType type
,
23 const syncer::DataTypeAssociationStats
& association_stats
));
24 MOCK_METHOD2(OnSingleDataTypeWillStop
,
25 void(syncer::ModelType
, const syncer::SyncError
& error
));
26 MOCK_METHOD1(OnModelAssociationDone
, void(
27 const DataTypeManager::ConfigureResult
& result
));
30 FakeDataTypeController
* GetController(
31 const DataTypeController::TypeMap
& controllers
,
32 syncer::ModelType model_type
) {
33 DataTypeController::TypeMap::const_iterator it
=
34 controllers
.find(model_type
);
35 if (it
== controllers
.end()) {
38 return (FakeDataTypeController
*)(it
->second
.get());
41 ACTION_P(VerifyResult
, expected_result
) {
42 EXPECT_EQ(arg0
.status
, expected_result
.status
);
43 EXPECT_TRUE(arg0
.requested_types
.Equals(expected_result
.requested_types
));
46 class SyncModelAssociationManagerTest
: public testing::Test
{
48 SyncModelAssociationManagerTest() {
52 base::MessageLoopForUI ui_loop_
;
53 MockModelAssociationManagerDelegate delegate_
;
54 DataTypeController::TypeMap controllers_
;
57 // Start a type and make sure ModelAssociationManager callst the |Start|
58 // method and calls the callback when it is done.
59 TEST_F(SyncModelAssociationManagerTest
, SimpleModelStart
) {
60 controllers_
[syncer::BOOKMARKS
] =
61 new FakeDataTypeController(syncer::BOOKMARKS
);
62 controllers_
[syncer::APPS
] =
63 new FakeDataTypeController(syncer::APPS
);
64 ModelAssociationManager
model_association_manager(&controllers_
,
66 syncer::ModelTypeSet
types(syncer::BOOKMARKS
, syncer::APPS
);
67 DataTypeManager::ConfigureResult
expected_result(DataTypeManager::OK
, types
);
68 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
69 WillOnce(VerifyResult(expected_result
));
71 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
72 DataTypeController::NOT_RUNNING
);
73 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
74 DataTypeController::NOT_RUNNING
);
76 // Initialize() kicks off model loading.
77 model_association_manager
.Initialize(types
);
79 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
80 DataTypeController::MODEL_LOADED
);
81 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
82 DataTypeController::MODEL_LOADED
);
84 model_association_manager
.StartAssociationAsync(types
);
86 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
87 DataTypeController::ASSOCIATING
);
88 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
89 DataTypeController::ASSOCIATING
);
90 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
91 DataTypeController::OK
);
92 GetController(controllers_
, syncer::APPS
)->FinishStart(
93 DataTypeController::OK
);
96 // Start a type and call stop before it finishes associating.
97 TEST_F(SyncModelAssociationManagerTest
, StopModelBeforeFinish
) {
98 controllers_
[syncer::BOOKMARKS
] =
99 new FakeDataTypeController(syncer::BOOKMARKS
);
100 ModelAssociationManager
model_association_manager(
104 syncer::ModelTypeSet types
;
105 types
.Put(syncer::BOOKMARKS
);
107 DataTypeManager::ConfigureResult
expected_result(DataTypeManager::ABORTED
,
110 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
111 WillOnce(VerifyResult(expected_result
));
112 EXPECT_CALL(delegate_
,
113 OnSingleDataTypeWillStop(syncer::BOOKMARKS
, _
));
115 model_association_manager
.Initialize(types
);
116 model_association_manager
.StartAssociationAsync(types
);
118 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
119 DataTypeController::ASSOCIATING
);
120 model_association_manager
.Stop();
121 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
122 DataTypeController::NOT_RUNNING
);
125 // Start a type, let it finish and then call stop.
126 TEST_F(SyncModelAssociationManagerTest
, StopAfterFinish
) {
127 controllers_
[syncer::BOOKMARKS
] =
128 new FakeDataTypeController(syncer::BOOKMARKS
);
129 ModelAssociationManager
model_association_manager(
132 syncer::ModelTypeSet types
;
133 types
.Put(syncer::BOOKMARKS
);
134 DataTypeManager::ConfigureResult
expected_result(DataTypeManager::OK
, types
);
135 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
136 WillOnce(VerifyResult(expected_result
));
137 EXPECT_CALL(delegate_
,
138 OnSingleDataTypeWillStop(syncer::BOOKMARKS
, _
));
140 model_association_manager
.Initialize(types
);
141 model_association_manager
.StartAssociationAsync(types
);
143 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
144 DataTypeController::ASSOCIATING
);
145 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
146 DataTypeController::OK
);
148 model_association_manager
.Stop();
149 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
150 DataTypeController::NOT_RUNNING
);
153 // Make a type fail model association and verify correctness.
154 TEST_F(SyncModelAssociationManagerTest
, TypeFailModelAssociation
) {
155 controllers_
[syncer::BOOKMARKS
] =
156 new FakeDataTypeController(syncer::BOOKMARKS
);
157 ModelAssociationManager
model_association_manager(
160 syncer::ModelTypeSet types
;
161 types
.Put(syncer::BOOKMARKS
);
162 DataTypeManager::ConfigureResult
expected_result(DataTypeManager::OK
, types
);
163 EXPECT_CALL(delegate_
,
164 OnSingleDataTypeWillStop(syncer::BOOKMARKS
, _
));
165 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
166 WillOnce(VerifyResult(expected_result
));
168 model_association_manager
.Initialize(types
);
169 model_association_manager
.StartAssociationAsync(types
);
171 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
172 DataTypeController::ASSOCIATING
);
173 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
174 DataTypeController::ASSOCIATION_FAILED
);
175 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
176 DataTypeController::NOT_RUNNING
);
179 // Ensure configuring stops when a type returns a unrecoverable error.
180 TEST_F(SyncModelAssociationManagerTest
, TypeReturnUnrecoverableError
) {
181 controllers_
[syncer::BOOKMARKS
] =
182 new FakeDataTypeController(syncer::BOOKMARKS
);
183 ModelAssociationManager
model_association_manager(
186 syncer::ModelTypeSet types
;
187 types
.Put(syncer::BOOKMARKS
);
188 DataTypeManager::ConfigureResult
expected_result(
189 DataTypeManager::UNRECOVERABLE_ERROR
, types
);
190 EXPECT_CALL(delegate_
,
191 OnSingleDataTypeWillStop(syncer::BOOKMARKS
, _
));
192 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
193 WillOnce(VerifyResult(expected_result
));
195 model_association_manager
.Initialize(types
);
197 model_association_manager
.StartAssociationAsync(types
);
199 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
200 DataTypeController::ASSOCIATING
);
201 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
202 DataTypeController::UNRECOVERABLE_ERROR
);
205 TEST_F(SyncModelAssociationManagerTest
, SlowTypeAsFailedType
) {
206 controllers_
[syncer::BOOKMARKS
] =
207 new FakeDataTypeController(syncer::BOOKMARKS
);
208 controllers_
[syncer::APPS
] =
209 new FakeDataTypeController(syncer::APPS
);
210 GetController(controllers_
, syncer::BOOKMARKS
)->SetDelayModelLoad();
211 ModelAssociationManager
model_association_manager(&controllers_
,
213 syncer::ModelTypeSet types
;
214 types
.Put(syncer::BOOKMARKS
);
215 types
.Put(syncer::APPS
);
217 syncer::ModelTypeSet expected_types_unfinished
;
218 expected_types_unfinished
.Put(syncer::BOOKMARKS
);
219 DataTypeManager::ConfigureResult
expected_result_partially_done(
220 DataTypeManager::OK
, types
);
222 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
223 WillOnce(VerifyResult(expected_result_partially_done
));
225 model_association_manager
.Initialize(types
);
226 model_association_manager
.StartAssociationAsync(types
);
227 GetController(controllers_
, syncer::APPS
)->FinishStart(
228 DataTypeController::OK
);
230 EXPECT_CALL(delegate_
,
231 OnSingleDataTypeWillStop(syncer::BOOKMARKS
, _
));
232 model_association_manager
.GetTimerForTesting()->user_task().Run();
234 EXPECT_EQ(DataTypeController::NOT_RUNNING
,
235 GetController(controllers_
, syncer::BOOKMARKS
)->state());
238 TEST_F(SyncModelAssociationManagerTest
, StartMultipleTimes
) {
239 controllers_
[syncer::BOOKMARKS
] =
240 new FakeDataTypeController(syncer::BOOKMARKS
);
241 controllers_
[syncer::APPS
] =
242 new FakeDataTypeController(syncer::APPS
);
243 ModelAssociationManager
model_association_manager(&controllers_
,
245 syncer::ModelTypeSet types
;
246 types
.Put(syncer::BOOKMARKS
);
247 types
.Put(syncer::APPS
);
249 DataTypeManager::ConfigureResult
result_1st(
251 syncer::ModelTypeSet(syncer::BOOKMARKS
));
252 DataTypeManager::ConfigureResult
result_2nd(
254 syncer::ModelTypeSet(syncer::APPS
));
255 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
257 WillOnce(VerifyResult(result_1st
)).
258 WillOnce(VerifyResult(result_2nd
));
260 model_association_manager
.Initialize(types
);
262 // Start BOOKMARKS first.
263 model_association_manager
.StartAssociationAsync(
264 syncer::ModelTypeSet(syncer::BOOKMARKS
));
265 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
266 DataTypeController::ASSOCIATING
);
267 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
268 DataTypeController::MODEL_LOADED
);
270 // Finish BOOKMARKS association.
271 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
272 DataTypeController::OK
);
273 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
274 DataTypeController::RUNNING
);
275 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
276 DataTypeController::MODEL_LOADED
);
279 model_association_manager
.StartAssociationAsync(
280 syncer::ModelTypeSet(syncer::APPS
));
281 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
282 DataTypeController::ASSOCIATING
);
283 GetController(controllers_
, syncer::APPS
)->FinishStart(
284 DataTypeController::OK
);
285 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
286 DataTypeController::RUNNING
);
289 // Test that model that failed to load between initialization and association
290 // is reported and stopped properly.
291 TEST_F(SyncModelAssociationManagerTest
, ModelLoadFailBeforeAssociationStart
) {
292 controllers_
[syncer::BOOKMARKS
] =
293 new FakeDataTypeController(syncer::BOOKMARKS
);
294 GetController(controllers_
, syncer::BOOKMARKS
)->SetModelLoadError(
295 syncer::SyncError(FROM_HERE
, syncer::SyncError::DATATYPE_ERROR
,
296 "", syncer::BOOKMARKS
));
297 ModelAssociationManager
model_association_manager(
300 syncer::ModelTypeSet types
;
301 types
.Put(syncer::BOOKMARKS
);
302 DataTypeManager::ConfigureResult
expected_result(DataTypeManager::OK
, types
);
303 EXPECT_CALL(delegate_
,
304 OnSingleDataTypeWillStop(syncer::BOOKMARKS
, _
));
305 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
306 WillOnce(VerifyResult(expected_result
));
308 model_association_manager
.Initialize(types
);
309 EXPECT_EQ(DataTypeController::NOT_RUNNING
,
310 GetController(controllers_
, syncer::BOOKMARKS
)->state());
311 model_association_manager
.StartAssociationAsync(types
);
312 EXPECT_EQ(DataTypeController::NOT_RUNNING
,
313 GetController(controllers_
, syncer::BOOKMARKS
)->state());
316 // Test that a runtime error is handled by stopping the type.
317 TEST_F(SyncModelAssociationManagerTest
, StopAfterConfiguration
) {
318 controllers_
[syncer::BOOKMARKS
] =
319 new FakeDataTypeController(syncer::BOOKMARKS
);
320 ModelAssociationManager
model_association_manager(
323 syncer::ModelTypeSet types
;
324 types
.Put(syncer::BOOKMARKS
);
325 DataTypeManager::ConfigureResult
expected_result(DataTypeManager::OK
, types
);
326 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
327 WillOnce(VerifyResult(expected_result
));
329 model_association_manager
.Initialize(types
);
330 model_association_manager
.StartAssociationAsync(types
);
332 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
333 DataTypeController::ASSOCIATING
);
334 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
335 DataTypeController::OK
);
336 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
337 DataTypeController::RUNNING
);
339 testing::Mock::VerifyAndClearExpectations(&delegate_
);
340 EXPECT_CALL(delegate_
,
341 OnSingleDataTypeWillStop(syncer::BOOKMARKS
, _
));
342 syncer::SyncError
error(FROM_HERE
,
343 syncer::SyncError::DATATYPE_ERROR
,
346 GetController(controllers_
, syncer::BOOKMARKS
)
347 ->OnSingleDataTypeUnrecoverableError(error
);
350 TEST_F(SyncModelAssociationManagerTest
, AbortDuringAssociation
) {
351 controllers_
[syncer::BOOKMARKS
] =
352 new FakeDataTypeController(syncer::BOOKMARKS
);
353 controllers_
[syncer::APPS
] =
354 new FakeDataTypeController(syncer::APPS
);
355 ModelAssociationManager
model_association_manager(&controllers_
,
357 syncer::ModelTypeSet types
;
358 types
.Put(syncer::BOOKMARKS
);
359 types
.Put(syncer::APPS
);
361 syncer::ModelTypeSet expected_types_unfinished
;
362 expected_types_unfinished
.Put(syncer::BOOKMARKS
);
363 DataTypeManager::ConfigureResult
expected_result_partially_done(
364 DataTypeManager::OK
, types
);
366 EXPECT_CALL(delegate_
, OnModelAssociationDone(_
)).
367 WillOnce(VerifyResult(expected_result_partially_done
));
369 model_association_manager
.Initialize(types
);
370 model_association_manager
.StartAssociationAsync(types
);
371 GetController(controllers_
, syncer::APPS
)->FinishStart(
372 DataTypeController::OK
);
373 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
374 DataTypeController::RUNNING
);
375 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
376 DataTypeController::ASSOCIATING
);
378 EXPECT_CALL(delegate_
,
379 OnSingleDataTypeWillStop(syncer::BOOKMARKS
, _
));
380 model_association_manager
.GetTimerForTesting()->user_task().Run();
382 EXPECT_EQ(DataTypeController::NOT_RUNNING
,
383 GetController(controllers_
, syncer::BOOKMARKS
)->state());
386 } // namespace sync_driver