Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / sync / glue / sync_backend_registrar_unittest.cc
blob0bb25faf43a729543b1f44dd9a395cd1c0a3aed0
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 "chrome/browser/sync/glue/ui_model_worker.h"
8 #include "chrome/test/base/testing_profile.h"
9 #include "components/sync_driver/change_processor_mock.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/test/test_browser_thread_bundle.h"
12 #include "sync/internal_api/public/base/model_type.h"
13 #include "sync/internal_api/public/test/test_user_share.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 namespace browser_sync {
19 namespace {
21 using ::testing::_;
22 using ::testing::InSequence;
23 using ::testing::Return;
24 using ::testing::StrictMock;
25 using content::BrowserThread;
26 using syncer::FIRST_REAL_MODEL_TYPE;
27 using syncer::AUTOFILL;
28 using syncer::BOOKMARKS;
29 using syncer::PREFERENCES;
30 using syncer::THEMES;
31 using syncer::NIGORI;
32 using syncer::PASSWORDS;
33 using syncer::MODEL_TYPE_COUNT;
34 using syncer::ModelTypeSet;
35 using syncer::ModelType;
36 using syncer::ModelTypeFromInt;
38 void TriggerChanges(SyncBackendRegistrar* registrar, ModelType type) {
39 registrar->OnChangesApplied(type, 0, NULL,
40 syncer::ImmutableChangeRecordList());
41 registrar->OnChangesComplete(type);
44 class SyncBackendRegistrarTest : public testing::Test {
45 public:
46 void TestNonUIDataTypeActivationAsync(sync_driver::ChangeProcessor* processor,
47 base::WaitableEvent* done) {
48 registrar_->ActivateDataType(AUTOFILL,
49 syncer::GROUP_DB,
50 processor,
51 test_user_share_.user_share());
52 syncer::ModelSafeRoutingInfo expected_routing_info;
53 expected_routing_info[AUTOFILL] = syncer::GROUP_DB;
54 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
55 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet(AUTOFILL));
56 TriggerChanges(registrar_.get(), AUTOFILL);
57 done->Signal();
60 protected:
61 SyncBackendRegistrarTest()
62 : sync_thread_(NULL),
63 thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
64 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
65 content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
67 virtual ~SyncBackendRegistrarTest() {}
69 virtual void SetUp() {
70 test_user_share_.SetUp();
71 registrar_.reset(new SyncBackendRegistrar("test", &profile_,
72 scoped_ptr<base::Thread>()));
73 sync_thread_ = registrar_->sync_thread();
76 virtual void TearDown() {
77 registrar_->RequestWorkerStopOnUIThread();
78 test_user_share_.TearDown();
79 sync_thread_->message_loop()->PostTask(
80 FROM_HERE,
81 base::Bind(&SyncBackendRegistrar::Shutdown,
82 base::Unretained(registrar_.release())));
83 sync_thread_->message_loop()->RunUntilIdle();
86 void ExpectRoutingInfo(
87 SyncBackendRegistrar* registrar,
88 const syncer::ModelSafeRoutingInfo& expected_routing_info) {
89 syncer::ModelSafeRoutingInfo routing_info;
90 registrar->GetModelSafeRoutingInfo(&routing_info);
91 EXPECT_EQ(expected_routing_info, routing_info);
94 void ExpectHasProcessorsForTypes(const SyncBackendRegistrar& registrar,
95 ModelTypeSet types) {
96 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
97 ModelType model_type = ModelTypeFromInt(i);
98 EXPECT_EQ(types.Has(model_type),
99 registrar_->IsTypeActivatedForTest(model_type));
103 syncer::TestUserShare test_user_share_;
104 TestingProfile profile_;
105 scoped_ptr<SyncBackendRegistrar> registrar_;
107 base::Thread* sync_thread_;
108 content::TestBrowserThreadBundle thread_bundle_;
111 TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) {
112 registrar_->SetInitialTypes(ModelTypeSet());
113 EXPECT_FALSE(registrar_->IsNigoriEnabled());
115 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
116 registrar_->GetWorkers(&workers);
117 EXPECT_EQ(4u, workers.size());
119 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
120 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
123 TEST_F(SyncBackendRegistrarTest, ConstructorNonEmpty) {
124 const ModelTypeSet initial_types(BOOKMARKS, NIGORI, PASSWORDS);
125 registrar_->SetInitialTypes(initial_types);
126 EXPECT_TRUE(registrar_->IsNigoriEnabled());
128 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
129 registrar_->GetWorkers(&workers);
130 EXPECT_EQ(4u, workers.size());
133 syncer::ModelSafeRoutingInfo expected_routing_info;
134 expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
135 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
136 // Passwords dropped because of no password store.
137 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
139 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
142 TEST_F(SyncBackendRegistrarTest, ConfigureDataTypes) {
143 registrar_->SetInitialTypes(ModelTypeSet());
145 // Add.
146 const ModelTypeSet types1(BOOKMARKS, NIGORI, AUTOFILL);
147 EXPECT_TRUE(
148 registrar_->ConfigureDataTypes(types1, ModelTypeSet()).Equals(types1));
150 syncer::ModelSafeRoutingInfo expected_routing_info;
151 expected_routing_info[BOOKMARKS] = syncer::GROUP_PASSIVE;
152 expected_routing_info[NIGORI] = syncer::GROUP_PASSIVE;
153 expected_routing_info[AUTOFILL] = syncer::GROUP_PASSIVE;
154 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
156 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
157 EXPECT_TRUE(types1.Equals(registrar_->GetLastConfiguredTypes()));
159 // Add and remove.
160 const ModelTypeSet types2(PREFERENCES, THEMES);
161 EXPECT_TRUE(registrar_->ConfigureDataTypes(types2, types1).Equals(types2));
163 syncer::ModelSafeRoutingInfo expected_routing_info;
164 expected_routing_info[PREFERENCES] = syncer::GROUP_PASSIVE;
165 expected_routing_info[THEMES] = syncer::GROUP_PASSIVE;
166 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
168 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
169 EXPECT_TRUE(types2.Equals(registrar_->GetLastConfiguredTypes()));
171 // Remove.
172 EXPECT_TRUE(registrar_->ConfigureDataTypes(ModelTypeSet(), types2).Empty());
173 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
174 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
175 EXPECT_TRUE(ModelTypeSet().Equals(registrar_->GetLastConfiguredTypes()));
178 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateUIDataType) {
179 InSequence in_sequence;
180 registrar_->SetInitialTypes(ModelTypeSet());
182 // Should do nothing.
183 TriggerChanges(registrar_.get(), BOOKMARKS);
185 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
186 EXPECT_CALL(change_processor_mock, StartImpl());
187 EXPECT_CALL(change_processor_mock, IsRunning())
188 .WillRepeatedly(Return(true));
189 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
190 EXPECT_CALL(change_processor_mock, IsRunning())
191 .WillRepeatedly(Return(true));
192 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
193 EXPECT_CALL(change_processor_mock, IsRunning())
194 .WillRepeatedly(Return(false));
196 const ModelTypeSet types(BOOKMARKS);
197 EXPECT_TRUE(
198 registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
199 registrar_->ActivateDataType(BOOKMARKS, syncer::GROUP_UI,
200 &change_processor_mock,
201 test_user_share_.user_share());
203 syncer::ModelSafeRoutingInfo expected_routing_info;
204 expected_routing_info[BOOKMARKS] = syncer::GROUP_UI;
205 ExpectRoutingInfo(registrar_.get(), expected_routing_info);
207 ExpectHasProcessorsForTypes(*registrar_, types);
209 TriggerChanges(registrar_.get(), BOOKMARKS);
211 registrar_->DeactivateDataType(BOOKMARKS);
212 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
213 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
215 // Should do nothing.
216 TriggerChanges(registrar_.get(), BOOKMARKS);
219 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateNonUIDataType) {
220 InSequence in_sequence;
221 registrar_->SetInitialTypes(ModelTypeSet());
223 // Should do nothing.
224 TriggerChanges(registrar_.get(), AUTOFILL);
226 StrictMock<sync_driver::ChangeProcessorMock> change_processor_mock;
227 EXPECT_CALL(change_processor_mock, StartImpl());
228 EXPECT_CALL(change_processor_mock, IsRunning())
229 .WillRepeatedly(Return(true));
230 EXPECT_CALL(change_processor_mock, ApplyChangesFromSyncModel(NULL, _, _));
231 EXPECT_CALL(change_processor_mock, IsRunning())
232 .WillRepeatedly(Return(true));
233 EXPECT_CALL(change_processor_mock, CommitChangesFromSyncModel());
234 EXPECT_CALL(change_processor_mock, IsRunning())
235 .WillRepeatedly(Return(false));
237 const ModelTypeSet types(AUTOFILL);
238 EXPECT_TRUE(
239 registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
241 base::WaitableEvent done(false, false);
242 BrowserThread::PostTask(
243 BrowserThread::DB,
244 FROM_HERE,
245 base::Bind(&SyncBackendRegistrarTest::TestNonUIDataTypeActivationAsync,
246 base::Unretained(this),
247 &change_processor_mock,
248 &done));
249 done.Wait();
251 registrar_->DeactivateDataType(AUTOFILL);
252 ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
253 ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
255 // Should do nothing.
256 TriggerChanges(registrar_.get(), AUTOFILL);
259 class SyncBackendRegistrarShutdownTest : public testing::Test {
260 public:
261 void BlockDBThread() {
262 EXPECT_FALSE(db_thread_lock_.Try());
264 db_thread_blocked_.Signal();
265 base::AutoLock l(db_thread_lock_);
268 protected:
269 friend class TestRegistrar;
271 SyncBackendRegistrarShutdownTest()
272 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
273 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
274 content::TestBrowserThreadBundle::REAL_IO_THREAD),
275 db_thread_blocked_(false, false),
276 registrar_destroyed_(false, false) {}
278 virtual ~SyncBackendRegistrarShutdownTest() {}
280 content::TestBrowserThreadBundle thread_bundle_;
281 base::WaitableEvent db_thread_blocked_;
282 base::Lock db_thread_lock_;
283 base::WaitableEvent registrar_destroyed_;
286 // Wrap SyncBackendRegistrar so that we can monitor its lifetime.
287 class TestRegistrar : public SyncBackendRegistrar {
288 public:
289 explicit TestRegistrar(Profile* profile,
290 SyncBackendRegistrarShutdownTest* test)
291 : SyncBackendRegistrar("test", profile, scoped_ptr<base::Thread>()),
292 test_(test) {}
294 virtual ~TestRegistrar() { test_->registrar_destroyed_.Signal(); }
296 private:
297 SyncBackendRegistrarShutdownTest* test_;
300 TEST_F(SyncBackendRegistrarShutdownTest, BlockingShutdown) {
301 // Take ownership of |db_thread_lock_| so that the DB thread can't acquire it.
302 db_thread_lock_.Acquire();
304 // This will block the DB thread by waiting on |db_thread_lock_|.
305 BrowserThread::PostTask(
306 BrowserThread::DB,
307 FROM_HERE,
308 base::Bind(&SyncBackendRegistrarShutdownTest::BlockDBThread,
309 base::Unretained(this)));
311 TestingProfile profile;
312 scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile, this));
313 base::Thread* sync_thread = registrar->sync_thread();
315 // Stop here until the DB thread gets a chance to run and block on the lock.
316 // Please note that since the task above didn't finish, the task to
317 // initialize the worker on the DB thread hasn't had a chance to run yet too.
318 // Which means ModelSafeWorker::SetWorkingLoopToCurrent hasn't been called
319 // for the DB worker.
320 db_thread_blocked_.Wait();
322 registrar->SetInitialTypes(ModelTypeSet());
324 // Start the shutdown.
325 registrar->RequestWorkerStopOnUIThread();
326 sync_thread->message_loop()->PostTask(
327 FROM_HERE,
328 base::Bind(&SyncBackendRegistrar::Shutdown,
329 base::Unretained(registrar.release())));
331 // The test verifies that the sync thread doesn't block because
332 // of the blocked DB thread and can finish the shutdown.
333 sync_thread->message_loop()->RunUntilIdle();
335 db_thread_lock_.Release();
337 base::MessageLoop::current()->RunUntilIdle();
339 // This verifies that all workers have been removed and the registrar
340 // destroyed.
341 registrar_destroyed_.Wait();
344 } // namespace
346 } // namespace browser_sync