Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Side by Side Diff: components/sync/driver/non_ui_data_type_controller_unittest.cc

Issue 2549223003: [Sync] Rename NonUIDataTypeController to AsyncDirectoryTypeController (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 "components/sync/driver/non_ui_data_type_controller.h"
6
7 #include <utility>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/location.h"
14 #include "base/macros.h"
15 #include "base/run_loop.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/test/test_timeouts.h"
19 #include "base/threading/thread.h"
20 #include "base/threading/thread_task_runner_handle.h"
21 #include "base/tracked_objects.h"
22 #include "components/sync/driver/data_type_controller_mock.h"
23 #include "components/sync/driver/fake_sync_client.h"
24 #include "components/sync/driver/generic_change_processor_factory.h"
25 #include "components/sync/driver/non_ui_data_type_controller_mock.h"
26 #include "components/sync/engine/model_safe_worker.h"
27 #include "components/sync/model/fake_syncable_service.h"
28 #include "components/sync/model/sync_change.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace syncer {
33
34 class SyncClient;
35
36 namespace {
37
38 using base::WaitableEvent;
39 using testing::_;
40 using testing::AtLeast;
41 using testing::DoAll;
42 using testing::InvokeWithoutArgs;
43 using testing::Mock;
44 using testing::Return;
45 using testing::SetArgumentPointee;
46 using testing::StrictMock;
47
48 const ModelType kType = AUTOFILL_PROFILE;
49
50 ACTION_P(WaitOnEvent, event) {
51 event->Wait();
52 }
53
54 ACTION_P(SignalEvent, event) {
55 event->Signal();
56 }
57
58 ACTION_P(SaveChangeProcessor, scoped_change_processor) {
59 scoped_change_processor->reset(arg2);
60 }
61
62 class SharedChangeProcessorMock : public SharedChangeProcessor {
63 public:
64 explicit SharedChangeProcessorMock(ModelType type)
65 : SharedChangeProcessor(type) {}
66
67 base::WeakPtr<SyncableService> Connect(
68 SyncClient*,
69 GenericChangeProcessorFactory*,
70 UserShare*,
71 std::unique_ptr<DataTypeErrorHandler>,
72 const base::WeakPtr<SyncMergeResult>&) {
73 return std::move(connect_return_);
74 }
75 MOCK_METHOD0(Disconnect, bool());
76 MOCK_METHOD2(ProcessSyncChanges,
77 SyncError(const tracked_objects::Location&,
78 const SyncChangeList&));
79 MOCK_CONST_METHOD2(GetAllSyncDataReturnError,
80 SyncError(ModelType, SyncDataList*));
81 MOCK_METHOD0(GetSyncCount, int());
82 MOCK_METHOD1(SyncModelHasUserCreatedNodes, bool(bool*));
83 MOCK_METHOD0(CryptoReadyIfNecessary, bool());
84 MOCK_CONST_METHOD1(GetDataTypeContext, bool(std::string*));
85 MOCK_METHOD1(RecordAssociationTime, void(base::TimeDelta time));
86
87 void SetConnectReturn(base::WeakPtr<SyncableService> service) {
88 connect_return_ = service;
89 }
90
91 protected:
92 virtual ~SharedChangeProcessorMock() { DCHECK(!connect_return_); }
93 MOCK_METHOD2(OnUnrecoverableError,
94 void(const tracked_objects::Location&, const std::string&));
95
96 private:
97 base::WeakPtr<SyncableService> connect_return_;
98 DISALLOW_COPY_AND_ASSIGN(SharedChangeProcessorMock);
99 };
100
101 class NonUIDataTypeControllerFake : public NonUIDataTypeController {
102 public:
103 NonUIDataTypeControllerFake(
104 SyncClient* sync_client,
105 NonUIDataTypeControllerMock* mock,
106 SharedChangeProcessor* change_processor,
107 scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner)
108 : NonUIDataTypeController(kType,
109 base::Closure(),
110 sync_client,
111 GROUP_DB,
112 nullptr),
113 blocked_(false),
114 mock_(mock),
115 change_processor_(change_processor),
116 backend_task_runner_(backend_task_runner) {}
117 ~NonUIDataTypeControllerFake() override {}
118
119 // Prevent tasks from being posted on the backend thread until
120 // UnblockBackendTasks() is called.
121 void BlockBackendTasks() { blocked_ = true; }
122
123 // Post pending tasks on the backend thread and start allowing tasks
124 // to be posted on the backend thread again.
125 void UnblockBackendTasks() {
126 blocked_ = false;
127 for (std::vector<PendingTask>::const_iterator it = pending_tasks_.begin();
128 it != pending_tasks_.end(); ++it) {
129 PostTaskOnModelThread(it->from_here, it->task);
130 }
131 pending_tasks_.clear();
132 }
133
134 SharedChangeProcessor* CreateSharedChangeProcessor() override {
135 return change_processor_.get();
136 }
137
138 std::unique_ptr<DataTypeErrorHandler> CreateErrorHandler() override {
139 return NonUIDataTypeController::CreateErrorHandler();
140 }
141
142 protected:
143 bool PostTaskOnModelThread(const tracked_objects::Location& from_here,
144 const base::Closure& task) override {
145 if (blocked_) {
146 pending_tasks_.push_back(PendingTask(from_here, task));
147 return true;
148 } else {
149 return backend_task_runner_->PostTask(from_here, task);
150 }
151 }
152
153 // We mock the following methods because their default implementations do
154 // nothing, but we still want to make sure they're called appropriately.
155 bool StartModels() override { return mock_->StartModels(); }
156 void StopModels() override { mock_->StopModels(); }
157 void RecordStartFailure(DataTypeController::ConfigureResult result) override {
158 mock_->RecordStartFailure(result);
159 }
160
161 private:
162 struct PendingTask {
163 PendingTask(const tracked_objects::Location& from_here,
164 const base::Closure& task)
165 : from_here(from_here), task(task) {}
166
167 tracked_objects::Location from_here;
168 base::Closure task;
169 };
170
171 bool blocked_;
172 std::vector<PendingTask> pending_tasks_;
173 NonUIDataTypeControllerMock* mock_;
174 scoped_refptr<SharedChangeProcessor> change_processor_;
175 scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_;
176
177 DISALLOW_COPY_AND_ASSIGN(NonUIDataTypeControllerFake);
178 };
179
180 class SyncNonUIDataTypeControllerTest : public testing::Test,
181 public FakeSyncClient {
182 public:
183 SyncNonUIDataTypeControllerTest() : backend_thread_("dbthread") {}
184
185 void SetUp() override {
186 backend_thread_.Start();
187 change_processor_ = new SharedChangeProcessorMock(kType);
188 // All of these are refcounted, so don't need to be released.
189 dtc_mock_ = base::MakeUnique<StrictMock<NonUIDataTypeControllerMock>>();
190 non_ui_dtc_ = base::MakeUnique<NonUIDataTypeControllerFake>(
191 this, dtc_mock_.get(), change_processor_.get(),
192 backend_thread_.task_runner());
193 }
194
195 void TearDown() override { backend_thread_.Stop(); }
196
197 void WaitForDTC() {
198 WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
199 base::WaitableEvent::InitialState::NOT_SIGNALED);
200 backend_thread_.task_runner()->PostTask(
201 FROM_HERE,
202 base::Bind(&SyncNonUIDataTypeControllerTest::SignalDone, &done));
203 done.TimedWait(TestTimeouts::action_timeout());
204 if (!done.IsSignaled()) {
205 ADD_FAILURE() << "Timed out waiting for DB thread to finish.";
206 }
207 base::RunLoop().RunUntilIdle();
208 }
209
210 SyncService* GetSyncService() override {
211 // Make sure this isn't called on backend_thread.
212 EXPECT_FALSE(backend_thread_.task_runner()->BelongsToCurrentThread());
213 return FakeSyncClient::GetSyncService();
214 }
215
216 protected:
217 void SetStartExpectations() {
218 EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(true));
219 EXPECT_CALL(model_load_callback_, Run(_, _));
220 }
221
222 void SetAssociateExpectations() {
223 change_processor_->SetConnectReturn(syncable_service_.AsWeakPtr());
224 EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
225 .WillOnce(Return(true));
226 EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
227 .WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
228 EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_, _))
229 .WillOnce(Return(SyncError()));
230 EXPECT_CALL(*change_processor_.get(), GetSyncCount()).WillOnce(Return(0));
231 EXPECT_CALL(*change_processor_.get(), RecordAssociationTime(_));
232 }
233
234 void SetActivateExpectations(DataTypeController::ConfigureResult result) {
235 EXPECT_CALL(start_callback_, Run(result, _, _));
236 }
237
238 void SetStopExpectations() {
239 EXPECT_CALL(*dtc_mock_.get(), StopModels());
240 EXPECT_CALL(*change_processor_.get(), Disconnect()).WillOnce(Return(true));
241 }
242
243 void SetStartFailExpectations(DataTypeController::ConfigureResult result) {
244 EXPECT_CALL(*dtc_mock_.get(), StopModels()).Times(AtLeast(1));
245 EXPECT_CALL(*dtc_mock_.get(), RecordStartFailure(result));
246 EXPECT_CALL(start_callback_, Run(result, _, _));
247 }
248
249 void Start() {
250 non_ui_dtc_->LoadModels(base::Bind(
251 &ModelLoadCallbackMock::Run, base::Unretained(&model_load_callback_)));
252 non_ui_dtc_->StartAssociating(base::Bind(
253 &StartCallbackMock::Run, base::Unretained(&start_callback_)));
254 }
255
256 static void SignalDone(WaitableEvent* done) { done->Signal(); }
257
258 base::MessageLoopForUI message_loop_;
259 base::Thread backend_thread_;
260
261 StartCallbackMock start_callback_;
262 ModelLoadCallbackMock model_load_callback_;
263 // Must be destroyed after non_ui_dtc_.
264 FakeSyncableService syncable_service_;
265 std::unique_ptr<NonUIDataTypeControllerFake> non_ui_dtc_;
266 std::unique_ptr<NonUIDataTypeControllerMock> dtc_mock_;
267 scoped_refptr<SharedChangeProcessorMock> change_processor_;
268 std::unique_ptr<SyncChangeProcessor> saved_change_processor_;
269 };
270
271 TEST_F(SyncNonUIDataTypeControllerTest, StartOk) {
272 SetStartExpectations();
273 SetAssociateExpectations();
274 SetActivateExpectations(DataTypeController::OK);
275 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
276 Start();
277 WaitForDTC();
278 EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
279 }
280
281 TEST_F(SyncNonUIDataTypeControllerTest, StartFirstRun) {
282 SetStartExpectations();
283 change_processor_->SetConnectReturn(syncable_service_.AsWeakPtr());
284 EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
285 .WillOnce(Return(true));
286 EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
287 .WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
288 EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_, _))
289 .WillOnce(Return(SyncError()));
290 EXPECT_CALL(*change_processor_.get(), RecordAssociationTime(_));
291 SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
292 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
293 Start();
294 WaitForDTC();
295 EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
296 }
297
298 // Start the DTC and have StartModels() return false. Then, stop the
299 // DTC without finishing model startup. It should stop cleanly.
300 TEST_F(SyncNonUIDataTypeControllerTest, AbortDuringStartModels) {
301 EXPECT_CALL(*dtc_mock_.get(), StartModels()).WillOnce(Return(false));
302 EXPECT_CALL(*dtc_mock_.get(), StopModels());
303 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
304 non_ui_dtc_->LoadModels(base::Bind(&ModelLoadCallbackMock::Run,
305 base::Unretained(&model_load_callback_)));
306 WaitForDTC();
307 EXPECT_EQ(DataTypeController::MODEL_STARTING, non_ui_dtc_->state());
308 non_ui_dtc_->Stop();
309 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
310 }
311
312 // Start the DTC and have MergeDataAndStartSyncing() return an error.
313 // The DTC should become disabled, and the DTC should still stop
314 // cleanly.
315 TEST_F(SyncNonUIDataTypeControllerTest, StartAssociationFailed) {
316 SetStartExpectations();
317 change_processor_->SetConnectReturn(syncable_service_.AsWeakPtr());
318 EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
319 .WillOnce(Return(true));
320 EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
321 .WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
322 EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_, _))
323 .WillOnce(Return(SyncError()));
324 EXPECT_CALL(*change_processor_.get(), RecordAssociationTime(_));
325 SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
326 // Set up association to fail with an association failed error.
327 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
328 syncable_service_.set_merge_data_and_start_syncing_error(SyncError(
329 FROM_HERE, SyncError::DATATYPE_ERROR, "Sync Error", non_ui_dtc_->type()));
330 Start();
331 WaitForDTC();
332 EXPECT_EQ(DataTypeController::DISABLED, non_ui_dtc_->state());
333 non_ui_dtc_->Stop();
334 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
335 }
336
337 TEST_F(SyncNonUIDataTypeControllerTest,
338 StartAssociationTriggersUnrecoverableError) {
339 SetStartExpectations();
340 SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
341 // Set up association to fail with an unrecoverable error.
342 change_processor_->SetConnectReturn(syncable_service_.AsWeakPtr());
343 EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
344 .WillRepeatedly(Return(true));
345 EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
346 .WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
347 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
348 Start();
349 WaitForDTC();
350 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
351 }
352
353 TEST_F(SyncNonUIDataTypeControllerTest, StartAssociationCryptoNotReady) {
354 SetStartExpectations();
355 SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
356 // Set up association to fail with a NEEDS_CRYPTO error.
357 change_processor_->SetConnectReturn(syncable_service_.AsWeakPtr());
358 EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
359 .WillRepeatedly(Return(false));
360 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
361 Start();
362 WaitForDTC();
363 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
364 }
365
366 // Trigger a Stop() call when we check if the model associator has user created
367 // nodes.
368 TEST_F(SyncNonUIDataTypeControllerTest, AbortDuringAssociation) {
369 WaitableEvent wait_for_db_thread_pause(
370 base::WaitableEvent::ResetPolicy::AUTOMATIC,
371 base::WaitableEvent::InitialState::NOT_SIGNALED);
372 WaitableEvent pause_db_thread(
373 base::WaitableEvent::ResetPolicy::AUTOMATIC,
374 base::WaitableEvent::InitialState::NOT_SIGNALED);
375
376 SetStartExpectations();
377 change_processor_->SetConnectReturn(syncable_service_.AsWeakPtr());
378 EXPECT_CALL(*change_processor_.get(), CryptoReadyIfNecessary())
379 .WillOnce(Return(true));
380 EXPECT_CALL(*change_processor_.get(), SyncModelHasUserCreatedNodes(_))
381 .WillOnce(DoAll(SignalEvent(&wait_for_db_thread_pause),
382 WaitOnEvent(&pause_db_thread),
383 SetArgumentPointee<0>(true), Return(true)));
384 EXPECT_CALL(*change_processor_.get(), GetAllSyncDataReturnError(_, _))
385 .WillOnce(Return(SyncError(FROM_HERE, SyncError::DATATYPE_ERROR,
386 "Disconnected.", kType)));
387 EXPECT_CALL(*dtc_mock_.get(), StopModels());
388 EXPECT_CALL(*change_processor_.get(), Disconnect())
389 .WillOnce(DoAll(SignalEvent(&pause_db_thread), Return(true)));
390 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
391 Start();
392 wait_for_db_thread_pause.Wait();
393 non_ui_dtc_->Stop();
394 WaitForDTC();
395 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
396 }
397
398 // Start the DTC while the backend tasks are blocked. Then stop the DTC before
399 // the backend tasks get a chance to run.
400 TEST_F(SyncNonUIDataTypeControllerTest, StartAfterSyncShutdown) {
401 non_ui_dtc_->BlockBackendTasks();
402
403 SetStartExpectations();
404 // We don't expect StopSyncing to be called because local_service_ will never
405 // have been set.
406 SetStopExpectations();
407 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
408 Start();
409 non_ui_dtc_->Stop();
410 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
411 Mock::VerifyAndClearExpectations(change_processor_.get());
412 Mock::VerifyAndClearExpectations(dtc_mock_.get());
413
414 non_ui_dtc_->UnblockBackendTasks();
415 WaitForDTC();
416 }
417
418 TEST_F(SyncNonUIDataTypeControllerTest, Stop) {
419 SetStartExpectations();
420 SetAssociateExpectations();
421 SetActivateExpectations(DataTypeController::OK);
422 SetStopExpectations();
423 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
424 Start();
425 WaitForDTC();
426 EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
427 non_ui_dtc_->Stop();
428 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
429 }
430
431 // Start the DTC then block its backend tasks. While its backend
432 // tasks are blocked, stop and start it again, then unblock its
433 // backend tasks. The (delayed) running of the backend tasks from the
434 // stop after the restart shouldn't cause any problems.
435 TEST_F(SyncNonUIDataTypeControllerTest, StopStart) {
436 SetStartExpectations();
437 SetAssociateExpectations();
438 SetActivateExpectations(DataTypeController::OK);
439 SetStopExpectations();
440 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
441 Start();
442 WaitForDTC();
443 EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
444
445 non_ui_dtc_->BlockBackendTasks();
446 non_ui_dtc_->Stop();
447 SetStartExpectations();
448 SetAssociateExpectations();
449 SetActivateExpectations(DataTypeController::OK);
450 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
451 Start();
452 non_ui_dtc_->UnblockBackendTasks();
453
454 WaitForDTC();
455 EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
456 }
457
458 TEST_F(SyncNonUIDataTypeControllerTest, OnUnrecoverableError) {
459 SetStartExpectations();
460 SetAssociateExpectations();
461 SetActivateExpectations(DataTypeController::OK);
462 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state());
463 Start();
464 WaitForDTC();
465 EXPECT_EQ(DataTypeController::RUNNING, non_ui_dtc_->state());
466
467 testing::Mock::VerifyAndClearExpectations(&start_callback_);
468 EXPECT_CALL(model_load_callback_, Run(_, _));
469 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, "error",
470 non_ui_dtc_->type());
471 backend_thread_.task_runner()->PostTask(
472 FROM_HERE,
473 base::Bind(&DataTypeErrorHandler::OnUnrecoverableError,
474 base::Passed(non_ui_dtc_->CreateErrorHandler()), error));
475 WaitForDTC();
476 }
477
478 } // namespace
479
480 } // namespace syncer
OLDNEW
« no previous file with comments | « components/sync/driver/non_ui_data_type_controller_mock.cc ('k') | components/sync_sessions/session_data_type_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698