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/command_line.h"
7 #include "base/compiler_specific.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "chrome/browser/invalidation/fake_invalidation_service.h"
14 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
15 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
16 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
17 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
20 #include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
21 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/pref_names.h"
24 #include "chrome/test/base/testing_browser_process.h"
25 #include "chrome/test/base/testing_pref_service_syncable.h"
26 #include "chrome/test/base/testing_profile.h"
27 #include "chrome/test/base/testing_profile_manager.h"
28 #include "components/invalidation/invalidation_service.h"
29 #include "components/invalidation/profile_invalidation_provider.h"
30 #include "components/signin/core/browser/signin_manager.h"
31 #include "components/sync_driver/data_type_manager_impl.h"
32 #include "components/sync_driver/pref_names.h"
33 #include "components/sync_driver/sync_prefs.h"
34 #include "content/public/test/test_browser_thread_bundle.h"
35 #include "google_apis/gaia/gaia_constants.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
43 namespace browser_sync {
47 ACTION(ReturnNewDataTypeManager) {
48 return new browser_sync::DataTypeManagerImpl(base::Closure(),
57 using testing::Return;
58 using testing::StrictMock;
61 class TestProfileSyncServiceObserver : public ProfileSyncServiceObserver {
63 explicit TestProfileSyncServiceObserver(ProfileSyncService* service)
64 : service_(service), first_setup_in_progress_(false) {}
65 virtual void OnStateChanged() OVERRIDE {
66 first_setup_in_progress_ = service_->FirstSetupInProgress();
68 bool first_setup_in_progress() const { return first_setup_in_progress_; }
70 ProfileSyncService* service_;
71 bool first_setup_in_progress_;
74 // A variant of the SyncBackendHostMock that won't automatically
75 // call back when asked to initialized. Allows us to test things
76 // that could happen while backend init is in progress.
77 class SyncBackendHostNoReturn : public SyncBackendHostMock {
78 virtual void Initialize(
79 SyncFrontend* frontend,
80 scoped_ptr<base::Thread> sync_thread,
81 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
82 const GURL& service_url,
83 const syncer::SyncCredentials& credentials,
84 bool delete_sync_data_folder,
85 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
86 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
87 syncer::ReportUnrecoverableErrorFunction
88 report_unrecoverable_error_function,
89 syncer::NetworkResources* network_resources) OVERRIDE {}
92 class SyncBackendHostMockCollectDeleteDirParam : public SyncBackendHostMock {
94 explicit SyncBackendHostMockCollectDeleteDirParam(
95 std::vector<bool>* delete_dir_param)
96 : delete_dir_param_(delete_dir_param) {}
98 virtual void Initialize(
99 SyncFrontend* frontend,
100 scoped_ptr<base::Thread> sync_thread,
101 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
102 const GURL& service_url,
103 const syncer::SyncCredentials& credentials,
104 bool delete_sync_data_folder,
105 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
106 scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
107 syncer::ReportUnrecoverableErrorFunction
108 report_unrecoverable_error_function,
109 syncer::NetworkResources* network_resources) OVERRIDE {
110 delete_dir_param_->push_back(delete_sync_data_folder);
111 SyncBackendHostMock::Initialize(frontend, sync_thread.Pass(),
112 event_handler, service_url, credentials,
113 delete_sync_data_folder,
114 sync_manager_factory.Pass(),
115 unrecoverable_error_handler.Pass(),
116 report_unrecoverable_error_function,
121 std::vector<bool>* delete_dir_param_;
124 ACTION(ReturnNewSyncBackendHostMock) {
125 return new browser_sync::SyncBackendHostMock();
128 ACTION(ReturnNewSyncBackendHostNoReturn) {
129 return new browser_sync::SyncBackendHostNoReturn();
132 ACTION_P(ReturnNewMockHostCollectDeleteDirParam, delete_dir_param) {
133 return new browser_sync::SyncBackendHostMockCollectDeleteDirParam(
137 KeyedService* BuildFakeProfileInvalidationProvider(
138 content::BrowserContext* context) {
139 return new invalidation::ProfileInvalidationProvider(
140 scoped_ptr<invalidation::InvalidationService>(
141 new invalidation::FakeInvalidationService));
144 // A test harness that uses a real ProfileSyncService and in most cases a
145 // MockSyncBackendHost.
147 // This is useful if we want to test the ProfileSyncService and don't care about
148 // testing the SyncBackendHost.
149 class ProfileSyncServiceTest : public ::testing::Test {
151 ProfileSyncServiceTest()
152 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
153 profile_manager_(TestingBrowserProcess::GetGlobal()) {}
154 virtual ~ProfileSyncServiceTest() {}
156 virtual void SetUp() OVERRIDE {
157 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
158 switches::kSyncDeferredStartupTimeoutSeconds, "0");
160 CHECK(profile_manager_.SetUp());
162 TestingProfile::TestingFactories testing_facotries;
163 testing_facotries.push_back(
164 std::make_pair(ProfileOAuth2TokenServiceFactory::GetInstance(),
165 BuildAutoIssuingFakeProfileOAuth2TokenService));
166 testing_facotries.push_back(
168 invalidation::ProfileInvalidationProviderFactory::GetInstance(),
169 BuildFakeProfileInvalidationProvider));
171 profile_ = profile_manager_.CreateTestingProfile(
172 "sync-service-test", scoped_ptr<PrefServiceSyncable>(),
173 base::UTF8ToUTF16("sync-service-test"), 0, std::string(),
177 virtual void TearDown() OVERRIDE {
178 // Kill the service before the profile.
180 service_->Shutdown();
185 void IssueTestTokens() {
186 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
187 ->UpdateCredentials("test", "oauth2_login_token");
190 void CreateService(ProfileSyncServiceStartBehavior behavior) {
191 SigninManagerBase* signin =
192 SigninManagerFactory::GetForProfile(profile_);
193 signin->SetAuthenticatedUsername("test");
194 ProfileOAuth2TokenService* oauth2_token_service =
195 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
196 components_factory_ = new StrictMock<ProfileSyncComponentsFactoryMock>();
197 service_.reset(new ProfileSyncService(
200 make_scoped_ptr(new ManagedUserSigninManagerWrapper(profile_, signin)),
201 oauth2_token_service,
203 service_->SetClearingBrowseringDataForTesting(
204 base::Bind(&ProfileSyncServiceTest::ClearBrowsingDataCallback,
205 base::Unretained(this)));
208 #if defined(OS_WIN) || defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
209 void CreateServiceWithoutSignIn() {
210 CreateService(browser_sync::MANUAL_START);
211 SigninManagerFactory::GetForProfile(profile())->SignOut(
212 signin_metrics::SIGNOUT_TEST);
213 service()->SetBackupStartDelayForTest(
214 base::TimeDelta::FromMilliseconds(100));
218 void ShutdownAndDeleteService() {
220 service_->Shutdown();
225 service_->Initialize();
228 void ExpectDataTypeManagerCreation(int times) {
229 EXPECT_CALL(*components_factory_, CreateDataTypeManager(_, _, _, _, _, _))
231 .WillRepeatedly(ReturnNewDataTypeManager());
234 void ExpectSyncBackendHostCreation(int times) {
235 EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _, _, _))
237 .WillRepeatedly(ReturnNewSyncBackendHostMock());
240 void ExpectSyncBackendHostCreationCollectDeleteDir(
241 int times, std::vector<bool> *delete_dir_param) {
242 EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _, _, _))
244 .WillRepeatedly(ReturnNewMockHostCollectDeleteDirParam(
248 void PrepareDelayedInitSyncBackendHost() {
249 EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _, _, _)).
250 WillOnce(ReturnNewSyncBackendHostNoReturn());
253 TestingProfile* profile() {
257 ProfileSyncService* service() {
258 return service_.get();
261 ProfileSyncComponentsFactoryMock* components_factory() {
262 return components_factory_;
265 void ClearBrowsingDataCallback(Profile* profile, base::Time start,
267 EXPECT_EQ(profile_, profile);
268 clear_browsing_data_start_ = start;
272 // The requested start time when ClearBrowsingDataCallback is called.
273 base::Time clear_browsing_data_start_;
276 content::TestBrowserThreadBundle thread_bundle_;
277 TestingProfileManager profile_manager_;
278 TestingProfile* profile_;
279 scoped_ptr<ProfileSyncService> service_;
281 // Pointer to the components factory. Not owned. May be null.
282 ProfileSyncComponentsFactoryMock* components_factory_;
285 // Verify that the server URLs are sane.
286 TEST_F(ProfileSyncServiceTest, InitialState) {
287 CreateService(browser_sync::AUTO_START);
289 const std::string& url = service()->sync_service_url().spec();
290 EXPECT_TRUE(url == ProfileSyncService::kSyncServerUrl ||
291 url == ProfileSyncService::kDevServerUrl);
294 // Verify a successful initialization.
295 TEST_F(ProfileSyncServiceTest, SuccessfulInitialization) {
296 profile()->GetTestingPrefService()->SetManagedPref(
297 sync_driver::prefs::kSyncManaged, base::Value::CreateBooleanValue(false));
299 CreateService(browser_sync::AUTO_START);
300 ExpectDataTypeManagerCreation(1);
301 ExpectSyncBackendHostCreation(1);
303 EXPECT_FALSE(service()->IsManaged());
304 EXPECT_TRUE(service()->sync_initialized());
305 EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
309 // Verify that the SetSetupInProgress function call updates state
310 // and notifies observers.
311 TEST_F(ProfileSyncServiceTest, SetupInProgress) {
312 CreateService(browser_sync::AUTO_START);
315 TestProfileSyncServiceObserver observer(service());
316 service()->AddObserver(&observer);
318 service()->SetSetupInProgress(true);
319 EXPECT_TRUE(observer.first_setup_in_progress());
320 service()->SetSetupInProgress(false);
321 EXPECT_FALSE(observer.first_setup_in_progress());
323 service()->RemoveObserver(&observer);
326 // Verify that disable by enterprise policy works.
327 TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInit) {
328 profile()->GetTestingPrefService()->SetManagedPref(
329 sync_driver::prefs::kSyncManaged, base::Value::CreateBooleanValue(true));
331 CreateService(browser_sync::AUTO_START);
333 EXPECT_TRUE(service()->IsManaged());
334 EXPECT_FALSE(service()->sync_initialized());
337 // Verify that disable by enterprise policy works even after the backend has
339 TEST_F(ProfileSyncServiceTest, DisabledByPolicyAfterInit) {
341 CreateService(browser_sync::AUTO_START);
342 ExpectDataTypeManagerCreation(1);
343 ExpectSyncBackendHostCreation(1);
346 EXPECT_FALSE(service()->IsManaged());
347 EXPECT_TRUE(service()->sync_initialized());
349 profile()->GetTestingPrefService()->SetManagedPref(
350 sync_driver::prefs::kSyncManaged, base::Value::CreateBooleanValue(true));
352 EXPECT_TRUE(service()->IsManaged());
353 EXPECT_FALSE(service()->sync_initialized());
356 // Exercies the ProfileSyncService's code paths related to getting shut down
357 // before the backend initialize call returns.
358 TEST_F(ProfileSyncServiceTest, AbortedByShutdown) {
359 CreateService(browser_sync::AUTO_START);
360 PrepareDelayedInitSyncBackendHost();
364 EXPECT_FALSE(service()->sync_initialized());
366 ShutdownAndDeleteService();
369 // Test StopAndSuppress() before we've initialized the backend.
370 TEST_F(ProfileSyncServiceTest, EarlyStopAndSuppress) {
371 CreateService(browser_sync::AUTO_START);
374 service()->StopAndSuppress();
375 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
376 sync_driver::prefs::kSyncSuppressStart));
378 // Because of supression, this should fail.
380 EXPECT_FALSE(service()->sync_initialized());
382 // Remove suppression. This should be enough to allow init to happen.
383 ExpectDataTypeManagerCreation(1);
384 ExpectSyncBackendHostCreation(1);
385 service()->UnsuppressAndStart();
386 EXPECT_TRUE(service()->sync_initialized());
387 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
388 sync_driver::prefs::kSyncSuppressStart));
391 // Test StopAndSuppress() after we've initialized the backend.
392 TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) {
393 CreateService(browser_sync::AUTO_START);
395 ExpectDataTypeManagerCreation(1);
396 ExpectSyncBackendHostCreation(1);
399 EXPECT_TRUE(service()->sync_initialized());
400 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
401 sync_driver::prefs::kSyncSuppressStart));
403 testing::Mock::VerifyAndClearExpectations(components_factory());
405 service()->StopAndSuppress();
406 EXPECT_FALSE(service()->sync_initialized());
407 EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
408 sync_driver::prefs::kSyncSuppressStart));
410 ExpectDataTypeManagerCreation(1);
411 ExpectSyncBackendHostCreation(1);
413 service()->UnsuppressAndStart();
414 EXPECT_TRUE(service()->sync_initialized());
415 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
416 sync_driver::prefs::kSyncSuppressStart));
419 // Certain ProfileSyncService tests don't apply to Chrome OS, for example
420 // things that deal with concepts like "signing out" and policy.
421 #if defined(OS_WIN) || defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
422 TEST_F(ProfileSyncServiceTest, EnableSyncAndSignOutDesktop) {
423 CreateService(browser_sync::AUTO_START);
424 ExpectDataTypeManagerCreation(2);
425 ExpectSyncBackendHostCreation(2);
429 EXPECT_TRUE(service()->sync_initialized());
430 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
431 sync_driver::prefs::kSyncSuppressStart));
432 EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
434 SigninManagerFactory::GetForProfile(profile())->SignOut(
435 signin_metrics::SIGNOUT_TEST);
436 EXPECT_TRUE(service()->sync_initialized());
437 EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
439 #elif !defined (OS_CHROMEOS)
440 TEST_F(ProfileSyncServiceTest, EnableSyncAndSignOut) {
441 CreateService(browser_sync::AUTO_START);
442 ExpectDataTypeManagerCreation(1);
443 ExpectSyncBackendHostCreation(1);
447 EXPECT_TRUE(service()->sync_initialized());
448 EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
449 sync_driver::prefs::kSyncSuppressStart));
451 SigninManagerFactory::GetForProfile(profile())->SignOut(
452 signin_metrics::SIGNOUT_TEST);
453 EXPECT_FALSE(service()->sync_initialized());
455 #endif // !defined(OS_CHROMEOS)
457 TEST_F(ProfileSyncServiceTest, GetSyncTokenStatus) {
458 CreateService(browser_sync::AUTO_START);
460 ExpectDataTypeManagerCreation(1);
461 ExpectSyncBackendHostCreation(1);
465 ProfileSyncService::SyncTokenStatus token_status =
466 service()->GetSyncTokenStatus();
467 EXPECT_EQ(syncer::CONNECTION_NOT_ATTEMPTED, token_status.connection_status);
468 EXPECT_TRUE(token_status.connection_status_update_time.is_null());
469 EXPECT_TRUE(token_status.token_request_time.is_null());
470 EXPECT_TRUE(token_status.token_receive_time.is_null());
472 // Simulate an auth error.
473 service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
475 // The token request will take the form of a posted task. Run it.
479 token_status = service()->GetSyncTokenStatus();
480 EXPECT_EQ(syncer::CONNECTION_AUTH_ERROR, token_status.connection_status);
481 EXPECT_FALSE(token_status.connection_status_update_time.is_null());
482 EXPECT_FALSE(token_status.token_request_time.is_null());
483 EXPECT_FALSE(token_status.token_receive_time.is_null());
484 EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
485 token_status.last_get_token_error);
486 EXPECT_TRUE(token_status.next_token_request_time.is_null());
488 // Simulate successful connection.
489 service()->OnConnectionStatusChange(syncer::CONNECTION_OK);
490 token_status = service()->GetSyncTokenStatus();
491 EXPECT_EQ(syncer::CONNECTION_OK, token_status.connection_status);
494 #if defined(ENABLE_PRE_SYNC_BACKUP)
495 TEST_F(ProfileSyncServiceTest, StartBackup) {
496 CreateServiceWithoutSignIn();
497 ExpectDataTypeManagerCreation(1);
498 std::vector<bool> delete_dir_param;
499 ExpectSyncBackendHostCreationCollectDeleteDir(1, &delete_dir_param);
501 EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
502 base::RunLoop run_loop;
503 base::MessageLoop::current()->PostDelayedTask(
504 FROM_HERE, run_loop.QuitClosure(),
505 base::TimeDelta::FromMilliseconds(100));
507 EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
509 EXPECT_EQ(1u, delete_dir_param.size());
510 EXPECT_FALSE(delete_dir_param[0]);
513 TEST_F(ProfileSyncServiceTest, BackupAfterSyncDisabled) {
514 CreateService(browser_sync::MANUAL_START);
515 service()->SetSyncSetupCompleted();
516 ExpectDataTypeManagerCreation(2);
517 std::vector<bool> delete_dir_param;
518 ExpectSyncBackendHostCreationCollectDeleteDir(2, &delete_dir_param);
521 EXPECT_TRUE(service()->sync_initialized());
522 EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
524 // First sync time should be recorded.
525 sync_driver::SyncPrefs sync_prefs(service()->profile()->GetPrefs());
526 EXPECT_FALSE(sync_prefs.GetFirstSyncTime().is_null());
528 syncer::SyncProtocolError client_cmd;
529 client_cmd.action = syncer::DISABLE_SYNC_ON_CLIENT;
530 service()->OnActionableError(client_cmd);
531 EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
533 // Browsing data is not cleared because rollback is skipped.
534 EXPECT_TRUE(clear_browsing_data_start_.is_null());
536 // First sync time is erased once backup starts.
537 EXPECT_TRUE(sync_prefs.GetFirstSyncTime().is_null());
539 EXPECT_EQ(2u, delete_dir_param.size());
540 EXPECT_FALSE(delete_dir_param[0]);
541 EXPECT_TRUE(delete_dir_param[1]);
544 TEST_F(ProfileSyncServiceTest, RollbackThenBackup) {
545 CommandLine::ForCurrentProcess()->AppendSwitch(
546 switches::kSyncEnableRollback);
548 CreateService(browser_sync::MANUAL_START);
549 service()->SetSyncSetupCompleted();
550 ExpectDataTypeManagerCreation(3);
551 std::vector<bool> delete_dir_param;
552 ExpectSyncBackendHostCreationCollectDeleteDir(3, &delete_dir_param);
555 EXPECT_TRUE(service()->sync_initialized());
556 EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
558 // First sync time should be recorded.
559 sync_driver::SyncPrefs sync_prefs(service()->profile()->GetPrefs());
560 base::Time first_sync_time = sync_prefs.GetFirstSyncTime();
561 EXPECT_FALSE(first_sync_time.is_null());
563 syncer::SyncProtocolError client_cmd;
564 client_cmd.action = syncer::DISABLE_SYNC_AND_ROLLBACK;
565 service()->OnActionableError(client_cmd);
566 EXPECT_TRUE(service()->sync_initialized());
567 EXPECT_EQ(ProfileSyncService::ROLLBACK, service()->backend_mode());
569 // Browser data should be cleared during rollback.
570 EXPECT_EQ(first_sync_time, clear_browsing_data_start_);
572 client_cmd.action = syncer::ROLLBACK_DONE;
573 service()->OnActionableError(client_cmd);
574 EXPECT_TRUE(service()->sync_initialized());
575 EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
577 // First sync time is erased once backup starts.
578 EXPECT_TRUE(sync_prefs.GetFirstSyncTime().is_null());
580 EXPECT_EQ(3u, delete_dir_param.size());
581 EXPECT_FALSE(delete_dir_param[0]);
582 EXPECT_FALSE(delete_dir_param[1]);
583 EXPECT_TRUE(delete_dir_param[2]);
586 TEST_F(ProfileSyncServiceTest, StartNewBackupDbOnSettingsReset) {
587 CreateServiceWithoutSignIn();
588 ExpectDataTypeManagerCreation(1);
589 std::vector<bool> delete_dir_param;
590 ExpectSyncBackendHostCreationCollectDeleteDir(1, &delete_dir_param);
592 EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
594 // Set reset time to pretend settings reset happened.
595 profile()->GetPrefs()->SetString(
596 prefs::kPreferenceResetTime,
597 base::Int64ToString(base::Time::Now().ToInternalValue()));
599 base::RunLoop run_loop;
600 base::MessageLoop::current()->PostDelayedTask(
601 FROM_HERE, run_loop.QuitClosure(),
602 base::TimeDelta::FromMilliseconds(100));
605 EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
607 EXPECT_EQ(1u, delete_dir_param.size());
608 EXPECT_TRUE(delete_dir_param[0]);
613 TEST_F(ProfileSyncServiceTest, GetSyncServiceURL) {
614 // See that we can override the URL with a flag.
615 CommandLine command_line(
616 base::FilePath(base::FilePath(FILE_PATH_LITERAL("chrome.exe"))));
617 command_line.AppendSwitchASCII(switches::kSyncServiceURL, "https://foo/bar");
618 EXPECT_EQ("https://foo/bar",
619 ProfileSyncService::GetSyncServiceURL(command_line).spec());
623 } // namespace browser_sync