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