Update .DEPS.git
[chromium-blink-merge.git] / sync / engine / download_unittest.cc
blob14c9305dd902f5aecea6eb8107b47516a0c59579
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.
5 #include "sync/engine/download.h"
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"
21 namespace syncer {
23 using sessions::MockDebugInfoGetter;
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_) {}
30 virtual void SetUp() {
31 dir_maker_.SetUp();
33 AddUpdateHandler(AUTOFILL, GROUP_DB);
34 AddUpdateHandler(BOOKMARKS, GROUP_UI);
35 AddUpdateHandler(PREFERENCES, GROUP_UI);
38 virtual void TearDown() {
39 dir_maker_.TearDown();
42 ModelTypeSet proto_request_types() {
43 return proto_request_types_;
46 syncable::Directory* directory() {
47 return dir_maker_.directory();
50 GetUpdatesProcessor* get_updates_processor() {
51 return get_updates_processor_.get();
54 void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse* response) {
55 ModelTypeSet types = proto_request_types();
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");
64 response->set_changes_remaining(0);
67 private:
68 void AddUpdateHandler(ModelType type, ModelSafeGroup group) {
69 DCHECK(directory());
71 proto_request_types_.Put(type);
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_));
80 base::MessageLoop loop_; // Needed for directory init.
81 TestDirectorySetterUpper dir_maker_;
83 ModelTypeSet proto_request_types_;
84 UpdateHandlerMap update_handler_map_;
85 STLValueDeleter<UpdateHandlerMap> update_handler_deleter_;
86 scoped_ptr<GetUpdatesProcessor> get_updates_processor_;
88 DISALLOW_COPY_AND_ASSIGN(DownloadUpdatesTest);
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));
96 sync_pb::ClientToServerMessage msg;
97 download::BuildNormalDownloadUpdatesImpl(proto_request_types(),
98 get_updates_processor(),
99 nudge_tracker,
100 msg.mutable_get_updates());
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());
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();
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());
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);
144 sync_pb::ClientToServerMessage msg;
145 download::BuildNormalDownloadUpdatesImpl(proto_request_types(),
146 get_updates_processor(),
147 nudge_tracker,
148 msg.mutable_get_updates());
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());
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();
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());
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());
184 const sync_pb::GetUpdatesMessage& gu_msg = msg.get_updates();
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());
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);
196 EXPECT_TRUE(proto_request_types().Equals(progress_types));
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());
206 const sync_pb::GetUpdatesMessage& gu_msg = msg.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(proto_request_types().Equals(progress_types));
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());
228 const sync_pb::GetUpdatesMessage& gu_msg = msg.get_updates();
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());
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);
241 EXPECT_TRUE(proto_request_types().Equals(progress_types));
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));
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());
258 // Verify that a bogus response message is detected.
259 TEST_F(DownloadUpdatesTest, InvalidResponse) {
260 sync_pb::GetUpdatesResponse gu_response;
261 InitFakeUpdateResponse(&gu_response);
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();
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);
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);
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);
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);
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);
303 class DownloadUpdatesDebugInfoTest : public ::testing::Test {
304 public:
305 DownloadUpdatesDebugInfoTest() {}
306 virtual ~DownloadUpdatesDebugInfoTest() {}
308 sessions::StatusController* status() {
309 return &status_;
312 sessions::DebugInfoGetter* debug_info_getter() {
313 return &debug_info_getter_;
316 void AddDebugEvent() {
317 debug_info_getter_.AddDebugEvent();
320 private:
321 sessions::StatusController status_;
322 MockDebugInfoGetter debug_info_getter_;
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());
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());
342 } // namespace syncer