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_garbage_collector.h"
6
7 #include <optional>
8 #include <string>
9
10 #include "base/memory/raw_ptr.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "base/time/time.h"
13 #include "base/timer/mock_timer.h"
14 #include "net/base/isolation_info.h"
15 #include "net/base/network_anonymization_key.h"
16 #include "net/reporting/reporting_cache.h"
17 #include "net/reporting/reporting_policy.h"
18 #include "net/reporting/reporting_report.h"
19 #include "net/reporting/reporting_test_util.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace net {
23 namespace {
24
25 class ReportingGarbageCollectorTest : public ReportingTestBase {
26 protected:
report_count()27 size_t report_count() {
28 std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
29 cache()->GetReports(&reports);
30 return reports.size();
31 }
32
33 const std::optional<base::UnguessableToken> kReportingSource_ =
34 base::UnguessableToken::Create();
35 const NetworkAnonymizationKey kNak_;
36 const IsolationInfo kIsolationInfo_;
37 const GURL kUrl_ = GURL("https://origin/path");
38 const std::string kUserAgent_ = "Mozilla/1.0";
39 const std::string kGroup_ = "group";
40 const std::string kType_ = "default";
41 };
42
43 // Make sure the garbage collector is actually present in the context.
TEST_F(ReportingGarbageCollectorTest,Created)44 TEST_F(ReportingGarbageCollectorTest, Created) {
45 EXPECT_NE(nullptr, garbage_collector());
46 }
47
48 // Make sure that the garbage collection timer is started and stopped correctly.
TEST_F(ReportingGarbageCollectorTest,Timer)49 TEST_F(ReportingGarbageCollectorTest, Timer) {
50 EXPECT_FALSE(garbage_collection_timer()->IsRunning());
51
52 cache()->AddReport(std::nullopt, kNak_, kUrl_, kUserAgent_, kGroup_, kType_,
53 base::Value::Dict(), 0, tick_clock()->NowTicks(), 0);
54
55 EXPECT_TRUE(garbage_collection_timer()->IsRunning());
56
57 garbage_collection_timer()->Fire();
58
59 EXPECT_FALSE(garbage_collection_timer()->IsRunning());
60 }
61
TEST_F(ReportingGarbageCollectorTest,Report)62 TEST_F(ReportingGarbageCollectorTest, Report) {
63 cache()->AddReport(std::nullopt, kNak_, kUrl_, kUserAgent_, kGroup_, kType_,
64 base::Value::Dict(), 0, tick_clock()->NowTicks(), 0);
65 garbage_collection_timer()->Fire();
66
67 EXPECT_EQ(1u, report_count());
68 }
69
TEST_F(ReportingGarbageCollectorTest,ExpiredReport)70 TEST_F(ReportingGarbageCollectorTest, ExpiredReport) {
71 cache()->AddReport(std::nullopt, kNak_, kUrl_, kUserAgent_, kGroup_, kType_,
72 base::Value::Dict(), 0, tick_clock()->NowTicks(), 0);
73 tick_clock()->Advance(2 * policy().max_report_age);
74 garbage_collection_timer()->Fire();
75
76 EXPECT_EQ(0u, report_count());
77 }
78
TEST_F(ReportingGarbageCollectorTest,FailedReport)79 TEST_F(ReportingGarbageCollectorTest, FailedReport) {
80 cache()->AddReport(std::nullopt, kNak_, kUrl_, kUserAgent_, kGroup_, kType_,
81 base::Value::Dict(), 0, tick_clock()->NowTicks(), 0);
82
83 std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
84 cache()->GetReports(&reports);
85 for (int i = 0; i < policy().max_report_attempts; i++) {
86 cache()->IncrementReportsAttempts(reports);
87 }
88
89 garbage_collection_timer()->Fire();
90
91 EXPECT_EQ(0u, report_count());
92 }
93
TEST_F(ReportingGarbageCollectorTest,ExpiredSource)94 TEST_F(ReportingGarbageCollectorTest, ExpiredSource) {
95 ReportingEndpointGroupKey group_key(kNak_, kReportingSource_,
96 url::Origin::Create(kUrl_), kGroup_);
97 cache()->SetV1EndpointForTesting(group_key, *kReportingSource_,
98 kIsolationInfo_, kUrl_);
99
100 // Mark the source as expired. The source should be removed as soon as
101 // garbage collection runs, as there are no queued reports for it.
102 cache()->SetExpiredSource(*kReportingSource_);
103
104 // Before garbage collection, the endpoint should still exist.
105 EXPECT_EQ(1u, cache()->GetReportingSourceCountForTesting());
106 EXPECT_TRUE(cache()->GetV1EndpointForTesting(*kReportingSource_, kGroup_));
107
108 // Fire garbage collection. The endpoint configuration should be removed.
109 garbage_collection_timer()->Fire();
110 EXPECT_EQ(0u, cache()->GetReportingSourceCountForTesting());
111 EXPECT_FALSE(cache()->GetV1EndpointForTesting(*kReportingSource_, kGroup_));
112 }
113
TEST_F(ReportingGarbageCollectorTest,ExpiredSourceWithPendingReports)114 TEST_F(ReportingGarbageCollectorTest, ExpiredSourceWithPendingReports) {
115 ReportingEndpointGroupKey group_key(kNak_, kReportingSource_,
116 url::Origin::Create(kUrl_), kGroup_);
117 cache()->SetV1EndpointForTesting(group_key, *kReportingSource_,
118 kIsolationInfo_, kUrl_);
119 cache()->AddReport(kReportingSource_, kNak_, kUrl_, kUserAgent_, kGroup_,
120 kType_, base::Value::Dict(), 0, tick_clock()->NowTicks(),
121 0);
122 // Mark the source as expired. The source data should be removed as soon as
123 // all reports are delivered.
124 cache()->SetExpiredSource(*kReportingSource_);
125
126 // Even though expired, GC should not delete the source as there is still a
127 // queued report.
128 garbage_collection_timer()->Fire();
129 EXPECT_EQ(1u, report_count());
130 EXPECT_EQ(1u, cache()->GetReportingSourceCountForTesting());
131 EXPECT_TRUE(cache()->GetV1EndpointForTesting(*kReportingSource_, kGroup_));
132
133 // Deliver report.
134 std::vector<raw_ptr<const ReportingReport, VectorExperimental>> reports;
135 cache()->GetReports(&reports);
136 cache()->RemoveReports(reports);
137 EXPECT_EQ(0u, report_count());
138
139 // Fire garbage collection again. The endpoint configuration should be
140 // removed.
141 garbage_collection_timer()->Fire();
142 EXPECT_EQ(0u, cache()->GetReportingSourceCountForTesting());
143 EXPECT_FALSE(cache()->GetV1EndpointForTesting(*kReportingSource_, kGroup_));
144 }
145
146 } // namespace
147 } // namespace net
148