1 // Copyright 2011 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 // This is a mock of the http cache and related testing classes. To be fair, it 6 // is not really a mock http cache given that it uses the real implementation of 7 // the http cache, but it has fake implementations of all required components, 8 // so it is useful for unit tests at the http layer. 9 10 #ifndef NET_HTTP_MOCK_HTTP_CACHE_H_ 11 #define NET_HTTP_MOCK_HTTP_CACHE_H_ 12 13 #include <stdint.h> 14 15 #include <map> 16 #include <memory> 17 #include <string> 18 #include <utility> 19 #include <vector> 20 21 #include "base/memory/raw_ptr.h" 22 #include "base/strings/string_split.h" 23 #include "net/base/completion_once_callback.h" 24 #include "net/base/request_priority.h" 25 #include "net/disk_cache/disk_cache.h" 26 #include "net/http/http_cache.h" 27 #include "net/http/http_transaction_test_util.h" 28 29 namespace net { 30 31 //----------------------------------------------------------------------------- 32 // Mock disk cache (a very basic memory cache implementation). 33 34 class MockDiskEntry : public disk_cache::Entry, 35 public base::RefCounted<MockDiskEntry> { 36 public: 37 enum DeferOp { 38 DEFER_NONE, 39 DEFER_CREATE, 40 DEFER_READ, 41 DEFER_WRITE, 42 }; 43 44 // Bit mask used for set_fail_requests(). 45 enum FailOp { 46 FAIL_READ = 0x01, 47 FAIL_WRITE = 0x02, 48 FAIL_READ_SPARSE = 0x04, 49 FAIL_WRITE_SPARSE = 0x08, 50 FAIL_GET_AVAILABLE_RANGE = 0x10, 51 FAIL_ALL = 0xFF 52 }; 53 54 explicit MockDiskEntry(const std::string& key); 55 is_doomed()56 bool is_doomed() const { return doomed_; } 57 58 void Doom() override; 59 void Close() override; 60 std::string GetKey() const override; 61 base::Time GetLastUsed() const override; 62 base::Time GetLastModified() const override; 63 int32_t GetDataSize(int index) const override; 64 int ReadData(int index, 65 int offset, 66 IOBuffer* buf, 67 int buf_len, 68 CompletionOnceCallback callback) override; 69 int WriteData(int index, 70 int offset, 71 IOBuffer* buf, 72 int buf_len, 73 CompletionOnceCallback callback, 74 bool truncate) override; 75 int ReadSparseData(int64_t offset, 76 IOBuffer* buf, 77 int buf_len, 78 CompletionOnceCallback callback) override; 79 int WriteSparseData(int64_t offset, 80 IOBuffer* buf, 81 int buf_len, 82 CompletionOnceCallback callback) override; 83 RangeResult GetAvailableRange(int64_t offset, 84 int len, 85 RangeResultCallback callback) override; 86 bool CouldBeSparse() const override; 87 void CancelSparseIO() override; 88 net::Error ReadyForSparseIO( 89 CompletionOnceCallback completion_callback) override; 90 void SetLastUsedTimeForTest(base::Time time) override; 91 in_memory_data()92 uint8_t in_memory_data() const { return in_memory_data_; } set_in_memory_data(uint8_t val)93 void set_in_memory_data(uint8_t val) { in_memory_data_ = val; } 94 95 // Fail subsequent requests, specified via FailOp bits. set_fail_requests(int mask)96 void set_fail_requests(int mask) { fail_requests_ = mask; } 97 set_fail_sparse_requests()98 void set_fail_sparse_requests() { fail_sparse_requests_ = true; } 99 100 // If |value| is true, don't deliver any completion callbacks until called 101 // again with |value| set to false. Caution: remember to enable callbacks 102 // again or all subsequent tests will fail. 103 static void IgnoreCallbacks(bool value); 104 105 // Defers invoking the callback for the given operation. Calling code should 106 // invoke ResumeDiskEntryOperation to resume. SetDefer(DeferOp defer_op)107 void SetDefer(DeferOp defer_op) { defer_op_ = defer_op; } 108 109 // Resumes deferred cache operation by posting |resume_callback_| with 110 // |resume_return_code_|. 111 void ResumeDiskEntryOperation(); 112 113 // Sets the maximum length of a stream. This is only applied to stream 1. set_max_file_size(int val)114 void set_max_file_size(int val) { max_file_size_ = val; } 115 116 private: 117 friend class base::RefCounted<MockDiskEntry>; 118 struct CallbackInfo; 119 120 ~MockDiskEntry() override; 121 122 // Unlike the callbacks for MockHttpTransaction, we want this one to run even 123 // if the consumer called Close on the MockDiskEntry. We achieve that by 124 // leveraging the fact that this class is reference counted. 125 void CallbackLater(CompletionOnceCallback callback, int result); 126 void CallbackLater(base::OnceClosure callback); 127 128 void RunCallback(base::OnceClosure callback); 129 130 // When |store| is true, stores the callback to be delivered later; otherwise 131 // delivers any callback previously stored. 132 static void StoreAndDeliverCallbacks(bool store, 133 MockDiskEntry* entry, 134 base::OnceClosure callback); 135 136 static const int kNumCacheEntryDataIndices = 3; 137 138 std::string key_; 139 std::vector<char> data_[kNumCacheEntryDataIndices]; 140 uint8_t in_memory_data_ = 0; 141 int test_mode_; 142 int max_file_size_; 143 bool doomed_ = false; 144 bool sparse_ = false; 145 int fail_requests_ = 0; 146 bool fail_sparse_requests_ = false; 147 bool busy_ = false; 148 bool delayed_ = false; 149 bool cancel_ = false; 150 151 // Used for pause and restart. 152 DeferOp defer_op_ = DEFER_NONE; 153 CompletionOnceCallback resume_callback_; 154 int resume_return_code_ = 0; 155 156 static bool ignore_callbacks_; 157 }; 158 159 class MockDiskCache : public disk_cache::Backend { 160 public: 161 MockDiskCache(); 162 ~MockDiskCache() override; 163 164 int32_t GetEntryCount() const override; 165 EntryResult OpenOrCreateEntry(const std::string& key, 166 net::RequestPriority request_priority, 167 EntryResultCallback callback) override; 168 EntryResult OpenEntry(const std::string& key, 169 net::RequestPriority request_priority, 170 EntryResultCallback callback) override; 171 EntryResult CreateEntry(const std::string& key, 172 net::RequestPriority request_priority, 173 EntryResultCallback callback) override; 174 net::Error DoomEntry(const std::string& key, 175 net::RequestPriority request_priority, 176 CompletionOnceCallback callback) override; 177 net::Error DoomAllEntries(CompletionOnceCallback callback) override; 178 net::Error DoomEntriesBetween(base::Time initial_time, 179 base::Time end_time, 180 CompletionOnceCallback callback) override; 181 net::Error DoomEntriesSince(base::Time initial_time, 182 CompletionOnceCallback callback) override; 183 int64_t CalculateSizeOfAllEntries( 184 Int64CompletionOnceCallback callback) override; 185 std::unique_ptr<Iterator> CreateIterator() override; 186 void GetStats(base::StringPairs* stats) override; 187 void OnExternalCacheHit(const std::string& key) override; 188 uint8_t GetEntryInMemoryData(const std::string& key) override; 189 void SetEntryInMemoryData(const std::string& key, uint8_t data) override; 190 int64_t MaxFileSize() const override; 191 192 // Returns number of times a cache entry was successfully opened. open_count()193 int open_count() const { return open_count_; } 194 195 // Returns number of times a cache entry was successfully created. create_count()196 int create_count() const { return create_count_; } 197 198 // Returns number of doomed entries. doomed_count()199 int doomed_count() const { return doomed_count_; } 200 201 // Fail any subsequent CreateEntry, OpenEntry, and DoomEntry set_fail_requests(bool value)202 void set_fail_requests(bool value) { fail_requests_ = value; } 203 204 // Return entries that fail some of their requests. 205 // The value is formed as a bitmask of MockDiskEntry::FailOp. set_soft_failures_mask(int value)206 void set_soft_failures_mask(int value) { soft_failures_ = value; } 207 208 // Returns entries that fail some of their requests, but only until 209 // the entry is re-created. The value is formed as a bitmask of 210 // MockDiskEntry::FailOp. set_soft_failures_one_instance(int value)211 void set_soft_failures_one_instance(int value) { 212 soft_failures_one_instance_ = value; 213 } 214 215 // Makes sure that CreateEntry is not called twice for a given key. set_double_create_check(bool value)216 void set_double_create_check(bool value) { double_create_check_ = value; } 217 218 // Determines whether to provide the GetEntryInMemoryData/SetEntryInMemoryData 219 // interface. Default is true. set_support_in_memory_entry_data(bool value)220 void set_support_in_memory_entry_data(bool value) { 221 support_in_memory_entry_data_ = value; 222 } 223 224 // OpenEntry, CreateEntry, and DoomEntry immediately return with 225 // ERR_IO_PENDING and will callback some time later with an error. set_force_fail_callback_later(bool value)226 void set_force_fail_callback_later(bool value) { 227 force_fail_callback_later_ = value; 228 } 229 230 // Makes all requests for data ranges to fail as not implemented. set_fail_sparse_requests()231 void set_fail_sparse_requests() { fail_sparse_requests_ = true; } 232 233 // Sets the limit on how big entry streams can get. Only stream 1 enforces 234 // this, but MaxFileSize() will still report it. set_max_file_size(int new_size)235 void set_max_file_size(int new_size) { max_file_size_ = new_size; } 236 237 void ReleaseAll(); 238 239 // Returns true if a doomed entry exists with this key. 240 bool IsDiskEntryDoomed(const std::string& key); 241 242 // Defers invoking the callback for the given operation. Calling code should 243 // invoke ResumeCacheOperation to resume. SetDefer(MockDiskEntry::DeferOp defer_op)244 void SetDefer(MockDiskEntry::DeferOp defer_op) { defer_op_ = defer_op; } 245 246 // Resume deferred cache operation by posting |resume_callback_| with 247 // |resume_return_code_|. 248 void ResumeCacheOperation(); 249 250 // Returns a reference to the disk entry with the given |key|. 251 scoped_refptr<MockDiskEntry> GetDiskEntryRef(const std::string& key); 252 253 // Returns a reference to the vector storing all keys for external cache hits. 254 const std::vector<std::string>& GetExternalCacheHits() const; 255 256 private: 257 using EntryMap = std::map<std::string, MockDiskEntry*>; 258 class NotImplementedIterator; 259 260 void CallbackLater(base::OnceClosure callback); 261 262 EntryMap entries_; 263 std::vector<std::string> external_cache_hits_; 264 int open_count_ = 0; 265 int create_count_ = 0; 266 int doomed_count_ = 0; 267 int max_file_size_; 268 bool fail_requests_ = false; 269 int soft_failures_ = 0; 270 int soft_failures_one_instance_ = 0; 271 bool double_create_check_ = true; 272 bool fail_sparse_requests_ = false; 273 bool support_in_memory_entry_data_ = true; 274 bool force_fail_callback_later_ = false; 275 276 // Used for pause and restart. 277 MockDiskEntry::DeferOp defer_op_ = MockDiskEntry::DEFER_NONE; 278 base::OnceClosure resume_callback_; 279 }; 280 281 class MockBackendFactory : public HttpCache::BackendFactory { 282 public: 283 disk_cache::BackendResult CreateBackend( 284 NetLog* net_log, 285 disk_cache::BackendResultCallback callback) override; 286 }; 287 288 class MockHttpCache { 289 public: 290 MockHttpCache(); 291 explicit MockHttpCache( 292 std::unique_ptr<HttpCache::BackendFactory> disk_cache_factory); 293 http_cache()294 HttpCache* http_cache() { return &http_cache_; } 295 network_layer()296 MockNetworkLayer* network_layer() { 297 return static_cast<MockNetworkLayer*>(http_cache_.network_layer()); 298 } 299 disk_cache::Backend* backend(); 300 MockDiskCache* disk_cache(); 301 302 // Wrapper around http_cache()->CreateTransaction(DEFAULT_PRIORITY...) 303 int CreateTransaction(std::unique_ptr<HttpTransaction>* trans); 304 305 // Wrapper to simulate cache lock timeout for new transactions. 306 void SimulateCacheLockTimeout(); 307 308 // Wrapper to simulate cache lock timeout for new transactions. 309 void SimulateCacheLockTimeoutAfterHeaders(); 310 311 // Wrapper to fail request conditionalization for new transactions. 312 void FailConditionalizations(); 313 314 // Helper function for reading response info from the disk cache. 315 static bool ReadResponseInfo(disk_cache::Entry* disk_entry, 316 HttpResponseInfo* response_info, 317 bool* response_truncated); 318 319 // Helper function for writing response info into the disk cache. 320 static bool WriteResponseInfo(disk_cache::Entry* disk_entry, 321 const HttpResponseInfo* response_info, 322 bool skip_transient_headers, 323 bool response_truncated); 324 325 // Helper function to synchronously open a backend entry. 326 bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry); 327 328 // Helper function to synchronously create a backend entry. 329 bool CreateBackendEntry(const std::string& key, 330 disk_cache::Entry** entry, 331 NetLog* net_log); 332 333 // Returns the test mode after considering the global override. 334 static int GetTestMode(int test_mode); 335 336 // Overrides the test mode for a given operation. Remember to reset it after 337 // the test! (by setting test_mode to zero). 338 static void SetTestMode(int test_mode); 339 340 // Functions to test the state of ActiveEntry. 341 bool IsWriterPresent(const std::string& key); 342 bool IsHeadersTransactionPresent(const std::string& key); 343 int GetCountReaders(const std::string& key); 344 int GetCountAddToEntryQueue(const std::string& key); 345 int GetCountDoneHeadersQueue(const std::string& key); 346 int GetCountWriterTransactions(const std::string& key); 347 348 base::WeakPtr<HttpCache> GetWeakPtr(); 349 350 private: 351 HttpCache http_cache_; 352 }; 353 354 // This version of the disk cache doesn't invoke CreateEntry callbacks. 355 class MockDiskCacheNoCB : public MockDiskCache { 356 EntryResult CreateEntry(const std::string& key, 357 net::RequestPriority request_priority, 358 EntryResultCallback callback) override; 359 }; 360 361 class MockBackendNoCbFactory : public HttpCache::BackendFactory { 362 public: 363 disk_cache::BackendResult CreateBackend( 364 NetLog* net_log, 365 disk_cache::BackendResultCallback callback) override; 366 }; 367 368 // This backend factory allows us to control the backend instantiation. 369 class MockBlockingBackendFactory : public HttpCache::BackendFactory { 370 public: 371 MockBlockingBackendFactory(); 372 ~MockBlockingBackendFactory() override; 373 374 disk_cache::BackendResult CreateBackend( 375 NetLog* net_log, 376 disk_cache::BackendResultCallback callback) override; 377 378 // Completes the backend creation. Any blocked call will be notified via the 379 // provided callback. 380 void FinishCreation(); 381 set_fail(bool fail)382 void set_fail(bool fail) { fail_ = fail; } 383 ReleaseCallback()384 disk_cache::BackendResultCallback ReleaseCallback() { 385 return std::move(callback_); 386 } 387 388 private: 389 disk_cache::BackendResult MakeResult(); 390 391 disk_cache::BackendResultCallback callback_; 392 bool block_ = true; 393 bool fail_ = false; 394 }; 395 396 } // namespace net 397 398 #endif // NET_HTTP_MOCK_HTTP_CACHE_H_ 399