Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / components / sync_driver / model_association_manager_unittest.cc
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 MockModelAssociationResultProcessor :
15     public ModelAssociationResultProcessor {
16  public:
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));
24 };
25
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()) {
32     return NULL;
33   }
34   return (FakeDataTypeController*)(it->second.get());
35 }
36
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());
42
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();
49          ++it1, ++it2) {
50       EXPECT_EQ((*it1).first, (*it2).first);
51     }
52   }
53
54   EXPECT_TRUE(arg0.unfinished_data_types.Equals(
55       expected_result.unfinished_data_types));
56 }
57
58 class SyncModelAssociationManagerTest : public testing::Test {
59  public:
60   SyncModelAssociationManagerTest() {
61   }
62
63  protected:
64   base::MessageLoopForUI ui_loop_;
65   MockModelAssociationResultProcessor result_processor_;
66   DataTypeController::TypeMap controllers_;
67 };
68
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_,
77                                                     &result_processor_);
78   syncer::ModelTypeSet types(syncer::BOOKMARKS, syncer::APPS);
79   DataTypeManager::ConfigureResult expected_result(
80       DataTypeManager::OK,
81       types,
82       std::map<syncer::ModelType, syncer::SyncError>(),
83       syncer::ModelTypeSet(),
84       syncer::ModelTypeSet());
85   EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
86               WillOnce(VerifyResult(expected_result));
87
88   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
89             DataTypeController::NOT_RUNNING);
90   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
91             DataTypeController::NOT_RUNNING);
92
93   // Initialize() kicks off model loading.
94   model_association_manager.Initialize(types);
95
96   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
97             DataTypeController::MODEL_LOADED);
98   EXPECT_EQ(GetController(controllers_, syncer::APPS)->state(),
99             DataTypeController::MODEL_LOADED);
100
101   model_association_manager.StartAssociationAsync(types);
102
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);
111 }
112
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(
118       &controllers_,
119       &result_processor_);
120
121   syncer::ModelTypeSet types;
122   types.Put(syncer::BOOKMARKS);
123
124   std::map<syncer::ModelType, syncer::SyncError> errors;
125   syncer::SyncError error(FROM_HERE,
126                           syncer::SyncError::DATATYPE_ERROR,
127                           "Failed",
128                           syncer::BOOKMARKS);
129   errors[syncer::BOOKMARKS] = error;
130
131   DataTypeManager::ConfigureResult expected_result(
132       DataTypeManager::ABORTED,
133       types,
134       errors,
135       syncer::ModelTypeSet(syncer::BOOKMARKS),
136       syncer::ModelTypeSet());
137
138   EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
139               WillOnce(VerifyResult(expected_result));
140
141   model_association_manager.Initialize(types);
142   model_association_manager.StartAssociationAsync(types);
143
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);
149 }
150
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(
156       &controllers_,
157       &result_processor_);
158   syncer::ModelTypeSet types;
159   types.Put(syncer::BOOKMARKS);
160   DataTypeManager::ConfigureResult expected_result(
161       DataTypeManager::OK,
162       types,
163       std::map<syncer::ModelType, syncer::SyncError>(),
164       syncer::ModelTypeSet(),
165       syncer::ModelTypeSet());
166   EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
167               WillOnce(VerifyResult(expected_result));
168
169   model_association_manager.Initialize(types);
170   model_association_manager.StartAssociationAsync(types);
171
172   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
173             DataTypeController::ASSOCIATING);
174   GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
175       DataTypeController::OK);
176
177   model_association_manager.Stop();
178   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
179             DataTypeController::NOT_RUNNING);
180 }
181
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(
187       &controllers_,
188       &result_processor_);
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,
194                           "Failed",
195                           syncer::BOOKMARKS);
196   errors[syncer::BOOKMARKS] = error;
197   DataTypeManager::ConfigureResult expected_result(
198       DataTypeManager::PARTIAL_SUCCESS,
199       types,
200       errors,
201       syncer::ModelTypeSet(),
202       syncer::ModelTypeSet());
203   EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
204               WillOnce(VerifyResult(expected_result));
205
206   model_association_manager.Initialize(types);
207   model_association_manager.StartAssociationAsync(types);
208
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);
215 }
216
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(
222       &controllers_,
223       &result_processor_);
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,
229                           "Failed",
230                           syncer::BOOKMARKS);
231   errors[syncer::BOOKMARKS] = error;
232   DataTypeManager::ConfigureResult expected_result(
233       DataTypeManager::UNRECOVERABLE_ERROR,
234       types,
235       errors,
236       syncer::ModelTypeSet(),
237       syncer::ModelTypeSet());
238   EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
239               WillOnce(VerifyResult(expected_result));
240
241   model_association_manager.Initialize(types);
242
243   model_association_manager.StartAssociationAsync(types);
244
245   EXPECT_EQ(GetController(controllers_, syncer::BOOKMARKS)->state(),
246             DataTypeController::ASSOCIATING);
247   GetController(controllers_, syncer::BOOKMARKS)->FinishStart(
248       DataTypeController::UNRECOVERABLE_ERROR);
249 }
250
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_,
258                                                     &result_processor_);
259   syncer::ModelTypeSet types;
260   types.Put(syncer::BOOKMARKS);
261   types.Put(syncer::APPS);
262
263   std::map<syncer::ModelType, syncer::SyncError> errors;
264   syncer::SyncError error(FROM_HERE,
265                           syncer::SyncError::DATATYPE_ERROR,
266                           "Association timed out.",
267                           syncer::BOOKMARKS);
268   errors[syncer::BOOKMARKS] = error;
269
270   syncer::ModelTypeSet expected_types_unfinished;
271   expected_types_unfinished.Put(syncer::BOOKMARKS);
272   DataTypeManager::ConfigureResult expected_result_partially_done(
273       DataTypeManager::PARTIAL_SUCCESS,
274       types,
275       errors,
276       expected_types_unfinished,
277       syncer::ModelTypeSet());
278
279   EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
280               WillOnce(VerifyResult(expected_result_partially_done));
281
282   model_association_manager.Initialize(types);
283   model_association_manager.StartAssociationAsync(types);
284   GetController(controllers_, syncer::APPS)->FinishStart(
285       DataTypeController::OK);
286
287   model_association_manager.GetTimerForTesting()->user_task().Run();
288
289   EXPECT_EQ(DataTypeController::NOT_RUNNING,
290             GetController(controllers_, syncer::BOOKMARKS)->state());
291 }
292
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_,
299                                                     &result_processor_);
300   syncer::ModelTypeSet types;
301   types.Put(syncer::BOOKMARKS);
302   types.Put(syncer::APPS);
303
304   DataTypeManager::ConfigureResult result_1st(
305       DataTypeManager::OK,
306       syncer::ModelTypeSet(syncer::BOOKMARKS),
307       std::map<syncer::ModelType, syncer::SyncError>(),
308       syncer::ModelTypeSet(),
309       syncer::ModelTypeSet());
310   DataTypeManager::ConfigureResult result_2nd(
311       DataTypeManager::OK,
312       syncer::ModelTypeSet(syncer::APPS),
313       std::map<syncer::ModelType, syncer::SyncError>(),
314       syncer::ModelTypeSet(),
315       syncer::ModelTypeSet());
316   EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
317       Times(2).
318       WillOnce(VerifyResult(result_1st)).
319       WillOnce(VerifyResult(result_2nd));
320
321   model_association_manager.Initialize(types);
322
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);
330
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);
338
339   // Start APPS next.
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);
348 }
349
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(
359       &controllers_,
360       &result_processor_);
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,
366                           "Failed",
367                           syncer::BOOKMARKS);
368   errors[syncer::BOOKMARKS] = error;
369   DataTypeManager::ConfigureResult expected_result(
370       DataTypeManager::PARTIAL_SUCCESS,
371       types,
372       errors,
373       syncer::ModelTypeSet(),
374       syncer::ModelTypeSet());
375   EXPECT_CALL(result_processor_, OnModelAssociationDone(_)).
376               WillOnce(VerifyResult(expected_result));
377
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());
384 }
385
386 }  // namespace browser_sync