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