autofill_data_type_controller_unittest.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 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/callback.h"
8#include "base/message_loop.h"
9#include "base/ref_counted.h"
10#include "base/scoped_ptr.h"
11#include "base/synchronization/waitable_event.h"
12#include "chrome/browser/autofill/personal_data_manager.h"
13#include "chrome/browser/browser_thread.h"
14#include "chrome/browser/sync/glue/autofill_data_type_controller.h"
15#include "chrome/browser/sync/glue/change_processor_mock.h"
16#include "chrome/browser/sync/glue/model_associator_mock.h"
17#include "chrome/browser/sync/profile_sync_factory_mock.h"
18#include "chrome/browser/sync/profile_sync_service_mock.h"
19#include "chrome/browser/sync/profile_sync_test_util.h"
20#include "chrome/browser/webdata/web_data_service.h"
21#include "chrome/common/notification_source.h"
22#include "chrome/common/notification_type.h"
23#include "chrome/test/profile_mock.h"
24#include "testing/gmock/include/gmock/gmock.h"
25
26using base::WaitableEvent;
27using browser_sync::AutofillDataTypeController;
28using browser_sync::ChangeProcessorMock;
29using browser_sync::DataTypeController;
30using browser_sync::ModelAssociatorMock;
31using testing::_;
32using testing::DoAll;
33using testing::Invoke;
34using testing::Return;
35using testing::SetArgumentPointee;
36
37namespace {
38
39ACTION_P(WaitOnEvent, event) {
40  event->Wait();
41}
42
43ACTION_P(SignalEvent, event) {
44  event->Signal();
45}
46
47class StartCallback {
48 public:
49  MOCK_METHOD1(Run, void(DataTypeController::StartResult result));
50};
51
52class PersonalDataManagerMock : public PersonalDataManager {
53 public:
54  MOCK_CONST_METHOD0(IsDataLoaded, bool());
55};
56
57class WebDataServiceFake : public WebDataService {
58 public:
59  explicit WebDataServiceFake(bool is_database_loaded)
60      : is_database_loaded_(is_database_loaded) {}
61
62  virtual bool IsDatabaseLoaded() {
63    return is_database_loaded_;
64  }
65 private:
66  bool is_database_loaded_;
67};
68
69class SignalEventTask : public Task {
70 public:
71  explicit SignalEventTask(WaitableEvent* done_event)
72      : done_event_(done_event) {}
73
74  virtual void Run() {
75    done_event_->Signal();
76  }
77
78 private:
79  WaitableEvent* done_event_;
80};
81
82class AutofillDataTypeControllerTest : public testing::Test {
83 public:
84  AutofillDataTypeControllerTest()
85      : ui_thread_(BrowserThread::UI, &message_loop_),
86        db_thread_(BrowserThread::DB) {}
87
88  virtual void SetUp() {
89    db_thread_.Start();
90    web_data_service_ = new WebDataServiceFake(true);
91    personal_data_manager_ = new PersonalDataManagerMock();
92    autofill_dtc_ =
93        new AutofillDataTypeController(&profile_sync_factory_,
94                                       &profile_,
95                                       &service_);
96  }
97
98  virtual void TearDown() {
99    WaitForEmptyDBMessageLoop();
100    db_thread_.Stop();
101  }
102
103 protected:
104  void SetStartExpectations() {
105    EXPECT_CALL(profile_, GetPersonalDataManager()).
106        WillRepeatedly(Return(personal_data_manager_.get()));
107    EXPECT_CALL(*(personal_data_manager_.get()), IsDataLoaded()).
108        WillRepeatedly(Return(true));
109    EXPECT_CALL(profile_, GetWebDataService(_)).
110        WillOnce(Return(web_data_service_.get()));
111  }
112
113  void SetAssociateExpectations() {
114    model_associator_ = new ModelAssociatorMock();
115    change_processor_ = new ChangeProcessorMock();
116    EXPECT_CALL(profile_sync_factory_,
117                CreateAutofillSyncComponents(_, _, _, _)).
118        WillOnce(Return(
119            ProfileSyncFactory::SyncComponents(model_associator_,
120                                               change_processor_)));
121
122    EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
123        WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true)));
124    EXPECT_CALL(*model_associator_, AssociateModels()).
125        WillRepeatedly(Return(true));
126    EXPECT_CALL(service_, ActivateDataType(_, _));
127    EXPECT_CALL(*change_processor_, IsRunning()).WillRepeatedly(Return(true));
128  }
129
130  void SetStopExpectations() {
131    EXPECT_CALL(service_, DeactivateDataType(_, _));
132    EXPECT_CALL(*model_associator_, DisassociateModels());
133  }
134
135  void WaitForEmptyDBMessageLoop() {
136    // Run a task through the DB message loop to ensure that
137    // everything before it has been run.
138    WaitableEvent done_event(false, false);
139    BrowserThread::PostTask(BrowserThread::DB,
140                            FROM_HERE,
141                            new SignalEventTask(&done_event));
142    done_event.Wait();
143  }
144
145  MessageLoopForUI message_loop_;
146  BrowserThread ui_thread_;
147  BrowserThread db_thread_;
148  scoped_refptr<AutofillDataTypeController> autofill_dtc_;
149  ProfileSyncFactoryMock profile_sync_factory_;
150  ProfileMock profile_;
151  scoped_refptr<PersonalDataManagerMock> personal_data_manager_;
152  scoped_refptr<WebDataService> web_data_service_;
153  ProfileSyncServiceMock service_;
154  ModelAssociatorMock* model_associator_;
155  ChangeProcessorMock* change_processor_;
156  StartCallback start_callback_;
157};
158
159TEST_F(AutofillDataTypeControllerTest, StartPDMAndWDSReady) {
160  SetStartExpectations();
161  SetAssociateExpectations();
162  EXPECT_EQ(DataTypeController::NOT_RUNNING, autofill_dtc_->state());
163  EXPECT_CALL(start_callback_, Run(DataTypeController::OK)).
164      WillOnce(QuitUIMessageLoop());
165  autofill_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
166  MessageLoop::current()->Run();
167  EXPECT_EQ(DataTypeController::RUNNING, autofill_dtc_->state());
168  SetStopExpectations();
169  autofill_dtc_->Stop();
170  EXPECT_EQ(DataTypeController::NOT_RUNNING, autofill_dtc_->state());
171}
172
173TEST_F(AutofillDataTypeControllerTest, AbortWhilePDMStarting) {
174  EXPECT_CALL(profile_, GetPersonalDataManager()).
175      WillRepeatedly(Return(personal_data_manager_.get()));
176  EXPECT_CALL(*(personal_data_manager_.get()), IsDataLoaded()).
177      WillRepeatedly(Return(false));
178  autofill_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
179  EXPECT_EQ(DataTypeController::MODEL_STARTING, autofill_dtc_->state());
180
181  EXPECT_CALL(service_, DeactivateDataType(_, _)).Times(0);
182  EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED));
183  autofill_dtc_->Stop();
184  EXPECT_EQ(DataTypeController::NOT_RUNNING, autofill_dtc_->state());
185}
186
187TEST_F(AutofillDataTypeControllerTest, AbortWhileWDSStarting) {
188  EXPECT_CALL(profile_, GetPersonalDataManager()).
189      WillRepeatedly(Return(personal_data_manager_.get()));
190  EXPECT_CALL(*(personal_data_manager_.get()), IsDataLoaded()).
191      WillRepeatedly(Return(true));
192  scoped_refptr<WebDataServiceFake> web_data_service_not_loaded(
193      new WebDataServiceFake(false));
194  EXPECT_CALL(profile_, GetWebDataService(_)).
195      WillOnce(Return(web_data_service_not_loaded.get()));
196  autofill_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
197  EXPECT_EQ(DataTypeController::MODEL_STARTING, autofill_dtc_->state());
198
199  EXPECT_CALL(service_, DeactivateDataType(_, _)).Times(0);
200  EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED));
201  autofill_dtc_->Stop();
202  EXPECT_EQ(DataTypeController::NOT_RUNNING, autofill_dtc_->state());
203}
204
205TEST_F(AutofillDataTypeControllerTest, AbortWhileAssociatingNotActivated) {
206  SetStartExpectations();
207
208  model_associator_ = new ModelAssociatorMock();
209  change_processor_ = new ChangeProcessorMock();
210  EXPECT_CALL(profile_sync_factory_,
211              CreateAutofillSyncComponents(_, _, _, _)).
212      WillOnce(Return(
213          ProfileSyncFactory::SyncComponents(model_associator_,
214                                             change_processor_)));
215
216  // Use the pause_db_thread WaitableEvent to pause the DB thread when
217  // the model association process reaches the
218  // SyncModelHasUserCreatedNodes method.  This lets us call Stop()
219  // while model association is in progress.  When we call Stop(),
220  // this will call the model associator's AbortAssociation() method
221  // that signals the event and lets the DB thread continue.
222  WaitableEvent pause_db_thread(false, false);
223  WaitableEvent wait_for_db_thread_pause(false, false);
224  EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
225      WillOnce(DoAll(
226          SignalEvent(&wait_for_db_thread_pause),
227          WaitOnEvent(&pause_db_thread),
228          SetArgumentPointee<0>(true),
229          Return(false)));
230  EXPECT_CALL(*model_associator_, AbortAssociation()).
231      WillOnce(SignalEvent(&pause_db_thread));
232
233  autofill_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
234  wait_for_db_thread_pause.Wait();
235  EXPECT_EQ(DataTypeController::ASSOCIATING, autofill_dtc_->state());
236
237  EXPECT_CALL(service_, DeactivateDataType(_, _)).Times(0);
238  EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED));
239  autofill_dtc_->Stop();
240  EXPECT_EQ(DataTypeController::NOT_RUNNING, autofill_dtc_->state());
241}
242
243TEST_F(AutofillDataTypeControllerTest, AbortWhileAssociatingActivated) {
244  SetStartExpectations();
245
246  model_associator_ = new ModelAssociatorMock();
247  change_processor_ = new ChangeProcessorMock();
248  EXPECT_CALL(profile_sync_factory_,
249              CreateAutofillSyncComponents(_, _, _, _)).
250      WillOnce(Return(
251          ProfileSyncFactory::SyncComponents(model_associator_,
252                                             change_processor_)));
253  EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
254      WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true)));
255  EXPECT_CALL(*model_associator_, AssociateModels()).
256      WillRepeatedly(Return(true));
257  EXPECT_CALL(*change_processor_, IsRunning()).WillRepeatedly(Return(true));
258
259  // The usage of pause_db_thread is similar as in the previous test,
260  // but here we will wait until the DB thread calls
261  // ActivateDataType() before  allowing it to continue.
262  WaitableEvent pause_db_thread(false, false);
263  WaitableEvent wait_for_db_thread_pause(false, false);
264  EXPECT_CALL(service_, ActivateDataType(_, _)).
265      WillOnce(DoAll(
266          SignalEvent(&wait_for_db_thread_pause),
267          WaitOnEvent(&pause_db_thread)));
268  EXPECT_CALL(*model_associator_, AbortAssociation()).
269      WillOnce(SignalEvent(&pause_db_thread));
270
271  autofill_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
272  wait_for_db_thread_pause.Wait();
273  EXPECT_EQ(DataTypeController::ASSOCIATING, autofill_dtc_->state());
274
275  SetStopExpectations();
276  EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED));
277  autofill_dtc_->Stop();
278  EXPECT_EQ(DataTypeController::NOT_RUNNING, autofill_dtc_->state());
279}
280
281}  // namespace
282