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