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/sessions/mock_debug_info_getter.h"
19 #include "testing/gtest/include/gtest/gtest.h"
23 using sessions::MockDebugInfoGetter;
25 // A test fixture for tests exercising download updates functions.
26 class GetUpdatesProcessorTest : public ::testing::Test {
28 GetUpdatesProcessorTest() :
29 kTestStartTime(base::TimeTicks::Now()),
30 update_handler_deleter_(&update_handler_map_) {}
32 virtual void SetUp() {
33 AddUpdateHandler(AUTOFILL);
34 AddUpdateHandler(BOOKMARKS);
35 AddUpdateHandler(PREFERENCES);
38 ModelTypeSet enabled_types() {
39 return enabled_types_;
42 scoped_ptr<GetUpdatesProcessor> BuildGetUpdatesProcessor(
43 const GetUpdatesDelegate& delegate) {
44 return scoped_ptr<GetUpdatesProcessor>(
45 new GetUpdatesProcessor(&update_handler_map_, delegate));
48 void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse* response) {
49 ModelTypeSet types = enabled_types();
51 for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
52 sync_pb::DataTypeProgressMarker* marker =
53 response->add_new_progress_marker();
54 marker->set_data_type_id(GetSpecificsFieldNumberFromModelType(it.Get()));
55 marker->set_token("foobarbaz");
56 sync_pb::DataTypeContext* context = response->add_context_mutations();
57 context->set_data_type_id(GetSpecificsFieldNumberFromModelType(it.Get()));
58 context->set_version(1);
59 context->set_context("context");
62 response->set_changes_remaining(0);
65 const UpdateHandler* GetHandler(ModelType type) {
66 UpdateHandlerMap::iterator it = update_handler_map_.find(type);
67 if (it == update_handler_map_.end())
72 const base::TimeTicks kTestStartTime;
75 MockUpdateHandler* AddUpdateHandler(ModelType type) {
76 enabled_types_.Put(type);
78 MockUpdateHandler* handler = new MockUpdateHandler(type);
79 update_handler_map_.insert(std::make_pair(type, handler));
85 ModelTypeSet enabled_types_;
86 UpdateHandlerMap update_handler_map_;
87 STLValueDeleter<UpdateHandlerMap> update_handler_deleter_;
88 scoped_ptr<GetUpdatesProcessor> get_updates_processor_;
90 DISALLOW_COPY_AND_ASSIGN(GetUpdatesProcessorTest);
93 // Basic test to make sure nudges are expressed properly in the request.
94 TEST_F(GetUpdatesProcessorTest, BookmarkNudge) {
95 sessions::NudgeTracker nudge_tracker;
96 nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS));
98 sync_pb::ClientToServerMessage message;
99 NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
100 scoped_ptr<GetUpdatesProcessor> processor(
101 BuildGetUpdatesProcessor(normal_delegate));
102 processor->PrepareGetUpdates(enabled_types(), &message);
104 const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
105 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::LOCAL,
106 gu_msg.caller_info().source());
107 EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
108 for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
109 syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
110 gu_msg.from_progress_marker(i).data_type_id());
112 const sync_pb::DataTypeProgressMarker& progress_marker =
113 gu_msg.from_progress_marker(i);
114 const sync_pb::GetUpdateTriggers& gu_trigger =
115 progress_marker.get_update_triggers();
117 // We perform some basic tests of GU trigger and source fields here. The
118 // more complicated scenarios are tested by the NudgeTracker tests.
119 if (type == BOOKMARKS) {
120 EXPECT_TRUE(progress_marker.has_notification_hint());
121 EXPECT_EQ("", progress_marker.notification_hint());
122 EXPECT_EQ(1, gu_trigger.local_modification_nudges());
123 EXPECT_EQ(0, gu_trigger.datatype_refresh_nudges());
125 EXPECT_FALSE(progress_marker.has_notification_hint());
126 EXPECT_EQ(0, gu_trigger.local_modification_nudges());
127 EXPECT_EQ(0, gu_trigger.datatype_refresh_nudges());
132 // Basic test to ensure invalidation payloads are expressed in the request.
133 TEST_F(GetUpdatesProcessorTest, NotifyMany) {
134 sessions::NudgeTracker nudge_tracker;
135 nudge_tracker.RecordRemoteInvalidation(
136 BuildInvalidationMap(AUTOFILL, 1, "autofill_payload"));
137 nudge_tracker.RecordRemoteInvalidation(
138 BuildInvalidationMap(BOOKMARKS, 1, "bookmark_payload"));
139 nudge_tracker.RecordRemoteInvalidation(
140 BuildInvalidationMap(PREFERENCES, 1, "preferences_payload"));
141 ModelTypeSet notified_types;
142 notified_types.Put(AUTOFILL);
143 notified_types.Put(BOOKMARKS);
144 notified_types.Put(PREFERENCES);
146 sync_pb::ClientToServerMessage message;
147 NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
148 scoped_ptr<GetUpdatesProcessor> processor(
149 BuildGetUpdatesProcessor(normal_delegate));
150 processor->PrepareGetUpdates(enabled_types(), &message);
152 const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
153 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION,
154 gu_msg.caller_info().source());
155 EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
156 for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
157 syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
158 gu_msg.from_progress_marker(i).data_type_id());
160 const sync_pb::DataTypeProgressMarker& progress_marker =
161 gu_msg.from_progress_marker(i);
162 const sync_pb::GetUpdateTriggers& gu_trigger =
163 progress_marker.get_update_triggers();
165 // We perform some basic tests of GU trigger and source fields here. The
166 // more complicated scenarios are tested by the NudgeTracker tests.
167 if (notified_types.Has(type)) {
168 EXPECT_TRUE(progress_marker.has_notification_hint());
169 EXPECT_FALSE(progress_marker.notification_hint().empty());
170 EXPECT_EQ(1, gu_trigger.notification_hint_size());
172 EXPECT_FALSE(progress_marker.has_notification_hint());
173 EXPECT_EQ(0, gu_trigger.notification_hint_size());
178 TEST_F(GetUpdatesProcessorTest, ConfigureTest) {
179 sync_pb::ClientToServerMessage message;
180 ConfigureGetUpdatesDelegate configure_delegate(
181 sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
182 scoped_ptr<GetUpdatesProcessor> processor(
183 BuildGetUpdatesProcessor(configure_delegate));
184 processor->PrepareGetUpdates(enabled_types(), &message);
186 const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
187 EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION, gu_msg.get_updates_origin());
188 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION,
189 gu_msg.caller_info().source());
191 ModelTypeSet progress_types;
192 for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
193 syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
194 gu_msg.from_progress_marker(i).data_type_id());
195 progress_types.Put(type);
197 EXPECT_TRUE(enabled_types().Equals(progress_types));
200 TEST_F(GetUpdatesProcessorTest, PollTest) {
201 sync_pb::ClientToServerMessage message;
202 PollGetUpdatesDelegate poll_delegate;
203 scoped_ptr<GetUpdatesProcessor> processor(
204 BuildGetUpdatesProcessor(poll_delegate));
205 processor->PrepareGetUpdates(enabled_types(), &message);
207 const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
208 EXPECT_EQ(sync_pb::SyncEnums::PERIODIC, gu_msg.get_updates_origin());
209 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::PERIODIC,
210 gu_msg.caller_info().source());
212 ModelTypeSet progress_types;
213 for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
214 syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
215 gu_msg.from_progress_marker(i).data_type_id());
216 progress_types.Put(type);
218 EXPECT_TRUE(enabled_types().Equals(progress_types));
221 TEST_F(GetUpdatesProcessorTest, RetryTest) {
222 sessions::NudgeTracker nudge_tracker;
225 base::TimeTicks t1 = kTestStartTime;
226 nudge_tracker.SetNextRetryTime(t1);
228 // Get the nudge tracker to think the retry is due.
229 nudge_tracker.SetSyncCycleStartTime(t1 + base::TimeDelta::FromSeconds(1));
231 sync_pb::ClientToServerMessage message;
232 NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
233 scoped_ptr<GetUpdatesProcessor> processor(
234 BuildGetUpdatesProcessor(normal_delegate));
235 processor->PrepareGetUpdates(enabled_types(), &message);
237 const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
238 EXPECT_EQ(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
239 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RETRY,
240 gu_msg.caller_info().source());
241 EXPECT_TRUE(gu_msg.is_retry());
243 ModelTypeSet progress_types;
244 for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
245 syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
246 gu_msg.from_progress_marker(i).data_type_id());
247 progress_types.Put(type);
249 EXPECT_TRUE(enabled_types().Equals(progress_types));
252 TEST_F(GetUpdatesProcessorTest, NudgeWithRetryTest) {
253 sessions::NudgeTracker nudge_tracker;
256 base::TimeTicks t1 = kTestStartTime;
257 nudge_tracker.SetNextRetryTime(t1);
259 // Get the nudge tracker to think the retry is due.
260 nudge_tracker.SetSyncCycleStartTime(t1 + base::TimeDelta::FromSeconds(1));
262 // Record a local change, too.
263 nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS));
265 sync_pb::ClientToServerMessage message;
266 NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
267 scoped_ptr<GetUpdatesProcessor> processor(
268 BuildGetUpdatesProcessor(normal_delegate));
269 processor->PrepareGetUpdates(enabled_types(), &message);
271 const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
272 EXPECT_NE(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
273 EXPECT_NE(sync_pb::GetUpdatesCallerInfo::RETRY,
274 gu_msg.caller_info().source());
276 EXPECT_TRUE(gu_msg.is_retry());
279 // Verify that a bogus response message is detected.
280 TEST_F(GetUpdatesProcessorTest, InvalidResponse) {
281 sync_pb::GetUpdatesResponse gu_response;
282 InitFakeUpdateResponse(&gu_response);
284 // This field is essential for making the client stop looping. If it's unset
285 // then something is very wrong. The client should detect this.
286 gu_response.clear_changes_remaining();
288 sessions::NudgeTracker nudge_tracker;
289 NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
290 sessions::StatusController status;
291 scoped_ptr<GetUpdatesProcessor> processor(
292 BuildGetUpdatesProcessor(normal_delegate));
293 SyncerError error = processor->ProcessResponse(gu_response,
296 EXPECT_EQ(error, SERVER_RESPONSE_VALIDATION_FAILED);
299 // Verify that we correctly detect when there's more work to be done.
300 TEST_F(GetUpdatesProcessorTest, MoreToDownloadResponse) {
301 sync_pb::GetUpdatesResponse gu_response;
302 InitFakeUpdateResponse(&gu_response);
303 gu_response.set_changes_remaining(1);
305 sessions::NudgeTracker nudge_tracker;
306 NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
307 sessions::StatusController status;
308 scoped_ptr<GetUpdatesProcessor> processor(
309 BuildGetUpdatesProcessor(normal_delegate));
310 SyncerError error = processor->ProcessResponse(gu_response,
313 EXPECT_EQ(error, SERVER_MORE_TO_DOWNLOAD);
316 // A simple scenario: No updates returned and nothing more to download.
317 TEST_F(GetUpdatesProcessorTest, NormalResponseTest) {
318 sync_pb::GetUpdatesResponse gu_response;
319 InitFakeUpdateResponse(&gu_response);
320 gu_response.set_changes_remaining(0);
322 sessions::NudgeTracker nudge_tracker;
323 NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
324 sessions::StatusController status;
325 scoped_ptr<GetUpdatesProcessor> processor(
326 BuildGetUpdatesProcessor(normal_delegate));
327 SyncerError error = processor->ProcessResponse(gu_response,
330 EXPECT_EQ(error, SYNCER_OK);
333 // Variant of GetUpdatesProcessor test designed to test update application.
335 // Maintains two enabled types, but requests that updates be applied for only
337 class GetUpdatesProcessorApplyUpdatesTest : public GetUpdatesProcessorTest {
339 GetUpdatesProcessorApplyUpdatesTest() {}
340 virtual ~GetUpdatesProcessorApplyUpdatesTest() {}
342 virtual void SetUp() OVERRIDE {
343 bookmarks_handler_ = AddUpdateHandler(BOOKMARKS);
344 autofill_handler_ = AddUpdateHandler(AUTOFILL);
347 ModelTypeSet GetGuTypes() {
348 return ModelTypeSet(AUTOFILL);
351 MockUpdateHandler* GetNonAppliedHandler() {
352 return bookmarks_handler_;
355 MockUpdateHandler* GetAppliedHandler() {
356 return autofill_handler_;
360 MockUpdateHandler* bookmarks_handler_;
361 MockUpdateHandler* autofill_handler_;
364 // Verify that a normal cycle applies updates non-passively to the specified
366 TEST_F(GetUpdatesProcessorApplyUpdatesTest, Normal) {
367 sessions::NudgeTracker nudge_tracker;
368 NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
369 scoped_ptr<GetUpdatesProcessor> processor(
370 BuildGetUpdatesProcessor(normal_delegate));
372 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
373 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
375 sessions::StatusController status;
376 processor->ApplyUpdates(GetGuTypes(), &status);
378 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
379 EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
381 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
382 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
385 // Verify that a configure cycle applies updates passively to the specified
387 TEST_F(GetUpdatesProcessorApplyUpdatesTest, Configure) {
388 ConfigureGetUpdatesDelegate configure_delegate(
389 sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
390 scoped_ptr<GetUpdatesProcessor> processor(
391 BuildGetUpdatesProcessor(configure_delegate));
393 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
394 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
396 sessions::StatusController status;
397 processor->ApplyUpdates(GetGuTypes(), &status);
399 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
400 EXPECT_EQ(1, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
402 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
403 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
406 // Verify that a poll cycle applies updates non-passively to the specified
408 TEST_F(GetUpdatesProcessorApplyUpdatesTest, Poll) {
409 PollGetUpdatesDelegate poll_delegate;
410 scoped_ptr<GetUpdatesProcessor> processor(
411 BuildGetUpdatesProcessor(poll_delegate));
413 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
414 EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
416 sessions::StatusController status;
417 processor->ApplyUpdates(GetGuTypes(), &status);
419 EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
420 EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
422 EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
423 EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
426 class DownloadUpdatesDebugInfoTest : public ::testing::Test {
428 DownloadUpdatesDebugInfoTest() {}
429 virtual ~DownloadUpdatesDebugInfoTest() {}
431 sessions::StatusController* status() {
435 sessions::DebugInfoGetter* debug_info_getter() {
436 return &debug_info_getter_;
439 void AddDebugEvent() {
440 debug_info_getter_.AddDebugEvent();
444 sessions::StatusController status_;
445 MockDebugInfoGetter debug_info_getter_;
448 // Verify CopyClientDebugInfo when there are no events to upload.
449 TEST_F(DownloadUpdatesDebugInfoTest, VerifyCopyClientDebugInfo_Empty) {
450 sync_pb::DebugInfo debug_info;
451 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info);
452 EXPECT_EQ(0, debug_info.events_size());
455 TEST_F(DownloadUpdatesDebugInfoTest, VerifyCopyOverwrites) {
456 sync_pb::DebugInfo debug_info;
458 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info);
459 EXPECT_EQ(1, debug_info.events_size());
460 GetUpdatesProcessor::CopyClientDebugInfo(debug_info_getter(), &debug_info);
461 EXPECT_EQ(1, debug_info.events_size());
464 } // namespace syncer