xref: /aosp_15_r20/external/cronet/net/reporting/reporting_endpoint_manager_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_endpoint_manager.h"
6 
7 #include <optional>
8 #include <string>
9 
10 #include "base/memory/raw_ptr.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/test/simple_test_tick_clock.h"
13 #include "base/time/time.h"
14 #include "base/unguessable_token.h"
15 #include "net/base/backoff_entry.h"
16 #include "net/base/isolation_info.h"
17 #include "net/base/network_anonymization_key.h"
18 #include "net/base/schemeful_site.h"
19 #include "net/reporting/reporting_cache.h"
20 #include "net/reporting/reporting_endpoint.h"
21 #include "net/reporting/reporting_policy.h"
22 #include "net/reporting/reporting_test_util.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "url/gurl.h"
25 #include "url/origin.h"
26 
27 namespace net {
28 namespace {
29 
30 class TestReportingCache : public ReportingCache {
31  public:
32   class PersistentReportingStore;
33 
34   // Tests using this class only use one origin/group.
TestReportingCache(const url::Origin & expected_origin,const std::string & expected_group)35   TestReportingCache(const url::Origin& expected_origin,
36                      const std::string& expected_group)
37       : expected_origin_(expected_origin), expected_group_(expected_group) {}
38 
39   TestReportingCache(const TestReportingCache&) = delete;
40   TestReportingCache& operator=(const TestReportingCache&) = delete;
41 
42   ~TestReportingCache() override = default;
43 
SetEndpoint(const ReportingEndpoint & reporting_endpoint)44   void SetEndpoint(const ReportingEndpoint& reporting_endpoint) {
45     reporting_endpoints_[reporting_endpoint.group_key.network_anonymization_key]
46         .push_back(reporting_endpoint);
47   }
48 
49   // ReportingCache implementation:
50 
GetCandidateEndpointsForDelivery(const ReportingEndpointGroupKey & group_key)51   std::vector<ReportingEndpoint> GetCandidateEndpointsForDelivery(
52       const ReportingEndpointGroupKey& group_key) override {
53     EXPECT_EQ(expected_origin_, group_key.origin);
54     EXPECT_EQ(expected_group_, group_key.group_name);
55     return reporting_endpoints_[group_key.network_anonymization_key];
56   }
57 
58   // Everything below is NOTREACHED.
AddReport(const std::optional<base::UnguessableToken> & reporting_source,const NetworkAnonymizationKey & network_anonymization_key,const GURL & url,const std::string & user_agent,const std::string & group_name,const std::string & type,base::Value::Dict body,int depth,base::TimeTicks queued,int attempts)59   void AddReport(const std::optional<base::UnguessableToken>& reporting_source,
60                  const NetworkAnonymizationKey& network_anonymization_key,
61                  const GURL& url,
62                  const std::string& user_agent,
63                  const std::string& group_name,
64                  const std::string& type,
65                  base::Value::Dict body,
66                  int depth,
67                  base::TimeTicks queued,
68                  int attempts) override {
69     NOTREACHED();
70   }
GetReports(std::vector<raw_ptr<const ReportingReport,VectorExperimental>> * reports_out) const71   void GetReports(
72       std::vector<raw_ptr<const ReportingReport, VectorExperimental>>*
73           reports_out) const override {
74     NOTREACHED();
75   }
GetReportsAsValue() const76   base::Value GetReportsAsValue() const override {
77     NOTREACHED();
78     return base::Value();
79   }
80   std::vector<raw_ptr<const ReportingReport, VectorExperimental>>
GetReportsToDeliver()81   GetReportsToDeliver() override {
82     NOTREACHED();
83     return {};
84   }
85   std::vector<raw_ptr<const ReportingReport, VectorExperimental>>
GetReportsToDeliverForSource(const base::UnguessableToken & reporting_source)86   GetReportsToDeliverForSource(
87       const base::UnguessableToken& reporting_source) override {
88     NOTREACHED();
89     return {};
90   }
ClearReportsPending(const std::vector<raw_ptr<const ReportingReport,VectorExperimental>> & reports)91   void ClearReportsPending(
92       const std::vector<raw_ptr<const ReportingReport, VectorExperimental>>&
93           reports) override {
94     NOTREACHED();
95   }
IncrementReportsAttempts(const std::vector<raw_ptr<const ReportingReport,VectorExperimental>> & reports)96   void IncrementReportsAttempts(
97       const std::vector<raw_ptr<const ReportingReport, VectorExperimental>>&
98           reports) override {
99     NOTREACHED();
100   }
101   base::flat_map<url::Origin, std::vector<ReportingEndpoint>>
GetV1ReportingEndpointsByOrigin() const102   GetV1ReportingEndpointsByOrigin() const override {
103     NOTREACHED();
104     return base::flat_map<url::Origin, std::vector<ReportingEndpoint>>();
105   }
IncrementEndpointDeliveries(const ReportingEndpointGroupKey & group_key,const GURL & url,int reports_delivered,bool successful)106   void IncrementEndpointDeliveries(const ReportingEndpointGroupKey& group_key,
107                                    const GURL& url,
108                                    int reports_delivered,
109                                    bool successful) override {
110     NOTREACHED();
111   }
SetExpiredSource(const base::UnguessableToken & reporting_source)112   void SetExpiredSource(
113       const base::UnguessableToken& reporting_source) override {
114     NOTREACHED();
115   }
GetExpiredSources() const116   const base::flat_set<base::UnguessableToken>& GetExpiredSources()
117       const override {
118     NOTREACHED();
119     return expired_sources_;
120   }
RemoveReports(const std::vector<raw_ptr<const ReportingReport,VectorExperimental>> & reports)121   void RemoveReports(
122       const std::vector<raw_ptr<const ReportingReport, VectorExperimental>>&
123           reports) override {
124     NOTREACHED();
125   }
RemoveReports(const std::vector<raw_ptr<const ReportingReport,VectorExperimental>> & reports,bool delivery_success)126   void RemoveReports(
127       const std::vector<raw_ptr<const ReportingReport, VectorExperimental>>&
128           reports,
129       bool delivery_success) override {
130     NOTREACHED();
131   }
RemoveAllReports()132   void RemoveAllReports() override { NOTREACHED(); }
GetFullReportCountForTesting() const133   size_t GetFullReportCountForTesting() const override {
134     NOTREACHED();
135     return 0;
136   }
GetReportCountWithStatusForTesting(ReportingReport::Status status) const137   size_t GetReportCountWithStatusForTesting(
138       ReportingReport::Status status) const override {
139     NOTREACHED();
140     return 0;
141   }
IsReportPendingForTesting(const ReportingReport * report) const142   bool IsReportPendingForTesting(const ReportingReport* report) const override {
143     NOTREACHED();
144     return false;
145   }
IsReportDoomedForTesting(const ReportingReport * report) const146   bool IsReportDoomedForTesting(const ReportingReport* report) const override {
147     NOTREACHED();
148     return false;
149   }
OnParsedHeader(const NetworkAnonymizationKey & network_anonymization_key,const url::Origin & origin,std::vector<ReportingEndpointGroup> parsed_header)150   void OnParsedHeader(
151       const NetworkAnonymizationKey& network_anonymization_key,
152       const url::Origin& origin,
153       std::vector<ReportingEndpointGroup> parsed_header) override {
154     NOTREACHED();
155   }
OnParsedReportingEndpointsHeader(const base::UnguessableToken & reporting_source,const IsolationInfo & isolation_info,std::vector<ReportingEndpoint> endpoints)156   void OnParsedReportingEndpointsHeader(
157       const base::UnguessableToken& reporting_source,
158       const IsolationInfo& isolation_info,
159       std::vector<ReportingEndpoint> endpoints) override {
160     NOTREACHED();
161   }
GetAllOrigins() const162   std::set<url::Origin> GetAllOrigins() const override {
163     NOTREACHED();
164     return std::set<url::Origin>();
165   }
RemoveClient(const NetworkAnonymizationKey & network_anonymization_key,const url::Origin & origin)166   void RemoveClient(const NetworkAnonymizationKey& network_anonymization_key,
167                     const url::Origin& origin) override {
168     NOTREACHED();
169   }
RemoveClientsForOrigin(const url::Origin & origin)170   void RemoveClientsForOrigin(const url::Origin& origin) override {
171     NOTREACHED();
172   }
RemoveAllClients()173   void RemoveAllClients() override { NOTREACHED(); }
RemoveEndpointGroup(const ReportingEndpointGroupKey & group_key)174   void RemoveEndpointGroup(
175       const ReportingEndpointGroupKey& group_key) override {
176     NOTREACHED();
177   }
RemoveEndpointsForUrl(const GURL & url)178   void RemoveEndpointsForUrl(const GURL& url) override { NOTREACHED(); }
RemoveSourceAndEndpoints(const base::UnguessableToken & reporting_source)179   void RemoveSourceAndEndpoints(
180       const base::UnguessableToken& reporting_source) override {
181     NOTREACHED();
182   }
AddClientsLoadedFromStore(std::vector<ReportingEndpoint> loaded_endpoints,std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups)183   void AddClientsLoadedFromStore(
184       std::vector<ReportingEndpoint> loaded_endpoints,
185       std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups)
186       override {
187     NOTREACHED();
188   }
GetClientsAsValue() const189   base::Value GetClientsAsValue() const override {
190     NOTREACHED();
191     return base::Value();
192   }
GetEndpointCount() const193   size_t GetEndpointCount() const override {
194     NOTREACHED();
195     return 0;
196   }
Flush()197   void Flush() override { NOTREACHED(); }
GetV1EndpointForTesting(const base::UnguessableToken & reporting_source,const std::string & endpoint_name) const198   ReportingEndpoint GetV1EndpointForTesting(
199       const base::UnguessableToken& reporting_source,
200       const std::string& endpoint_name) const override {
201     NOTREACHED();
202     return ReportingEndpoint();
203   }
GetEndpointForTesting(const ReportingEndpointGroupKey & group_key,const GURL & url) const204   ReportingEndpoint GetEndpointForTesting(
205       const ReportingEndpointGroupKey& group_key,
206       const GURL& url) const override {
207     NOTREACHED();
208     return ReportingEndpoint();
209   }
EndpointGroupExistsForTesting(const ReportingEndpointGroupKey & group_key,OriginSubdomains include_subdomains,base::Time expires) const210   bool EndpointGroupExistsForTesting(const ReportingEndpointGroupKey& group_key,
211                                      OriginSubdomains include_subdomains,
212                                      base::Time expires) const override {
213     NOTREACHED();
214     return false;
215   }
ClientExistsForTesting(const NetworkAnonymizationKey & network_anonymization_key,const url::Origin & origin) const216   bool ClientExistsForTesting(
217       const NetworkAnonymizationKey& network_anonymization_key,
218       const url::Origin& origin) const override {
219     NOTREACHED();
220     return false;
221   }
GetEndpointGroupCountForTesting() const222   size_t GetEndpointGroupCountForTesting() const override {
223     NOTREACHED();
224     return 0;
225   }
GetClientCountForTesting() const226   size_t GetClientCountForTesting() const override {
227     NOTREACHED();
228     return 0;
229   }
GetReportingSourceCountForTesting() const230   size_t GetReportingSourceCountForTesting() const override {
231     NOTREACHED();
232     return 0;
233   }
SetEndpointForTesting(const ReportingEndpointGroupKey & group_key,const GURL & url,OriginSubdomains include_subdomains,base::Time expires,int priority,int weight)234   void SetEndpointForTesting(const ReportingEndpointGroupKey& group_key,
235                              const GURL& url,
236                              OriginSubdomains include_subdomains,
237                              base::Time expires,
238                              int priority,
239                              int weight) override {
240     NOTREACHED();
241   }
SetV1EndpointForTesting(const ReportingEndpointGroupKey & group_key,const base::UnguessableToken & reporting_source,const IsolationInfo & isolation_info,const GURL & url)242   void SetV1EndpointForTesting(const ReportingEndpointGroupKey& group_key,
243                                const base::UnguessableToken& reporting_source,
244                                const IsolationInfo& isolation_info,
245                                const GURL& url) override {
246     NOTREACHED();
247   }
GetIsolationInfoForEndpoint(const ReportingEndpoint & endpoint) const248   IsolationInfo GetIsolationInfoForEndpoint(
249       const ReportingEndpoint& endpoint) const override {
250     NOTREACHED();
251     return IsolationInfo();
252   }
253 
254  private:
255   const url::Origin expected_origin_;
256   const std::string expected_group_;
257 
258   std::map<NetworkAnonymizationKey, std::vector<ReportingEndpoint>>
259       reporting_endpoints_;
260   base::flat_set<base::UnguessableToken> expired_sources_;
261 };
262 
263 class ReportingEndpointManagerTest : public testing::Test {
264  public:
ReportingEndpointManagerTest()265   ReportingEndpointManagerTest() : cache_(kOrigin, kGroup) {
266     policy_.endpoint_backoff_policy.num_errors_to_ignore = 0;
267     policy_.endpoint_backoff_policy.initial_delay_ms = 60000;
268     policy_.endpoint_backoff_policy.multiply_factor = 2.0;
269     policy_.endpoint_backoff_policy.jitter_factor = 0.0;
270     policy_.endpoint_backoff_policy.maximum_backoff_ms = -1;
271     policy_.endpoint_backoff_policy.entry_lifetime_ms = 0;
272     policy_.endpoint_backoff_policy.always_use_initial_delay = false;
273 
274     clock_.SetNowTicks(base::TimeTicks());
275 
276     endpoint_manager_ = ReportingEndpointManager::Create(
277         &policy_, &clock_, &delegate_, &cache_, TestReportingRandIntCallback());
278   }
279 
280  protected:
SetEndpoint(const GURL & endpoint,int priority=ReportingEndpoint::EndpointInfo::kDefaultPriority,int weight=ReportingEndpoint::EndpointInfo::kDefaultWeight,const NetworkAnonymizationKey & network_anonymization_key=NetworkAnonymizationKey ())281   void SetEndpoint(
282       const GURL& endpoint,
283       int priority = ReportingEndpoint::EndpointInfo::kDefaultPriority,
284       int weight = ReportingEndpoint::EndpointInfo::kDefaultWeight,
285       const NetworkAnonymizationKey& network_anonymization_key =
286           NetworkAnonymizationKey()) {
287     ReportingEndpointGroupKey group_key(kGroupKey);
288     group_key.network_anonymization_key = network_anonymization_key;
289     cache_.SetEndpoint(ReportingEndpoint(
290         group_key,
291         ReportingEndpoint::EndpointInfo{endpoint, priority, weight}));
292   }
293 
294   const NetworkAnonymizationKey kNak;
295   const url::Origin kOrigin = url::Origin::Create(GURL("https://origin/"));
296   const SchemefulSite kSite = SchemefulSite(kOrigin);
297   const std::string kGroup = "group";
298   const ReportingEndpointGroupKey kGroupKey =
299       ReportingEndpointGroupKey(kNak, kOrigin, kGroup);
300   const GURL kEndpoint = GURL("https://endpoint/");
301 
302   ReportingPolicy policy_;
303   base::SimpleTestTickClock clock_;
304   TestReportingDelegate delegate_;
305   TestReportingCache cache_;
306   std::unique_ptr<ReportingEndpointManager> endpoint_manager_;
307 };
308 
TEST_F(ReportingEndpointManagerTest,NoEndpoint)309 TEST_F(ReportingEndpointManagerTest, NoEndpoint) {
310   ReportingEndpoint endpoint =
311       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
312   EXPECT_FALSE(endpoint);
313 }
314 
TEST_F(ReportingEndpointManagerTest,Endpoint)315 TEST_F(ReportingEndpointManagerTest, Endpoint) {
316   SetEndpoint(kEndpoint);
317 
318   ReportingEndpoint endpoint =
319       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
320   ASSERT_TRUE(endpoint);
321   EXPECT_EQ(kEndpoint, endpoint.info.url);
322 }
323 
TEST_F(ReportingEndpointManagerTest,BackedOffEndpoint)324 TEST_F(ReportingEndpointManagerTest, BackedOffEndpoint) {
325   ASSERT_EQ(2.0, policy_.endpoint_backoff_policy.multiply_factor);
326 
327   base::TimeDelta initial_delay =
328       base::Milliseconds(policy_.endpoint_backoff_policy.initial_delay_ms);
329 
330   SetEndpoint(kEndpoint);
331 
332   endpoint_manager_->InformOfEndpointRequest(NetworkAnonymizationKey(),
333                                              kEndpoint, false);
334 
335   // After one failure, endpoint is in exponential backoff.
336   ReportingEndpoint endpoint =
337       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
338   EXPECT_FALSE(endpoint);
339 
340   // After initial delay, endpoint is usable again.
341   clock_.Advance(initial_delay);
342 
343   ReportingEndpoint endpoint2 =
344       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
345   ASSERT_TRUE(endpoint2);
346   EXPECT_EQ(kEndpoint, endpoint2.info.url);
347 
348   endpoint_manager_->InformOfEndpointRequest(NetworkAnonymizationKey(),
349                                              kEndpoint, false);
350 
351   // After a second failure, endpoint is backed off again.
352   ReportingEndpoint endpoint3 =
353       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
354   EXPECT_FALSE(endpoint3);
355 
356   clock_.Advance(initial_delay);
357 
358   // Next backoff is longer -- 2x the first -- so endpoint isn't usable yet.
359   ReportingEndpoint endpoint4 =
360       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
361   EXPECT_FALSE(endpoint4);
362 
363   clock_.Advance(initial_delay);
364 
365   // After 2x the initial delay, the endpoint is usable again.
366   ReportingEndpoint endpoint5 =
367       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
368   ASSERT_TRUE(endpoint5);
369   EXPECT_EQ(kEndpoint, endpoint5.info.url);
370 
371   endpoint_manager_->InformOfEndpointRequest(NetworkAnonymizationKey(),
372                                              kEndpoint, true);
373   endpoint_manager_->InformOfEndpointRequest(NetworkAnonymizationKey(),
374                                              kEndpoint, true);
375 
376   // Two more successful requests should reset the backoff to the initial delay
377   // again.
378   endpoint_manager_->InformOfEndpointRequest(NetworkAnonymizationKey(),
379                                              kEndpoint, false);
380 
381   ReportingEndpoint endpoint6 =
382       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
383   EXPECT_FALSE(endpoint6);
384 
385   clock_.Advance(initial_delay);
386 
387   ReportingEndpoint endpoint7 =
388       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
389   EXPECT_TRUE(endpoint7);
390 }
391 
392 // Make sure that multiple endpoints will all be returned at some point, to
393 // avoid accidentally or intentionally implementing any priority ordering.
TEST_F(ReportingEndpointManagerTest,RandomEndpoint)394 TEST_F(ReportingEndpointManagerTest, RandomEndpoint) {
395   static const GURL kEndpoint1("https://endpoint1/");
396   static const GURL kEndpoint2("https://endpoint2/");
397   static const int kMaxAttempts = 20;
398 
399   SetEndpoint(kEndpoint1);
400   SetEndpoint(kEndpoint2);
401 
402   bool endpoint1_seen = false;
403   bool endpoint2_seen = false;
404 
405   for (int i = 0; i < kMaxAttempts; ++i) {
406     ReportingEndpoint endpoint =
407         endpoint_manager_->FindEndpointForDelivery(kGroupKey);
408     ASSERT_TRUE(endpoint);
409     ASSERT_TRUE(endpoint.info.url == kEndpoint1 ||
410                 endpoint.info.url == kEndpoint2);
411 
412     if (endpoint.info.url == kEndpoint1)
413       endpoint1_seen = true;
414     else if (endpoint.info.url == kEndpoint2)
415       endpoint2_seen = true;
416 
417     if (endpoint1_seen && endpoint2_seen)
418       break;
419   }
420 
421   EXPECT_TRUE(endpoint1_seen);
422   EXPECT_TRUE(endpoint2_seen);
423 }
424 
TEST_F(ReportingEndpointManagerTest,Priority)425 TEST_F(ReportingEndpointManagerTest, Priority) {
426   static const GURL kPrimaryEndpoint("https://endpoint1/");
427   static const GURL kBackupEndpoint("https://endpoint2/");
428 
429   SetEndpoint(kPrimaryEndpoint, 10 /* priority */,
430               ReportingEndpoint::EndpointInfo::kDefaultWeight);
431   SetEndpoint(kBackupEndpoint, 20 /* priority */,
432               ReportingEndpoint::EndpointInfo::kDefaultWeight);
433 
434   ReportingEndpoint endpoint =
435       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
436   ASSERT_TRUE(endpoint);
437   EXPECT_EQ(kPrimaryEndpoint, endpoint.info.url);
438 
439   // The backoff policy we set up in the constructor means that a single failed
440   // upload will take the primary endpoint out of contention.  This should cause
441   // us to choose the backend endpoint.
442   endpoint_manager_->InformOfEndpointRequest(NetworkAnonymizationKey(),
443                                              kPrimaryEndpoint, false);
444   ReportingEndpoint endpoint2 =
445       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
446   ASSERT_TRUE(endpoint2);
447   EXPECT_EQ(kBackupEndpoint, endpoint2.info.url);
448 
449   // Advance the current time far enough to clear out the primary endpoint's
450   // backoff clock.  This should bring the primary endpoint back into play.
451   clock_.Advance(base::Minutes(2));
452   ReportingEndpoint endpoint3 =
453       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
454   ASSERT_TRUE(endpoint3);
455   EXPECT_EQ(kPrimaryEndpoint, endpoint3.info.url);
456 }
457 
458 // Note: This test depends on the deterministic mock RandIntCallback set up in
459 // TestReportingContext, which returns consecutive integers starting at 0
460 // (modulo the requested range, plus the requested minimum).
TEST_F(ReportingEndpointManagerTest,Weight)461 TEST_F(ReportingEndpointManagerTest, Weight) {
462   static const GURL kEndpoint1("https://endpoint1/");
463   static const GURL kEndpoint2("https://endpoint2/");
464 
465   static const int kEndpoint1Weight = 5;
466   static const int kEndpoint2Weight = 2;
467   static const int kTotalEndpointWeight = kEndpoint1Weight + kEndpoint2Weight;
468 
469   SetEndpoint(kEndpoint1, ReportingEndpoint::EndpointInfo::kDefaultPriority,
470               kEndpoint1Weight);
471   SetEndpoint(kEndpoint2, ReportingEndpoint::EndpointInfo::kDefaultPriority,
472               kEndpoint2Weight);
473 
474   int endpoint1_count = 0;
475   int endpoint2_count = 0;
476 
477   for (int i = 0; i < kTotalEndpointWeight; ++i) {
478     ReportingEndpoint endpoint =
479         endpoint_manager_->FindEndpointForDelivery(kGroupKey);
480     ASSERT_TRUE(endpoint);
481     ASSERT_TRUE(endpoint.info.url == kEndpoint1 ||
482                 endpoint.info.url == kEndpoint2);
483 
484     if (endpoint.info.url == kEndpoint1)
485       ++endpoint1_count;
486     else if (endpoint.info.url == kEndpoint2)
487       ++endpoint2_count;
488   }
489 
490   EXPECT_EQ(kEndpoint1Weight, endpoint1_count);
491   EXPECT_EQ(kEndpoint2Weight, endpoint2_count);
492 }
493 
TEST_F(ReportingEndpointManagerTest,ZeroWeights)494 TEST_F(ReportingEndpointManagerTest, ZeroWeights) {
495   static const GURL kEndpoint1("https://endpoint1/");
496   static const GURL kEndpoint2("https://endpoint2/");
497 
498   SetEndpoint(kEndpoint1, ReportingEndpoint::EndpointInfo::kDefaultPriority,
499               0 /* weight */);
500   SetEndpoint(kEndpoint2, ReportingEndpoint::EndpointInfo::kDefaultPriority,
501               0 /* weight */);
502 
503   int endpoint1_count = 0;
504   int endpoint2_count = 0;
505 
506   for (int i = 0; i < 10; ++i) {
507     ReportingEndpoint endpoint =
508         endpoint_manager_->FindEndpointForDelivery(kGroupKey);
509     ASSERT_TRUE(endpoint);
510     ASSERT_TRUE(endpoint.info.url == kEndpoint1 ||
511                 endpoint.info.url == kEndpoint2);
512 
513     if (endpoint.info.url == kEndpoint1)
514       ++endpoint1_count;
515     else if (endpoint.info.url == kEndpoint2)
516       ++endpoint2_count;
517   }
518 
519   EXPECT_EQ(5, endpoint1_count);
520   EXPECT_EQ(5, endpoint2_count);
521 }
522 
523 // Check that ReportingEndpointManager distinguishes NetworkAnonymizationKeys.
TEST_F(ReportingEndpointManagerTest,NetworkAnonymizationKey)524 TEST_F(ReportingEndpointManagerTest, NetworkAnonymizationKey) {
525   const SchemefulSite kSite2(GURL("https://origin2/"));
526 
527   const auto kNetworkAnonymizationKey1 =
528       NetworkAnonymizationKey::CreateSameSite(kSite);
529   const auto kNetworkAnonymizationKey2 =
530       NetworkAnonymizationKey::CreateSameSite(kSite2);
531   const ReportingEndpointGroupKey kGroupKey1(kNetworkAnonymizationKey1, kOrigin,
532                                              kGroup);
533   const ReportingEndpointGroupKey kGroupKey2(kNetworkAnonymizationKey2, kOrigin,
534                                              kGroup);
535 
536   // An Endpoint set for kNetworkAnonymizationKey1 should not affect
537   // kNetworkAnonymizationKey2.
538   SetEndpoint(kEndpoint, ReportingEndpoint::EndpointInfo::kDefaultPriority,
539               0 /* weight */, kNetworkAnonymizationKey1);
540   ReportingEndpoint endpoint =
541       endpoint_manager_->FindEndpointForDelivery(kGroupKey1);
542   ASSERT_TRUE(endpoint);
543   EXPECT_EQ(kEndpoint, endpoint.info.url);
544   EXPECT_FALSE(endpoint_manager_->FindEndpointForDelivery(kGroupKey2));
545   EXPECT_FALSE(endpoint_manager_->FindEndpointForDelivery(kGroupKey));
546 
547   // Set the same Endpoint for kNetworkAnonymizationKey2, so both should be
548   // reporting to the same URL.
549   SetEndpoint(kEndpoint, ReportingEndpoint::EndpointInfo::kDefaultPriority,
550               0 /* weight */, kNetworkAnonymizationKey2);
551   endpoint = endpoint_manager_->FindEndpointForDelivery(kGroupKey1);
552   ASSERT_TRUE(endpoint);
553   EXPECT_EQ(kEndpoint, endpoint.info.url);
554   endpoint = endpoint_manager_->FindEndpointForDelivery(kGroupKey2);
555   ASSERT_TRUE(endpoint);
556   EXPECT_EQ(kEndpoint, endpoint.info.url);
557   EXPECT_FALSE(endpoint_manager_->FindEndpointForDelivery(kGroupKey));
558 
559   // An error reporting to that URL in the context of kNetworkAnonymizationKey1
560   // should only affect the Endpoint retrieved in the context of
561   // kNetworkAnonymizationKey1.
562   endpoint_manager_->InformOfEndpointRequest(kNetworkAnonymizationKey1,
563                                              kEndpoint, false);
564   EXPECT_FALSE(endpoint_manager_->FindEndpointForDelivery(kGroupKey1));
565   endpoint = endpoint_manager_->FindEndpointForDelivery(kGroupKey2);
566   ASSERT_TRUE(endpoint);
567   EXPECT_EQ(kEndpoint, endpoint.info.url);
568   EXPECT_FALSE(endpoint_manager_->FindEndpointForDelivery(kGroupKey));
569 }
570 
TEST_F(ReportingEndpointManagerTest,NetworkAnonymizationKeyWithMultipleEndpoints)571 TEST_F(ReportingEndpointManagerTest,
572        NetworkAnonymizationKeyWithMultipleEndpoints) {
573   const SchemefulSite kSite2(GURL("https://origin2/"));
574 
575   const auto kNetworkAnonymizationKey1 =
576       NetworkAnonymizationKey::CreateSameSite(kSite);
577   const auto kNetworkAnonymizationKey2 =
578       NetworkAnonymizationKey::CreateSameSite(kSite2);
579   const ReportingEndpointGroupKey kGroupKey1(kNetworkAnonymizationKey1, kOrigin,
580                                              kGroup);
581   const ReportingEndpointGroupKey kGroupKey2(kNetworkAnonymizationKey2, kOrigin,
582                                              kGroup);
583 
584   const GURL kEndpoint1("https://endpoint1/");
585   const GURL kEndpoint2("https://endpoint2/");
586   const GURL kEndpoint3("https://endpoint3/");
587   const int kMaxAttempts = 20;
588 
589   // Add two Endpoints for kNetworkAnonymizationKey1, and a different one for
590   // kNetworkAnonymizationKey2.
591   SetEndpoint(kEndpoint1, ReportingEndpoint::EndpointInfo::kDefaultPriority,
592               ReportingEndpoint::EndpointInfo::kDefaultWeight,
593               kNetworkAnonymizationKey1);
594   SetEndpoint(kEndpoint2, ReportingEndpoint::EndpointInfo::kDefaultPriority,
595               ReportingEndpoint::EndpointInfo::kDefaultWeight,
596               kNetworkAnonymizationKey1);
597   SetEndpoint(kEndpoint3, ReportingEndpoint::EndpointInfo::kDefaultPriority,
598               ReportingEndpoint::EndpointInfo::kDefaultWeight,
599               kNetworkAnonymizationKey2);
600 
601   bool endpoint1_seen = false;
602   bool endpoint2_seen = false;
603 
604   // Make sure that calling FindEndpointForDelivery() with
605   // kNetworkAnonymizationKey1 can return both of its endpoints, but not
606   // kNetworkAnonymizationKey2's endpoint.
607   for (int i = 0; i < kMaxAttempts; ++i) {
608     ReportingEndpoint endpoint =
609         endpoint_manager_->FindEndpointForDelivery(kGroupKey1);
610     ASSERT_TRUE(endpoint);
611     ASSERT_TRUE(endpoint.info.url == kEndpoint1 ||
612                 endpoint.info.url == kEndpoint2);
613 
614     if (endpoint.info.url == kEndpoint1) {
615       endpoint1_seen = true;
616     } else if (endpoint.info.url == kEndpoint2) {
617       endpoint2_seen = true;
618     }
619   }
620 
621   EXPECT_TRUE(endpoint1_seen);
622   EXPECT_TRUE(endpoint2_seen);
623 
624   ReportingEndpoint endpoint =
625       endpoint_manager_->FindEndpointForDelivery(kGroupKey2);
626   ASSERT_TRUE(endpoint);
627   EXPECT_EQ(kEndpoint3, endpoint.info.url);
628 }
629 
TEST_F(ReportingEndpointManagerTest,CacheEviction)630 TEST_F(ReportingEndpointManagerTest, CacheEviction) {
631   // Add |kMaxEndpointBackoffCacheSize| endpoints.
632   for (int i = 0; i < ReportingEndpointManager::kMaxEndpointBackoffCacheSize;
633        ++i) {
634     SetEndpoint(GURL(base::StringPrintf("https://endpoint%i/", i)));
635   }
636 
637   // Mark each endpoint as bad, one-at-a-time. Use FindEndpointForDelivery() to
638   // pick which one to mark as bad, both to exercise the code walking through
639   // all endpoints, and as a consistency check.
640   std::set<GURL> seen_endpoints;
641   for (int i = 0; i < ReportingEndpointManager::kMaxEndpointBackoffCacheSize;
642        ++i) {
643     ReportingEndpoint endpoint =
644         endpoint_manager_->FindEndpointForDelivery(kGroupKey);
645     EXPECT_TRUE(endpoint);
646     EXPECT_FALSE(seen_endpoints.count(endpoint.info.url));
647     seen_endpoints.insert(endpoint.info.url);
648     endpoint_manager_->InformOfEndpointRequest(NetworkAnonymizationKey(),
649                                                endpoint.info.url, false);
650   }
651   // All endpoints should now be marked as bad.
652   EXPECT_FALSE(endpoint_manager_->FindEndpointForDelivery(kGroupKey));
653 
654   // Add another endpoint with a different NetworkAnonymizationKey;
655   const auto kDifferentNetworkAnonymizationKey =
656       NetworkAnonymizationKey::CreateSameSite(kSite);
657   const ReportingEndpointGroupKey kDifferentGroupKey(
658       kDifferentNetworkAnonymizationKey, kOrigin, kGroup);
659   SetEndpoint(kEndpoint, ReportingEndpoint::EndpointInfo::kDefaultPriority,
660               ReportingEndpoint::EndpointInfo::kDefaultWeight,
661               kDifferentNetworkAnonymizationKey);
662   // All endpoints associated with the empty NetworkAnonymizationKey should
663   // still be marked as bad.
664   EXPECT_FALSE(endpoint_manager_->FindEndpointForDelivery(kGroupKey));
665 
666   // Make the endpoint added for the kDifferentNetworkAnonymizationKey as bad.
667   endpoint_manager_->InformOfEndpointRequest(kDifferentNetworkAnonymizationKey,
668                                              kEndpoint, false);
669   // The only endpoint for kDifferentNetworkAnonymizationKey should still be
670   // marked as bad.
671   EXPECT_FALSE(endpoint_manager_->FindEndpointForDelivery(kDifferentGroupKey));
672   // One of the endpoints for the empty NetworkAnonymizationKey should no longer
673   // be marked as bad, due to eviction.
674   ReportingEndpoint endpoint =
675       endpoint_manager_->FindEndpointForDelivery(kGroupKey);
676   EXPECT_TRUE(endpoint);
677 
678   // Reporting a success for the (only) good endpoint for the empty
679   // NetworkAnonymizationKey should evict the entry for
680   // kNetworkAnonymizationKey, since the most recent FindEndpointForDelivery()
681   // call visited all of the empty NetworkAnonymizationKey's cached bad entries.
682   endpoint_manager_->InformOfEndpointRequest(NetworkAnonymizationKey(),
683                                              endpoint.info.url, true);
684 
685   EXPECT_TRUE(endpoint_manager_->FindEndpointForDelivery(kDifferentGroupKey));
686 }
687 
688 }  // namespace
689 }  // namespace net
690