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