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
{
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
;
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
{
49 void TestNonUIDataTypeActivationAsync(sync_driver::ChangeProcessor
* processor
,
50 base::WaitableEvent
* done
) {
51 registrar_
->ActivateDataType(AUTOFILL
,
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
);
64 SyncBackendRegistrarTest()
65 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD
|
66 content::TestBrowserThreadBundle::REAL_FILE_THREAD
|
67 content::TestBrowserThreadBundle::REAL_IO_THREAD
),
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());
152 const ModelTypeSet
types1(BOOKMARKS
, NIGORI
, AUTOFILL
);
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()));
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()));
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
);
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
);
245 registrar_
->ConfigureDataTypes(types
, ModelTypeSet()).Equals(types
));
247 base::WaitableEvent
done(false, false);
248 BrowserThread::PostTask(
251 base::Bind(&SyncBackendRegistrarTest::TestNonUIDataTypeActivationAsync
,
252 base::Unretained(this),
253 &change_processor_mock
,
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
{
267 void BlockDBThread() {
268 EXPECT_FALSE(db_thread_lock_
.Try());
270 db_thread_blocked_
.Signal();
271 base::AutoLock
l(db_thread_lock_
);
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
{
302 explicit TestRegistrar(Profile
* profile
,
303 SyncBackendRegistrarShutdownTest
* test
)
304 : SyncBackendRegistrar(
307 scoped_ptr
<base::Thread
>(),
308 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI
),
309 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB
),
310 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)),
313 ~TestRegistrar() override
{ test_
->PostQuitOnUIMessageLoop(); }
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(
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.
365 } // namespace browser_sync