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