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 "base/bind.h"
      6 #include "base/bind_helpers.h"
      7 #include "base/callback.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/run_loop.h"
     10 #include "base/tracked_objects.h"
     11 #include "chrome/browser/chrome_notification_types.h"
     12 #include "chrome/browser/search_engines/template_url_service_factory.h"
     13 #include "chrome/browser/search_engines/template_url_service_test_util.h"
     14 #include "chrome/browser/sync/glue/data_type_controller_mock.h"
     15 #include "chrome/browser/sync/glue/fake_generic_change_processor.h"
     16 #include "chrome/browser/sync/glue/search_engine_data_type_controller.h"
     17 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
     18 #include "chrome/browser/sync/profile_sync_service_mock.h"
     19 #include "chrome/test/base/profile_mock.h"
     20 #include "content/public/browser/notification_service.h"
     21 #include "sync/api/fake_syncable_service.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 
     24 using testing::_;
     25 using testing::DoAll;
     26 using testing::InvokeWithoutArgs;
     27 using testing::Return;
     28 using testing::SetArgumentPointee;
     29 
     30 namespace browser_sync {
     31 namespace {
     32 
     33 ACTION(MakeSharedChangeProcessor) {
     34   return new SharedChangeProcessor();
     35 }
     36 
     37 ACTION_P(ReturnAndRelease, change_processor) {
     38   return change_processor->release();
     39 }
     40 
     41 class SyncSearchEngineDataTypeControllerTest : public testing::Test {
     42  public:
     43   SyncSearchEngineDataTypeControllerTest()
     44       : change_processor_(new FakeGenericChangeProcessor()) {}
     45 
     46   virtual void SetUp() {
     47     test_util_.SetUp();
     48     profile_sync_factory_.reset(new ProfileSyncComponentsFactoryMock());
     49     // Feed the DTC test_util_'s profile so it is reused later.
     50     // This allows us to control the associated TemplateURLService.
     51     search_engine_dtc_ =
     52         new SearchEngineDataTypeController(profile_sync_factory_.get(),
     53                                            test_util_.profile(),
     54                                            &service_);
     55   }
     56 
     57   virtual void TearDown() {
     58     // Must be done before we pump the loop.
     59     syncable_service_.StopSyncing(syncer::SEARCH_ENGINES);
     60     search_engine_dtc_ = NULL;
     61     test_util_.TearDown();
     62   }
     63 
     64  protected:
     65   // Pre-emptively get the TURL Service and make sure it is loaded.
     66   void PreloadTemplateURLService() {
     67     test_util_.VerifyLoad();
     68   }
     69 
     70   void SetStartExpectations() {
     71     // Ownership gets passed to caller of CreateGenericChangeProcessor.
     72     EXPECT_CALL(model_load_callback_, Run(_, _));
     73     EXPECT_CALL(*profile_sync_factory_,
     74                 GetSyncableServiceForType(syncer::SEARCH_ENGINES)).
     75         WillOnce(Return(syncable_service_.AsWeakPtr()));
     76     EXPECT_CALL(*profile_sync_factory_, CreateSharedChangeProcessor()).
     77         WillOnce(MakeSharedChangeProcessor());
     78     EXPECT_CALL(*profile_sync_factory_,
     79                 CreateGenericChangeProcessor(_, _, _, _)).
     80         WillOnce(ReturnAndRelease(&change_processor_));
     81   }
     82 
     83   void SetActivateExpectations() {
     84     EXPECT_CALL(service_, ActivateDataType(syncer::SEARCH_ENGINES, _, _));
     85   }
     86 
     87   void SetStopExpectations() {
     88     EXPECT_CALL(service_, DeactivateDataType(syncer::SEARCH_ENGINES));
     89   }
     90 
     91   void Start() {
     92     search_engine_dtc_->LoadModels(
     93         base::Bind(&ModelLoadCallbackMock::Run,
     94                    base::Unretained(&model_load_callback_)));
     95     search_engine_dtc_->StartAssociating(
     96         base::Bind(&StartCallbackMock::Run,
     97                    base::Unretained(&start_callback_)));
     98   }
     99 
    100   // This also manages a BrowserThread and MessageLoop for us. Note that this
    101   // must be declared here as the destruction order of the BrowserThread
    102   // matters - we could leak if this is declared below.
    103   TemplateURLServiceTestUtil test_util_;
    104   scoped_refptr<SearchEngineDataTypeController> search_engine_dtc_;
    105   scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
    106   ProfileSyncServiceMock service_;
    107   scoped_ptr<FakeGenericChangeProcessor> change_processor_;
    108   syncer::FakeSyncableService syncable_service_;
    109   StartCallbackMock start_callback_;
    110   ModelLoadCallbackMock model_load_callback_;
    111 };
    112 
    113 TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceReady) {
    114   SetStartExpectations();
    115   // We want to start ready.
    116   PreloadTemplateURLService();
    117   SetActivateExpectations();
    118   EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
    119 
    120   EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
    121   EXPECT_FALSE(syncable_service_.syncing());
    122   Start();
    123   EXPECT_EQ(DataTypeController::RUNNING, search_engine_dtc_->state());
    124   EXPECT_TRUE(syncable_service_.syncing());
    125 }
    126 
    127 TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceNotReady) {
    128   EXPECT_CALL(*profile_sync_factory_, CreateSharedChangeProcessor()).
    129       WillOnce(MakeSharedChangeProcessor());
    130 
    131   EXPECT_CALL(model_load_callback_, Run(_, _));
    132   EXPECT_FALSE(syncable_service_.syncing());
    133   search_engine_dtc_->LoadModels(
    134       base::Bind(&ModelLoadCallbackMock::Run,
    135                  base::Unretained(&model_load_callback_)));
    136   EXPECT_EQ(DataTypeController::MODEL_STARTING, search_engine_dtc_->state());
    137   EXPECT_FALSE(syncable_service_.syncing());
    138 
    139   // Send the notification that the TemplateURLService has started.
    140   content::NotificationService::current()->Notify(
    141       chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED,
    142       content::Source<TemplateURLService>(test_util_.model()),
    143       content::NotificationService::NoDetails());
    144   EXPECT_EQ(DataTypeController::MODEL_LOADED, search_engine_dtc_->state());
    145 
    146   // Wait until WebDB is loaded before we shut it down.
    147   base::RunLoop().RunUntilIdle();
    148 }
    149 
    150 TEST_F(SyncSearchEngineDataTypeControllerTest, StartFirstRun) {
    151   SetStartExpectations();
    152   PreloadTemplateURLService();
    153   SetActivateExpectations();
    154   change_processor_->set_sync_model_has_user_created_nodes(false);
    155   EXPECT_CALL(start_callback_, Run(DataTypeController::OK_FIRST_RUN, _, _));
    156 
    157   Start();
    158   EXPECT_TRUE(syncable_service_.syncing());
    159 }
    160 
    161 TEST_F(SyncSearchEngineDataTypeControllerTest, StartAssociationFailed) {
    162   SetStartExpectations();
    163   PreloadTemplateURLService();
    164   SetStopExpectations();
    165   EXPECT_CALL(start_callback_,
    166               Run(DataTypeController::ASSOCIATION_FAILED, _, _));
    167   syncable_service_.set_merge_data_and_start_syncing_error(
    168       syncer::SyncError(FROM_HERE,
    169                         syncer::SyncError::DATATYPE_ERROR,
    170                         "Error",
    171                         syncer::SEARCH_ENGINES));
    172 
    173   Start();
    174   EXPECT_EQ(DataTypeController::DISABLED, search_engine_dtc_->state());
    175   EXPECT_FALSE(syncable_service_.syncing());
    176   search_engine_dtc_->Stop();
    177   EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
    178   EXPECT_FALSE(syncable_service_.syncing());
    179 }
    180 
    181 TEST_F(SyncSearchEngineDataTypeControllerTest,
    182        StartAssociationTriggersUnrecoverableError) {
    183   SetStartExpectations();
    184   PreloadTemplateURLService();
    185   EXPECT_CALL(start_callback_,
    186               Run(DataTypeController::UNRECOVERABLE_ERROR, _, _));
    187   // Set up association to fail with an unrecoverable error.
    188   change_processor_->set_sync_model_has_user_created_nodes_success(false);
    189 
    190   Start();
    191   EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
    192   EXPECT_FALSE(syncable_service_.syncing());
    193 }
    194 
    195 TEST_F(SyncSearchEngineDataTypeControllerTest, Stop) {
    196   SetStartExpectations();
    197   PreloadTemplateURLService();
    198   SetActivateExpectations();
    199   SetStopExpectations();
    200   EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
    201 
    202   EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
    203   EXPECT_FALSE(syncable_service_.syncing());
    204   Start();
    205   EXPECT_EQ(DataTypeController::RUNNING, search_engine_dtc_->state());
    206   EXPECT_TRUE(syncable_service_.syncing());
    207   search_engine_dtc_->Stop();
    208   EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
    209   EXPECT_FALSE(syncable_service_.syncing());
    210 }
    211 
    212 TEST_F(SyncSearchEngineDataTypeControllerTest,
    213        OnSingleDatatypeUnrecoverableError) {
    214   SetStartExpectations();
    215   PreloadTemplateURLService();
    216   SetActivateExpectations();
    217   EXPECT_CALL(service_, DisableBrokenDatatype(_, _, _)).
    218       WillOnce(InvokeWithoutArgs(search_engine_dtc_.get(),
    219                                  &SearchEngineDataTypeController::Stop));
    220   SetStopExpectations();
    221 
    222   EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
    223   Start();
    224   // This should cause search_engine_dtc_->Stop() to be called.
    225   search_engine_dtc_->OnSingleDatatypeUnrecoverableError(FROM_HERE, "Test");
    226   base::RunLoop().RunUntilIdle();
    227   EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
    228   EXPECT_FALSE(syncable_service_.syncing());
    229 }
    230 
    231 }  // namespace
    232 }  // namespace browser_sync
    233