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