Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / sync / engine / download_unittest.cc
1 // Copyright 2013 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/download.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/sync_directory_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/syncable/directory.h"
17 #include "sync/test/engine/fake_model_worker.h"
18 #include "sync/test/engine/test_directory_setter_upper.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 using sessions::MockDebugInfoGetter;
25
26 // A test fixture for tests exercising download updates functions.
27 class DownloadUpdatesTest : public ::testing::Test {
28  protected:
29   DownloadUpdatesTest() :
30     kTestStartTime(base::TimeTicks::Now()),
31     update_handler_deleter_(&update_handler_map_) {}
32
33   virtual void SetUp() {
34     dir_maker_.SetUp();
35
36     AddUpdateHandler(AUTOFILL, GROUP_DB);
37     AddUpdateHandler(BOOKMARKS, GROUP_UI);
38     AddUpdateHandler(PREFERENCES, GROUP_UI);
39   }
40
41   virtual void TearDown() {
42     dir_maker_.TearDown();
43   }
44
45   ModelTypeSet request_types() {
46     return request_types_;
47   }
48
49   syncable::Directory* directory() {
50     return dir_maker_.directory();
51   }
52
53   scoped_ptr<GetUpdatesProcessor> BuildGetUpdatesProcessor(
54       const GetUpdatesDelegate& delegate) {
55     return scoped_ptr<GetUpdatesProcessor>(
56         new GetUpdatesProcessor(&update_handler_map_, delegate));
57   }
58
59   void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse* response) {
60     ModelTypeSet types = request_types();
61
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     }
68
69     response->set_changes_remaining(0);
70   }
71
72   const base::TimeTicks kTestStartTime;
73
74  private:
75   void AddUpdateHandler(ModelType type, ModelSafeGroup group) {
76     DCHECK(directory());
77
78     request_types_.Put(type);
79
80     scoped_refptr<ModelSafeWorker> worker = new FakeModelWorker(group);
81     SyncDirectoryUpdateHandler* handler =
82         new SyncDirectoryUpdateHandler(directory(), type, worker);
83     update_handler_map_.insert(std::make_pair(type, handler));
84   }
85
86   base::MessageLoop loop_;  // Needed for directory init.
87   TestDirectorySetterUpper dir_maker_;
88
89   ModelTypeSet request_types_;
90   UpdateHandlerMap update_handler_map_;
91   STLValueDeleter<UpdateHandlerMap> update_handler_deleter_;
92   scoped_ptr<GetUpdatesProcessor> get_updates_processor_;
93
94   DISALLOW_COPY_AND_ASSIGN(DownloadUpdatesTest);
95 };
96
97 // Basic test to make sure nudges are expressed properly in the request.
98 TEST_F(DownloadUpdatesTest, BookmarkNudge) {
99   sessions::NudgeTracker nudge_tracker;
100   nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS));
101
102   sync_pb::GetUpdatesMessage gu_msg;
103   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
104   scoped_ptr<GetUpdatesProcessor> processor(
105       BuildGetUpdatesProcessor(normal_delegate));
106   processor->PrepareGetUpdates(request_types(), &gu_msg);
107
108   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::LOCAL,
109             gu_msg.caller_info().source());
110   EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
111   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
112     syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
113         gu_msg.from_progress_marker(i).data_type_id());
114
115     const sync_pb::DataTypeProgressMarker& progress_marker =
116         gu_msg.from_progress_marker(i);
117     const sync_pb::GetUpdateTriggers& gu_trigger =
118         progress_marker.get_update_triggers();
119
120     // We perform some basic tests of GU trigger and source fields here.  The
121     // more complicated scenarios are tested by the NudgeTracker tests.
122     if (type == BOOKMARKS) {
123       EXPECT_TRUE(progress_marker.has_notification_hint());
124       EXPECT_EQ("", progress_marker.notification_hint());
125       EXPECT_EQ(1, gu_trigger.local_modification_nudges());
126       EXPECT_EQ(0, gu_trigger.datatype_refresh_nudges());
127     } else {
128       EXPECT_FALSE(progress_marker.has_notification_hint());
129       EXPECT_EQ(0, gu_trigger.local_modification_nudges());
130       EXPECT_EQ(0, gu_trigger.datatype_refresh_nudges());
131     }
132   }
133 }
134
135 // Basic test to ensure invalidation payloads are expressed in the request.
136 TEST_F(DownloadUpdatesTest, NotifyMany) {
137   sessions::NudgeTracker nudge_tracker;
138   nudge_tracker.RecordRemoteInvalidation(
139       BuildInvalidationMap(AUTOFILL, 1, "autofill_payload"));
140   nudge_tracker.RecordRemoteInvalidation(
141       BuildInvalidationMap(BOOKMARKS, 1, "bookmark_payload"));
142   nudge_tracker.RecordRemoteInvalidation(
143       BuildInvalidationMap(PREFERENCES, 1, "preferences_payload"));
144   ModelTypeSet notified_types;
145   notified_types.Put(AUTOFILL);
146   notified_types.Put(BOOKMARKS);
147   notified_types.Put(PREFERENCES);
148
149   sync_pb::GetUpdatesMessage gu_msg;
150   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
151   scoped_ptr<GetUpdatesProcessor> processor(
152       BuildGetUpdatesProcessor(normal_delegate));
153   processor->PrepareGetUpdates(request_types(), &gu_msg);
154
155   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION,
156             gu_msg.caller_info().source());
157   EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
158   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
159     syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
160         gu_msg.from_progress_marker(i).data_type_id());
161
162     const sync_pb::DataTypeProgressMarker& progress_marker =
163         gu_msg.from_progress_marker(i);
164     const sync_pb::GetUpdateTriggers& gu_trigger =
165         progress_marker.get_update_triggers();
166
167     // We perform some basic tests of GU trigger and source fields here.  The
168     // more complicated scenarios are tested by the NudgeTracker tests.
169     if (notified_types.Has(type)) {
170       EXPECT_TRUE(progress_marker.has_notification_hint());
171       EXPECT_FALSE(progress_marker.notification_hint().empty());
172       EXPECT_EQ(1, gu_trigger.notification_hint_size());
173     } else {
174       EXPECT_FALSE(progress_marker.has_notification_hint());
175       EXPECT_EQ(0, gu_trigger.notification_hint_size());
176     }
177   }
178 }
179
180 TEST_F(DownloadUpdatesTest, ConfigureTest) {
181   sync_pb::GetUpdatesMessage gu_msg;
182   ConfigureGetUpdatesDelegate configure_delegate(
183       sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
184   scoped_ptr<GetUpdatesProcessor> processor(
185       BuildGetUpdatesProcessor(configure_delegate));
186   processor->PrepareGetUpdates(request_types(), &gu_msg);
187
188   EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION, gu_msg.get_updates_origin());
189   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION,
190             gu_msg.caller_info().source());
191
192   ModelTypeSet progress_types;
193   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
194     syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
195         gu_msg.from_progress_marker(i).data_type_id());
196     progress_types.Put(type);
197   }
198   EXPECT_TRUE(request_types().Equals(progress_types));
199 }
200
201 TEST_F(DownloadUpdatesTest, PollTest) {
202   sync_pb::GetUpdatesMessage gu_msg;
203   PollGetUpdatesDelegate poll_delegate;
204   scoped_ptr<GetUpdatesProcessor> processor(
205       BuildGetUpdatesProcessor(poll_delegate));
206   processor->PrepareGetUpdates(request_types(), &gu_msg);
207
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());
211
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);
217   }
218   EXPECT_TRUE(request_types().Equals(progress_types));
219 }
220
221 TEST_F(DownloadUpdatesTest, RetryTest) {
222   sessions::NudgeTracker nudge_tracker;
223
224   // Schedule a retry.
225   base::TimeTicks t1 = kTestStartTime;
226   nudge_tracker.SetNextRetryTime(t1);
227
228   // Get the nudge tracker to think the retry is due.
229   nudge_tracker.SetSyncCycleStartTime(t1 + base::TimeDelta::FromSeconds(1));
230
231   sync_pb::GetUpdatesMessage gu_msg;
232   RetryGetUpdatesDelegate retry_delegate;
233   scoped_ptr<GetUpdatesProcessor> processor(
234       BuildGetUpdatesProcessor(retry_delegate));
235   processor->PrepareGetUpdates(request_types(), &gu_msg);
236
237   EXPECT_EQ(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
238   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RETRY,
239             gu_msg.caller_info().source());
240   EXPECT_TRUE(gu_msg.is_retry());
241
242   ModelTypeSet progress_types;
243   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
244     syncer::ModelType type = GetModelTypeFromSpecificsFieldNumber(
245         gu_msg.from_progress_marker(i).data_type_id());
246     progress_types.Put(type);
247   }
248   EXPECT_TRUE(request_types().Equals(progress_types));
249 }
250
251 TEST_F(DownloadUpdatesTest, NudgeWithRetryTest) {
252   sessions::NudgeTracker nudge_tracker;
253
254   // Schedule a retry.
255   base::TimeTicks t1 = kTestStartTime;
256   nudge_tracker.SetNextRetryTime(t1);
257
258   // Get the nudge tracker to think the retry is due.
259   nudge_tracker.SetSyncCycleStartTime(t1 + base::TimeDelta::FromSeconds(1));
260
261   // Record a local change, too.
262   nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS));
263
264   sync_pb::GetUpdatesMessage gu_msg;
265   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
266   scoped_ptr<GetUpdatesProcessor> processor(
267       BuildGetUpdatesProcessor(normal_delegate));
268   processor->PrepareGetUpdates(request_types(), &gu_msg);
269
270   EXPECT_NE(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
271   EXPECT_NE(sync_pb::GetUpdatesCallerInfo::RETRY,
272             gu_msg.caller_info().source());
273
274   EXPECT_TRUE(gu_msg.is_retry());
275 }
276
277 // Verify that a bogus response message is detected.
278 TEST_F(DownloadUpdatesTest, InvalidResponse) {
279   sync_pb::GetUpdatesResponse gu_response;
280   InitFakeUpdateResponse(&gu_response);
281
282   // This field is essential for making the client stop looping.  If it's unset
283   // then something is very wrong.  The client should detect this.
284   gu_response.clear_changes_remaining();
285
286   sessions::NudgeTracker nudge_tracker;
287   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
288   sessions::StatusController status;
289   scoped_ptr<GetUpdatesProcessor> processor(
290       BuildGetUpdatesProcessor(normal_delegate));
291   SyncerError error = download::ProcessResponse(gu_response,
292                                                 request_types(),
293                                                 processor.get(),
294                                                 &status);
295   EXPECT_EQ(error, SERVER_RESPONSE_VALIDATION_FAILED);
296 }
297
298 // Verify that we correctly detect when there's more work to be done.
299 TEST_F(DownloadUpdatesTest, MoreToDownloadResponse) {
300   sync_pb::GetUpdatesResponse gu_response;
301   InitFakeUpdateResponse(&gu_response);
302   gu_response.set_changes_remaining(1);
303
304   sessions::NudgeTracker nudge_tracker;
305   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
306   sessions::StatusController status;
307   scoped_ptr<GetUpdatesProcessor> processor(
308       BuildGetUpdatesProcessor(normal_delegate));
309   SyncerError error = download::ProcessResponse(gu_response,
310                                                 request_types(),
311                                                 processor.get(),
312                                                 &status);
313   EXPECT_EQ(error, SERVER_MORE_TO_DOWNLOAD);
314 }
315
316 // A simple scenario: No updates returned and nothing more to download.
317 TEST_F(DownloadUpdatesTest, NormalResponseTest) {
318   sync_pb::GetUpdatesResponse gu_response;
319   InitFakeUpdateResponse(&gu_response);
320   gu_response.set_changes_remaining(0);
321
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 = download::ProcessResponse(gu_response,
328                                                 request_types(),
329                                                 processor.get(),
330                                                 &status);
331   EXPECT_EQ(error, SYNCER_OK);
332 }
333
334 class DownloadUpdatesDebugInfoTest : public ::testing::Test {
335  public:
336   DownloadUpdatesDebugInfoTest() {}
337   virtual ~DownloadUpdatesDebugInfoTest() {}
338
339   sessions::StatusController* status() {
340     return &status_;
341   }
342
343   sessions::DebugInfoGetter* debug_info_getter() {
344     return &debug_info_getter_;
345   }
346
347   void AddDebugEvent() {
348     debug_info_getter_.AddDebugEvent();
349   }
350
351  private:
352   sessions::StatusController status_;
353   MockDebugInfoGetter debug_info_getter_;
354 };
355
356
357 // Verify CopyClientDebugInfo when there are no events to upload.
358 TEST_F(DownloadUpdatesDebugInfoTest, VerifyCopyClientDebugInfo_Empty) {
359   sync_pb::DebugInfo debug_info;
360   download::CopyClientDebugInfo(debug_info_getter(), &debug_info);
361   EXPECT_EQ(0, debug_info.events_size());
362 }
363
364 TEST_F(DownloadUpdatesDebugInfoTest, VerifyCopyOverwrites) {
365   sync_pb::DebugInfo debug_info;
366   AddDebugEvent();
367   download::CopyClientDebugInfo(debug_info_getter(), &debug_info);
368   EXPECT_EQ(1, debug_info.events_size());
369   download::CopyClientDebugInfo(debug_info_getter(), &debug_info);
370   EXPECT_EQ(1, debug_info.events_size());
371 }
372
373 }  // namespace syncer