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
);
34 using sessions::MockDebugInfoGetter
;
36 // A test fixture for tests exercising download updates functions.
37 class GetUpdatesProcessorTest
: public ::testing::Test
{
39 GetUpdatesProcessorTest() :
40 kTestStartTime(base::TimeTicks::Now()),
41 update_handler_deleter_(&update_handler_map_
) {}
43 void SetUp() override
{
44 AddUpdateHandler(AUTOFILL
);
45 AddUpdateHandler(BOOKMARKS
);
46 AddUpdateHandler(PREFERENCES
);
49 ModelTypeSet
enabled_types() {
50 return enabled_types_
;
53 scoped_ptr
<GetUpdatesProcessor
> BuildGetUpdatesProcessor(
54 const GetUpdatesDelegate
& delegate
) {
55 return scoped_ptr
<GetUpdatesProcessor
>(
56 new GetUpdatesProcessor(&update_handler_map_
, delegate
));
59 void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse
* response
) {
60 ModelTypeSet types
= enabled_types();
62 for (ModelTypeSet::Iterator it
= types
.First(); it
.Good(); it
.Inc()) {
63 sync_pb::DataTypeProgressMarker
* marker
=
64 response
->add_new_progress_marker();
65 marker
->set_data_type_id(GetSpecificsFieldNumberFromModelType(it
.Get()));
66 marker
->set_token("foobarbaz");
67 sync_pb::DataTypeContext
* context
= response
->add_context_mutations();
68 context
->set_data_type_id(GetSpecificsFieldNumberFromModelType(it
.Get()));
69 context
->set_version(1);
70 context
->set_context("context");
73 response
->set_changes_remaining(0);
76 const UpdateHandler
* GetHandler(ModelType type
) {
77 UpdateHandlerMap::iterator it
= update_handler_map_
.find(type
);
78 if (it
== update_handler_map_
.end())
83 const base::TimeTicks kTestStartTime
;
86 MockUpdateHandler
* AddUpdateHandler(ModelType type
) {
87 enabled_types_
.Put(type
);
89 MockUpdateHandler
* handler
= new MockUpdateHandler(type
);
90 update_handler_map_
.insert(std::make_pair(type
, handler
));
96 ModelTypeSet enabled_types_
;
97 UpdateHandlerMap update_handler_map_
;
98 STLValueDeleter
<UpdateHandlerMap
> update_handler_deleter_
;
99 scoped_ptr
<GetUpdatesProcessor
> get_updates_processor_
;
101 DISALLOW_COPY_AND_ASSIGN(GetUpdatesProcessorTest
);
104 // Basic test to make sure nudges are expressed properly in the request.
105 TEST_F(GetUpdatesProcessorTest
, BookmarkNudge
) {
106 sessions::NudgeTracker nudge_tracker
;
107 nudge_tracker
.RecordLocalChange(ModelTypeSet(BOOKMARKS
));
109 sync_pb::ClientToServerMessage message
;
110 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
111 scoped_ptr
<GetUpdatesProcessor
> processor(
112 BuildGetUpdatesProcessor(normal_delegate
));
113 processor
->PrepareGetUpdates(enabled_types(), &message
);
115 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
116 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::LOCAL
,
117 gu_msg
.caller_info().source());
118 EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER
, gu_msg
.get_updates_origin());
119 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
120 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
121 gu_msg
.from_progress_marker(i
).data_type_id());
123 const sync_pb::DataTypeProgressMarker
& progress_marker
=
124 gu_msg
.from_progress_marker(i
);
125 const sync_pb::GetUpdateTriggers
& gu_trigger
=
126 progress_marker
.get_update_triggers();
128 // We perform some basic tests of GU trigger and source fields here. The
129 // more complicated scenarios are tested by the NudgeTracker tests.
130 if (type
== BOOKMARKS
) {
131 EXPECT_TRUE(progress_marker
.has_notification_hint());
132 EXPECT_EQ("", progress_marker
.notification_hint());
133 EXPECT_EQ(1, gu_trigger
.local_modification_nudges());
134 EXPECT_EQ(0, gu_trigger
.datatype_refresh_nudges());
136 EXPECT_FALSE(progress_marker
.has_notification_hint());
137 EXPECT_EQ(0, gu_trigger
.local_modification_nudges());
138 EXPECT_EQ(0, gu_trigger
.datatype_refresh_nudges());
143 // Basic test to ensure invalidation payloads are expressed in the request.
144 TEST_F(GetUpdatesProcessorTest
, NotifyMany
) {
145 sessions::NudgeTracker nudge_tracker
;
146 nudge_tracker
.RecordRemoteInvalidation(
147 AUTOFILL
, BuildInvalidation(1, "autofill_payload"));
148 nudge_tracker
.RecordRemoteInvalidation(
149 BOOKMARKS
, BuildInvalidation(1, "bookmark_payload"));
150 nudge_tracker
.RecordRemoteInvalidation(
151 PREFERENCES
, BuildInvalidation(1, "preferences_payload"));
152 ModelTypeSet notified_types
;
153 notified_types
.Put(AUTOFILL
);
154 notified_types
.Put(BOOKMARKS
);
155 notified_types
.Put(PREFERENCES
);
157 sync_pb::ClientToServerMessage message
;
158 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
159 scoped_ptr
<GetUpdatesProcessor
> processor(
160 BuildGetUpdatesProcessor(normal_delegate
));
161 processor
->PrepareGetUpdates(enabled_types(), &message
);
163 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
164 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION
,
165 gu_msg
.caller_info().source());
166 EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER
, gu_msg
.get_updates_origin());
167 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
168 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
169 gu_msg
.from_progress_marker(i
).data_type_id());
171 const sync_pb::DataTypeProgressMarker
& progress_marker
=
172 gu_msg
.from_progress_marker(i
);
173 const sync_pb::GetUpdateTriggers
& gu_trigger
=
174 progress_marker
.get_update_triggers();
176 // We perform some basic tests of GU trigger and source fields here. The
177 // more complicated scenarios are tested by the NudgeTracker tests.
178 if (notified_types
.Has(type
)) {
179 EXPECT_TRUE(progress_marker
.has_notification_hint());
180 EXPECT_FALSE(progress_marker
.notification_hint().empty());
181 EXPECT_EQ(1, gu_trigger
.notification_hint_size());
183 EXPECT_FALSE(progress_marker
.has_notification_hint());
184 EXPECT_EQ(0, gu_trigger
.notification_hint_size());
189 // Basic test to ensure initial sync requests are expressed in the request.
190 TEST_F(GetUpdatesProcessorTest
, InitialSyncRequest
) {
191 sessions::NudgeTracker nudge_tracker
;
192 nudge_tracker
.RecordInitialSyncRequired(AUTOFILL
);
193 nudge_tracker
.RecordInitialSyncRequired(PREFERENCES
);
195 ModelTypeSet initial_sync_types
= ModelTypeSet(AUTOFILL
, PREFERENCES
);
197 sync_pb::ClientToServerMessage message
;
198 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
199 scoped_ptr
<GetUpdatesProcessor
> processor(
200 BuildGetUpdatesProcessor(normal_delegate
));
201 processor
->PrepareGetUpdates(enabled_types(), &message
);
203 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
204 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH
,
205 gu_msg
.caller_info().source());
206 EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER
, gu_msg
.get_updates_origin());
207 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
208 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
209 gu_msg
.from_progress_marker(i
).data_type_id());
211 const sync_pb::DataTypeProgressMarker
& progress_marker
=
212 gu_msg
.from_progress_marker(i
);
213 const sync_pb::GetUpdateTriggers
& gu_trigger
=
214 progress_marker
.get_update_triggers();
216 // We perform some basic tests of GU trigger and source fields here. The
217 // more complicated scenarios are tested by the NudgeTracker tests.
218 if (initial_sync_types
.Has(type
)) {
219 EXPECT_TRUE(gu_trigger
.initial_sync_in_progress());
221 EXPECT_TRUE(gu_trigger
.has_initial_sync_in_progress());
222 EXPECT_FALSE(gu_trigger
.initial_sync_in_progress());
227 TEST_F(GetUpdatesProcessorTest
, ConfigureTest
) {
228 sync_pb::ClientToServerMessage message
;
229 ConfigureGetUpdatesDelegate
configure_delegate(
230 sync_pb::GetUpdatesCallerInfo::RECONFIGURATION
);
231 scoped_ptr
<GetUpdatesProcessor
> processor(
232 BuildGetUpdatesProcessor(configure_delegate
));
233 processor
->PrepareGetUpdates(enabled_types(), &message
);
235 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
236 EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION
, gu_msg
.get_updates_origin());
237 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION
,
238 gu_msg
.caller_info().source());
240 ModelTypeSet progress_types
;
241 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
242 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
243 gu_msg
.from_progress_marker(i
).data_type_id());
244 progress_types
.Put(type
);
246 EXPECT_TRUE(enabled_types().Equals(progress_types
));
249 TEST_F(GetUpdatesProcessorTest
, PollTest
) {
250 sync_pb::ClientToServerMessage message
;
251 PollGetUpdatesDelegate poll_delegate
;
252 scoped_ptr
<GetUpdatesProcessor
> processor(
253 BuildGetUpdatesProcessor(poll_delegate
));
254 processor
->PrepareGetUpdates(enabled_types(), &message
);
256 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
257 EXPECT_EQ(sync_pb::SyncEnums::PERIODIC
, gu_msg
.get_updates_origin());
258 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::PERIODIC
,
259 gu_msg
.caller_info().source());
261 ModelTypeSet progress_types
;
262 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
263 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
264 gu_msg
.from_progress_marker(i
).data_type_id());
265 progress_types
.Put(type
);
267 EXPECT_TRUE(enabled_types().Equals(progress_types
));
270 TEST_F(GetUpdatesProcessorTest
, RetryTest
) {
271 sessions::NudgeTracker nudge_tracker
;
274 base::TimeTicks t1
= kTestStartTime
;
275 nudge_tracker
.SetNextRetryTime(t1
);
277 // Get the nudge tracker to think the retry is due.
278 nudge_tracker
.SetSyncCycleStartTime(t1
+ base::TimeDelta::FromSeconds(1));
280 sync_pb::ClientToServerMessage message
;
281 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
282 scoped_ptr
<GetUpdatesProcessor
> processor(
283 BuildGetUpdatesProcessor(normal_delegate
));
284 processor
->PrepareGetUpdates(enabled_types(), &message
);
286 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
287 EXPECT_EQ(sync_pb::SyncEnums::RETRY
, gu_msg
.get_updates_origin());
288 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RETRY
,
289 gu_msg
.caller_info().source());
290 EXPECT_TRUE(gu_msg
.is_retry());
292 ModelTypeSet progress_types
;
293 for (int i
= 0; i
< gu_msg
.from_progress_marker_size(); ++i
) {
294 syncer::ModelType type
= GetModelTypeFromSpecificsFieldNumber(
295 gu_msg
.from_progress_marker(i
).data_type_id());
296 progress_types
.Put(type
);
298 EXPECT_TRUE(enabled_types().Equals(progress_types
));
301 TEST_F(GetUpdatesProcessorTest
, NudgeWithRetryTest
) {
302 sessions::NudgeTracker nudge_tracker
;
305 base::TimeTicks t1
= kTestStartTime
;
306 nudge_tracker
.SetNextRetryTime(t1
);
308 // Get the nudge tracker to think the retry is due.
309 nudge_tracker
.SetSyncCycleStartTime(t1
+ base::TimeDelta::FromSeconds(1));
311 // Record a local change, too.
312 nudge_tracker
.RecordLocalChange(ModelTypeSet(BOOKMARKS
));
314 sync_pb::ClientToServerMessage message
;
315 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
316 scoped_ptr
<GetUpdatesProcessor
> processor(
317 BuildGetUpdatesProcessor(normal_delegate
));
318 processor
->PrepareGetUpdates(enabled_types(), &message
);
320 const sync_pb::GetUpdatesMessage
& gu_msg
= message
.get_updates();
321 EXPECT_NE(sync_pb::SyncEnums::RETRY
, gu_msg
.get_updates_origin());
322 EXPECT_NE(sync_pb::GetUpdatesCallerInfo::RETRY
,
323 gu_msg
.caller_info().source());
325 EXPECT_TRUE(gu_msg
.is_retry());
328 // Verify that a bogus response message is detected.
329 TEST_F(GetUpdatesProcessorTest
, InvalidResponse
) {
330 sync_pb::GetUpdatesResponse gu_response
;
331 InitFakeUpdateResponse(&gu_response
);
333 // This field is essential for making the client stop looping. If it's unset
334 // then something is very wrong. The client should detect this.
335 gu_response
.clear_changes_remaining();
337 sessions::NudgeTracker nudge_tracker
;
338 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
339 sessions::StatusController status
;
340 scoped_ptr
<GetUpdatesProcessor
> processor(
341 BuildGetUpdatesProcessor(normal_delegate
));
342 SyncerError error
= processor
->ProcessResponse(gu_response
,
345 EXPECT_EQ(error
, SERVER_RESPONSE_VALIDATION_FAILED
);
348 // Verify that we correctly detect when there's more work to be done.
349 TEST_F(GetUpdatesProcessorTest
, MoreToDownloadResponse
) {
350 sync_pb::GetUpdatesResponse gu_response
;
351 InitFakeUpdateResponse(&gu_response
);
352 gu_response
.set_changes_remaining(1);
354 sessions::NudgeTracker nudge_tracker
;
355 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
356 sessions::StatusController status
;
357 scoped_ptr
<GetUpdatesProcessor
> processor(
358 BuildGetUpdatesProcessor(normal_delegate
));
359 SyncerError error
= processor
->ProcessResponse(gu_response
,
362 EXPECT_EQ(error
, SERVER_MORE_TO_DOWNLOAD
);
365 // A simple scenario: No updates returned and nothing more to download.
366 TEST_F(GetUpdatesProcessorTest
, NormalResponseTest
) {
367 sync_pb::GetUpdatesResponse gu_response
;
368 InitFakeUpdateResponse(&gu_response
);
369 gu_response
.set_changes_remaining(0);
371 sessions::NudgeTracker nudge_tracker
;
372 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
373 sessions::StatusController status
;
374 scoped_ptr
<GetUpdatesProcessor
> processor(
375 BuildGetUpdatesProcessor(normal_delegate
));
376 SyncerError error
= processor
->ProcessResponse(gu_response
,
379 EXPECT_EQ(error
, SYNCER_OK
);
382 // Variant of GetUpdatesProcessor test designed to test update application.
384 // Maintains two enabled types, but requests that updates be applied for only
386 class GetUpdatesProcessorApplyUpdatesTest
: public GetUpdatesProcessorTest
{
388 GetUpdatesProcessorApplyUpdatesTest() {}
389 ~GetUpdatesProcessorApplyUpdatesTest() override
{}
391 void SetUp() override
{
392 bookmarks_handler_
= AddUpdateHandler(BOOKMARKS
);
393 autofill_handler_
= AddUpdateHandler(AUTOFILL
);
396 ModelTypeSet
GetGuTypes() {
397 return ModelTypeSet(AUTOFILL
);
400 MockUpdateHandler
* GetNonAppliedHandler() {
401 return bookmarks_handler_
;
404 MockUpdateHandler
* GetAppliedHandler() {
405 return autofill_handler_
;
409 MockUpdateHandler
* bookmarks_handler_
;
410 MockUpdateHandler
* autofill_handler_
;
413 // Verify that a normal cycle applies updates non-passively to the specified
415 TEST_F(GetUpdatesProcessorApplyUpdatesTest
, Normal
) {
416 sessions::NudgeTracker nudge_tracker
;
417 NormalGetUpdatesDelegate
normal_delegate(nudge_tracker
);
418 scoped_ptr
<GetUpdatesProcessor
> processor(
419 BuildGetUpdatesProcessor(normal_delegate
));
421 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
422 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
424 sessions::StatusController status
;
425 processor
->ApplyUpdates(GetGuTypes(), &status
);
427 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
428 EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
430 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
431 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
434 // Verify that a configure cycle applies updates passively to the specified
436 TEST_F(GetUpdatesProcessorApplyUpdatesTest
, Configure
) {
437 ConfigureGetUpdatesDelegate
configure_delegate(
438 sync_pb::GetUpdatesCallerInfo::RECONFIGURATION
);
439 scoped_ptr
<GetUpdatesProcessor
> processor(
440 BuildGetUpdatesProcessor(configure_delegate
));
442 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
443 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
445 sessions::StatusController status
;
446 processor
->ApplyUpdates(GetGuTypes(), &status
);
448 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
449 EXPECT_EQ(1, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
451 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
452 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
455 // Verify that a poll cycle applies updates non-passively to the specified
457 TEST_F(GetUpdatesProcessorApplyUpdatesTest
, Poll
) {
458 PollGetUpdatesDelegate poll_delegate
;
459 scoped_ptr
<GetUpdatesProcessor
> processor(
460 BuildGetUpdatesProcessor(poll_delegate
));
462 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
463 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
465 sessions::StatusController status
;
466 processor
->ApplyUpdates(GetGuTypes(), &status
);
468 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
469 EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
471 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
472 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
475 class DownloadUpdatesDebugInfoTest
: public ::testing::Test
{
477 DownloadUpdatesDebugInfoTest() {}
478 ~DownloadUpdatesDebugInfoTest() override
{}
480 sessions::StatusController
* status() {
484 sessions::DebugInfoGetter
* debug_info_getter() {
485 return &debug_info_getter_
;
488 void AddDebugEvent() {
489 debug_info_getter_
.AddDebugEvent();
493 sessions::StatusController status_
;
494 MockDebugInfoGetter debug_info_getter_
;
497 // Verify CopyClientDebugInfo when there are no events to upload.
498 TEST_F(DownloadUpdatesDebugInfoTest
, VerifyCopyClientDebugInfo_Empty
) {
499 sync_pb::DebugInfo debug_info
;
500 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info
);
501 EXPECT_EQ(0, debug_info
.events_size());
504 TEST_F(DownloadUpdatesDebugInfoTest
, VerifyCopyOverwrites
) {
505 sync_pb::DebugInfo debug_info
;
507 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info
);
508 EXPECT_EQ(1, debug_info
.events_size());
509 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info
);
510 EXPECT_EQ(1, debug_info
.events_size());
513 } // namespace syncer