Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_registrar_unittest.cc
blob59a3c50470c30a05789af11fdada3135007e4e58
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/test/base/testing_profile.h"
11 #include "components/sync_driver/change_processor_mock.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "sync/internal_api/public/base/model_type.h"
15 #include "sync/internal_api/public/test/test_user_share.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace browser_sync {
21 namespace {
23 using ::testing::_;
24 using ::testing::InSequence;
25 using ::testing::Return;
26 using ::testing::StrictMock;
27 using content::BrowserThread;
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;
40 void TriggerChanges(SyncBackendRegistrar* registrar, ModelType type) {
41 registrar->OnChangesApplied(type, 0, NULL,
42 syncer::ImmutableChangeRecordList());
43 registrar->OnChangesComplete(type);
46 // Flaky: https://crbug.com/498238
47 class SyncBackendRegistrarTest : public testing::Test {
48 public:
49 void TestNonUIDataTypeActivationAsync(sync_driver::ChangeProcessor* processor,
50 base::WaitableEvent* done) {
51 registrar_->ActivateDataType(AUTOFILL,
52 syncer::GROUP_DB,
53 processor,
54 test_user_share_.user_share());
55 syncer::ModelSafeRoutingInfo expected_routing_info;
56 expected_routing_info[AUTOFILL] = syncer::GROUP_DB;
57 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
58 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet(AUTOFILL));
59 TriggerChanges(registrar_.get(), AUTOFILL);
60 done->Signal();
63 protected:
64 SyncBackendRegistrarTest()
65 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
66 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
67 content::TestBrowserThreadBundle::REAL_IO_THREAD),
68 sync_thread_(NULL) {}
70 ~SyncBackendRegistrarTest() override {}
72 void SetUp() override {
73 test_user_share_.SetUp();
74 registrar_.reset(new SyncBackendRegistrar(
75 "test", &profile_, scoped_ptr<base::Thread>(),
76 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
77 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
78 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)));
79 sync_thread_ = registrar_->sync_thread();
82 void TearDown() override {
83 registrar_->RequestWorkerStopOnUIThread();
84 test_user_share_.TearDown();
85 sync_thread_->task_runner()->PostTask(
86 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
87 base::Unretained(registrar_.release())));
88 sync_thread_->WaitUntilThreadStarted();
89 sync_thread_->message_loop()->RunUntilIdle();
92 void ExpectRoutingInfo(
93 SyncBackendRegistrar* registrar,
94 const syncer::ModelSafeRoutingInfo& expected_routing_info) {
95 syncer::ModelSafeRoutingInfo routing_info;
96 registrar->GetModelSafeRoutingInfo(&routing_info);
97 EXPECT_EQ(expected_routing_info, routing_info);
100 void ExpectHasProcessorsForTypes(const SyncBackendRegistrar& registrar,
101 ModelTypeSet types) {
102 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
103 ModelType model_type = ModelTypeFromInt(i);
104 EXPECT_EQ(types.Has(model_type),
105 registrar_->IsTypeActivatedForTest(model_type));
109 content::TestBrowserThreadBundle thread_bundle_;
110 syncer::TestUserShare test_user_share_;
111 TestingProfile profile_;
112 scoped_ptr<SyncBackendRegistrar> registrar_;
114 base::Thread* sync_thread_;
117 TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) {
118 registrar_->SetInitialTypes(ModelTypeSet());
119 EXPECT_FALSE(registrar_->IsNigoriEnabled());
121 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
122 registrar_->GetWorkers(&workers);
123 EXPECT_EQ(4u, workers.size());
125 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
126 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
129 TEST_F(SyncBackendRegistrarTest, ConstructorNonEmpty) {
130 const ModelTypeSet initial_types(BOOKMARKS, NIGORI, PASSWORDS);
131 registrar_->SetInitialTypes(initial_types);
132 EXPECT_TRUE(registrar_->IsNigoriEnabled());
134 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
135 registrar_->GetWorkers(&workers);
136 EXPECT_EQ(4u, workers.size());
139 syncer::ModelSafeRoutingInfo expected_routing_info;
140 expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
141 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
142 // Passwords dropped because of no password store.
143 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
145 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
148 TEST_F(SyncBackendRegistrarTest, ConfigureDataTypes) {
149 registrar_->SetInitialTypes(ModelTypeSet());
151 // Add.
152 const ModelTypeSet types1(BOOKMARKS, NIGORI, AUTOFILL);
153 EXPECT_TRUE(
154 registrar_->ConfigureDataTypes(types1, ModelTypeSet()).Equals(types1));
156 syncer::ModelSafeRoutingInfo expected_routing_info;
157 expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
158 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
159 expected_routing_info[AUTOFILL] = syncer::GROUP_PASSIVE;
160 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
162 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
163 EXPECT_TRUE(types1.Equals(registrar_->GetLastConfiguredTypes()));
165 // Add and remove.
166 const ModelTypeSet types2(PREFERENCES, THEMES);
167 EXPECT_TRUE(registrar_->ConfigureDataTypes(types2, types1).Equals(types2));
169 syncer::ModelSafeRoutingInfo expected_routing_info;
170 expected_routing_info[PREFERENCES] = syncer::GROUP_PASSIVE;
171 expected_routing_info[THEMES] = syncer::GROUP_PASSIVE;
172 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
174 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
175 EXPECT_TRUE(types2.Equals(registrar_->GetLastConfiguredTypes()));
177 // Remove.
178 EXPECT_TRUE(registrar_->ConfigureDataTypes(ModelTypeSet(), types2).Empty());
179 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
180 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
181 EXPECT_TRUE(ModelTypeSet().Equals(registrar_->GetLastConfiguredTypes()));
184 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateUIDataType) {
185 InSequence in_sequence;
186 registrar_->SetInitialTypes(ModelTypeSet());
188 // Should do nothing.
189 TriggerChanges(registrar_.get(), BOOKMARKS);
191 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
192 EXPECT_CALL(change_processor_mock, StartImpl());
193 EXPECT_CALL(change_processor_mock, IsRunning())
194 .WillRepeatedly(Return(true));
195 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
196 EXPECT_CALL(change_processor_mock, IsRunning())
197 .WillRepeatedly(Return(true));
198 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
199 EXPECT_CALL(change_processor_mock, IsRunning())
200 .WillRepeatedly(Return(false));
202 const ModelTypeSet types(BOOKMARKS);
203 EXPECT_TRUE(
204 registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
205 registrar_->ActivateDataType(BOOKMARKS, syncer::GROUP_UI,
206 &change_processor_mock,
207 test_user_share_.user_share());
209 syncer::ModelSafeRoutingInfo expected_routing_info;
210 expected_routing_info[BOOKMARKS] = syncer::GROUP_UI;
211 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
213 ExpectHasProcessorsForTypes(*registrar_, types);
215 TriggerChanges(registrar_.get(), BOOKMARKS);
217 registrar_->DeactivateDataType(BOOKMARKS);
218 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
219 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
221 // Should do nothing.
222 TriggerChanges(registrar_.get(), BOOKMARKS);
225 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateNonUIDataType) {
226 InSequence in_sequence;
227 registrar_->SetInitialTypes(ModelTypeSet());
229 // Should do nothing.
230 TriggerChanges(registrar_.get(), AUTOFILL);
232 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
233 EXPECT_CALL(change_processor_mock, StartImpl());
234 EXPECT_CALL(change_processor_mock, IsRunning())
235 .WillRepeatedly(Return(true));
236 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
237 EXPECT_CALL(change_processor_mock, IsRunning())
238 .WillRepeatedly(Return(true));
239 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
240 EXPECT_CALL(change_processor_mock, IsRunning())
241 .WillRepeatedly(Return(false));
243 const ModelTypeSet types(AUTOFILL);
244 EXPECT_TRUE(
245 registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
247 base::WaitableEvent done(false, false);
248 BrowserThread::PostTask(
249 BrowserThread::DB,
250 FROM_HERE,
251 base::Bind(&SyncBackendRegistrarTest::TestNonUIDataTypeActivationAsync,
252 base::Unretained(this),
253 &change_processor_mock,
254 &done));
255 done.Wait();
257 registrar_->DeactivateDataType(AUTOFILL);
258 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
259 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
261 // Should do nothing.
262 TriggerChanges(registrar_.get(), AUTOFILL);
265 class SyncBackendRegistrarShutdownTest : public testing::Test {
266 public:
267 void BlockDBThread() {
268 EXPECT_FALSE(db_thread_lock_.Try());
270 db_thread_blocked_.Signal();
271 base::AutoLock l(db_thread_lock_);
274 protected:
275 friend class TestRegistrar;
277 SyncBackendRegistrarShutdownTest()
278 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
279 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
280 content::TestBrowserThreadBundle::REAL_IO_THREAD),
281 db_thread_blocked_(false, false) {
282 quit_closure_ = run_loop_.QuitClosure();
285 ~SyncBackendRegistrarShutdownTest() override {}
287 void PostQuitOnUIMessageLoop() {
288 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_closure_);
291 content::TestBrowserThreadBundle thread_bundle_;
292 TestingProfile profile_;
293 base::WaitableEvent db_thread_blocked_;
294 base::Lock db_thread_lock_;
295 base::RunLoop run_loop_;
296 base::Closure quit_closure_;
299 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
300 class TestRegistrar : public SyncBackendRegistrar {
301 public:
302 explicit TestRegistrar(Profile* profile,
303 SyncBackendRegistrarShutdownTest* test)
304 : SyncBackendRegistrar(
305 "test",
306 profile,
307 scoped_ptr<base::Thread>(),
308 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
309 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB),
310 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)),
311 test_(test) {}
313 ~TestRegistrar() override { test_->PostQuitOnUIMessageLoop(); }
315 private:
316 SyncBackendRegistrarShutdownTest* test_;
319 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
320 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it.
321 db_thread_lock_.Acquire();
323 // This will block the DB thread by waiting on |db_thread_lock_|.
324 BrowserThread::PostTask(
325 BrowserThread::DB,
326 FROM_HERE,
327 base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread,
328 base::Unretained(this)));
330 scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile_, this));
331 base::Thread* sync_thread = registrar->sync_thread();
333 // Stop here until the DB thread gets a chance to run and block on the lock.
334 // Please note that since the task above didn't finish, the task to
335 // initialize the worker on the DB thread hasn't had a chance to run yet too.
336 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
337 // for the DB worker.
338 db_thread_blocked_.Wait();
340 registrar->SetInitialTypes(ModelTypeSet());
342 // Start the shutdown.
343 registrar->RequestWorkerStopOnUIThread();
345 sync_thread->task_runner()->PostTask(
346 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown,
347 base::Unretained(registrar.release())));
349 // Make sure the thread starts running.
350 sync_thread->WaitUntilThreadStarted();
352 // The test verifies that the sync thread doesn't block because
353 // of the blocked DB thread and can finish the shutdown.
354 sync_thread->message_loop()->RunUntilIdle();
356 db_thread_lock_.Release();
358 // Run the main thread loop until all workers have been removed and the
359 // registrar destroyed.
360 run_loop_.Run();
363 } // namespace
365 } // namespace browser_sync