Add more checks to investigate SupervisedUserPrefStore crash at startup.
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_registrar_unittest.cc
blob1129bbffb8272ef42e504bda7cbe9e70afeef80f
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/run_loop.h"
8 #include "chrome/browser/sync/glue/ui_model_worker.h"
9 #include "chrome/test/base/testing_profile.h"
10 #include "components/sync_driver/change_processor_mock.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/test/test_browser_thread_bundle.h"
13 #include "sync/internal_api/public/base/model_type.h"
14 #include "sync/internal_api/public/test/test_user_share.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace browser_sync {
20 namespace {
22 using ::testing::_;
23 using ::testing::InSequence;
24 using ::testing::Return;
25 using ::testing::StrictMock;
26 using content::BrowserThread;
27 using syncer::FIRST_REAL_MODEL_TYPE;
28 using syncer::AUTOFILL;
29 using syncer::BOOKMARKS;
30 using syncer::PREFERENCES;
31 using syncer::THEMES;
32 using syncer::NIGORI;
33 using syncer::PASSWORDS;
34 using syncer::MODEL_TYPE_COUNT;
35 using syncer::ModelTypeSet;
36 using syncer::ModelType;
37 using syncer::ModelTypeFromInt;
39 void TriggerChanges(SyncBackendRegistrar* registrar, ModelType type) {
40 registrar->OnChangesApplied(type, 0, NULL,
41 syncer::ImmutableChangeRecordList());
42 registrar->OnChangesComplete(type);
45 class SyncBackendRegistrarTest : public testing::Test {
46 public:
47 void TestNonUIDataTypeActivationAsync(sync_driver::ChangeProcessor* processor,
48 base::WaitableEvent* done) {
49 registrar_->ActivateDataType(AUTOFILL,
50 syncer::GROUP_DB,
51 processor,
52 test_user_share_.user_share());
53 syncer::ModelSafeRoutingInfo expected_routing_info;
54 expected_routing_info[AUTOFILL] = syncer::GROUP_DB;
55 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
56 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet(AUTOFILL));
57 TriggerChanges(registrar_.get(), AUTOFILL);
58 done->Signal();
61 protected:
62 SyncBackendRegistrarTest()
63 : sync_thread_(NULL),
64 thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
65 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
66 content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
68 ~SyncBackendRegistrarTest() override {}
70 void SetUp() override {
71 test_user_share_.SetUp();
72 registrar_.reset(new SyncBackendRegistrar("test", &profile_,
73 scoped_ptr<base::Thread>()));
74 sync_thread_ = registrar_->sync_thread();
77 void TearDown() override {
78 registrar_->RequestWorkerStopOnUIThread();
79 test_user_share_.TearDown();
80 sync_thread_->message_loop()->PostTask(
81 FROM_HERE,
82 base::Bind(&SyncBackendRegistrar::Shutdown,
83 base::Unretained(registrar_.release())));
84 sync_thread_->message_loop()->RunUntilIdle();
87 void ExpectRoutingInfo(
88 SyncBackendRegistrar* registrar,
89 const syncer::ModelSafeRoutingInfo& expected_routing_info) {
90 syncer::ModelSafeRoutingInfo routing_info;
91 registrar->GetModelSafeRoutingInfo(&routing_info);
92 EXPECT_EQ(expected_routing_info, routing_info);
95 void ExpectHasProcessorsForTypes(const SyncBackendRegistrar& registrar,
96 ModelTypeSet types) {
97 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
98 ModelType model_type = ModelTypeFromInt(i);
99 EXPECT_EQ(types.Has(model_type),
100 registrar_->IsTypeActivatedForTest(model_type));
104 syncer::TestUserShare test_user_share_;
105 TestingProfile profile_;
106 scoped_ptr<SyncBackendRegistrar> registrar_;
108 base::Thread* sync_thread_;
109 content::TestBrowserThreadBundle thread_bundle_;
112 TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) {
113 registrar_->SetInitialTypes(ModelTypeSet());
114 EXPECT_FALSE(registrar_->IsNigoriEnabled());
116 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
117 registrar_->GetWorkers(&workers);
118 EXPECT_EQ(4u, workers.size());
120 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
121 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
124 TEST_F(SyncBackendRegistrarTest, ConstructorNonEmpty) {
125 const ModelTypeSet initial_types(BOOKMARKS, NIGORI, PASSWORDS);
126 registrar_->SetInitialTypes(initial_types);
127 EXPECT_TRUE(registrar_->IsNigoriEnabled());
129 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
130 registrar_->GetWorkers(&workers);
131 EXPECT_EQ(4u, workers.size());
134 syncer::ModelSafeRoutingInfo expected_routing_info;
135 expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
136 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
137 // Passwords dropped because of no password store.
138 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
140 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
143 TEST_F(SyncBackendRegistrarTest, ConfigureDataTypes) {
144 registrar_->SetInitialTypes(ModelTypeSet());
146 // Add.
147 const ModelTypeSet types1(BOOKMARKS, NIGORI, AUTOFILL);
148 EXPECT_TRUE(
149 registrar_->ConfigureDataTypes(types1, ModelTypeSet()).Equals(types1));
151 syncer::ModelSafeRoutingInfo expected_routing_info;
152 expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
153 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
154 expected_routing_info[AUTOFILL] = syncer::GROUP_PASSIVE;
155 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
157 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
158 EXPECT_TRUE(types1.Equals(registrar_->GetLastConfiguredTypes()));
160 // Add and remove.
161 const ModelTypeSet types2(PREFERENCES, THEMES);
162 EXPECT_TRUE(registrar_->ConfigureDataTypes(types2, types1).Equals(types2));
164 syncer::ModelSafeRoutingInfo expected_routing_info;
165 expected_routing_info[PREFERENCES] = syncer::GROUP_PASSIVE;
166 expected_routing_info[THEMES] = syncer::GROUP_PASSIVE;
167 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
169 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
170 EXPECT_TRUE(types2.Equals(registrar_->GetLastConfiguredTypes()));
172 // Remove.
173 EXPECT_TRUE(registrar_->ConfigureDataTypes(ModelTypeSet(), types2).Empty());
174 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
175 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
176 EXPECT_TRUE(ModelTypeSet().Equals(registrar_->GetLastConfiguredTypes()));
179 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateUIDataType) {
180 InSequence in_sequence;
181 registrar_->SetInitialTypes(ModelTypeSet());
183 // Should do nothing.
184 TriggerChanges(registrar_.get(), BOOKMARKS);
186 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
187 EXPECT_CALL(change_processor_mock, StartImpl());
188 EXPECT_CALL(change_processor_mock, IsRunning())
189 .WillRepeatedly(Return(true));
190 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
191 EXPECT_CALL(change_processor_mock, IsRunning())
192 .WillRepeatedly(Return(true));
193 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
194 EXPECT_CALL(change_processor_mock, IsRunning())
195 .WillRepeatedly(Return(false));
197 const ModelTypeSet types(BOOKMARKS);
198 EXPECT_TRUE(
199 registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
200 registrar_->ActivateDataType(BOOKMARKS, syncer::GROUP_UI,
201 &change_processor_mock,
202 test_user_share_.user_share());
204 syncer::ModelSafeRoutingInfo expected_routing_info;
205 expected_routing_info[BOOKMARKS] = syncer::GROUP_UI;
206 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
208 ExpectHasProcessorsForTypes(*registrar_, types);
210 TriggerChanges(registrar_.get(), BOOKMARKS);
212 registrar_->DeactivateDataType(BOOKMARKS);
213 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
214 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
216 // Should do nothing.
217 TriggerChanges(registrar_.get(), BOOKMARKS);
220 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateNonUIDataType) {
221 InSequence in_sequence;
222 registrar_->SetInitialTypes(ModelTypeSet());
224 // Should do nothing.
225 TriggerChanges(registrar_.get(), AUTOFILL);
227 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
228 EXPECT_CALL(change_processor_mock, StartImpl());
229 EXPECT_CALL(change_processor_mock, IsRunning())
230 .WillRepeatedly(Return(true));
231 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
232 EXPECT_CALL(change_processor_mock, IsRunning())
233 .WillRepeatedly(Return(true));
234 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
235 EXPECT_CALL(change_processor_mock, IsRunning())
236 .WillRepeatedly(Return(false));
238 const ModelTypeSet types(AUTOFILL);
239 EXPECT_TRUE(
240 registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
242 base::WaitableEvent done(false, false);
243 BrowserThread::PostTask(
244 BrowserThread::DB,
245 FROM_HERE,
246 base::Bind(&SyncBackendRegistrarTest::TestNonUIDataTypeActivationAsync,
247 base::Unretained(this),
248 &change_processor_mock,
249 &done));
250 done.Wait();
252 registrar_->DeactivateDataType(AUTOFILL);
253 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
254 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
256 // Should do nothing.
257 TriggerChanges(registrar_.get(), AUTOFILL);
260 class SyncBackendRegistrarShutdownTest : public testing::Test {
261 public:
262 void BlockDBThread() {
263 EXPECT_FALSE(db_thread_lock_.Try());
265 db_thread_blocked_.Signal();
266 base::AutoLock l(db_thread_lock_);
269 protected:
270 friend class TestRegistrar;
272 SyncBackendRegistrarShutdownTest()
273 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
274 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
275 content::TestBrowserThreadBundle::REAL_IO_THREAD),
276 db_thread_blocked_(false, false) {
277 quit_closure_ = run_loop_.QuitClosure();
280 ~SyncBackendRegistrarShutdownTest() override {}
282 void PostQuitOnUIMessageLoop() {
283 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_closure_);
286 content::TestBrowserThreadBundle thread_bundle_;
287 TestingProfile profile_;
288 base::WaitableEvent db_thread_blocked_;
289 base::Lock db_thread_lock_;
290 base::RunLoop run_loop_;
291 base::Closure quit_closure_;
294 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
295 class TestRegistrar : public SyncBackendRegistrar {
296 public:
297 explicit TestRegistrar(Profile* profile,
298 SyncBackendRegistrarShutdownTest* test)
299 : SyncBackendRegistrar("test", profile, scoped_ptr<base::Thread>()),
300 test_(test) {}
302 ~TestRegistrar() override { test_->PostQuitOnUIMessageLoop(); }
304 private:
305 SyncBackendRegistrarShutdownTest* test_;
308 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
309 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it.
310 db_thread_lock_.Acquire();
312 // This will block the DB thread by waiting on |db_thread_lock_|.
313 BrowserThread::PostTask(
314 BrowserThread::DB,
315 FROM_HERE,
316 base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread,
317 base::Unretained(this)));
319 scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile_, this));
320 base::Thread* sync_thread = registrar->sync_thread();
322 // Stop here until the DB thread gets a chance to run and block on the lock.
323 // Please note that since the task above didn't finish, the task to
324 // initialize the worker on the DB thread hasn't had a chance to run yet too.
325 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
326 // for the DB worker.
327 db_thread_blocked_.Wait();
329 registrar->SetInitialTypes(ModelTypeSet());
331 // Start the shutdown.
332 registrar->RequestWorkerStopOnUIThread();
334 sync_thread->message_loop()->PostTask(
335 FROM_HERE,
336 base::Bind(&SyncBackendRegistrar::Shutdown,
337 base::Unretained(registrar.release())));
339 // The test verifies that the sync thread doesn't block because
340 // of the blocked DB thread and can finish the shutdown.
341 sync_thread->message_loop()->RunUntilIdle();
343 db_thread_lock_.Release();
345 // Run the main thread loop until all workers have been removed and the
346 // registrar destroyed.
347 run_loop_.Run();
350 } // namespace
352 } // namespace browser_sync