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/scoped_ptr.h"
      9 #include "base/message_loop.h"
     10 #include "base/task.h"
     11 #include "base/tracked_objects.h"
     12 #include "chrome/browser/sync/glue/change_processor_mock.h"
     13 #include "chrome/browser/sync/glue/frontend_data_type_controller.h"
     14 #include "chrome/browser/sync/glue/frontend_data_type_controller_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/test/profile_mock.h"
     19 #include "content/browser/browser_thread.h"
     20 
     21 using browser_sync::ChangeProcessorMock;
     22 using browser_sync::DataTypeController;
     23 using browser_sync::FrontendDataTypeController;
     24 using browser_sync::FrontendDataTypeControllerMock;
     25 using browser_sync::ModelAssociatorMock;
     26 using testing::_;
     27 using testing::DoAll;
     28 using testing::InvokeWithoutArgs;
     29 using testing::Return;
     30 using testing::SetArgumentPointee;
     31 using testing::StrictMock;
     32 
     33 class StartCallback {
     34  public:
     35   MOCK_METHOD2(Run, void(DataTypeController::StartResult result,
     36                          const tracked_objects::Location& from_here));
     37 };
     38 
     39 class FrontendDataTypeControllerFake : public FrontendDataTypeController {
     40  public:
     41   FrontendDataTypeControllerFake(
     42       ProfileSyncFactory* profile_sync_factory,
     43       Profile* profile,
     44       ProfileSyncService* sync_service,
     45       FrontendDataTypeControllerMock* mock)
     46       : FrontendDataTypeController(profile_sync_factory,
     47                                    profile,
     48                                    sync_service),
     49         mock_(mock) {}
     50   virtual syncable::ModelType type() const { return syncable::BOOKMARKS; }
     51 
     52  private:
     53   virtual void CreateSyncComponents() {
     54     ProfileSyncFactory::SyncComponents sync_components =
     55         profile_sync_factory_->
     56             CreateBookmarkSyncComponents(sync_service_, this);
     57     model_associator_.reset(sync_components.model_associator);
     58     change_processor_.reset(sync_components.change_processor);
     59   }
     60 
     61   // We mock the following methods because their default implementations do
     62   // nothing, but we still want to make sure they're called appropriately.
     63   virtual bool StartModels() {
     64     return mock_->StartModels();
     65   }
     66   virtual void CleanupState() {
     67     mock_->CleanupState();
     68   }
     69   virtual void RecordUnrecoverableError(
     70       const tracked_objects::Location& from_here,
     71       const std::string& message) {
     72     mock_->RecordUnrecoverableError(from_here, message);
     73   }
     74   virtual void RecordAssociationTime(base::TimeDelta time) {
     75     mock_->RecordAssociationTime(time);
     76   }
     77   virtual void RecordStartFailure(DataTypeController::StartResult result) {
     78     mock_->RecordStartFailure(result);
     79   }
     80  private:
     81   FrontendDataTypeControllerMock* mock_;
     82 };
     83 
     84 class FrontendDataTypeControllerTest : public testing::Test {
     85  public:
     86   FrontendDataTypeControllerTest()
     87       : ui_thread_(BrowserThread::UI, &message_loop_) {}
     88 
     89   virtual void SetUp() {
     90     profile_sync_factory_.reset(new ProfileSyncFactoryMock());
     91     dtc_mock_ = new StrictMock<FrontendDataTypeControllerMock>();
     92     frontend_dtc_ =
     93         new FrontendDataTypeControllerFake(profile_sync_factory_.get(),
     94                                            &profile_,
     95                                            &service_,
     96                                            dtc_mock_.get());
     97   }
     98 
     99  protected:
    100   void SetStartExpectations() {
    101     EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(true));
    102     model_associator_ = new ModelAssociatorMock();
    103     change_processor_ = new ChangeProcessorMock();
    104     EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
    105         WillOnce(Return(ProfileSyncFactory::SyncComponents(model_associator_,
    106                                                            change_processor_)));
    107   }
    108 
    109   void SetAssociateExpectations() {
    110     EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    111         WillOnce(Return(true));
    112     EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
    113         WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
    114     EXPECT_CALL(*model_associator_, AssociateModels()).
    115         WillOnce(Return(true));
    116     EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
    117   }
    118 
    119   void SetActivateExpectations(DataTypeController::StartResult result) {
    120     EXPECT_CALL(service_, ActivateDataType(_, _));
    121     EXPECT_CALL(start_callback_, Run(result,_));
    122   }
    123 
    124   void SetStopExpectations() {
    125     EXPECT_CALL(*dtc_mock_, CleanupState());
    126     EXPECT_CALL(service_, DeactivateDataType(_, _));
    127     EXPECT_CALL(*model_associator_, DisassociateModels());
    128   }
    129 
    130   void SetStartFailExpectations(DataTypeController::StartResult result) {
    131     EXPECT_CALL(*dtc_mock_, CleanupState());
    132     EXPECT_CALL(*dtc_mock_, RecordStartFailure(result));
    133     EXPECT_CALL(start_callback_, Run(result,_));
    134   }
    135 
    136   MessageLoopForUI message_loop_;
    137   BrowserThread ui_thread_;
    138   scoped_refptr<FrontendDataTypeControllerFake> frontend_dtc_;
    139   scoped_ptr<ProfileSyncFactoryMock> profile_sync_factory_;
    140   scoped_refptr<FrontendDataTypeControllerMock> dtc_mock_;
    141   ProfileMock profile_;
    142   ProfileSyncServiceMock service_;
    143   ModelAssociatorMock* model_associator_;
    144   ChangeProcessorMock* change_processor_;
    145   StartCallback start_callback_;
    146 };
    147 
    148 TEST_F(FrontendDataTypeControllerTest, StartOk) {
    149   SetStartExpectations();
    150   SetAssociateExpectations();
    151   SetActivateExpectations(DataTypeController::OK);
    152   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    153   frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
    154   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
    155 }
    156 
    157 TEST_F(FrontendDataTypeControllerTest, StartFirstRun) {
    158   SetStartExpectations();
    159   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    160       WillOnce(Return(true));
    161   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
    162       WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
    163   EXPECT_CALL(*model_associator_, AssociateModels()).
    164       WillOnce(Return(true));
    165   EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
    166   SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
    167   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    168   frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
    169   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
    170 }
    171 
    172 TEST_F(FrontendDataTypeControllerTest, StartAssociationFailed) {
    173   SetStartExpectations();
    174   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    175       WillOnce(Return(true));
    176   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
    177       WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
    178   EXPECT_CALL(*model_associator_, AssociateModels()).
    179       WillOnce(Return(false));
    180   EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
    181   SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
    182   // Set up association to fail with an association failed error.
    183   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    184   frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
    185   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    186 }
    187 
    188 TEST_F(FrontendDataTypeControllerTest,
    189        StartAssociationTriggersUnrecoverableError) {
    190   SetStartExpectations();
    191   SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
    192   // Set up association to fail with an unrecoverable error.
    193   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    194       WillRepeatedly(Return(true));
    195   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
    196       WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
    197   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    198   frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
    199   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    200 }
    201 
    202 TEST_F(FrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
    203   SetStartExpectations();
    204   SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
    205   // Set up association to fail with a NEEDS_CRYPTO error.
    206   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    207       WillRepeatedly(Return(false));
    208   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    209   frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
    210   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    211 }
    212 
    213 TEST_F(FrontendDataTypeControllerTest, Stop) {
    214   SetStartExpectations();
    215   SetAssociateExpectations();
    216   SetActivateExpectations(DataTypeController::OK);
    217   SetStopExpectations();
    218 
    219   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    220   frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
    221   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
    222   frontend_dtc_->Stop();
    223   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    224 }
    225 
    226 TEST_F(FrontendDataTypeControllerTest, OnUnrecoverableError) {
    227   SetStartExpectations();
    228   SetAssociateExpectations();
    229   SetActivateExpectations(DataTypeController::OK);
    230   EXPECT_CALL(*dtc_mock_, RecordUnrecoverableError(_, "Test"));
    231   EXPECT_CALL(service_, OnUnrecoverableError(_,_)).
    232       WillOnce(InvokeWithoutArgs(frontend_dtc_.get(),
    233                                  &FrontendDataTypeController::Stop));
    234   SetStopExpectations();
    235 
    236   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    237   frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
    238   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
    239   // This should cause frontend_dtc_->Stop() to be called.
    240   frontend_dtc_->OnUnrecoverableError(FROM_HERE, "Test");
    241   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    242 }
    243