Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / glue / non_frontend_data_type_controller_unittest.cc
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 "testing/gtest/include/gtest/gtest.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/compiler_specific.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/test/test_timeouts.h"
15 #include "base/tracked_objects.h"
16 #include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
17 #include "chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h"
18 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
19 #include "chrome/browser/sync/profile_sync_service_mock.h"
20 #include "chrome/test/base/profile_mock.h"
21 #include "components/sync_driver/change_processor_mock.h"
22 #include "components/sync_driver/data_type_controller_mock.h"
23 #include "components/sync_driver/model_associator_mock.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "sync/internal_api/public/engine/model_safe_worker.h"
26
27 using base::WaitableEvent;
28 using syncer::GROUP_DB;
29 using browser_sync::NonFrontendDataTypeController;
30 using browser_sync::NonFrontendDataTypeControllerMock;
31 using sync_driver::ChangeProcessorMock;
32 using sync_driver::DataTypeController;
33 using sync_driver::ModelAssociatorMock;
34 using sync_driver::ModelLoadCallbackMock;
35 using sync_driver::StartCallbackMock;
36 using content::BrowserThread;
37 using testing::_;
38 using testing::DoAll;
39 using testing::InvokeWithoutArgs;
40 using testing::Return;
41 using testing::SetArgumentPointee;
42 using testing::StrictMock;
43
44 ACTION_P(WaitOnEvent, event) {
45   event->Wait();
46 }
47
48 ACTION_P(SignalEvent, event) {
49   event->Signal();
50 }
51
52 class NonFrontendDataTypeControllerFake : public NonFrontendDataTypeController {
53  public:
54   NonFrontendDataTypeControllerFake(
55       ProfileSyncComponentsFactory* profile_sync_factory,
56       Profile* profile,
57       ProfileSyncService* sync_service,
58       NonFrontendDataTypeControllerMock* mock)
59       : NonFrontendDataTypeController(base::MessageLoopProxy::current(),
60                                       base::Closure(),
61                                       profile_sync_factory,
62                                       profile,
63                                       sync_service),
64         mock_(mock) {}
65
66   syncer::ModelType type() const override { return syncer::BOOKMARKS; }
67   syncer::ModelSafeGroup model_safe_group() const override {
68     return syncer::GROUP_DB;
69   }
70
71  private:
72   ~NonFrontendDataTypeControllerFake() override {}
73
74   ProfileSyncComponentsFactory::SyncComponents CreateSyncComponents() override {
75     return profile_sync_factory()->
76             CreateBookmarkSyncComponents(profile_sync_service(), this);
77   }
78
79   bool PostTaskOnBackendThread(const tracked_objects::Location& from_here,
80                                const base::Closure& task) override {
81     return BrowserThread::PostTask(BrowserThread::DB, from_here, task);
82   }
83
84   // We mock the following methods because their default implementations do
85   // nothing, but we still want to make sure they're called appropriately.
86   bool StartModels() override { return mock_->StartModels(); }
87   void RecordUnrecoverableError(const tracked_objects::Location& from_here,
88                                 const std::string& message) override {
89     mock_->RecordUnrecoverableError(from_here, message);
90   }
91   void RecordAssociationTime(base::TimeDelta time) override {
92     mock_->RecordAssociationTime(time);
93   }
94   void RecordStartFailure(DataTypeController::ConfigureResult result) override {
95     mock_->RecordStartFailure(result);
96   }
97   void DisconnectProcessor(sync_driver::ChangeProcessor* processor) override {
98     mock_->DisconnectProcessor(processor);
99   }
100
101  private:
102   NonFrontendDataTypeControllerMock* mock_;
103 };
104
105 class SyncNonFrontendDataTypeControllerTest : public testing::Test {
106  public:
107   SyncNonFrontendDataTypeControllerTest()
108       : ui_thread_(BrowserThread::UI, &message_loop_),
109         db_thread_(BrowserThread::DB),
110         service_(&profile_),
111         model_associator_(NULL),
112         change_processor_(NULL) {}
113
114   void SetUp() override {
115     db_thread_.Start();
116     profile_sync_factory_.reset(new ProfileSyncComponentsFactoryMock());
117
118     // All of these are refcounted, so don't need to be released.
119     dtc_mock_ = new StrictMock<NonFrontendDataTypeControllerMock>();
120     non_frontend_dtc_ =
121         new NonFrontendDataTypeControllerFake(profile_sync_factory_.get(),
122                                               &profile_,
123                                               &service_,
124                                               dtc_mock_.get());
125   }
126
127   void TearDown() override {
128     if (non_frontend_dtc_->state() !=
129         NonFrontendDataTypeController::NOT_RUNNING) {
130       non_frontend_dtc_->Stop();
131     }
132     db_thread_.Stop();
133   }
134
135  protected:
136   void SetStartExpectations() {
137     EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(true));
138     EXPECT_CALL(model_load_callback_, Run(_, _));
139     model_associator_ = new ModelAssociatorMock();
140     change_processor_ = new ChangeProcessorMock();
141     EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
142         WillOnce(Return(ProfileSyncComponentsFactory::SyncComponents(
143             model_associator_, change_processor_)));
144   }
145
146   void SetAssociateExpectations() {
147     EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
148         WillOnce(Return(true));
149     EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
150         WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
151     EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
152         WillOnce(Return(syncer::SyncError()));
153     EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
154   }
155
156   void SetActivateExpectations(DataTypeController::ConfigureResult result) {
157     EXPECT_CALL(start_callback_, Run(result, _, _));
158   }
159
160   void SetStopExpectations() {
161     EXPECT_CALL(*dtc_mock_.get(), DisconnectProcessor(_));
162     EXPECT_CALL(service_, DeactivateDataType(_));
163     EXPECT_CALL(*model_associator_, DisassociateModels()).
164                 WillOnce(Return(syncer::SyncError()));
165   }
166
167   void SetStartFailExpectations(DataTypeController::ConfigureResult result) {
168     if (DataTypeController::IsUnrecoverableResult(result))
169       EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, _));
170     if (model_associator_) {
171       EXPECT_CALL(*model_associator_, DisassociateModels()).
172                   WillOnce(Return(syncer::SyncError()));
173     }
174     EXPECT_CALL(*dtc_mock_.get(), RecordStartFailure(result));
175     EXPECT_CALL(start_callback_, Run(result, _, _));
176   }
177
178   static void SignalDone(WaitableEvent* done) {
179     done->Signal();
180   }
181
182   void WaitForDTC() {
183     WaitableEvent done(true, false);
184     BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
185         base::Bind(&SyncNonFrontendDataTypeControllerTest::SignalDone, &done));
186     done.TimedWait(TestTimeouts::action_timeout());
187     if (!done.IsSignaled()) {
188       ADD_FAILURE() << "Timed out waiting for DB thread to finish.";
189     }
190     base::MessageLoop::current()->RunUntilIdle();
191   }
192
193   void Start() {
194     non_frontend_dtc_->LoadModels(
195         base::Bind(&ModelLoadCallbackMock::Run,
196                    base::Unretained(&model_load_callback_)));
197     non_frontend_dtc_->StartAssociating(
198         base::Bind(&StartCallbackMock::Run,
199                    base::Unretained(&start_callback_)));
200   }
201
202   base::MessageLoopForUI message_loop_;
203   content::TestBrowserThread ui_thread_;
204   content::TestBrowserThread db_thread_;
205   scoped_refptr<NonFrontendDataTypeControllerFake> non_frontend_dtc_;
206   scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
207   scoped_refptr<NonFrontendDataTypeControllerMock> dtc_mock_;
208   ProfileMock profile_;
209   ProfileSyncServiceMock service_;
210   ModelAssociatorMock* model_associator_;
211   ChangeProcessorMock* change_processor_;
212   StartCallbackMock start_callback_;
213   ModelLoadCallbackMock model_load_callback_;
214 };
215
216 TEST_F(SyncNonFrontendDataTypeControllerTest, StartOk) {
217   SetStartExpectations();
218   SetAssociateExpectations();
219   SetActivateExpectations(DataTypeController::OK);
220   SetStopExpectations();
221   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
222   Start();
223   WaitForDTC();
224   EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
225 }
226
227 TEST_F(SyncNonFrontendDataTypeControllerTest, StartFirstRun) {
228   SetStartExpectations();
229   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
230       WillOnce(Return(true));
231   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
232       WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
233   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
234       WillOnce(Return(syncer::SyncError()));
235   EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
236   SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
237   SetStopExpectations();
238   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
239   Start();
240   WaitForDTC();
241   EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
242 }
243
244 TEST_F(SyncNonFrontendDataTypeControllerTest, StartAssociationFailed) {
245   SetStartExpectations();
246   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
247       WillOnce(Return(true));
248   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
249       WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
250   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
251       WillOnce(
252           Return(syncer::SyncError(FROM_HERE,
253                                    syncer::SyncError::DATATYPE_ERROR,
254                                    "Error",
255                                    syncer::BOOKMARKS)));
256   EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
257   SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
258   // Set up association to fail with an association failed error.
259   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
260   Start();
261   WaitForDTC();
262   EXPECT_EQ(DataTypeController::DISABLED, non_frontend_dtc_->state());
263 }
264
265 TEST_F(SyncNonFrontendDataTypeControllerTest,
266        StartAssociationTriggersUnrecoverableError) {
267   SetStartExpectations();
268   SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
269   // Set up association to fail with an unrecoverable error.
270   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
271       WillRepeatedly(Return(true));
272   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
273       WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
274   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
275   Start();
276   WaitForDTC();
277   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
278 }
279
280 TEST_F(SyncNonFrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
281   SetStartExpectations();
282   SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
283   // Set up association to fail with a NEEDS_CRYPTO error.
284   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
285       WillRepeatedly(Return(false));
286   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
287   Start();
288   WaitForDTC();
289   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
290 }
291
292 // Trigger a Stop() call when we check if the model associator has user created
293 // nodes.
294 TEST_F(SyncNonFrontendDataTypeControllerTest, AbortDuringAssociationInactive) {
295   WaitableEvent wait_for_db_thread_pause(false, false);
296   WaitableEvent pause_db_thread(false, false);
297
298   SetStartExpectations();
299   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
300       WillOnce(Return(true));
301   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
302       WillOnce(DoAll(
303           SignalEvent(&wait_for_db_thread_pause),
304           WaitOnEvent(&pause_db_thread),
305           SetArgumentPointee<0>(true),
306           Return(true)));
307   EXPECT_CALL(*model_associator_, AbortAssociation()).WillOnce(
308       SignalEvent(&pause_db_thread));
309   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
310               WillOnce(Return(syncer::SyncError()));
311   SetStopExpectations();
312   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
313   Start();
314   wait_for_db_thread_pause.Wait();
315   non_frontend_dtc_->Stop();
316   WaitForDTC();
317   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
318 }
319
320 // Same as above but abort during the Activate call.
321 TEST_F(SyncNonFrontendDataTypeControllerTest, AbortDuringAssociationActivated) {
322   WaitableEvent wait_for_association_starts(false, false);
323   WaitableEvent wait_for_dtc_stop(false, false);
324
325   SetStartExpectations();
326   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
327       WillOnce(Return(true));
328   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
329       WillOnce(DoAll(
330           SetArgumentPointee<0>(true),
331           Return(true)));
332   EXPECT_CALL(*model_associator_, AbortAssociation());
333   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
334       WillOnce(DoAll(
335           SignalEvent(&wait_for_association_starts),
336           WaitOnEvent(&wait_for_dtc_stop),
337           Return(syncer::SyncError())));
338   SetStopExpectations();
339   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
340   Start();
341   wait_for_association_starts.Wait();
342   non_frontend_dtc_->Stop();
343   wait_for_dtc_stop.Signal();
344   WaitForDTC();
345   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
346 }
347
348 TEST_F(SyncNonFrontendDataTypeControllerTest, Stop) {
349   SetStartExpectations();
350   SetAssociateExpectations();
351   SetActivateExpectations(DataTypeController::OK);
352   SetStopExpectations();
353   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
354   Start();
355   WaitForDTC();
356   EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
357   non_frontend_dtc_->Stop();
358   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
359 }
360
361 // Disabled due to http://crbug.com/388367
362 TEST_F(SyncNonFrontendDataTypeControllerTest,
363        DISABLED_OnSingleDataTypeUnrecoverableError) {
364   SetStartExpectations();
365   SetAssociateExpectations();
366   SetActivateExpectations(DataTypeController::OK);
367   EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, "Test"));
368   EXPECT_CALL(service_, DisableDatatype(_))
369       .WillOnce(InvokeWithoutArgs(non_frontend_dtc_.get(),
370                                   &NonFrontendDataTypeController::Stop));
371   SetStopExpectations();
372   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
373   Start();
374   WaitForDTC();
375   EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
376   // This should cause non_frontend_dtc_->Stop() to be called.
377   syncer::SyncError error(FROM_HERE,
378                           syncer::SyncError::DATATYPE_ERROR,
379                           "error",
380                           non_frontend_dtc_->type());
381   BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, base::Bind(
382       &NonFrontendDataTypeControllerFake::OnSingleDataTypeUnrecoverableError,
383       non_frontend_dtc_.get(),
384       error));
385   WaitForDTC();
386   EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
387 }