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

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

Issue 2249213002: [OBSOLETE] Reporting: Initial implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Try fixing unittest compile error on Android? Created 3 years, 10 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
« no previous file with comments | « net/reporting/reporting_service.cc ('k') | net/reporting/reporting_uploader.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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_service.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/json/json_reader.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/run_loop.h"
14 #include "base/test/simple_test_tick_clock.h"
15 #include "base/values.h"
16 #include "net/base/network_change_notifier.h"
17 #include "net/reporting/reporting_uploader.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "url/gurl.h"
20
21 namespace net {
22 namespace {
23
24 class MockUploader : public ReportingUploader {
25 public:
26 class PendingDelivery {
27 public:
28 PendingDelivery(MockUploader* uploader,
29 const GURL& url,
30 const std::string& json,
31 const Callback& callback)
32 : uploader_(uploader), url_(url), json_(json), callback_(callback) {
33 DCHECK(uploader_);
34 }
35
36 ~PendingDelivery() {}
37
38 void Complete(Outcome outcome) {
39 callback_.Run(outcome);
40 // Deletes |this|.
41 uploader_->OnDeliveryComplete(this);
42 }
43
44 const GURL& url() const { return url_; }
45 const std::string& json() const { return json_; }
46
47 private:
48 MockUploader* uploader_;
49 GURL url_;
50 std::string json_;
51 Callback callback_;
52 };
53
54 MockUploader() {}
55 ~MockUploader() override {}
56
57 void AttemptDelivery(const GURL& url,
58 const std::string& json,
59 const Callback& callback) override {
60 deliveries_.push_back(
61 base::MakeUnique<PendingDelivery>(this, url, json, callback));
62 }
63
64 const std::vector<std::unique_ptr<PendingDelivery>>& GetPendingDeliveries()
65 const {
66 return deliveries_;
67 }
68
69 void OnDeliveryComplete(PendingDelivery* delivery) {
70 for (auto it = deliveries_.begin(); it != deliveries_.end(); ++it) {
71 if (it->get() == delivery) {
72 deliveries_.erase(it);
73 return;
74 }
75 }
76 NOTREACHED();
77 }
78
79 private:
80 std::vector<std::unique_ptr<PendingDelivery>> deliveries_;
81 };
82
83 class ReportingServiceTest : public ::testing::Test {
84 protected:
85 ReportingServiceTest()
86 : clock_(new base::SimpleTestTickClock()),
87 uploader_(new MockUploader()) {}
88
89 ~ReportingServiceTest() override {
90 // These are owned by the Service, so clear them to avoid accidentally
91 // accessing them after the Service is destroyed.
92 clock_ = nullptr;
93 uploader_ = nullptr;
94 }
95
96 void CreateServiceWithDefaultPolicy() {
97 CreateServiceWithPolicy(ReportingService::Policy());
98 }
99
100 void CreateServiceWithPolicy(const ReportingService::Policy& policy) {
101 DCHECK(!service_);
102 policy_ = policy;
103 service_ = base::MakeUnique<ReportingService>(policy);
104 service_->set_clock_for_testing(base::WrapUnique(clock_));
105 service_->set_uploader(base::WrapUnique(uploader_));
106 }
107
108 void QueueReport(const GURL& url) {
109 service_->QueueReport(base::MakeUnique<base::DictionaryValue>(), url,
110 url.GetOrigin(), "default", "test");
111 }
112
113 const std::vector<std::unique_ptr<MockUploader::PendingDelivery>>&
114 GetPendingDeliveries() {
115 return uploader_->GetPendingDeliveries();
116 }
117
118 size_t GetReportCount() { return service_->GetReportCountForTesting(); }
119
120 bool HasEndpoint(const std::string& endpoint_url) {
121 return service_->HasEndpointForTesting(GURL(endpoint_url));
122 }
123
124 bool HasClient(const std::string& endpoint_url,
125 const std::string& origin_url) {
126 return service_->HasClientForTesting(GURL(endpoint_url), GURL(origin_url));
127 }
128
129 int GetEndpointFailures(const std::string& endpoint_url) {
130 return service_->GetEndpointFailuresForTesting(GURL(endpoint_url));
131 }
132
133 void MockNetworkChange() {
134 // TODO: Need to SetTestNotificationsOnly(true) to keep things from flaking,
135 // but have to figure out how to do that before NCN is created or how to
136 // recreate NCN.
137 NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
138 NetworkChangeNotifier::CONNECTION_NONE);
139 base::RunLoop().RunUntilIdle();
140 NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
141 NetworkChangeNotifier::CONNECTION_WIFI);
142 base::RunLoop().RunUntilIdle();
143 }
144
145 // |policy_| is a copy of the policy used to configure |service_|, for easier
146 // reference.
147 ReportingService::Policy policy_;
148 // |clock_| and |uploader_| are owned by |service_|, not the test.
149 base::SimpleTestTickClock* clock_;
150 MockUploader* uploader_;
151 std::unique_ptr<ReportingService> service_;
152 };
153
154 TEST_F(ReportingServiceTest, ProcessHeaderFromInsecureOrigin) {
155 CreateServiceWithDefaultPolicy();
156
157 service_->ProcessHeader(GURL("http://insecure/"),
158 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
159 EXPECT_FALSE(HasClient("https://endpoint/", "http://insecure"));
160 }
161
162 TEST_F(ReportingServiceTest, ProcessInvalidHeaders) {
163 static const struct {
164 const char* header_value;
165 const char* description;
166 } kInvalidHeaderTestCases[] = {
167 {"{\"max-age\":1}", "missing url"},
168 {"{\"url\":0,\"max-age\":1}", "non-string url"},
169 {"{\"url\":\"http://insecure/\",\"max-age\":1}", "insecure url"},
170
171 {"{\"url\":\"https://endpoint/\"}", "missing max-age"},
172 {"{\"url\":\"https://endpoint/\",\"max-age\":\"\"}",
173 "non-integer max-age"},
174 {"{\"url\":\"https://endpoint/\",\"max-age\":-1}", "negative max-age"},
175
176 {"{\"url\":\"https://endpoint/\",\"max-age\":1,\"group\":0}",
177 "non-string group"},
178
179 {"{\"url\":\"https://endpoint/\",\"max-age\":1,\"includeSubdomains\":0}",
180 "non-boolean includeSubdomains"},
181 };
182
183 CreateServiceWithDefaultPolicy();
184
185 for (size_t i = 0; i < arraysize(kInvalidHeaderTestCases); ++i) {
186 auto& test_case = kInvalidHeaderTestCases[i];
187 service_->ProcessHeader(GURL("https://origin/"), test_case.header_value);
188 EXPECT_FALSE(HasClient("https://endpoint/", "https://origin/"));
189 }
190 }
191
192 TEST_F(ReportingServiceTest, ProcessValidHeader) {
193 CreateServiceWithDefaultPolicy();
194
195 service_->ProcessHeader(GURL("https://origin/"),
196 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
197 EXPECT_TRUE(HasClient("https://endpoint/", "https://origin/"));
198
199 #if 0
200 EXPECT_EQ(1u, GetCache().GetEndpoints().size());
201 const std::unique_ptr<ReportingEndpoint>* endpoint_ptr =
202 GetCache().GetEndpoint(GURL("https://endpoint/"));
203 ASSERT_TRUE(endpoint_ptr);
204 const std::unique_ptr<ReportingEndpoint>& endpoint = *endpoint_ptr;
205 EXPECT_EQ(GURL("https://endpoint/"), endpoint->url);
206
207 EXPECT_EQ(1u, endpoint->clients.count(GURL("https://origin/")));
208 auto client_it = endpoint->clients.find(GURL("https://origin/"));
209 ASSERT_TRUE(client_it != endpoint->clients.end());
210 const ReportingClient& client = client_it->second;
211 EXPECT_EQ(GURL("https://origin"), client.origin);
212 EXPECT_FALSE(client.subdomains);
213 EXPECT_EQ("default", client.group);
214 EXPECT_EQ(base::TimeDelta::FromSeconds(1), client.ttl);
215 #endif
216 }
217
218 TEST_F(ReportingServiceTest, ProcessZeroMaxAgeHeader) {
219 CreateServiceWithDefaultPolicy();
220
221 service_->ProcessHeader(GURL("https://origin/"),
222 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
223 EXPECT_TRUE(HasClient("https://endpoint/", "https://origin/"));
224 service_->ProcessHeader(GURL("https://origin/"),
225 "{\"url\":\"https://endpoint/\",\"max-age\":0}");
226 EXPECT_FALSE(HasClient("https://endpoint/", "https://origin/"));
227 }
228
229 TEST_F(ReportingServiceTest, DeliverySuccess) {
230 CreateServiceWithDefaultPolicy();
231
232 service_->ProcessHeader(GURL("https://origin/"),
233 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
234 QueueReport(GURL("https://origin/path"));
235 service_->SendReports();
236
237 ASSERT_EQ(1u, GetPendingDeliveries().size());
238 const std::unique_ptr<MockUploader::PendingDelivery>& delivery =
239 GetPendingDeliveries()[0];
240 EXPECT_EQ(GURL("https://endpoint/"), delivery->url());
241 {
242 auto reports_value = base::JSONReader::Read(delivery->json());
243 const base::ListValue* reports;
244 ASSERT_TRUE(reports_value->GetAsList(&reports));
245 ASSERT_EQ(1u, reports->GetSize());
246 const base::DictionaryValue* report;
247 ASSERT_TRUE(reports->GetDictionary(0u, &report));
248 std::string type;
249 ASSERT_TRUE(report->GetString("type", &type));
250 EXPECT_EQ("test", type);
251 std::string url;
252 ASSERT_TRUE(report->GetString("url", &url));
253 EXPECT_EQ("https://origin/path", url);
254 }
255
256 delivery->Complete(ReportingUploader::SUCCESS);
257
258 EXPECT_EQ(0, GetEndpointFailures("https://endpoint/"));
259 }
260
261 TEST_F(ReportingServiceTest, DeliveryFailure) {
262 CreateServiceWithDefaultPolicy();
263
264 service_->ProcessHeader(GURL("https://origin/"),
265 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
266 QueueReport(GURL("https://origin/path"));
267 service_->SendReports();
268
269 GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
270
271 EXPECT_EQ(1, GetEndpointFailures("https://endpoint/"));
272 }
273
274 TEST_F(ReportingServiceTest, DeliveryRemoveEndpoint) {
275 CreateServiceWithDefaultPolicy();
276
277 service_->ProcessHeader(GURL("https://origin/"),
278 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
279 QueueReport(GURL("https://origin/path"));
280 service_->SendReports();
281
282 GetPendingDeliveries()[0]->Complete(ReportingUploader::REMOVE_ENDPOINT);
283
284 EXPECT_FALSE(HasClient("https://endpoint/", "https://origin/"));
285 }
286
287 TEST_F(ReportingServiceTest, NoDeliveryToPendingEndpoint) {
288 CreateServiceWithDefaultPolicy();
289
290 service_->ProcessHeader(GURL("https://origin/"),
291 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
292 QueueReport(GURL("https://origin/"));
293 service_->SendReports();
294
295 GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
296
297 // Without advancing the clock, the endpoint should still be pending, so the
298 // Manager should not try to deliver reports to it.
299 service_->SendReports();
300
301 EXPECT_TRUE(GetPendingDeliveries().empty());
302 }
303
304 TEST_F(ReportingServiceTest, NoDeliveryToMismatchedEndpoint) {
305 CreateServiceWithDefaultPolicy();
306
307 service_->ProcessHeader(GURL("https://origin1/"),
308 "{\"url\":\"https://endpoint1/\",\"max-age\":1}");
309 QueueReport(GURL("https://origin2/"));
310 service_->SendReports();
311
312 EXPECT_TRUE(GetPendingDeliveries().empty());
313 }
314
315 TEST_F(ReportingServiceTest, BatchReportsForSameOrigin) {
316 CreateServiceWithDefaultPolicy();
317
318 service_->ProcessHeader(GURL("https://origin/"),
319 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
320 QueueReport(GURL("https://origin/"));
321 QueueReport(GURL("https://origin/"));
322 service_->SendReports();
323
324 ASSERT_EQ(1u, GetPendingDeliveries().size());
325 GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
326 }
327
328 TEST_F(ReportingServiceTest, BatchReportsForSameEndpoint) {
329 CreateServiceWithDefaultPolicy();
330
331 service_->ProcessHeader(GURL("https://origin1/"),
332 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
333 service_->ProcessHeader(GURL("https://origin2/"),
334 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
335 QueueReport(GURL("https://origin1/"));
336 QueueReport(GURL("https://origin2/"));
337 service_->SendReports();
338
339 ASSERT_EQ(1u, GetPendingDeliveries().size());
340 GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
341 }
342
343 TEST_F(ReportingServiceTest, ExpiredEndpoint) {
344 CreateServiceWithDefaultPolicy();
345
346 service_->ProcessHeader(GURL("https://origin/"),
347 "{\"url\":\"https://endpoint/\",\"max-age\":1}");
348 EXPECT_TRUE(HasEndpoint("https://endpoint/"));
349
350 clock_->Advance(base::TimeDelta::FromSeconds(2));
351 service_->CollectGarbageForTesting();
352 EXPECT_FALSE(HasEndpoint("https://endpoint/"));
353 }
354
355 TEST_F(ReportingServiceTest, UnusedEndpoint) {
356 CreateServiceWithDefaultPolicy();
357
358 service_->ProcessHeader(
359 GURL("https://origin/"),
360 "{\"url\":\"https://endpoint/\",\"max-age\":999999999}");
361 EXPECT_TRUE(HasEndpoint("https://endpoint/"));
362
363 clock_->Advance(2 * policy_.endpoint_lifetime);
364 service_->CollectGarbageForTesting();
365 EXPECT_FALSE(HasEndpoint("https://endpoint/"));
366 }
367
368 TEST_F(ReportingServiceTest, FailedEndpoint) {
369 ReportingService::Policy policy;
370 policy.endpoint_backoff.initial_delay_ms = 0;
371 policy.endpoint_backoff.maximum_backoff_ms = 0;
372 policy.endpoint_backoff.entry_lifetime_ms = 1000;
373 policy.max_endpoint_failures = 3;
374 policy.max_report_failures = -1;
375 CreateServiceWithPolicy(policy);
376
377 service_->ProcessHeader(
378 GURL("https://origin/"),
379 "{\"url\":\"https://endpoint/\",\"max-age\":999999999}");
380 QueueReport(GURL("https://origin/"));
381
382 for (int i = 0; i < policy_.max_endpoint_failures + 1; i++) {
383 EXPECT_TRUE(HasEndpoint("https://endpoint/"));
384 service_->SendReports();
385 ASSERT_EQ(1u, GetPendingDeliveries().size());
386 GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
387 }
388 EXPECT_TRUE(HasEndpoint("https://endpoint/"));
389
390 clock_->Advance(base::TimeDelta::FromMilliseconds(
391 2 * policy_.endpoint_backoff.entry_lifetime_ms));
392
393 service_->CollectGarbageForTesting();
394 EXPECT_FALSE(HasEndpoint("https://endpoint/"));
395 }
396
397 TEST_F(ReportingServiceTest, EvictedEndpoint) {
398 ReportingService::Policy policy;
399 policy.max_endpoint_count = 1;
400 CreateServiceWithPolicy(policy);
401
402 service_->ProcessHeader(GURL("https://origin1/"),
403 "{\"url\":\"https://endpoint1/\",\"max-age\":1}");
404 EXPECT_TRUE(HasEndpoint("https://endpoint1"));
405
406 service_->ProcessHeader(GURL("https://origin2/"),
407 "{\"url\":\"https://endpoint2/\",\"max-age\":1}");
408 EXPECT_FALSE(HasEndpoint("https://endpoint1"));
409 EXPECT_TRUE(HasEndpoint("https://endpoint2"));
410 }
411
412 TEST_F(ReportingServiceTest, ExpiredReport) {
413 CreateServiceWithDefaultPolicy();
414
415 QueueReport(GURL("https://origin/"));
416 ASSERT_EQ(1u, GetReportCount());
417
418 clock_->Advance(policy_.report_lifetime / 2);
419 service_->CollectGarbageForTesting();
420 ASSERT_EQ(1u, GetReportCount());
421
422 clock_->Advance(policy_.report_lifetime);
423 service_->CollectGarbageForTesting();
424 EXPECT_EQ(0u, GetReportCount());
425 }
426
427 TEST_F(ReportingServiceTest, FailedReport) {
428 ReportingService::Policy policy;
429 policy.endpoint_backoff.initial_delay_ms = 0;
430 policy.endpoint_backoff.maximum_backoff_ms = 0;
431 policy.endpoint_backoff.entry_lifetime_ms = 0;
432 policy.max_endpoint_failures = 1000;
433 policy.max_report_failures = 3;
434 CreateServiceWithPolicy(policy);
435
436 service_->ProcessHeader(
437 GURL("https://origin/"),
438 "{\"url\":\"https://endpoint/\",\"max-age\":999999999}");
439 QueueReport(GURL("https://origin/"));
440
441 for (size_t i = 0; i < policy_.max_report_failures + 1; i++) {
442 EXPECT_EQ(1u, GetReportCount());
443 service_->SendReports();
444 ASSERT_EQ(1u, GetPendingDeliveries().size());
445 GetPendingDeliveries()[0]->Complete(ReportingUploader::FAILURE);
446 }
447 EXPECT_EQ(0u, GetReportCount());
448 }
449
450 TEST_F(ReportingServiceTest, EvictedReport) {
451 ReportingService::Policy policy;
452 policy.max_report_count = 3;
453 CreateServiceWithPolicy(policy);
454
455 for (size_t i = 0; i < policy_.max_report_count; i++) {
456 QueueReport(GURL("https://origin/"));
457 EXPECT_EQ(static_cast<size_t>(i + 1), GetReportCount());
458 }
459 QueueReport(GURL("https://origin/"));
460 EXPECT_EQ(static_cast<size_t>(policy_.max_report_count), GetReportCount());
461 }
462
463 TEST_F(ReportingServiceTest, NetworkChangePersist) {
464 ReportingService::Policy policy;
465 policy.persist_reports_across_network_changes = true;
466 CreateServiceWithPolicy(policy);
467
468 QueueReport(GURL("https://origin/"));
469 EXPECT_EQ(1u, GetReportCount());
470
471 MockNetworkChange();
472 EXPECT_EQ(1u, GetReportCount());
473 }
474
475 TEST_F(ReportingServiceTest, NetworkChangeClear) {
476 ReportingService::Policy policy;
477 policy.persist_reports_across_network_changes = false;
478 CreateServiceWithPolicy(policy);
479
480 QueueReport(GURL("https://origin/"));
481 EXPECT_EQ(1u, GetReportCount());
482
483 MockNetworkChange();
484 EXPECT_EQ(0u, GetReportCount());
485 }
486
487 } // namespace
488 } // namespace net
OLDNEW
« no previous file with comments | « net/reporting/reporting_service.cc ('k') | net/reporting/reporting_uploader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698