Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: components/sync/driver/glue/sync_backend_registrar_unittest.cc

Issue 2471183003: Do not observe MessageLoop destruction from ModelSafeWorker. (Closed)
Patch Set: CR maxbogue #23 Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « components/sync/driver/glue/sync_backend_registrar.cc ('k') | components/sync/driver/glue/ui_model_worker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698