Fix DCHECK crash in SyncBackendRegistrar test
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_registrar_unittest.cc
blob217501405a98af626e4c5c42dc1c022e2b0266ab
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 "chrome/browser/sync/glue/sync_backend_registrar.h"
7 #include "base/location.h"
8 #include "base/run_loop.h"
9 #include "base/single_thread_task_runner.h"
10 #include "chrome/browser/sync/glue/ui_model_worker.h"
11 #include "chrome/test/base/testing_profile.h"
12 #include "components/sync_driver/change_processor_mock.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/test/test_browser_thread_bundle.h"
15 #include "sync/internal_api/public/base/model_type.h"
16 #include "sync/internal_api/public/test/test_user_share.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 namespace browser_sync {
22 namespace {
24 using ::testing::_;
25 using ::testing::InSequence;
26 using ::testing::Return;
27 using ::testing::StrictMock;
28 using content::BrowserThread;
29 using syncer::FIRST_REAL_MODEL_TYPE;
30 using syncer::AUTOFILL;
31 using syncer::BOOKMARKS;
32 using syncer::PREFERENCES;
33 using syncer::THEMES;
34 using syncer::NIGORI;
35 using syncer::PASSWORDS;
36 using syncer::MODEL_TYPE_COUNT;
37 using syncer::ModelTypeSet;
38 using syncer::ModelType;
39 using syncer::ModelTypeFromInt;
41 void TriggerChanges(SyncBackendRegistrar* registrar, ModelType type) {
42 registrar->OnChangesApplied(type, 0, NULL,
43 syncer::ImmutableChangeRecordList());
44 registrar->OnChangesComplete(type);
47 // Flaky: https://crbug.com/498238
48 class SyncBackendRegistrarTest : public testing::Test {
49 public:
50 void TestNonUIDataTypeActivationAsync(sync_driver::ChangeProcessor* processor,
51 base::WaitableEvent* done) {
52 registrar_->ActivateDataType(AUTOFILL,
53 syncer::GROUP_DB,
54 processor,
55 test_user_share_.user_share());
56 syncer::ModelSafeRoutingInfo expected_routing_info;
57 expected_routing_info[AUTOFILL] = syncer::GROUP_DB;
58 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
59 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet(AUTOFILL));
60 TriggerChanges(registrar_.get(), AUTOFILL);
61 done->Signal();
64 protected:
65 SyncBackendRegistrarTest()
66 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
67 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
68 content::TestBrowserThreadBundle::REAL_IO_THREAD),
69 sync_thread_(NULL) {}
71 ~SyncBackendRegistrarTest() override {}
73 void SetUp() override {
74 test_user_share_.SetUp();
75 registrar_.reset(new SyncBackendRegistrar("test", &profile_,
76 scoped_ptr<base::Thread>()));
77 sync_thread_ = registrar_->sync_thread();
80 void TearDown() override {
81 registrar_->RequestWorkerStopOnUIThread();
82 test_user_share_.TearDown();
83 sync_thread_->task_runner()->PostTask(
84 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
85 base::Unretained(registrar_.release())));
86 sync_thread_->WaitUntilThreadStarted();
87 sync_thread_->message_loop()->RunUntilIdle();
90 void ExpectRoutingInfo(
91 SyncBackendRegistrar* registrar,
92 const syncer::ModelSafeRoutingInfo& expected_routing_info) {
93 syncer::ModelSafeRoutingInfo routing_info;
94 registrar->GetModelSafeRoutingInfo(&routing_info);
95 EXPECT_EQ(expected_routing_info, routing_info);
98 void ExpectHasProcessorsForTypes(const SyncBackendRegistrar& registrar,
99 ModelTypeSet types) {
100 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
101 ModelType model_type = ModelTypeFromInt(i);
102 EXPECT_EQ(types.Has(model_type),
103 registrar_->IsTypeActivatedForTest(model_type));
107 content::TestBrowserThreadBundle thread_bundle_;
108 syncer::TestUserShare test_user_share_;
109 TestingProfile profile_;
110 scoped_ptr<SyncBackendRegistrar> registrar_;
112 base::Thread* sync_thread_;
115 TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) {
116 registrar_->SetInitialTypes(ModelTypeSet());
117 EXPECT_FALSE(registrar_->IsNigoriEnabled());
119 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
120 registrar_->GetWorkers(&workers);
121 EXPECT_EQ(4u, workers.size());
123 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
124 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
127 TEST_F(SyncBackendRegistrarTest, ConstructorNonEmpty) {
128 const ModelTypeSet initial_types(BOOKMARKS, NIGORI, PASSWORDS);
129 registrar_->SetInitialTypes(initial_types);
130 EXPECT_TRUE(registrar_->IsNigoriEnabled());
132 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
133 registrar_->GetWorkers(&workers);
134 EXPECT_EQ(4u, workers.size());
137 syncer::ModelSafeRoutingInfo expected_routing_info;
138 expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
139 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
140 // Passwords dropped because of no password store.
141 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
143 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
146 TEST_F(SyncBackendRegistrarTest, ConfigureDataTypes) {
147 registrar_->SetInitialTypes(ModelTypeSet());
149 // Add.
150 const ModelTypeSet types1(BOOKMARKS, NIGORI, AUTOFILL);
151 EXPECT_TRUE(
152 registrar_->ConfigureDataTypes(types1, ModelTypeSet()).Equals(types1));
154 syncer::ModelSafeRoutingInfo expected_routing_info;
155 expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
156 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
157 expected_routing_info[AUTOFILL] = syncer::GROUP_PASSIVE;
158 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
160 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
161 EXPECT_TRUE(types1.Equals(registrar_->GetLastConfiguredTypes()));
163 // Add and remove.
164 const ModelTypeSet types2(PREFERENCES, THEMES);
165 EXPECT_TRUE(registrar_->ConfigureDataTypes(types2, types1).Equals(types2));
167 syncer::ModelSafeRoutingInfo expected_routing_info;
168 expected_routing_info[PREFERENCES] = syncer::GROUP_PASSIVE;
169 expected_routing_info[THEMES] = syncer::GROUP_PASSIVE;
170 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
172 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
173 EXPECT_TRUE(types2.Equals(registrar_->GetLastConfiguredTypes()));
175 // Remove.
176 EXPECT_TRUE(registrar_->ConfigureDataTypes(ModelTypeSet(), types2).Empty());
177 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
178 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
179 EXPECT_TRUE(ModelTypeSet().Equals(registrar_->GetLastConfiguredTypes()));
182 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateUIDataType) {
183 InSequence in_sequence;
184 registrar_->SetInitialTypes(ModelTypeSet());
186 // Should do nothing.
187 TriggerChanges(registrar_.get(), BOOKMARKS);
189 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
190 EXPECT_CALL(change_processor_mock, StartImpl());
191 EXPECT_CALL(change_processor_mock, IsRunning())
192 .WillRepeatedly(Return(true));
193 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
194 EXPECT_CALL(change_processor_mock, IsRunning())
195 .WillRepeatedly(Return(true));
196 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
197 EXPECT_CALL(change_processor_mock, IsRunning())
198 .WillRepeatedly(Return(false));
200 const ModelTypeSet types(BOOKMARKS);
201 EXPECT_TRUE(
202 registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
203 registrar_->ActivateDataType(BOOKMARKS, syncer::GROUP_UI,
204 &change_processor_mock,
205 test_user_share_.user_share());
207 syncer::ModelSafeRoutingInfo expected_routing_info;
208 expected_routing_info[BOOKMARKS] = syncer::GROUP_UI;
209 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
211 ExpectHasProcessorsForTypes(*registrar_, types);
213 TriggerChanges(registrar_.get(), BOOKMARKS);
215 registrar_->DeactivateDataType(BOOKMARKS);
216 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
217 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
219 // Should do nothing.
220 TriggerChanges(registrar_.get(), BOOKMARKS);
223 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateNonUIDataType) {
224 InSequence in_sequence;
225 registrar_->SetInitialTypes(ModelTypeSet());
227 // Should do nothing.
228 TriggerChanges(registrar_.get(), AUTOFILL);
230 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
231 EXPECT_CALL(change_processor_mock, StartImpl());
232 EXPECT_CALL(change_processor_mock, IsRunning())
233 .WillRepeatedly(Return(true));
234 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
235 EXPECT_CALL(change_processor_mock, IsRunning())
236 .WillRepeatedly(Return(true));
237 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
238 EXPECT_CALL(change_processor_mock, IsRunning())
239 .WillRepeatedly(Return(false));
241 const ModelTypeSet types(AUTOFILL);
242 EXPECT_TRUE(
243 registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
245 base::WaitableEvent done(false, false);
246 BrowserThread::PostTask(
247 BrowserThread::DB,
248 FROM_HERE,
249 base::Bind(&SyncBackendRegistrarTest::TestNonUIDataTypeActivationAsync,
250 base::Unretained(this),
251 &change_processor_mock,
252 &done));
253 done.Wait();
255 registrar_->DeactivateDataType(AUTOFILL);
256 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
257 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
259 // Should do nothing.
260 TriggerChanges(registrar_.get(), AUTOFILL);
263 class SyncBackendRegistrarShutdownTest : public testing::Test {
264 public:
265 void BlockDBThread() {
266 EXPECT_FALSE(db_thread_lock_.Try());
268 db_thread_blocked_.Signal();
269 base::AutoLock l(db_thread_lock_);
272 protected:
273 friend class TestRegistrar;
275 SyncBackendRegistrarShutdownTest()
276 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
277 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
278 content::TestBrowserThreadBundle::REAL_IO_THREAD),
279 db_thread_blocked_(false, false) {
280 quit_closure_ = run_loop_.QuitClosure();
283 ~SyncBackendRegistrarShutdownTest() override {}
285 void PostQuitOnUIMessageLoop() {
286 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_closure_);
289 content::TestBrowserThreadBundle thread_bundle_;
290 TestingProfile profile_;
291 base::WaitableEvent db_thread_blocked_;
292 base::Lock db_thread_lock_;
293 base::RunLoop run_loop_;
294 base::Closure quit_closure_;
297 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
298 class TestRegistrar : public SyncBackendRegistrar {
299 public:
300 explicit TestRegistrar(Profile* profile,
301 SyncBackendRegistrarShutdownTest* test)
302 : SyncBackendRegistrar("test", profile, scoped_ptr<base::Thread>()),
303 test_(test) {}
305 ~TestRegistrar() override { test_->PostQuitOnUIMessageLoop(); }
307 private:
308 SyncBackendRegistrarShutdownTest* test_;
311 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
312 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it.
313 db_thread_lock_.Acquire();
315 // This will block the DB thread by waiting on |db_thread_lock_|.
316 BrowserThread::PostTask(
317 BrowserThread::DB,
318 FROM_HERE,
319 base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread,
320 base::Unretained(this)));
322 scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile_, this));
323 base::Thread* sync_thread = registrar->sync_thread();
325 // Stop here until the DB thread gets a chance to run and block on the lock.
326 // Please note that since the task above didn't finish, the task to
327 // initialize the worker on the DB thread hasn't had a chance to run yet too.
328 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
329 // for the DB worker.
330 db_thread_blocked_.Wait();
332 registrar->SetInitialTypes(ModelTypeSet());
334 // Start the shutdown.
335 registrar->RequestWorkerStopOnUIThread();
337 sync_thread->task_runner()->PostTask(
338 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
339 base::Unretained(registrar.release())));
341 // Make sure the thread starts running.
342 sync_thread->WaitUntilThreadStarted();
344 // The test verifies that the sync thread doesn't block because
345 // of the blocked DB thread and can finish the shutdown.
346 sync_thread->message_loop()->RunUntilIdle();
348 db_thread_lock_.Release();
350 // Run the main thread loop until all workers have been removed and the
351 // registrar destroyed.
352 run_loop_.Run();
355 } // namespace
357 } // namespace browser_sync