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

Side by Side Diff: chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc

Issue 6811003: [Sync] Make generic non-frontend thread datatype controller. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix autofill Created 9 years, 8 months 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
6
7 #include "base/callback.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop.h"
10 #include "base/task.h"
11 #include "base/test/test_timeouts.h"
12 #include "base/tracked_objects.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "chrome/browser/sync/engine/model_safe_worker.h"
15 #include "chrome/browser/sync/glue/change_processor_mock.h"
16 #include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
17 #include "chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h"
18 #include "chrome/browser/sync/glue/model_associator_mock.h"
19 #include "chrome/browser/sync/profile_sync_factory_mock.h"
20 #include "chrome/browser/sync/profile_sync_service_mock.h"
21 #include "chrome/test/profile_mock.h"
22 #include "content/browser/browser_thread.h"
23
24 using base::WaitableEvent;
25 using browser_sync::ChangeProcessorMock;
26 using browser_sync::DataTypeController;
27 using browser_sync::GROUP_DB;
28 using browser_sync::NonFrontendDataTypeController;
29 using browser_sync::NonFrontendDataTypeControllerMock;
30 using browser_sync::ModelAssociatorMock;
31 using testing::_;
32 using testing::DoAll;
33 using testing::InvokeWithoutArgs;
34 using testing::Return;
35 using testing::SetArgumentPointee;
36 using testing::StrictMock;
37
38 class StartCallback {
39 public:
40 MOCK_METHOD2(Run, void(DataTypeController::StartResult result,
41 const tracked_objects::Location& from_here));
42 };
43
44 ACTION_P(WaitOnEvent, event) {
45 event->Wait();
46 }
47
48 ACTION_P(SignalEvent, event) {
49 event->Signal();
50 }
51
52 class NonFrontendDataTypeControllerFake : public NonFrontendDataTypeController {
53 public:
54 NonFrontendDataTypeControllerFake(
55 ProfileSyncFactory* profile_sync_factory,
56 Profile* profile,
57 ProfileSyncService* sync_service,
58 NonFrontendDataTypeControllerMock* mock)
59 : NonFrontendDataTypeController(profile_sync_factory,
60 profile,
61 sync_service),
62 mock_(mock) {}
63
64 virtual syncable::ModelType type() const { return syncable::BOOKMARKS; }
65 virtual browser_sync::ModelSafeGroup model_safe_group() const {
66 return GROUP_DB;
67 }
68
69 private:
70 virtual void CreateSyncComponents() {
71 ProfileSyncFactory::SyncComponents sync_components =
72 profile_sync_factory_->
73 CreateBookmarkSyncComponents(sync_service_, this);
74 model_associator_.reset(sync_components.model_associator);
75 change_processor_.reset(sync_components.change_processor);
76 }
77 virtual bool KickOffAssociation() {
78 mock_->KickOffAssociation();
79 return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
80 NewRunnableMethod(
81 this,
82 &NonFrontendDataTypeControllerFake::Associate));
83 }
84 virtual bool KickOffDestroy() {
85 mock_->KickOffDestroy();
86 return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
87 NewRunnableMethod(
88 this,
89 &NonFrontendDataTypeControllerFake::Destroy));
90 }
91
92 // We mock the following methods because their default implementations do
93 // nothing, but we still want to make sure they're called appropriately.
94 virtual bool StartModels() {
95 return mock_->StartModels();
96 }
97 virtual void CleanUpState() {
98 mock_->CleanUpState();
99 }
100 virtual void RecordUnrecoverableError(
101 const tracked_objects::Location& from_here,
102 const std::string& message) {
103 mock_->RecordUnrecoverableError(from_here, message);
104 }
105 virtual void RecordAssociationTime(base::TimeDelta time) {
106 mock_->RecordAssociationTime(time);
107 }
108 virtual void RecordStartFailure(DataTypeController::StartResult result) {
109 mock_->RecordStartFailure(result);
110 }
111 private:
112 NonFrontendDataTypeControllerMock* mock_;
113 };
114
115 class NonFrontendDataTypeControllerTest : public testing::Test {
116 public:
117 NonFrontendDataTypeControllerTest()
118 : ui_thread_(BrowserThread::UI, &message_loop_),
119 db_thread_(BrowserThread::DB),
120 model_associator_(NULL),
121 change_processor_(NULL),
122 signaled_(false) {}
123
124 virtual void SetUp() {
125 db_thread_.Start();
126 profile_sync_factory_.reset(new ProfileSyncFactoryMock());
127
128 // Both of these are refcounted, so don't need to be released.
129 dtc_mock_ = new StrictMock<NonFrontendDataTypeControllerMock>();
130 non_frontend_dtc_ =
131 new NonFrontendDataTypeControllerFake(profile_sync_factory_.get(),
132 &profile_,
133 &service_,
134 dtc_mock_.get());
135 }
136
137 virtual void TearDown() {
138 db_thread_.Stop();
139 }
140
141 protected:
142 void SetStartExpectations() {
143 EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(true));
144 model_associator_ = new ModelAssociatorMock();
145 change_processor_ = new ChangeProcessorMock();
146 EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
147 WillOnce(Return(ProfileSyncFactory::SyncComponents(model_associator_,
148 change_processor_)));
149 }
150
151 void SetAssociateExpectations() {
152 EXPECT_CALL(*dtc_mock_, KickOffAssociation());
153 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
154 WillOnce(Return(true));
155 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
156 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
157 EXPECT_CALL(*model_associator_, AssociateModels()).
158 WillOnce(Return(true));
159 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
160 }
161
162 void SetActivateExpectations(DataTypeController::StartResult result) {
163 EXPECT_CALL(service_, ActivateDataType(_, _));
164 EXPECT_CALL(start_callback_, Run(result,_));
165 }
166
167 void SetStopExpectations() {
168 EXPECT_CALL(*dtc_mock_, KickOffDestroy());
169 EXPECT_CALL(*dtc_mock_, CleanUpState());
170 EXPECT_CALL(service_, DeactivateDataType(_, _));
171 EXPECT_CALL(*model_associator_, DisassociateModels());
172 }
173
174 void SetStartFailExpectations(DataTypeController::StartResult result) {
175 EXPECT_CALL(*dtc_mock_, CleanUpState());
176 EXPECT_CALL(*dtc_mock_, RecordStartFailure(result));
177 EXPECT_CALL(start_callback_, Run(result,_));
178 }
179
180 static void SignalDone(WaitableEvent* done, bool* signaled) {
181 done->Signal();
182 *signaled = true;
183 }
184
185 void WaitForDTC() {
186 WaitableEvent done(false, false);
187 signaled_ = false;
188 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
189 NewRunnableFunction(&NonFrontendDataTypeControllerTest::SignalDone,
190 &done, &signaled_));
191 done.TimedWait(base::TimeDelta::FromMilliseconds(
192 TestTimeouts::action_timeout_ms()));
193 if (!signaled_) {
194 ADD_FAILURE() << "Timed out waiting for DB thread to finish.";
195 }
196 signaled_ = false;
197 MessageLoop::current()->RunAllPending();
198 }
199
200 MessageLoopForUI message_loop_;
201 BrowserThread ui_thread_;
202 BrowserThread db_thread_;
203 scoped_refptr<NonFrontendDataTypeControllerFake> non_frontend_dtc_;
204 scoped_ptr<ProfileSyncFactoryMock> profile_sync_factory_;
205 scoped_refptr<NonFrontendDataTypeControllerMock> dtc_mock_;
206 ProfileMock profile_;
207 ProfileSyncServiceMock service_;
208 ModelAssociatorMock* model_associator_;
209 ChangeProcessorMock* change_processor_;
210 StartCallback start_callback_;
211 bool signaled_;
212 };
213
214 TEST_F(NonFrontendDataTypeControllerTest, StartOk) {
215 SetStartExpectations();
216 SetAssociateExpectations();
217 SetActivateExpectations(DataTypeController::OK);
218 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
219 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
220 WaitForDTC();
221 EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
222 }
223
224 TEST_F(NonFrontendDataTypeControllerTest, StartFirstRun) {
225 SetStartExpectations();
226 EXPECT_CALL(*dtc_mock_, KickOffAssociation());
227 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
228 WillOnce(Return(true));
229 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
230 WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
231 EXPECT_CALL(*model_associator_, AssociateModels()).
232 WillOnce(Return(true));
233 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
234 SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
235 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
236 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
237 WaitForDTC();
238 EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
239 }
240
241 TEST_F(NonFrontendDataTypeControllerTest, AbortDuringStartModels) {
242 EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(false));
243 SetStartFailExpectations(DataTypeController::ABORTED);
244 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
245 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
246 WaitForDTC();
247 EXPECT_EQ(DataTypeController::MODEL_STARTING, non_frontend_dtc_->state());
248 non_frontend_dtc_->Stop();
249 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
250 }
251
252 TEST_F(NonFrontendDataTypeControllerTest, StartAssociationFailed) {
253 SetStartExpectations();
254 EXPECT_CALL(*dtc_mock_, KickOffAssociation());
255 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
256 WillOnce(Return(true));
257 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
258 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
259 EXPECT_CALL(*model_associator_, AssociateModels()).
260 WillOnce(Return(false));
261 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
262 SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
263 // Set up association to fail with an association failed error.
264 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
265 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
266 WaitForDTC();
267 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
268 }
269
270 TEST_F(NonFrontendDataTypeControllerTest,
271 StartAssociationTriggersUnrecoverableError) {
272 SetStartExpectations();
273 SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
274 // Set up association to fail with an unrecoverable error.
275 EXPECT_CALL(*dtc_mock_, KickOffAssociation());
276 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
277 WillRepeatedly(Return(true));
278 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
279 WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
280 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
281 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
282 WaitForDTC();
283 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
284 }
285
286 TEST_F(NonFrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
287 SetStartExpectations();
288 SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
289 // Set up association to fail with a NEEDS_CRYPTO error.
290 EXPECT_CALL(*dtc_mock_, KickOffAssociation());
291 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
292 WillRepeatedly(Return(false));
293 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
294 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
295 WaitForDTC();
296 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
297 }
298
299 // Trigger a Stop() call when we check if the model associator has user created
300 // nodes.
301 TEST_F(NonFrontendDataTypeControllerTest, AbortDuringAssociationInactive) {
302 WaitableEvent wait_for_db_thread_pause(false, false);
303 WaitableEvent pause_db_thread(false, false);
304
305 SetStartExpectations();
306 EXPECT_CALL(*dtc_mock_, KickOffAssociation());
307 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
308 WillOnce(Return(true));
309 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
310 WillOnce(DoAll(
311 SignalEvent(&wait_for_db_thread_pause),
312 WaitOnEvent(&pause_db_thread),
313 SetArgumentPointee<0>(true),
314 Return(true)));
315 EXPECT_CALL(*model_associator_, AbortAssociation()).WillOnce(
316 SignalEvent(&pause_db_thread));
317 EXPECT_CALL(*model_associator_, AssociateModels()).WillOnce(Return(true));
318 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
319 EXPECT_CALL(service_, ActivateDataType(_, _));
320 EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED,_));
321 EXPECT_CALL(*dtc_mock_, RecordStartFailure(DataTypeController::ABORTED));
322 SetStopExpectations();
323 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
324 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
325 wait_for_db_thread_pause.Wait();
326 non_frontend_dtc_->Stop();
327 WaitForDTC();
328 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
329 }
330
331 // Same as above but abort during the Activate call.
332 TEST_F(NonFrontendDataTypeControllerTest, AbortDuringAssociationActivated) {
333 WaitableEvent wait_for_db_thread_pause(false, false);
334 WaitableEvent pause_db_thread(false, false);
335
336 SetStartExpectations();
337 EXPECT_CALL(*dtc_mock_, KickOffAssociation());
338 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
339 WillOnce(Return(true));
340 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
341 WillOnce(DoAll(
342 SetArgumentPointee<0>(true),
343 Return(true)));
344 EXPECT_CALL(*model_associator_, AbortAssociation()).WillOnce(
345 SignalEvent(&pause_db_thread));
346 EXPECT_CALL(*model_associator_, AssociateModels()).
347 WillOnce(Return(true));
348 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
349 EXPECT_CALL(service_, ActivateDataType(_, _)).WillOnce(DoAll(
350 SignalEvent(&wait_for_db_thread_pause),
351 WaitOnEvent(&pause_db_thread)));
352 EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED,_));
353 EXPECT_CALL(*dtc_mock_, RecordStartFailure(DataTypeController::ABORTED));
354 SetStopExpectations();
355 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
356 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
357 wait_for_db_thread_pause.Wait();
358 non_frontend_dtc_->Stop();
359 WaitForDTC();
360 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
361 }
362
363 TEST_F(NonFrontendDataTypeControllerTest, Stop) {
364 SetStartExpectations();
365 SetAssociateExpectations();
366 SetActivateExpectations(DataTypeController::OK);
367 SetStopExpectations();
368 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
369 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
370 WaitForDTC();
371 EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
372 non_frontend_dtc_->Stop();
373 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
374 }
375
376 TEST_F(NonFrontendDataTypeControllerTest, OnUnrecoverableError) {
377 SetStartExpectations();
378 SetAssociateExpectations();
379 SetActivateExpectations(DataTypeController::OK);
380 EXPECT_CALL(*dtc_mock_, RecordUnrecoverableError(_, "Test"));
381 EXPECT_CALL(service_, OnUnrecoverableError(_,_)).WillOnce(
382 InvokeWithoutArgs(non_frontend_dtc_.get(),
383 &NonFrontendDataTypeController::Stop));
384 SetStopExpectations();
385 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
386 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
387 WaitForDTC();
388 EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
389 // This should cause non_frontend_dtc_->Stop() to be called.
390 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
391 NewRunnableMethod(
392 non_frontend_dtc_.get(),
393 &NonFrontendDataTypeControllerFake::OnUnrecoverableError,
394 FROM_HERE,
395 std::string("Test")));
396 WaitForDTC();
397 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
398 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698