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"
13 namespace browser_sync
{
14 class MockModelAssociationResultProcessor
:
15 public ModelAssociationResultProcessor
{
17 MockModelAssociationResultProcessor() {}
18 ~MockModelAssociationResultProcessor() {}
19 MOCK_METHOD2(OnSingleDataTypeAssociationDone
,
20 void(syncer::ModelType type
,
21 const syncer::DataTypeAssociationStats
& association_stats
));
22 MOCK_METHOD1(OnModelAssociationDone
, void(
23 const DataTypeManager::ConfigureResult
& result
));
26 FakeDataTypeController
* GetController(
27 const DataTypeController::TypeMap
& controllers
,
28 syncer::ModelType model_type
) {
29 DataTypeController::TypeMap::const_iterator it
=
30 controllers
.find(model_type
);
31 if (it
== controllers
.end()) {
34 return (FakeDataTypeController
*)(it
->second
.get());
37 ACTION_P(VerifyResult
, expected_result
) {
38 EXPECT_EQ(arg0
.status
, expected_result
.status
);
39 EXPECT_TRUE(arg0
.requested_types
.Equals(expected_result
.requested_types
));
40 EXPECT_EQ(arg0
.failed_data_types
.size(),
41 expected_result
.failed_data_types
.size());
43 if (arg0
.failed_data_types
.size() ==
44 expected_result
.failed_data_types
.size()) {
45 std::map
<syncer::ModelType
, syncer::SyncError
>::const_iterator it1
, it2
;
46 for (it1
= arg0
.failed_data_types
.begin(),
47 it2
= expected_result
.failed_data_types
.begin();
48 it1
!= arg0
.failed_data_types
.end();
50 EXPECT_EQ((*it1
).first
, (*it2
).first
);
54 EXPECT_TRUE(arg0
.unfinished_data_types
.Equals(
55 expected_result
.unfinished_data_types
));
58 class SyncModelAssociationManagerTest
: public testing::Test
{
60 SyncModelAssociationManagerTest() {
64 base::MessageLoopForUI ui_loop_
;
65 MockModelAssociationResultProcessor result_processor_
;
66 DataTypeController::TypeMap controllers_
;
69 // Start a type and make sure ModelAssociationManager callst the |Start|
70 // method and calls the callback when it is done.
71 TEST_F(SyncModelAssociationManagerTest
, SimpleModelStart
) {
72 controllers_
[syncer::BOOKMARKS
] =
73 new FakeDataTypeController(syncer::BOOKMARKS
);
74 controllers_
[syncer::APPS
] =
75 new FakeDataTypeController(syncer::APPS
);
76 ModelAssociationManager
model_association_manager(&controllers_
,
78 syncer::ModelTypeSet
types(syncer::BOOKMARKS
, syncer::APPS
);
79 DataTypeManager::ConfigureResult
expected_result(
82 std::map
<syncer::ModelType
, syncer::SyncError
>(),
83 syncer::ModelTypeSet(),
84 syncer::ModelTypeSet());
85 EXPECT_CALL(result_processor_
, OnModelAssociationDone(_
)).
86 WillOnce(VerifyResult(expected_result
));
88 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
89 DataTypeController::NOT_RUNNING
);
90 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
91 DataTypeController::NOT_RUNNING
);
93 // Initialize() kicks off model loading.
94 model_association_manager
.Initialize(types
);
96 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
97 DataTypeController::MODEL_LOADED
);
98 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
99 DataTypeController::MODEL_LOADED
);
101 model_association_manager
.StartAssociationAsync(types
);
103 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
104 DataTypeController::ASSOCIATING
);
105 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
106 DataTypeController::ASSOCIATING
);
107 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
108 DataTypeController::OK
);
109 GetController(controllers_
, syncer::APPS
)->FinishStart(
110 DataTypeController::OK
);
113 // Start a type and call stop before it finishes associating.
114 TEST_F(SyncModelAssociationManagerTest
, StopModelBeforeFinish
) {
115 controllers_
[syncer::BOOKMARKS
] =
116 new FakeDataTypeController(syncer::BOOKMARKS
);
117 ModelAssociationManager
model_association_manager(
121 syncer::ModelTypeSet types
;
122 types
.Put(syncer::BOOKMARKS
);
124 std::map
<syncer::ModelType
, syncer::SyncError
> errors
;
125 syncer::SyncError
error(FROM_HERE
,
126 syncer::SyncError::DATATYPE_ERROR
,
129 errors
[syncer::BOOKMARKS
] = error
;
131 DataTypeManager::ConfigureResult
expected_result(
132 DataTypeManager::ABORTED
,
135 syncer::ModelTypeSet(syncer::BOOKMARKS
),
136 syncer::ModelTypeSet());
138 EXPECT_CALL(result_processor_
, OnModelAssociationDone(_
)).
139 WillOnce(VerifyResult(expected_result
));
141 model_association_manager
.Initialize(types
);
142 model_association_manager
.StartAssociationAsync(types
);
144 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
145 DataTypeController::ASSOCIATING
);
146 model_association_manager
.Stop();
147 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
148 DataTypeController::NOT_RUNNING
);
151 // Start a type, let it finish and then call stop.
152 TEST_F(SyncModelAssociationManagerTest
, StopAfterFinish
) {
153 controllers_
[syncer::BOOKMARKS
] =
154 new FakeDataTypeController(syncer::BOOKMARKS
);
155 ModelAssociationManager
model_association_manager(
158 syncer::ModelTypeSet types
;
159 types
.Put(syncer::BOOKMARKS
);
160 DataTypeManager::ConfigureResult
expected_result(
163 std::map
<syncer::ModelType
, syncer::SyncError
>(),
164 syncer::ModelTypeSet(),
165 syncer::ModelTypeSet());
166 EXPECT_CALL(result_processor_
, OnModelAssociationDone(_
)).
167 WillOnce(VerifyResult(expected_result
));
169 model_association_manager
.Initialize(types
);
170 model_association_manager
.StartAssociationAsync(types
);
172 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
173 DataTypeController::ASSOCIATING
);
174 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
175 DataTypeController::OK
);
177 model_association_manager
.Stop();
178 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
179 DataTypeController::NOT_RUNNING
);
182 // Make a type fail model association and verify correctness.
183 TEST_F(SyncModelAssociationManagerTest
, TypeFailModelAssociation
) {
184 controllers_
[syncer::BOOKMARKS
] =
185 new FakeDataTypeController(syncer::BOOKMARKS
);
186 ModelAssociationManager
model_association_manager(
189 syncer::ModelTypeSet types
;
190 types
.Put(syncer::BOOKMARKS
);
191 std::map
<syncer::ModelType
, syncer::SyncError
> errors
;
192 syncer::SyncError
error(FROM_HERE
,
193 syncer::SyncError::DATATYPE_ERROR
,
196 errors
[syncer::BOOKMARKS
] = error
;
197 DataTypeManager::ConfigureResult
expected_result(
198 DataTypeManager::PARTIAL_SUCCESS
,
201 syncer::ModelTypeSet(),
202 syncer::ModelTypeSet());
203 EXPECT_CALL(result_processor_
, OnModelAssociationDone(_
)).
204 WillOnce(VerifyResult(expected_result
));
206 model_association_manager
.Initialize(types
);
207 model_association_manager
.StartAssociationAsync(types
);
209 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
210 DataTypeController::ASSOCIATING
);
211 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
212 DataTypeController::ASSOCIATION_FAILED
);
213 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
214 DataTypeController::NOT_RUNNING
);
217 // Ensure configuring stops when a type returns a unrecoverable error.
218 TEST_F(SyncModelAssociationManagerTest
, TypeReturnUnrecoverableError
) {
219 controllers_
[syncer::BOOKMARKS
] =
220 new FakeDataTypeController(syncer::BOOKMARKS
);
221 ModelAssociationManager
model_association_manager(
224 syncer::ModelTypeSet types
;
225 types
.Put(syncer::BOOKMARKS
);
226 std::map
<syncer::ModelType
, syncer::SyncError
> errors
;
227 syncer::SyncError
error(FROM_HERE
,
228 syncer::SyncError::DATATYPE_ERROR
,
231 errors
[syncer::BOOKMARKS
] = error
;
232 DataTypeManager::ConfigureResult
expected_result(
233 DataTypeManager::UNRECOVERABLE_ERROR
,
236 syncer::ModelTypeSet(),
237 syncer::ModelTypeSet());
238 EXPECT_CALL(result_processor_
, OnModelAssociationDone(_
)).
239 WillOnce(VerifyResult(expected_result
));
241 model_association_manager
.Initialize(types
);
243 model_association_manager
.StartAssociationAsync(types
);
245 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
246 DataTypeController::ASSOCIATING
);
247 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
248 DataTypeController::UNRECOVERABLE_ERROR
);
251 TEST_F(SyncModelAssociationManagerTest
, SlowTypeAsFailedType
) {
252 controllers_
[syncer::BOOKMARKS
] =
253 new FakeDataTypeController(syncer::BOOKMARKS
);
254 controllers_
[syncer::APPS
] =
255 new FakeDataTypeController(syncer::APPS
);
256 GetController(controllers_
, syncer::BOOKMARKS
)->SetDelayModelLoad();
257 ModelAssociationManager
model_association_manager(&controllers_
,
259 syncer::ModelTypeSet types
;
260 types
.Put(syncer::BOOKMARKS
);
261 types
.Put(syncer::APPS
);
263 std::map
<syncer::ModelType
, syncer::SyncError
> errors
;
264 syncer::SyncError
error(FROM_HERE
,
265 syncer::SyncError::DATATYPE_ERROR
,
266 "Association timed out.",
268 errors
[syncer::BOOKMARKS
] = error
;
270 syncer::ModelTypeSet expected_types_unfinished
;
271 expected_types_unfinished
.Put(syncer::BOOKMARKS
);
272 DataTypeManager::ConfigureResult
expected_result_partially_done(
273 DataTypeManager::PARTIAL_SUCCESS
,
276 expected_types_unfinished
,
277 syncer::ModelTypeSet());
279 EXPECT_CALL(result_processor_
, OnModelAssociationDone(_
)).
280 WillOnce(VerifyResult(expected_result_partially_done
));
282 model_association_manager
.Initialize(types
);
283 model_association_manager
.StartAssociationAsync(types
);
284 GetController(controllers_
, syncer::APPS
)->FinishStart(
285 DataTypeController::OK
);
287 model_association_manager
.GetTimerForTesting()->user_task().Run();
289 EXPECT_EQ(DataTypeController::NOT_RUNNING
,
290 GetController(controllers_
, syncer::BOOKMARKS
)->state());
293 TEST_F(SyncModelAssociationManagerTest
, StartMultipleTimes
) {
294 controllers_
[syncer::BOOKMARKS
] =
295 new FakeDataTypeController(syncer::BOOKMARKS
);
296 controllers_
[syncer::APPS
] =
297 new FakeDataTypeController(syncer::APPS
);
298 ModelAssociationManager
model_association_manager(&controllers_
,
300 syncer::ModelTypeSet types
;
301 types
.Put(syncer::BOOKMARKS
);
302 types
.Put(syncer::APPS
);
304 DataTypeManager::ConfigureResult
result_1st(
306 syncer::ModelTypeSet(syncer::BOOKMARKS
),
307 std::map
<syncer::ModelType
, syncer::SyncError
>(),
308 syncer::ModelTypeSet(),
309 syncer::ModelTypeSet());
310 DataTypeManager::ConfigureResult
result_2nd(
312 syncer::ModelTypeSet(syncer::APPS
),
313 std::map
<syncer::ModelType
, syncer::SyncError
>(),
314 syncer::ModelTypeSet(),
315 syncer::ModelTypeSet());
316 EXPECT_CALL(result_processor_
, OnModelAssociationDone(_
)).
318 WillOnce(VerifyResult(result_1st
)).
319 WillOnce(VerifyResult(result_2nd
));
321 model_association_manager
.Initialize(types
);
323 // Start BOOKMARKS first.
324 model_association_manager
.StartAssociationAsync(
325 syncer::ModelTypeSet(syncer::BOOKMARKS
));
326 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
327 DataTypeController::ASSOCIATING
);
328 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
329 DataTypeController::MODEL_LOADED
);
331 // Finish BOOKMARKS association.
332 GetController(controllers_
, syncer::BOOKMARKS
)->FinishStart(
333 DataTypeController::OK
);
334 EXPECT_EQ(GetController(controllers_
, syncer::BOOKMARKS
)->state(),
335 DataTypeController::RUNNING
);
336 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
337 DataTypeController::MODEL_LOADED
);
340 model_association_manager
.StartAssociationAsync(
341 syncer::ModelTypeSet(syncer::APPS
));
342 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
343 DataTypeController::ASSOCIATING
);
344 GetController(controllers_
, syncer::APPS
)->FinishStart(
345 DataTypeController::OK
);
346 EXPECT_EQ(GetController(controllers_
, syncer::APPS
)->state(),
347 DataTypeController::RUNNING
);
350 // Test that model that failed to load between initialization and association
351 // is reported and stopped properly.
352 TEST_F(SyncModelAssociationManagerTest
, ModelLoadFailBeforeAssociationStart
) {
353 controllers_
[syncer::BOOKMARKS
] =
354 new FakeDataTypeController(syncer::BOOKMARKS
);
355 GetController(controllers_
, syncer::BOOKMARKS
)->SetModelLoadError(
356 syncer::SyncError(FROM_HERE
, syncer::SyncError::DATATYPE_ERROR
,
357 "", syncer::BOOKMARKS
));
358 ModelAssociationManager
model_association_manager(
361 syncer::ModelTypeSet types
;
362 types
.Put(syncer::BOOKMARKS
);
363 std::map
<syncer::ModelType
, syncer::SyncError
> errors
;
364 syncer::SyncError
error(FROM_HERE
,
365 syncer::SyncError::DATATYPE_ERROR
,
368 errors
[syncer::BOOKMARKS
] = error
;
369 DataTypeManager::ConfigureResult
expected_result(
370 DataTypeManager::PARTIAL_SUCCESS
,
373 syncer::ModelTypeSet(),
374 syncer::ModelTypeSet());
375 EXPECT_CALL(result_processor_
, OnModelAssociationDone(_
)).
376 WillOnce(VerifyResult(expected_result
));
378 model_association_manager
.Initialize(types
);
379 EXPECT_EQ(DataTypeController::DISABLED
,
380 GetController(controllers_
, syncer::BOOKMARKS
)->state());
381 model_association_manager
.StartAssociationAsync(types
);
382 EXPECT_EQ(DataTypeController::NOT_RUNNING
,
383 GetController(controllers_
, syncer::BOOKMARKS
)->state());
386 } // namespace browser_sync