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/fake_invalidation_service.h"
11 #include "chrome/browser/invalidation/invalidation_service_factory.h"
12 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
13 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
14 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "chrome/browser/sync/glue/data_type_manager_impl.h"
17 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
18 #include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
19 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/testing_pref_service_syncable.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "components/signin/core/browser/signin_manager.h"
24 #include "components/sync_driver/pref_names.h"
25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "google_apis/gaia/gaia_constants.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
30 namespace browser_sync
{
34 ACTION(ReturnNewDataTypeManager
) {
35 return new browser_sync::DataTypeManagerImpl(arg0
,
43 using testing::StrictMock
;
46 class TestProfileSyncServiceObserver
: public ProfileSyncServiceObserver
{
48 explicit TestProfileSyncServiceObserver(ProfileSyncService
* service
)
49 : service_(service
), first_setup_in_progress_(false) {}
50 virtual void OnStateChanged() OVERRIDE
{
51 first_setup_in_progress_
= service_
->FirstSetupInProgress();
53 bool first_setup_in_progress() const { return first_setup_in_progress_
; }
55 ProfileSyncService
* service_
;
56 bool first_setup_in_progress_
;
59 // A variant of the SyncBackendHostMock that won't automatically
60 // call back when asked to initialized. Allows us to test things
61 // that could happen while backend init is in progress.
62 class SyncBackendHostNoReturn
: public SyncBackendHostMock
{
63 virtual void Initialize(
64 SyncFrontend
* frontend
,
65 scoped_ptr
<base::Thread
> sync_thread
,
66 const syncer::WeakHandle
<syncer::JsEventHandler
>& event_handler
,
67 const GURL
& service_url
,
68 const syncer::SyncCredentials
& credentials
,
69 bool delete_sync_data_folder
,
70 scoped_ptr
<syncer::SyncManagerFactory
> sync_manager_factory
,
71 scoped_ptr
<syncer::UnrecoverableErrorHandler
> unrecoverable_error_handler
,
72 syncer::ReportUnrecoverableErrorFunction
73 report_unrecoverable_error_function
,
74 syncer::NetworkResources
* network_resources
) OVERRIDE
{}
77 ACTION(ReturnNewSyncBackendHostMock
) {
78 return new browser_sync::SyncBackendHostMock();
81 ACTION(ReturnNewSyncBackendHostNoReturn
) {
82 return new browser_sync::SyncBackendHostNoReturn();
85 // A test harness that uses a real ProfileSyncService and in most cases a
86 // MockSyncBackendHost.
88 // This is useful if we want to test the ProfileSyncService and don't care about
89 // testing the SyncBackendHost.
90 class ProfileSyncServiceTest
: public ::testing::Test
{
92 ProfileSyncServiceTest()
93 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
) {}
94 virtual ~ProfileSyncServiceTest() {}
96 virtual void SetUp() OVERRIDE
{
97 TestingProfile::Builder builder
;
99 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
100 BuildAutoIssuingFakeProfileOAuth2TokenService
);
101 invalidation::InvalidationServiceFactory::GetInstance()->
102 RegisterTestingFactory(invalidation::FakeInvalidationService::Build
);
104 profile_
= builder
.Build().Pass();
107 virtual void TearDown() OVERRIDE
{
108 // Kill the service before the profile.
110 service_
->Shutdown();
116 void IssueTestTokens() {
117 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_
.get())
118 ->UpdateCredentials("test", "oauth2_login_token");
121 void CreateService(ProfileSyncServiceStartBehavior behavior
) {
122 SigninManagerBase
* signin
=
123 SigninManagerFactory::GetForProfile(profile_
.get());
124 signin
->SetAuthenticatedUsername("test");
125 ProfileOAuth2TokenService
* oauth2_token_service
=
126 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_
.get());
127 components_factory_
= new StrictMock
<ProfileSyncComponentsFactoryMock
>();
128 service_
.reset(new ProfileSyncService(
131 new ManagedUserSigninManagerWrapper(profile_
.get(), signin
),
132 oauth2_token_service
,
136 void ShutdownAndDeleteService() {
138 service_
->Shutdown();
143 service_
->Initialize();
146 void ExpectDataTypeManagerCreation() {
147 EXPECT_CALL(*components_factory_
, CreateDataTypeManager(_
, _
, _
, _
, _
, _
)).
148 WillOnce(ReturnNewDataTypeManager());
151 void ExpectSyncBackendHostCreation() {
152 EXPECT_CALL(*components_factory_
, CreateSyncBackendHost(_
, _
, _
)).
153 WillOnce(ReturnNewSyncBackendHostMock());
156 void PrepareDelayedInitSyncBackendHost() {
157 EXPECT_CALL(*components_factory_
, CreateSyncBackendHost(_
, _
, _
)).
158 WillOnce(ReturnNewSyncBackendHostNoReturn());
161 TestingProfile
* profile() {
162 return profile_
.get();
165 ProfileSyncService
* service() {
166 return service_
.get();
169 ProfileSyncComponentsFactoryMock
* components_factory() {
170 return components_factory_
;
174 scoped_ptr
<TestingProfile
> profile_
;
175 scoped_ptr
<ProfileSyncService
> service_
;
177 // Pointer to the components factory. Not owned. May be null.
178 ProfileSyncComponentsFactoryMock
* components_factory_
;
180 content::TestBrowserThreadBundle thread_bundle_
;
183 // Verify that the server URLs are sane.
184 TEST_F(ProfileSyncServiceTest
, InitialState
) {
185 CreateService(browser_sync::AUTO_START
);
187 const std::string
& url
= service()->sync_service_url().spec();
188 EXPECT_TRUE(url
== ProfileSyncService::kSyncServerUrl
||
189 url
== ProfileSyncService::kDevServerUrl
);
192 // Verify a successful initialization.
193 TEST_F(ProfileSyncServiceTest
, SuccessfulInitialization
) {
194 profile()->GetTestingPrefService()->SetManagedPref(
195 sync_driver::prefs::kSyncManaged
, base::Value::CreateBooleanValue(false));
197 CreateService(browser_sync::AUTO_START
);
198 ExpectDataTypeManagerCreation();
199 ExpectSyncBackendHostCreation();
201 EXPECT_FALSE(service()->IsManaged());
202 EXPECT_TRUE(service()->sync_initialized());
206 // Verify that the SetSetupInProgress function call updates state
207 // and notifies observers.
208 TEST_F(ProfileSyncServiceTest
, SetupInProgress
) {
209 CreateService(browser_sync::AUTO_START
);
212 TestProfileSyncServiceObserver
observer(service());
213 service()->AddObserver(&observer
);
215 service()->SetSetupInProgress(true);
216 EXPECT_TRUE(observer
.first_setup_in_progress());
217 service()->SetSetupInProgress(false);
218 EXPECT_FALSE(observer
.first_setup_in_progress());
220 service()->RemoveObserver(&observer
);
223 // Verify that disable by enterprise policy works.
224 TEST_F(ProfileSyncServiceTest
, DisabledByPolicyBeforeInit
) {
225 profile()->GetTestingPrefService()->SetManagedPref(
226 sync_driver::prefs::kSyncManaged
, base::Value::CreateBooleanValue(true));
228 CreateService(browser_sync::AUTO_START
);
230 EXPECT_TRUE(service()->IsManaged());
231 EXPECT_FALSE(service()->sync_initialized());
234 // Verify that disable by enterprise policy works even after the backend has
236 TEST_F(ProfileSyncServiceTest
, DisabledByPolicyAfterInit
) {
238 CreateService(browser_sync::AUTO_START
);
239 ExpectDataTypeManagerCreation();
240 ExpectSyncBackendHostCreation();
243 EXPECT_FALSE(service()->IsManaged());
244 EXPECT_TRUE(service()->sync_initialized());
246 profile()->GetTestingPrefService()->SetManagedPref(
247 sync_driver::prefs::kSyncManaged
, base::Value::CreateBooleanValue(true));
249 EXPECT_TRUE(service()->IsManaged());
250 EXPECT_FALSE(service()->sync_initialized());
253 // Exercies the ProfileSyncService's code paths related to getting shut down
254 // before the backend initialize call returns.
255 TEST_F(ProfileSyncServiceTest
, AbortedByShutdown
) {
256 CreateService(browser_sync::AUTO_START
);
257 PrepareDelayedInitSyncBackendHost();
261 EXPECT_FALSE(service()->sync_initialized());
263 ShutdownAndDeleteService();
266 // Test StopAndSuppress() before we've initialized the backend.
267 TEST_F(ProfileSyncServiceTest
, EarlyStopAndSuppress
) {
268 CreateService(browser_sync::AUTO_START
);
271 service()->StopAndSuppress();
272 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
273 sync_driver::prefs::kSyncSuppressStart
));
275 // Because of supression, this should fail.
277 EXPECT_FALSE(service()->sync_initialized());
279 // Remove suppression. This should be enough to allow init to happen.
280 ExpectDataTypeManagerCreation();
281 ExpectSyncBackendHostCreation();
282 service()->UnsuppressAndStart();
283 EXPECT_TRUE(service()->sync_initialized());
284 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
285 sync_driver::prefs::kSyncSuppressStart
));
288 // Test StopAndSuppress() after we've initialized the backend.
289 TEST_F(ProfileSyncServiceTest
, DisableAndEnableSyncTemporarily
) {
290 CreateService(browser_sync::AUTO_START
);
292 ExpectDataTypeManagerCreation();
293 ExpectSyncBackendHostCreation();
296 EXPECT_TRUE(service()->sync_initialized());
297 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
298 sync_driver::prefs::kSyncSuppressStart
));
300 testing::Mock::VerifyAndClearExpectations(components_factory());
302 service()->StopAndSuppress();
303 EXPECT_FALSE(service()->sync_initialized());
304 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
305 sync_driver::prefs::kSyncSuppressStart
));
307 ExpectDataTypeManagerCreation();
308 ExpectSyncBackendHostCreation();
310 service()->UnsuppressAndStart();
311 EXPECT_TRUE(service()->sync_initialized());
312 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
313 sync_driver::prefs::kSyncSuppressStart
));
316 // Certain ProfileSyncService tests don't apply to Chrome OS, for example
317 // things that deal with concepts like "signing out" and policy.
318 #if !defined (OS_CHROMEOS)
320 TEST_F(ProfileSyncServiceTest
, EnableSyncAndSignOut
) {
321 CreateService(browser_sync::AUTO_START
);
322 ExpectDataTypeManagerCreation();
323 ExpectSyncBackendHostCreation();
327 EXPECT_TRUE(service()->sync_initialized());
328 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
329 sync_driver::prefs::kSyncSuppressStart
));
331 SigninManagerFactory::GetForProfile(profile())->SignOut();
332 EXPECT_FALSE(service()->sync_initialized());
335 #endif // !defined(OS_CHROMEOS)
337 TEST_F(ProfileSyncServiceTest
, GetSyncTokenStatus
) {
338 CreateService(browser_sync::AUTO_START
);
340 ExpectDataTypeManagerCreation();
341 ExpectSyncBackendHostCreation();
345 ProfileSyncService::SyncTokenStatus token_status
=
346 service()->GetSyncTokenStatus();
347 EXPECT_EQ(syncer::CONNECTION_NOT_ATTEMPTED
, token_status
.connection_status
);
348 EXPECT_TRUE(token_status
.connection_status_update_time
.is_null());
349 EXPECT_TRUE(token_status
.token_request_time
.is_null());
350 EXPECT_TRUE(token_status
.token_receive_time
.is_null());
352 // Simulate an auth error.
353 service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR
);
355 // The token request will take the form of a posted task. Run it.
359 token_status
= service()->GetSyncTokenStatus();
360 EXPECT_EQ(syncer::CONNECTION_AUTH_ERROR
, token_status
.connection_status
);
361 EXPECT_FALSE(token_status
.connection_status_update_time
.is_null());
362 EXPECT_FALSE(token_status
.token_request_time
.is_null());
363 EXPECT_FALSE(token_status
.token_receive_time
.is_null());
364 EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
365 token_status
.last_get_token_error
);
366 EXPECT_TRUE(token_status
.next_token_request_time
.is_null());
368 // Simulate successful connection.
369 service()->OnConnectionStatusChange(syncer::CONNECTION_OK
);
370 token_status
= service()->GetSyncTokenStatus();
371 EXPECT_EQ(syncer::CONNECTION_OK
, token_status
.connection_status
);
375 } // namespace browser_sync