1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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/strings/string_split.h" 22 #include "net/base/completion_once_callback.h" 23 #include "net/base/request_priority.h" 24 #include "net/disk_cache/disk_cache.h" 25 #include "net/http/http_cache.h" 26 #include "net/http/http_transaction_test_util.h" 27 28 namespace net { 29 30 //----------------------------------------------------------------------------- 31 // Mock disk cache (a very basic memory cache implementation). 32 33 class MockDiskEntry : public disk_cache::Entry, 34 public base::RefCounted<MockDiskEntry> { 35 public: 36 enum DeferOp { 37 DEFER_NONE, 38 DEFER_CREATE, 39 DEFER_READ, 40 DEFER_WRITE, 41 }; 42 43 // Bit mask used for set_fail_requests(). 44 enum FailOp { 45 FAIL_READ = 0x01, 46 FAIL_WRITE = 0x02, 47 FAIL_READ_SPARSE = 0x04, 48 FAIL_WRITE_SPARSE = 0x08, 49 FAIL_GET_AVAILABLE_RANGE = 0x10, 50 FAIL_ALL = 0xFF 51 }; 52 53 explicit MockDiskEntry(const std::string& key); 54 is_doomed()55 bool is_doomed() const { return doomed_; } 56 57 void Doom() override; 58 void Close() override; 59 std::string GetKey() const override; 60 base::Time GetLastUsed() const override; 61 base::Time GetLastModified() const override; 62 int32_t GetDataSize(int index) const override; 63 int ReadData(int index, 64 int offset, 65 IOBuffer* buf, 66 int buf_len, 67 CompletionOnceCallback callback) override; 68 int WriteData(int index, 69 int offset, 70 IOBuffer* buf, 71 int buf_len, 72 CompletionOnceCallback callback, 73 bool truncate) override; 74 int ReadSparseData(int64_t offset, 75 IOBuffer* buf, 76 int buf_len, 77 CompletionOnceCallback callback) override; 78 int WriteSparseData(int64_t offset, 79 IOBuffer* buf, 80 int buf_len, 81 CompletionOnceCallback callback) override; 82 int GetAvailableRange(int64_t offset, 83 int len, 84 int64_t* start, 85 CompletionOnceCallback 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 127 void RunCallback(CompletionOnceCallback callback, int result); 128 129 // When |store| is true, stores the callback to be delivered later; otherwise 130 // delivers any callback previously stored. 131 static void StoreAndDeliverCallbacks(bool store, 132 MockDiskEntry* entry, 133 CompletionOnceCallback callback, 134 int result); 135 136 static const int kNumCacheEntryDataIndices = 3; 137 138 std::string key_; 139 std::vector<char> data_[kNumCacheEntryDataIndices]; 140 uint8_t in_memory_data_; 141 int test_mode_; 142 int max_file_size_; 143 bool doomed_; 144 bool sparse_; 145 int fail_requests_; 146 bool fail_sparse_requests_; 147 bool busy_; 148 bool delayed_; 149 bool cancel_; 150 151 // Used for pause and restart. 152 DeferOp defer_op_; 153 CompletionOnceCallback resume_callback_; 154 int resume_return_code_; 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 size_t DumpMemoryStats( 189 base::trace_event::ProcessMemoryDump* pmd, 190 const std::string& parent_absolute_name) const override; 191 uint8_t GetEntryInMemoryData(const std::string& key) override; 192 void SetEntryInMemoryData(const std::string& key, uint8_t data) override; 193 int64_t MaxFileSize() const override; 194 195 // Returns number of times a cache entry was successfully opened. open_count()196 int open_count() const { return open_count_; } 197 198 // Returns number of times a cache entry was successfully created. create_count()199 int create_count() const { return create_count_; } 200 201 // Returns number of doomed entries. doomed_count()202 int doomed_count() const { return doomed_count_; } 203 204 // Fail any subsequent CreateEntry, OpenEntry, and DoomEntry set_fail_requests(bool value)205 void set_fail_requests(bool value) { fail_requests_ = value; } 206 207 // Return entries that fail some of their requests. 208 // The value is formed as a bitmask of MockDiskEntry::FailOp. set_soft_failures_mask(int value)209 void set_soft_failures_mask(int value) { soft_failures_ = value; } 210 211 // Returns entries that fail some of their requests, but only until 212 // the entry is re-created. The value is formed as a bitmask of 213 // MockDiskEntry::FailOp. set_soft_failures_one_instance(int value)214 void set_soft_failures_one_instance(int value) { 215 soft_failures_one_instance_ = value; 216 } 217 218 // Makes sure that CreateEntry is not called twice for a given key. set_double_create_check(bool value)219 void set_double_create_check(bool value) { double_create_check_ = value; } 220 221 // Determines whether to provide the GetEntryInMemoryData/SetEntryInMemoryData 222 // interface. Default is true. set_support_in_memory_entry_data(bool value)223 void set_support_in_memory_entry_data(bool value) { 224 support_in_memory_entry_data_ = value; 225 } 226 227 // OpenEntry, CreateEntry, and DoomEntry immediately return with 228 // ERR_IO_PENDING and will callback some time later with an error. set_force_fail_callback_later(bool value)229 void set_force_fail_callback_later(bool value) { 230 force_fail_callback_later_ = value; 231 } 232 233 // Makes all requests for data ranges to fail as not implemented. set_fail_sparse_requests()234 void set_fail_sparse_requests() { fail_sparse_requests_ = true; } 235 236 // Sets the limit on how big entry streams can get. Only stream 1 enforces 237 // this, but MaxFileSize() will still report it. set_max_file_size(int new_size)238 void set_max_file_size(int new_size) { max_file_size_ = new_size; } 239 240 void ReleaseAll(); 241 242 // Returns true if a doomed entry exists with this key. 243 bool IsDiskEntryDoomed(const std::string& key); 244 245 // Defers invoking the callback for the given operation. Calling code should 246 // invoke ResumeCacheOperation to resume. SetDefer(MockDiskEntry::DeferOp defer_op)247 void SetDefer(MockDiskEntry::DeferOp defer_op) { defer_op_ = defer_op; } 248 249 // Resume deferred cache operation by posting |resume_callback_| with 250 // |resume_return_code_|. 251 void ResumeCacheOperation(); 252 253 // Returns a reference to the disk entry with the given |key|. 254 scoped_refptr<MockDiskEntry> GetDiskEntryRef(const std::string& key); 255 256 // Returns a reference to the vector storing all keys for external cache hits. 257 const std::vector<std::string>& GetExternalCacheHits() const; 258 259 private: 260 using EntryMap = std::map<std::string, MockDiskEntry*>; 261 class NotImplementedIterator; 262 263 void CallbackLater(base::OnceClosure callback); 264 265 EntryMap entries_; 266 std::vector<std::string> external_cache_hits_; 267 int open_count_; 268 int create_count_; 269 int doomed_count_; 270 int max_file_size_; 271 bool fail_requests_; 272 int soft_failures_; 273 int soft_failures_one_instance_; 274 bool double_create_check_; 275 bool fail_sparse_requests_; 276 bool support_in_memory_entry_data_; 277 bool force_fail_callback_later_; 278 279 // Used for pause and restart. 280 MockDiskEntry::DeferOp defer_op_; 281 base::OnceClosure resume_callback_; 282 }; 283 284 class MockBackendFactory : public HttpCache::BackendFactory { 285 public: 286 int CreateBackend(NetLog* net_log, 287 std::unique_ptr<disk_cache::Backend>* backend, 288 CompletionOnceCallback callback) override; 289 }; 290 291 class MockHttpCache { 292 public: 293 MockHttpCache(); 294 explicit MockHttpCache( 295 std::unique_ptr<HttpCache::BackendFactory> disk_cache_factory); 296 // |is_main_cache| if set, will set a quic server info factory. 297 explicit MockHttpCache(bool is_main_cache); 298 299 MockHttpCache(std::unique_ptr<HttpCache::BackendFactory> disk_cache_factory, 300 bool is_main_cache); 301 http_cache()302 HttpCache* http_cache() { return &http_cache_; } 303 network_layer()304 MockNetworkLayer* network_layer() { 305 return static_cast<MockNetworkLayer*>(http_cache_.network_layer()); 306 } 307 disk_cache::Backend* backend(); 308 MockDiskCache* disk_cache(); 309 310 // Wrapper around http_cache()->CreateTransaction(DEFAULT_PRIORITY...) 311 int CreateTransaction(std::unique_ptr<HttpTransaction>* trans); 312 313 // Wrapper to simulate cache lock timeout for new transactions. 314 void SimulateCacheLockTimeout(); 315 316 // Wrapper to simulate cache lock timeout for new transactions. 317 void SimulateCacheLockTimeoutAfterHeaders(); 318 319 // Wrapper to fail request conditionalization for new transactions. 320 void FailConditionalizations(); 321 322 // Helper function for reading response info from the disk cache. 323 static bool ReadResponseInfo(disk_cache::Entry* disk_entry, 324 HttpResponseInfo* response_info, 325 bool* response_truncated); 326 327 // Helper function for writing response info into the disk cache. 328 static bool WriteResponseInfo(disk_cache::Entry* disk_entry, 329 const HttpResponseInfo* response_info, 330 bool skip_transient_headers, 331 bool response_truncated); 332 333 // Helper function to synchronously open a backend entry. 334 bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry); 335 336 // Helper function to synchronously create a backend entry. 337 bool CreateBackendEntry(const std::string& key, 338 disk_cache::Entry** entry, 339 NetLog* net_log); 340 341 // Returns the test mode after considering the global override. 342 static int GetTestMode(int test_mode); 343 344 // Overrides the test mode for a given operation. Remember to reset it after 345 // the test! (by setting test_mode to zero). 346 static void SetTestMode(int test_mode); 347 348 // Functions to test the state of ActiveEntry. 349 bool IsWriterPresent(const std::string& key); 350 bool IsHeadersTransactionPresent(const std::string& key); 351 int GetCountReaders(const std::string& key); 352 int GetCountAddToEntryQueue(const std::string& key); 353 int GetCountDoneHeadersQueue(const std::string& key); 354 int GetCountWriterTransactions(const std::string& key); 355 356 private: 357 HttpCache http_cache_; 358 }; 359 360 // This version of the disk cache doesn't invoke CreateEntry callbacks. 361 class MockDiskCacheNoCB : public MockDiskCache { 362 EntryResult CreateEntry(const std::string& key, 363 net::RequestPriority request_priority, 364 EntryResultCallback callback) override; 365 }; 366 367 class MockBackendNoCbFactory : public HttpCache::BackendFactory { 368 public: 369 int CreateBackend(NetLog* net_log, 370 std::unique_ptr<disk_cache::Backend>* backend, 371 CompletionOnceCallback callback) override; 372 }; 373 374 // This backend factory allows us to control the backend instantiation. 375 class MockBlockingBackendFactory : public HttpCache::BackendFactory { 376 public: 377 MockBlockingBackendFactory(); 378 ~MockBlockingBackendFactory() override; 379 380 int CreateBackend(NetLog* net_log, 381 std::unique_ptr<disk_cache::Backend>* backend, 382 CompletionOnceCallback callback) override; 383 384 // Completes the backend creation. Any blocked call will be notified via the 385 // provided callback. 386 void FinishCreation(); 387 backend()388 std::unique_ptr<disk_cache::Backend>* backend() { return backend_; } set_fail(bool fail)389 void set_fail(bool fail) { fail_ = fail; } 390 ReleaseCallback()391 CompletionOnceCallback ReleaseCallback() { return std::move(callback_); } 392 393 private: Result()394 int Result() { return fail_ ? ERR_FAILED : OK; } 395 396 std::unique_ptr<disk_cache::Backend>* backend_; 397 CompletionOnceCallback callback_; 398 bool block_; 399 bool fail_; 400 }; 401 402 } // namespace net 403 404 #endif // NET_HTTP_MOCK_HTTP_CACHE_H_ 405