• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
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"
11 
12 using ::testing::_;
13 namespace browser_sync {
14 class MockModelAssociationManagerDelegate :
15     public ModelAssociationManagerDelegate {
16  public:
MockModelAssociationManagerDelegate()17   MockModelAssociationManagerDelegate() {}
~MockModelAssociationManagerDelegate()18   ~MockModelAssociationManagerDelegate() {}
19   MOCK_METHOD2(OnSingleDataTypeAssociationDone,
20       void(syncer::ModelType type,
21       const syncer::DataTypeAssociationStats& association_stats));
22   MOCK_METHOD1(OnSingleDataTypeWillStop, void(syncer::ModelType));
23   MOCK_METHOD1(OnModelAssociationDone, void(
24       const DataTypeManager::ConfigureResult& result));
25 };
26 
GetController(const DataTypeController::TypeMap & controllers,syncer::ModelType model_type)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 
ACTION_P(VerifyResult,expected_result)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:
SyncModelAssociationManagerTest()61   SyncModelAssociationManagerTest() {
62   }
63 
64  protected:
65   base::MessageLoopForUI ui_loop_;
66   MockModelAssociationManagerDelegate delegate_;
67   DataTypeController::TypeMap controllers_;
68 };
69 
70 // Start a type and make sure ModelAssociationManager callst the |Start|
71 // method and calls the callback when it is done.
TEST_F(SyncModelAssociationManagerTest,SimpleModelStart)72 TEST_F(SyncModelAssociationManagerTest, SimpleModelStart) {
73   controllers_[syncer::BOOKMARKS] =
74       new FakeDataTypeController(syncer::BOOKMARKS);
75   controllers_[syncer::APPS] =
76       new FakeDataTypeController(syncer::APPS);
77   ModelAssociationManager model_association_manager(&controllers_,
78                                                     &delegate_);
79   syncer::ModelTypeSet types(syncer::BOOKMARKS, syncer::APPS);
80   DataTypeManager::ConfigureResult expected_result(
81       DataTypeManager::OK,
82       types,
83       std::map<syncer::ModelType, syncer::SyncError>(),
84       syncer::ModelTypeSet(),
85       syncer::ModelTypeSet());
86   EXPECT_CALL(delegate_, OnModelAssociationDone(_)).
87               WillOnce(VerifyResult(expected_result));
88 
89   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
90             DataTypeController::NOT_RUNNING);
91   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
92             DataTypeController::NOT_RUNNING);
93 
94   // Initialize() kicks off model loading.
95   model_association_manager.Initialize(types);
96 
97   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
98             DataTypeController::MODEL_LOADED);
99   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
100             DataTypeController::MODEL_LOADED);
101 
102   model_association_manager.StartAssociationAsync(types);
103 
104   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
105             DataTypeController::ASSOCIATING);
106   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
107             DataTypeController::ASSOCIATING);
108   GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
109       DataTypeController::OK);
110   GetController(controllers_, syncer::APPS)->FinishStart(
111       DataTypeController::OK);
112 }
113 
114 // Start a type and call stop before it finishes associating.
TEST_F(SyncModelAssociationManagerTest,StopModelBeforeFinish)115 TEST_F(SyncModelAssociationManagerTest, StopModelBeforeFinish) {
116   controllers_[syncer::BOOKMARKS] =
117       new FakeDataTypeController(syncer::BOOKMARKS);
118   ModelAssociationManager model_association_manager(
119       &controllers_,
120       &delegate_);
121 
122   syncer::ModelTypeSet types;
123   types.Put(syncer::BOOKMARKS);
124 
125   std::map<syncer::ModelType, syncer::SyncError> errors;
126   syncer::SyncError error(FROM_HERE,
127                           syncer::SyncError::DATATYPE_ERROR,
128                           "Failed",
129                           syncer::BOOKMARKS);
130   errors[syncer::BOOKMARKS] = error;
131 
132   DataTypeManager::ConfigureResult expected_result(
133       DataTypeManager::ABORTED,
134       types,
135       errors,
136       syncer::ModelTypeSet(syncer::BOOKMARKS),
137       syncer::ModelTypeSet());
138 
139   EXPECT_CALL(delegate_, OnModelAssociationDone(_)).
140               WillOnce(VerifyResult(expected_result));
141   EXPECT_CALL(delegate_,
142               OnSingleDataTypeWillStop(syncer::BOOKMARKS));
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.
TEST_F(SyncModelAssociationManagerTest,StopAfterFinish)155 TEST_F(SyncModelAssociationManagerTest, StopAfterFinish) {
156   controllers_[syncer::BOOKMARKS] =
157       new FakeDataTypeController(syncer::BOOKMARKS);
158   ModelAssociationManager model_association_manager(
159       &controllers_,
160       &delegate_);
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(delegate_, OnModelAssociationDone(_)).
170               WillOnce(VerifyResult(expected_result));
171   EXPECT_CALL(delegate_,
172               OnSingleDataTypeWillStop(syncer::BOOKMARKS));
173 
174   model_association_manager.Initialize(types);
175   model_association_manager.StartAssociationAsync(types);
176 
177   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
178             DataTypeController::ASSOCIATING);
179   GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
180       DataTypeController::OK);
181 
182   model_association_manager.Stop();
183   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
184             DataTypeController::NOT_RUNNING);
185 }
186 
187 // Make a type fail model association and verify correctness.
TEST_F(SyncModelAssociationManagerTest,TypeFailModelAssociation)188 TEST_F(SyncModelAssociationManagerTest, TypeFailModelAssociation) {
189   controllers_[syncer::BOOKMARKS] =
190       new FakeDataTypeController(syncer::BOOKMARKS);
191   ModelAssociationManager model_association_manager(
192       &controllers_,
193       &delegate_);
194   syncer::ModelTypeSet types;
195   types.Put(syncer::BOOKMARKS);
196   std::map<syncer::ModelType, syncer::SyncError> errors;
197   syncer::SyncError error(FROM_HERE,
198                           syncer::SyncError::DATATYPE_ERROR,
199                           "Failed",
200                           syncer::BOOKMARKS);
201   errors[syncer::BOOKMARKS] = error;
202   DataTypeManager::ConfigureResult expected_result(
203       DataTypeManager::PARTIAL_SUCCESS,
204       types,
205       errors,
206       syncer::ModelTypeSet(),
207       syncer::ModelTypeSet());
208   EXPECT_CALL(delegate_, OnModelAssociationDone(_)).
209               WillOnce(VerifyResult(expected_result));
210 
211   model_association_manager.Initialize(types);
212   model_association_manager.StartAssociationAsync(types);
213 
214   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
215             DataTypeController::ASSOCIATING);
216   GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
217       DataTypeController::ASSOCIATION_FAILED);
218   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
219             DataTypeController::NOT_RUNNING);
220 }
221 
222 // Ensure configuring stops when a type returns a unrecoverable error.
TEST_F(SyncModelAssociationManagerTest,TypeReturnUnrecoverableError)223 TEST_F(SyncModelAssociationManagerTest, TypeReturnUnrecoverableError) {
224   controllers_[syncer::BOOKMARKS] =
225       new FakeDataTypeController(syncer::BOOKMARKS);
226   ModelAssociationManager model_association_manager(
227       &controllers_,
228       &delegate_);
229   syncer::ModelTypeSet types;
230   types.Put(syncer::BOOKMARKS);
231   std::map<syncer::ModelType, syncer::SyncError> errors;
232   syncer::SyncError error(FROM_HERE,
233                           syncer::SyncError::DATATYPE_ERROR,
234                           "Failed",
235                           syncer::BOOKMARKS);
236   errors[syncer::BOOKMARKS] = error;
237   DataTypeManager::ConfigureResult expected_result(
238       DataTypeManager::UNRECOVERABLE_ERROR,
239       types,
240       errors,
241       syncer::ModelTypeSet(),
242       syncer::ModelTypeSet());
243   EXPECT_CALL(delegate_, OnModelAssociationDone(_)).
244               WillOnce(VerifyResult(expected_result));
245 
246   model_association_manager.Initialize(types);
247 
248   model_association_manager.StartAssociationAsync(types);
249 
250   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
251             DataTypeController::ASSOCIATING);
252   GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
253       DataTypeController::UNRECOVERABLE_ERROR);
254 }
255 
TEST_F(SyncModelAssociationManagerTest,SlowTypeAsFailedType)256 TEST_F(SyncModelAssociationManagerTest, SlowTypeAsFailedType) {
257   controllers_[syncer::BOOKMARKS] =
258       new FakeDataTypeController(syncer::BOOKMARKS);
259   controllers_[syncer::APPS] =
260       new FakeDataTypeController(syncer::APPS);
261   GetController(controllers_, syncer::BOOKMARKS)->SetDelayModelLoad();
262   ModelAssociationManager model_association_manager(&controllers_,
263                                                     &delegate_);
264   syncer::ModelTypeSet types;
265   types.Put(syncer::BOOKMARKS);
266   types.Put(syncer::APPS);
267 
268   std::map<syncer::ModelType, syncer::SyncError> errors;
269   syncer::SyncError error(FROM_HERE,
270                           syncer::SyncError::DATATYPE_ERROR,
271                           "Association timed out.",
272                           syncer::BOOKMARKS);
273   errors[syncer::BOOKMARKS] = error;
274 
275   syncer::ModelTypeSet expected_types_unfinished;
276   expected_types_unfinished.Put(syncer::BOOKMARKS);
277   DataTypeManager::ConfigureResult expected_result_partially_done(
278       DataTypeManager::PARTIAL_SUCCESS,
279       types,
280       errors,
281       expected_types_unfinished,
282       syncer::ModelTypeSet());
283 
284   EXPECT_CALL(delegate_, OnModelAssociationDone(_)).
285               WillOnce(VerifyResult(expected_result_partially_done));
286 
287   model_association_manager.Initialize(types);
288   model_association_manager.StartAssociationAsync(types);
289   GetController(controllers_, syncer::APPS)->FinishStart(
290       DataTypeController::OK);
291 
292   model_association_manager.GetTimerForTesting()->user_task().Run();
293 
294   EXPECT_EQ(DataTypeController::NOT_RUNNING,
295             GetController(controllers_, syncer::BOOKMARKS)->state());
296 }
297 
TEST_F(SyncModelAssociationManagerTest,StartMultipleTimes)298 TEST_F(SyncModelAssociationManagerTest, StartMultipleTimes) {
299   controllers_[syncer::BOOKMARKS] =
300       new FakeDataTypeController(syncer::BOOKMARKS);
301   controllers_[syncer::APPS] =
302       new FakeDataTypeController(syncer::APPS);
303   ModelAssociationManager model_association_manager(&controllers_,
304                                                     &delegate_);
305   syncer::ModelTypeSet types;
306   types.Put(syncer::BOOKMARKS);
307   types.Put(syncer::APPS);
308 
309   DataTypeManager::ConfigureResult result_1st(
310       DataTypeManager::OK,
311       syncer::ModelTypeSet(syncer::BOOKMARKS),
312       std::map<syncer::ModelType, syncer::SyncError>(),
313       syncer::ModelTypeSet(),
314       syncer::ModelTypeSet());
315   DataTypeManager::ConfigureResult result_2nd(
316       DataTypeManager::OK,
317       syncer::ModelTypeSet(syncer::APPS),
318       std::map<syncer::ModelType, syncer::SyncError>(),
319       syncer::ModelTypeSet(),
320       syncer::ModelTypeSet());
321   EXPECT_CALL(delegate_, OnModelAssociationDone(_)).
322       Times(2).
323       WillOnce(VerifyResult(result_1st)).
324       WillOnce(VerifyResult(result_2nd));
325 
326   model_association_manager.Initialize(types);
327 
328   // Start BOOKMARKS first.
329   model_association_manager.StartAssociationAsync(
330       syncer::ModelTypeSet(syncer::BOOKMARKS));
331   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
332             DataTypeController::ASSOCIATING);
333   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
334             DataTypeController::MODEL_LOADED);
335 
336   // Finish BOOKMARKS association.
337   GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
338       DataTypeController::OK);
339   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
340             DataTypeController::RUNNING);
341   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
342             DataTypeController::MODEL_LOADED);
343 
344   // Start APPS next.
345   model_association_manager.StartAssociationAsync(
346       syncer::ModelTypeSet(syncer::APPS));
347   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
348             DataTypeController::ASSOCIATING);
349   GetController(controllers_, syncer::APPS)->FinishStart(
350       DataTypeController::OK);
351   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
352             DataTypeController::RUNNING);
353 }
354 
355 // Test that model that failed to load between initialization and association
356 // is reported and stopped properly.
TEST_F(SyncModelAssociationManagerTest,ModelLoadFailBeforeAssociationStart)357 TEST_F(SyncModelAssociationManagerTest, ModelLoadFailBeforeAssociationStart) {
358   controllers_[syncer::BOOKMARKS] =
359       new FakeDataTypeController(syncer::BOOKMARKS);
360   GetController(controllers_, syncer::BOOKMARKS)->SetModelLoadError(
361       syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
362                         "", syncer::BOOKMARKS));
363   ModelAssociationManager model_association_manager(
364       &controllers_,
365       &delegate_);
366   syncer::ModelTypeSet types;
367   types.Put(syncer::BOOKMARKS);
368   std::map<syncer::ModelType, syncer::SyncError> errors;
369   syncer::SyncError error(FROM_HERE,
370                           syncer::SyncError::DATATYPE_ERROR,
371                           "Failed",
372                           syncer::BOOKMARKS);
373   errors[syncer::BOOKMARKS] = error;
374   DataTypeManager::ConfigureResult expected_result(
375       DataTypeManager::PARTIAL_SUCCESS,
376       types,
377       errors,
378       syncer::ModelTypeSet(),
379       syncer::ModelTypeSet());
380   EXPECT_CALL(delegate_, OnModelAssociationDone(_)).
381               WillOnce(VerifyResult(expected_result));
382 
383   model_association_manager.Initialize(types);
384   EXPECT_EQ(DataTypeController::DISABLED,
385             GetController(controllers_, syncer::BOOKMARKS)->state());
386   model_association_manager.StartAssociationAsync(types);
387   EXPECT_EQ(DataTypeController::NOT_RUNNING,
388             GetController(controllers_, syncer::BOOKMARKS)->state());
389 }
390 
391 }  // namespace browser_sync
392