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_test_util.h"
6
7 #include <memory>
8 #include <optional>
9 #include <string>
10 #include <vector>
11
12 #include "base/check_op.h"
13 #include "base/functional/bind.h"
14 #include "base/json/json_reader.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/memory/raw_ptr.h"
17 #include "base/notreached.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/test/simple_test_clock.h"
20 #include "base/test/simple_test_tick_clock.h"
21 #include "base/timer/mock_timer.h"
22 #include "net/base/isolation_info.h"
23 #include "net/base/network_anonymization_key.h"
24 #include "net/reporting/reporting_cache.h"
25 #include "net/reporting/reporting_context.h"
26 #include "net/reporting/reporting_delegate.h"
27 #include "net/reporting/reporting_delivery_agent.h"
28 #include "net/reporting/reporting_endpoint.h"
29 #include "net/reporting/reporting_garbage_collector.h"
30 #include "net/reporting/reporting_policy.h"
31 #include "net/reporting/reporting_uploader.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "url/gurl.h"
34 #include "url/origin.h"
35
36 namespace net {
37
38 namespace {
39
40 class PendingUploadImpl : public TestReportingUploader::PendingUpload {
41 public:
PendingUploadImpl(const url::Origin & report_origin,const GURL & url,const IsolationInfo & isolation_info,const std::string & json,ReportingUploader::UploadCallback callback,base::OnceCallback<void (PendingUpload *)> complete_callback)42 PendingUploadImpl(const url::Origin& report_origin,
43 const GURL& url,
44 const IsolationInfo& isolation_info,
45 const std::string& json,
46 ReportingUploader::UploadCallback callback,
47 base::OnceCallback<void(PendingUpload*)> complete_callback)
48 : report_origin_(report_origin),
49 url_(url),
50 isolation_info_(isolation_info),
51 json_(json),
52 callback_(std::move(callback)),
53 complete_callback_(std::move(complete_callback)) {}
54
55 ~PendingUploadImpl() override = default;
56
57 // PendingUpload implementation:
report_origin() const58 const url::Origin& report_origin() const override { return report_origin_; }
url() const59 const GURL& url() const override { return url_; }
json() const60 const std::string& json() const override { return json_; }
GetValue() const61 std::optional<base::Value> GetValue() const override {
62 return base::JSONReader::Read(json_);
63 }
64
Complete(ReportingUploader::Outcome outcome)65 void Complete(ReportingUploader::Outcome outcome) override {
66 std::move(callback_).Run(outcome);
67 // Deletes |this|.
68 std::move(complete_callback_).Run(this);
69 }
70
71 private:
72 url::Origin report_origin_;
73 GURL url_;
74 IsolationInfo isolation_info_;
75 std::string json_;
76 ReportingUploader::UploadCallback callback_;
77 base::OnceCallback<void(PendingUpload*)> complete_callback_;
78 };
79
ErasePendingUpload(std::vector<std::unique_ptr<TestReportingUploader::PendingUpload>> * uploads,TestReportingUploader::PendingUpload * upload)80 void ErasePendingUpload(
81 std::vector<std::unique_ptr<TestReportingUploader::PendingUpload>>* uploads,
82 TestReportingUploader::PendingUpload* upload) {
83 for (auto it = uploads->begin(); it != uploads->end(); ++it) {
84 if (it->get() == upload) {
85 uploads->erase(it);
86 return;
87 }
88 }
89 NOTREACHED();
90 }
91
92 } // namespace
93
TestReportingRandIntCallback()94 RandIntCallback TestReportingRandIntCallback() {
95 return base::BindRepeating(
96 [](int* rand_counter, int min, int max) {
97 DCHECK_LE(min, max);
98 return min + ((*rand_counter)++ % (max - min + 1));
99 },
100 base::Owned(std::make_unique<int>(0)));
101 }
102
103 TestReportingUploader::PendingUpload::~PendingUpload() = default;
104 TestReportingUploader::PendingUpload::PendingUpload() = default;
105
106 TestReportingUploader::TestReportingUploader() = default;
107 TestReportingUploader::~TestReportingUploader() = default;
108
StartUpload(const url::Origin & report_origin,const GURL & url,const IsolationInfo & isolation_info,const std::string & json,int max_depth,bool eligible_for_credentials,UploadCallback callback)109 void TestReportingUploader::StartUpload(const url::Origin& report_origin,
110 const GURL& url,
111 const IsolationInfo& isolation_info,
112 const std::string& json,
113 int max_depth,
114 bool eligible_for_credentials,
115 UploadCallback callback) {
116 pending_uploads_.push_back(std::make_unique<PendingUploadImpl>(
117 report_origin, url, isolation_info, json, std::move(callback),
118 base::BindOnce(&ErasePendingUpload, &pending_uploads_)));
119 }
120
OnShutdown()121 void TestReportingUploader::OnShutdown() {
122 pending_uploads_.clear();
123 }
124
GetPendingUploadCountForTesting() const125 int TestReportingUploader::GetPendingUploadCountForTesting() const {
126 return pending_uploads_.size();
127 }
128
129 TestReportingDelegate::TestReportingDelegate() = default;
130
131 TestReportingDelegate::~TestReportingDelegate() = default;
132
CanQueueReport(const url::Origin & origin) const133 bool TestReportingDelegate::CanQueueReport(const url::Origin& origin) const {
134 return true;
135 }
136
CanSendReports(std::set<url::Origin> origins,base::OnceCallback<void (std::set<url::Origin>)> result_callback) const137 void TestReportingDelegate::CanSendReports(
138 std::set<url::Origin> origins,
139 base::OnceCallback<void(std::set<url::Origin>)> result_callback) const {
140 if (pause_permissions_check_) {
141 saved_origins_ = std::move(origins);
142 permissions_check_callback_ = std::move(result_callback);
143 return;
144 }
145
146 if (disallow_report_uploads_)
147 origins.clear();
148 std::move(result_callback).Run(std::move(origins));
149 }
150
PermissionsCheckPaused() const151 bool TestReportingDelegate::PermissionsCheckPaused() const {
152 return !permissions_check_callback_.is_null();
153 }
154
ResumePermissionsCheck()155 void TestReportingDelegate::ResumePermissionsCheck() {
156 if (disallow_report_uploads_)
157 saved_origins_.clear();
158 std::move(permissions_check_callback_).Run(std::move(saved_origins_));
159 }
160
CanSetClient(const url::Origin & origin,const GURL & endpoint) const161 bool TestReportingDelegate::CanSetClient(const url::Origin& origin,
162 const GURL& endpoint) const {
163 return true;
164 }
165
CanUseClient(const url::Origin & origin,const GURL & endpoint) const166 bool TestReportingDelegate::CanUseClient(const url::Origin& origin,
167 const GURL& endpoint) const {
168 return true;
169 }
170
TestReportingContext(base::Clock * clock,const base::TickClock * tick_clock,const ReportingPolicy & policy,ReportingCache::PersistentReportingStore * store)171 TestReportingContext::TestReportingContext(
172 base::Clock* clock,
173 const base::TickClock* tick_clock,
174 const ReportingPolicy& policy,
175 ReportingCache::PersistentReportingStore* store)
176 : ReportingContext(policy,
177 clock,
178 tick_clock,
179 TestReportingRandIntCallback(),
180 std::make_unique<TestReportingUploader>(),
181 std::make_unique<TestReportingDelegate>(),
182 store) {
183 auto delivery_timer = std::make_unique<base::MockOneShotTimer>();
184 delivery_timer_ = delivery_timer.get();
185 auto garbage_collection_timer = std::make_unique<base::MockOneShotTimer>();
186 garbage_collection_timer_ = garbage_collection_timer.get();
187 garbage_collector()->SetTimerForTesting(std::move(garbage_collection_timer));
188 delivery_agent()->SetTimerForTesting(std::move(delivery_timer));
189 }
190
~TestReportingContext()191 TestReportingContext::~TestReportingContext() {
192 delivery_timer_ = nullptr;
193 garbage_collection_timer_ = nullptr;
194 }
195
ReportingTestBase()196 ReportingTestBase::ReportingTestBase() {
197 // For tests, disable jitter.
198 ReportingPolicy policy;
199 policy.endpoint_backoff_policy.jitter_factor = 0.0;
200
201 CreateContext(policy, base::Time::Now(), base::TimeTicks::Now());
202 }
203
204 ReportingTestBase::~ReportingTestBase() = default;
205
UsePolicy(const ReportingPolicy & new_policy)206 void ReportingTestBase::UsePolicy(const ReportingPolicy& new_policy) {
207 CreateContext(new_policy, clock()->Now(), tick_clock()->NowTicks());
208 }
209
UseStore(ReportingCache::PersistentReportingStore * store)210 void ReportingTestBase::UseStore(
211 ReportingCache::PersistentReportingStore* store) {
212 store_ = store;
213 CreateContext(policy(), clock()->Now(), tick_clock()->NowTicks());
214 }
215
FindEndpointInCache(const ReportingEndpointGroupKey & group_key,const GURL & url)216 const ReportingEndpoint ReportingTestBase::FindEndpointInCache(
217 const ReportingEndpointGroupKey& group_key,
218 const GURL& url) {
219 return cache()->GetEndpointForTesting(group_key, url);
220 }
221
SetEndpointInCache(const ReportingEndpointGroupKey & group_key,const GURL & url,base::Time expires,OriginSubdomains include_subdomains,int priority,int weight)222 bool ReportingTestBase::SetEndpointInCache(
223 const ReportingEndpointGroupKey& group_key,
224 const GURL& url,
225 base::Time expires,
226 OriginSubdomains include_subdomains,
227 int priority,
228 int weight) {
229 cache()->SetEndpointForTesting(group_key, url, include_subdomains, expires,
230 priority, weight);
231 const ReportingEndpoint endpoint = FindEndpointInCache(group_key, url);
232 return endpoint.is_valid();
233 }
234
SetV1EndpointInCache(const ReportingEndpointGroupKey & group_key,const base::UnguessableToken & reporting_source,const IsolationInfo & isolation_info,const GURL & url)235 void ReportingTestBase::SetV1EndpointInCache(
236 const ReportingEndpointGroupKey& group_key,
237 const base::UnguessableToken& reporting_source,
238 const IsolationInfo& isolation_info,
239 const GURL& url) {
240 cache()->SetV1EndpointForTesting(group_key, reporting_source, isolation_info,
241 url);
242 }
243
EndpointExistsInCache(const ReportingEndpointGroupKey & group_key,const GURL & url)244 bool ReportingTestBase::EndpointExistsInCache(
245 const ReportingEndpointGroupKey& group_key,
246 const GURL& url) {
247 ReportingEndpoint endpoint = cache()->GetEndpointForTesting(group_key, url);
248 return endpoint.is_valid();
249 }
250
GetEndpointStatistics(const ReportingEndpointGroupKey & group_key,const GURL & url)251 ReportingEndpoint::Statistics ReportingTestBase::GetEndpointStatistics(
252 const ReportingEndpointGroupKey& group_key,
253 const GURL& url) {
254 ReportingEndpoint endpoint;
255 if (group_key.IsDocumentEndpoint()) {
256 endpoint = cache()->GetV1EndpointForTesting(
257 group_key.reporting_source.value(), group_key.group_name);
258 } else {
259 endpoint = cache()->GetEndpointForTesting(group_key, url);
260 }
261 if (endpoint)
262 return endpoint.stats;
263 return ReportingEndpoint::Statistics();
264 }
265
EndpointGroupExistsInCache(const ReportingEndpointGroupKey & group_key,OriginSubdomains include_subdomains,base::Time expires)266 bool ReportingTestBase::EndpointGroupExistsInCache(
267 const ReportingEndpointGroupKey& group_key,
268 OriginSubdomains include_subdomains,
269 base::Time expires) {
270 return cache()->EndpointGroupExistsForTesting(group_key, include_subdomains,
271 expires);
272 }
273
ClientExistsInCacheForOrigin(const url::Origin & origin)274 bool ReportingTestBase::ClientExistsInCacheForOrigin(
275 const url::Origin& origin) {
276 std::set<url::Origin> all_origins = cache()->GetAllOrigins();
277 return all_origins.find(origin) != all_origins.end();
278 }
279
MakeURL(size_t index)280 GURL ReportingTestBase::MakeURL(size_t index) {
281 return GURL(base::StringPrintf("https://example%zd.test", index));
282 }
283
SimulateRestart(base::TimeDelta delta,base::TimeDelta delta_ticks)284 void ReportingTestBase::SimulateRestart(base::TimeDelta delta,
285 base::TimeDelta delta_ticks) {
286 CreateContext(policy(), clock()->Now() + delta,
287 tick_clock()->NowTicks() + delta_ticks);
288 }
289
CreateContext(const ReportingPolicy & policy,base::Time now,base::TimeTicks now_ticks)290 void ReportingTestBase::CreateContext(const ReportingPolicy& policy,
291 base::Time now,
292 base::TimeTicks now_ticks) {
293 context_ = std::make_unique<TestReportingContext>(&clock_, &tick_clock_,
294 policy, store_);
295 clock()->SetNow(now);
296 tick_clock()->SetNowTicks(now_ticks);
297 }
298
yesterday()299 base::TimeTicks ReportingTestBase::yesterday() {
300 return tick_clock()->NowTicks() - base::Days(1);
301 }
302
now()303 base::TimeTicks ReportingTestBase::now() {
304 return tick_clock()->NowTicks();
305 }
306
tomorrow()307 base::TimeTicks ReportingTestBase::tomorrow() {
308 return tick_clock()->NowTicks() + base::Days(1);
309 }
310
311 TestReportingService::Report::Report() = default;
312
313 TestReportingService::Report::Report(Report&& other) = default;
314
Report(const GURL & url,const NetworkAnonymizationKey & network_anonymization_key,const std::string & user_agent,const std::string & group,const std::string & type,std::unique_ptr<const base::Value> body,int depth)315 TestReportingService::Report::Report(
316 const GURL& url,
317 const NetworkAnonymizationKey& network_anonymization_key,
318 const std::string& user_agent,
319 const std::string& group,
320 const std::string& type,
321 std::unique_ptr<const base::Value> body,
322 int depth)
323 : url(url),
324 network_anonymization_key(network_anonymization_key),
325 user_agent(user_agent),
326 group(group),
327 type(type),
328 body(std::move(body)),
329 depth(depth) {}
330
331 TestReportingService::Report::~Report() = default;
332
333 TestReportingService::TestReportingService() = default;
334
335 TestReportingService::~TestReportingService() = default;
336
QueueReport(const GURL & url,const std::optional<base::UnguessableToken> & reporting_source,const NetworkAnonymizationKey & network_anonymization_key,const std::string & user_agent,const std::string & group,const std::string & type,base::Value::Dict body,int depth)337 void TestReportingService::QueueReport(
338 const GURL& url,
339 const std::optional<base::UnguessableToken>& reporting_source,
340 const NetworkAnonymizationKey& network_anonymization_key,
341 const std::string& user_agent,
342 const std::string& group,
343 const std::string& type,
344 base::Value::Dict body,
345 int depth) {
346 reports_.emplace_back(
347 Report(url, network_anonymization_key, user_agent, group, type,
348 std::make_unique<base::Value>(std::move(body)), depth));
349 }
350
ProcessReportToHeader(const url::Origin & origin,const NetworkAnonymizationKey & network_anonymization_key,const std::string & header_value)351 void TestReportingService::ProcessReportToHeader(
352 const url::Origin& origin,
353 const NetworkAnonymizationKey& network_anonymization_key,
354 const std::string& header_value) {
355 NOTREACHED();
356 }
357
RemoveBrowsingData(uint64_t data_type_mask,const base::RepeatingCallback<bool (const url::Origin &)> & origin_filter)358 void TestReportingService::RemoveBrowsingData(
359 uint64_t data_type_mask,
360 const base::RepeatingCallback<bool(const url::Origin&)>& origin_filter) {
361 NOTREACHED();
362 }
363
RemoveAllBrowsingData(uint64_t data_type_mask)364 void TestReportingService::RemoveAllBrowsingData(uint64_t data_type_mask) {
365 NOTREACHED();
366 }
367
OnShutdown()368 void TestReportingService::OnShutdown() {}
369
GetPolicy() const370 const ReportingPolicy& TestReportingService::GetPolicy() const {
371 NOTREACHED();
372 return dummy_policy_;
373 }
374
GetContextForTesting() const375 ReportingContext* TestReportingService::GetContextForTesting() const {
376 NOTREACHED();
377 return nullptr;
378 }
379
380 std::vector<raw_ptr<const ReportingReport, VectorExperimental>>
GetReports() const381 TestReportingService::GetReports() const {
382 NOTREACHED();
383 return std::vector<raw_ptr<const ReportingReport, VectorExperimental>>();
384 }
385
386 base::flat_map<url::Origin, std::vector<ReportingEndpoint>>
GetV1ReportingEndpointsByOrigin() const387 TestReportingService::GetV1ReportingEndpointsByOrigin() const {
388 NOTREACHED();
389 return base::flat_map<url::Origin, std::vector<ReportingEndpoint>>();
390 }
391
AddReportingCacheObserver(ReportingCacheObserver * observer)392 void TestReportingService::AddReportingCacheObserver(
393 ReportingCacheObserver* observer) {
394 NOTREACHED();
395 }
396
RemoveReportingCacheObserver(ReportingCacheObserver * observer)397 void TestReportingService::RemoveReportingCacheObserver(
398 ReportingCacheObserver* observer) {
399 NOTREACHED();
400 }
401
402 } // namespace net
403