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