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