Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / sync / engine / get_updates_processor_unittest.cc
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.
4
5 #include "sync/engine/get_updates_processor.h"
6
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"
21
22 namespace syncer {
23
24 namespace {
25
26 scoped_ptr<InvalidationInterface> BuildInvalidation(
27     int64 version,
28     const std::string& payload) {
29   return MockInvalidation::Build(version, payload)
30       .PassAs<InvalidationInterface>();
31 }
32
33 }  // namespace
34
35 using sessions::MockDebugInfoGetter;
36
37 // A test fixture for tests exercising download updates functions.
38 class GetUpdatesProcessorTest : public ::testing::Test {
39  protected:
40   GetUpdatesProcessorTest() :
41     kTestStartTime(base::TimeTicks::Now()),
42     update_handler_deleter_(&update_handler_map_) {}
43
44   virtual void SetUp() {
45     AddUpdateHandler(AUTOFILL);
46     AddUpdateHandler(BOOKMARKS);
47     AddUpdateHandler(PREFERENCES);
48   }
49
50   ModelTypeSet enabled_types() {
51     return enabled_types_;
52   }
53
54   scoped_ptr<GetUpdatesProcessor> BuildGetUpdatesProcessor(
55       const GetUpdatesDelegate& delegate) {
56     return scoped_ptr<GetUpdatesProcessor>(
57         new GetUpdatesProcessor(&update_handler_map_, delegate));
58   }
59
60   void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse* response) {
61     ModelTypeSet types = enabled_types();
62
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");
72     }
73
74     response->set_changes_remaining(0);
75   }
76
77   const UpdateHandler* GetHandler(ModelType type) {
78     UpdateHandlerMap::iterator it = update_handler_map_.find(type);
79     if (it == update_handler_map_.end())
80       return NULL;
81     return it->second;
82   }
83
84   const base::TimeTicks kTestStartTime;
85
86  protected:
87   MockUpdateHandler* AddUpdateHandler(ModelType type) {
88     enabled_types_.Put(type);
89
90     MockUpdateHandler* handler = new MockUpdateHandler(type);
91     update_handler_map_.insert(std::make_pair(type, handler));
92
93     return handler;
94   }
95
96  private:
97   ModelTypeSet enabled_types_;
98   UpdateHandlerMap update_handler_map_;
99   STLValueDeleter<UpdateHandlerMap> update_handler_deleter_;
100   scoped_ptr<GetUpdatesProcessor> get_updates_processor_;
101
102   DISALLOW_COPY_AND_ASSIGN(GetUpdatesProcessorTest);
103 };
104
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));
109
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);
115
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());
123
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();
128
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());
136     } else {
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());
140     }
141   }
142 }
143
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);
157
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);
163
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());
171
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();
176
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());
183     } else {
184       EXPECT_FALSE(progress_marker.has_notification_hint());
185       EXPECT_EQ(0, gu_trigger.notification_hint_size());
186     }
187   }
188 }
189
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);
195
196   ModelTypeSet initial_sync_types = ModelTypeSet(AUTOFILL, PREFERENCES);
197
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);
203
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());
211
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();
216
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());
221     } else {
222       EXPECT_TRUE(gu_trigger.has_initial_sync_in_progress());
223       EXPECT_FALSE(gu_trigger.initial_sync_in_progress());
224     }
225   }
226 }
227
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);
235
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());
240
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);
246   }
247   EXPECT_TRUE(enabled_types().Equals(progress_types));
248 }
249
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);
256
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());
261
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);
267   }
268   EXPECT_TRUE(enabled_types().Equals(progress_types));
269 }
270
271 TEST_F(GetUpdatesProcessorTest, RetryTest) {
272   sessions::NudgeTracker nudge_tracker;
273
274   // Schedule a retry.
275   base::TimeTicks t1 = kTestStartTime;
276   nudge_tracker.SetNextRetryTime(t1);
277
278   // Get the nudge tracker to think the retry is due.
279   nudge_tracker.SetSyncCycleStartTime(t1 + base::TimeDelta::FromSeconds(1));
280
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);
286
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());
292
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);
298   }
299   EXPECT_TRUE(enabled_types().Equals(progress_types));
300 }
301
302 TEST_F(GetUpdatesProcessorTest, NudgeWithRetryTest) {
303   sessions::NudgeTracker nudge_tracker;
304
305   // Schedule a retry.
306   base::TimeTicks t1 = kTestStartTime;
307   nudge_tracker.SetNextRetryTime(t1);
308
309   // Get the nudge tracker to think the retry is due.
310   nudge_tracker.SetSyncCycleStartTime(t1 + base::TimeDelta::FromSeconds(1));
311
312   // Record a local change, too.
313   nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS));
314
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);
320
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());
325
326   EXPECT_TRUE(gu_msg.is_retry());
327 }
328
329 // Verify that a bogus response message is detected.
330 TEST_F(GetUpdatesProcessorTest, InvalidResponse) {
331   sync_pb::GetUpdatesResponse gu_response;
332   InitFakeUpdateResponse(&gu_response);
333
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();
337
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,
344                                                  enabled_types(),
345                                                  &status);
346   EXPECT_EQ(error, SERVER_RESPONSE_VALIDATION_FAILED);
347 }
348
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);
354
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,
361                                                  enabled_types(),
362                                                  &status);
363   EXPECT_EQ(error, SERVER_MORE_TO_DOWNLOAD);
364 }
365
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);
371
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,
378                                                  enabled_types(),
379                                                  &status);
380   EXPECT_EQ(error, SYNCER_OK);
381 }
382
383 // Variant of GetUpdatesProcessor test designed to test update application.
384 //
385 // Maintains two enabled types, but requests that updates be applied for only
386 // one of them.
387 class GetUpdatesProcessorApplyUpdatesTest : public GetUpdatesProcessorTest {
388  public:
389   GetUpdatesProcessorApplyUpdatesTest() {}
390   virtual ~GetUpdatesProcessorApplyUpdatesTest() {}
391
392   virtual void SetUp() OVERRIDE {
393     bookmarks_handler_ = AddUpdateHandler(BOOKMARKS);
394     autofill_handler_ = AddUpdateHandler(AUTOFILL);
395   }
396
397   ModelTypeSet GetGuTypes() {
398     return ModelTypeSet(AUTOFILL);
399   }
400
401   MockUpdateHandler* GetNonAppliedHandler() {
402     return bookmarks_handler_;
403   }
404
405   MockUpdateHandler* GetAppliedHandler() {
406     return autofill_handler_;
407   }
408
409  private:
410   MockUpdateHandler* bookmarks_handler_;
411   MockUpdateHandler* autofill_handler_;
412 };
413
414 // Verify that a normal cycle applies updates non-passively to the specified
415 // types.
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));
421
422   EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
423   EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
424
425   sessions::StatusController status;
426   processor->ApplyUpdates(GetGuTypes(), &status);
427
428   EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
429   EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
430
431   EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
432   EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
433 }
434
435 // Verify that a configure cycle applies updates passively to the specified
436 // types.
437 TEST_F(GetUpdatesProcessorApplyUpdatesTest, Configure) {
438   ConfigureGetUpdatesDelegate configure_delegate(
439       sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
440   scoped_ptr<GetUpdatesProcessor> processor(
441       BuildGetUpdatesProcessor(configure_delegate));
442
443   EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
444   EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
445
446   sessions::StatusController status;
447   processor->ApplyUpdates(GetGuTypes(), &status);
448
449   EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
450   EXPECT_EQ(1, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
451
452   EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
453   EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
454 }
455
456 // Verify that a poll cycle applies updates non-passively to the specified
457 // types.
458 TEST_F(GetUpdatesProcessorApplyUpdatesTest, Poll) {
459   PollGetUpdatesDelegate poll_delegate;
460   scoped_ptr<GetUpdatesProcessor> processor(
461       BuildGetUpdatesProcessor(poll_delegate));
462
463   EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
464   EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
465
466   sessions::StatusController status;
467   processor->ApplyUpdates(GetGuTypes(), &status);
468
469   EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
470   EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
471
472   EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
473   EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
474 }
475
476 class DownloadUpdatesDebugInfoTest : public ::testing::Test {
477  public:
478   DownloadUpdatesDebugInfoTest() {}
479   virtual ~DownloadUpdatesDebugInfoTest() {}
480
481   sessions::StatusController* status() {
482     return &status_;
483   }
484
485   sessions::DebugInfoGetter* debug_info_getter() {
486     return &debug_info_getter_;
487   }
488
489   void AddDebugEvent() {
490     debug_info_getter_.AddDebugEvent();
491   }
492
493  private:
494   sessions::StatusController status_;
495   MockDebugInfoGetter debug_info_getter_;
496 };
497
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());
503 }
504
505 TEST_F(DownloadUpdatesDebugInfoTest, VerifyCopyOverwrites) {
506   sync_pb::DebugInfo debug_info;
507   AddDebugEvent();
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());
512 }
513
514 }  // namespace syncer