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
{
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
;
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
{
47 void TestNonUIDataTypeActivationAsync(sync_driver::ChangeProcessor
* processor
,
48 base::WaitableEvent
* done
) {
49 registrar_
->ActivateDataType(AUTOFILL
,
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
);
62 SyncBackendRegistrarTest()
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(
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
,
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());
147 const ModelTypeSet
types1(BOOKMARKS
, NIGORI
, AUTOFILL
);
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()));
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()));
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
);
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
);
240 registrar_
->ConfigureDataTypes(types
, ModelTypeSet()).Equals(types
));
242 base::WaitableEvent
done(false, false);
243 BrowserThread::PostTask(
246 base::Bind(&SyncBackendRegistrarTest::TestNonUIDataTypeActivationAsync
,
247 base::Unretained(this),
248 &change_processor_mock
,
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
{
262 void BlockDBThread() {
263 EXPECT_FALSE(db_thread_lock_
.Try());
265 db_thread_blocked_
.Signal();
266 base::AutoLock
l(db_thread_lock_
);
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
{
297 explicit TestRegistrar(Profile
* profile
,
298 SyncBackendRegistrarShutdownTest
* test
)
299 : SyncBackendRegistrar("test", profile
, scoped_ptr
<base::Thread
>()),
302 ~TestRegistrar() override
{ test_
->PostQuitOnUIMessageLoop(); }
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(
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(
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.
352 } // namespace browser_sync