xref: /aosp_15_r20/external/cronet/net/reporting/reporting_delivery_agent_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 The Chromium Authors
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 <optional>
8 #include <vector>
9 
10 #include "base/json/json_reader.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/test/metrics/histogram_tester.h"
13 #include "base/test/scoped_feature_list.h"
14 #include "base/test/simple_test_tick_clock.h"
15 #include "base/test/values_test_util.h"
16 #include "base/time/time.h"
17 #include "base/timer/mock_timer.h"
18 #include "base/unguessable_token.h"
19 #include "base/values.h"
20 #include "net/base/backoff_entry.h"
21 #include "net/base/features.h"
22 #include "net/base/isolation_info.h"
23 #include "net/base/network_anonymization_key.h"
24 #include "net/base/schemeful_site.h"
25 #include "net/reporting/reporting_cache.h"
26 #include "net/reporting/reporting_report.h"
27 #include "net/reporting/reporting_test_util.h"
28 #include "net/reporting/reporting_uploader.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "url/gurl.h"
31 #include "url/origin.h"
32 
33 namespace net {
34 namespace {
35 
36 constexpr char kReportingUploadHeaderTypeHistogram[] =
37     "Net.Reporting.UploadHeaderType";
38 
39 class ReportingDeliveryAgentTest : public ReportingTestBase {
40  protected:
ReportingDeliveryAgentTest()41   ReportingDeliveryAgentTest() {
42     // This is a private API of the reporting service, so no need to test the
43     // case kPartitionNelAndReportingByNetworkIsolationKey is disabled - the
44     // feature is only applied at the entry points of the service.
45     feature_list_.InitAndEnableFeature(
46         features::kPartitionNelAndReportingByNetworkIsolationKey);
47 
48     ReportingPolicy policy;
49     policy.endpoint_backoff_policy.num_errors_to_ignore = 0;
50     policy.endpoint_backoff_policy.initial_delay_ms = 60000;
51     policy.endpoint_backoff_policy.multiply_factor = 2.0;
52     policy.endpoint_backoff_policy.jitter_factor = 0.0;
53     policy.endpoint_backoff_policy.maximum_backoff_ms = -1;
54     policy.endpoint_backoff_policy.entry_lifetime_ms = 0;
55     policy.endpoint_backoff_policy.always_use_initial_delay = false;
56     UsePolicy(policy);
57   }
58 
AddReport(const std::optional<base::UnguessableToken> & reporting_source,const NetworkAnonymizationKey & network_anonymization_key,const GURL & url,const std::string & group)59   void AddReport(const std::optional<base::UnguessableToken>& reporting_source,
60                  const NetworkAnonymizationKey& network_anonymization_key,
61                  const GURL& url,
62                  const std::string& group) {
63     base::Value::Dict report_body;
64     report_body.Set("key", "value");
65     cache()->AddReport(reporting_source, network_anonymization_key, url,
66                        kUserAgent_, group, kType_, std::move(report_body),
67                        0 /* depth */, tick_clock()->NowTicks() /* queued */,
68                        0 /* attempts */);
69   }
70 
71   // The first report added to the cache is uploaded immediately, and a timer is
72   // started for all subsequent reports (which may then be batched). To test
73   // behavior involving batching multiple reports, we need to add, upload, and
74   // immediately resolve a dummy report to prime the delivery timer.
UploadFirstReportAndStartTimer()75   void UploadFirstReportAndStartTimer() {
76     ReportingEndpointGroupKey dummy_group(
77         NetworkAnonymizationKey(),
78         url::Origin::Create(GURL("https://dummy.test")), "dummy");
79     ASSERT_TRUE(SetEndpointInCache(
80         dummy_group, GURL("https://dummy.test/upload"), kExpires_));
81     AddReport(std::nullopt, dummy_group.network_anonymization_key,
82               dummy_group.origin.GetURL(), dummy_group.group_name);
83 
84     ASSERT_EQ(1u, pending_uploads().size());
85     pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
86     EXPECT_EQ(0u, pending_uploads().size());
87     EXPECT_TRUE(delivery_timer()->IsRunning());
88   }
89 
90   // Prime delivery timer with a document report with a endpoint group that
91   // has matching reporting_source.
UploadFirstDocumentReportAndStartTimer()92   void UploadFirstDocumentReportAndStartTimer() {
93     ReportingEndpointGroupKey dummy_group(
94         kNak_, kDocumentReportingSource_,
95         url::Origin::Create(GURL("https://dummy.test")), "dummy");
96     SetV1EndpointInCache(dummy_group, kDocumentReportingSource_,
97                          kIsolationInfo_, GURL("https://dummy.test/upload"));
98     AddReport(kDocumentReportingSource_, dummy_group.network_anonymization_key,
99               dummy_group.origin.GetURL(), dummy_group.group_name);
100 
101     ASSERT_EQ(1u, pending_uploads().size());
102     pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
103     EXPECT_EQ(0u, pending_uploads().size());
104     EXPECT_TRUE(delivery_timer()->IsRunning());
105   }
106 
SendReportsForSource(base::UnguessableToken reporting_source)107   void SendReportsForSource(base::UnguessableToken reporting_source) {
108     delivery_agent()->SendReportsForSource(reporting_source);
109   }
110 
111   base::test::ScopedFeatureList feature_list_;
112 
113   const GURL kUrl_ = GURL("https://origin/path");
114   const GURL kOtherUrl_ = GURL("https://other-origin/path");
115   const GURL kSubdomainUrl_ = GURL("https://sub.origin/path");
116   const url::Origin kOrigin_ = url::Origin::Create(GURL("https://origin/"));
117   const url::Origin kOtherOrigin_ =
118       url::Origin::Create(GURL("https://other-origin/"));
119   const std::optional<base::UnguessableToken> kEmptyReportingSource_ =
120       std::nullopt;
121   const base::UnguessableToken kDocumentReportingSource_ =
122       base::UnguessableToken::Create();
123   const NetworkAnonymizationKey kNak_ =
124       NetworkAnonymizationKey::CreateSameSite(SchemefulSite(kOrigin_));
125   const NetworkAnonymizationKey kOtherNak_ =
126       NetworkAnonymizationKey::CreateSameSite(SchemefulSite(kOtherOrigin_));
127   const IsolationInfo kIsolationInfo_ =
128       IsolationInfo::Create(IsolationInfo::RequestType::kOther,
129                             kOrigin_,
130                             kOrigin_,
131                             SiteForCookies::FromOrigin(kOrigin_));
132   const IsolationInfo kOtherIsolationInfo_ =
133       IsolationInfo::Create(IsolationInfo::RequestType::kOther,
134                             kOtherOrigin_,
135                             kOtherOrigin_,
136                             SiteForCookies::FromOrigin(kOtherOrigin_));
137   const GURL kEndpoint_ = GURL("https://endpoint/");
138   const std::string kUserAgent_ = "Mozilla/1.0";
139   const std::string kGroup_ = "group";
140   const std::string kType_ = "type";
141   const base::Time kExpires_ = base::Time::Now() + base::Days(7);
142   const ReportingEndpointGroupKey kGroupKey_ =
143       ReportingEndpointGroupKey(kNak_, kOrigin_, kGroup_);
144   const ReportingEndpointGroupKey kDocumentGroupKey_ =
145       ReportingEndpointGroupKey(kGroupKey_, kDocumentReportingSource_);
146 };
147 
TEST_F(ReportingDeliveryAgentTest,SuccessfulImmediateUpload)148 TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateUpload) {
149   base::HistogramTester histograms;
150   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
151   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
152 
153   // Upload is automatically started when cache is modified.
154 
155   ASSERT_EQ(1u, pending_uploads().size());
156   EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
157   {
158     auto value = pending_uploads()[0]->GetValue();
159 
160     ASSERT_TRUE(value->is_list());
161     ASSERT_EQ(1u, value->GetList().size());
162 
163     const base::Value& report = value->GetList()[0];
164     ASSERT_TRUE(report.is_dict());
165     const base::Value::Dict& report_dict = report.GetDict();
166     EXPECT_EQ(5u, report_dict.size());
167 
168     ExpectDictIntegerValue(0, report_dict, "age");
169     ExpectDictStringValue(kType_, report_dict, "type");
170     ExpectDictStringValue(kUrl_.spec(), report_dict, "url");
171     ExpectDictStringValue(kUserAgent_, report_dict, "user_agent");
172     const base::Value::Dict* body = report_dict.FindDict("body");
173     EXPECT_EQ("value", *body->FindString("key"));
174   }
175   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
176 
177   // Successful upload should remove delivered reports.
178   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
179   cache()->GetReports(&reports);
180   EXPECT_TRUE(reports.empty());
181   histograms.ExpectBucketCount(
182       kReportingUploadHeaderTypeHistogram,
183       ReportingDeliveryAgent::ReportingUploadHeaderType::kReportTo, 1);
184   histograms.ExpectBucketCount(
185       kReportingUploadHeaderTypeHistogram,
186       ReportingDeliveryAgent::ReportingUploadHeaderType::kReportingEndpoints,
187       0);
188 
189   {
190     ReportingEndpoint::Statistics stats =
191         GetEndpointStatistics(kGroupKey_, kEndpoint_);
192     EXPECT_EQ(1, stats.attempted_uploads);
193     EXPECT_EQ(1, stats.successful_uploads);
194     EXPECT_EQ(1, stats.attempted_reports);
195     EXPECT_EQ(1, stats.successful_reports);
196   }
197 
198   // TODO(dcreager): Check that BackoffEntry was informed of success.
199 }
200 
TEST_F(ReportingDeliveryAgentTest,ReportToHeaderCountedCorrectly)201 TEST_F(ReportingDeliveryAgentTest, ReportToHeaderCountedCorrectly) {
202   base::HistogramTester histograms;
203 
204   // Set an endpoint with no reporting source (as if configured with the
205   // Report-To header).
206   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
207 
208   // Add and upload a report with an associated source.
209   AddReport(kDocumentReportingSource_, kNak_, kUrl_, kGroup_);
210   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
211 
212   // Successful upload should count this as a Report-To delivery, even though
213   // the report itself had a reporting source.
214   histograms.ExpectBucketCount(
215       kReportingUploadHeaderTypeHistogram,
216       ReportingDeliveryAgent::ReportingUploadHeaderType::kReportTo, 1);
217   histograms.ExpectBucketCount(
218       kReportingUploadHeaderTypeHistogram,
219       ReportingDeliveryAgent::ReportingUploadHeaderType::kReportingEndpoints,
220       0);
221 }
222 
TEST_F(ReportingDeliveryAgentTest,SuccessfulImmediateUploadDocumentReport)223 TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateUploadDocumentReport) {
224   base::HistogramTester histograms;
225 
226   SetV1EndpointInCache(kDocumentGroupKey_, kDocumentReportingSource_,
227                        kIsolationInfo_, kEndpoint_);
228   AddReport(kDocumentReportingSource_, kNak_, kUrl_, kGroup_);
229 
230   // Upload is automatically started when cache is modified.
231 
232   ASSERT_EQ(1u, pending_uploads().size());
233   EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
234   {
235     const auto value = pending_uploads()[0]->GetValue();
236 
237     ASSERT_TRUE(value->is_list());
238     ASSERT_EQ(1u, value->GetList().size());
239 
240     const base::Value& report = value->GetList()[0];
241     ASSERT_TRUE(report.is_dict());
242     const base::Value::Dict& report_dict = report.GetDict();
243 
244     ExpectDictIntegerValue(0, report_dict, "age");
245     ExpectDictStringValue(kType_, report_dict, "type");
246     ExpectDictStringValue(kUrl_.spec(), report_dict, "url");
247     ExpectDictStringValue(kUserAgent_, report_dict, "user_agent");
248     const base::Value::Dict* body = report_dict.FindDict("body");
249     EXPECT_EQ("value", *body->FindString("key"));
250   }
251   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
252 
253   // Successful upload should remove delivered reports.
254   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
255   cache()->GetReports(&reports);
256   EXPECT_TRUE(reports.empty());
257   histograms.ExpectBucketCount(
258       kReportingUploadHeaderTypeHistogram,
259       ReportingDeliveryAgent::ReportingUploadHeaderType::kReportingEndpoints,
260       1);
261   histograms.ExpectBucketCount(
262       kReportingUploadHeaderTypeHistogram,
263       ReportingDeliveryAgent::ReportingUploadHeaderType::kReportTo, 0);
264 
265   {
266     ReportingEndpoint::Statistics stats =
267         GetEndpointStatistics(kDocumentGroupKey_, kEndpoint_);
268     EXPECT_EQ(1, stats.attempted_uploads);
269     EXPECT_EQ(1, stats.successful_uploads);
270     EXPECT_EQ(1, stats.attempted_reports);
271     EXPECT_EQ(1, stats.successful_reports);
272   }
273 }
274 
TEST_F(ReportingDeliveryAgentTest,UploadHeaderTypeEnumCountPerReport)275 TEST_F(ReportingDeliveryAgentTest, UploadHeaderTypeEnumCountPerReport) {
276   UploadFirstDocumentReportAndStartTimer();
277   base::HistogramTester histograms;
278 
279   SetV1EndpointInCache(kDocumentGroupKey_, kDocumentReportingSource_,
280                        kIsolationInfo_, kEndpoint_);
281   AddReport(kDocumentReportingSource_, kNak_, kUrl_, kGroup_);
282   AddReport(kDocumentReportingSource_, kNak_, kUrl_, kGroup_);
283 
284   // There should be one upload per (NAK, origin, reporting source).
285   EXPECT_TRUE(delivery_timer()->IsRunning());
286   delivery_timer()->Fire();
287 
288   ASSERT_EQ(1u, pending_uploads().size());
289   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
290 
291   // Successful upload should remove delivered reports.
292   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
293   cache()->GetReports(&reports);
294   EXPECT_TRUE(reports.empty());
295   histograms.ExpectBucketCount(
296       kReportingUploadHeaderTypeHistogram,
297       ReportingDeliveryAgent::ReportingUploadHeaderType::kReportingEndpoints,
298       2);
299   histograms.ExpectBucketCount(
300       kReportingUploadHeaderTypeHistogram,
301       ReportingDeliveryAgent::ReportingUploadHeaderType::kReportTo, 0);
302 }
303 
TEST_F(ReportingDeliveryAgentTest,SuccessfulImmediateSubdomainUpload)304 TEST_F(ReportingDeliveryAgentTest, SuccessfulImmediateSubdomainUpload) {
305   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_,
306                                  OriginSubdomains::INCLUDE));
307   AddReport(kEmptyReportingSource_, kNak_, kSubdomainUrl_, kGroup_);
308 
309   // Upload is automatically started when cache is modified.
310 
311   ASSERT_EQ(1u, pending_uploads().size());
312   EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
313   {
314     auto value = pending_uploads()[0]->GetValue();
315 
316     ASSERT_TRUE(value->is_list());
317     ASSERT_EQ(1u, value->GetList().size());
318 
319     const base::Value& report = value->GetList()[0];
320     ASSERT_TRUE(report.is_dict());
321     const base::Value::Dict& report_dict = report.GetDict();
322     EXPECT_EQ(5u, report_dict.size());
323 
324     ExpectDictIntegerValue(0, report_dict, "age");
325     ExpectDictStringValue(kType_, report_dict, "type");
326     ExpectDictStringValue(kSubdomainUrl_.spec(), report_dict, "url");
327     ExpectDictStringValue(kUserAgent_, report_dict, "user_agent");
328     const base::Value::Dict* body = report_dict.FindDict("body");
329     EXPECT_EQ("value", *body->FindString("key"));
330   }
331   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
332 
333   // Successful upload should remove delivered reports.
334   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
335   cache()->GetReports(&reports);
336   EXPECT_TRUE(reports.empty());
337 
338   {
339     ReportingEndpoint::Statistics stats =
340         GetEndpointStatistics(kGroupKey_, kEndpoint_);
341     EXPECT_EQ(1, stats.attempted_uploads);
342     EXPECT_EQ(1, stats.successful_uploads);
343     EXPECT_EQ(1, stats.attempted_reports);
344     EXPECT_EQ(1, stats.successful_reports);
345   }
346 
347   // TODO(dcreager): Check that BackoffEntry was informed of success.
348 }
349 
TEST_F(ReportingDeliveryAgentTest,SuccessfulImmediateSubdomainUploadWithOverwrittenEndpoint)350 TEST_F(ReportingDeliveryAgentTest,
351        SuccessfulImmediateSubdomainUploadWithOverwrittenEndpoint) {
352   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_,
353                                  OriginSubdomains::INCLUDE));
354   AddReport(kEmptyReportingSource_, kNak_, kSubdomainUrl_, kGroup_);
355 
356   // Upload is automatically started when cache is modified.
357 
358   ASSERT_EQ(1u, pending_uploads().size());
359   // Change the endpoint group to exclude subdomains.
360   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_,
361                                  OriginSubdomains::EXCLUDE));
362   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
363 
364   {
365     ReportingEndpoint::Statistics stats =
366         GetEndpointStatistics(kGroupKey_, kEndpoint_);
367     EXPECT_EQ(1, stats.attempted_uploads);
368     EXPECT_EQ(1, stats.successful_uploads);
369     EXPECT_EQ(1, stats.attempted_reports);
370     EXPECT_EQ(1, stats.successful_reports);
371   }
372 
373   // Successful upload should remove delivered reports.
374   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
375   cache()->GetReports(&reports);
376   EXPECT_TRUE(reports.empty());
377 }
378 
TEST_F(ReportingDeliveryAgentTest,SuccessfulDelayedUpload)379 TEST_F(ReportingDeliveryAgentTest, SuccessfulDelayedUpload) {
380   // Trigger and complete an upload to start the delivery timer.
381   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
382   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
383   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
384 
385   // Add another report to upload after a delay.
386   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
387 
388   EXPECT_TRUE(delivery_timer()->IsRunning());
389   delivery_timer()->Fire();
390 
391   ASSERT_EQ(1u, pending_uploads().size());
392   EXPECT_EQ(kEndpoint_, pending_uploads()[0]->url());
393   {
394     auto value = pending_uploads()[0]->GetValue();
395 
396     ASSERT_TRUE(value->is_list());
397     ASSERT_EQ(1u, value->GetList().size());
398 
399     const base::Value& report = value->GetList()[0];
400     ASSERT_TRUE(report.is_dict());
401     const base::Value::Dict& report_dict = report.GetDict();
402     EXPECT_EQ(5u, report_dict.size());
403 
404     ExpectDictIntegerValue(0, report_dict, "age");
405     ExpectDictStringValue(kType_, report_dict, "type");
406     ExpectDictStringValue(kUrl_.spec(), report_dict, "url");
407     ExpectDictStringValue(kUserAgent_, report_dict, "user_agent");
408     const base::Value::Dict* body = report_dict.FindDict("body");
409     EXPECT_EQ("value", *body->FindString("key"));
410   }
411   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
412 
413   {
414     ReportingEndpoint::Statistics stats =
415         GetEndpointStatistics(kGroupKey_, kEndpoint_);
416     EXPECT_EQ(2, stats.attempted_uploads);
417     EXPECT_EQ(2, stats.successful_uploads);
418     EXPECT_EQ(2, stats.attempted_reports);
419     EXPECT_EQ(2, stats.successful_reports);
420   }
421 
422   // Successful upload should remove delivered reports.
423   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
424   cache()->GetReports(&reports);
425   EXPECT_TRUE(reports.empty());
426 
427   // TODO(juliatuttle): Check that BackoffEntry was informed of success.
428 }
429 
TEST_F(ReportingDeliveryAgentTest,FailedUpload)430 TEST_F(ReportingDeliveryAgentTest, FailedUpload) {
431   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
432   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
433 
434   EXPECT_TRUE(delivery_timer()->IsRunning());
435   delivery_timer()->Fire();
436 
437   ASSERT_EQ(1u, pending_uploads().size());
438   pending_uploads()[0]->Complete(ReportingUploader::Outcome::FAILURE);
439 
440   {
441     ReportingEndpoint::Statistics stats =
442         GetEndpointStatistics(kGroupKey_, kEndpoint_);
443     EXPECT_EQ(1, stats.attempted_uploads);
444     EXPECT_EQ(0, stats.successful_uploads);
445     EXPECT_EQ(1, stats.attempted_reports);
446     EXPECT_EQ(0, stats.successful_reports);
447   }
448 
449   // Failed upload should increment reports' attempts.
450   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
451   cache()->GetReports(&reports);
452   ASSERT_EQ(1u, reports.size());
453   EXPECT_EQ(1, reports[0]->attempts);
454 
455   // Since endpoint is now failing, an upload won't be started despite a pending
456   // report.
457   ASSERT_TRUE(pending_uploads().empty());
458   EXPECT_TRUE(delivery_timer()->IsRunning());
459   delivery_timer()->Fire();
460   EXPECT_TRUE(pending_uploads().empty());
461 
462   {
463     ReportingEndpoint::Statistics stats =
464         GetEndpointStatistics(kGroupKey_, kEndpoint_);
465     EXPECT_EQ(1, stats.attempted_uploads);
466     EXPECT_EQ(0, stats.successful_uploads);
467     EXPECT_EQ(1, stats.attempted_reports);
468     EXPECT_EQ(0, stats.successful_reports);
469   }
470 }
471 
TEST_F(ReportingDeliveryAgentTest,DisallowedUpload)472 TEST_F(ReportingDeliveryAgentTest, DisallowedUpload) {
473   // This mimics the check that is controlled by the BACKGROUND_SYNC permission
474   // in a real browser profile.
475   context()->test_delegate()->set_disallow_report_uploads(true);
476 
477   static const int kAgeMillis = 12345;
478 
479   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
480   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
481 
482   tick_clock()->Advance(base::Milliseconds(kAgeMillis));
483 
484   EXPECT_TRUE(delivery_timer()->IsRunning());
485   delivery_timer()->Fire();
486 
487   // We should not try to upload the report, since we weren't given permission
488   // for this origin.
489   EXPECT_TRUE(pending_uploads().empty());
490 
491   {
492     ReportingEndpoint::Statistics stats =
493         GetEndpointStatistics(kGroupKey_, kEndpoint_);
494     EXPECT_EQ(0, stats.attempted_uploads);
495     EXPECT_EQ(0, stats.successful_uploads);
496     EXPECT_EQ(0, stats.attempted_reports);
497     EXPECT_EQ(0, stats.successful_reports);
498   }
499 
500   // Disallowed reports should NOT have been removed from the cache.
501   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
502   cache()->GetReports(&reports);
503   EXPECT_EQ(1u, reports.size());
504 }
505 
TEST_F(ReportingDeliveryAgentTest,RemoveEndpointUpload)506 TEST_F(ReportingDeliveryAgentTest, RemoveEndpointUpload) {
507   static const ReportingEndpointGroupKey kOtherGroupKey(kNak_, kOtherOrigin_,
508                                                         kGroup_);
509 
510   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
511   ASSERT_TRUE(SetEndpointInCache(kOtherGroupKey, kEndpoint_, kExpires_));
512 
513   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
514 
515   EXPECT_TRUE(delivery_timer()->IsRunning());
516   delivery_timer()->Fire();
517 
518   ASSERT_EQ(1u, pending_uploads().size());
519   pending_uploads()[0]->Complete(ReportingUploader::Outcome::REMOVE_ENDPOINT);
520 
521   // "Remove endpoint" upload should remove endpoint from *all* origins and
522   // increment reports' attempts.
523   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
524   cache()->GetReports(&reports);
525   ASSERT_EQ(1u, reports.size());
526   EXPECT_EQ(1, reports[0]->attempts);
527 
528   EXPECT_FALSE(FindEndpointInCache(kGroupKey_, kEndpoint_));
529   EXPECT_FALSE(FindEndpointInCache(kOtherGroupKey, kEndpoint_));
530 
531   // Since endpoint is now failing, an upload won't be started despite a pending
532   // report.
533   EXPECT_TRUE(delivery_timer()->IsRunning());
534   delivery_timer()->Fire();
535   EXPECT_TRUE(pending_uploads().empty());
536 }
537 
TEST_F(ReportingDeliveryAgentTest,ConcurrentRemove)538 TEST_F(ReportingDeliveryAgentTest, ConcurrentRemove) {
539   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
540   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
541 
542   EXPECT_TRUE(delivery_timer()->IsRunning());
543   delivery_timer()->Fire();
544   ASSERT_EQ(1u, pending_uploads().size());
545 
546   // Remove the report while the upload is running.
547   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
548   cache()->GetReports(&reports);
549   EXPECT_EQ(1u, reports.size());
550 
551   const ReportingReport* report = reports[0];
552   EXPECT_FALSE(cache()->IsReportDoomedForTesting(report));
553 
554   // Report should appear removed, even though the cache has doomed it.
555   cache()->RemoveReports(reports);
556   cache()->GetReports(&reports);
557   EXPECT_TRUE(reports.empty());
558   EXPECT_TRUE(cache()->IsReportDoomedForTesting(report));
559 
560   // Completing upload shouldn't crash, and report should still be gone.
561   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
562   cache()->GetReports(&reports);
563   EXPECT_TRUE(reports.empty());
564 }
565 
TEST_F(ReportingDeliveryAgentTest,ConcurrentRemoveDuringPermissionsCheck)566 TEST_F(ReportingDeliveryAgentTest, ConcurrentRemoveDuringPermissionsCheck) {
567   // Pause the permissions check, so that we can try to remove some reports
568   // while we're in the middle of verifying that we can upload them.  (This is
569   // similar to the previous test, but removes the reports during a different
570   // part of the upload process.)
571   context()->test_delegate()->set_pause_permissions_check(true);
572 
573   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
574   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
575 
576   ASSERT_TRUE(context()->test_delegate()->PermissionsCheckPaused());
577 
578   // Remove the report while the upload is running.
579   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
580   cache()->GetReports(&reports);
581   EXPECT_EQ(1u, reports.size());
582 
583   const ReportingReport* report = reports[0];
584   EXPECT_FALSE(cache()->IsReportDoomedForTesting(report));
585 
586   // Report should appear removed, even though the cache has doomed it.
587   cache()->RemoveReports(reports);
588   cache()->GetReports(&reports);
589   EXPECT_TRUE(reports.empty());
590   EXPECT_TRUE(cache()->IsReportDoomedForTesting(report));
591 
592   // Completing upload shouldn't crash, and report should still be gone.
593   context()->test_delegate()->ResumePermissionsCheck();
594   ASSERT_EQ(1u, pending_uploads().size());
595   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
596   cache()->GetReports(&reports);
597   EXPECT_TRUE(reports.empty());
598 }
599 
600 // Reports uploaded together must share a NAK and origin.
601 // Test that the agent will not combine reports destined for the same endpoint
602 // if the reports are from different origins or NAKs, but does combine all
603 // reports for the same (NAK, origin).
TEST_F(ReportingDeliveryAgentTest,OnlyBatchSameNakAndOrigin)604 TEST_F(ReportingDeliveryAgentTest, OnlyBatchSameNakAndOrigin) {
605   const ReportingEndpointGroupKey kGroupKeys[] = {
606       ReportingEndpointGroupKey(kNak_, kOrigin_, kGroup_),
607       ReportingEndpointGroupKey(kNak_, kOtherOrigin_, kGroup_),
608       ReportingEndpointGroupKey(kOtherNak_, kOrigin_, kGroup_),
609       ReportingEndpointGroupKey(kOtherNak_, kOtherOrigin_, kGroup_),
610   };
611   for (const ReportingEndpointGroupKey& group_key : kGroupKeys) {
612     ASSERT_TRUE(SetEndpointInCache(group_key, kEndpoint_, kExpires_));
613   }
614 
615   // Trigger and complete an upload to start the delivery timer.
616   UploadFirstReportAndStartTimer();
617 
618   // Now that the delivery timer is running, these reports won't be immediately
619   // uploaded.
620   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
621   AddReport(kEmptyReportingSource_, kNak_, kOtherUrl_, kGroup_);
622   AddReport(kEmptyReportingSource_, kNak_, kOtherUrl_, kGroup_);
623   AddReport(kEmptyReportingSource_, kOtherNak_, kUrl_, kGroup_);
624   AddReport(kEmptyReportingSource_, kOtherNak_, kUrl_, kGroup_);
625   AddReport(kEmptyReportingSource_, kOtherNak_, kUrl_, kGroup_);
626   AddReport(kEmptyReportingSource_, kOtherNak_, kOtherUrl_, kGroup_);
627   AddReport(kEmptyReportingSource_, kOtherNak_, kOtherUrl_, kGroup_);
628   AddReport(kEmptyReportingSource_, kOtherNak_, kOtherUrl_, kGroup_);
629   AddReport(kEmptyReportingSource_, kOtherNak_, kOtherUrl_, kGroup_);
630   EXPECT_EQ(0u, pending_uploads().size());
631 
632   // There should be one upload per (NAK, origin).
633   EXPECT_TRUE(delivery_timer()->IsRunning());
634   delivery_timer()->Fire();
635   ASSERT_EQ(4u, pending_uploads().size());
636 
637   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
638   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
639   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
640   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
641   EXPECT_EQ(0u, pending_uploads().size());
642 
643   for (int i = 0; i < 4; ++i) {
644     ReportingEndpoint::Statistics stats =
645         GetEndpointStatistics(kGroupKeys[i], kEndpoint_);
646     EXPECT_EQ(1, stats.attempted_uploads);
647     EXPECT_EQ(1, stats.successful_uploads);
648     EXPECT_EQ(i + 1, stats.attempted_reports);
649     EXPECT_EQ(i + 1, stats.successful_reports);
650   }
651 }
652 
653 // Test that the agent won't start a second upload for a (NAK, origin, group)
654 // while one is pending, even if a different endpoint is available, but will
655 // once the original delivery is complete and the (NAK, origin, group) is no
656 // longer pending.
TEST_F(ReportingDeliveryAgentTest,SerializeUploadsToGroup)657 TEST_F(ReportingDeliveryAgentTest, SerializeUploadsToGroup) {
658   static const GURL kDifferentEndpoint("https://endpoint2/");
659 
660   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
661   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kDifferentEndpoint, kExpires_));
662 
663   // Trigger and complete an upload to start the delivery timer.
664   UploadFirstReportAndStartTimer();
665 
666   // First upload causes this group key to become pending.
667   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
668   EXPECT_EQ(0u, pending_uploads().size());
669   EXPECT_TRUE(delivery_timer()->IsRunning());
670   delivery_timer()->Fire();
671   EXPECT_EQ(1u, pending_uploads().size());
672 
673   // Second upload isn't started because the group is pending.
674   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
675   EXPECT_TRUE(delivery_timer()->IsRunning());
676   delivery_timer()->Fire();
677   ASSERT_EQ(1u, pending_uploads().size());
678 
679   // Resolve the first upload.
680   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
681   EXPECT_EQ(0u, pending_uploads().size());
682 
683   // Now the other upload can happen.
684   EXPECT_TRUE(delivery_timer()->IsRunning());
685   delivery_timer()->Fire();
686   ASSERT_EQ(1u, pending_uploads().size());
687   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
688   EXPECT_EQ(0u, pending_uploads().size());
689 
690   // A total of 2 reports were uploaded.
691   {
692     ReportingEndpoint::Statistics stats =
693         GetEndpointStatistics(kGroupKey_, kEndpoint_);
694     ReportingEndpoint::Statistics different_stats =
695         GetEndpointStatistics(kGroupKey_, kDifferentEndpoint);
696     EXPECT_EQ(2, stats.attempted_uploads + different_stats.attempted_uploads);
697     EXPECT_EQ(2, stats.successful_uploads + different_stats.successful_uploads);
698     EXPECT_EQ(2, stats.attempted_reports + different_stats.attempted_reports);
699     EXPECT_EQ(2, stats.successful_reports + different_stats.successful_reports);
700   }
701 }
702 
703 // Tests that the agent will start parallel uploads to different groups within
704 // the same (NAK, origin) to endpoints with different URLs.
TEST_F(ReportingDeliveryAgentTest,ParallelizeUploadsAcrossGroups)705 TEST_F(ReportingDeliveryAgentTest, ParallelizeUploadsAcrossGroups) {
706   static const GURL kDifferentEndpoint("https://endpoint2/");
707   static const std::string kDifferentGroup("group2");
708   const ReportingEndpointGroupKey kDifferentGroupKey(kNak_, kOrigin_,
709                                                      kDifferentGroup);
710 
711   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
712   ASSERT_TRUE(
713       SetEndpointInCache(kDifferentGroupKey, kDifferentEndpoint, kExpires_));
714 
715   // Trigger and complete an upload to start the delivery timer.
716   UploadFirstReportAndStartTimer();
717 
718   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
719   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kDifferentGroup);
720 
721   EXPECT_TRUE(delivery_timer()->IsRunning());
722   delivery_timer()->Fire();
723   ASSERT_EQ(2u, pending_uploads().size());
724 
725   pending_uploads()[1]->Complete(ReportingUploader::Outcome::SUCCESS);
726   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
727   EXPECT_EQ(0u, pending_uploads().size());
728 
729   {
730     ReportingEndpoint::Statistics stats =
731         GetEndpointStatistics(kGroupKey_, kEndpoint_);
732     EXPECT_EQ(1, stats.attempted_uploads);
733     EXPECT_EQ(1, stats.successful_uploads);
734     EXPECT_EQ(1, stats.attempted_reports);
735     EXPECT_EQ(1, stats.successful_reports);
736   }
737   {
738     ReportingEndpoint::Statistics stats =
739         GetEndpointStatistics(kDifferentGroupKey, kDifferentEndpoint);
740     EXPECT_EQ(1, stats.attempted_uploads);
741     EXPECT_EQ(1, stats.successful_uploads);
742     EXPECT_EQ(1, stats.attempted_reports);
743     EXPECT_EQ(1, stats.successful_reports);
744   }
745 }
746 
747 // Tests that the agent will include reports for different groups for the same
748 // (NAK, origin) in the same upload if they are destined for the same endpoint
749 // URL.
TEST_F(ReportingDeliveryAgentTest,BatchReportsAcrossGroups)750 TEST_F(ReportingDeliveryAgentTest, BatchReportsAcrossGroups) {
751   static const std::string kDifferentGroup("group2");
752   const ReportingEndpointGroupKey kDifferentGroupKey(kNak_, kOrigin_,
753                                                      kDifferentGroup);
754 
755   ASSERT_TRUE(SetEndpointInCache(kGroupKey_, kEndpoint_, kExpires_));
756   ASSERT_TRUE(SetEndpointInCache(kDifferentGroupKey, kEndpoint_, kExpires_));
757 
758   UploadFirstReportAndStartTimer();
759 
760   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kGroup_);
761   AddReport(kEmptyReportingSource_, kNak_, kUrl_, kDifferentGroup);
762 
763   EXPECT_TRUE(delivery_timer()->IsRunning());
764   delivery_timer()->Fire();
765   ASSERT_EQ(1u, pending_uploads().size());
766   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
767   EXPECT_EQ(0u, pending_uploads().size());
768 
769   {
770     ReportingEndpoint::Statistics stats =
771         GetEndpointStatistics(kGroupKey_, kEndpoint_);
772     EXPECT_EQ(1, stats.attempted_uploads);
773     EXPECT_EQ(1, stats.successful_uploads);
774     EXPECT_EQ(1, stats.attempted_reports);
775     EXPECT_EQ(1, stats.successful_reports);
776   }
777   {
778     ReportingEndpoint::Statistics stats =
779         GetEndpointStatistics(kDifferentGroupKey, kEndpoint_);
780     EXPECT_EQ(1, stats.attempted_uploads);
781     EXPECT_EQ(1, stats.successful_uploads);
782     EXPECT_EQ(1, stats.attempted_reports);
783     EXPECT_EQ(1, stats.successful_reports);
784   }
785 }
786 
787 // Tests that the agent can send all outstanding reports for a single source
788 // when necessary. This test queues two reports for the same reporting source,
789 // for different endpoints, another for a different source at the same URL, and
790 // another for a different source on a different origin.
TEST_F(ReportingDeliveryAgentTest,SendReportsForSource)791 TEST_F(ReportingDeliveryAgentTest, SendReportsForSource) {
792   static const std::string kGroup2("group2");
793 
794   // Two other reporting sources; kReportingSource2 will enqueue reports for the
795   // same URL as kReportingSource_, while kReportingSource3 will be a separate
796   // origin.
797   const base::UnguessableToken kReportingSource1 =
798       base::UnguessableToken::Create();
799   const base::UnguessableToken kReportingSource2 =
800       base::UnguessableToken::Create();
801   const base::UnguessableToken kReportingSource3 =
802       base::UnguessableToken::Create();
803 
804   const IsolationInfo kIsolationInfo1 =
805       IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin_,
806                             kOrigin_, SiteForCookies::FromOrigin(kOrigin_));
807   const IsolationInfo kIsolationInfo2 =
808       IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin_,
809                             kOrigin_, SiteForCookies::FromOrigin(kOrigin_));
810   const IsolationInfo kIsolationInfo3 = IsolationInfo::Create(
811       IsolationInfo::RequestType::kOther, kOtherOrigin_, kOtherOrigin_,
812       SiteForCookies::FromOrigin(kOtherOrigin_));
813 
814   // Set up identical endpoint configuration for kReportingSource1 and
815   // kReportingSource2. kReportingSource3 is independent.
816   const ReportingEndpointGroupKey kGroup1Key1(kNak_, kReportingSource1,
817                                               kOrigin_, kGroup_);
818   const ReportingEndpointGroupKey kGroup2Key1(kNak_, kReportingSource1,
819                                               kOrigin_, kGroup2);
820   const ReportingEndpointGroupKey kGroup1Key2(kNak_, kReportingSource2,
821                                               kOrigin_, kGroup_);
822   const ReportingEndpointGroupKey kGroup2Key2(kNak_, kReportingSource2,
823                                               kOrigin_, kGroup2);
824   const ReportingEndpointGroupKey kOtherGroupKey(kOtherNak_, kReportingSource3,
825                                                  kOtherOrigin_, kGroup_);
826 
827   SetV1EndpointInCache(kGroup1Key1, kReportingSource1, kIsolationInfo1, kUrl_);
828   SetV1EndpointInCache(kGroup2Key1, kReportingSource1, kIsolationInfo1, kUrl_);
829   SetV1EndpointInCache(kGroup1Key2, kReportingSource2, kIsolationInfo2, kUrl_);
830   SetV1EndpointInCache(kGroup2Key2, kReportingSource2, kIsolationInfo2, kUrl_);
831   SetV1EndpointInCache(kOtherGroupKey, kReportingSource3, kIsolationInfo3,
832                        kOtherUrl_);
833 
834   UploadFirstReportAndStartTimer();
835 
836   AddReport(kReportingSource1, kNak_, kUrl_, kGroup_);
837   AddReport(kReportingSource1, kNak_, kUrl_, kGroup2);
838   AddReport(kReportingSource2, kNak_, kUrl_, kGroup_);
839   AddReport(kReportingSource3, kOtherNak_, kUrl_, kGroup_);
840 
841   // There should be four queued reports at this point.
842   EXPECT_EQ(4u, cache()->GetReportCountWithStatusForTesting(
843                     ReportingReport::Status::QUEUED));
844   EXPECT_EQ(0u, pending_uploads().size());
845   SendReportsForSource(kReportingSource1);
846   // Sending all reports for the source should only queue two, despite the fact
847   // that there are other reports queued for the same origin and endpoint.
848   EXPECT_EQ(2u, cache()->GetReportCountWithStatusForTesting(
849                     ReportingReport::Status::QUEUED));
850   EXPECT_EQ(2u, cache()->GetReportCountWithStatusForTesting(
851                     ReportingReport::Status::PENDING));
852   // All pending reports for the same source should be batched into a single
853   // upload.
854   ASSERT_EQ(1u, pending_uploads().size());
855   pending_uploads()[0]->Complete(ReportingUploader::Outcome::SUCCESS);
856   EXPECT_EQ(0u, pending_uploads().size());
857 }
858 
859 // Tests that the agent can send all outstanding V1 reports for multiple sources
860 // and that these are not batched together.
TEST_F(ReportingDeliveryAgentTest,SendReportsForMultipleSources)861 TEST_F(ReportingDeliveryAgentTest, SendReportsForMultipleSources) {
862   static const std::string kGroup2("group2");
863 
864   // Two other reporting sources; kReportingSource2 will enqueue reports for the
865   // same URL as kReportingSource_, while kReportingSource3 will be a separate
866   // origin.
867   const base::UnguessableToken kReportingSource1 =
868       base::UnguessableToken::Create();
869   const base::UnguessableToken kReportingSource2 =
870       base::UnguessableToken::Create();
871   const base::UnguessableToken kReportingSource3 =
872       base::UnguessableToken::Create();
873 
874   const IsolationInfo kIsolationInfo1 =
875       IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin_,
876                             kOrigin_, SiteForCookies::FromOrigin(kOrigin_));
877   const IsolationInfo kIsolationInfo2 =
878       IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin_,
879                             kOrigin_, SiteForCookies::FromOrigin(kOrigin_));
880   const IsolationInfo kIsolationInfo3 = IsolationInfo::Create(
881       IsolationInfo::RequestType::kOther, kOtherOrigin_, kOtherOrigin_,
882       SiteForCookies::FromOrigin(kOtherOrigin_));
883 
884   // Set up identical endpoint configuration for kReportingSource1 and
885   // kReportingSource2. kReportingSource3 is independent.
886   const ReportingEndpointGroupKey kGroup1Key1(kNak_, kReportingSource1,
887                                               kOrigin_, kGroup_);
888   const ReportingEndpointGroupKey kGroup2Key1(kNak_, kReportingSource1,
889                                               kOrigin_, kGroup2);
890   const ReportingEndpointGroupKey kGroup1Key2(kNak_, kReportingSource2,
891                                               kOrigin_, kGroup_);
892   const ReportingEndpointGroupKey kGroup2Key2(kNak_, kReportingSource2,
893                                               kOrigin_, kGroup2);
894   const ReportingEndpointGroupKey kOtherGroupKey(kOtherNak_, kReportingSource3,
895                                                  kOtherOrigin_, kGroup_);
896 
897   SetV1EndpointInCache(kGroup1Key1, kReportingSource1, kIsolationInfo1, kUrl_);
898   SetV1EndpointInCache(kGroup2Key1, kReportingSource1, kIsolationInfo1, kUrl_);
899   SetV1EndpointInCache(kGroup1Key2, kReportingSource2, kIsolationInfo2, kUrl_);
900   SetV1EndpointInCache(kGroup2Key2, kReportingSource2, kIsolationInfo2, kUrl_);
901   SetV1EndpointInCache(kOtherGroupKey, kReportingSource3, kIsolationInfo3,
902                        kOtherUrl_);
903 
904   UploadFirstReportAndStartTimer();
905 
906   AddReport(kReportingSource1, kNak_, kUrl_, kGroup_);
907   AddReport(kReportingSource1, kNak_, kUrl_, kGroup2);
908   AddReport(kReportingSource2, kNak_, kUrl_, kGroup_);
909   AddReport(kReportingSource3, kOtherNak_, kUrl_, kGroup_);
910 
911   // There should be four queued reports at this point.
912   EXPECT_EQ(4u, cache()->GetReportCountWithStatusForTesting(
913                     ReportingReport::Status::QUEUED));
914   EXPECT_EQ(0u, pending_uploads().size());
915 
916   // Send reports for both ReportingSource 1 and 2 at the same time. These
917   // should be sent to the same endpoint, but should still not be batched
918   // together.
919   SendReportsForSource(kReportingSource1);
920   SendReportsForSource(kReportingSource2);
921 
922   // We expect to see three pending reports, and one still queued. The pending
923   // reports should be divided into two uploads.
924   EXPECT_EQ(1u, cache()->GetReportCountWithStatusForTesting(
925                     ReportingReport::Status::QUEUED));
926   EXPECT_EQ(3u, cache()->GetReportCountWithStatusForTesting(
927                     ReportingReport::Status::PENDING));
928   ASSERT_EQ(2u, pending_uploads().size());
929 }
930 
931 }  // namespace
932 }  // namespace net
933