| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/sync/driver/glue/sync_backend_registrar.h" | 5 #include "components/sync/driver/glue/sync_backend_registrar.h" |
| 6 | 6 |
| 7 #include <memory> |
| 8 |
| 7 #include "base/location.h" | 9 #include "base/location.h" |
| 8 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 9 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
| 10 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
| 11 #include "components/sync/driver/change_processor_mock.h" | 13 #include "components/sync/driver/change_processor_mock.h" |
| 12 #include "components/sync/driver/fake_sync_client.h" | 14 #include "components/sync/driver/fake_sync_client.h" |
| 13 #include "components/sync/driver/glue/browser_thread_model_worker.h" | 15 #include "components/sync/driver/glue/browser_thread_model_worker.h" |
| 14 #include "components/sync/driver/sync_api_component_factory_mock.h" | 16 #include "components/sync/driver/sync_api_component_factory_mock.h" |
| 15 #include "components/sync/engine/passive_model_worker.h" | 17 #include "components/sync/engine/passive_model_worker.h" |
| 16 #include "components/sync/syncable/test_user_share.h" | 18 #include "components/sync/syncable/test_user_share.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 35 public: | 37 public: |
| 36 RegistrarSyncClient( | 38 RegistrarSyncClient( |
| 37 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, | 39 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, |
| 38 const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner, | 40 const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner, |
| 39 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) | 41 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) |
| 40 : ui_task_runner_(ui_task_runner), | 42 : ui_task_runner_(ui_task_runner), |
| 41 db_task_runner_(db_task_runner), | 43 db_task_runner_(db_task_runner), |
| 42 file_task_runner_(file_task_runner) {} | 44 file_task_runner_(file_task_runner) {} |
| 43 | 45 |
| 44 scoped_refptr<ModelSafeWorker> CreateModelWorkerForGroup( | 46 scoped_refptr<ModelSafeWorker> CreateModelWorkerForGroup( |
| 45 ModelSafeGroup group, | 47 ModelSafeGroup group) override { |
| 46 WorkerLoopDestructionObserver* observer) override { | |
| 47 switch (group) { | 48 switch (group) { |
| 48 case GROUP_UI: | 49 case GROUP_UI: |
| 49 return new BrowserThreadModelWorker(ui_task_runner_, group, observer); | 50 return new BrowserThreadModelWorker(ui_task_runner_, group); |
| 50 case GROUP_DB: | 51 case GROUP_DB: |
| 51 return new BrowserThreadModelWorker(db_task_runner_, group, observer); | 52 return new BrowserThreadModelWorker(db_task_runner_, group); |
| 52 case GROUP_FILE: | 53 case GROUP_FILE: |
| 53 return new BrowserThreadModelWorker(file_task_runner_, group, observer); | 54 return new BrowserThreadModelWorker(file_task_runner_, group); |
| 54 case GROUP_PASSIVE: | 55 case GROUP_PASSIVE: |
| 55 return new PassiveModelWorker(observer); | 56 return new PassiveModelWorker(); |
| 56 default: | 57 default: |
| 57 return nullptr; | 58 return nullptr; |
| 58 } | 59 } |
| 59 } | 60 } |
| 60 | 61 |
| 61 private: | 62 private: |
| 62 const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; | 63 const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; |
| 63 const scoped_refptr<base::SingleThreadTaskRunner> db_task_runner_; | 64 const scoped_refptr<base::SingleThreadTaskRunner> db_task_runner_; |
| 64 const scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; | 65 const scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; |
| 65 }; | 66 }; |
| 66 | 67 |
| 67 // Flaky: https://crbug.com/498238 | 68 // Flaky: https://crbug.com/498238 |
| 68 class SyncBackendRegistrarTest : public testing::Test { | 69 class SyncBackendRegistrarTest : public testing::Test { |
| 69 public: | 70 public: |
| 70 void TestNonUIDataTypeActivationAsync(ChangeProcessor* processor, | 71 void TestNonUIDataTypeActivationAsync(ChangeProcessor* processor, |
| 71 base::WaitableEvent* done) { | 72 base::WaitableEvent* done) { |
| 72 registrar_->ActivateDataType(AUTOFILL, GROUP_DB, processor, | 73 registrar_->ActivateDataType(AUTOFILL, GROUP_DB, processor, |
| 73 test_user_share_.user_share()); | 74 test_user_share_.user_share()); |
| 74 ExpectRoutingInfo(registrar_.get(), {{AUTOFILL, GROUP_DB}}); | 75 ExpectRoutingInfo(registrar_.get(), {{AUTOFILL, GROUP_DB}}); |
| 75 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet(AUTOFILL)); | 76 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet(AUTOFILL)); |
| 76 TriggerChanges(registrar_.get(), AUTOFILL); | 77 TriggerChanges(registrar_.get(), AUTOFILL); |
| 77 done->Signal(); | 78 done->Signal(); |
| 78 } | 79 } |
| 79 | 80 |
| 80 protected: | 81 protected: |
| 81 SyncBackendRegistrarTest() | 82 SyncBackendRegistrarTest() |
| 82 : db_thread_("DBThreadForTest"), | 83 : db_thread_("DBThreadForTest"), file_thread_("FileThreadForTest") {} |
| 83 file_thread_("FileThreadForTest"), | |
| 84 sync_thread_(nullptr) {} | |
| 85 | 84 |
| 86 ~SyncBackendRegistrarTest() override {} | 85 ~SyncBackendRegistrarTest() override {} |
| 87 | 86 |
| 88 void SetUp() override { | 87 void SetUp() override { |
| 89 db_thread_.StartAndWaitForTesting(); | 88 db_thread_.StartAndWaitForTesting(); |
| 90 file_thread_.StartAndWaitForTesting(); | 89 file_thread_.StartAndWaitForTesting(); |
| 91 test_user_share_.SetUp(); | 90 test_user_share_.SetUp(); |
| 92 sync_client_ = base::MakeUnique<RegistrarSyncClient>( | 91 sync_client_ = base::MakeUnique<RegistrarSyncClient>( |
| 93 ui_task_runner(), db_task_runner(), file_task_runner()); | 92 ui_task_runner(), db_task_runner(), file_task_runner()); |
| 94 registrar_ = base::MakeUnique<SyncBackendRegistrar>( | 93 registrar_ = base::MakeUnique<SyncBackendRegistrar>( |
| 95 "test", sync_client_.get(), std::unique_ptr<base::Thread>(), | 94 "test", sync_client_.get(), std::unique_ptr<base::Thread>(), |
| 96 ui_task_runner(), db_task_runner(), file_task_runner()); | 95 ui_task_runner(), db_task_runner(), file_task_runner()); |
| 97 sync_thread_ = registrar_->sync_thread(); | |
| 98 } | 96 } |
| 99 | 97 |
| 100 void TearDown() override { | 98 void TearDown() override { |
| 101 registrar_->RequestWorkerStopOnUIThread(); | 99 registrar_->RequestWorkerStopOnUIThread(); |
| 102 test_user_share_.TearDown(); | 100 test_user_share_.TearDown(); |
| 103 sync_thread_->task_runner()->PostTask( | 101 { |
| 104 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown, | 102 std::unique_ptr<base::Thread> released_sync_thread = |
| 105 base::Unretained(registrar_.release()))); | 103 registrar_->ReleaseSyncThread(); |
| 106 sync_thread_->WaitUntilThreadStarted(); | 104 released_sync_thread->task_runner()->DeleteSoon(FROM_HERE, |
| 105 registrar_.release()); |
| 106 // |released_sync_thread| is joined at the end of this scope. |
| 107 } |
| 107 base::RunLoop().RunUntilIdle(); | 108 base::RunLoop().RunUntilIdle(); |
| 108 } | 109 } |
| 109 | 110 |
| 110 void ExpectRoutingInfo(SyncBackendRegistrar* registrar, | 111 void ExpectRoutingInfo(SyncBackendRegistrar* registrar, |
| 111 const ModelSafeRoutingInfo& expected_routing_info) { | 112 const ModelSafeRoutingInfo& expected_routing_info) { |
| 112 ModelSafeRoutingInfo actual_routing_info; | 113 ModelSafeRoutingInfo actual_routing_info; |
| 113 registrar->GetModelSafeRoutingInfo(&actual_routing_info); | 114 registrar->GetModelSafeRoutingInfo(&actual_routing_info); |
| 114 EXPECT_EQ(expected_routing_info, actual_routing_info); | 115 EXPECT_EQ(expected_routing_info, actual_routing_info); |
| 115 } | 116 } |
| 116 | 117 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 141 return db_thread_.task_runner(); | 142 return db_thread_.task_runner(); |
| 142 } | 143 } |
| 143 | 144 |
| 144 base::MessageLoop message_loop_; | 145 base::MessageLoop message_loop_; |
| 145 base::Thread db_thread_; | 146 base::Thread db_thread_; |
| 146 base::Thread file_thread_; | 147 base::Thread file_thread_; |
| 147 | 148 |
| 148 TestUserShare test_user_share_; | 149 TestUserShare test_user_share_; |
| 149 std::unique_ptr<RegistrarSyncClient> sync_client_; | 150 std::unique_ptr<RegistrarSyncClient> sync_client_; |
| 150 std::unique_ptr<SyncBackendRegistrar> registrar_; | 151 std::unique_ptr<SyncBackendRegistrar> registrar_; |
| 151 | |
| 152 base::Thread* sync_thread_; | |
| 153 }; | 152 }; |
| 154 | 153 |
| 155 TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) { | 154 TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) { |
| 156 registrar_->SetInitialTypes(ModelTypeSet()); | 155 registrar_->SetInitialTypes(ModelTypeSet()); |
| 157 EXPECT_FALSE(registrar_->IsNigoriEnabled()); | 156 EXPECT_FALSE(registrar_->IsNigoriEnabled()); |
| 158 EXPECT_EQ(4u, GetWorkersSize()); | 157 EXPECT_EQ(4u, GetWorkersSize()); |
| 159 ExpectRoutingInfo(registrar_.get(), ModelSafeRoutingInfo()); | 158 ExpectRoutingInfo(registrar_.get(), ModelSafeRoutingInfo()); |
| 160 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet()); | 159 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet()); |
| 161 } | 160 } |
| 162 | 161 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 // it should be included in types to be downloaded. | 296 // it should be included in types to be downloaded. |
| 298 ModelTypeSet types_to_add(AUTOFILL, BOOKMARKS); | 297 ModelTypeSet types_to_add(AUTOFILL, BOOKMARKS); |
| 299 ModelTypeSet newly_added_types = | 298 ModelTypeSet newly_added_types = |
| 300 registrar_->ConfigureDataTypes(types_to_add, ModelTypeSet()); | 299 registrar_->ConfigureDataTypes(types_to_add, ModelTypeSet()); |
| 301 EXPECT_EQ(ModelTypeSet(BOOKMARKS), newly_added_types); | 300 EXPECT_EQ(ModelTypeSet(BOOKMARKS), newly_added_types); |
| 302 EXPECT_EQ(types_to_add, registrar_->GetLastConfiguredTypes()); | 301 EXPECT_EQ(types_to_add, registrar_->GetLastConfiguredTypes()); |
| 303 ExpectRoutingInfo(registrar_.get(), {{AUTOFILL, GROUP_NON_BLOCKING}, | 302 ExpectRoutingInfo(registrar_.get(), {{AUTOFILL, GROUP_NON_BLOCKING}, |
| 304 {BOOKMARKS, GROUP_NON_BLOCKING}}); | 303 {BOOKMARKS, GROUP_NON_BLOCKING}}); |
| 305 } | 304 } |
| 306 | 305 |
| 307 class SyncBackendRegistrarShutdownTest : public testing::Test { | |
| 308 public: | |
| 309 void BlockDBThread() { | |
| 310 EXPECT_FALSE(db_thread_lock_.Try()); | |
| 311 | |
| 312 db_thread_blocked_.Signal(); | |
| 313 base::AutoLock l(db_thread_lock_); | |
| 314 } | |
| 315 | |
| 316 protected: | |
| 317 friend class TestRegistrar; | |
| 318 | |
| 319 SyncBackendRegistrarShutdownTest() | |
| 320 : db_thread_("DBThreadForTest"), | |
| 321 file_thread_("FileThreadForTest"), | |
| 322 db_thread_blocked_(base::WaitableEvent::ResetPolicy::AUTOMATIC, | |
| 323 base::WaitableEvent::InitialState::NOT_SIGNALED) { | |
| 324 quit_closure_ = run_loop_.QuitClosure(); | |
| 325 } | |
| 326 | |
| 327 ~SyncBackendRegistrarShutdownTest() override {} | |
| 328 | |
| 329 void SetUp() override { | |
| 330 db_thread_.StartAndWaitForTesting(); | |
| 331 file_thread_.StartAndWaitForTesting(); | |
| 332 sync_client_ = base::MakeUnique<RegistrarSyncClient>( | |
| 333 ui_task_runner(), db_task_runner(), file_task_runner()); | |
| 334 } | |
| 335 | |
| 336 void PostQuitOnUIMessageLoop() { | |
| 337 ui_task_runner()->PostTask(FROM_HERE, quit_closure_); | |
| 338 } | |
| 339 | |
| 340 const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner() { | |
| 341 return message_loop_.task_runner(); | |
| 342 } | |
| 343 | |
| 344 const scoped_refptr<base::SingleThreadTaskRunner> db_task_runner() { | |
| 345 return db_thread_.task_runner(); | |
| 346 } | |
| 347 | |
| 348 const scoped_refptr<base::SingleThreadTaskRunner> file_task_runner() { | |
| 349 return file_thread_.task_runner(); | |
| 350 } | |
| 351 | |
| 352 base::MessageLoop message_loop_; | |
| 353 base::Thread db_thread_; | |
| 354 base::Thread file_thread_; | |
| 355 | |
| 356 std::unique_ptr<RegistrarSyncClient> sync_client_; | |
| 357 base::WaitableEvent db_thread_blocked_; | |
| 358 | |
| 359 base::Lock db_thread_lock_; | |
| 360 base::RunLoop run_loop_; | |
| 361 base::Closure quit_closure_; | |
| 362 }; | |
| 363 | |
| 364 // Wrap SyncBackendRegistrar so that we can monitor its lifetime. | |
| 365 class TestRegistrar : public SyncBackendRegistrar { | |
| 366 public: | |
| 367 explicit TestRegistrar( | |
| 368 SyncClient* sync_client, | |
| 369 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, | |
| 370 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread, | |
| 371 const scoped_refptr<base::SingleThreadTaskRunner>& file_thread, | |
| 372 SyncBackendRegistrarShutdownTest* test) | |
| 373 : SyncBackendRegistrar("test", | |
| 374 sync_client, | |
| 375 std::unique_ptr<base::Thread>(), | |
| 376 ui_thread, | |
| 377 db_thread, | |
| 378 file_thread), | |
| 379 test_(test) {} | |
| 380 | |
| 381 ~TestRegistrar() override { test_->PostQuitOnUIMessageLoop(); } | |
| 382 | |
| 383 private: | |
| 384 SyncBackendRegistrarShutdownTest* test_; | |
| 385 }; | |
| 386 | |
| 387 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) { | |
| 388 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it. | |
| 389 db_thread_lock_.Acquire(); | |
| 390 | |
| 391 // This will block the DB thread by waiting on |db_thread_lock_|. | |
| 392 db_task_runner()->PostTask( | |
| 393 FROM_HERE, base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread, | |
| 394 base::Unretained(this))); | |
| 395 | |
| 396 std::unique_ptr<TestRegistrar> registrar( | |
| 397 new TestRegistrar(sync_client_.get(), ui_task_runner(), db_task_runner(), | |
| 398 file_task_runner(), this)); | |
| 399 base::Thread* sync_thread = registrar->sync_thread(); | |
| 400 | |
| 401 // Stop here until the DB thread gets a chance to run and block on the lock. | |
| 402 // Please note that since the task above didn't finish, the task to | |
| 403 // initialize the worker on the DB thread hasn't had a chance to run yet too. | |
| 404 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called | |
| 405 // for the DB worker. | |
| 406 db_thread_blocked_.Wait(); | |
| 407 | |
| 408 registrar->SetInitialTypes(ModelTypeSet()); | |
| 409 | |
| 410 // Start the shutdown. | |
| 411 registrar->RequestWorkerStopOnUIThread(); | |
| 412 | |
| 413 sync_thread->task_runner()->PostTask( | |
| 414 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown, | |
| 415 base::Unretained(registrar.release()))); | |
| 416 | |
| 417 // Make sure the thread starts running. | |
| 418 sync_thread->WaitUntilThreadStarted(); | |
| 419 | |
| 420 // The test verifies that the sync thread doesn't block because | |
| 421 // of the blocked DB thread and can finish the shutdown. | |
| 422 base::RunLoop().RunUntilIdle(); | |
| 423 | |
| 424 db_thread_lock_.Release(); | |
| 425 | |
| 426 // Run the main thread loop until all workers have been removed and the | |
| 427 // registrar destroyed. | |
| 428 run_loop_.Run(); | |
| 429 } | |
| 430 | |
| 431 } // namespace | 306 } // namespace |
| 432 | 307 |
| 433 } // namespace syncer | 308 } // namespace syncer |
| OLD | NEW |