Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / sync / profile_sync_service_unittest.cc
blobe18bbfd3e0d8fdebcd89bb29dfb7d522315e8599
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/file_util.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop.h"
10 #include "base/values.h"
11 #include "chrome/browser/signin/signin_manager.h"
12 #include "chrome/browser/signin/signin_manager_factory.h"
13 #include "chrome/browser/signin/token_service.h"
14 #include "chrome/browser/signin/token_service_factory.h"
15 #include "chrome/browser/sync/glue/bookmark_data_type_controller.h"
16 #include "chrome/browser/sync/glue/data_type_controller.h"
17 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
18 #include "chrome/browser/sync/test_profile_sync_service.h"
19 #include "chrome/common/chrome_version_info.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/testing_pref_service.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "content/public/common/content_client.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "google/cacheinvalidation/include/types.h"
26 #include "google_apis/gaia/gaia_constants.h"
27 #include "sync/js/js_arg_list.h"
28 #include "sync/js/js_event_details.h"
29 #include "sync/js/js_test_util.h"
30 #include "sync/notifier/fake_invalidation_handler.h"
31 #include "sync/notifier/invalidator.h"
32 #include "sync/notifier/invalidator_test_template.h"
33 #include "sync/notifier/object_id_invalidation_map_test_util.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 #include "webkit/user_agent/user_agent.h"
38 // TODO(akalin): Add tests here that exercise the whole
39 // ProfileSyncService/SyncBackendHost stack while mocking out as
40 // little as possible.
42 namespace browser_sync {
44 namespace {
46 using content::BrowserThread;
47 using testing::_;
48 using testing::AtLeast;
49 using testing::AtMost;
50 using testing::Mock;
51 using testing::Return;
52 using testing::StrictMock;
54 class ProfileSyncServiceTestHarness {
55 public:
56 ProfileSyncServiceTestHarness()
57 : ui_thread_(BrowserThread::UI, &ui_loop_),
58 db_thread_(BrowserThread::DB),
59 file_thread_(BrowserThread::FILE),
60 io_thread_(BrowserThread::IO) {}
62 ~ProfileSyncServiceTestHarness() {}
64 void SetUp() {
65 file_thread_.Start();
66 io_thread_.StartIOThread();
67 profile.reset(new TestingProfile());
68 profile->CreateRequestContext();
70 // We need to set the user agent before the backend host can call
71 // webkit_glue::GetUserAgent().
72 webkit_glue::SetUserAgent(content::GetContentClient()->GetUserAgent(),
73 false);
76 void TearDown() {
77 // Kill the service before the profile.
78 if (service.get()) {
79 service->Shutdown();
81 service.reset();
82 profile.reset();
83 // Pump messages posted by the sync thread (which may end up
84 // posting on the IO thread).
85 ui_loop_.RunAllPending();
86 io_thread_.Stop();
87 file_thread_.Stop();
88 // Ensure that the sync objects destruct to avoid memory leaks.
89 ui_loop_.RunAllPending();
92 // TODO(akalin): Refactor the StartSyncService*() functions below.
94 void StartSyncService() {
95 StartSyncServiceAndSetInitialSyncEnded(
96 true, true, false, true, syncer::STORAGE_IN_MEMORY);
99 void StartSyncServiceAndSetInitialSyncEnded(
100 bool set_initial_sync_ended,
101 bool issue_auth_token,
102 bool synchronous_sync_configuration,
103 bool sync_setup_completed,
104 syncer::StorageOption storage_option) {
105 if (!service.get()) {
106 SigninManager* signin =
107 SigninManagerFactory::GetForProfile(profile.get());
108 signin->SetAuthenticatedUsername("test");
109 ProfileSyncComponentsFactoryMock* factory =
110 new ProfileSyncComponentsFactoryMock();
111 service.reset(new TestProfileSyncService(
112 factory,
113 profile.get(),
114 signin,
115 ProfileSyncService::AUTO_START,
116 true,
117 base::Closure()));
118 if (!set_initial_sync_ended)
119 service->dont_set_initial_sync_ended_on_init();
120 if (synchronous_sync_configuration)
121 service->set_synchronous_sync_configuration();
122 service->set_storage_option(storage_option);
123 if (!sync_setup_completed)
124 profile->GetPrefs()->SetBoolean(prefs::kSyncHasSetupCompleted, false);
126 // Register the bookmark data type.
127 ON_CALL(*factory, CreateDataTypeManager(_, _, _, _)).
128 WillByDefault(ReturnNewDataTypeManager());
130 if (issue_auth_token) {
131 IssueTestTokens();
133 service->Initialize();
137 void IssueTestTokens() {
138 TokenService* token_service =
139 TokenServiceFactory::GetForProfile(profile.get());
140 token_service->IssueAuthTokenForTest(
141 GaiaConstants::kSyncService, "token1");
142 token_service->IssueAuthTokenForTest(
143 GaiaConstants::kGaiaOAuth2LoginRefreshToken, "token2");
146 scoped_ptr<TestProfileSyncService> service;
147 scoped_ptr<TestingProfile> profile;
149 private:
150 MessageLoop ui_loop_;
151 // Needed by |service|.
152 content::TestBrowserThread ui_thread_;
153 content::TestBrowserThread db_thread_;
154 // Needed by DisableAndEnableSyncTemporarily test case.
155 content::TestBrowserThread file_thread_;
156 // Needed by |service| and |profile|'s request context.
157 content::TestBrowserThread io_thread_;
160 class ProfileSyncServiceTest : public testing::Test {
161 protected:
162 virtual void SetUp() {
163 harness_.SetUp();
166 virtual void TearDown() {
167 harness_.TearDown();
170 ProfileSyncServiceTestHarness harness_;
173 TEST_F(ProfileSyncServiceTest, InitialState) {
174 SigninManager* signin =
175 SigninManagerFactory::GetForProfile(harness_.profile.get());
176 harness_.service.reset(new TestProfileSyncService(
177 new ProfileSyncComponentsFactoryMock(),
178 harness_.profile.get(),
179 signin,
180 ProfileSyncService::MANUAL_START,
181 true,
182 base::Closure()));
183 harness_.service->Initialize();
184 EXPECT_TRUE(
185 harness_.service->sync_service_url().spec() ==
186 ProfileSyncService::kSyncServerUrl ||
187 harness_.service->sync_service_url().spec() ==
188 ProfileSyncService::kDevServerUrl);
191 TEST_F(ProfileSyncServiceTest, DisabledByPolicy) {
192 harness_.profile->GetTestingPrefService()->SetManagedPref(
193 prefs::kSyncManaged,
194 Value::CreateBooleanValue(true));
195 SigninManager* signin =
196 SigninManagerFactory::GetForProfile(harness_.profile.get());
197 harness_.service.reset(new TestProfileSyncService(
198 new ProfileSyncComponentsFactoryMock(),
199 harness_.profile.get(),
200 signin,
201 ProfileSyncService::MANUAL_START,
202 true,
203 base::Closure()));
204 harness_.service->Initialize();
205 EXPECT_TRUE(harness_.service->IsManaged());
208 TEST_F(ProfileSyncServiceTest, AbortedByShutdown) {
209 SigninManager* signin =
210 SigninManagerFactory::GetForProfile(harness_.profile.get());
211 signin->SetAuthenticatedUsername("test");
212 ProfileSyncComponentsFactoryMock* factory =
213 new ProfileSyncComponentsFactoryMock();
214 harness_.service.reset(new TestProfileSyncService(
215 factory,
216 harness_.profile.get(),
217 signin,
218 ProfileSyncService::AUTO_START,
219 true,
220 base::Closure()));
221 EXPECT_CALL(*factory, CreateDataTypeManager(_, _, _, _)).Times(0);
222 EXPECT_CALL(*factory, CreateBookmarkSyncComponents(_, _)).
223 Times(0);
224 harness_.service->RegisterDataTypeController(
225 new BookmarkDataTypeController(harness_.service->factory(),
226 harness_.profile.get(),
227 harness_.service.get()));
229 harness_.service->Initialize();
230 harness_.service.reset();
233 TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) {
234 SigninManager* signin =
235 SigninManagerFactory::GetForProfile(harness_.profile.get());
236 signin->SetAuthenticatedUsername("test");
237 ProfileSyncComponentsFactoryMock* factory =
238 new ProfileSyncComponentsFactoryMock();
239 harness_.service.reset(new TestProfileSyncService(
240 factory,
241 harness_.profile.get(),
242 signin,
243 ProfileSyncService::AUTO_START,
244 true,
245 base::Closure()));
246 // Register the bookmark data type.
247 EXPECT_CALL(*factory, CreateDataTypeManager(_, _, _, _)).
248 WillRepeatedly(ReturnNewDataTypeManager());
250 harness_.IssueTestTokens();
252 harness_.service->Initialize();
253 EXPECT_TRUE(harness_.service->sync_initialized());
254 EXPECT_TRUE(harness_.service->GetBackendForTest() != NULL);
255 EXPECT_FALSE(
256 harness_.profile->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
258 harness_.service->StopAndSuppress();
259 EXPECT_FALSE(harness_.service->sync_initialized());
260 EXPECT_TRUE(
261 harness_.profile->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
263 harness_.service->UnsuppressAndStart();
264 EXPECT_TRUE(harness_.service->sync_initialized());
265 EXPECT_FALSE(
266 harness_.profile->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart));
269 TEST_F(ProfileSyncServiceTest, JsControllerHandlersBasic) {
270 harness_.StartSyncService();
271 EXPECT_TRUE(harness_.service->sync_initialized());
272 EXPECT_TRUE(harness_.service->GetBackendForTest() != NULL);
274 syncer::JsController* js_controller = harness_.service->GetJsController();
275 StrictMock<syncer::MockJsEventHandler> event_handler;
276 js_controller->AddJsEventHandler(&event_handler);
277 js_controller->RemoveJsEventHandler(&event_handler);
280 TEST_F(ProfileSyncServiceTest,
281 JsControllerHandlersDelayedBackendInitialization) {
282 harness_.StartSyncServiceAndSetInitialSyncEnded(true, false, false, true,
283 syncer::STORAGE_IN_MEMORY);
285 StrictMock<syncer::MockJsEventHandler> event_handler;
286 EXPECT_CALL(event_handler, HandleJsEvent(_, _)).Times(AtLeast(1));
288 EXPECT_EQ(NULL, harness_.service->GetBackendForTest());
289 EXPECT_FALSE(harness_.service->sync_initialized());
291 syncer::JsController* js_controller = harness_.service->GetJsController();
292 js_controller->AddJsEventHandler(&event_handler);
293 // Since we're doing synchronous initialization, backend should be
294 // initialized by this call.
295 harness_.IssueTestTokens();
296 EXPECT_TRUE(harness_.service->sync_initialized());
297 js_controller->RemoveJsEventHandler(&event_handler);
300 TEST_F(ProfileSyncServiceTest, JsControllerProcessJsMessageBasic) {
301 harness_.StartSyncService();
303 StrictMock<syncer::MockJsReplyHandler> reply_handler;
305 ListValue arg_list1;
306 arg_list1.Append(Value::CreateStringValue("TRANSIENT_INVALIDATION_ERROR"));
307 syncer::JsArgList args1(&arg_list1);
308 EXPECT_CALL(reply_handler,
309 HandleJsReply("getNotificationState", HasArgs(args1)));
312 syncer::JsController* js_controller = harness_.service->GetJsController();
313 js_controller->ProcessJsMessage("getNotificationState", args1,
314 reply_handler.AsWeakHandle());
317 // This forces the sync thread to process the message and reply.
318 harness_.TearDown();
321 TEST_F(ProfileSyncServiceTest,
322 JsControllerProcessJsMessageBasicDelayedBackendInitialization) {
323 harness_.StartSyncServiceAndSetInitialSyncEnded(true, false, false, true,
324 syncer::STORAGE_IN_MEMORY);
326 StrictMock<syncer::MockJsReplyHandler> reply_handler;
328 ListValue arg_list1;
329 arg_list1.Append(Value::CreateStringValue("TRANSIENT_INVALIDATION_ERROR"));
330 syncer::JsArgList args1(&arg_list1);
331 EXPECT_CALL(reply_handler,
332 HandleJsReply("getNotificationState", HasArgs(args1)));
335 syncer::JsController* js_controller = harness_.service->GetJsController();
336 js_controller->ProcessJsMessage("getNotificationState",
337 args1, reply_handler.AsWeakHandle());
340 harness_.IssueTestTokens();
342 // This forces the sync thread to process the message and reply.
343 harness_.TearDown();
346 // Make sure that things still work if sync is not enabled, but some old sync
347 // databases are lingering in the "Sync Data" folder.
348 TEST_F(ProfileSyncServiceTest, TestStartupWithOldSyncData) {
349 const char* nonsense1 = "reginald";
350 const char* nonsense2 = "beartato";
351 const char* nonsense3 = "harrison";
352 FilePath temp_directory =
353 harness_.profile->GetPath().AppendASCII("Sync Data");
354 FilePath sync_file1 =
355 temp_directory.AppendASCII("BookmarkSyncSettings.sqlite3");
356 FilePath sync_file2 = temp_directory.AppendASCII("SyncData.sqlite3");
357 FilePath sync_file3 = temp_directory.AppendASCII("nonsense_file");
358 ASSERT_TRUE(file_util::CreateDirectory(temp_directory));
359 ASSERT_NE(-1,
360 file_util::WriteFile(sync_file1, nonsense1, strlen(nonsense1)));
361 ASSERT_NE(-1,
362 file_util::WriteFile(sync_file2, nonsense2, strlen(nonsense2)));
363 ASSERT_NE(-1,
364 file_util::WriteFile(sync_file3, nonsense3, strlen(nonsense3)));
366 harness_.StartSyncServiceAndSetInitialSyncEnded(false, false, true, false,
367 syncer::STORAGE_ON_DISK);
368 EXPECT_FALSE(harness_.service->HasSyncSetupCompleted());
369 EXPECT_FALSE(harness_.service->sync_initialized());
371 // Since we're doing synchronous initialization, backend should be
372 // initialized by this call.
373 harness_.IssueTestTokens();
375 // Stop the service so we can read the new Sync Data files that were
376 // created.
377 harness_.service->Shutdown();
378 harness_.service.reset();
380 // This file should have been deleted when the whole directory was nuked.
381 ASSERT_FALSE(file_util::PathExists(sync_file3));
382 ASSERT_FALSE(file_util::PathExists(sync_file1));
384 // This will still exist, but the text should have changed.
385 ASSERT_TRUE(file_util::PathExists(sync_file2));
386 std::string file2text;
387 ASSERT_TRUE(file_util::ReadFileToString(sync_file2, &file2text));
388 ASSERT_NE(file2text.compare(nonsense2), 0);
391 // Simulates a scenario where a database is corrupted and it is impossible to
392 // recreate it. This test is useful mainly when it is run under valgrind. Its
393 // expectations are not very interesting.
394 TEST_F(ProfileSyncServiceTest, FailToOpenDatabase) {
395 harness_.StartSyncServiceAndSetInitialSyncEnded(false, true, true, true,
396 syncer::STORAGE_INVALID);
398 // The backend is not ready. Ensure the PSS knows this.
399 EXPECT_FALSE(harness_.service->sync_initialized());
402 // Register a handler with the ProfileSyncService, and disable and
403 // reenable sync. The handler should get notified of the state
404 // changes.
405 // Flaky on all platforms. http://crbug.com/154491
406 TEST_F(ProfileSyncServiceTest, FLAKY_DisableInvalidationsOnStop) {
407 harness_.StartSyncServiceAndSetInitialSyncEnded(
408 true, true, true, true, syncer::STORAGE_IN_MEMORY);
410 syncer::FakeInvalidationHandler handler;
411 harness_.service->RegisterInvalidationHandler(&handler);
413 SyncBackendHostForProfileSyncTest* const backend =
414 harness_.service->GetBackendForTest();
416 backend->EmitOnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED);
417 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
419 harness_.service->StopAndSuppress();
420 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
421 handler.GetInvalidatorState());
423 harness_.service->UnsuppressAndStart();
424 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
426 harness_.service->UnregisterInvalidationHandler(&handler);
429 // Register for some IDs with the ProfileSyncService, restart sync,
430 // and trigger some invalidation messages. They should still be
431 // received by the handler.
432 TEST_F(ProfileSyncServiceTest, UpdateRegisteredInvalidationIdsPersistence) {
433 harness_.StartSyncService();
435 syncer::ObjectIdSet ids;
436 ids.insert(invalidation::ObjectId(3, "id3"));
437 const syncer::ObjectIdInvalidationMap& states =
438 syncer::ObjectIdSetToInvalidationMap(ids, "payload");
440 syncer::FakeInvalidationHandler handler;
442 harness_.service->RegisterInvalidationHandler(&handler);
443 harness_.service->UpdateRegisteredInvalidationIds(&handler, ids);
445 harness_.service->StopAndSuppress();
446 harness_.service->UnsuppressAndStart();
448 SyncBackendHostForProfileSyncTest* const backend =
449 harness_.service->GetBackendForTest();
451 backend->EmitOnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED);
452 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
454 backend->EmitOnIncomingInvalidation(states, syncer::REMOTE_INVALIDATION);
455 EXPECT_THAT(states, Eq(handler.GetLastInvalidationMap()));
456 EXPECT_EQ(syncer::REMOTE_INVALIDATION, handler.GetLastInvalidationSource());
458 backend->EmitOnInvalidatorStateChange(syncer::TRANSIENT_INVALIDATION_ERROR);
459 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
460 handler.GetInvalidatorState());
462 harness_.service->UnregisterInvalidationHandler(&handler);
465 // Thin Invalidator wrapper around ProfileSyncService.
466 class ProfileSyncServiceInvalidator : public syncer::Invalidator {
467 public:
468 explicit ProfileSyncServiceInvalidator(ProfileSyncService* service)
469 : service_(service) {}
471 virtual ~ProfileSyncServiceInvalidator() {}
473 // Invalidator implementation.
474 virtual void RegisterHandler(syncer::InvalidationHandler* handler) OVERRIDE {
475 service_->RegisterInvalidationHandler(handler);
478 virtual void UpdateRegisteredIds(syncer::InvalidationHandler* handler,
479 const syncer::ObjectIdSet& ids) OVERRIDE {
480 service_->UpdateRegisteredInvalidationIds(handler, ids);
483 virtual void UnregisterHandler(
484 syncer::InvalidationHandler* handler) OVERRIDE {
485 service_->UnregisterInvalidationHandler(handler);
488 virtual syncer::InvalidatorState GetInvalidatorState() const OVERRIDE {
489 return service_->GetInvalidatorState();
492 virtual void SetUniqueId(const std::string& unique_id) OVERRIDE {
493 // Do nothing.
496 virtual void SetStateDeprecated(const std::string& state) OVERRIDE {
497 // Do nothing.
500 virtual void UpdateCredentials(
501 const std::string& email, const std::string& token) OVERRIDE {
502 // Do nothing.
505 virtual void SendInvalidation(
506 const syncer::ObjectIdInvalidationMap& invalidation_map) OVERRIDE {
507 // Do nothing.
510 private:
511 ProfileSyncService* const service_;
513 DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceInvalidator);
516 } // namespace
519 // ProfileSyncServiceInvalidatorTestDelegate has to be visible from
520 // the syncer namespace (where InvalidatorTest lives).
521 class ProfileSyncServiceInvalidatorTestDelegate {
522 public:
523 ProfileSyncServiceInvalidatorTestDelegate() {}
525 ~ProfileSyncServiceInvalidatorTestDelegate() {
526 DestroyInvalidator();
529 void CreateInvalidator(
530 const std::string& initial_state,
531 const base::WeakPtr<syncer::InvalidationStateTracker>&
532 invalidation_state_tracker) {
533 DCHECK(!invalidator_.get());
534 harness_.SetUp();
535 harness_.StartSyncService();
536 invalidator_.reset(
537 new ProfileSyncServiceInvalidator(harness_.service.get()));
540 ProfileSyncServiceInvalidator* GetInvalidator() {
541 return invalidator_.get();
544 void DestroyInvalidator() {
545 invalidator_.reset();
546 harness_.TearDown();
549 void WaitForInvalidator() {
550 // Do nothing.
553 void TriggerOnInvalidatorStateChange(syncer::InvalidatorState state) {
554 harness_.service->GetBackendForTest()->EmitOnInvalidatorStateChange(state);
557 void TriggerOnIncomingInvalidation(
558 const syncer::ObjectIdInvalidationMap& invalidation_map,
559 syncer::IncomingInvalidationSource source) {
560 harness_.service->GetBackendForTest()->EmitOnIncomingInvalidation(
561 invalidation_map, source);
564 static bool InvalidatorHandlesDeprecatedState() {
565 return false;
568 private:
569 ProfileSyncServiceTestHarness harness_;
570 scoped_ptr<ProfileSyncServiceInvalidator> invalidator_;
573 } // namespace browser_sync
575 namespace syncer {
576 namespace {
578 // ProfileSyncService should behave just like an invalidator.
579 INSTANTIATE_TYPED_TEST_CASE_P(
580 ProfileSyncServiceInvalidatorTest, InvalidatorTest,
581 ::browser_sync::ProfileSyncServiceInvalidatorTestDelegate);
583 } // namespace
584 } // namespace syncer