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/search_engines/template_url_service_factory.h" 12 #include "chrome/browser/search_engines/template_url_service_test_util.h" 13 #include "chrome/browser/sync/glue/search_engine_data_type_controller.h" 14 #include "chrome/browser/sync/profile_sync_components_factory_mock.h" 15 #include "chrome/browser/sync/profile_sync_service_mock.h" 16 #include "chrome/test/base/profile_mock.h" 17 #include "components/sync_driver/data_type_controller_mock.h" 18 #include "components/sync_driver/fake_generic_change_processor.h" 19 #include "sync/api/fake_syncable_service.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 using testing::_; 23 using testing::DoAll; 24 using testing::InvokeWithoutArgs; 25 using testing::Return; 26 using testing::SetArgumentPointee; 27 28 namespace browser_sync { 29 namespace { 30 31 class SyncSearchEngineDataTypeControllerTest : public testing::Test { 32 public: 33 SyncSearchEngineDataTypeControllerTest() { } 34 35 virtual void SetUp() { 36 test_util_.SetUp(); 37 service_.reset(new ProfileSyncServiceMock(test_util_.profile())); 38 profile_sync_factory_.reset(new ProfileSyncComponentsFactoryMock()); 39 // Feed the DTC test_util_'s profile so it is reused later. 40 // This allows us to control the associated TemplateURLService. 41 search_engine_dtc_ = 42 new SearchEngineDataTypeController( 43 profile_sync_factory_.get(), test_util_.profile(), 44 DataTypeController::DisableTypeCallback()); 45 } 46 47 virtual void TearDown() { 48 // Must be done before we pump the loop. 49 syncable_service_.StopSyncing(syncer::SEARCH_ENGINES); 50 search_engine_dtc_ = NULL; 51 service_.reset(); 52 test_util_.TearDown(); 53 } 54 55 protected: 56 // Pre-emptively get the TURL Service and make sure it is loaded. 57 void PreloadTemplateURLService() { 58 test_util_.VerifyLoad(); 59 } 60 61 void SetStartExpectations() { 62 search_engine_dtc_->SetGenericChangeProcessorFactoryForTest( 63 make_scoped_ptr<GenericChangeProcessorFactory>( 64 new FakeGenericChangeProcessorFactory(make_scoped_ptr( 65 new FakeGenericChangeProcessor(profile_sync_factory_.get()))))); 66 EXPECT_CALL(model_load_callback_, Run(_, _)); 67 EXPECT_CALL(*profile_sync_factory_, 68 GetSyncableServiceForType(syncer::SEARCH_ENGINES)). 69 WillOnce(Return(syncable_service_.AsWeakPtr())); 70 } 71 72 void Start() { 73 search_engine_dtc_->LoadModels( 74 base::Bind(&ModelLoadCallbackMock::Run, 75 base::Unretained(&model_load_callback_))); 76 search_engine_dtc_->StartAssociating( 77 base::Bind(&StartCallbackMock::Run, 78 base::Unretained(&start_callback_))); 79 } 80 81 // This also manages a BrowserThread and MessageLoop for us. Note that this 82 // must be declared here as the destruction order of the BrowserThread 83 // matters - we could leak if this is declared below. 84 TemplateURLServiceTestUtil test_util_; 85 scoped_refptr<SearchEngineDataTypeController> search_engine_dtc_; 86 scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_; 87 scoped_ptr<ProfileSyncServiceMock> service_; 88 syncer::FakeSyncableService syncable_service_; 89 StartCallbackMock start_callback_; 90 ModelLoadCallbackMock model_load_callback_; 91 }; 92 93 TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceReady) { 94 SetStartExpectations(); 95 // We want to start ready. 96 PreloadTemplateURLService(); 97 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _)); 98 99 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state()); 100 EXPECT_FALSE(syncable_service_.syncing()); 101 Start(); 102 EXPECT_EQ(DataTypeController::RUNNING, search_engine_dtc_->state()); 103 EXPECT_TRUE(syncable_service_.syncing()); 104 } 105 106 TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceNotReady) { 107 EXPECT_CALL(model_load_callback_, Run(_, _)); 108 EXPECT_FALSE(syncable_service_.syncing()); 109 search_engine_dtc_->LoadModels( 110 base::Bind(&ModelLoadCallbackMock::Run, 111 base::Unretained(&model_load_callback_))); 112 EXPECT_TRUE(search_engine_dtc_->GetSubscriptionForTesting()); 113 EXPECT_EQ(DataTypeController::MODEL_STARTING, search_engine_dtc_->state()); 114 EXPECT_FALSE(syncable_service_.syncing()); 115 116 // Send the notification that the TemplateURLService has started. 117 PreloadTemplateURLService(); 118 EXPECT_EQ(NULL, search_engine_dtc_->GetSubscriptionForTesting()); 119 EXPECT_EQ(DataTypeController::MODEL_LOADED, search_engine_dtc_->state()); 120 121 // Wait until WebDB is loaded before we shut it down. 122 base::RunLoop().RunUntilIdle(); 123 } 124 125 TEST_F(SyncSearchEngineDataTypeControllerTest, StartAssociationFailed) { 126 SetStartExpectations(); 127 PreloadTemplateURLService(); 128 EXPECT_CALL(start_callback_, 129 Run(DataTypeController::ASSOCIATION_FAILED, _, _)); 130 syncable_service_.set_merge_data_and_start_syncing_error( 131 syncer::SyncError(FROM_HERE, 132 syncer::SyncError::DATATYPE_ERROR, 133 "Error", 134 syncer::SEARCH_ENGINES)); 135 136 Start(); 137 EXPECT_EQ(DataTypeController::DISABLED, search_engine_dtc_->state()); 138 EXPECT_FALSE(syncable_service_.syncing()); 139 search_engine_dtc_->Stop(); 140 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state()); 141 EXPECT_FALSE(syncable_service_.syncing()); 142 } 143 144 TEST_F(SyncSearchEngineDataTypeControllerTest, Stop) { 145 SetStartExpectations(); 146 PreloadTemplateURLService(); 147 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _)); 148 149 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state()); 150 EXPECT_FALSE(syncable_service_.syncing()); 151 Start(); 152 EXPECT_EQ(DataTypeController::RUNNING, search_engine_dtc_->state()); 153 EXPECT_TRUE(syncable_service_.syncing()); 154 search_engine_dtc_->Stop(); 155 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state()); 156 EXPECT_FALSE(syncable_service_.syncing()); 157 } 158 159 TEST_F(SyncSearchEngineDataTypeControllerTest, StopBeforeLoaded) { 160 EXPECT_CALL(model_load_callback_, Run(_, _)); 161 EXPECT_FALSE(syncable_service_.syncing()); 162 search_engine_dtc_->LoadModels( 163 base::Bind(&ModelLoadCallbackMock::Run, 164 base::Unretained(&model_load_callback_))); 165 EXPECT_TRUE(search_engine_dtc_->GetSubscriptionForTesting()); 166 EXPECT_EQ(DataTypeController::MODEL_STARTING, search_engine_dtc_->state()); 167 EXPECT_FALSE(syncable_service_.syncing()); 168 search_engine_dtc_->Stop(); 169 EXPECT_EQ(NULL, search_engine_dtc_->GetSubscriptionForTesting()); 170 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state()); 171 EXPECT_FALSE(syncable_service_.syncing()); 172 } 173 174 } // namespace 175 } // namespace browser_sync 176