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.
5 #include "base/basictypes.h"
6 #include "base/compiler_specific.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "base/values.h"
10 #include "chrome/browser/invalidation/invalidation_service_factory.h"
11 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
12 #include "chrome/browser/signin/signin_manager.h"
13 #include "chrome/browser/signin/signin_manager_factory.h"
14 #include "chrome/browser/sync/fake_oauth2_token_service_for_sync.h"
15 #include "chrome/browser/sync/glue/data_type_manager_impl.h"
16 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
17 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/test/base/testing_pref_service_syncable.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "google_apis/gaia/gaia_constants.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 namespace browser_sync
{
30 ACTION(ReturnNewDataTypeManager
) {
31 return new browser_sync::DataTypeManagerImpl(arg0
,
40 using testing::StrictMock
;
42 class TestProfileSyncServiceObserver
: public ProfileSyncServiceObserver
{
44 explicit TestProfileSyncServiceObserver(ProfileSyncService
* service
)
45 : service_(service
), first_setup_in_progress_(false) {}
46 virtual void OnStateChanged() OVERRIDE
{
47 first_setup_in_progress_
= service_
->FirstSetupInProgress();
49 bool first_setup_in_progress() const { return first_setup_in_progress_
; }
51 ProfileSyncService
* service_
;
52 bool first_setup_in_progress_
;
55 // A variant of the SyncBackendHostMock that won't automatically
56 // call back when asked to initialized. Allows us to test things
57 // that could happen while backend init is in progress.
58 class SyncBackendHostNoReturn
: public SyncBackendHostMock
{
59 virtual void Initialize(
60 SyncFrontend
* frontend
,
61 scoped_ptr
<base::Thread
> sync_thread
,
62 const syncer::WeakHandle
<syncer::JsEventHandler
>& event_handler
,
63 const GURL
& service_url
,
64 const syncer::SyncCredentials
& credentials
,
65 bool delete_sync_data_folder
,
66 scoped_ptr
<syncer::SyncManagerFactory
> sync_manager_factory
,
67 scoped_ptr
<syncer::UnrecoverableErrorHandler
> unrecoverable_error_handler
,
68 syncer::ReportUnrecoverableErrorFunction
69 report_unrecoverable_error_function
,
70 syncer::NetworkResources
* network_resources
) OVERRIDE
{}
73 ACTION(ReturnNewSyncBackendHostMock
) {
74 return new browser_sync::SyncBackendHostMock();
77 ACTION(ReturnNewSyncBackendHostNoReturn
) {
78 return new browser_sync::SyncBackendHostNoReturn();
81 // A test harness that uses a real ProfileSyncService and in most cases a
82 // MockSyncBackendHost.
84 // This is useful if we want to test the ProfileSyncService and don't care about
85 // testing the SyncBackendHost.
86 class ProfileSyncServiceTest
: public ::testing::Test
{
88 ProfileSyncServiceTest()
89 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
) {}
90 virtual ~ProfileSyncServiceTest() {}
92 virtual void SetUp() OVERRIDE
{
93 TestingProfile::Builder builder
;
95 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
96 FakeOAuth2TokenServiceForSync::BuildTokenService
);
97 invalidation::InvalidationServiceFactory::GetInstance()->
98 SetBuildOnlyFakeInvalidatorsForTest(true);
100 profile_
= builder
.Build().Pass();
103 virtual void TearDown() OVERRIDE
{
104 // Kill the service before the profile.
106 service_
->Shutdown();
112 void IssueTestTokens() {
113 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_
.get())
114 ->UpdateCredentials("test", "oauth2_login_token");
117 void CreateService(ProfileSyncService::StartBehavior behavior
) {
118 SigninManagerBase
* signin
=
119 SigninManagerFactory::GetForProfile(profile_
.get());
120 signin
->SetAuthenticatedUsername("test");
121 ProfileOAuth2TokenService
* oauth2_token_service
=
122 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_
.get());
123 components_factory_
= new StrictMock
<ProfileSyncComponentsFactoryMock
>();
124 service_
.reset(new ProfileSyncService(
128 oauth2_token_service
,
132 void ShutdownAndDeleteService() {
134 service_
->Shutdown();
139 service_
->Initialize();
142 void ExpectDataTypeManagerCreation() {
143 EXPECT_CALL(*components_factory_
, CreateDataTypeManager(_
, _
, _
, _
, _
, _
)).
144 WillOnce(ReturnNewDataTypeManager());
147 void ExpectSyncBackendHostCreation() {
148 EXPECT_CALL(*components_factory_
, CreateSyncBackendHost(_
, _
, _
)).
149 WillOnce(ReturnNewSyncBackendHostMock());
152 void PrepareDelayedInitSyncBackendHost() {
153 EXPECT_CALL(*components_factory_
, CreateSyncBackendHost(_
, _
, _
)).
154 WillOnce(ReturnNewSyncBackendHostNoReturn());
157 TestingProfile
* profile() {
158 return profile_
.get();
161 ProfileSyncService
* service() {
162 return service_
.get();
165 ProfileSyncComponentsFactoryMock
* components_factory() {
166 return components_factory_
;
170 scoped_ptr
<TestingProfile
> profile_
;
171 scoped_ptr
<ProfileSyncService
> service_
;
173 // Pointer to the components factory. Not owned. May be null.
174 ProfileSyncComponentsFactoryMock
* components_factory_
;
176 content::TestBrowserThreadBundle thread_bundle_
;
179 // Verify that the server URLs are sane.
180 TEST_F(ProfileSyncServiceTest
, InitialState
) {
181 CreateService(ProfileSyncService::AUTO_START
);
183 const std::string
& url
= service()->sync_service_url().spec();
184 EXPECT_TRUE(url
== ProfileSyncService::kSyncServerUrl
||
185 url
== ProfileSyncService::kDevServerUrl
);
188 // Verify a successful initialization.
189 TEST_F(ProfileSyncServiceTest
, SuccessfulInitialization
) {
190 profile()->GetTestingPrefService()->SetManagedPref(
192 base::Value::CreateBooleanValue(false));
194 CreateService(ProfileSyncService::AUTO_START
);
195 ExpectDataTypeManagerCreation();
196 ExpectSyncBackendHostCreation();
198 EXPECT_FALSE(service()->IsManaged());
199 EXPECT_TRUE(service()->sync_initialized());
203 // Verify that the SetSetupInProgress function call updates state
204 // and notifies observers.
205 TEST_F(ProfileSyncServiceTest
, SetupInProgress
) {
206 CreateService(ProfileSyncService::MANUAL_START
);
209 TestProfileSyncServiceObserver
observer(service());
210 service()->AddObserver(&observer
);
212 service()->SetSetupInProgress(true);
213 EXPECT_TRUE(observer
.first_setup_in_progress());
214 service()->SetSetupInProgress(false);
215 EXPECT_FALSE(observer
.first_setup_in_progress());
217 service()->RemoveObserver(&observer
);
220 // Verify that disable by enterprise policy works.
221 TEST_F(ProfileSyncServiceTest
, DisabledByPolicyBeforeInit
) {
222 profile()->GetTestingPrefService()->SetManagedPref(
224 base::Value::CreateBooleanValue(true));
226 CreateService(ProfileSyncService::AUTO_START
);
228 EXPECT_TRUE(service()->IsManaged());
229 EXPECT_FALSE(service()->sync_initialized());
232 // Verify that disable by enterprise policy works even after the backend has
234 TEST_F(ProfileSyncServiceTest
, DisabledByPolicyAfterInit
) {
236 CreateService(ProfileSyncService::AUTO_START
);
237 ExpectDataTypeManagerCreation();
238 ExpectSyncBackendHostCreation();
241 EXPECT_FALSE(service()->IsManaged());
242 EXPECT_TRUE(service()->sync_initialized());
244 profile()->GetTestingPrefService()->SetManagedPref(
246 base::Value::CreateBooleanValue(true));
248 EXPECT_TRUE(service()->IsManaged());
249 EXPECT_FALSE(service()->sync_initialized());
252 // Exercies the ProfileSyncService's code paths related to getting shut down
253 // before the backend initialize call returns.
254 TEST_F(ProfileSyncServiceTest
, AbortedByShutdown
) {
255 CreateService(ProfileSyncService::AUTO_START
);
256 PrepareDelayedInitSyncBackendHost();
260 EXPECT_FALSE(service()->sync_initialized());
262 ShutdownAndDeleteService();
265 // Test StopAndSuppress() before we've initialized the backend.
266 TEST_F(ProfileSyncServiceTest
, EarlyStopAndSuppress
) {
267 CreateService(ProfileSyncService::AUTO_START
);
270 service()->StopAndSuppress();
271 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart
));
273 // Because of supression, this should fail.
275 EXPECT_FALSE(service()->sync_initialized());
277 // Remove suppression. This should be enough to allow init to happen.
278 ExpectDataTypeManagerCreation();
279 ExpectSyncBackendHostCreation();
280 service()->UnsuppressAndStart();
281 EXPECT_TRUE(service()->sync_initialized());
283 profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart
));
286 // Test StopAndSuppress() after we've initialized the backend.
287 TEST_F(ProfileSyncServiceTest
, DisableAndEnableSyncTemporarily
) {
288 CreateService(ProfileSyncService::AUTO_START
);
290 ExpectDataTypeManagerCreation();
291 ExpectSyncBackendHostCreation();
294 EXPECT_TRUE(service()->sync_initialized());
295 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart
));
297 testing::Mock::VerifyAndClearExpectations(components_factory());
299 service()->StopAndSuppress();
300 EXPECT_FALSE(service()->sync_initialized());
301 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart
));
303 ExpectDataTypeManagerCreation();
304 ExpectSyncBackendHostCreation();
306 service()->UnsuppressAndStart();
307 EXPECT_TRUE(service()->sync_initialized());
309 profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart
));
312 // Certain ProfileSyncService tests don't apply to Chrome OS, for example
313 // things that deal with concepts like "signing out" and policy.
314 #if !defined (OS_CHROMEOS)
316 TEST_F(ProfileSyncServiceTest
, EnableSyncAndSignOut
) {
317 CreateService(ProfileSyncService::AUTO_START
);
318 ExpectDataTypeManagerCreation();
319 ExpectSyncBackendHostCreation();
323 EXPECT_TRUE(service()->sync_initialized());
324 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart
));
326 SigninManagerFactory::GetForProfile(profile())->SignOut();
327 EXPECT_FALSE(service()->sync_initialized());
330 #endif // !defined(OS_CHROMEOS)
332 TEST_F(ProfileSyncServiceTest
, GetSyncTokenStatus
) {
333 CreateService(ProfileSyncService::AUTO_START
);
335 ExpectDataTypeManagerCreation();
336 ExpectSyncBackendHostCreation();
340 ProfileSyncService::SyncTokenStatus token_status
=
341 service()->GetSyncTokenStatus();
342 EXPECT_EQ(syncer::CONNECTION_NOT_ATTEMPTED
, token_status
.connection_status
);
343 EXPECT_TRUE(token_status
.connection_status_update_time
.is_null());
344 EXPECT_TRUE(token_status
.token_request_time
.is_null());
345 EXPECT_TRUE(token_status
.token_receive_time
.is_null());
347 // Simulate an auth error.
348 service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR
);
350 // The token request will take the form of a posted task. Run it.
354 token_status
= service()->GetSyncTokenStatus();
355 EXPECT_EQ(syncer::CONNECTION_AUTH_ERROR
, token_status
.connection_status
);
356 EXPECT_FALSE(token_status
.connection_status_update_time
.is_null());
357 EXPECT_FALSE(token_status
.token_request_time
.is_null());
358 EXPECT_FALSE(token_status
.token_receive_time
.is_null());
359 EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
360 token_status
.last_get_token_error
);
361 EXPECT_TRUE(token_status
.next_token_request_time
.is_null());
363 // Simulate successful connection.
364 service()->OnConnectionStatusChange(syncer::CONNECTION_OK
);
365 token_status
= service()->GetSyncTokenStatus();
366 EXPECT_EQ(syncer::CONNECTION_OK
, token_status
.connection_status
);
370 } // namespace browser_sync