Home | History | Annotate | Download | only in glue
      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/memory/scoped_ptr.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/tracked_objects.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/profile_sync_components_factory_mock.h"
     16 #include "chrome/browser/sync/profile_sync_service_mock.h"
     17 #include "chrome/test/base/profile_mock.h"
     18 #include "components/sync_driver/change_processor_mock.h"
     19 #include "components/sync_driver/data_type_controller_mock.h"
     20 #include "components/sync_driver/model_associator_mock.h"
     21 #include "content/public/test/test_browser_thread_bundle.h"
     22 
     23 using browser_sync::FrontendDataTypeController;
     24 using browser_sync::FrontendDataTypeControllerMock;
     25 using sync_driver::ChangeProcessorMock;
     26 using sync_driver::DataTypeController;
     27 using sync_driver::ModelAssociatorMock;
     28 using sync_driver::ModelLoadCallbackMock;
     29 using sync_driver::StartCallbackMock;
     30 using testing::_;
     31 using testing::DoAll;
     32 using testing::InvokeWithoutArgs;
     33 using testing::Return;
     34 using testing::SetArgumentPointee;
     35 using testing::StrictMock;
     36 
     37 class FrontendDataTypeControllerFake : public FrontendDataTypeController {
     38  public:
     39   FrontendDataTypeControllerFake(
     40       ProfileSyncComponentsFactory* profile_sync_factory,
     41       Profile* profile,
     42       ProfileSyncService* sync_service,
     43       FrontendDataTypeControllerMock* mock)
     44       : FrontendDataTypeController(base::MessageLoopProxy::current(),
     45                                    base::Closure(),
     46                                    profile_sync_factory,
     47                                    profile,
     48                                    sync_service),
     49         mock_(mock) {}
     50   virtual syncer::ModelType type() const OVERRIDE { return syncer::BOOKMARKS; }
     51 
     52  private:
     53   virtual void CreateSyncComponents() OVERRIDE {
     54     ProfileSyncComponentsFactory::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() OVERRIDE {
     64     return mock_->StartModels();
     65   }
     66   virtual void CleanUpState() OVERRIDE {
     67     mock_->CleanUpState();
     68   }
     69   virtual void RecordUnrecoverableError(
     70       const tracked_objects::Location& from_here,
     71       const std::string& message) OVERRIDE {
     72     mock_->RecordUnrecoverableError(from_here, message);
     73   }
     74   virtual void RecordAssociationTime(base::TimeDelta time) OVERRIDE {
     75     mock_->RecordAssociationTime(time);
     76   }
     77   virtual void RecordStartFailure(
     78       DataTypeController::ConfigureResult result) OVERRIDE {
     79     mock_->RecordStartFailure(result);
     80   }
     81  private:
     82   virtual ~FrontendDataTypeControllerFake() {}
     83   FrontendDataTypeControllerMock* mock_;
     84 };
     85 
     86 class SyncFrontendDataTypeControllerTest : public testing::Test {
     87  public:
     88   SyncFrontendDataTypeControllerTest()
     89       : thread_bundle_(content::TestBrowserThreadBundle::DEFAULT),
     90         service_(&profile_) {}
     91 
     92   virtual void SetUp() {
     93     profile_sync_factory_.reset(new ProfileSyncComponentsFactoryMock());
     94     dtc_mock_ = new StrictMock<FrontendDataTypeControllerMock>();
     95     frontend_dtc_ =
     96         new FrontendDataTypeControllerFake(profile_sync_factory_.get(),
     97                                            &profile_,
     98                                            &service_,
     99                                            dtc_mock_.get());
    100   }
    101 
    102  protected:
    103   void SetStartExpectations() {
    104     EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(true));
    105     EXPECT_CALL(model_load_callback_, Run(_, _));
    106     model_associator_ = new ModelAssociatorMock();
    107     change_processor_ = new ChangeProcessorMock();
    108     EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
    109         WillOnce(Return(ProfileSyncComponentsFactory::SyncComponents(
    110             model_associator_, change_processor_)));
    111   }
    112 
    113   void SetAssociateExpectations() {
    114     EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    115         WillOnce(Return(true));
    116     EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
    117         WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
    118     EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
    119         WillOnce(Return(syncer::SyncError()));
    120     EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
    121   }
    122 
    123   void SetActivateExpectations(DataTypeController::ConfigureResult result) {
    124     EXPECT_CALL(start_callback_, Run(result, _, _));
    125   }
    126 
    127   void SetStopExpectations() {
    128     EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
    129     EXPECT_CALL(service_, DeactivateDataType(_));
    130     EXPECT_CALL(*model_associator_, DisassociateModels()).
    131                 WillOnce(Return(syncer::SyncError()));
    132   }
    133 
    134   void SetStartFailExpectations(DataTypeController::ConfigureResult result) {
    135     if (DataTypeController::IsUnrecoverableResult(result))
    136       EXPECT_CALL(*dtc_mock_.get(), RecordUnrecoverableError(_, _));
    137     EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
    138     EXPECT_CALL(*dtc_mock_.get(), RecordStartFailure(result));
    139     EXPECT_CALL(start_callback_, Run(result, _, _));
    140   }
    141 
    142   void Start() {
    143     frontend_dtc_->LoadModels(
    144         base::Bind(&ModelLoadCallbackMock::Run,
    145                    base::Unretained(&model_load_callback_)));
    146     frontend_dtc_->StartAssociating(
    147         base::Bind(&StartCallbackMock::Run,
    148                    base::Unretained(&start_callback_)));
    149   }
    150 
    151   void PumpLoop() { base::MessageLoop::current()->RunUntilIdle(); }
    152 
    153   content::TestBrowserThreadBundle thread_bundle_;
    154   scoped_refptr<FrontendDataTypeControllerFake> frontend_dtc_;
    155   scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
    156   scoped_refptr<FrontendDataTypeControllerMock> dtc_mock_;
    157   ProfileMock profile_;
    158   ProfileSyncServiceMock service_;
    159   ModelAssociatorMock* model_associator_;
    160   ChangeProcessorMock* change_processor_;
    161   StartCallbackMock start_callback_;
    162   ModelLoadCallbackMock model_load_callback_;
    163 };
    164 
    165 TEST_F(SyncFrontendDataTypeControllerTest, StartOk) {
    166   SetStartExpectations();
    167   SetAssociateExpectations();
    168   SetActivateExpectations(DataTypeController::OK);
    169   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    170   Start();
    171   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
    172 }
    173 
    174 TEST_F(SyncFrontendDataTypeControllerTest, StartFirstRun) {
    175   SetStartExpectations();
    176   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    177       WillOnce(Return(true));
    178   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
    179       WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
    180   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
    181       WillOnce(Return(syncer::SyncError()));
    182   EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
    183   SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
    184   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    185   Start();
    186   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
    187 }
    188 
    189 TEST_F(SyncFrontendDataTypeControllerTest, AbortDuringStartModels) {
    190   EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(false));
    191   EXPECT_CALL(*dtc_mock_.get(), CleanUpState());
    192   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    193   frontend_dtc_->LoadModels(
    194       base::Bind(&ModelLoadCallbackMock::Run,
    195                  base::Unretained(&model_load_callback_)));
    196   EXPECT_EQ(DataTypeController::MODEL_STARTING, frontend_dtc_->state());
    197   frontend_dtc_->Stop();
    198   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    199 }
    200 
    201 TEST_F(SyncFrontendDataTypeControllerTest, StartAssociationFailed) {
    202   SetStartExpectations();
    203   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    204       WillOnce(Return(true));
    205   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
    206       WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
    207   EXPECT_CALL(*model_associator_, AssociateModels(_, _)).
    208       WillOnce(Return(syncer::SyncError(FROM_HERE,
    209                                         syncer::SyncError::DATATYPE_ERROR,
    210                                         "error",
    211                                         syncer::BOOKMARKS)));
    212 
    213   EXPECT_CALL(*dtc_mock_.get(), RecordAssociationTime(_));
    214   SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
    215   // Set up association to fail with an association failed error.
    216   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    217   Start();
    218   EXPECT_EQ(DataTypeController::DISABLED, frontend_dtc_->state());
    219 }
    220 
    221 TEST_F(SyncFrontendDataTypeControllerTest,
    222        StartAssociationTriggersUnrecoverableError) {
    223   SetStartExpectations();
    224   SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
    225   // Set up association to fail with an unrecoverable error.
    226   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    227       WillRepeatedly(Return(true));
    228   EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
    229       WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
    230   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    231   Start();
    232   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    233 }
    234 
    235 TEST_F(SyncFrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
    236   SetStartExpectations();
    237   SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
    238   // Set up association to fail with a NEEDS_CRYPTO error.
    239   EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
    240       WillRepeatedly(Return(false));
    241   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    242   Start();
    243   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    244 }
    245 
    246 TEST_F(SyncFrontendDataTypeControllerTest, Stop) {
    247   SetStartExpectations();
    248   SetAssociateExpectations();
    249   SetActivateExpectations(DataTypeController::OK);
    250   SetStopExpectations();
    251   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    252   Start();
    253   EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
    254   frontend_dtc_->Stop();
    255   EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
    256 }
    257