Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / glue / sync_backend_registrar_unittest.cc
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.
4
5 #include "chrome/browser/sync/glue/sync_backend_registrar.h"
6
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"
17
18 namespace browser_sync {
19
20 namespace {
21
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;
38
39 void TriggerChanges(SyncBackendRegistrar* registrar, ModelType type) {
40   registrar->OnChangesApplied(type, 0, NULL,
41                               syncer::ImmutableChangeRecordList());
42   registrar->OnChangesComplete(type);
43 }
44
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();
59   }
60
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) {}
67
68   ~SyncBackendRegistrarTest() override {}
69
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();
75   }
76
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();
85   }
86
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);
93   }
94
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));
101     }
102   }
103
104   syncer::TestUserShare test_user_share_;
105   TestingProfile profile_;
106   scoped_ptr<SyncBackendRegistrar> registrar_;
107
108   base::Thread* sync_thread_;
109   content::TestBrowserThreadBundle thread_bundle_;
110 };
111
112 TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) {
113   registrar_->SetInitialTypes(ModelTypeSet());
114   EXPECT_FALSE(registrar_->IsNigoriEnabled());
115   {
116     std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
117     registrar_->GetWorkers(&workers);
118     EXPECT_EQ(4u, workers.size());
119   }
120   ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
121   ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
122 }
123
124 TEST_F(SyncBackendRegistrarTest, ConstructorNonEmpty) {
125   const ModelTypeSet initial_types(BOOKMARKS, NIGORI, PASSWORDS);
126   registrar_->SetInitialTypes(initial_types);
127   EXPECT_TRUE(registrar_->IsNigoriEnabled());
128   {
129     std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers;
130     registrar_->GetWorkers(&workers);
131     EXPECT_EQ(4u, workers.size());
132   }
133   {
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);
139   }
140   ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
141 }
142
143 TEST_F(SyncBackendRegistrarTest, ConfigureDataTypes) {
144   registrar_->SetInitialTypes(ModelTypeSet());
145
146   // Add.
147   const ModelTypeSet types1(BOOKMARKS, NIGORI, AUTOFILL);
148   EXPECT_TRUE(
149       registrar_->ConfigureDataTypes(types1, ModelTypeSet()).Equals(types1));
150   {
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);
156   }
157   ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
158   EXPECT_TRUE(types1.Equals(registrar_->GetLastConfiguredTypes()));
159
160   // Add and remove.
161   const ModelTypeSet types2(PREFERENCES, THEMES);
162   EXPECT_TRUE(registrar_->ConfigureDataTypes(types2, types1).Equals(types2));
163   {
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);
168   }
169   ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
170   EXPECT_TRUE(types2.Equals(registrar_->GetLastConfiguredTypes()));
171
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()));
177 }
178
179 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateUIDataType) {
180   InSequence in_sequence;
181   registrar_->SetInitialTypes(ModelTypeSet());
182
183   // Should do nothing.
184   TriggerChanges(registrar_.get(), BOOKMARKS);
185
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));
196
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());
203   {
204     syncer::ModelSafeRoutingInfo expected_routing_info;
205     expected_routing_info[BOOKMARKS] = syncer::GROUP_UI;
206     ExpectRoutingInfo(registrar_.get(), expected_routing_info);
207   }
208   ExpectHasProcessorsForTypes(*registrar_, types);
209
210   TriggerChanges(registrar_.get(), BOOKMARKS);
211
212   registrar_->DeactivateDataType(BOOKMARKS);
213   ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
214   ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
215
216   // Should do nothing.
217   TriggerChanges(registrar_.get(), BOOKMARKS);
218 }
219
220 TEST_F(SyncBackendRegistrarTest, ActivateDeactivateNonUIDataType) {
221   InSequence in_sequence;
222   registrar_->SetInitialTypes(ModelTypeSet());
223
224   // Should do nothing.
225   TriggerChanges(registrar_.get(), AUTOFILL);
226
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));
237
238   const ModelTypeSet types(AUTOFILL);
239   EXPECT_TRUE(
240       registrar_->ConfigureDataTypes(types, ModelTypeSet()).Equals(types));
241
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();
251
252   registrar_->DeactivateDataType(AUTOFILL);
253   ExpectRoutingInfo(registrar_.get(), syncer::ModelSafeRoutingInfo());
254   ExpectHasProcessorsForTypes(*registrar_, ModelTypeSet());
255
256   // Should do nothing.
257   TriggerChanges(registrar_.get(), AUTOFILL);
258 }
259
260 class SyncBackendRegistrarShutdownTest : public testing::Test {
261  public:
262   void BlockDBThread() {
263     EXPECT_FALSE(db_thread_lock_.Try());
264
265     db_thread_blocked_.Signal();
266     base::AutoLock l(db_thread_lock_);
267   }
268
269  protected:
270   friend class TestRegistrar;
271
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();
278   }
279
280   ~SyncBackendRegistrarShutdownTest() override {}
281
282   void PostQuitOnUIMessageLoop() {
283     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_closure_);
284   }
285
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_;
292 };
293
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) {}
301
302   ~TestRegistrar() override { test_->PostQuitOnUIMessageLoop(); }
303
304  private:
305   SyncBackendRegistrarShutdownTest* test_;
306 };
307
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();
311
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)));
318
319   scoped_ptr<TestRegistrar> registrar(new TestRegistrar(&profile_, this));
320   base::Thread* sync_thread = registrar->sync_thread();
321
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();
328
329   registrar->SetInitialTypes(ModelTypeSet());
330
331   // Start the shutdown.
332   registrar->RequestWorkerStopOnUIThread();
333
334   sync_thread->message_loop()->PostTask(
335       FROM_HERE,
336       base::Bind(&SyncBackendRegistrar::Shutdown,
337                  base::Unretained(registrar.release())));
338
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();
342
343   db_thread_lock_.Release();
344
345   // Run the main thread loop until all workers have been removed and the
346   // registrar destroyed.
347   run_loop_.Run();
348 }
349
350 }  // namespace
351
352 }  // namespace browser_sync