Home | History | Annotate | Download | only in glue
      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