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