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/data_type_controller_mock.h"
14 #include "chrome/browser/sync/glue/fake_generic_change_processor.h"
15 #include "chrome/browser/sync/glue/search_engine_data_type_controller.h"
16 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
17 #include "chrome/browser/sync/profile_sync_service_mock.h"
18 #include "chrome/test/base/profile_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()) {}
44 virtual void SetUp() {
46 profile_sync_factory_.reset(new ProfileSyncComponentsFactoryMock());
47 // Feed the DTC test_util_'s profile so it is reused later.
48 // This allows us to control the associated TemplateURLService.
50 new SearchEngineDataTypeController(profile_sync_factory_.get(),
55 virtual void TearDown() {
56 // Must be done before we pump the loop.
57 syncable_service_.StopSyncing(syncer::SEARCH_ENGINES);
58 search_engine_dtc_ = NULL;
59 test_util_.TearDown();
63 // Pre-emptively get the TURL Service and make sure it is loaded.
64 void PreloadTemplateURLService() {
65 test_util_.VerifyLoad();
68 void SetStartExpectations() {
69 // Ownership gets passed to caller of CreateGenericChangeProcessor.
70 EXPECT_CALL(model_load_callback_, Run(_, _));
71 EXPECT_CALL(*profile_sync_factory_,
72 GetSyncableServiceForType(syncer::SEARCH_ENGINES)).
73 WillOnce(Return(syncable_service_.AsWeakPtr()));
74 EXPECT_CALL(*profile_sync_factory_, CreateSharedChangeProcessor()).
75 WillOnce(MakeSharedChangeProcessor());
76 EXPECT_CALL(*profile_sync_factory_,
77 CreateGenericChangeProcessor(_, _, _, _)).
78 WillOnce(ReturnAndRelease(&change_processor_));
81 void SetActivateExpectations() {
82 EXPECT_CALL(service_, ActivateDataType(syncer::SEARCH_ENGINES, _, _));
85 void SetStopExpectations() {
86 EXPECT_CALL(service_, DeactivateDataType(syncer::SEARCH_ENGINES));
90 search_engine_dtc_->LoadModels(
91 base::Bind(&ModelLoadCallbackMock::Run,
92 base::Unretained(&model_load_callback_)));
93 search_engine_dtc_->StartAssociating(
94 base::Bind(&StartCallbackMock::Run,
95 base::Unretained(&start_callback_)));
98 // This also manages a BrowserThread and MessageLoop for us. Note that this
99 // must be declared here as the destruction order of the BrowserThread
100 // matters - we could leak if this is declared below.
101 TemplateURLServiceTestUtil test_util_;
102 scoped_refptr<SearchEngineDataTypeController> search_engine_dtc_;
103 scoped_ptr<ProfileSyncComponentsFactoryMock> profile_sync_factory_;
104 ProfileSyncServiceMock service_;
105 scoped_ptr<FakeGenericChangeProcessor> change_processor_;
106 syncer::FakeSyncableService syncable_service_;
107 StartCallbackMock start_callback_;
108 ModelLoadCallbackMock model_load_callback_;
111 TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceReady) {
112 SetStartExpectations();
113 // We want to start ready.
114 PreloadTemplateURLService();
115 SetActivateExpectations();
116 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
118 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
119 EXPECT_FALSE(syncable_service_.syncing());
121 EXPECT_EQ(DataTypeController::RUNNING, search_engine_dtc_->state());
122 EXPECT_TRUE(syncable_service_.syncing());
125 TEST_F(SyncSearchEngineDataTypeControllerTest, StartURLServiceNotReady) {
126 EXPECT_CALL(*profile_sync_factory_, CreateSharedChangeProcessor()).
127 WillOnce(MakeSharedChangeProcessor());
129 EXPECT_CALL(model_load_callback_, Run(_, _));
130 EXPECT_FALSE(syncable_service_.syncing());
131 search_engine_dtc_->LoadModels(
132 base::Bind(&ModelLoadCallbackMock::Run,
133 base::Unretained(&model_load_callback_)));
134 EXPECT_EQ(DataTypeController::MODEL_STARTING, search_engine_dtc_->state());
135 EXPECT_FALSE(syncable_service_.syncing());
137 // Send the notification that the TemplateURLService has started.
138 PreloadTemplateURLService();
139 EXPECT_EQ(DataTypeController::MODEL_LOADED, search_engine_dtc_->state());
141 // Wait until WebDB is loaded before we shut it down.
142 base::RunLoop().RunUntilIdle();
145 TEST_F(SyncSearchEngineDataTypeControllerTest, StartFirstRun) {
146 SetStartExpectations();
147 PreloadTemplateURLService();
148 SetActivateExpectations();
149 change_processor_->set_sync_model_has_user_created_nodes(false);
150 EXPECT_CALL(start_callback_, Run(DataTypeController::OK_FIRST_RUN, _, _));
153 EXPECT_TRUE(syncable_service_.syncing());
156 TEST_F(SyncSearchEngineDataTypeControllerTest, StartAssociationFailed) {
157 SetStartExpectations();
158 PreloadTemplateURLService();
159 SetStopExpectations();
160 EXPECT_CALL(start_callback_,
161 Run(DataTypeController::ASSOCIATION_FAILED, _, _));
162 syncable_service_.set_merge_data_and_start_syncing_error(
163 syncer::SyncError(FROM_HERE,
164 syncer::SyncError::DATATYPE_ERROR,
166 syncer::SEARCH_ENGINES));
169 EXPECT_EQ(DataTypeController::DISABLED, search_engine_dtc_->state());
170 EXPECT_FALSE(syncable_service_.syncing());
171 search_engine_dtc_->Stop();
172 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
173 EXPECT_FALSE(syncable_service_.syncing());
176 TEST_F(SyncSearchEngineDataTypeControllerTest,
177 StartAssociationTriggersUnrecoverableError) {
178 SetStartExpectations();
179 PreloadTemplateURLService();
180 EXPECT_CALL(start_callback_,
181 Run(DataTypeController::UNRECOVERABLE_ERROR, _, _));
182 // Set up association to fail with an unrecoverable error.
183 change_processor_->set_sync_model_has_user_created_nodes_success(false);
186 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
187 EXPECT_FALSE(syncable_service_.syncing());
190 TEST_F(SyncSearchEngineDataTypeControllerTest, Stop) {
191 SetStartExpectations();
192 PreloadTemplateURLService();
193 SetActivateExpectations();
194 SetStopExpectations();
195 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
197 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
198 EXPECT_FALSE(syncable_service_.syncing());
200 EXPECT_EQ(DataTypeController::RUNNING, search_engine_dtc_->state());
201 EXPECT_TRUE(syncable_service_.syncing());
202 search_engine_dtc_->Stop();
203 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
204 EXPECT_FALSE(syncable_service_.syncing());
207 TEST_F(SyncSearchEngineDataTypeControllerTest,
208 OnSingleDatatypeUnrecoverableError) {
209 SetStartExpectations();
210 PreloadTemplateURLService();
211 SetActivateExpectations();
212 EXPECT_CALL(service_, DisableBrokenDatatype(_, _, _)).
213 WillOnce(InvokeWithoutArgs(search_engine_dtc_.get(),
214 &SearchEngineDataTypeController::Stop));
215 SetStopExpectations();
217 EXPECT_CALL(start_callback_, Run(DataTypeController::OK, _, _));
219 // This should cause search_engine_dtc_->Stop() to be called.
220 search_engine_dtc_->OnSingleDatatypeUnrecoverableError(FROM_HERE, "Test");
221 base::RunLoop().RunUntilIdle();
222 EXPECT_EQ(DataTypeController::NOT_RUNNING, search_engine_dtc_->state());
223 EXPECT_FALSE(syncable_service_.syncing());
227 } // namespace browser_sync