xref: /aosp_15_r20/external/cronet/net/reporting/reporting_test_util.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #ifndef NET_REPORTING_REPORTING_TEST_UTIL_H_
6 #define NET_REPORTING_REPORTING_TEST_UTIL_H_
7 
8 #include <memory>
9 #include <optional>
10 #include <set>
11 #include <string>
12 #include <vector>
13 
14 #include "base/memory/raw_ptr.h"
15 #include "base/test/simple_test_clock.h"
16 #include "base/test/simple_test_tick_clock.h"
17 #include "base/unguessable_token.h"
18 #include "net/base/network_anonymization_key.h"
19 #include "net/base/rand_callback.h"
20 #include "net/reporting/reporting_cache.h"
21 #include "net/reporting/reporting_context.h"
22 #include "net/reporting/reporting_delegate.h"
23 #include "net/reporting/reporting_service.h"
24 #include "net/reporting/reporting_uploader.h"
25 #include "net/test/test_with_task_environment.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "url/gurl.h"
29 
30 namespace base {
31 class MockOneShotTimer;
32 class SimpleTestClock;
33 class SimpleTestTickClock;
34 class Value;
35 }  // namespace base
36 
37 namespace url {
38 class Origin;
39 }  // namespace url
40 
41 namespace net {
42 
43 class IsolationInfo;
44 struct ReportingEndpoint;
45 class ReportingGarbageCollector;
46 
47 // A matcher for ReportingReports, which checks that the url of the report is
48 // the given url.
49 // Usage: EXPECT_THAT(report, ReportUrlIs(url));
50 // EXPECT_THAT(reports(),
51 //             testing::ElementsAre(ReportUrlIs(url1), ReportUrlIs(url2)));
52 MATCHER_P(ReportUrlIs, url, "") {
53   return arg.url == url;
54 }
55 
56 RandIntCallback TestReportingRandIntCallback();
57 
58 // A test implementation of ReportingUploader that holds uploads for tests to
59 // examine and complete with a specified outcome.
60 class TestReportingUploader : public ReportingUploader {
61  public:
62   class PendingUpload {
63    public:
64     virtual ~PendingUpload();
65 
66     virtual const url::Origin& report_origin() const = 0;
67     virtual const GURL& url() const = 0;
68     virtual const std::string& json() const = 0;
69     virtual std::optional<base::Value> GetValue() const = 0;
70 
71     virtual void Complete(Outcome outcome) = 0;
72 
73    protected:
74     PendingUpload();
75   };
76 
77   TestReportingUploader();
78 
79   TestReportingUploader(const TestReportingUploader&) = delete;
80   TestReportingUploader& operator=(const TestReportingUploader&) = delete;
81 
82   ~TestReportingUploader() override;
83 
pending_uploads()84   const std::vector<std::unique_ptr<PendingUpload>>& pending_uploads() const {
85     return pending_uploads_;
86   }
87 
88   // ReportingUploader implementation:
89 
90   void StartUpload(const url::Origin& report_origin,
91                    const GURL& url,
92                    const IsolationInfo& isolation_info,
93                    const std::string& json,
94                    int max_depth,
95                    bool eligible_for_credentials,
96                    UploadCallback callback) override;
97 
98   void OnShutdown() override;
99 
100   int GetPendingUploadCountForTesting() const override;
101 
102  private:
103   std::vector<std::unique_ptr<PendingUpload>> pending_uploads_;
104 };
105 
106 // Allows all permissions unless set_disallow_report_uploads is called; uses
107 // the real ReportingDelegate for JSON parsing to exercise depth and size
108 // limits.
109 class TestReportingDelegate : public ReportingDelegate {
110  public:
111   TestReportingDelegate();
112 
113   TestReportingDelegate(const TestReportingDelegate&) = delete;
114   TestReportingDelegate& operator=(const TestReportingDelegate&) = delete;
115 
116   // ReportingDelegate implementation:
117 
118   ~TestReportingDelegate() override;
119 
set_disallow_report_uploads(bool disallow_report_uploads)120   void set_disallow_report_uploads(bool disallow_report_uploads) {
121     disallow_report_uploads_ = disallow_report_uploads;
122   }
123 
set_pause_permissions_check(bool pause_permissions_check)124   void set_pause_permissions_check(bool pause_permissions_check) {
125     pause_permissions_check_ = pause_permissions_check;
126   }
127 
128   bool CanQueueReport(const url::Origin& origin) const override;
129 
130   void CanSendReports(std::set<url::Origin> origins,
131                       base::OnceCallback<void(std::set<url::Origin>)>
132                           result_callback) const override;
133 
134   bool PermissionsCheckPaused() const;
135   void ResumePermissionsCheck();
136 
137   bool CanSetClient(const url::Origin& origin,
138                     const GURL& endpoint) const override;
139 
140   bool CanUseClient(const url::Origin& origin,
141                     const GURL& endpoint) const override;
142 
143  private:
144   bool disallow_report_uploads_ = false;
145   bool pause_permissions_check_ = false;
146 
147   mutable std::set<url::Origin> saved_origins_;
148   mutable base::OnceCallback<void(std::set<url::Origin>)>
149       permissions_check_callback_;
150 };
151 
152 // A test implementation of ReportingContext that uses test versions of
153 // Clock, TickClock, Timer, and ReportingUploader.
154 class TestReportingContext : public ReportingContext {
155  public:
156   TestReportingContext(
157       base::Clock* clock,
158       const base::TickClock* tick_clock,
159       const ReportingPolicy& policy,
160       ReportingCache::PersistentReportingStore* store = nullptr);
161 
162   TestReportingContext(const TestReportingContext&) = delete;
163   TestReportingContext& operator=(const TestReportingContext&) = delete;
164 
165   ~TestReportingContext() override;
166 
test_delivery_timer()167   base::MockOneShotTimer* test_delivery_timer() { return delivery_timer_; }
test_garbage_collection_timer()168   base::MockOneShotTimer* test_garbage_collection_timer() {
169     return garbage_collection_timer_;
170   }
test_uploader()171   TestReportingUploader* test_uploader() {
172     return reinterpret_cast<TestReportingUploader*>(uploader());
173   }
test_delegate()174   TestReportingDelegate* test_delegate() {
175     return reinterpret_cast<TestReportingDelegate*>(delegate());
176   }
177 
178  private:
179   // Owned by the DeliveryAgent and GarbageCollector, respectively, but
180   // referenced here to preserve type:
181 
182   raw_ptr<base::MockOneShotTimer> delivery_timer_;
183   raw_ptr<base::MockOneShotTimer> garbage_collection_timer_;
184 };
185 
186 // A unit test base class that provides a TestReportingContext and shorthand
187 // getters.
188 class ReportingTestBase : public TestWithTaskEnvironment {
189  public:
190   ReportingTestBase(const ReportingTestBase&) = delete;
191   ReportingTestBase& operator=(const ReportingTestBase&) = delete;
192 
193  protected:
194   ReportingTestBase();
195   ~ReportingTestBase() override;
196 
197   void UsePolicy(const ReportingPolicy& policy);
198   void UseStore(ReportingCache::PersistentReportingStore* store);
199 
200   // Finds a particular endpoint in the cache and returns it (or an invalid
201   // ReportingEndpoint, if not found).
202   const ReportingEndpoint FindEndpointInCache(
203       const ReportingEndpointGroupKey& group_key,
204       const GURL& url);
205 
206   // Sets an endpoint with the given properties in a group with the given
207   // properties, bypassing header parsing. Note that the endpoint is not
208   // guaranteed to exist in the cache after calling this function, if endpoint
209   // eviction is triggered. Returns whether the endpoint was successfully set.
210   bool SetEndpointInCache(
211       const ReportingEndpointGroupKey& group_key,
212       const GURL& url,
213       base::Time expires,
214       OriginSubdomains include_subdomains = OriginSubdomains::DEFAULT,
215       int priority = ReportingEndpoint::EndpointInfo::kDefaultPriority,
216       int weight = ReportingEndpoint::EndpointInfo::kDefaultWeight);
217 
218   // Sets an endpoint with the given group_key and url as origin in the document
219   // endpoints map using |reporting_source| as key.
220   void SetV1EndpointInCache(const ReportingEndpointGroupKey& group_key,
221                             const base::UnguessableToken& reporting_source,
222                             const IsolationInfo& isolation_info,
223                             const GURL& url);
224 
225   // Returns whether an endpoint with the given properties exists in the cache.
226   bool EndpointExistsInCache(const ReportingEndpointGroupKey& group_key,
227                              const GURL& url);
228 
229   // Gets the statistics for a given endpoint, if it exists.
230   ReportingEndpoint::Statistics GetEndpointStatistics(
231       const ReportingEndpointGroupKey& group_key,
232       const GURL& url);
233 
234   // Returns whether an endpoint group with exactly the given properties exists
235   // in the cache. |expires| can be omitted, in which case it will not be
236   // checked.
237   bool EndpointGroupExistsInCache(const ReportingEndpointGroupKey& group_key,
238                                   OriginSubdomains include_subdomains,
239                                   base::Time expires = base::Time());
240 
241   // Returns whether a client for the given origin exists in the cache.
242   bool ClientExistsInCacheForOrigin(const url::Origin& origin);
243 
244   // Makes a unique URL with the provided index.
245   GURL MakeURL(size_t index);
246 
247   // Simulates an embedder restart, preserving the ReportingPolicy.
248   //
249   // Advances the Clock by |delta|, and the TickClock by |delta_ticks|. Both can
250   // be zero or negative.
251   void SimulateRestart(base::TimeDelta delta, base::TimeDelta delta_ticks);
252 
context()253   TestReportingContext* context() { return context_.get(); }
254 
policy()255   const ReportingPolicy& policy() { return context_->policy(); }
256 
clock()257   base::SimpleTestClock* clock() { return &clock_; }
tick_clock()258   base::SimpleTestTickClock* tick_clock() { return &tick_clock_; }
delivery_timer()259   base::MockOneShotTimer* delivery_timer() {
260     return context_->test_delivery_timer();
261   }
garbage_collection_timer()262   base::MockOneShotTimer* garbage_collection_timer() {
263     return context_->test_garbage_collection_timer();
264   }
uploader()265   TestReportingUploader* uploader() { return context_->test_uploader(); }
266 
cache()267   ReportingCache* cache() { return context_->cache(); }
delivery_agent()268   ReportingDeliveryAgent* delivery_agent() {
269     return context_->delivery_agent();
270   }
garbage_collector()271   ReportingGarbageCollector* garbage_collector() {
272     return context_->garbage_collector();
273   }
store()274   ReportingCache::PersistentReportingStore* store() { return store_; }
275 
276   base::TimeTicks yesterday();
277   base::TimeTicks now();
278   base::TimeTicks tomorrow();
279 
280   const std::vector<std::unique_ptr<TestReportingUploader::PendingUpload>>&
pending_uploads()281   pending_uploads() {
282     return uploader()->pending_uploads();
283   }
284 
285  private:
286   void CreateContext(const ReportingPolicy& policy,
287                      base::Time now,
288                      base::TimeTicks now_ticks);
289 
290   base::SimpleTestClock clock_;
291   base::SimpleTestTickClock tick_clock_;
292   std::unique_ptr<TestReportingContext> context_;
293   raw_ptr<ReportingCache::PersistentReportingStore, DanglingUntriaged> store_ =
294       nullptr;
295 };
296 
297 class TestReportingService : public ReportingService {
298  public:
299   struct Report {
300     Report();
301 
302     Report(const Report&) = delete;
303 
304     Report(Report&& other);
305 
306     Report(const GURL& url,
307            const NetworkAnonymizationKey& network_anonymization_key,
308            const std::string& user_agent,
309            const std::string& group,
310            const std::string& type,
311            std::unique_ptr<const base::Value> body,
312            int depth);
313 
314     ~Report();
315 
316     GURL url;
317     NetworkAnonymizationKey network_anonymization_key;
318     std::string user_agent;
319     std::string group;
320     std::string type;
321     std::unique_ptr<const base::Value> body;
322     int depth;
323   };
324 
325   TestReportingService();
326 
327   TestReportingService(const TestReportingService&) = delete;
328   TestReportingService& operator=(const TestReportingService&) = delete;
329 
reports()330   const std::vector<Report>& reports() const { return reports_; }
331 
332   // ReportingService implementation:
333 
334   ~TestReportingService() override;
335 
SetDocumentReportingEndpoints(const base::UnguessableToken & reporting_source,const url::Origin & origin,const IsolationInfo & isolation_info,const base::flat_map<std::string,std::string> & endpoints)336   void SetDocumentReportingEndpoints(
337       const base::UnguessableToken& reporting_source,
338       const url::Origin& origin,
339       const IsolationInfo& isolation_info,
340       const base::flat_map<std::string, std::string>& endpoints) override {}
341 
SendReportsAndRemoveSource(const base::UnguessableToken & reporting_source)342   void SendReportsAndRemoveSource(
343       const base::UnguessableToken& reporting_source) override {}
344 
345   void QueueReport(
346       const GURL& url,
347       const std::optional<base::UnguessableToken>& reporting_source,
348       const NetworkAnonymizationKey& network_anonymization_key,
349       const std::string& user_agent,
350       const std::string& group,
351       const std::string& type,
352       base::Value::Dict body,
353       int depth) override;
354 
355   void ProcessReportToHeader(
356       const url::Origin& url,
357       const NetworkAnonymizationKey& network_anonymization_key,
358       const std::string& header_value) override;
359 
360   void RemoveBrowsingData(
361       uint64_t data_type_mask,
362       const base::RepeatingCallback<bool(const url::Origin&)>& origin_filter)
363       override;
364 
365   void RemoveAllBrowsingData(uint64_t data_type_mask) override;
366 
367   void OnShutdown() override;
368 
369   const ReportingPolicy& GetPolicy() const override;
370 
371   ReportingContext* GetContextForTesting() const override;
372 
373   std::vector<raw_ptr<const ReportingReport, VectorExperimental>> GetReports()
374       const override;
375   base::flat_map<url::Origin, std::vector<ReportingEndpoint>>
376   GetV1ReportingEndpointsByOrigin() const override;
377   void AddReportingCacheObserver(ReportingCacheObserver* observer) override;
378   void RemoveReportingCacheObserver(ReportingCacheObserver* observer) override;
379 
380  private:
381   std::vector<Report> reports_;
382   ReportingPolicy dummy_policy_;
383 };
384 
385 }  // namespace net
386 
387 #endif  // NET_REPORTING_REPORTING_TEST_UTIL_H_
388