OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "base/callback.h" | |
6 #include "base/message_loop/message_loop.h" | |
7 #include "chrome/browser/sync/glue/model_association_manager.h" | |
8 #include "components/sync_driver/fake_data_type_controller.h" | |
9 #include "content/public/test/test_browser_thread.h" | |
10 #include "testing/gmock/include/gmock/gmock.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 using ::testing::_; | |
14 namespace browser_sync { | |
15 class MockModelAssociationResultProcessor : | |
16 public ModelAssociationResultProcessor { | |
17 public: | |
18 MockModelAssociationResultProcessor() {} | |
19 ~MockModelAssociationResultProcessor() {} | |
20 MOCK_METHOD2(OnSingleDataTypeAssociationDone, | |
21 void(syncer::ModelType type, | |
22 const syncer::DataTypeAssociationStats& association_stats)); | |
23 MOCK_METHOD1(OnModelAssociationDone, void( | |
24 const DataTypeManager::ConfigureResult& result)); | |
25 }; | |
26 | |
27 FakeDataTypeController* GetController( | |
28 const DataTypeController::TypeMap& controllers, | |
29 syncer::ModelType model_type) { | |
30 DataTypeController::TypeMap::const_iterator it = | |
31 controllers.find(model_type); | |
32 if (it == controllers.end()) { | |
33 return NULL; | |
34 } | |
35 return (FakeDataTypeController*)(it->second.get()); | |
36 } | |
37 | |
38 ACTION_P(VerifyResult, expected_result) { | |
39 EXPECT_EQ(arg0.status, expected_result.status); | |
40 EXPECT_TRUE(arg0.requested_types.Equals(expected_result.requested_types)); | |
41 EXPECT_EQ(arg0.failed_data_types.size(), | |
42 expected_result.failed_data_types.size()); | |
43 | |
44 if (arg0.failed_data_types.size() == | |
45 expected_result.failed_data_types.size()) { | |
46 std::map<syncer::ModelType, syncer::SyncError>::const_iterator it1, it2; | |
47 for (it1 = arg0.failed_data_types.begin(), | |
48 it2 = expected_result.failed_data_types.begin(); | |
49 it1 != arg0.failed_data_types.end(); | |
50 ++it1, ++it2) { | |
51 EXPECT_EQ((*it1).first, (*it2).first); | |
52 } | |
53 } | |
54 | |
55 EXPECT_TRUE(arg0.unfinished_data_types.Equals( | |
56 expected_result.unfinished_data_types)); | |
57 } | |
58 | |
59 class SyncModelAssociationManagerTest : public testing::Test { | |
60 public: | |
61 SyncModelAssociationManagerTest() : | |
62 ui_thread_(content::BrowserThread::UI, &ui_loop_) { | |
63 } | |
64 | |
65 protected: | |
66 base::MessageLoopForUI ui_loop_; | |
67 content::TestBrowserThread ui_thread_; | |
68 MockModelAssociationResultProcessor result_processor_; | |
69 DataTypeController::TypeMap controllers_; | |
70 }; | |
71 | |
72 // Start a type and make sure ModelAssociationManager callst the |Start| | |
73 // method and calls the callback when it is done. | |
74 TEST_F(SyncModelAssociationManagerTest, SimpleModelStart) { | |
75 controllers_[syncer::BOOKMARKS] = | |
76 new FakeDataTypeController(syncer::BOOKMARKS); | |
77 controllers_[syncer::APPS] = | |
78 new FakeDataTypeController(syncer::APPS); | |
79 ModelAssociationManager model_association_manager(&controllers_, | |
80 &result_processor_); | |
81 syncer::ModelTypeSet types(syncer::BOOKMARKS, syncer::APPS); | |
82 DataTypeManager::ConfigureResult expected_result( | |
83 DataTypeManager::OK, | |
84 types, | |
85 std::map<syncer::ModelType, syncer::SyncError>(), | |
86 syncer::ModelTypeSet(), | |
87 syncer::ModelTypeSet()); | |
88 EXPECT_CALL(result_processor_, OnModelAssociationDone(_)). | |
89 WillOnce(VerifyResult(expected_result)); | |
90 | |
91 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
92 DataTypeController::NOT_RUNNING); | |
93 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), | |
94 DataTypeController::NOT_RUNNING); | |
95 | |
96 // Initialize() kicks off model loading. | |
97 model_association_manager.Initialize(types); | |
98 | |
99 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
100 DataTypeController::MODEL_LOADED); | |
101 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), | |
102 DataTypeController::MODEL_LOADED); | |
103 | |
104 model_association_manager.StartAssociationAsync(types); | |
105 | |
106 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
107 DataTypeController::ASSOCIATING); | |
108 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), | |
109 DataTypeController::ASSOCIATING); | |
110 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( | |
111 DataTypeController::OK); | |
112 GetController(controllers_, syncer::APPS)->FinishStart( | |
113 DataTypeController::OK); | |
114 } | |
115 | |
116 // Start a type and call stop before it finishes associating. | |
117 TEST_F(SyncModelAssociationManagerTest, StopModelBeforeFinish) { | |
118 controllers_[syncer::BOOKMARKS] = | |
119 new FakeDataTypeController(syncer::BOOKMARKS); | |
120 ModelAssociationManager model_association_manager( | |
121 &controllers_, | |
122 &result_processor_); | |
123 | |
124 syncer::ModelTypeSet types; | |
125 types.Put(syncer::BOOKMARKS); | |
126 | |
127 std::map<syncer::ModelType, syncer::SyncError> errors; | |
128 syncer::SyncError error(FROM_HERE, | |
129 syncer::SyncError::DATATYPE_ERROR, | |
130 "Failed", | |
131 syncer::BOOKMARKS); | |
132 errors[syncer::BOOKMARKS] = error; | |
133 | |
134 DataTypeManager::ConfigureResult expected_result( | |
135 DataTypeManager::ABORTED, | |
136 types, | |
137 errors, | |
138 syncer::ModelTypeSet(syncer::BOOKMARKS), | |
139 syncer::ModelTypeSet()); | |
140 | |
141 EXPECT_CALL(result_processor_, OnModelAssociationDone(_)). | |
142 WillOnce(VerifyResult(expected_result)); | |
143 | |
144 model_association_manager.Initialize(types); | |
145 model_association_manager.StartAssociationAsync(types); | |
146 | |
147 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
148 DataTypeController::ASSOCIATING); | |
149 model_association_manager.Stop(); | |
150 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
151 DataTypeController::NOT_RUNNING); | |
152 } | |
153 | |
154 // Start a type, let it finish and then call stop. | |
155 TEST_F(SyncModelAssociationManagerTest, StopAfterFinish) { | |
156 controllers_[syncer::BOOKMARKS] = | |
157 new FakeDataTypeController(syncer::BOOKMARKS); | |
158 ModelAssociationManager model_association_manager( | |
159 &controllers_, | |
160 &result_processor_); | |
161 syncer::ModelTypeSet types; | |
162 types.Put(syncer::BOOKMARKS); | |
163 DataTypeManager::ConfigureResult expected_result( | |
164 DataTypeManager::OK, | |
165 types, | |
166 std::map<syncer::ModelType, syncer::SyncError>(), | |
167 syncer::ModelTypeSet(), | |
168 syncer::ModelTypeSet()); | |
169 EXPECT_CALL(result_processor_, OnModelAssociationDone(_)). | |
170 WillOnce(VerifyResult(expected_result)); | |
171 | |
172 model_association_manager.Initialize(types); | |
173 model_association_manager.StartAssociationAsync(types); | |
174 | |
175 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
176 DataTypeController::ASSOCIATING); | |
177 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( | |
178 DataTypeController::OK); | |
179 | |
180 model_association_manager.Stop(); | |
181 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
182 DataTypeController::NOT_RUNNING); | |
183 } | |
184 | |
185 // Make a type fail model association and verify correctness. | |
186 TEST_F(SyncModelAssociationManagerTest, TypeFailModelAssociation) { | |
187 controllers_[syncer::BOOKMARKS] = | |
188 new FakeDataTypeController(syncer::BOOKMARKS); | |
189 ModelAssociationManager model_association_manager( | |
190 &controllers_, | |
191 &result_processor_); | |
192 syncer::ModelTypeSet types; | |
193 types.Put(syncer::BOOKMARKS); | |
194 std::map<syncer::ModelType, syncer::SyncError> errors; | |
195 syncer::SyncError error(FROM_HERE, | |
196 syncer::SyncError::DATATYPE_ERROR, | |
197 "Failed", | |
198 syncer::BOOKMARKS); | |
199 errors[syncer::BOOKMARKS] = error; | |
200 DataTypeManager::ConfigureResult expected_result( | |
201 DataTypeManager::PARTIAL_SUCCESS, | |
202 types, | |
203 errors, | |
204 syncer::ModelTypeSet(), | |
205 syncer::ModelTypeSet()); | |
206 EXPECT_CALL(result_processor_, OnModelAssociationDone(_)). | |
207 WillOnce(VerifyResult(expected_result)); | |
208 | |
209 model_association_manager.Initialize(types); | |
210 model_association_manager.StartAssociationAsync(types); | |
211 | |
212 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
213 DataTypeController::ASSOCIATING); | |
214 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( | |
215 DataTypeController::ASSOCIATION_FAILED); | |
216 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
217 DataTypeController::NOT_RUNNING); | |
218 } | |
219 | |
220 // Ensure configuring stops when a type returns a unrecoverable error. | |
221 TEST_F(SyncModelAssociationManagerTest, TypeReturnUnrecoverableError) { | |
222 controllers_[syncer::BOOKMARKS] = | |
223 new FakeDataTypeController(syncer::BOOKMARKS); | |
224 ModelAssociationManager model_association_manager( | |
225 &controllers_, | |
226 &result_processor_); | |
227 syncer::ModelTypeSet types; | |
228 types.Put(syncer::BOOKMARKS); | |
229 std::map<syncer::ModelType, syncer::SyncError> errors; | |
230 syncer::SyncError error(FROM_HERE, | |
231 syncer::SyncError::DATATYPE_ERROR, | |
232 "Failed", | |
233 syncer::BOOKMARKS); | |
234 errors[syncer::BOOKMARKS] = error; | |
235 DataTypeManager::ConfigureResult expected_result( | |
236 DataTypeManager::UNRECOVERABLE_ERROR, | |
237 types, | |
238 errors, | |
239 syncer::ModelTypeSet(), | |
240 syncer::ModelTypeSet()); | |
241 EXPECT_CALL(result_processor_, OnModelAssociationDone(_)). | |
242 WillOnce(VerifyResult(expected_result)); | |
243 | |
244 model_association_manager.Initialize(types); | |
245 | |
246 model_association_manager.StartAssociationAsync(types); | |
247 | |
248 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
249 DataTypeController::ASSOCIATING); | |
250 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( | |
251 DataTypeController::UNRECOVERABLE_ERROR); | |
252 } | |
253 | |
254 TEST_F(SyncModelAssociationManagerTest, SlowTypeAsFailedType) { | |
255 controllers_[syncer::BOOKMARKS] = | |
256 new FakeDataTypeController(syncer::BOOKMARKS); | |
257 controllers_[syncer::APPS] = | |
258 new FakeDataTypeController(syncer::APPS); | |
259 GetController(controllers_, syncer::BOOKMARKS)->SetDelayModelLoad(); | |
260 ModelAssociationManager model_association_manager(&controllers_, | |
261 &result_processor_); | |
262 syncer::ModelTypeSet types; | |
263 types.Put(syncer::BOOKMARKS); | |
264 types.Put(syncer::APPS); | |
265 | |
266 std::map<syncer::ModelType, syncer::SyncError> errors; | |
267 syncer::SyncError error(FROM_HERE, | |
268 syncer::SyncError::DATATYPE_ERROR, | |
269 "Association timed out.", | |
270 syncer::BOOKMARKS); | |
271 errors[syncer::BOOKMARKS] = error; | |
272 | |
273 syncer::ModelTypeSet expected_types_unfinished; | |
274 expected_types_unfinished.Put(syncer::BOOKMARKS); | |
275 DataTypeManager::ConfigureResult expected_result_partially_done( | |
276 DataTypeManager::PARTIAL_SUCCESS, | |
277 types, | |
278 errors, | |
279 expected_types_unfinished, | |
280 syncer::ModelTypeSet()); | |
281 | |
282 EXPECT_CALL(result_processor_, OnModelAssociationDone(_)). | |
283 WillOnce(VerifyResult(expected_result_partially_done)); | |
284 | |
285 model_association_manager.Initialize(types); | |
286 model_association_manager.StartAssociationAsync(types); | |
287 GetController(controllers_, syncer::APPS)->FinishStart( | |
288 DataTypeController::OK); | |
289 | |
290 model_association_manager.GetTimerForTesting()->user_task().Run(); | |
291 | |
292 EXPECT_EQ(DataTypeController::NOT_RUNNING, | |
293 GetController(controllers_, syncer::BOOKMARKS)->state()); | |
294 } | |
295 | |
296 TEST_F(SyncModelAssociationManagerTest, StartMultipleTimes) { | |
297 controllers_[syncer::BOOKMARKS] = | |
298 new FakeDataTypeController(syncer::BOOKMARKS); | |
299 controllers_[syncer::APPS] = | |
300 new FakeDataTypeController(syncer::APPS); | |
301 ModelAssociationManager model_association_manager(&controllers_, | |
302 &result_processor_); | |
303 syncer::ModelTypeSet types; | |
304 types.Put(syncer::BOOKMARKS); | |
305 types.Put(syncer::APPS); | |
306 | |
307 DataTypeManager::ConfigureResult result_1st( | |
308 DataTypeManager::OK, | |
309 syncer::ModelTypeSet(syncer::BOOKMARKS), | |
310 std::map<syncer::ModelType, syncer::SyncError>(), | |
311 syncer::ModelTypeSet(), | |
312 syncer::ModelTypeSet()); | |
313 DataTypeManager::ConfigureResult result_2nd( | |
314 DataTypeManager::OK, | |
315 syncer::ModelTypeSet(syncer::APPS), | |
316 std::map<syncer::ModelType, syncer::SyncError>(), | |
317 syncer::ModelTypeSet(), | |
318 syncer::ModelTypeSet()); | |
319 EXPECT_CALL(result_processor_, OnModelAssociationDone(_)). | |
320 Times(2). | |
321 WillOnce(VerifyResult(result_1st)). | |
322 WillOnce(VerifyResult(result_2nd)); | |
323 | |
324 model_association_manager.Initialize(types); | |
325 | |
326 // Start BOOKMARKS first. | |
327 model_association_manager.StartAssociationAsync( | |
328 syncer::ModelTypeSet(syncer::BOOKMARKS)); | |
329 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
330 DataTypeController::ASSOCIATING); | |
331 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), | |
332 DataTypeController::MODEL_LOADED); | |
333 | |
334 // Finish BOOKMARKS association. | |
335 GetController(controllers_, syncer::BOOKMARKS)->FinishStart( | |
336 DataTypeController::OK); | |
337 EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(), | |
338 DataTypeController::RUNNING); | |
339 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), | |
340 DataTypeController::MODEL_LOADED); | |
341 | |
342 // Start APPS next. | |
343 model_association_manager.StartAssociationAsync( | |
344 syncer::ModelTypeSet(syncer::APPS)); | |
345 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), | |
346 DataTypeController::ASSOCIATING); | |
347 GetController(controllers_, syncer::APPS)->FinishStart( | |
348 DataTypeController::OK); | |
349 EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(), | |
350 DataTypeController::RUNNING); | |
351 } | |
352 | |
353 // Test that model that failed to load between initialization and association | |
354 // is reported and stopped properly. | |
355 TEST_F(SyncModelAssociationManagerTest, ModelLoadFailBeforeAssociationStart) { | |
356 controllers_[syncer::BOOKMARKS] = | |
357 new FakeDataTypeController(syncer::BOOKMARKS); | |
358 GetController(controllers_, syncer::BOOKMARKS)->SetModelLoadError( | |
359 syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | |
360 "", syncer::BOOKMARKS)); | |
361 ModelAssociationManager model_association_manager( | |
362 &controllers_, | |
363 &result_processor_); | |
364 syncer::ModelTypeSet types; | |
365 types.Put(syncer::BOOKMARKS); | |
366 std::map<syncer::ModelType, syncer::SyncError> errors; | |
367 syncer::SyncError error(FROM_HERE, | |
368 syncer::SyncError::DATATYPE_ERROR, | |
369 "Failed", | |
370 syncer::BOOKMARKS); | |
371 errors[syncer::BOOKMARKS] = error; | |
372 DataTypeManager::ConfigureResult expected_result( | |
373 DataTypeManager::PARTIAL_SUCCESS, | |
374 types, | |
375 errors, | |
376 syncer::ModelTypeSet(), | |
377 syncer::ModelTypeSet()); | |
378 EXPECT_CALL(result_processor_, OnModelAssociationDone(_)). | |
379 WillOnce(VerifyResult(expected_result)); | |
380 | |
381 model_association_manager.Initialize(types); | |
382 EXPECT_EQ(DataTypeController::DISABLED, | |
383 GetController(controllers_, syncer::BOOKMARKS)->state()); | |
384 model_association_manager.StartAssociationAsync(types); | |
385 EXPECT_EQ(DataTypeController::NOT_RUNNING, | |
386 GetController(controllers_, syncer::BOOKMARKS)->state()); | |
387 } | |
388 | |
389 } // namespace browser_sync | |
OLD | NEW |