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