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

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: Copy paste :( 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 NonFrontendDataTypeControllerMock* mock)
58 : NonFrontendDataTypeController(profile_sync_factory,
59 profile),
60 mock_(mock) {}
61
62 virtual syncable::ModelType type() const { return syncable::BOOKMARKS; }
63 virtual browser_sync::ModelSafeGroup model_safe_group() const {
64 return GROUP_DB;
65 }
66
67 private:
68 virtual void CreateSyncComponents() {
69 ProfileSyncFactory::SyncComponents sync_components =
70 profile_sync_factory()->
71 CreateBookmarkSyncComponents(profile_sync_service(), this);
72 set_model_associator(sync_components.model_associator);
73 set_change_processor(sync_components.change_processor);
74 }
75 virtual bool StartAssociationAsync() {
76 mock_->StartAssociationAsync();
77 return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
78 NewRunnableMethod(
79 this,
80 &NonFrontendDataTypeControllerFake::StartAssociation));
81 }
82 virtual bool StopAssociationAsync() {
83 mock_->StopAssociationAsync();
84 return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
85 NewRunnableMethod(
86 this,
87 &NonFrontendDataTypeControllerFake::StopAssociation));
88 }
89
90 // We mock the following methods because their default implementations do
91 // nothing, but we still want to make sure they're called appropriately.
92 virtual bool StartModels() {
93 return mock_->StartModels();
94 }
95 virtual void StopModels() {
96 mock_->StopModels();
97 }
98 virtual void RecordUnrecoverableError(
99 const tracked_objects::Location& from_here,
100 const std::string& message) {
101 mock_->RecordUnrecoverableError(from_here, message);
102 }
103 virtual void RecordAssociationTime(base::TimeDelta time) {
104 mock_->RecordAssociationTime(time);
105 }
106 virtual void RecordStartFailure(DataTypeController::StartResult result) {
107 mock_->RecordStartFailure(result);
108 }
109 private:
110 NonFrontendDataTypeControllerMock* mock_;
111 };
112
113 class NonFrontendDataTypeControllerTest : public testing::Test {
114 public:
115 NonFrontendDataTypeControllerTest()
116 : ui_thread_(BrowserThread::UI, &message_loop_),
117 db_thread_(BrowserThread::DB),
118 model_associator_(NULL),
119 change_processor_(NULL),
120 signaled_(false) {}
121
122 virtual void SetUp() {
123 EXPECT_CALL(profile_, GetProfileSyncService()).WillRepeatedly(
124 Return(&service_));
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 dtc_mock_.get());
134 }
135
136 virtual void TearDown() {
137 db_thread_.Stop();
138 }
139
140 protected:
141 void SetStartExpectations() {
142 EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(true));
143 model_associator_ = new ModelAssociatorMock();
144 change_processor_ = new ChangeProcessorMock();
145 EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
146 WillOnce(Return(ProfileSyncFactory::SyncComponents(model_associator_,
147 change_processor_)));
148 }
149
150 void SetAssociateExpectations() {
151 EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
152 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
153 WillOnce(Return(true));
154 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
155 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
156 EXPECT_CALL(*model_associator_, AssociateModels()).
157 WillOnce(Return(true));
158 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
159 }
160
161 void SetActivateExpectations(DataTypeController::StartResult result) {
162 EXPECT_CALL(service_, ActivateDataType(_, _));
163 EXPECT_CALL(start_callback_, Run(result,_));
164 }
165
166 void SetStopExpectations() {
167 EXPECT_CALL(*dtc_mock_, StopAssociationAsync());
168 EXPECT_CALL(*dtc_mock_, StopModels());
169 EXPECT_CALL(service_, DeactivateDataType(_, _));
170 EXPECT_CALL(*model_associator_, DisassociateModels());
171 }
172
173 void SetStartFailExpectations(DataTypeController::StartResult result) {
174 EXPECT_CALL(*dtc_mock_, StopModels());
175 EXPECT_CALL(*dtc_mock_, RecordStartFailure(result));
176 EXPECT_CALL(start_callback_, Run(result,_));
177 }
178
179 static void SignalDone(WaitableEvent* done, bool* signaled) {
180 done->Signal();
181 *signaled = true;
182 }
183
184 void WaitForDTC() {
185 WaitableEvent done(false, false);
186 signaled_ = false;
187 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
188 NewRunnableFunction(&NonFrontendDataTypeControllerTest::SignalDone,
189 &done, &signaled_));
190 done.TimedWait(base::TimeDelta::FromMilliseconds(
191 TestTimeouts::action_timeout_ms()));
192 if (!signaled_) {
193 ADD_FAILURE() << "Timed out waiting for DB thread to finish.";
194 }
195 signaled_ = false;
196 MessageLoop::current()->RunAllPending();
197 }
198
199 MessageLoopForUI message_loop_;
200 BrowserThread ui_thread_;
201 BrowserThread db_thread_;
202 scoped_refptr<NonFrontendDataTypeControllerFake> non_frontend_dtc_;
203 scoped_ptr<ProfileSyncFactoryMock> profile_sync_factory_;
204 scoped_refptr<NonFrontendDataTypeControllerMock> dtc_mock_;
205 ProfileMock profile_;
206 ProfileSyncServiceMock service_;
207 ModelAssociatorMock* model_associator_;
208 ChangeProcessorMock* change_processor_;
209 StartCallback start_callback_;
210 bool signaled_;
211 };
212
213 TEST_F(NonFrontendDataTypeControllerTest, StartOk) {
214 SetStartExpectations();
215 SetAssociateExpectations();
216 SetActivateExpectations(DataTypeController::OK);
217 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
218 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
219 WaitForDTC();
220 EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
221 }
222
223 TEST_F(NonFrontendDataTypeControllerTest, StartFirstRun) {
224 SetStartExpectations();
225 EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
226 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
227 WillOnce(Return(true));
228 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
229 WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
230 EXPECT_CALL(*model_associator_, AssociateModels()).
231 WillOnce(Return(true));
232 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
233 SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
234 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
235 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
236 WaitForDTC();
237 EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
238 }
239
240 TEST_F(NonFrontendDataTypeControllerTest, AbortDuringStartModels) {
241 EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(false));
242 SetStartFailExpectations(DataTypeController::ABORTED);
243 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
244 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
245 WaitForDTC();
246 EXPECT_EQ(DataTypeController::MODEL_STARTING, non_frontend_dtc_->state());
247 non_frontend_dtc_->Stop();
248 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
249 }
250
251 TEST_F(NonFrontendDataTypeControllerTest, StartAssociationFailed) {
252 SetStartExpectations();
253 EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
254 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
255 WillOnce(Return(true));
256 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
257 WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
258 EXPECT_CALL(*model_associator_, AssociateModels()).
259 WillOnce(Return(false));
260 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
261 SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
262 // Set up association to fail with an association failed error.
263 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
264 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
265 WaitForDTC();
266 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
267 }
268
269 TEST_F(NonFrontendDataTypeControllerTest,
270 StartAssociationTriggersUnrecoverableError) {
271 SetStartExpectations();
272 SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
273 // Set up association to fail with an unrecoverable error.
274 EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
275 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
276 WillRepeatedly(Return(true));
277 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
278 WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
279 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
280 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
281 WaitForDTC();
282 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
283 }
284
285 TEST_F(NonFrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
286 SetStartExpectations();
287 SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
288 // Set up association to fail with a NEEDS_CRYPTO error.
289 EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
290 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
291 WillRepeatedly(Return(false));
292 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
293 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
294 WaitForDTC();
295 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
296 }
297
298 // Trigger a Stop() call when we check if the model associator has user created
299 // nodes.
300 TEST_F(NonFrontendDataTypeControllerTest, AbortDuringAssociationInactive) {
301 WaitableEvent wait_for_db_thread_pause(false, false);
302 WaitableEvent pause_db_thread(false, false);
303
304 SetStartExpectations();
305 EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
306 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
307 WillOnce(Return(true));
308 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
309 WillOnce(DoAll(
310 SignalEvent(&wait_for_db_thread_pause),
311 WaitOnEvent(&pause_db_thread),
312 SetArgumentPointee<0>(true),
313 Return(true)));
314 EXPECT_CALL(*model_associator_, AbortAssociation()).WillOnce(
315 SignalEvent(&pause_db_thread));
316 EXPECT_CALL(*model_associator_, AssociateModels()).WillOnce(Return(true));
317 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
318 EXPECT_CALL(service_, ActivateDataType(_, _));
319 EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED,_));
320 EXPECT_CALL(*dtc_mock_, RecordStartFailure(DataTypeController::ABORTED));
321 SetStopExpectations();
322 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
323 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
324 wait_for_db_thread_pause.Wait();
325 non_frontend_dtc_->Stop();
326 WaitForDTC();
327 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
328 }
329
330 // Same as above but abort during the Activate call.
331 TEST_F(NonFrontendDataTypeControllerTest, AbortDuringAssociationActivated) {
332 WaitableEvent wait_for_db_thread_pause(false, false);
333 WaitableEvent pause_db_thread(false, false);
334
335 SetStartExpectations();
336 EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
337 EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
338 WillOnce(Return(true));
339 EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
340 WillOnce(DoAll(
341 SetArgumentPointee<0>(true),
342 Return(true)));
343 EXPECT_CALL(*model_associator_, AbortAssociation()).WillOnce(
344 SignalEvent(&pause_db_thread));
345 EXPECT_CALL(*model_associator_, AssociateModels()).
346 WillOnce(Return(true));
347 EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
348 EXPECT_CALL(service_, ActivateDataType(_, _)).WillOnce(DoAll(
349 SignalEvent(&wait_for_db_thread_pause),
350 WaitOnEvent(&pause_db_thread)));
351 EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED,_));
352 EXPECT_CALL(*dtc_mock_, RecordStartFailure(DataTypeController::ABORTED));
353 SetStopExpectations();
354 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
355 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
356 wait_for_db_thread_pause.Wait();
357 non_frontend_dtc_->Stop();
358 WaitForDTC();
359 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
360 }
361
362 TEST_F(NonFrontendDataTypeControllerTest, Stop) {
363 SetStartExpectations();
364 SetAssociateExpectations();
365 SetActivateExpectations(DataTypeController::OK);
366 SetStopExpectations();
367 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
368 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
369 WaitForDTC();
370 EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
371 non_frontend_dtc_->Stop();
372 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
373 }
374
375 TEST_F(NonFrontendDataTypeControllerTest, OnUnrecoverableError) {
376 SetStartExpectations();
377 SetAssociateExpectations();
378 SetActivateExpectations(DataTypeController::OK);
379 EXPECT_CALL(*dtc_mock_, RecordUnrecoverableError(_, "Test"));
380 EXPECT_CALL(service_, OnUnrecoverableError(_,_)).WillOnce(
381 InvokeWithoutArgs(non_frontend_dtc_.get(),
382 &NonFrontendDataTypeController::Stop));
383 SetStopExpectations();
384 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
385 non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
386 WaitForDTC();
387 EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
388 // This should cause non_frontend_dtc_->Stop() to be called.
389 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
390 NewRunnableMethod(
391 non_frontend_dtc_.get(),
392 &NonFrontendDataTypeControllerFake::OnUnrecoverableError,
393 FROM_HERE,
394 std::string("Test")));
395 WaitForDTC();
396 EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
397 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698