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.
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/fake_generic_change_processor.h"
14 #include "chrome/browser/sync/glue/search_engine_data_type_controller.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/data_type_controller_mock.h"
19 #include "sync/api/fake_syncable_service.h"
20 #include "testing/gtest/include/gtest/gtest.h"
24 using testing::InvokeWithoutArgs;
25 using testing::Return;
26 using testing::SetArgumentPointee;
28 namespace browser_sync {
31 ACTION(MakeSharedChangeProcessor) {
32 return new SharedChangeProcessor();
35 ACTION_P(ReturnAndRelease, change_processor) {
36 return change_processor->release();
39 class SyncSearchEngineDataTypeControllerTest : public testing::Test {
41 SyncSearchEngineDataTypeControllerTest()
42 : change_processor_(new FakeGenericChangeProcessor()) {
45 virtual void SetUp() {
47 service_.reset(new ProfileSyncServiceMock(test_util_.profile()));
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.
52 new SearchEngineDataTypeController(profile_sync_factory_.get(),
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;
62 test_util_.TearDown();
66 // Pre-emptively get the TURL Service and make sure it is loaded.
67 void PreloadTemplateURLService() {
68 test_util_.VerifyLoad();
71 void SetStartExpectations() {
72 // Ownership gets passed to caller of CreateGenericChangeProcessor.
73 EXPECT_CALL(model_load_callback_, Run(_, _));
74 EXPECT_CALL(*profile_sync_factory_,
75 GetSyncableServiceForType(syncer::SEARCH_ENGINES)).
76 WillOnce(Return(syncable_service_.AsWeakPtr()));
77 EXPECT_CALL(*profile_sync_factory_, CreateSharedChangeProcessor()).
78 WillOnce(MakeSharedChangeProcessor());
79 EXPECT_CALL(*profile_sync_factory_,
80 CreateGenericChangeProcessor(_, _, _, _)).
81 WillOnce(ReturnAndRelease(&change_processor_));
84 void SetActivateExpectations() {
85 EXPECT_CALL(*service_.get(),
86 ActivateDataType(syncer::SEARCH_ENGINES, _, _));
89 void SetStopExpectations() {
90 EXPECT_CALL(*service_.get(),
91 DeactivateDataType(syncer::SEARCH_ENGINES));
95 search_engine_dtc_->LoadModels(
96 base::Bind(&ModelLoadCallbackMock::Run,
97 base::Unretained(&model_load_callback_)));
98 search_engine_dtc_->StartAssociating(
99 base::Bind(&StartCallbackMock::Run,
100 base::Unretained(&start_callback_)));
103 // This also manages a BrowserThread and MessageLoop for us. Note that this
104 // must be declared here as the destruction order of the BrowserThread
105 // matters - we could leak if this is declared below.
106 TemplateURLServiceTestUtil test_util_;
107 scoped_refptr<SearchEngineDataTypeController> search_engine_dtc_;
108 scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
109 scoped_ptr<ProfileSyncServiceMock> service_;
110 scoped_ptr<FakeGenericChangeProcessor> change_processor_;
111 syncer::FakeSyncableService syncable_service_;
112 StartCallbackMock start_callback_;
113 ModelLoadCallbackMock model_load_callback_;
116 TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceReady) {
117 SetStartExpectations();
118 // We want to start ready.
119 PreloadTemplateURLService();
120 SetActivateExpectations();
121 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
123 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
124 EXPECT_FALSE(syncable_service_.syncing());
126 EXPECT_EQ(DataTypeController::RUNNING, search_engine_dtc_->state());
127 EXPECT_TRUE(syncable_service_.syncing());
130 TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceNotReady) {
131 EXPECT_CALL(*profile_sync_factory_, CreateSharedChangeProcessor()).
132 WillOnce(MakeSharedChangeProcessor());
134 EXPECT_CALL(model_load_callback_, Run(_, _));
135 EXPECT_FALSE(syncable_service_.syncing());
136 search_engine_dtc_->LoadModels(
137 base::Bind(&ModelLoadCallbackMock::Run,
138 base::Unretained(&model_load_callback_)));
139 EXPECT_EQ(DataTypeController::MODEL_STARTING, search_engine_dtc_->state());
140 EXPECT_FALSE(syncable_service_.syncing());
142 // Send the notification that the TemplateURLService has started.
143 PreloadTemplateURLService();
144 EXPECT_EQ(DataTypeController::MODEL_LOADED, search_engine_dtc_->state());
146 // Wait until WebDB is loaded before we shut it down.
147 base::RunLoop().RunUntilIdle();
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, _, _));
158 EXPECT_TRUE(syncable_service_.syncing());
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,
171 syncer::SEARCH_ENGINES));
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());
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);
191 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
192 EXPECT_FALSE(syncable_service_.syncing());
195 TEST_F(SyncSearchEngineDataTypeControllerTest, Stop) {
196 SetStartExpectations();
197 PreloadTemplateURLService();
198 SetActivateExpectations();
199 SetStopExpectations();
200 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
202 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
203 EXPECT_FALSE(syncable_service_.syncing());
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());
212 TEST_F(SyncSearchEngineDataTypeControllerTest,
213 OnSingleDatatypeUnrecoverableError) {
214 SetStartExpectations();
215 PreloadTemplateURLService();
216 SetActivateExpectations();
217 EXPECT_CALL(*service_.get(), DisableBrokenDatatype(_, _, _)).
218 WillOnce(InvokeWithoutArgs(search_engine_dtc_.get(),
219 &SearchEngineDataTypeController::Stop));
220 SetStopExpectations();
222 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
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());
232 } // namespace browser_sync