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