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.
5 #include "sync/engine/get_updates_processor.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/stl_util.h"
9 #include "sync/engine/get_updates_delegate.h"
10 #include "sync/engine/update_handler.h"
11 #include "sync/internal_api/public/base/model_type_test_util.h"
12 #include "sync/protocol/sync.pb.h"
13 #include "sync/sessions/debug_info_getter.h"
14 #include "sync/sessions/nudge_tracker.h"
15 #include "sync/sessions/status_controller.h"
16 #include "sync/test/engine/fake_model_worker.h"
17 #include "sync/test/engine/mock_update_handler.h"
18 #include "sync/test/mock_invalidation.h"
19 #include "sync/test/sessions/mock_debug_info_getter.h"
20 #include "testing/gtest/include/gtest/gtest.h"
26 scoped_ptr
<InvalidationInterface
> BuildInvalidation(
28 const std::string
& payload
) {
29 return MockInvalidation::Build(version
, payload
)
30 .PassAs
<InvalidationInterface
>();
35 using sessions::MockDebugInfoGetter
;
37 // A test fixture for tests exercising download updates functions.
38 class GetUpdatesProcessorTest
: public ::testing::Test
{
40 GetUpdatesProcessorTest() :
41 kTestStartTime(base::TimeTicks::Now()),
42 update_handler_deleter_(&update_handler_map_
) {}
44 virtual void SetUp() {
45 AddUpdateHandler(AUTOFILL
);
46 AddUpdateHandler(BOOKMARKS
);
47 AddUpdateHandler(PREFERENCES
);
50 ModelTypeSet
enabled_types() {
51 return enabled_types_
;
54 scoped_ptr
<GetUpdatesProcessor
> BuildGetUpdatesProcessor(
55 const GetUpdatesDelegate
& delegate
) {
56 return scoped_ptr
<GetUpdatesProcessor
>(
57 new GetUpdatesProcessor(&update_handler_map_
, delegate
));
60 void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse
* response
) {
61 ModelTypeSet types
= enabled_types();
63 for (ModelTypeSet::Iterator it
= types
.First(); it
.Good(); it
.Inc()) {
64 sync_pb::DataTypeProgressMarker
* marker
=
65 response
->add_new_progress_marker();
66 marker
->set_data_type_id(GetSpecificsFieldNumberFromModelType(it
.Get()));
67 marker
->set_token("foobarbaz");
68 sync_pb::DataTypeContext
* context
= response
->add_context_mutations();
69 context
->set_data_type_id(GetSpecificsFieldNumberFromModelType(it
.Get()));
70 context
->set_version(1);
71 context
->set_context("context");
74 response
->set_changes_remaining(0);
77 const UpdateHandler
* GetHandler(ModelType type
) {
78 UpdateHandlerMap::iterator it
= update_handler_map_
.find(type
);
79 if (it
== update_handler_map_
.end())
84 const base::TimeTicks kTestStartTime
;
87 MockUpdateHandler
* AddUpdateHandler(ModelType type
) {
88 enabled_types_
.Put(type
);
90 MockUpdateHandler
* handler
= new MockUpdateHandler(type
);
91 update_handler_map_
.insert(std::make_pair(type
, handler
));
97 ModelTypeSet enabled_types_
;
98 UpdateHandlerMap update_handler_map_
;
99 STLValueDeleter
<UpdateHandlerMap
> update_handler_deleter_
;
100 scoped_ptr
<GetUpdatesProcessor
> get_updates_processor_
;
102 DISALLOW_COPY_AND_ASSIGN(GetUpdatesProcessorTest
);
105 // Basic test to make sure nudges are expressed properly in the request.
106 TEST_F(GetUpdatesProcessorTest
, BookmarkNudge
) {
107 sessions::NudgeTracker nudge_tracker
;
108 nudge_tracker
.RecordLocalChange(ModelTypeSet(BOOKMARKS
));
110 sync_pb::ClientToServerMessage message
;
111 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
112 scoped_ptr
<GetUpdatesProcessor
> processor(
113 BuildGetUpdatesProcessor(normal_delegate
));
114 processor
->PrepareGetUpdates(enabled_types(), &message
);
116 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
117 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::LOCAL
,
118 gu_msg
.caller_info().source());
119 EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER
, gu_msg
.get_updates_origin());
120 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
121 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
122 gu_msg
.from_progress_marker(i
).data_type_id());
124 const sync_pb::DataTypeProgressMarker
& progress_marker
=
125 gu_msg
.from_progress_marker(i
);
126 const sync_pb::GetUpdateTriggers
& gu_trigger
=
127 progress_marker
.get_update_triggers();
129 // We perform some basic tests of GU trigger and source fields here. The
130 // more complicated scenarios are tested by the NudgeTracker tests.
131 if (type
== BOOKMARKS
) {
132 EXPECT_TRUE(progress_marker
.has_notification_hint());
133 EXPECT_EQ("", progress_marker
.notification_hint());
134 EXPECT_EQ(1, gu_trigger
.local_modification_nudges());
135 EXPECT_EQ(0, gu_trigger
.datatype_refresh_nudges());
137 EXPECT_FALSE(progress_marker
.has_notification_hint());
138 EXPECT_EQ(0, gu_trigger
.local_modification_nudges());
139 EXPECT_EQ(0, gu_trigger
.datatype_refresh_nudges());
144 // Basic test to ensure invalidation payloads are expressed in the request.
145 TEST_F(GetUpdatesProcessorTest
, NotifyMany
) {
146 sessions::NudgeTracker nudge_tracker
;
147 nudge_tracker
.RecordRemoteInvalidation(
148 AUTOFILL
, BuildInvalidation(1, "autofill_payload"));
149 nudge_tracker
.RecordRemoteInvalidation(
150 BOOKMARKS
, BuildInvalidation(1, "bookmark_payload"));
151 nudge_tracker
.RecordRemoteInvalidation(
152 PREFERENCES
, BuildInvalidation(1, "preferences_payload"));
153 ModelTypeSet notified_types
;
154 notified_types
.Put(AUTOFILL
);
155 notified_types
.Put(BOOKMARKS
);
156 notified_types
.Put(PREFERENCES
);
158 sync_pb::ClientToServerMessage message
;
159 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
160 scoped_ptr
<GetUpdatesProcessor
> processor(
161 BuildGetUpdatesProcessor(normal_delegate
));
162 processor
->PrepareGetUpdates(enabled_types(), &message
);
164 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
165 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION
,
166 gu_msg
.caller_info().source());
167 EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER
, gu_msg
.get_updates_origin());
168 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
169 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
170 gu_msg
.from_progress_marker(i
).data_type_id());
172 const sync_pb::DataTypeProgressMarker
& progress_marker
=
173 gu_msg
.from_progress_marker(i
);
174 const sync_pb::GetUpdateTriggers
& gu_trigger
=
175 progress_marker
.get_update_triggers();
177 // We perform some basic tests of GU trigger and source fields here. The
178 // more complicated scenarios are tested by the NudgeTracker tests.
179 if (notified_types
.Has(type
)) {
180 EXPECT_TRUE(progress_marker
.has_notification_hint());
181 EXPECT_FALSE(progress_marker
.notification_hint().empty());
182 EXPECT_EQ(1, gu_trigger
.notification_hint_size());
184 EXPECT_FALSE(progress_marker
.has_notification_hint());
185 EXPECT_EQ(0, gu_trigger
.notification_hint_size());
190 // Basic test to ensure initial sync requests are expressed in the request.
191 TEST_F(GetUpdatesProcessorTest
, InitialSyncRequest
) {
192 sessions::NudgeTracker nudge_tracker
;
193 nudge_tracker
.RecordInitialSyncRequired(AUTOFILL
);
194 nudge_tracker
.RecordInitialSyncRequired(PREFERENCES
);
196 ModelTypeSet initial_sync_types
= ModelTypeSet(AUTOFILL
, PREFERENCES
);
198 sync_pb::ClientToServerMessage message
;
199 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
200 scoped_ptr
<GetUpdatesProcessor
> processor(
201 BuildGetUpdatesProcessor(normal_delegate
));
202 processor
->PrepareGetUpdates(enabled_types(), &message
);
204 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
205 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH
,
206 gu_msg
.caller_info().source());
207 EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER
, gu_msg
.get_updates_origin());
208 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
209 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
210 gu_msg
.from_progress_marker(i
).data_type_id());
212 const sync_pb::DataTypeProgressMarker
& progress_marker
=
213 gu_msg
.from_progress_marker(i
);
214 const sync_pb::GetUpdateTriggers
& gu_trigger
=
215 progress_marker
.get_update_triggers();
217 // We perform some basic tests of GU trigger and source fields here. The
218 // more complicated scenarios are tested by the NudgeTracker tests.
219 if (initial_sync_types
.Has(type
)) {
220 EXPECT_TRUE(gu_trigger
.initial_sync_in_progress());
222 EXPECT_TRUE(gu_trigger
.has_initial_sync_in_progress());
223 EXPECT_FALSE(gu_trigger
.initial_sync_in_progress());
228 TEST_F(GetUpdatesProcessorTest
, ConfigureTest
) {
229 sync_pb::ClientToServerMessage message
;
230 ConfigureGetUpdatesDelegate
configure_delegate(
231 sync_pb::GetUpdatesCallerInfo::RECONFIGURATION
);
232 scoped_ptr
<GetUpdatesProcessor
> processor(
233 BuildGetUpdatesProcessor(configure_delegate
));
234 processor
->PrepareGetUpdates(enabled_types(), &message
);
236 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
237 EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION
, gu_msg
.get_updates_origin());
238 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION
,
239 gu_msg
.caller_info().source());
241 ModelTypeSet progress_types
;
242 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
243 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
244 gu_msg
.from_progress_marker(i
).data_type_id());
245 progress_types
.Put(type
);
247 EXPECT_TRUE(enabled_types().Equals(progress_types
));
250 TEST_F(GetUpdatesProcessorTest
, PollTest
) {
251 sync_pb::ClientToServerMessage message
;
252 PollGetUpdatesDelegate poll_delegate
;
253 scoped_ptr
<GetUpdatesProcessor
> processor(
254 BuildGetUpdatesProcessor(poll_delegate
));
255 processor
->PrepareGetUpdates(enabled_types(), &message
);
257 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
258 EXPECT_EQ(sync_pb::SyncEnums::PERIODIC
, gu_msg
.get_updates_origin());
259 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::PERIODIC
,
260 gu_msg
.caller_info().source());
262 ModelTypeSet progress_types
;
263 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
264 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
265 gu_msg
.from_progress_marker(i
).data_type_id());
266 progress_types
.Put(type
);
268 EXPECT_TRUE(enabled_types().Equals(progress_types
));
271 TEST_F(GetUpdatesProcessorTest
, RetryTest
) {
272 sessions::NudgeTracker nudge_tracker
;
275 base::TimeTicks t1
= kTestStartTime
;
276 nudge_tracker
.SetNextRetryTime(t1
);
278 // Get the nudge tracker to think the retry is due.
279 nudge_tracker
.SetSyncCycleStartTime(t1
+ base::TimeDelta::FromSeconds(1));
281 sync_pb::ClientToServerMessage message
;
282 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
283 scoped_ptr
<GetUpdatesProcessor
> processor(
284 BuildGetUpdatesProcessor(normal_delegate
));
285 processor
->PrepareGetUpdates(enabled_types(), &message
);
287 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
288 EXPECT_EQ(sync_pb::SyncEnums::RETRY
, gu_msg
.get_updates_origin());
289 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RETRY
,
290 gu_msg
.caller_info().source());
291 EXPECT_TRUE(gu_msg
.is_retry());
293 ModelTypeSet progress_types
;
294 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
295 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
296 gu_msg
.from_progress_marker(i
).data_type_id());
297 progress_types
.Put(type
);
299 EXPECT_TRUE(enabled_types().Equals(progress_types
));
302 TEST_F(GetUpdatesProcessorTest
, NudgeWithRetryTest
) {
303 sessions::NudgeTracker nudge_tracker
;
306 base::TimeTicks t1
= kTestStartTime
;
307 nudge_tracker
.SetNextRetryTime(t1
);
309 // Get the nudge tracker to think the retry is due.
310 nudge_tracker
.SetSyncCycleStartTime(t1
+ base::TimeDelta::FromSeconds(1));
312 // Record a local change, too.
313 nudge_tracker
.RecordLocalChange(ModelTypeSet(BOOKMARKS
));
315 sync_pb::ClientToServerMessage message
;
316 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
317 scoped_ptr
<GetUpdatesProcessor
> processor(
318 BuildGetUpdatesProcessor(normal_delegate
));
319 processor
->PrepareGetUpdates(enabled_types(), &message
);
321 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
322 EXPECT_NE(sync_pb::SyncEnums::RETRY
, gu_msg
.get_updates_origin());
323 EXPECT_NE(sync_pb::GetUpdatesCallerInfo::RETRY
,
324 gu_msg
.caller_info().source());
326 EXPECT_TRUE(gu_msg
.is_retry());
329 // Verify that a bogus response message is detected.
330 TEST_F(GetUpdatesProcessorTest
, InvalidResponse
) {
331 sync_pb::GetUpdatesResponse gu_response
;
332 InitFakeUpdateResponse(&gu_response
);
334 // This field is essential for making the client stop looping. If it's unset
335 // then something is very wrong. The client should detect this.
336 gu_response
.clear_changes_remaining();
338 sessions::NudgeTracker nudge_tracker
;
339 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
340 sessions::StatusController status
;
341 scoped_ptr
<GetUpdatesProcessor
> processor(
342 BuildGetUpdatesProcessor(normal_delegate
));
343 SyncerError error
= processor
->ProcessResponse(gu_response
,
346 EXPECT_EQ(error
, SERVER_RESPONSE_VALIDATION_FAILED
);
349 // Verify that we correctly detect when there's more work to be done.
350 TEST_F(GetUpdatesProcessorTest
, MoreToDownloadResponse
) {
351 sync_pb::GetUpdatesResponse gu_response
;
352 InitFakeUpdateResponse(&gu_response
);
353 gu_response
.set_changes_remaining(1);
355 sessions::NudgeTracker nudge_tracker
;
356 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
357 sessions::StatusController status
;
358 scoped_ptr
<GetUpdatesProcessor
> processor(
359 BuildGetUpdatesProcessor(normal_delegate
));
360 SyncerError error
= processor
->ProcessResponse(gu_response
,
363 EXPECT_EQ(error
, SERVER_MORE_TO_DOWNLOAD
);
366 // A simple scenario: No updates returned and nothing more to download.
367 TEST_F(GetUpdatesProcessorTest
, NormalResponseTest
) {
368 sync_pb::GetUpdatesResponse gu_response
;
369 InitFakeUpdateResponse(&gu_response
);
370 gu_response
.set_changes_remaining(0);
372 sessions::NudgeTracker nudge_tracker
;
373 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
374 sessions::StatusController status
;
375 scoped_ptr
<GetUpdatesProcessor
> processor(
376 BuildGetUpdatesProcessor(normal_delegate
));
377 SyncerError error
= processor
->ProcessResponse(gu_response
,
380 EXPECT_EQ(error
, SYNCER_OK
);
383 // Variant of GetUpdatesProcessor test designed to test update application.
385 // Maintains two enabled types, but requests that updates be applied for only
387 class GetUpdatesProcessorApplyUpdatesTest
: public GetUpdatesProcessorTest
{
389 GetUpdatesProcessorApplyUpdatesTest() {}
390 virtual ~GetUpdatesProcessorApplyUpdatesTest() {}
392 virtual void SetUp() OVERRIDE
{
393 bookmarks_handler_
= AddUpdateHandler(BOOKMARKS
);
394 autofill_handler_
= AddUpdateHandler(AUTOFILL
);
397 ModelTypeSet
GetGuTypes() {
398 return ModelTypeSet(AUTOFILL
);
401 MockUpdateHandler
* GetNonAppliedHandler() {
402 return bookmarks_handler_
;
405 MockUpdateHandler
* GetAppliedHandler() {
406 return autofill_handler_
;
410 MockUpdateHandler
* bookmarks_handler_
;
411 MockUpdateHandler
* autofill_handler_
;
414 // Verify that a normal cycle applies updates non-passively to the specified
416 TEST_F(GetUpdatesProcessorApplyUpdatesTest
, Normal
) {
417 sessions::NudgeTracker nudge_tracker
;
418 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
419 scoped_ptr
<GetUpdatesProcessor
> processor(
420 BuildGetUpdatesProcessor(normal_delegate
));
422 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
423 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
425 sessions::StatusController status
;
426 processor
->ApplyUpdates(GetGuTypes(), &status
);
428 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
429 EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
431 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
432 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
435 // Verify that a configure cycle applies updates passively to the specified
437 TEST_F(GetUpdatesProcessorApplyUpdatesTest
, Configure
) {
438 ConfigureGetUpdatesDelegate
configure_delegate(
439 sync_pb::GetUpdatesCallerInfo::RECONFIGURATION
);
440 scoped_ptr
<GetUpdatesProcessor
> processor(
441 BuildGetUpdatesProcessor(configure_delegate
));
443 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
444 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
446 sessions::StatusController status
;
447 processor
->ApplyUpdates(GetGuTypes(), &status
);
449 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
450 EXPECT_EQ(1, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
452 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
453 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
456 // Verify that a poll cycle applies updates non-passively to the specified
458 TEST_F(GetUpdatesProcessorApplyUpdatesTest
, Poll
) {
459 PollGetUpdatesDelegate poll_delegate
;
460 scoped_ptr
<GetUpdatesProcessor
> processor(
461 BuildGetUpdatesProcessor(poll_delegate
));
463 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
464 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
466 sessions::StatusController status
;
467 processor
->ApplyUpdates(GetGuTypes(), &status
);
469 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
470 EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
472 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
473 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
476 class DownloadUpdatesDebugInfoTest
: public ::testing::Test
{
478 DownloadUpdatesDebugInfoTest() {}
479 virtual ~DownloadUpdatesDebugInfoTest() {}
481 sessions::StatusController
* status() {
485 sessions::DebugInfoGetter
* debug_info_getter() {
486 return &debug_info_getter_
;
489 void AddDebugEvent() {
490 debug_info_getter_
.AddDebugEvent();
494 sessions::StatusController status_
;
495 MockDebugInfoGetter debug_info_getter_
;
498 // Verify CopyClientDebugInfo when there are no events to upload.
499 TEST_F(DownloadUpdatesDebugInfoTest
, VerifyCopyClientDebugInfo_Empty
) {
500 sync_pb::DebugInfo debug_info
;
501 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info
);
502 EXPECT_EQ(0, debug_info
.events_size());
505 TEST_F(DownloadUpdatesDebugInfoTest
, VerifyCopyOverwrites
) {
506 sync_pb::DebugInfo debug_info
;
508 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info
);
509 EXPECT_EQ(1, debug_info
.events_size());
510 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info
);
511 EXPECT_EQ(1, debug_info
.events_size());
514 } // namespace syncer