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

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

Issue 2739483002: Reporting: Implement delivery agent. (Closed)
Patch Set: rebase, &c. 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_test_util.h"
18 #include "net/reporting/reporting_uploader.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "url/gurl.h"
21 #include "url/origin.h"
22
23 namespace net {
24 namespace {
25
26 using Report = ReportingCache::Report;
27
28 const GURL kUrl("https://origin/path");
29 const url::Origin kOrigin(GURL("https://origin/"));
30 const GURL kEndpoint("https://endpoint/");
31 const std::string kGroup("group");
32 const std::string kType("type");
33
34 class MockUploader : public ReportingUploader {
35 public:
36 class PendingUpload {
37 public:
38 PendingUpload(MockUploader* uploader,
39 const GURL& url,
40 const std::string& json,
41 const Callback& callback)
42 : uploader_(uploader), url_(url), json_(json), callback_(callback) {
43 DCHECK(uploader_);
44 }
45
46 ~PendingUpload() {}
47
48 void Complete(Outcome outcome) {
49 callback_.Run(outcome);
50 // Deletes |this|.
51 uploader_->OnUploadComplete(this);
52 }
53
54 const GURL& url() const { return url_; }
55 const std::string& json() const { return json_; }
56
57 std::unique_ptr<base::Value> GetValue() const {
58 return base::JSONReader::Read(json_);
59 }
60
61 private:
62 MockUploader* uploader_;
63 GURL url_;
64 std::string json_;
65 Callback callback_;
66 };
67
68 MockUploader() {}
69 ~MockUploader() override {}
70
71 void StartUpload(const GURL& url,
72 const std::string& json,
73 const Callback& callback) override {
74 uploads_.push_back(
75 base::MakeUnique<PendingUpload>(this, url, json, callback));
76 }
77
78 const std::vector<std::unique_ptr<PendingUpload>>& pending_uploads() const {
79 return uploads_;
80 }
81
82 void OnUploadComplete(PendingUpload* upload) {
83 for (auto it = uploads_.begin(); it != uploads_.end(); ++it) {
84 if (it->get() == upload) {
85 uploads_.erase(it);
86 return;
87 }
88 }
89 NOTREACHED();
90 }
91
92 private:
93 std::vector<std::unique_ptr<PendingUpload>> uploads_;
94 };
95
96 class ReportingDeliveryAgentTest : public ::testing::Test {
97 protected:
98 ReportingDeliveryAgentTest()
99 : agent_(&clock_, &cache_, &uploader_, &backoff_policy_) {
100 backoff_policy_.num_errors_to_ignore = 0;
101 backoff_policy_.initial_delay_ms = 60000;
102 backoff_policy_.multiply_factor = 2.0;
103 backoff_policy_.jitter_factor = 0.0;
104 backoff_policy_.maximum_backoff_ms = -1;
105 backoff_policy_.entry_lifetime_ms = 0;
106 backoff_policy_.always_use_initial_delay = false;
107 }
108
109 base::TimeTicks tomorrow() {
110 return clock_.NowTicks() + base::TimeDelta::FromDays(1);
111 }
112
113 const std::vector<std::unique_ptr<MockUploader::PendingUpload>>&
114 pending_uploads() const {
115 return uploader_.pending_uploads();
116 }
117
118 base::SimpleTestTickClock clock_;
119 ReportingCache cache_;
120 MockUploader uploader_;
121 BackoffEntry::Policy backoff_policy_;
122 ReportingDeliveryAgent agent_;
123 };
124
125 TEST_F(ReportingDeliveryAgentTest, SuccessfulUpload) {
126 static const int kAgeMillis = 12345;
127
128 base::DictionaryValue body;
129 body.SetString("key", "value");
130
131 cache_.SetClient(kOrigin, kEndpoint, false, 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 Report*> 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, false, kGroup, tomorrow());
169 cache_.AddReport(kUrl, kGroup, kType,
170 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
171 0);
172
173 agent_.SendReports();
174
175 ASSERT_EQ(1u, pending_uploads().size());
176 pending_uploads()[0]->Complete(ReportingUploader::FAILURE);
177
178 // Failed upload should increment reports' attempts.
179 std::vector<const Report*> reports;
180 cache_.GetReports(&reports);
181 ASSERT_EQ(1u, reports.size());
182 EXPECT_EQ(1, reports[0]->attempts);
183
184 // Since endpoint is now failing, an upload won't be started despite a pending
185 // report.
186 ASSERT_TRUE(pending_uploads().empty());
187 agent_.SendReports();
188 EXPECT_TRUE(pending_uploads().empty());
189 }
190
191 TEST_F(ReportingDeliveryAgentTest, RemoveEndpointUpload) {
192 static const url::Origin kDifferentOrigin(GURL("https://origin2/"));
193
194 cache_.SetClient(kOrigin, kEndpoint, false, kGroup, tomorrow());
195 cache_.SetClient(kDifferentOrigin, kEndpoint, false, kGroup, tomorrow());
196 ASSERT_TRUE(FindClientInCache(&cache_, kOrigin, kEndpoint));
197 ASSERT_TRUE(FindClientInCache(&cache_, kDifferentOrigin, kEndpoint));
198
199 cache_.AddReport(kUrl, kGroup, kType,
200 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
201 0);
202
203 agent_.SendReports();
204
205 ASSERT_EQ(1u, pending_uploads().size());
206 pending_uploads()[0]->Complete(ReportingUploader::REMOVE_ENDPOINT);
207
208 // "Remove endpoint" upload should remove endpoint from *all* origins and
209 // increment reports' attempts.
210 std::vector<const Report*> reports;
211 cache_.GetReports(&reports);
212 ASSERT_EQ(1u, reports.size());
213 EXPECT_EQ(1, reports[0]->attempts);
214
215 EXPECT_FALSE(FindClientInCache(&cache_, kOrigin, kEndpoint));
216 EXPECT_FALSE(FindClientInCache(&cache_, kDifferentOrigin, kEndpoint));
217
218 // Since endpoint is now failing, an upload won't be started despite a pending
219 // report.
220 agent_.SendReports();
221 EXPECT_TRUE(pending_uploads().empty());
222 }
223
224 TEST_F(ReportingDeliveryAgentTest, ConcurrentRemove) {
225 cache_.SetClient(kOrigin, kEndpoint, false, kGroup, tomorrow());
226 cache_.AddReport(kUrl, kGroup, kType,
227 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
228 0);
229
230 agent_.SendReports();
231 ASSERT_EQ(1u, pending_uploads().size());
232
233 // Remove the report while the upload is running.
234 std::vector<const Report*> reports;
235 cache_.GetReports(&reports);
236 EXPECT_EQ(1u, reports.size());
237
238 // Report should appear removed, even though the cache has doomed it.
239 cache_.RemoveReports(reports);
240 cache_.GetReports(&reports);
241 EXPECT_TRUE(reports.empty());
242
243 // Completing upload shouldn't crash, and report should still be gone.
244 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
245 cache_.GetReports(&reports);
246 EXPECT_TRUE(reports.empty());
247 }
248
249 // Test that the agent will combine reports destined for the same endpoint, even
250 // if the reports are from different origins.
251 TEST_F(ReportingDeliveryAgentTest,
252 BatchReportsFromDifferentOriginsToSameEndpoint) {
253 static const GURL kDifferentUrl("https://origin2/path");
254 static const url::Origin kDifferentOrigin(kDifferentUrl);
255
256 cache_.SetClient(kOrigin, kEndpoint, false, kGroup, tomorrow());
257 cache_.SetClient(kDifferentOrigin, kEndpoint, false, kGroup, tomorrow());
258
259 cache_.AddReport(kUrl, kGroup, kType,
260 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
261 0);
262 cache_.AddReport(kDifferentUrl, kGroup, kType,
263 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
264 0);
265
266 agent_.SendReports();
267 ASSERT_EQ(1u, pending_uploads().size());
268
269 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
270 EXPECT_EQ(0u, pending_uploads().size());
271 }
272
273 // Test that the agent won't start a second upload to the same endpoint (even
274 // for a different origin) while one is pending, but will once it is no longer
275 // pending.
276 TEST_F(ReportingDeliveryAgentTest, SerializeUploadsToEndpoint) {
277 static const GURL kDifferentUrl("https://origin2/path");
278 static const url::Origin kDifferentOrigin(kDifferentUrl);
279
280 cache_.SetClient(kOrigin, kEndpoint, false, kGroup, tomorrow());
281 cache_.SetClient(kDifferentOrigin, kEndpoint, false, kGroup, tomorrow());
282
283 cache_.AddReport(kUrl, kGroup, kType,
284 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
285 0);
286
287 agent_.SendReports();
288 EXPECT_EQ(1u, pending_uploads().size());
289
290 cache_.AddReport(kDifferentUrl, kGroup, kType,
291 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
292 0);
293
294 agent_.SendReports();
295 ASSERT_EQ(1u, pending_uploads().size());
296
297 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
298 EXPECT_EQ(0u, pending_uploads().size());
299
300 agent_.SendReports();
301 ASSERT_EQ(1u, pending_uploads().size());
302
303 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
304 EXPECT_EQ(0u, pending_uploads().size());
305 }
306
307 // Test that the agent won't start a second upload for an (origin, group) while
308 // one is pending, but will once it is no longer pending.
309 TEST_F(ReportingDeliveryAgentTest, SerializeUploadsToGroup) {
310 static const GURL kDifferentEndpoint("https://endpoint2/");
311 static const std::string kDifferentGroup("group2");
312
313 cache_.SetClient(kOrigin, kEndpoint, false, kGroup, tomorrow());
314 cache_.SetClient(kOrigin, kDifferentEndpoint, false, kDifferentGroup,
315 tomorrow());
316
317 cache_.AddReport(kUrl, kGroup, kType,
318 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
319 0);
320
321 agent_.SendReports();
322 EXPECT_EQ(1u, pending_uploads().size());
323
324 cache_.AddReport(kUrl, kDifferentGroup, kType,
325 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
326 0);
327
328 agent_.SendReports();
329 ASSERT_EQ(2u, pending_uploads().size());
330
331 pending_uploads()[1]->Complete(ReportingUploader::SUCCESS);
332 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
333 EXPECT_EQ(0u, pending_uploads().size());
334 }
335
336 // Test that the agent won't start a second upload for an (origin, group) while
337 // one is pending, but will once it is no longer pending.
338 TEST_F(ReportingDeliveryAgentTest, ParallelizeUploadsAcrossGroups) {
339 static const GURL kDifferentEndpoint("https://endpoint2/");
340
341 cache_.SetClient(kOrigin, kEndpoint, false, kGroup, tomorrow());
342 cache_.SetClient(kOrigin, kDifferentEndpoint, false, kGroup, tomorrow());
343
344 cache_.AddReport(kUrl, kGroup, kType,
345 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
346 0);
347
348 agent_.SendReports();
349 EXPECT_EQ(1u, pending_uploads().size());
350
351 cache_.AddReport(kUrl, kGroup, kType,
352 base::MakeUnique<base::DictionaryValue>(), clock_.NowTicks(),
353 0);
354
355 agent_.SendReports();
356 ASSERT_EQ(1u, pending_uploads().size());
357
358 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
359 EXPECT_EQ(0u, pending_uploads().size());
360
361 agent_.SendReports();
362 ASSERT_EQ(1u, pending_uploads().size());
363
364 pending_uploads()[0]->Complete(ReportingUploader::SUCCESS);
365 EXPECT_EQ(0u, pending_uploads().size());
366 }
367
368 } // namespace
369 } // namespace net
OLDNEW
« net/reporting/reporting_delivery_agent.h ('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