Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: net/reporting/reporting_delivery_agent_unittest.cc

Issue 2739483002: Reporting: Implement delivery agent. (Closed)
Patch Set: Make requested changes. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 "net/reporting/reporting_delivery_agent.h"
6
7 #include <vector>
8
9 #include "base/json/json_reader.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "base/test/values_test_util.h"
13 #include "base/time/time.h"
14 #include "base/values.h"
15 #include "net/base/backoff_entry.h"
16 #include "net/reporting/reporting_cache.h"
17 #include "net/reporting/reporting_report.h"
18 #include "net/reporting/reporting_test_util.h"
19 #include "net/reporting/reporting_uploader.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "url/gurl.h"
22 #include "url/origin.h"
23
24 namespace net {
25 namespace {
26
27 const GURL kUrl("https://origin/path");
28 const url::Origin kOrigin(GURL("https://origin/"));
29 const GURL kEndpoint("https://endpoint/");
30 const std::string kGroup("group");
31 const std::string kType("type");
32
33 class MockUploader : public ReportingUploader {
34 public:
35 class PendingUpload {
36 public:
37 PendingUpload(MockUploader* uploader,
38 const GURL& url,
39 const std::string& json,
40 const Callback& callback)
41 : uploader_(uploader), url_(url), json_(json), callback_(callback) {
42 DCHECK(uploader_);
43 }
44
45 ~PendingUpload() {}
46
47 void Complete(Outcome outcome) {
48 callback_.Run(outcome);
49 // Deletes |this|.
50 uploader_->OnUploadComplete(this);
51 }
52
53 const GURL& url() const { return url_; }
54 const std::string& json() const { return json_; }
55
56 std::unique_ptr<base::Value> GetValue() const {
57 return base::JSONReader::Read(json_);
58 }
59
60 private:
61 MockUploader* uploader_;
62 GURL url_;
63 std::string json_;
64 Callback callback_;
65 };
66
67 MockUploader() {}
68 ~MockUploader() override {}
69
70 void StartUpload(const GURL& url,
71 const std::string& json,
72 const Callback& callback) override {
73 uploads_.push_back(
74 base::MakeUnique<PendingUpload>(this, url, json, callback));
75 }
76
77 const std::vector<std::unique_ptr<PendingUpload>>& pending_uploads() const {
78 return uploads_;
79 }
80
81 void OnUploadComplete(PendingUpload* upload) {
82 for (auto it = uploads_.begin(); it != uploads_.end(); ++it) {
83 if (it->get() == upload) {
84 uploads_.erase(it);
85 return;
86 }
87 }
88 NOTREACHED();
89 }
90
91 private:
92 std::vector<std::unique_ptr<PendingUpload>> uploads_;
93 };
94
95 class ReportingDeliveryAgentTest : public ::testing::Test {
96 protected:
97 ReportingDeliveryAgentTest()
98 : agent_(&clock_, &cache_, &uploader_, &backoff_policy_) {
99 backoff_policy_.num_errors_to_ignore = 0;
100 backoff_policy_.initial_delay_ms = 60000;
101 backoff_policy_.multiply_factor = 2.0;
102 backoff_policy_.jitter_factor = 0.0;
103 backoff_policy_.maximum_backoff_ms = -1;
104 backoff_policy_.entry_lifetime_ms = 0;
105 backoff_policy_.always_use_initial_delay = false;
106 }
107
108 base::TimeTicks tomorrow() {
109 return clock_.NowTicks() + base::TimeDelta::FromDays(1);
110 }
111
112 const std::vector<std::unique_ptr<MockUploader::PendingUpload>>&
113 pending_uploads() const {
114 return uploader_.pending_uploads();
115 }
116
117 base::SimpleTestTickClock clock_;
118 ReportingCache cache_;
119 MockUploader uploader_;
120 BackoffEntry::Policy backoff_policy_;
121 ReportingDeliveryAgent agent_;
122 };
123
124 TEST_F(ReportingDeliveryAgentTest, SuccessfulUpload) {
125 static const int kAgeMillis = 12345;
126
127 base::DictionaryValue body;
128 body.SetString("key", "value");
129
130 cache_.SetClient(kOrigin, kEndpoint, ReportingClient::Subdomains::EXCLUDE,
131 kGroup, tomorrow());
132 cache_.AddReport(kUrl, kGroup, kType, body.CreateDeepCopy(),
133 clock_.NowTicks(), 0);
134
135 clock_.Advance(base::TimeDelta::FromMilliseconds(kAgeMillis));
136
137 agent_.SendReports();
138
139 ASSERT_EQ(1u, pending_uploads().size());
140 EXPECT_EQ(kEndpoint, pending_uploads()[0]->url());
141 {
142 auto value = pending_uploads()[0]->GetValue();
143
144 base::ListValue* list;
145 ASSERT_TRUE(value->GetAsList(&list));
146 EXPECT_EQ(1u, list->GetSize());
147
148 base::DictionaryValue* report;
149 ASSERT_TRUE(list->GetDictionary(0, &report));
150 EXPECT_EQ(4u, report->size());
151
152 ExpectDictIntegerValue(kAgeMillis, *report, "age");
153 ExpectDictStringValue(kType, *report, "type");
154 ExpectDictStringValue(kUrl.spec(), *report, "url");
155 ExpectDictDictionaryValue(body, *report, "report");
156 }
157 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
158
159 // Successful upload should remove delivered reports.
160 std::vector<const ReportingReport*> reports;
161 cache_.GetReports(&reports);
162 EXPECT_TRUE(reports.empty());
163
164 // TODO(juliatuttle): Check that BackoffEntry was informed of success.
165 }
166
167 TEST_F(ReportingDeliveryAgentTest, FailedUpload) {
168 cache_.SetClient(kOrigin, kEndpoint, ReportingClient::Subdomains::EXCLUDE,
169 kGroup, tomorrow());
170 cache_.AddReport(kUrl, kGroup, kType,
171 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
172 0);
173
174 agent_.SendReports();
175
176 ASSERT_EQ(1u, pending_uploads().size());
177 pending_uploads()[0]->Complete(ReportingUploader::FAILURE);
178
179 // Failed upload should increment reports' attempts.
180 std::vector<const ReportingReport*> reports;
181 cache_.GetReports(&reports);
182 ASSERT_EQ(1u, reports.size());
183 EXPECT_EQ(1, reports[0]->attempts);
184
185 // Since endpoint is now failing, an upload won't be started despite a pending
186 // report.
187 ASSERT_TRUE(pending_uploads().empty());
188 agent_.SendReports();
189 EXPECT_TRUE(pending_uploads().empty());
190 }
191
192 TEST_F(ReportingDeliveryAgentTest, RemoveEndpointUpload) {
193 static const url::Origin kDifferentOrigin(GURL("https://origin2/"));
194
195 cache_.SetClient(kOrigin, kEndpoint, ReportingClient::Subdomains::EXCLUDE,
196 kGroup, tomorrow());
197 cache_.SetClient(kDifferentOrigin, kEndpoint,
198 ReportingClient::Subdomains::EXCLUDE, kGroup, tomorrow());
199 ASSERT_TRUE(FindClientInCache(&cache_, kOrigin, kEndpoint));
200 ASSERT_TRUE(FindClientInCache(&cache_, kDifferentOrigin, kEndpoint));
201
202 cache_.AddReport(kUrl, kGroup, kType,
203 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
204 0);
205
206 agent_.SendReports();
207
208 ASSERT_EQ(1u, pending_uploads().size());
209 pending_uploads()[0]->Complete(ReportingUploader::REMOVE_ENDPOINT);
210
211 // "Remove endpoint" upload should remove endpoint from *all* origins and
212 // increment reports' attempts.
213 std::vector<const ReportingReport*> reports;
214 cache_.GetReports(&reports);
215 ASSERT_EQ(1u, reports.size());
216 EXPECT_EQ(1, reports[0]->attempts);
217
218 EXPECT_FALSE(FindClientInCache(&cache_, kOrigin, kEndpoint));
219 EXPECT_FALSE(FindClientInCache(&cache_, kDifferentOrigin, kEndpoint));
220
221 // Since endpoint is now failing, an upload won't be started despite a pending
222 // report.
223 agent_.SendReports();
224 EXPECT_TRUE(pending_uploads().empty());
225 }
226
227 TEST_F(ReportingDeliveryAgentTest, ConcurrentRemove) {
228 cache_.SetClient(kOrigin, kEndpoint, ReportingClient::Subdomains::EXCLUDE,
229 kGroup, tomorrow());
230 cache_.AddReport(kUrl, kGroup, kType,
231 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
232 0);
233
234 agent_.SendReports();
235 ASSERT_EQ(1u, pending_uploads().size());
236
237 // Remove the report while the upload is running.
238 std::vector<const ReportingReport*> reports;
239 cache_.GetReports(&reports);
240 EXPECT_EQ(1u, reports.size());
241
242 // Report should appear removed, even though the cache has doomed it.
243 cache_.RemoveReports(reports);
244 cache_.GetReports(&reports);
245 EXPECT_TRUE(reports.empty());
246
247 // Completing upload shouldn't crash, and report should still be gone.
248 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
249 cache_.GetReports(&reports);
250 EXPECT_TRUE(reports.empty());
251 }
252
253 // Test that the agent will combine reports destined for the same endpoint, even
254 // if the reports are from different origins.
255 TEST_F(ReportingDeliveryAgentTest,
256 BatchReportsFromDifferentOriginsToSameEndpoint) {
257 static const GURL kDifferentUrl("https://origin2/path");
258 static const url::Origin kDifferentOrigin(kDifferentUrl);
259
260 cache_.SetClient(kOrigin, kEndpoint, ReportingClient::Subdomains::EXCLUDE,
261 kGroup, tomorrow());
262 cache_.SetClient(kDifferentOrigin, kEndpoint,
263 ReportingClient::Subdomains::EXCLUDE, kGroup, tomorrow());
264
265 cache_.AddReport(kUrl, kGroup, kType,
266 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
267 0);
268 cache_.AddReport(kDifferentUrl, kGroup, kType,
269 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
270 0);
271
272 agent_.SendReports();
273 ASSERT_EQ(1u, pending_uploads().size());
274
275 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
276 EXPECT_EQ(0u, pending_uploads().size());
277 }
278
279 // Test that the agent won't start a second upload to the same endpoint (even
280 // for a different origin) while one is pending, but will once it is no longer
281 // pending.
282 TEST_F(ReportingDeliveryAgentTest, SerializeUploadsToEndpoint) {
283 static const GURL kDifferentUrl("https://origin2/path");
284 static const url::Origin kDifferentOrigin(kDifferentUrl);
285
286 cache_.SetClient(kOrigin, kEndpoint, ReportingClient::Subdomains::EXCLUDE,
287 kGroup, tomorrow());
288 cache_.SetClient(kDifferentOrigin, kEndpoint,
289 ReportingClient::Subdomains::EXCLUDE, kGroup, tomorrow());
290
291 cache_.AddReport(kUrl, kGroup, kType,
292 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
293 0);
294
295 agent_.SendReports();
296 EXPECT_EQ(1u, pending_uploads().size());
297
298 cache_.AddReport(kDifferentUrl, kGroup, kType,
299 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
300 0);
301
302 agent_.SendReports();
303 ASSERT_EQ(1u, pending_uploads().size());
304
305 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
306 EXPECT_EQ(0u, pending_uploads().size());
307
308 agent_.SendReports();
309 ASSERT_EQ(1u, pending_uploads().size());
310
311 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
312 EXPECT_EQ(0u, pending_uploads().size());
313 }
314
315 // Test that the agent won't start a second upload for an (origin, group) while
316 // one is pending, but will once it is no longer pending.
317 TEST_F(ReportingDeliveryAgentTest, SerializeUploadsToGroup) {
318 static const GURL kDifferentEndpoint("https://endpoint2/");
319 static const std::string kDifferentGroup("group2");
320
321 cache_.SetClient(kOrigin, kEndpoint, ReportingClient::Subdomains::EXCLUDE,
322 kGroup, tomorrow());
323 cache_.SetClient(kOrigin, kDifferentEndpoint,
324 ReportingClient::Subdomains::EXCLUDE, kDifferentGroup,
325 tomorrow());
326
327 cache_.AddReport(kUrl, kGroup, kType,
328 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
329 0);
330
331 agent_.SendReports();
332 EXPECT_EQ(1u, pending_uploads().size());
333
334 cache_.AddReport(kUrl, kDifferentGroup, kType,
335 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
336 0);
337
338 agent_.SendReports();
339 ASSERT_EQ(2u, pending_uploads().size());
340
341 pending_uploads()[1]->Complete(ReportingUploader::SUCCESS);
342 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
343 EXPECT_EQ(0u, pending_uploads().size());
344 }
345
346 // Test that the agent won't start a second upload for an (origin, group) while
347 // one is pending, but will once it is no longer pending.
348 TEST_F(ReportingDeliveryAgentTest, ParallelizeUploadsAcrossGroups) {
349 static const GURL kDifferentEndpoint("https://endpoint2/");
350
351 cache_.SetClient(kOrigin, kEndpoint, ReportingClient::Subdomains::EXCLUDE,
352 kGroup, tomorrow());
353 cache_.SetClient(kOrigin, kDifferentEndpoint,
354 ReportingClient::Subdomains::EXCLUDE, kGroup, tomorrow());
355
356 cache_.AddReport(kUrl, kGroup, kType,
357 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
358 0);
359
360 agent_.SendReports();
361 EXPECT_EQ(1u, pending_uploads().size());
362
363 cache_.AddReport(kUrl, kGroup, kType,
364 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
365 0);
366
367 agent_.SendReports();
368 ASSERT_EQ(1u, pending_uploads().size());
369
370 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
371 EXPECT_EQ(0u, pending_uploads().size());
372
373 agent_.SendReports();
374 ASSERT_EQ(1u, pending_uploads().size());
375
376 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
377 EXPECT_EQ(0u, pending_uploads().size());
378 }
379
380 } // namespace
381 } // namespace net
OLDNEW
« net/reporting/reporting_delivery_agent.cc ('K') | « net/reporting/reporting_delivery_agent.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698