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

Side by Side Diff: components/sync_driver/glue/sync_backend_registrar_unittest.cc

Issue 2203673002: [Sync] Move //components/sync_driver to //components/sync/driver. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sd-a
Patch Set: Full change rebased on static lib. Created 4 years, 4 months 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/sync_driver/glue/sync_backend_registrar.h"
6
7 #include "base/location.h"
8 #include "base/run_loop.h"
9 #include "base/single_thread_task_runner.h"
10 #include "components/sync/base/model_type.h"
11 #include "components/sync/core/test/test_user_share.h"
12 #include "components/sync/engine/passive_model_worker.h"
13 #include "components/sync_driver/change_processor_mock.h"
14 #include "components/sync_driver/fake_sync_client.h"
15 #include "components/sync_driver/glue/browser_thread_model_worker.h"
16 #include "components/sync_driver/sync_api_component_factory_mock.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace browser_sync {
21
22 namespace {
23
24 using ::testing::_;
25 using ::testing::InSequence;
26 using ::testing::Return;
27 using ::testing::StrictMock;
28 using syncer::FIRST_REAL_MODEL_TYPE;
29 using syncer::AUTOFILL;
30 using syncer::BOOKMARKS;
31 using syncer::PREFERENCES;
32 using syncer::THEMES;
33 using syncer::NIGORI;
34 using syncer::PASSWORDS;
35 using syncer::MODEL_TYPE_COUNT;
36 using syncer::ModelTypeSet;
37 using syncer::ModelType;
38 using syncer::ModelTypeFromInt;
39
40 void TriggerChanges(SyncBackendRegistrar* registrar, ModelType type) {
41 registrar->OnChangesApplied(type, 0, NULL,
42 syncer::ImmutableChangeRecordList());
43 registrar->OnChangesComplete(type);
44 }
45
46 class RegistrarSyncClient : public sync_driver::FakeSyncClient {
47 public:
48 RegistrarSyncClient(
49 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
50 const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner,
51 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner)
52 : ui_task_runner_(ui_task_runner),
53 db_task_runner_(db_task_runner),
54 file_task_runner_(file_task_runner) {}
55
56 scoped_refptr<syncer::ModelSafeWorker> CreateModelWorkerForGroup(
57 syncer::ModelSafeGroup group,
58 syncer::WorkerLoopDestructionObserver* observer) override {
59 switch (group) {
60 case syncer::GROUP_UI:
61 return new BrowserThreadModelWorker(ui_task_runner_, group, observer);
62 case syncer::GROUP_DB:
63 return new BrowserThreadModelWorker(db_task_runner_, group, observer);
64 case syncer::GROUP_FILE:
65 return new BrowserThreadModelWorker(file_task_runner_, group, observer);
66 case syncer::GROUP_PASSIVE:
67 return new syncer::PassiveModelWorker(observer);
68 default:
69 return nullptr;
70 }
71 }
72
73 private:
74 const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
75 const scoped_refptr<base::SingleThreadTaskRunner> db_task_runner_;
76 const scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
77 };
78
79 // Flaky: https://crbug.com/498238
80 class SyncBackendRegistrarTest : public testing::Test {
81 public:
82 void TestNonUIDataTypeActivationAsync(sync_driver::ChangeProcessor* processor,
83 base::WaitableEvent* done) {
84 registrar_->ActivateDataType(AUTOFILL,
85 syncer::GROUP_DB,
86 processor,
87 test_user_share_.user_share());
88 syncer::ModelSafeRoutingInfo expected_routing_info;
89 expected_routing_info[AUTOFILL] = syncer::GROUP_DB;
90 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
91 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet(AUTOFILL));
92 TriggerChanges(registrar_.get(), AUTOFILL);
93 done->Signal();
94 }
95
96 protected:
97 SyncBackendRegistrarTest()
98 : db_thread_("DBThreadForTest"),
99 file_thread_("FileThreadForTest"),
100 sync_thread_(NULL) {}
101
102 ~SyncBackendRegistrarTest() override {}
103
104 void SetUp() override {
105 db_thread_.StartAndWaitForTesting();
106 file_thread_.StartAndWaitForTesting();
107 test_user_share_.SetUp();
108 sync_client_.reset(new RegistrarSyncClient(
109 ui_task_runner(), db_task_runner(), file_task_runner()));
110 registrar_.reset(new SyncBackendRegistrar(
111 "test", sync_client_.get(), std::unique_ptr<base::Thread>(),
112 ui_task_runner(), db_task_runner(), file_task_runner()));
113 sync_thread_ = registrar_->sync_thread();
114 }
115
116 void TearDown() override {
117 registrar_->RequestWorkerStopOnUIThread();
118 test_user_share_.TearDown();
119 sync_thread_->task_runner()->PostTask(
120 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
121 base::Unretained(registrar_.release())));
122 sync_thread_->WaitUntilThreadStarted();
123 base::RunLoop().RunUntilIdle();
124 }
125
126 void ExpectRoutingInfo(
127 SyncBackendRegistrar* registrar,
128 const syncer::ModelSafeRoutingInfo& expected_routing_info) {
129 syncer::ModelSafeRoutingInfo routing_info;
130 registrar->GetModelSafeRoutingInfo(&routing_info);
131 EXPECT_EQ(expected_routing_info, routing_info);
132 }
133
134 void ExpectHasProcessorsForTypes(const SyncBackendRegistrar& registrar,
135 ModelTypeSet types) {
136 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
137 ModelType model_type = ModelTypeFromInt(i);
138 EXPECT_EQ(types.Has(model_type),
139 registrar_->IsTypeActivatedForTest(model_type));
140 }
141 }
142
143 const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner() {
144 return message_loop_.task_runner();
145 }
146
147 const scoped_refptr<base::SingleThreadTaskRunner> db_task_runner() {
148 return db_thread_.task_runner();
149 }
150
151 const scoped_refptr<base::SingleThreadTaskRunner> file_task_runner() {
152 return db_thread_.task_runner();
153 }
154
155 base::MessageLoop message_loop_;
156 base::Thread db_thread_;
157 base::Thread file_thread_;
158
159 syncer::TestUserShare test_user_share_;
160 std::unique_ptr<RegistrarSyncClient> sync_client_;
161 std::unique_ptr<SyncBackendRegistrar> registrar_;
162
163 base::Thread* sync_thread_;
164 };
165
166 TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) {
167 registrar_->SetInitialTypes(ModelTypeSet());
168 EXPECT_FALSE(registrar_->IsNigoriEnabled());
169 {
170 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
171 registrar_->GetWorkers(&workers);
172 EXPECT_EQ(4u, workers.size());
173 }
174 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
175 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
176 }
177
178 TEST_F(SyncBackendRegistrarTest, ConstructorNonEmpty) {
179 const ModelTypeSet initial_types(BOOKMARKS, NIGORI, PASSWORDS);
180 registrar_->RegisterNonBlockingType(BOOKMARKS);
181 registrar_->SetInitialTypes(initial_types);
182 EXPECT_TRUE(registrar_->IsNigoriEnabled());
183 {
184 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
185 registrar_->GetWorkers(&workers);
186 EXPECT_EQ(4u, workers.size());
187 }
188 {
189 syncer::ModelSafeRoutingInfo expected_routing_info;
190 expected_routing_info[BOOKMARKS] = syncer::GROUP_NON_BLOCKING;
191 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
192 // Passwords dropped because of no password store.
193 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
194 }
195 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
196 }
197
198 TEST_F(SyncBackendRegistrarTest, ConfigureDataTypes) {
199 registrar_->RegisterNonBlockingType(BOOKMARKS);
200 registrar_->SetInitialTypes(ModelTypeSet());
201
202 // Add.
203 const ModelTypeSet types1(BOOKMARKS, NIGORI, AUTOFILL);
204 EXPECT_EQ(types1, registrar_->ConfigureDataTypes(types1, ModelTypeSet()));
205 {
206 syncer::ModelSafeRoutingInfo expected_routing_info;
207 expected_routing_info[BOOKMARKS] = syncer::GROUP_NON_BLOCKING;
208 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
209 expected_routing_info[AUTOFILL] = syncer::GROUP_PASSIVE;
210 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
211 }
212 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
213 EXPECT_EQ(types1, registrar_->GetLastConfiguredTypes());
214
215 // Add and remove.
216 const ModelTypeSet types2(PREFERENCES, THEMES);
217 EXPECT_EQ(types2, registrar_->ConfigureDataTypes(types2, types1));
218 {
219 syncer::ModelSafeRoutingInfo expected_routing_info;
220 expected_routing_info[PREFERENCES] = syncer::GROUP_PASSIVE;
221 expected_routing_info[THEMES] = syncer::GROUP_PASSIVE;
222 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
223 }
224 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
225 EXPECT_EQ(types2, registrar_->GetLastConfiguredTypes());
226
227 // Remove.
228 EXPECT_TRUE(registrar_->ConfigureDataTypes(ModelTypeSet(), types2).Empty());
229 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
230 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
231 EXPECT_EQ(ModelTypeSet(), registrar_->GetLastConfiguredTypes());
232 }
233
234 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateUIDataType) {
235 InSequence in_sequence;
236 registrar_->SetInitialTypes(ModelTypeSet());
237
238 // Should do nothing.
239 TriggerChanges(registrar_.get(), BOOKMARKS);
240
241 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
242 EXPECT_CALL(change_processor_mock, StartImpl());
243 EXPECT_CALL(change_processor_mock, IsRunning())
244 .WillRepeatedly(Return(true));
245 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
246 EXPECT_CALL(change_processor_mock, IsRunning())
247 .WillRepeatedly(Return(true));
248 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
249 EXPECT_CALL(change_processor_mock, IsRunning())
250 .WillRepeatedly(Return(false));
251
252 const ModelTypeSet types(BOOKMARKS);
253 EXPECT_EQ(types, registrar_->ConfigureDataTypes(types, ModelTypeSet()));
254 registrar_->ActivateDataType(BOOKMARKS, syncer::GROUP_UI,
255 &change_processor_mock,
256 test_user_share_.user_share());
257 {
258 syncer::ModelSafeRoutingInfo expected_routing_info;
259 expected_routing_info[BOOKMARKS] = syncer::GROUP_UI;
260 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
261 }
262 ExpectHasProcessorsForTypes(*registrar_, types);
263
264 TriggerChanges(registrar_.get(), BOOKMARKS);
265
266 registrar_->DeactivateDataType(BOOKMARKS);
267 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
268 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
269
270 // Should do nothing.
271 TriggerChanges(registrar_.get(), BOOKMARKS);
272 }
273
274 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateNonUIDataType) {
275 InSequence in_sequence;
276 registrar_->SetInitialTypes(ModelTypeSet());
277
278 // Should do nothing.
279 TriggerChanges(registrar_.get(), AUTOFILL);
280
281 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
282 EXPECT_CALL(change_processor_mock, StartImpl());
283 EXPECT_CALL(change_processor_mock, IsRunning())
284 .WillRepeatedly(Return(true));
285 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
286 EXPECT_CALL(change_processor_mock, IsRunning())
287 .WillRepeatedly(Return(true));
288 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
289 EXPECT_CALL(change_processor_mock, IsRunning())
290 .WillRepeatedly(Return(false));
291
292 const ModelTypeSet types(AUTOFILL);
293 EXPECT_EQ(types, registrar_->ConfigureDataTypes(types, ModelTypeSet()));
294
295 base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
296 base::WaitableEvent::InitialState::NOT_SIGNALED);
297 db_task_runner()->PostTask(
298 FROM_HERE,
299 base::Bind(&SyncBackendRegistrarTest::TestNonUIDataTypeActivationAsync,
300 base::Unretained(this), &change_processor_mock, &done));
301 done.Wait();
302
303 registrar_->DeactivateDataType(AUTOFILL);
304 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
305 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
306
307 // Should do nothing.
308 TriggerChanges(registrar_.get(), AUTOFILL);
309 }
310
311 // Tests that registration and configuration of non-blocking data types is
312 // handled correctly in SyncBackendRegistrar.
313 TEST_F(SyncBackendRegistrarTest, ConfigureNonBlockingDataType) {
314 registrar_->RegisterNonBlockingType(AUTOFILL);
315 registrar_->RegisterNonBlockingType(BOOKMARKS);
316
317 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
318 // Simulate that initial sync was already done for AUTOFILL.
319 registrar_->AddRestoredNonBlockingType(AUTOFILL);
320 // It should be added to routing info and set of configured types.
321 EXPECT_EQ(ModelTypeSet(AUTOFILL), registrar_->GetLastConfiguredTypes());
322 {
323 syncer::ModelSafeRoutingInfo expected_routing_info;
324 expected_routing_info[AUTOFILL] = syncer::GROUP_NON_BLOCKING;
325 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
326 }
327
328 // Configure two non-blocking types. Initial sync wasn't done for BOOKMARKS so
329 // it should be included in types to be downloaded.
330 ModelTypeSet types_to_add(AUTOFILL, BOOKMARKS);
331 ModelTypeSet newly_added_types =
332 registrar_->ConfigureDataTypes(types_to_add, ModelTypeSet());
333 EXPECT_EQ(ModelTypeSet(BOOKMARKS), newly_added_types);
334 EXPECT_EQ(types_to_add, registrar_->GetLastConfiguredTypes());
335 {
336 syncer::ModelSafeRoutingInfo expected_routing_info;
337 expected_routing_info[AUTOFILL] = syncer::GROUP_NON_BLOCKING;
338 expected_routing_info[BOOKMARKS] = syncer::GROUP_NON_BLOCKING;
339 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
340 }
341 }
342
343 class SyncBackendRegistrarShutdownTest : public testing::Test {
344 public:
345 void BlockDBThread() {
346 EXPECT_FALSE(db_thread_lock_.Try());
347
348 db_thread_blocked_.Signal();
349 base::AutoLock l(db_thread_lock_);
350 }
351
352 protected:
353 friend class TestRegistrar;
354
355 SyncBackendRegistrarShutdownTest()
356 : db_thread_("DBThreadForTest"),
357 file_thread_("FileThreadForTest"),
358 db_thread_blocked_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
359 base::WaitableEvent::InitialState::NOT_SIGNALED) {
360 quit_closure_ = run_loop_.QuitClosure();
361 }
362
363 ~SyncBackendRegistrarShutdownTest() override {}
364
365 void SetUp() override {
366 db_thread_.StartAndWaitForTesting();
367 file_thread_.StartAndWaitForTesting();
368 sync_client_.reset(new RegistrarSyncClient(
369 ui_task_runner(), db_task_runner(), file_task_runner()));
370 }
371
372 void PostQuitOnUIMessageLoop() {
373 ui_task_runner()->PostTask(FROM_HERE, quit_closure_);
374 }
375
376 const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner() {
377 return message_loop_.task_runner();
378 }
379
380 const scoped_refptr<base::SingleThreadTaskRunner> db_task_runner() {
381 return db_thread_.task_runner();
382 }
383
384 const scoped_refptr<base::SingleThreadTaskRunner> file_task_runner() {
385 return file_thread_.task_runner();
386 }
387
388 base::MessageLoop message_loop_;
389 base::Thread db_thread_;
390 base::Thread file_thread_;
391
392 std::unique_ptr<RegistrarSyncClient> sync_client_;
393 base::WaitableEvent db_thread_blocked_;
394
395 base::Lock db_thread_lock_;
396 base::RunLoop run_loop_;
397 base::Closure quit_closure_;
398 };
399
400 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
401 class TestRegistrar : public SyncBackendRegistrar {
402 public:
403 explicit TestRegistrar(
404 sync_driver::SyncClient* sync_client,
405 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
406 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
407 const scoped_refptr<base::SingleThreadTaskRunner>& file_thread,
408 SyncBackendRegistrarShutdownTest* test)
409 : SyncBackendRegistrar("test",
410 sync_client,
411 std::unique_ptr<base::Thread>(),
412 ui_thread,
413 db_thread,
414 file_thread),
415 test_(test) {}
416
417 ~TestRegistrar() override { test_->PostQuitOnUIMessageLoop(); }
418
419 private:
420 SyncBackendRegistrarShutdownTest* test_;
421 };
422
423 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
424 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it.
425 db_thread_lock_.Acquire();
426
427 // This will block the DB thread by waiting on |db_thread_lock_|.
428 db_task_runner()->PostTask(
429 FROM_HERE, base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread,
430 base::Unretained(this)));
431
432 std::unique_ptr<TestRegistrar> registrar(
433 new TestRegistrar(sync_client_.get(), ui_task_runner(), db_task_runner(),
434 file_task_runner(), this));
435 base::Thread* sync_thread = registrar->sync_thread();
436
437 // Stop here until the DB thread gets a chance to run and block on the lock.
438 // Please note that since the task above didn't finish, the task to
439 // initialize the worker on the DB thread hasn't had a chance to run yet too.
440 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
441 // for the DB worker.
442 db_thread_blocked_.Wait();
443
444 registrar->SetInitialTypes(ModelTypeSet());
445
446 // Start the shutdown.
447 registrar->RequestWorkerStopOnUIThread();
448
449 sync_thread->task_runner()->PostTask(
450 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
451 base::Unretained(registrar.release())));
452
453 // Make sure the thread starts running.
454 sync_thread->WaitUntilThreadStarted();
455
456 // The test verifies that the sync thread doesn't block because
457 // of the blocked DB thread and can finish the shutdown.
458 base::RunLoop().RunUntilIdle();
459
460 db_thread_lock_.Release();
461
462 // Run the main thread loop until all workers have been removed and the
463 // registrar destroyed.
464 run_loop_.Run();
465 }
466
467 } // namespace
468
469 } // namespace browser_sync
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