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