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