Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: net/http/mock_http_cache.h

Issue 8588011: Split DiskCacheBasedSSLHostInfo unit tests to its own (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 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 #pragma once
13
14 #include "base/hash_tables.h"
15 #include "net/disk_cache/disk_cache.h"
5 #include "net/http/http_cache.h" 16 #include "net/http/http_cache.h"
6
7 #include "base/bind.h"
8 #include "base/hash_tables.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/message_loop.h"
11 #include "base/string_util.h"
12 #include "base/stringprintf.h"
13 #include "net/base/cache_type.h"
14 #include "net/base/cert_status_flags.h"
15 #include "net/base/host_port_pair.h"
16 #include "net/base/load_flags.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/net_log_unittest.h"
19 #include "net/base/ssl_cert_request_info.h"
20 #include "net/base/ssl_config_service.h"
21 #include "net/disk_cache/disk_cache.h"
22 #include "net/http/disk_cache_based_ssl_host_info.h"
23 #include "net/http/http_byte_range.h"
24 #include "net/http/http_request_headers.h"
25 #include "net/http/http_request_info.h"
26 #include "net/http/http_response_headers.h"
27 #include "net/http/http_response_info.h"
28 #include "net/http/http_transaction.h"
29 #include "net/http/http_transaction_unittest.h" 17 #include "net/http/http_transaction_unittest.h"
30 #include "net/http/http_util.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 using base::Time;
34
35 namespace {
36
37 int GetTestModeForEntry(const std::string& key) {
38 // 'key' is prefixed with an identifier if it corresponds to a cached POST.
39 // Skip past that to locate the actual URL.
40 //
41 // TODO(darin): It breaks the abstraction a bit that we assume 'key' is an
42 // URL corresponding to a registered MockTransaction. It would be good to
43 // have another way to access the test_mode.
44 GURL url;
45 if (isdigit(key[0])) {
46 size_t slash = key.find('/');
47 DCHECK(slash != std::string::npos);
48 url = GURL(key.substr(slash + 1));
49 } else {
50 url = GURL(key);
51 }
52 const MockTransaction* t = FindMockTransaction(url);
53 DCHECK(t);
54 return t->test_mode;
55 }
56
57 // We can override the test mode for a given operation by setting this global
58 // variable. Just remember to reset it after the test!.
59 int g_test_mode = 0;
60
61 // Returns the test mode after considering the global override.
62 int GetEffectiveTestMode(int test_mode) {
63 if (!g_test_mode)
64 return test_mode;
65
66 return g_test_mode;
67 }
68 18
69 //----------------------------------------------------------------------------- 19 //-----------------------------------------------------------------------------
70 // mock disk cache (a very basic memory cache implementation) 20 // Mock disk cache (a very basic memory cache implementation).
71
72 static const int kNumCacheEntryDataIndices = 3;
73 21
74 class MockDiskEntry : public disk_cache::Entry, 22 class MockDiskEntry : public disk_cache::Entry,
75 public base::RefCounted<MockDiskEntry> { 23 public base::RefCounted<MockDiskEntry> {
76 public: 24 public:
77 MockDiskEntry() 25 MockDiskEntry();
78 : test_mode_(0), doomed_(false), sparse_(false), 26 explicit MockDiskEntry(const std::string& key);
79 fail_requests_(false), busy_(false), delayed_(false) {
80 }
81
82 explicit MockDiskEntry(const std::string& key)
83 : key_(key), doomed_(false), sparse_(false),
84 fail_requests_(false), busy_(false), delayed_(false) {
85 test_mode_ = GetTestModeForEntry(key);
86 }
87 27
88 bool is_doomed() const { return doomed_; } 28 bool is_doomed() const { return doomed_; }
89 29
90 virtual void Doom() { 30 virtual void Doom() OVERRIDE;
91 doomed_ = true; 31 virtual void Close() OVERRIDE;
92 } 32 virtual std::string GetKey() const OVERRIDE;
93 33 virtual base::Time GetLastUsed() const OVERRIDE;
94 virtual void Close() { 34 virtual base::Time GetLastModified() const OVERRIDE;
95 Release(); 35 virtual int32 GetDataSize(int index) const OVERRIDE;
96 }
97
98 virtual std::string GetKey() const {
99 if (fail_requests_)
100 return std::string();
101 return key_;
102 }
103
104 virtual Time GetLastUsed() const {
105 return Time::FromInternalValue(0);
106 }
107
108 virtual Time GetLastModified() const {
109 return Time::FromInternalValue(0);
110 }
111
112 virtual int32 GetDataSize(int index) const {
113 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices);
114 return static_cast<int32>(data_[index].size());
115 }
116
117 virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len, 36 virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
118 net::OldCompletionCallback* callback) { 37 net::OldCompletionCallback* callback) OVERRIDE;
119 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices);
120 DCHECK(callback);
121
122 if (fail_requests_)
123 return net::ERR_CACHE_READ_FAILURE;
124
125 if (offset < 0 || offset > static_cast<int>(data_[index].size()))
126 return net::ERR_FAILED;
127 if (static_cast<size_t>(offset) == data_[index].size())
128 return 0;
129
130 int num = std::min(buf_len, static_cast<int>(data_[index].size()) - offset);
131 memcpy(buf->data(), &data_[index][offset], num);
132
133 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ)
134 return num;
135
136 CallbackLater(callback, num);
137 return net::ERR_IO_PENDING;
138 }
139
140 virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, 38 virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len,
141 net::OldCompletionCallback* callback, bool truncate) { 39 net::OldCompletionCallback* callback,
142 DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); 40 bool truncate) OVERRIDE;
143 DCHECK(callback);
144 DCHECK(truncate);
145
146 if (fail_requests_) {
147 CallbackLater(callback, net::ERR_CACHE_READ_FAILURE);
148 return net::ERR_IO_PENDING;
149 }
150
151 if (offset < 0 || offset > static_cast<int>(data_[index].size()))
152 return net::ERR_FAILED;
153
154 data_[index].resize(offset + buf_len);
155 if (buf_len)
156 memcpy(&data_[index][offset], buf->data(), buf_len);
157
158 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE)
159 return buf_len;
160
161 CallbackLater(callback, buf_len);
162 return net::ERR_IO_PENDING;
163 }
164
165 virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, 41 virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
166 net::OldCompletionCallback* callback) { 42 net::OldCompletionCallback* callback) OVERRIDE;
167 DCHECK(callback);
168 if (!sparse_ || busy_)
169 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
170 if (offset < 0)
171 return net::ERR_FAILED;
172
173 if (fail_requests_)
174 return net::ERR_CACHE_READ_FAILURE;
175
176 DCHECK(offset < kint32max);
177 int real_offset = static_cast<int>(offset);
178 if (!buf_len)
179 return 0;
180
181 int num = std::min(static_cast<int>(data_[1].size()) - real_offset,
182 buf_len);
183 memcpy(buf->data(), &data_[1][real_offset], num);
184
185 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ)
186 return num;
187
188 CallbackLater(callback, num);
189 busy_ = true;
190 delayed_ = false;
191 return net::ERR_IO_PENDING;
192 }
193
194 virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, 43 virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
195 net::OldCompletionCallback* callback) { 44 net::OldCompletionCallback* callback) OVERRIDE;
196 DCHECK(callback);
197 if (busy_)
198 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
199 if (!sparse_) {
200 if (data_[1].size())
201 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
202 sparse_ = true;
203 }
204 if (offset < 0)
205 return net::ERR_FAILED;
206 if (!buf_len)
207 return 0;
208
209 if (fail_requests_)
210 return net::ERR_CACHE_READ_FAILURE;
211
212 DCHECK(offset < kint32max);
213 int real_offset = static_cast<int>(offset);
214
215 if (static_cast<int>(data_[1].size()) < real_offset + buf_len)
216 data_[1].resize(real_offset + buf_len);
217
218 memcpy(&data_[1][real_offset], buf->data(), buf_len);
219 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE)
220 return buf_len;
221
222 CallbackLater(callback, buf_len);
223 return net::ERR_IO_PENDING;
224 }
225
226 virtual int GetAvailableRange(int64 offset, int len, int64* start, 45 virtual int GetAvailableRange(int64 offset, int len, int64* start,
227 net::OldCompletionCallback* callback) { 46 net::OldCompletionCallback* callback) OVERRIDE;
228 DCHECK(callback); 47 virtual bool CouldBeSparse() const OVERRIDE;
229 if (!sparse_ || busy_) 48 virtual void CancelSparseIO() OVERRIDE;
230 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 49 virtual int ReadyForSparseIO(
231 if (offset < 0) 50 net::OldCompletionCallback* completion_callback) OVERRIDE;
232 return net::ERR_FAILED;
233
234 if (fail_requests_)
235 return net::ERR_CACHE_READ_FAILURE;
236
237 *start = offset;
238 DCHECK(offset < kint32max);
239 int real_offset = static_cast<int>(offset);
240 if (static_cast<int>(data_[1].size()) < real_offset)
241 return 0;
242
243 int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len);
244 int count = 0;
245 for (; num > 0; num--, real_offset++) {
246 if (!count) {
247 if (data_[1][real_offset]) {
248 count++;
249 *start = real_offset;
250 }
251 } else {
252 if (!data_[1][real_offset])
253 break;
254 count++;
255 }
256 }
257 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE)
258 return count;
259
260 CallbackLater(callback, count);
261 return net::ERR_IO_PENDING;
262 }
263
264 virtual bool CouldBeSparse() const {
265 return sparse_;
266 }
267
268 virtual void CancelSparseIO() { cancel_ = true; }
269
270 virtual int ReadyForSparseIO(net::OldCompletionCallback* completion_callback) {
271 if (!cancel_)
272 return net::OK;
273
274 cancel_ = false;
275 DCHECK(completion_callback);
276 if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ)
277 return net::OK;
278
279 // The pending operation is already in the message loop (and hopefuly
280 // already in the second pass). Just notify the caller that it finished.
281 CallbackLater(completion_callback, 0);
282 return net::ERR_IO_PENDING;
283 }
284 51
285 // Fail most subsequent requests. 52 // Fail most subsequent requests.
286 void set_fail_requests() { fail_requests_ = true; } 53 void set_fail_requests() { fail_requests_ = true; }
287 54
288 // If |value| is true, don't deliver any completion callbacks until called 55 // If |value| is true, don't deliver any completion callbacks until called
289 // again with |value| set to false. Caution: remember to enable callbacks 56 // again with |value| set to false. Caution: remember to enable callbacks
290 // again or all subsequent tests will fail. 57 // again or all subsequent tests will fail.
291 static void IgnoreCallbacks(bool value) { 58 static void IgnoreCallbacks(bool value);
292 if (ignore_callbacks_ == value)
293 return;
294 ignore_callbacks_ = value;
295 if (!value)
296 StoreAndDeliverCallbacks(false, NULL, NULL, 0);
297 }
298 59
299 private: 60 private:
300 friend class base::RefCounted<MockDiskEntry>; 61 friend class base::RefCounted<MockDiskEntry>;
62 struct CallbackInfo;
301 63
302 struct CallbackInfo { 64 virtual ~MockDiskEntry();
303 scoped_refptr<MockDiskEntry> entry;
304 net::OldCompletionCallback* callback;
305 int result;
306 };
307
308 ~MockDiskEntry() {}
309 65
310 // Unlike the callbacks for MockHttpTransaction, we want this one to run even 66 // Unlike the callbacks for MockHttpTransaction, we want this one to run even
311 // if the consumer called Close on the MockDiskEntry. We achieve that by 67 // if the consumer called Close on the MockDiskEntry. We achieve that by
312 // leveraging the fact that this class is reference counted. 68 // leveraging the fact that this class is reference counted.
313 void CallbackLater(net::OldCompletionCallback* callback, int result) { 69 void CallbackLater(net::OldCompletionCallback* callback, int result);
314 if (ignore_callbacks_) 70
315 return StoreAndDeliverCallbacks(true, this, callback, result); 71 void RunCallback(net::OldCompletionCallback* callback, int result);
316 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
317 &MockDiskEntry::RunCallback, this, callback, result));
318 }
319 void RunCallback(net::OldCompletionCallback* callback, int result) {
320 if (busy_) {
321 // This is kind of hacky, but controlling the behavior of just this entry
322 // from a test is sort of complicated. What we really want to do is
323 // delay the delivery of a sparse IO operation a little more so that the
324 // request start operation (async) will finish without seeing the end of
325 // this operation (already posted to the message loop)... and without
326 // just delaying for n mS (which may cause trouble with slow bots). So
327 // we re-post this operation (all async sparse IO operations will take two
328 // trips trhough the message loop instead of one).
329 if (!delayed_) {
330 delayed_ = true;
331 return CallbackLater(callback, result);
332 }
333 }
334 busy_ = false;
335 callback->Run(result);
336 }
337 72
338 // When |store| is true, stores the callback to be delivered later; otherwise 73 // When |store| is true, stores the callback to be delivered later; otherwise
339 // delivers any callback previously stored. 74 // delivers any callback previously stored.
340 static void StoreAndDeliverCallbacks(bool store, MockDiskEntry* entry, 75 static void StoreAndDeliverCallbacks(bool store, MockDiskEntry* entry,
341 net::OldCompletionCallback* callback, 76 net::OldCompletionCallback* callback,
342 int result) { 77 int result);
343 static std::vector<CallbackInfo> callback_list; 78
344 if (store) { 79 static const int kNumCacheEntryDataIndices = 3;
345 CallbackInfo c = {entry, callback, result};
346 callback_list.push_back(c);
347 } else {
348 for (size_t i = 0; i < callback_list.size(); i++) {
349 CallbackInfo& c = callback_list[i];
350 c.entry->CallbackLater(c.callback, c.result);
351 }
352 callback_list.clear();
353 }
354 }
355 80
356 std::string key_; 81 std::string key_;
357 std::vector<char> data_[kNumCacheEntryDataIndices]; 82 std::vector<char> data_[kNumCacheEntryDataIndices];
358 int test_mode_; 83 int test_mode_;
359 bool doomed_; 84 bool doomed_;
360 bool sparse_; 85 bool sparse_;
361 bool fail_requests_; 86 bool fail_requests_;
362 bool busy_; 87 bool busy_;
363 bool delayed_; 88 bool delayed_;
364 static bool cancel_; 89 static bool cancel_;
365 static bool ignore_callbacks_; 90 static bool ignore_callbacks_;
366 }; 91 };
367 92
368 // Statics.
369 bool MockDiskEntry::cancel_ = false;
370 bool MockDiskEntry::ignore_callbacks_ = false;
371
372 class MockDiskCache : public disk_cache::Backend { 93 class MockDiskCache : public disk_cache::Backend {
373 public: 94 public:
374 MockDiskCache() 95 MockDiskCache();
375 : open_count_(0), create_count_(0), fail_requests_(false), 96 virtual ~MockDiskCache();
376 soft_failures_(false) {
377 }
378 97
379 ~MockDiskCache() { 98 virtual int32 GetEntryCount() const OVERRIDE;
380 ReleaseAll();
381 }
382
383 virtual int32 GetEntryCount() const {
384 return static_cast<int32>(entries_.size());
385 }
386
387 virtual int OpenEntry(const std::string& key, disk_cache::Entry** entry, 99 virtual int OpenEntry(const std::string& key, disk_cache::Entry** entry,
388 net::OldCompletionCallback* callback) { 100 net::OldCompletionCallback* callback) OVERRIDE;
389 DCHECK(callback);
390 if (fail_requests_)
391 return net::ERR_CACHE_OPEN_FAILURE;
392
393 EntryMap::iterator it = entries_.find(key);
394 if (it == entries_.end())
395 return net::ERR_CACHE_OPEN_FAILURE;
396
397 if (it->second->is_doomed()) {
398 it->second->Release();
399 entries_.erase(it);
400 return net::ERR_CACHE_OPEN_FAILURE;
401 }
402
403 open_count_++;
404
405 it->second->AddRef();
406 *entry = it->second;
407
408 if (soft_failures_)
409 it->second->set_fail_requests();
410
411 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START)
412 return net::OK;
413
414 CallbackLater(callback, net::OK);
415 return net::ERR_IO_PENDING;
416 }
417
418 virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry, 101 virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry,
419 net::OldCompletionCallback* callback) { 102 net::OldCompletionCallback* callback) OVERRIDE;
420 DCHECK(callback);
421 if (fail_requests_)
422 return net::ERR_CACHE_CREATE_FAILURE;
423
424 EntryMap::iterator it = entries_.find(key);
425 if (it != entries_.end()) {
426 DCHECK(it->second->is_doomed());
427 it->second->Release();
428 entries_.erase(it);
429 }
430
431 create_count_++;
432
433 MockDiskEntry* new_entry = new MockDiskEntry(key);
434
435 new_entry->AddRef();
436 entries_[key] = new_entry;
437
438 new_entry->AddRef();
439 *entry = new_entry;
440
441 if (soft_failures_)
442 new_entry->set_fail_requests();
443
444 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START)
445 return net::OK;
446
447 CallbackLater(callback, net::OK);
448 return net::ERR_IO_PENDING;
449 }
450
451 virtual int DoomEntry(const std::string& key, 103 virtual int DoomEntry(const std::string& key,
452 net::OldCompletionCallback* callback) { 104 net::OldCompletionCallback* callback) OVERRIDE;
453 DCHECK(callback); 105 virtual int DoomAllEntries(net::OldCompletionCallback* callback) OVERRIDE;
454 EntryMap::iterator it = entries_.find(key);
455 if (it != entries_.end()) {
456 it->second->Release();
457 entries_.erase(it);
458 }
459
460 if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START)
461 return net::OK;
462
463 CallbackLater(callback, net::OK);
464 return net::ERR_IO_PENDING;
465 }
466
467 virtual int DoomAllEntries(net::OldCompletionCallback* callback) {
468 return net::ERR_NOT_IMPLEMENTED;
469 }
470
471 virtual int DoomEntriesBetween(const base::Time initial_time, 106 virtual int DoomEntriesBetween(const base::Time initial_time,
472 const base::Time end_time, 107 const base::Time end_time,
473 net::OldCompletionCallback* callback) { 108 net::OldCompletionCallback* callback) OVERRIDE;
474 return net::ERR_NOT_IMPLEMENTED;
475 }
476
477 virtual int DoomEntriesSince(const base::Time initial_time, 109 virtual int DoomEntriesSince(const base::Time initial_time,
478 net::OldCompletionCallback* callback) { 110 net::OldCompletionCallback* callback) OVERRIDE;
479 return net::ERR_NOT_IMPLEMENTED;
480 }
481
482 virtual int OpenNextEntry(void** iter, disk_cache::Entry** next_entry, 111 virtual int OpenNextEntry(void** iter, disk_cache::Entry** next_entry,
483 net::OldCompletionCallback* callback) { 112 net::OldCompletionCallback* callback) OVERRIDE;
484 return net::ERR_NOT_IMPLEMENTED; 113 virtual void EndEnumeration(void** iter) OVERRIDE;
485 }
486
487 virtual void EndEnumeration(void** iter) {}
488
489 virtual void GetStats( 114 virtual void GetStats(
490 std::vector<std::pair<std::string, std::string> >* stats) { 115 std::vector<std::pair<std::string, std::string> >* stats) OVERRIDE;
gavinp 2011/11/18 14:26:22 Nit: #include <utility> #include <vector>
rvargas (doing something else) 2011/11/18 19:24:58 I know that's what lint wants, but historically we
gavinp 2011/11/22 18:33:48 I don't think that's a good rule in 2011; compiler
rvargas (doing something else) 2011/11/22 18:58:10 Looking at this particular case (without delving i
gavinp 2011/11/22 19:59:29 I remember that thread well. But IWYU was specifi
gavinp 2011/11/22 20:18:30 Annnd... I appear to have missed the point. I've
491 } 116 virtual void OnExternalCacheHit(const std::string& key) OVERRIDE;
492
493 virtual void OnExternalCacheHit(const std::string& key) {}
494 117
495 // returns number of times a cache entry was successfully opened 118 // returns number of times a cache entry was successfully opened
496 int open_count() const { return open_count_; } 119 int open_count() const { return open_count_; }
497 120
498 // returns number of times a cache entry was successfully created 121 // returns number of times a cache entry was successfully created
499 int create_count() const { return create_count_; } 122 int create_count() const { return create_count_; }
500 123
501 // Fail any subsequent CreateEntry and OpenEntry. 124 // Fail any subsequent CreateEntry and OpenEntry.
502 void set_fail_requests() { fail_requests_ = true; } 125 void set_fail_requests() { fail_requests_ = true; }
503 126
504 // Return entries that fail some of their requests. 127 // Return entries that fail some of their requests.
505 void set_soft_failures(bool value) { soft_failures_ = value; } 128 void set_soft_failures(bool value) { soft_failures_ = value; }
506 129
507 void ReleaseAll() { 130 void ReleaseAll();
508 EntryMap::iterator it = entries_.begin();
509 for (; it != entries_.end(); ++it)
510 it->second->Release();
511 entries_.clear();
512 }
513 131
514 private: 132 private:
515 typedef base::hash_map<std::string, MockDiskEntry*> EntryMap; 133 typedef base::hash_map<std::string, MockDiskEntry*> EntryMap;
134 class CallbackRunner;
516 135
517 class CallbackRunner : public Task { 136 void CallbackLater(net::OldCompletionCallback* callback, int result);
518 public:
519 CallbackRunner(net::OldCompletionCallback* callback, int result)
520 : callback_(callback), result_(result) {}
521 virtual void Run() {
522 callback_->Run(result_);
523 }
524
525 private:
526 net::OldCompletionCallback* callback_;
527 int result_;
528 DISALLOW_COPY_AND_ASSIGN(CallbackRunner);
529 };
530
531 void CallbackLater(net::OldCompletionCallback* callback, int result) {
532 MessageLoop::current()->PostTask(FROM_HERE,
533 new CallbackRunner(callback, result));
534 }
535 137
536 EntryMap entries_; 138 EntryMap entries_;
537 int open_count_; 139 int open_count_;
538 int create_count_; 140 int create_count_;
539 bool fail_requests_; 141 bool fail_requests_;
540 bool soft_failures_; 142 bool soft_failures_;
541 }; 143 };
542 144
543 class MockBackendFactory : public net::HttpCache::BackendFactory { 145 class MockBackendFactory : public net::HttpCache::BackendFactory {
544 public: 146 public:
545 virtual int CreateBackend(net::NetLog* /* net_log */, 147 virtual int CreateBackend(net::NetLog* net_log,
546 disk_cache::Backend** backend, 148 disk_cache::Backend** backend,
547 net::OldCompletionCallback* callback) { 149 net::OldCompletionCallback* callback) OVERRIDE;
548 *backend = new MockDiskCache();
549 return net::OK;
550 }
551 }; 150 };
552 151
553 class MockHttpCache { 152 class MockHttpCache {
554 public: 153 public:
555 MockHttpCache() 154 MockHttpCache();
556 : http_cache_(new MockNetworkLayer(), NULL, new MockBackendFactory()) { 155 explicit MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory);
557 }
558
559 explicit MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory)
560 : http_cache_(new MockNetworkLayer(), NULL, disk_cache_factory) {
561 }
562 156
563 net::HttpCache* http_cache() { return &http_cache_; } 157 net::HttpCache* http_cache() { return &http_cache_; }
564 158
565 MockNetworkLayer* network_layer() { 159 MockNetworkLayer* network_layer() {
566 return static_cast<MockNetworkLayer*>(http_cache_.network_layer()); 160 return static_cast<MockNetworkLayer*>(http_cache_.network_layer());
567 } 161 }
568 MockDiskCache* disk_cache() { 162 MockDiskCache* disk_cache();
569 TestOldCompletionCallback cb;
570 disk_cache::Backend* backend;
571 int rv = http_cache_.GetBackend(&backend, &cb);
572 rv = cb.GetResult(rv);
573 return (rv == net::OK) ? static_cast<MockDiskCache*>(backend) : NULL;
574 }
575 163
576 // Helper function for reading response info from the disk cache. 164 // Helper function for reading response info from the disk cache.
577 static bool ReadResponseInfo(disk_cache::Entry* disk_entry, 165 static bool ReadResponseInfo(disk_cache::Entry* disk_entry,
578 net::HttpResponseInfo* response_info, 166 net::HttpResponseInfo* response_info,
579 bool* response_truncated) { 167 bool* response_truncated);
580 int size = disk_entry->GetDataSize(0);
581
582 TestOldCompletionCallback cb;
583 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size));
584 int rv = disk_entry->ReadData(0, 0, buffer, size, &cb);
585 rv = cb.GetResult(rv);
586 EXPECT_EQ(size, rv);
587
588 return net::HttpCache::ParseResponseInfo(buffer->data(), size,
589 response_info,
590 response_truncated);
591 }
592 168
593 // Helper function for writing response info into the disk cache. 169 // Helper function for writing response info into the disk cache.
594 static bool WriteResponseInfo(disk_cache::Entry* disk_entry, 170 static bool WriteResponseInfo(disk_cache::Entry* disk_entry,
595 const net::HttpResponseInfo* response_info, 171 const net::HttpResponseInfo* response_info,
596 bool skip_transient_headers, 172 bool skip_transient_headers,
597 bool response_truncated) { 173 bool response_truncated);
598 Pickle pickle;
599 response_info->Persist(
600 &pickle, skip_transient_headers, response_truncated);
601
602 TestOldCompletionCallback cb;
603 scoped_refptr<net::WrappedIOBuffer> data(new net::WrappedIOBuffer(
604 reinterpret_cast<const char*>(pickle.data())));
605 int len = static_cast<int>(pickle.size());
606
607 int rv = disk_entry->WriteData(0, 0, data, len, &cb, true);
608 rv = cb.GetResult(rv);
609 return (rv == len);
610 }
611 174
612 // Helper function to synchronously open a backend entry. 175 // Helper function to synchronously open a backend entry.
613 bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry) { 176 bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry);
614 TestOldCompletionCallback cb;
615 int rv = disk_cache()->OpenEntry(key, entry, &cb);
616 return (cb.GetResult(rv) == net::OK);
617 }
618 177
619 // Helper function to synchronously create a backend entry. 178 // Helper function to synchronously create a backend entry.
620 bool CreateBackendEntry(const std::string& key, disk_cache::Entry** entry, 179 bool CreateBackendEntry(const std::string& key, disk_cache::Entry** entry,
621 net::NetLog* /* net_log */) { 180 net::NetLog* net_log);
622 TestOldCompletionCallback cb; 181
623 int rv = disk_cache()->CreateEntry(key, entry, &cb); 182 // Returns the test mode after considering the global override.
624 return (cb.GetResult(rv) == net::OK); 183 static int GetTestMode(int test_mode);
625 } 184
185 // Overrides the test mode for a given operation. Remember to reset it after
186 // the test! (by setting test_mode to zero).
187 static void SetTestMode(int test_mode);
626 188
627 private: 189 private:
628 net::HttpCache http_cache_; 190 net::HttpCache http_cache_;
629 }; 191 };
630 192
631 // This version of the disk cache doesn't invoke CreateEntry callbacks. 193 // This version of the disk cache doesn't invoke CreateEntry callbacks.
632 class MockDiskCacheNoCB : public MockDiskCache { 194 class MockDiskCacheNoCB : public MockDiskCache {
633 virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry, 195 virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry,
634 net::OldCompletionCallback* callback) { 196 net::OldCompletionCallback* callback) OVERRIDE;
635 return net::ERR_IO_PENDING;
636 }
637 }; 197 };
638 198
639 class MockBackendNoCbFactory : public net::HttpCache::BackendFactory { 199 class MockBackendNoCbFactory : public net::HttpCache::BackendFactory {
640 public: 200 public:
641 virtual int CreateBackend(net::NetLog* /* net_log */, 201 virtual int CreateBackend(net::NetLog* net_log,
642 disk_cache::Backend** backend, 202 disk_cache::Backend** backend,
643 net::OldCompletionCallback* callback) { 203 net::OldCompletionCallback* callback) OVERRIDE;
644 *backend = new MockDiskCacheNoCB();
645 return net::OK;
646 }
647 }; 204 };
648 205
649 // This backend factory allows us to control the backend instantiation. 206 // This backend factory allows us to control the backend instantiation.
650 class MockBlockingBackendFactory : public net::HttpCache::BackendFactory { 207 class MockBlockingBackendFactory : public net::HttpCache::BackendFactory {
651 public: 208 public:
652 MockBlockingBackendFactory() 209 MockBlockingBackendFactory();
653 : backend_(NULL), callback_(NULL), block_(true), fail_(false) {}
654 210
655 virtual int CreateBackend(net::NetLog* /* net_log */, 211 virtual int CreateBackend(net::NetLog* net_log,
656 disk_cache::Backend** backend, 212 disk_cache::Backend** backend,
657 net::OldCompletionCallback* callback) { 213 net::OldCompletionCallback* callback) OVERRIDE;
658 if (!block_) {
659 if (!fail_)
660 *backend = new MockDiskCache();
661 return Result();
662 }
663
664 backend_ = backend;
665 callback_ = callback;
666 return net::ERR_IO_PENDING;
667 }
668 214
669 // Completes the backend creation. Any blocked call will be notified via the 215 // Completes the backend creation. Any blocked call will be notified via the
670 // provided callback. 216 // provided callback.
671 void FinishCreation() { 217 void FinishCreation();
672 block_ = false;
673 if (callback_) {
674 if (!fail_)
675 *backend_ = new MockDiskCache();
676 net::OldCompletionCallback* cb = callback_;
677 callback_ = NULL;
678 cb->Run(Result()); // This object can be deleted here.
679 }
680 }
681 218
682 disk_cache::Backend** backend() { return backend_; } 219 disk_cache::Backend** backend() { return backend_; }
683 void set_fail(bool fail) { fail_ = fail; } 220 void set_fail(bool fail) { fail_ = fail; }
684 221
685 net::OldCompletionCallback* callback() { return callback_; } 222 net::OldCompletionCallback* callback() { return callback_; }
686 223
687 private: 224 private:
688 int Result() { return fail_ ? net::ERR_FAILED : net::OK; } 225 int Result() { return fail_ ? net::ERR_FAILED : net::OK; }
689 226
690 disk_cache::Backend** backend_; 227 disk_cache::Backend** backend_;
691 net::OldCompletionCallback* callback_; 228 net::OldCompletionCallback* callback_;
692 bool block_; 229 bool block_;
693 bool fail_; 230 bool fail_;
694 }; 231 };
695 232
696 class DeleteCacheOldCompletionCallback : public TestOldCompletionCallback { 233 #endif // NET_HTTP_MOCK_HTTP_CACHE_H_
697 public:
698 explicit DeleteCacheOldCompletionCallback(MockHttpCache* cache)
699 : cache_(cache) {}
700
701 virtual void RunWithParams(const Tuple1<int>& params) {
702 delete cache_;
703 TestOldCompletionCallback::RunWithParams(params);
704 }
705
706 private:
707 MockHttpCache* cache_;
708 };
709
710 //-----------------------------------------------------------------------------
711 // helpers
712
713 void ReadAndVerifyTransaction(net::HttpTransaction* trans,
714 const MockTransaction& trans_info) {
715 std::string content;
716 int rv = ReadTransaction(trans, &content);
717
718 EXPECT_EQ(net::OK, rv);
719 std::string expected(trans_info.data);
720 EXPECT_EQ(expected, content);
721 }
722
723 void RunTransactionTestWithRequestAndLog(net::HttpCache* cache,
724 const MockTransaction& trans_info,
725 const MockHttpRequest& request,
726 net::HttpResponseInfo* response_info,
727 const net::BoundNetLog& net_log) {
728 TestOldCompletionCallback callback;
729
730 // write to the cache
731
732 scoped_ptr<net::HttpTransaction> trans;
733 int rv = cache->CreateTransaction(&trans);
734 EXPECT_EQ(net::OK, rv);
735 ASSERT_TRUE(trans.get());
736
737 rv = trans->Start(&request, &callback, net_log);
738 if (rv == net::ERR_IO_PENDING)
739 rv = callback.WaitForResult();
740 ASSERT_EQ(net::OK, rv);
741
742 const net::HttpResponseInfo* response = trans->GetResponseInfo();
743 ASSERT_TRUE(response);
744
745 if (response_info)
746 *response_info = *response;
747
748 ReadAndVerifyTransaction(trans.get(), trans_info);
749 }
750
751 void RunTransactionTestWithRequest(net::HttpCache* cache,
752 const MockTransaction& trans_info,
753 const MockHttpRequest& request,
754 net::HttpResponseInfo* response_info) {
755 RunTransactionTestWithRequestAndLog(cache, trans_info, request,
756 response_info, net::BoundNetLog());
757 }
758
759 void RunTransactionTestWithLog(net::HttpCache* cache,
760 const MockTransaction& trans_info,
761 const net::BoundNetLog& log) {
762 RunTransactionTestWithRequestAndLog(
763 cache, trans_info, MockHttpRequest(trans_info), NULL, log);
764 }
765
766 void RunTransactionTest(net::HttpCache* cache,
767 const MockTransaction& trans_info) {
768 RunTransactionTestWithLog(cache, trans_info, net::BoundNetLog());
769 }
770
771 void RunTransactionTestWithResponseInfo(net::HttpCache* cache,
772 const MockTransaction& trans_info,
773 net::HttpResponseInfo* response) {
774 RunTransactionTestWithRequest(
775 cache, trans_info, MockHttpRequest(trans_info), response);
776 }
777
778 void RunTransactionTestWithResponse(net::HttpCache* cache,
779 const MockTransaction& trans_info,
780 std::string* response_headers) {
781 net::HttpResponseInfo response;
782 RunTransactionTestWithResponseInfo(cache, trans_info, &response);
783 response.headers->GetNormalizedHeaders(response_headers);
784 }
785
786 // This class provides a handler for kFastNoStoreGET_Transaction so that the
787 // no-store header can be included on demand.
788 class FastTransactionServer {
789 public:
790 FastTransactionServer() {
791 no_store = false;
792 }
793 ~FastTransactionServer() {}
794
795 void set_no_store(bool value) { no_store = value; }
796
797 static void FastNoStoreHandler(const net::HttpRequestInfo* request,
798 std::string* response_status,
799 std::string* response_headers,
800 std::string* response_data) {
801 if (no_store)
802 *response_headers = "Cache-Control: no-store\n";
803 }
804
805 private:
806 static bool no_store;
807 DISALLOW_COPY_AND_ASSIGN(FastTransactionServer);
808 };
809 bool FastTransactionServer::no_store;
810
811 const MockTransaction kFastNoStoreGET_Transaction = {
812 "http://www.google.com/nostore",
813 "GET",
814 base::Time(),
815 "",
816 net::LOAD_VALIDATE_CACHE,
817 "HTTP/1.1 200 OK",
818 "Cache-Control: max-age=10000\n",
819 base::Time(),
820 "<html><body>Google Blah Blah</body></html>",
821 TEST_MODE_SYNC_NET_START,
822 &FastTransactionServer::FastNoStoreHandler,
823 0
824 };
825
826 // This class provides a handler for kRangeGET_TransactionOK so that the range
827 // request can be served on demand.
828 class RangeTransactionServer {
829 public:
830 RangeTransactionServer() {
831 not_modified_ = false;
832 modified_ = false;
833 bad_200_ = false;
834 }
835 ~RangeTransactionServer() {
836 not_modified_ = false;
837 modified_ = false;
838 bad_200_ = false;
839 }
840
841 // Returns only 416 or 304 when set.
842 void set_not_modified(bool value) { not_modified_ = value; }
843
844 // Returns 206 when revalidating a range (instead of 304).
845 void set_modified(bool value) { modified_ = value; }
846
847 // Returns 200 instead of 206 (a malformed response overall).
848 void set_bad_200(bool value) { bad_200_ = value; }
849
850 static void RangeHandler(const net::HttpRequestInfo* request,
851 std::string* response_status,
852 std::string* response_headers,
853 std::string* response_data);
854
855 private:
856 static bool not_modified_;
857 static bool modified_;
858 static bool bad_200_;
859 DISALLOW_COPY_AND_ASSIGN(RangeTransactionServer);
860 };
861 bool RangeTransactionServer::not_modified_ = false;
862 bool RangeTransactionServer::modified_ = false;
863 bool RangeTransactionServer::bad_200_ = false;
864
865 // A dummy extra header that must be preserved on a given request.
866 #define EXTRA_HEADER "Extra: header"
867 static const char kExtraHeaderKey[] = "Extra";
868
869 // Static.
870 void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request,
871 std::string* response_status,
872 std::string* response_headers,
873 std::string* response_data) {
874 if (request->extra_headers.IsEmpty()) {
875 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
876 response_data->clear();
877 return;
878 }
879
880 // We want to make sure we don't delete extra headers.
881 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
882
883 if (not_modified_) {
884 response_status->assign("HTTP/1.1 304 Not Modified");
885 response_data->clear();
886 return;
887 }
888
889 std::vector<net::HttpByteRange> ranges;
890 std::string range_header;
891 if (!request->extra_headers.GetHeader(
892 net::HttpRequestHeaders::kRange, &range_header) ||
893 !net::HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ ||
894 ranges.size() != 1) {
895 // This is not a byte range request. We return 200.
896 response_status->assign("HTTP/1.1 200 OK");
897 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT");
898 response_data->assign("Not a range");
899 return;
900 }
901
902 // We can handle this range request.
903 net::HttpByteRange byte_range = ranges[0];
904 if (byte_range.first_byte_position() > 79) {
905 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
906 response_data->clear();
907 return;
908 }
909
910 EXPECT_TRUE(byte_range.ComputeBounds(80));
911 int start = static_cast<int>(byte_range.first_byte_position());
912 int end = static_cast<int>(byte_range.last_byte_position());
913
914 EXPECT_LT(end, 80);
915
916 std::string content_range = base::StringPrintf(
917 "Content-Range: bytes %d-%d/80\n", start, end);
918 response_headers->append(content_range);
919
920 if (!request->extra_headers.HasHeader("If-None-Match") || modified_) {
921 std::string data;
922 if (end == start) {
923 EXPECT_EQ(0, end % 10);
924 data = "r";
925 } else {
926 EXPECT_EQ(9, (end - start) % 10);
927 for (int block_start = start; block_start < end; block_start += 10) {
928 base::StringAppendF(&data, "rg: %02d-%02d ",
929 block_start, block_start + 9);
930 }
931 }
932 *response_data = data;
933
934 if (end - start != 9) {
935 // We also have to fix content-length.
936 int len = end - start + 1;
937 std::string content_length = base::StringPrintf("Content-Length: %d\n",
938 len);
939 response_headers->replace(response_headers->find("Content-Length:"),
940 content_length.size(), content_length);
941 }
942 } else {
943 response_status->assign("HTTP/1.1 304 Not Modified");
944 response_data->clear();
945 }
946 }
947
948 const MockTransaction kRangeGET_TransactionOK = {
949 "http://www.google.com/range",
950 "GET",
951 base::Time(),
952 "Range: bytes = 40-49\r\n"
953 EXTRA_HEADER,
954 net::LOAD_NORMAL,
955 "HTTP/1.1 206 Partial Content",
956 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
957 "ETag: \"foo\"\n"
958 "Accept-Ranges: bytes\n"
959 "Content-Length: 10\n",
960 base::Time(),
961 "rg: 40-49 ",
962 TEST_MODE_NORMAL,
963 &RangeTransactionServer::RangeHandler,
964 0
965 };
966
967 // Verifies the response headers (|response|) match a partial content
968 // response for the range starting at |start| and ending at |end|.
969 void Verify206Response(std::string response, int start, int end) {
970 std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
971 response.size()));
972 scoped_refptr<net::HttpResponseHeaders> headers(
973 new net::HttpResponseHeaders(raw_headers));
974
975 ASSERT_EQ(206, headers->response_code());
976
977 int64 range_start, range_end, object_size;
978 ASSERT_TRUE(
979 headers->GetContentRange(&range_start, &range_end, &object_size));
980 int64 content_length = headers->GetContentLength();
981
982 int length = end - start + 1;
983 ASSERT_EQ(length, content_length);
984 ASSERT_EQ(start, range_start);
985 ASSERT_EQ(end, range_end);
986 }
987
988 // Creates a truncated entry that can be resumed using byte ranges.
989 void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) {
990 // Create a disk cache entry that stores an incomplete resource.
991 disk_cache::Entry* entry;
992 ASSERT_TRUE(cache->CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
993 NULL));
994
995 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
996 raw_headers.size());
997
998 net::HttpResponseInfo response;
999 response.response_time = base::Time::Now();
1000 response.request_time = base::Time::Now();
1001 response.headers = new net::HttpResponseHeaders(raw_headers);
1002 // Set the last argument for this to be an incomplete request.
1003 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
1004
1005 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
1006 int len = static_cast<int>(base::strlcpy(buf->data(),
1007 "rg: 00-09 rg: 10-19 ", 100));
1008 TestOldCompletionCallback cb;
1009 int rv = entry->WriteData(1, 0, buf, len, &cb, true);
1010 EXPECT_EQ(len, cb.GetResult(rv));
1011 entry->Close();
1012 }
1013
1014 // Helper to represent a network HTTP response.
1015 struct Response {
1016 // Set this response into |trans|.
1017 void AssignTo(MockTransaction* trans) const {
1018 trans->status = status;
1019 trans->response_headers = headers;
1020 trans->data = body;
1021 }
1022
1023 std::string status_and_headers() const {
1024 return std::string(status) + "\n" + std::string(headers);
1025 }
1026
1027 const char* status;
1028 const char* headers;
1029 const char* body;
1030 };
1031
1032 struct Context {
1033 Context() : result(net::ERR_IO_PENDING) {}
1034
1035 int result;
1036 TestOldCompletionCallback callback;
1037 scoped_ptr<net::HttpTransaction> trans;
1038 };
1039
1040 } // namespace
1041
1042
1043 //-----------------------------------------------------------------------------
1044 // HttpCache tests
1045
1046 TEST(HttpCache, CreateThenDestroy) {
1047 MockHttpCache cache;
1048
1049 scoped_ptr<net::HttpTransaction> trans;
1050 int rv = cache.http_cache()->CreateTransaction(&trans);
1051 EXPECT_EQ(net::OK, rv);
1052 ASSERT_TRUE(trans.get());
1053 }
1054
1055 TEST(HttpCache, GetBackend) {
1056 MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(0));
1057
1058 disk_cache::Backend* backend;
1059 TestOldCompletionCallback cb;
1060 // This will lazily initialize the backend.
1061 int rv = cache.http_cache()->GetBackend(&backend, &cb);
1062 EXPECT_EQ(net::OK, cb.GetResult(rv));
1063 }
1064
1065 TEST(HttpCache, SimpleGET) {
1066 MockHttpCache cache;
1067
1068 // write to the cache
1069 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1070
1071 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1072 EXPECT_EQ(0, cache.disk_cache()->open_count());
1073 EXPECT_EQ(1, cache.disk_cache()->create_count());
1074 }
1075
1076 TEST(HttpCache, SimpleGETNoDiskCache) {
1077 MockHttpCache cache;
1078
1079 cache.disk_cache()->set_fail_requests();
1080
1081 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
1082 log.SetLogLevel(net::NetLog::LOG_BASIC);
1083
1084 // Read from the network, and don't use the cache.
1085 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction,
1086 log.bound());
1087
1088 // Check that the NetLog was filled as expected.
1089 // (We attempted to both Open and Create entries, but both failed).
1090 net::CapturingNetLog::EntryList entries;
1091 log.GetEntries(&entries);
1092
1093 EXPECT_EQ(6u, entries.size());
1094 EXPECT_TRUE(net::LogContainsBeginEvent(
1095 entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1096 EXPECT_TRUE(net::LogContainsEndEvent(
1097 entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1098 EXPECT_TRUE(net::LogContainsBeginEvent(
1099 entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
1100 EXPECT_TRUE(net::LogContainsEndEvent(
1101 entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
1102 EXPECT_TRUE(net::LogContainsBeginEvent(
1103 entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1104 EXPECT_TRUE(net::LogContainsEndEvent(
1105 entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1106
1107 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1108 EXPECT_EQ(0, cache.disk_cache()->open_count());
1109 EXPECT_EQ(0, cache.disk_cache()->create_count());
1110 }
1111
1112 TEST(HttpCache, SimpleGETNoDiskCache2) {
1113 // This will initialize a cache object with NULL backend.
1114 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1115 factory->set_fail(true);
1116 factory->FinishCreation(); // We'll complete synchronously.
1117 MockHttpCache cache(factory);
1118
1119 // Read from the network, and don't use the cache.
1120 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1121
1122 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1123 EXPECT_FALSE(cache.http_cache()->GetCurrentBackend());
1124 }
1125
1126 TEST(HttpCache, SimpleGETWithDiskFailures) {
1127 MockHttpCache cache;
1128
1129 cache.disk_cache()->set_soft_failures(true);
1130
1131 // Read from the network, and fail to write to the cache.
1132 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1133
1134 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1135 EXPECT_EQ(0, cache.disk_cache()->open_count());
1136 EXPECT_EQ(1, cache.disk_cache()->create_count());
1137
1138 // This one should see an empty cache again.
1139 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1140
1141 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1142 EXPECT_EQ(0, cache.disk_cache()->open_count());
1143 EXPECT_EQ(2, cache.disk_cache()->create_count());
1144 }
1145
1146 // Tests that disk failures after the transaction has started don't cause the
1147 // request to fail.
1148 TEST(HttpCache, SimpleGETWithDiskFailures2) {
1149 MockHttpCache cache;
1150
1151 MockHttpRequest request(kSimpleGET_Transaction);
1152
1153 scoped_ptr<Context> c(new Context());
1154 int rv = cache.http_cache()->CreateTransaction(&c->trans);
1155 EXPECT_EQ(net::OK, rv);
1156
1157 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1158 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1159 rv = c->callback.WaitForResult();
1160
1161 // Start failing request now.
1162 cache.disk_cache()->set_soft_failures(true);
1163
1164 // We have to open the entry again to propagate the failure flag.
1165 disk_cache::Entry* en;
1166 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &en));
1167 en->Close();
1168
1169 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1170 c.reset();
1171
1172 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1173 EXPECT_EQ(1, cache.disk_cache()->open_count());
1174 EXPECT_EQ(1, cache.disk_cache()->create_count());
1175
1176 // This one should see an empty cache again.
1177 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1178
1179 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1180 EXPECT_EQ(1, cache.disk_cache()->open_count());
1181 EXPECT_EQ(2, cache.disk_cache()->create_count());
1182 }
1183
1184 // Tests that we don't crash after failures to read from the cache.
1185 TEST(HttpCache, SimpleGETWithDiskFailures3) {
1186 MockHttpCache cache;
1187
1188 // Read from the network, and write to the cache.
1189 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1190
1191 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1192 EXPECT_EQ(0, cache.disk_cache()->open_count());
1193 EXPECT_EQ(1, cache.disk_cache()->create_count());
1194
1195 cache.disk_cache()->set_soft_failures(true);
1196
1197 // Now fail to read from the cache.
1198 scoped_ptr<Context> c(new Context());
1199 int rv = cache.http_cache()->CreateTransaction(&c->trans);
1200 EXPECT_EQ(net::OK, rv);
1201
1202 MockHttpRequest request(kSimpleGET_Transaction);
1203 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1204 EXPECT_EQ(net::ERR_CACHE_READ_FAILURE, c->callback.GetResult(rv));
1205 }
1206
1207 TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
1208 MockHttpCache cache;
1209
1210 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
1211
1212 // This prevents a number of write events from being logged.
1213 log.SetLogLevel(net::NetLog::LOG_BASIC);
1214
1215 // write to the cache
1216 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction,
1217 log.bound());
1218
1219 // Check that the NetLog was filled as expected.
1220 net::CapturingNetLog::EntryList entries;
1221 log.GetEntries(&entries);
1222
1223 EXPECT_EQ(8u, entries.size());
1224 EXPECT_TRUE(net::LogContainsBeginEvent(
1225 entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1226 EXPECT_TRUE(net::LogContainsEndEvent(
1227 entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1228 EXPECT_TRUE(net::LogContainsBeginEvent(
1229 entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
1230 EXPECT_TRUE(net::LogContainsEndEvent(
1231 entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
1232 EXPECT_TRUE(net::LogContainsBeginEvent(
1233 entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1234 EXPECT_TRUE(net::LogContainsEndEvent(
1235 entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1236 EXPECT_TRUE(net::LogContainsBeginEvent(
1237 entries, 6, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1238 EXPECT_TRUE(net::LogContainsEndEvent(
1239 entries, 7, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1240
1241 // force this transaction to read from the cache
1242 MockTransaction transaction(kSimpleGET_Transaction);
1243 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
1244
1245 log.Clear();
1246
1247 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
1248
1249 // Check that the NetLog was filled as expected.
1250 log.GetEntries(&entries);
1251
1252 EXPECT_EQ(8u, entries.size());
1253 EXPECT_TRUE(net::LogContainsBeginEvent(
1254 entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1255 EXPECT_TRUE(net::LogContainsEndEvent(
1256 entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1257 EXPECT_TRUE(net::LogContainsBeginEvent(
1258 entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
1259 EXPECT_TRUE(net::LogContainsEndEvent(
1260 entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
1261 EXPECT_TRUE(net::LogContainsBeginEvent(
1262 entries, 4, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1263 EXPECT_TRUE(net::LogContainsEndEvent(
1264 entries, 5, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1265 EXPECT_TRUE(net::LogContainsBeginEvent(
1266 entries, 6, net::NetLog::TYPE_HTTP_CACHE_READ_INFO));
1267 EXPECT_TRUE(net::LogContainsEndEvent(
1268 entries, 7, net::NetLog::TYPE_HTTP_CACHE_READ_INFO));
1269
1270 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1271 EXPECT_EQ(1, cache.disk_cache()->open_count());
1272 EXPECT_EQ(1, cache.disk_cache()->create_count());
1273 }
1274
1275 TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Miss) {
1276 MockHttpCache cache;
1277
1278 // force this transaction to read from the cache
1279 MockTransaction transaction(kSimpleGET_Transaction);
1280 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
1281
1282 MockHttpRequest request(transaction);
1283 TestOldCompletionCallback callback;
1284
1285 scoped_ptr<net::HttpTransaction> trans;
1286 int rv = cache.http_cache()->CreateTransaction(&trans);
1287 EXPECT_EQ(net::OK, rv);
1288 ASSERT_TRUE(trans.get());
1289
1290 rv = trans->Start(&request, &callback, net::BoundNetLog());
1291 if (rv == net::ERR_IO_PENDING)
1292 rv = callback.WaitForResult();
1293 ASSERT_EQ(net::ERR_CACHE_MISS, rv);
1294
1295 trans.reset();
1296
1297 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1298 EXPECT_EQ(0, cache.disk_cache()->open_count());
1299 EXPECT_EQ(0, cache.disk_cache()->create_count());
1300 }
1301
1302 TEST(HttpCache, SimpleGET_LoadPreferringCache_Hit) {
1303 MockHttpCache cache;
1304
1305 // write to the cache
1306 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1307
1308 // force this transaction to read from the cache if valid
1309 MockTransaction transaction(kSimpleGET_Transaction);
1310 transaction.load_flags |= net::LOAD_PREFERRING_CACHE;
1311
1312 RunTransactionTest(cache.http_cache(), transaction);
1313
1314 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1315 EXPECT_EQ(1, cache.disk_cache()->open_count());
1316 EXPECT_EQ(1, cache.disk_cache()->create_count());
1317 }
1318
1319 TEST(HttpCache, SimpleGET_LoadPreferringCache_Miss) {
1320 MockHttpCache cache;
1321
1322 // force this transaction to read from the cache if valid
1323 MockTransaction transaction(kSimpleGET_Transaction);
1324 transaction.load_flags |= net::LOAD_PREFERRING_CACHE;
1325
1326 RunTransactionTest(cache.http_cache(), transaction);
1327
1328 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1329 EXPECT_EQ(0, cache.disk_cache()->open_count());
1330 EXPECT_EQ(1, cache.disk_cache()->create_count());
1331 }
1332
1333 TEST(HttpCache, SimpleGET_LoadBypassCache) {
1334 MockHttpCache cache;
1335
1336 // Write to the cache.
1337 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1338
1339 // Force this transaction to write to the cache again.
1340 MockTransaction transaction(kSimpleGET_Transaction);
1341 transaction.load_flags |= net::LOAD_BYPASS_CACHE;
1342
1343 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
1344
1345 // This prevents a number of write events from being logged.
1346 log.SetLogLevel(net::NetLog::LOG_BASIC);
1347
1348 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
1349
1350 // Check that the NetLog was filled as expected.
1351 net::CapturingNetLog::EntryList entries;
1352 log.GetEntries(&entries);
1353
1354 EXPECT_EQ(8u, entries.size());
1355 EXPECT_TRUE(net::LogContainsBeginEvent(
1356 entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1357 EXPECT_TRUE(net::LogContainsEndEvent(
1358 entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1359 EXPECT_TRUE(net::LogContainsBeginEvent(
1360 entries, 2, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
1361 EXPECT_TRUE(net::LogContainsEndEvent(
1362 entries, 3, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
1363 EXPECT_TRUE(net::LogContainsBeginEvent(
1364 entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1365 EXPECT_TRUE(net::LogContainsEndEvent(
1366 entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1367 EXPECT_TRUE(net::LogContainsBeginEvent(
1368 entries, 6, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1369 EXPECT_TRUE(net::LogContainsEndEvent(
1370 entries, 7, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1371
1372 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1373 EXPECT_EQ(0, cache.disk_cache()->open_count());
1374 EXPECT_EQ(2, cache.disk_cache()->create_count());
1375 }
1376
1377 TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit) {
1378 MockHttpCache cache;
1379
1380 // write to the cache
1381 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1382
1383 // force this transaction to write to the cache again
1384 MockTransaction transaction(kSimpleGET_Transaction);
1385 transaction.request_headers = "pragma: no-cache";
1386
1387 RunTransactionTest(cache.http_cache(), transaction);
1388
1389 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1390 EXPECT_EQ(0, cache.disk_cache()->open_count());
1391 EXPECT_EQ(2, cache.disk_cache()->create_count());
1392 }
1393
1394 TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit2) {
1395 MockHttpCache cache;
1396
1397 // write to the cache
1398 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1399
1400 // force this transaction to write to the cache again
1401 MockTransaction transaction(kSimpleGET_Transaction);
1402 transaction.request_headers = "cache-control: no-cache";
1403
1404 RunTransactionTest(cache.http_cache(), transaction);
1405
1406 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1407 EXPECT_EQ(0, cache.disk_cache()->open_count());
1408 EXPECT_EQ(2, cache.disk_cache()->create_count());
1409 }
1410
1411 TEST(HttpCache, SimpleGET_LoadValidateCache) {
1412 MockHttpCache cache;
1413
1414 // write to the cache
1415 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1416
1417 // read from the cache
1418 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1419
1420 // force this transaction to validate the cache
1421 MockTransaction transaction(kSimpleGET_Transaction);
1422 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
1423
1424 RunTransactionTest(cache.http_cache(), transaction);
1425
1426 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1427 EXPECT_EQ(1, cache.disk_cache()->open_count());
1428 EXPECT_EQ(1, cache.disk_cache()->create_count());
1429 }
1430
1431 TEST(HttpCache, SimpleGET_LoadValidateCache_Implicit) {
1432 MockHttpCache cache;
1433
1434 // write to the cache
1435 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1436
1437 // read from the cache
1438 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1439
1440 // force this transaction to validate the cache
1441 MockTransaction transaction(kSimpleGET_Transaction);
1442 transaction.request_headers = "cache-control: max-age=0";
1443
1444 RunTransactionTest(cache.http_cache(), transaction);
1445
1446 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1447 EXPECT_EQ(1, cache.disk_cache()->open_count());
1448 EXPECT_EQ(1, cache.disk_cache()->create_count());
1449 }
1450
1451 static void PreserveRequestHeaders_Handler(
1452 const net::HttpRequestInfo* request,
1453 std::string* response_status,
1454 std::string* response_headers,
1455 std::string* response_data) {
1456 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
1457 }
1458
1459 // Tests that we don't remove extra headers for simple requests.
1460 TEST(HttpCache, SimpleGET_PreserveRequestHeaders) {
1461 MockHttpCache cache;
1462
1463 MockTransaction transaction(kSimpleGET_Transaction);
1464 transaction.handler = PreserveRequestHeaders_Handler;
1465 transaction.request_headers = EXTRA_HEADER;
1466 transaction.response_headers = "Cache-Control: max-age=0\n";
1467 AddMockTransaction(&transaction);
1468
1469 // Write, then revalidate the entry.
1470 RunTransactionTest(cache.http_cache(), transaction);
1471 RunTransactionTest(cache.http_cache(), transaction);
1472
1473 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1474 EXPECT_EQ(1, cache.disk_cache()->open_count());
1475 EXPECT_EQ(1, cache.disk_cache()->create_count());
1476 RemoveMockTransaction(&transaction);
1477 }
1478
1479 // Tests that we don't remove extra headers for conditionalized requests.
1480 TEST(HttpCache, ConditionalizedGET_PreserveRequestHeaders) {
1481 MockHttpCache cache;
1482
1483 // Write to the cache.
1484 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
1485
1486 MockTransaction transaction(kETagGET_Transaction);
1487 transaction.handler = PreserveRequestHeaders_Handler;
1488 transaction.request_headers = "If-None-Match: \"foopy\"\r\n"
1489 EXTRA_HEADER;
1490 AddMockTransaction(&transaction);
1491
1492 RunTransactionTest(cache.http_cache(), transaction);
1493
1494 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1495 EXPECT_EQ(1, cache.disk_cache()->open_count());
1496 EXPECT_EQ(1, cache.disk_cache()->create_count());
1497 RemoveMockTransaction(&transaction);
1498 }
1499
1500 TEST(HttpCache, SimpleGET_ManyReaders) {
1501 MockHttpCache cache;
1502
1503 MockHttpRequest request(kSimpleGET_Transaction);
1504
1505 std::vector<Context*> context_list;
1506 const int kNumTransactions = 5;
1507
1508 for (int i = 0; i < kNumTransactions; ++i) {
1509 context_list.push_back(new Context());
1510 Context* c = context_list[i];
1511
1512 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1513 EXPECT_EQ(net::OK, c->result);
1514 EXPECT_EQ(net::LOAD_STATE_IDLE, c->trans->GetLoadState());
1515
1516 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1517 }
1518
1519 // All requests are waiting for the active entry.
1520 for (int i = 0; i < kNumTransactions; ++i) {
1521 Context* c = context_list[i];
1522 EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
1523 }
1524
1525 // Allow all requests to move from the Create queue to the active entry.
1526 MessageLoop::current()->RunAllPending();
1527
1528 // The first request should be a writer at this point, and the subsequent
1529 // requests should be pending.
1530
1531 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1532 EXPECT_EQ(0, cache.disk_cache()->open_count());
1533 EXPECT_EQ(1, cache.disk_cache()->create_count());
1534
1535 // All requests depend on the writer, and the writer is between Start and
1536 // Read, i.e. idle.
1537 for (int i = 0; i < kNumTransactions; ++i) {
1538 Context* c = context_list[i];
1539 EXPECT_EQ(net::LOAD_STATE_IDLE, c->trans->GetLoadState());
1540 }
1541
1542 for (int i = 0; i < kNumTransactions; ++i) {
1543 Context* c = context_list[i];
1544 if (c->result == net::ERR_IO_PENDING)
1545 c->result = c->callback.WaitForResult();
1546 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1547 }
1548
1549 // We should not have had to re-open the disk entry
1550
1551 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1552 EXPECT_EQ(0, cache.disk_cache()->open_count());
1553 EXPECT_EQ(1, cache.disk_cache()->create_count());
1554
1555 for (int i = 0; i < kNumTransactions; ++i) {
1556 Context* c = context_list[i];
1557 delete c;
1558 }
1559 }
1560
1561 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4769.
1562 // If cancelling a request is racing with another request for the same resource
1563 // finishing, we have to make sure that we remove both transactions from the
1564 // entry.
1565 TEST(HttpCache, SimpleGET_RacingReaders) {
1566 MockHttpCache cache;
1567
1568 MockHttpRequest request(kSimpleGET_Transaction);
1569 MockHttpRequest reader_request(kSimpleGET_Transaction);
1570 reader_request.load_flags = net::LOAD_ONLY_FROM_CACHE;
1571
1572 std::vector<Context*> context_list;
1573 const int kNumTransactions = 5;
1574
1575 for (int i = 0; i < kNumTransactions; ++i) {
1576 context_list.push_back(new Context());
1577 Context* c = context_list[i];
1578
1579 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1580 EXPECT_EQ(net::OK, c->result);
1581
1582 MockHttpRequest* this_request = &request;
1583 if (i == 1 || i == 2)
1584 this_request = &reader_request;
1585
1586 c->result = c->trans->Start(this_request, &c->callback, net::BoundNetLog());
1587 }
1588
1589 // Allow all requests to move from the Create queue to the active entry.
1590 MessageLoop::current()->RunAllPending();
1591
1592 // The first request should be a writer at this point, and the subsequent
1593 // requests should be pending.
1594
1595 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1596 EXPECT_EQ(0, cache.disk_cache()->open_count());
1597 EXPECT_EQ(1, cache.disk_cache()->create_count());
1598
1599 Context* c = context_list[0];
1600 ASSERT_EQ(net::ERR_IO_PENDING, c->result);
1601 c->result = c->callback.WaitForResult();
1602 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1603
1604 // Now we have 2 active readers and two queued transactions.
1605
1606 EXPECT_EQ(net::LOAD_STATE_IDLE,
1607 context_list[2]->trans->GetLoadState());
1608 EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_CACHE,
1609 context_list[3]->trans->GetLoadState());
1610
1611 c = context_list[1];
1612 ASSERT_EQ(net::ERR_IO_PENDING, c->result);
1613 c->result = c->callback.WaitForResult();
1614 if (c->result == net::OK)
1615 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1616
1617 // At this point we have one reader, two pending transactions and a task on
1618 // the queue to move to the next transaction. Now we cancel the request that
1619 // is the current reader, and expect the queued task to be able to start the
1620 // next request.
1621
1622 c = context_list[2];
1623 c->trans.reset();
1624
1625 for (int i = 3; i < kNumTransactions; ++i) {
1626 Context* c = context_list[i];
1627 if (c->result == net::ERR_IO_PENDING)
1628 c->result = c->callback.WaitForResult();
1629 if (c->result == net::OK)
1630 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1631 }
1632
1633 // We should not have had to re-open the disk entry.
1634
1635 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1636 EXPECT_EQ(0, cache.disk_cache()->open_count());
1637 EXPECT_EQ(1, cache.disk_cache()->create_count());
1638
1639 for (int i = 0; i < kNumTransactions; ++i) {
1640 Context* c = context_list[i];
1641 delete c;
1642 }
1643 }
1644
1645 // Tests that we can doom an entry with pending transactions and delete one of
1646 // the pending transactions before the first one completes.
1647 // See http://code.google.com/p/chromium/issues/detail?id=25588
1648 TEST(HttpCache, SimpleGET_DoomWithPending) {
1649 // We need simultaneous doomed / not_doomed entries so let's use a real cache.
1650 MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024));
1651
1652 MockHttpRequest request(kSimpleGET_Transaction);
1653 MockHttpRequest writer_request(kSimpleGET_Transaction);
1654 writer_request.load_flags = net::LOAD_BYPASS_CACHE;
1655
1656 ScopedVector<Context> context_list;
1657 const int kNumTransactions = 4;
1658
1659 for (int i = 0; i < kNumTransactions; ++i) {
1660 context_list.push_back(new Context());
1661 Context* c = context_list[i];
1662
1663 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1664 EXPECT_EQ(net::OK, c->result);
1665
1666 MockHttpRequest* this_request = &request;
1667 if (i == 3)
1668 this_request = &writer_request;
1669
1670 c->result = c->trans->Start(this_request, &c->callback, net::BoundNetLog());
1671 }
1672
1673 // The first request should be a writer at this point, and the two subsequent
1674 // requests should be pending. The last request doomed the first entry.
1675
1676 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1677
1678 // Cancel the first queued transaction.
1679 delete context_list[1];
1680 context_list.get()[1] = NULL;
1681
1682 for (int i = 0; i < kNumTransactions; ++i) {
1683 if (i == 1)
1684 continue;
1685 Context* c = context_list[i];
1686 ASSERT_EQ(net::ERR_IO_PENDING, c->result);
1687 c->result = c->callback.WaitForResult();
1688 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1689 }
1690 }
1691
1692 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4731.
1693 // We may attempt to delete an entry synchronously with the act of adding a new
1694 // transaction to said entry.
1695 TEST(HttpCache, FastNoStoreGET_DoneWithPending) {
1696 MockHttpCache cache;
1697
1698 // The headers will be served right from the call to Start() the request.
1699 MockHttpRequest request(kFastNoStoreGET_Transaction);
1700 FastTransactionServer request_handler;
1701 AddMockTransaction(&kFastNoStoreGET_Transaction);
1702
1703 std::vector<Context*> context_list;
1704 const int kNumTransactions = 3;
1705
1706 for (int i = 0; i < kNumTransactions; ++i) {
1707 context_list.push_back(new Context());
1708 Context* c = context_list[i];
1709
1710 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1711 EXPECT_EQ(net::OK, c->result);
1712
1713 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1714 }
1715
1716 // Allow all requests to move from the Create queue to the active entry.
1717 MessageLoop::current()->RunAllPending();
1718
1719 // The first request should be a writer at this point, and the subsequent
1720 // requests should be pending.
1721
1722 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1723 EXPECT_EQ(0, cache.disk_cache()->open_count());
1724 EXPECT_EQ(1, cache.disk_cache()->create_count());
1725
1726 // Now, make sure that the second request asks for the entry not to be stored.
1727 request_handler.set_no_store(true);
1728
1729 for (int i = 0; i < kNumTransactions; ++i) {
1730 Context* c = context_list[i];
1731 if (c->result == net::ERR_IO_PENDING)
1732 c->result = c->callback.WaitForResult();
1733 ReadAndVerifyTransaction(c->trans.get(), kFastNoStoreGET_Transaction);
1734 delete c;
1735 }
1736
1737 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1738 EXPECT_EQ(0, cache.disk_cache()->open_count());
1739 EXPECT_EQ(2, cache.disk_cache()->create_count());
1740
1741 RemoveMockTransaction(&kFastNoStoreGET_Transaction);
1742 }
1743
1744 TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) {
1745 MockHttpCache cache;
1746
1747 MockHttpRequest request(kSimpleGET_Transaction);
1748
1749 std::vector<Context*> context_list;
1750 const int kNumTransactions = 2;
1751
1752 for (int i = 0; i < kNumTransactions; ++i) {
1753 context_list.push_back(new Context());
1754 Context* c = context_list[i];
1755
1756 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1757 EXPECT_EQ(net::OK, c->result);
1758
1759 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1760 }
1761
1762 // Allow all requests to move from the Create queue to the active entry.
1763 MessageLoop::current()->RunAllPending();
1764
1765 // The first request should be a writer at this point, and the subsequent
1766 // requests should be pending.
1767
1768 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1769 EXPECT_EQ(0, cache.disk_cache()->open_count());
1770 EXPECT_EQ(1, cache.disk_cache()->create_count());
1771
1772 for (int i = 0; i < kNumTransactions; ++i) {
1773 Context* c = context_list[i];
1774 if (c->result == net::ERR_IO_PENDING)
1775 c->result = c->callback.WaitForResult();
1776 // Destroy only the first transaction.
1777 if (i == 0) {
1778 delete c;
1779 context_list[i] = NULL;
1780 }
1781 }
1782
1783 // Complete the rest of the transactions.
1784 for (int i = 1; i < kNumTransactions; ++i) {
1785 Context* c = context_list[i];
1786 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1787 }
1788
1789 // We should have had to re-open the disk entry.
1790
1791 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1792 EXPECT_EQ(0, cache.disk_cache()->open_count());
1793 EXPECT_EQ(2, cache.disk_cache()->create_count());
1794
1795 for (int i = 1; i < kNumTransactions; ++i) {
1796 Context* c = context_list[i];
1797 delete c;
1798 }
1799 }
1800
1801 // Tests that we can cancel requests that are queued waiting to open the disk
1802 // cache entry.
1803 TEST(HttpCache, SimpleGET_ManyWriters_CancelCreate) {
1804 MockHttpCache cache;
1805
1806 MockHttpRequest request(kSimpleGET_Transaction);
1807
1808 std::vector<Context*> context_list;
1809 const int kNumTransactions = 5;
1810
1811 for (int i = 0; i < kNumTransactions; i++) {
1812 context_list.push_back(new Context());
1813 Context* c = context_list[i];
1814
1815 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1816 EXPECT_EQ(net::OK, c->result);
1817
1818 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1819 }
1820
1821 // The first request should be creating the disk cache entry and the others
1822 // should be pending.
1823
1824 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1825 EXPECT_EQ(0, cache.disk_cache()->open_count());
1826 EXPECT_EQ(1, cache.disk_cache()->create_count());
1827
1828 // Cancel a request from the pending queue.
1829 delete context_list[3];
1830 context_list[3] = NULL;
1831
1832 // Cancel the request that is creating the entry. This will force the pending
1833 // operations to restart.
1834 delete context_list[0];
1835 context_list[0] = NULL;
1836
1837 // Complete the rest of the transactions.
1838 for (int i = 1; i < kNumTransactions; i++) {
1839 Context* c = context_list[i];
1840 if (c) {
1841 c->result = c->callback.GetResult(c->result);
1842 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1843 }
1844 }
1845
1846 // We should have had to re-create the disk entry.
1847
1848 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1849 EXPECT_EQ(0, cache.disk_cache()->open_count());
1850 EXPECT_EQ(2, cache.disk_cache()->create_count());
1851
1852 for (int i = 1; i < kNumTransactions; ++i) {
1853 delete context_list[i];
1854 }
1855 }
1856
1857 // Tests that we can cancel a single request to open a disk cache entry.
1858 TEST(HttpCache, SimpleGET_CancelCreate) {
1859 MockHttpCache cache;
1860
1861 MockHttpRequest request(kSimpleGET_Transaction);
1862
1863 Context* c = new Context();
1864
1865 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1866 EXPECT_EQ(net::OK, c->result);
1867
1868 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1869 EXPECT_EQ(net::ERR_IO_PENDING, c->result);
1870
1871 // Release the reference that the mock disk cache keeps for this entry, so
1872 // that we test that the http cache handles the cancelation correctly.
1873 cache.disk_cache()->ReleaseAll();
1874 delete c;
1875
1876 MessageLoop::current()->RunAllPending();
1877 EXPECT_EQ(1, cache.disk_cache()->create_count());
1878 }
1879
1880 // Tests that we delete/create entries even if multiple requests are queued.
1881 TEST(HttpCache, SimpleGET_ManyWriters_BypassCache) {
1882 MockHttpCache cache;
1883
1884 MockHttpRequest request(kSimpleGET_Transaction);
1885 request.load_flags = net::LOAD_BYPASS_CACHE;
1886
1887 std::vector<Context*> context_list;
1888 const int kNumTransactions = 5;
1889
1890 for (int i = 0; i < kNumTransactions; i++) {
1891 context_list.push_back(new Context());
1892 Context* c = context_list[i];
1893
1894 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1895 EXPECT_EQ(net::OK, c->result);
1896
1897 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1898 }
1899
1900 // The first request should be deleting the disk cache entry and the others
1901 // should be pending.
1902
1903 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1904 EXPECT_EQ(0, cache.disk_cache()->open_count());
1905 EXPECT_EQ(0, cache.disk_cache()->create_count());
1906
1907 // Complete the transactions.
1908 for (int i = 0; i < kNumTransactions; i++) {
1909 Context* c = context_list[i];
1910 c->result = c->callback.GetResult(c->result);
1911 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1912 }
1913
1914 // We should have had to re-create the disk entry multiple times.
1915
1916 EXPECT_EQ(5, cache.network_layer()->transaction_count());
1917 EXPECT_EQ(0, cache.disk_cache()->open_count());
1918 EXPECT_EQ(5, cache.disk_cache()->create_count());
1919
1920 for (int i = 0; i < kNumTransactions; ++i) {
1921 delete context_list[i];
1922 }
1923 }
1924
1925 TEST(HttpCache, SimpleGET_AbandonedCacheRead) {
1926 MockHttpCache cache;
1927
1928 // write to the cache
1929 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1930
1931 MockHttpRequest request(kSimpleGET_Transaction);
1932 TestOldCompletionCallback callback;
1933
1934 scoped_ptr<net::HttpTransaction> trans;
1935 int rv = cache.http_cache()->CreateTransaction(&trans);
1936 EXPECT_EQ(net::OK, rv);
1937 rv = trans->Start(&request, &callback, net::BoundNetLog());
1938 if (rv == net::ERR_IO_PENDING)
1939 rv = callback.WaitForResult();
1940 ASSERT_EQ(net::OK, rv);
1941
1942 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
1943 rv = trans->Read(buf, 256, &callback);
1944 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1945
1946 // Test that destroying the transaction while it is reading from the cache
1947 // works properly.
1948 trans.reset();
1949
1950 // Make sure we pump any pending events, which should include a call to
1951 // HttpCache::Transaction::OnCacheReadCompleted.
1952 MessageLoop::current()->RunAllPending();
1953 }
1954
1955 // Tests that we can delete the HttpCache and deal with queued transactions
1956 // ("waiting for the backend" as opposed to Active or Doomed entries).
1957 TEST(HttpCache, SimpleGET_ManyWriters_DeleteCache) {
1958 scoped_ptr<MockHttpCache> cache(new MockHttpCache(
1959 new MockBackendNoCbFactory()));
1960
1961 MockHttpRequest request(kSimpleGET_Transaction);
1962
1963 std::vector<Context*> context_list;
1964 const int kNumTransactions = 5;
1965
1966 for (int i = 0; i < kNumTransactions; i++) {
1967 context_list.push_back(new Context());
1968 Context* c = context_list[i];
1969
1970 c->result = cache->http_cache()->CreateTransaction(&c->trans);
1971 EXPECT_EQ(net::OK, c->result);
1972
1973 c->result = c->trans->Start(&request, &c->callback, net::BoundNetLog());
1974 }
1975
1976 // The first request should be creating the disk cache entry and the others
1977 // should be pending.
1978
1979 EXPECT_EQ(0, cache->network_layer()->transaction_count());
1980 EXPECT_EQ(0, cache->disk_cache()->open_count());
1981 EXPECT_EQ(0, cache->disk_cache()->create_count());
1982
1983 cache.reset();
1984
1985 // There is not much to do with the transactions at this point... they are
1986 // waiting for a callback that will not fire.
1987 for (int i = 0; i < kNumTransactions; ++i) {
1988 delete context_list[i];
1989 }
1990 }
1991
1992 // Tests that we queue requests when initializing the backend.
1993 TEST(HttpCache, SimpleGET_WaitForBackend) {
1994 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1995 MockHttpCache cache(factory);
1996
1997 MockHttpRequest request0(kSimpleGET_Transaction);
1998 MockHttpRequest request1(kTypicalGET_Transaction);
1999 MockHttpRequest request2(kETagGET_Transaction);
2000
2001 std::vector<Context*> context_list;
2002 const int kNumTransactions = 3;
2003
2004 for (int i = 0; i < kNumTransactions; i++) {
2005 context_list.push_back(new Context());
2006 Context* c = context_list[i];
2007
2008 c->result = cache.http_cache()->CreateTransaction(&c->trans);
2009 EXPECT_EQ(net::OK, c->result);
2010 }
2011
2012 context_list[0]->result = context_list[0]->trans->Start(
2013 &request0, &context_list[0]->callback, net::BoundNetLog());
2014 context_list[1]->result = context_list[1]->trans->Start(
2015 &request1, &context_list[1]->callback, net::BoundNetLog());
2016 context_list[2]->result = context_list[2]->trans->Start(
2017 &request2, &context_list[2]->callback, net::BoundNetLog());
2018
2019 // Just to make sure that everything is still pending.
2020 MessageLoop::current()->RunAllPending();
2021
2022 // The first request should be creating the disk cache.
2023 EXPECT_FALSE(context_list[0]->callback.have_result());
2024
2025 factory->FinishCreation();
2026
2027 MessageLoop::current()->RunAllPending();
2028 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2029 EXPECT_EQ(3, cache.disk_cache()->create_count());
2030
2031 for (int i = 0; i < kNumTransactions; ++i) {
2032 EXPECT_TRUE(context_list[i]->callback.have_result());
2033 delete context_list[i];
2034 }
2035 }
2036
2037 // Tests that we can cancel requests that are queued waiting for the backend
2038 // to be initialized.
2039 TEST(HttpCache, SimpleGET_WaitForBackend_CancelCreate) {
2040 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
2041 MockHttpCache cache(factory);
2042
2043 MockHttpRequest request0(kSimpleGET_Transaction);
2044 MockHttpRequest request1(kTypicalGET_Transaction);
2045 MockHttpRequest request2(kETagGET_Transaction);
2046
2047 std::vector<Context*> context_list;
2048 const int kNumTransactions = 3;
2049
2050 for (int i = 0; i < kNumTransactions; i++) {
2051 context_list.push_back(new Context());
2052 Context* c = context_list[i];
2053
2054 c->result = cache.http_cache()->CreateTransaction(&c->trans);
2055 EXPECT_EQ(net::OK, c->result);
2056 }
2057
2058 context_list[0]->result = context_list[0]->trans->Start(
2059 &request0, &context_list[0]->callback, net::BoundNetLog());
2060 context_list[1]->result = context_list[1]->trans->Start(
2061 &request1, &context_list[1]->callback, net::BoundNetLog());
2062 context_list[2]->result = context_list[2]->trans->Start(
2063 &request2, &context_list[2]->callback, net::BoundNetLog());
2064
2065 // Just to make sure that everything is still pending.
2066 MessageLoop::current()->RunAllPending();
2067
2068 // The first request should be creating the disk cache.
2069 EXPECT_FALSE(context_list[0]->callback.have_result());
2070
2071 // Cancel a request from the pending queue.
2072 delete context_list[1];
2073 context_list[1] = NULL;
2074
2075 // Cancel the request that is creating the entry.
2076 delete context_list[0];
2077 context_list[0] = NULL;
2078
2079 // Complete the last transaction.
2080 factory->FinishCreation();
2081
2082 context_list[2]->result =
2083 context_list[2]->callback.GetResult(context_list[2]->result);
2084 ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction);
2085
2086 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2087 EXPECT_EQ(1, cache.disk_cache()->create_count());
2088
2089 delete context_list[2];
2090 }
2091
2092 // Tests that we can delete the cache while creating the backend.
2093 TEST(HttpCache, DeleteCacheWaitingForBackend) {
2094 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
2095 scoped_ptr<MockHttpCache> cache(new MockHttpCache(factory));
2096
2097 MockHttpRequest request(kSimpleGET_Transaction);
2098
2099 scoped_ptr<Context> c(new Context());
2100 c->result = cache->http_cache()->CreateTransaction(&c->trans);
2101 EXPECT_EQ(net::OK, c->result);
2102
2103 c->trans->Start(&request, &c->callback, net::BoundNetLog());
2104
2105 // Just to make sure that everything is still pending.
2106 MessageLoop::current()->RunAllPending();
2107
2108 // The request should be creating the disk cache.
2109 EXPECT_FALSE(c->callback.have_result());
2110
2111 // We cannot call FinishCreation because the factory itself will go away with
2112 // the cache, so grab the callback and attempt to use it.
2113 net::OldCompletionCallback* callback = factory->callback();
2114 disk_cache::Backend** backend = factory->backend();
2115
2116 cache.reset();
2117 MessageLoop::current()->RunAllPending();
2118
2119 *backend = NULL;
2120 callback->Run(net::ERR_ABORTED);
2121 }
2122
2123 // Tests that we can delete the cache while creating the backend, from within
2124 // one of the callbacks.
2125 TEST(HttpCache, DeleteCacheWaitingForBackend2) {
2126 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
2127 MockHttpCache* cache = new MockHttpCache(factory);
2128
2129 DeleteCacheOldCompletionCallback cb(cache);
2130 disk_cache::Backend* backend;
2131 int rv = cache->http_cache()->GetBackend(&backend, &cb);
2132 EXPECT_EQ(net::ERR_IO_PENDING, rv);
2133
2134 // Now let's queue a regular transaction
2135 MockHttpRequest request(kSimpleGET_Transaction);
2136
2137 scoped_ptr<Context> c(new Context());
2138 c->result = cache->http_cache()->CreateTransaction(&c->trans);
2139 EXPECT_EQ(net::OK, c->result);
2140
2141 c->trans->Start(&request, &c->callback, net::BoundNetLog());
2142
2143 // And another direct backend request.
2144 TestOldCompletionCallback cb2;
2145 rv = cache->http_cache()->GetBackend(&backend, &cb2);
2146 EXPECT_EQ(net::ERR_IO_PENDING, rv);
2147
2148 // Just to make sure that everything is still pending.
2149 MessageLoop::current()->RunAllPending();
2150
2151 // The request should be queued.
2152 EXPECT_FALSE(c->callback.have_result());
2153
2154 // Generate the callback.
2155 factory->FinishCreation();
2156 rv = cb.WaitForResult();
2157
2158 // The cache should be gone by now.
2159 MessageLoop::current()->RunAllPending();
2160 EXPECT_EQ(net::OK, c->callback.GetResult(c->result));
2161 EXPECT_FALSE(cb2.have_result());
2162 }
2163
2164 TEST(HttpCache, TypicalGET_ConditionalRequest) {
2165 MockHttpCache cache;
2166
2167 // write to the cache
2168 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
2169
2170 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2171 EXPECT_EQ(0, cache.disk_cache()->open_count());
2172 EXPECT_EQ(1, cache.disk_cache()->create_count());
2173
2174 // get the same URL again, but this time we expect it to result
2175 // in a conditional request.
2176 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
2177
2178 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2179 EXPECT_EQ(1, cache.disk_cache()->open_count());
2180 EXPECT_EQ(1, cache.disk_cache()->create_count());
2181 }
2182
2183 static void ETagGet_ConditionalRequest_Handler(
2184 const net::HttpRequestInfo* request,
2185 std::string* response_status,
2186 std::string* response_headers,
2187 std::string* response_data) {
2188 EXPECT_TRUE(
2189 request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch));
2190 response_status->assign("HTTP/1.1 304 Not Modified");
2191 response_headers->assign(kETagGET_Transaction.response_headers);
2192 response_data->clear();
2193 }
2194
2195 TEST(HttpCache, ETagGET_ConditionalRequest_304) {
2196 MockHttpCache cache;
2197
2198 ScopedMockTransaction transaction(kETagGET_Transaction);
2199
2200 // write to the cache
2201 RunTransactionTest(cache.http_cache(), transaction);
2202
2203 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2204 EXPECT_EQ(0, cache.disk_cache()->open_count());
2205 EXPECT_EQ(1, cache.disk_cache()->create_count());
2206
2207 // get the same URL again, but this time we expect it to result
2208 // in a conditional request.
2209 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
2210 transaction.handler = ETagGet_ConditionalRequest_Handler;
2211 RunTransactionTest(cache.http_cache(), transaction);
2212
2213 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2214 EXPECT_EQ(1, cache.disk_cache()->open_count());
2215 EXPECT_EQ(1, cache.disk_cache()->create_count());
2216 }
2217
2218 static void ETagGet_UnconditionalRequest_Handler(
2219 const net::HttpRequestInfo* request,
2220 std::string* response_status,
2221 std::string* response_headers,
2222 std::string* response_data) {
2223 EXPECT_FALSE(
2224 request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch));
2225 }
2226
2227 TEST(HttpCache, ETagGET_Http10) {
2228 MockHttpCache cache;
2229
2230 ScopedMockTransaction transaction(kETagGET_Transaction);
2231 transaction.status = "HTTP/1.0 200 OK";
2232
2233 // Write to the cache.
2234 RunTransactionTest(cache.http_cache(), transaction);
2235
2236 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2237 EXPECT_EQ(0, cache.disk_cache()->open_count());
2238 EXPECT_EQ(1, cache.disk_cache()->create_count());
2239
2240 // Get the same URL again, without generating a conditional request.
2241 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
2242 transaction.handler = ETagGet_UnconditionalRequest_Handler;
2243 RunTransactionTest(cache.http_cache(), transaction);
2244
2245 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2246 EXPECT_EQ(1, cache.disk_cache()->open_count());
2247 EXPECT_EQ(1, cache.disk_cache()->create_count());
2248 }
2249
2250 TEST(HttpCache, ETagGET_Http10_Range) {
2251 MockHttpCache cache;
2252
2253 ScopedMockTransaction transaction(kETagGET_Transaction);
2254 transaction.status = "HTTP/1.0 200 OK";
2255
2256 // Write to the cache.
2257 RunTransactionTest(cache.http_cache(), transaction);
2258
2259 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2260 EXPECT_EQ(0, cache.disk_cache()->open_count());
2261 EXPECT_EQ(1, cache.disk_cache()->create_count());
2262
2263 // Get the same URL again, but use a byte range request.
2264 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
2265 transaction.handler = ETagGet_UnconditionalRequest_Handler;
2266 transaction.request_headers = "Range: bytes = 5-";
2267 RunTransactionTest(cache.http_cache(), transaction);
2268
2269 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2270 EXPECT_EQ(1, cache.disk_cache()->open_count());
2271 EXPECT_EQ(2, cache.disk_cache()->create_count());
2272 }
2273
2274 static void ETagGet_ConditionalRequest_NoStore_Handler(
2275 const net::HttpRequestInfo* request,
2276 std::string* response_status,
2277 std::string* response_headers,
2278 std::string* response_data) {
2279 EXPECT_TRUE(
2280 request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch));
2281 response_status->assign("HTTP/1.1 304 Not Modified");
2282 response_headers->assign("Cache-Control: no-store\n");
2283 response_data->clear();
2284 }
2285
2286 TEST(HttpCache, ETagGET_ConditionalRequest_304_NoStore) {
2287 MockHttpCache cache;
2288
2289 ScopedMockTransaction transaction(kETagGET_Transaction);
2290
2291 // Write to the cache.
2292 RunTransactionTest(cache.http_cache(), transaction);
2293
2294 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2295 EXPECT_EQ(0, cache.disk_cache()->open_count());
2296 EXPECT_EQ(1, cache.disk_cache()->create_count());
2297
2298 // Get the same URL again, but this time we expect it to result
2299 // in a conditional request.
2300 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
2301 transaction.handler = ETagGet_ConditionalRequest_NoStore_Handler;
2302 RunTransactionTest(cache.http_cache(), transaction);
2303
2304 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2305 EXPECT_EQ(1, cache.disk_cache()->open_count());
2306 EXPECT_EQ(1, cache.disk_cache()->create_count());
2307
2308 ScopedMockTransaction transaction2(kETagGET_Transaction);
2309
2310 // Write to the cache again. This should create a new entry.
2311 RunTransactionTest(cache.http_cache(), transaction2);
2312
2313 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2314 EXPECT_EQ(1, cache.disk_cache()->open_count());
2315 EXPECT_EQ(2, cache.disk_cache()->create_count());
2316 }
2317
2318 TEST(HttpCache, SimplePOST_SkipsCache) {
2319 MockHttpCache cache;
2320
2321 // Test that we skip the cache for POST requests that do not have an upload
2322 // identifier.
2323
2324 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
2325
2326 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2327 EXPECT_EQ(0, cache.disk_cache()->open_count());
2328 EXPECT_EQ(0, cache.disk_cache()->create_count());
2329 }
2330
2331 // Helper that does 4 requests using HttpCache:
2332 //
2333 // (1) loads |kUrl| -- expects |net_response_1| to be returned.
2334 // (2) loads |kUrl| from cache only -- expects |net_response_1| to be returned.
2335 // (3) loads |kUrl| using |extra_request_headers| -- expects |net_response_2| to
2336 // be returned.
2337 // (4) loads |kUrl| from cache only -- expects |cached_response_2| to be
2338 // returned.
2339 static void ConditionalizedRequestUpdatesCacheHelper(
2340 const Response& net_response_1,
2341 const Response& net_response_2,
2342 const Response& cached_response_2,
2343 const char* extra_request_headers) {
2344 MockHttpCache cache;
2345
2346 // The URL we will be requesting.
2347 const char* kUrl = "http://foobar.com/main.css";
2348
2349 // Junk network response.
2350 static const Response kUnexpectedResponse = {
2351 "HTTP/1.1 500 Unexpected",
2352 "Server: unexpected_header",
2353 "unexpected body"
2354 };
2355
2356 // We will control the network layer's responses for |kUrl| using
2357 // |mock_network_response|.
2358 MockTransaction mock_network_response = { 0 };
2359 mock_network_response.url = kUrl;
2360 AddMockTransaction(&mock_network_response);
2361
2362 // Request |kUrl| for the first time. It should hit the network and
2363 // receive |kNetResponse1|, which it saves into the HTTP cache.
2364
2365 MockTransaction request = { 0 };
2366 request.url = kUrl;
2367 request.method = "GET";
2368 request.request_headers = "";
2369
2370 net_response_1.AssignTo(&mock_network_response); // Network mock.
2371 net_response_1.AssignTo(&request); // Expected result.
2372
2373 std::string response_headers;
2374 RunTransactionTestWithResponse(
2375 cache.http_cache(), request, &response_headers);
2376
2377 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
2378 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2379 EXPECT_EQ(0, cache.disk_cache()->open_count());
2380 EXPECT_EQ(1, cache.disk_cache()->create_count());
2381
2382 // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP
2383 // cache, so we don't hit the network.
2384
2385 request.load_flags = net::LOAD_ONLY_FROM_CACHE;
2386
2387 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
2388 net_response_1.AssignTo(&request); // Expected result.
2389
2390 RunTransactionTestWithResponse(
2391 cache.http_cache(), request, &response_headers);
2392
2393 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
2394 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2395 EXPECT_EQ(1, cache.disk_cache()->open_count());
2396 EXPECT_EQ(1, cache.disk_cache()->create_count());
2397
2398 // Request |kUrl| yet again, but this time give the request an
2399 // "If-Modified-Since" header. This will cause the request to re-hit the
2400 // network. However now the network response is going to be
2401 // different -- this simulates a change made to the CSS file.
2402
2403 request.request_headers = extra_request_headers;
2404 request.load_flags = net::LOAD_NORMAL;
2405
2406 net_response_2.AssignTo(&mock_network_response); // Network mock.
2407 net_response_2.AssignTo(&request); // Expected result.
2408
2409 RunTransactionTestWithResponse(
2410 cache.http_cache(), request, &response_headers);
2411
2412 EXPECT_EQ(net_response_2.status_and_headers(), response_headers);
2413 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2414 EXPECT_EQ(1, cache.disk_cache()->open_count());
2415 EXPECT_EQ(1, cache.disk_cache()->create_count());
2416
2417 // Finally, request |kUrl| again. This request should be serviced from
2418 // the cache. Moreover, the value in the cache should be |kNetResponse2|
2419 // and NOT |kNetResponse1|. The previous step should have replaced the
2420 // value in the cache with the modified response.
2421
2422 request.request_headers = "";
2423 request.load_flags = net::LOAD_ONLY_FROM_CACHE;
2424
2425 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
2426 cached_response_2.AssignTo(&request); // Expected result.
2427
2428 RunTransactionTestWithResponse(
2429 cache.http_cache(), request, &response_headers);
2430
2431 EXPECT_EQ(cached_response_2.status_and_headers(), response_headers);
2432 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2433 EXPECT_EQ(2, cache.disk_cache()->open_count());
2434 EXPECT_EQ(1, cache.disk_cache()->create_count());
2435
2436 RemoveMockTransaction(&mock_network_response);
2437 }
2438
2439 // Check that when an "if-modified-since" header is attached
2440 // to the request, the result still updates the cached entry.
2441 TEST(HttpCache, ConditionalizedRequestUpdatesCache1) {
2442 // First network response for |kUrl|.
2443 static const Response kNetResponse1 = {
2444 "HTTP/1.1 200 OK",
2445 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2446 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2447 "body1"
2448 };
2449
2450 // Second network response for |kUrl|.
2451 static const Response kNetResponse2 = {
2452 "HTTP/1.1 200 OK",
2453 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2454 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2455 "body2"
2456 };
2457
2458 const char* extra_headers =
2459 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n";
2460
2461 ConditionalizedRequestUpdatesCacheHelper(
2462 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
2463 }
2464
2465 // Check that when an "if-none-match" header is attached
2466 // to the request, the result updates the cached entry.
2467 TEST(HttpCache, ConditionalizedRequestUpdatesCache2) {
2468 // First network response for |kUrl|.
2469 static const Response kNetResponse1 = {
2470 "HTTP/1.1 200 OK",
2471 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2472 "Etag: \"ETAG1\"\n"
2473 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
2474 "body1"
2475 };
2476
2477 // Second network response for |kUrl|.
2478 static const Response kNetResponse2 = {
2479 "HTTP/1.1 200 OK",
2480 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2481 "Etag: \"ETAG2\"\n"
2482 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
2483 "body2"
2484 };
2485
2486 const char* extra_headers = "If-None-Match: \"ETAG1\"\n";
2487
2488 ConditionalizedRequestUpdatesCacheHelper(
2489 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
2490 }
2491
2492 // Check that when an "if-modified-since" header is attached
2493 // to a request, the 304 (not modified result) result updates the cached
2494 // headers, and the 304 response is returned rather than the cached response.
2495 TEST(HttpCache, ConditionalizedRequestUpdatesCache3) {
2496 // First network response for |kUrl|.
2497 static const Response kNetResponse1 = {
2498 "HTTP/1.1 200 OK",
2499 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2500 "Server: server1\n"
2501 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2502 "body1"
2503 };
2504
2505 // Second network response for |kUrl|.
2506 static const Response kNetResponse2 = {
2507 "HTTP/1.1 304 Not Modified",
2508 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2509 "Server: server2\n"
2510 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2511 ""
2512 };
2513
2514 static const Response kCachedResponse2 = {
2515 "HTTP/1.1 200 OK",
2516 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2517 "Server: server2\n"
2518 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2519 "body1"
2520 };
2521
2522 const char* extra_headers =
2523 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n";
2524
2525 ConditionalizedRequestUpdatesCacheHelper(
2526 kNetResponse1, kNetResponse2, kCachedResponse2, extra_headers);
2527 }
2528
2529 // Test that when doing an externally conditionalized if-modified-since
2530 // and there is no corresponding cache entry, a new cache entry is NOT
2531 // created (304 response).
2532 TEST(HttpCache, ConditionalizedRequestUpdatesCache4) {
2533 MockHttpCache cache;
2534
2535 const char* kUrl = "http://foobar.com/main.css";
2536
2537 static const Response kNetResponse = {
2538 "HTTP/1.1 304 Not Modified",
2539 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2540 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2541 ""
2542 };
2543
2544 const char* kExtraRequestHeaders =
2545 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT";
2546
2547 // We will control the network layer's responses for |kUrl| using
2548 // |mock_network_response|.
2549 MockTransaction mock_network_response = { 0 };
2550 mock_network_response.url = kUrl;
2551 AddMockTransaction(&mock_network_response);
2552
2553 MockTransaction request = { 0 };
2554 request.url = kUrl;
2555 request.method = "GET";
2556 request.request_headers = kExtraRequestHeaders;
2557
2558 kNetResponse.AssignTo(&mock_network_response); // Network mock.
2559 kNetResponse.AssignTo(&request); // Expected result.
2560
2561 std::string response_headers;
2562 RunTransactionTestWithResponse(
2563 cache.http_cache(), request, &response_headers);
2564
2565 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
2566 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2567 EXPECT_EQ(0, cache.disk_cache()->open_count());
2568 EXPECT_EQ(0, cache.disk_cache()->create_count());
2569
2570 RemoveMockTransaction(&mock_network_response);
2571 }
2572
2573 // Test that when doing an externally conditionalized if-modified-since
2574 // and there is no corresponding cache entry, a new cache entry is NOT
2575 // created (200 response).
2576 TEST(HttpCache, ConditionalizedRequestUpdatesCache5) {
2577 MockHttpCache cache;
2578
2579 const char* kUrl = "http://foobar.com/main.css";
2580
2581 static const Response kNetResponse = {
2582 "HTTP/1.1 200 OK",
2583 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2584 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2585 "foobar!!!"
2586 };
2587
2588 const char* kExtraRequestHeaders =
2589 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT";
2590
2591 // We will control the network layer's responses for |kUrl| using
2592 // |mock_network_response|.
2593 MockTransaction mock_network_response = { 0 };
2594 mock_network_response.url = kUrl;
2595 AddMockTransaction(&mock_network_response);
2596
2597 MockTransaction request = { 0 };
2598 request.url = kUrl;
2599 request.method = "GET";
2600 request.request_headers = kExtraRequestHeaders;
2601
2602 kNetResponse.AssignTo(&mock_network_response); // Network mock.
2603 kNetResponse.AssignTo(&request); // Expected result.
2604
2605 std::string response_headers;
2606 RunTransactionTestWithResponse(
2607 cache.http_cache(), request, &response_headers);
2608
2609 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
2610 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2611 EXPECT_EQ(0, cache.disk_cache()->open_count());
2612 EXPECT_EQ(0, cache.disk_cache()->create_count());
2613
2614 RemoveMockTransaction(&mock_network_response);
2615 }
2616
2617 // Test that when doing an externally conditionalized if-modified-since
2618 // if the date does not match the cache entry's last-modified date,
2619 // then we do NOT use the response (304) to update the cache.
2620 // (the if-modified-since date is 2 days AFTER the cache's modification date).
2621 TEST(HttpCache, ConditionalizedRequestUpdatesCache6) {
2622 static const Response kNetResponse1 = {
2623 "HTTP/1.1 200 OK",
2624 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2625 "Server: server1\n"
2626 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2627 "body1"
2628 };
2629
2630 // Second network response for |kUrl|.
2631 static const Response kNetResponse2 = {
2632 "HTTP/1.1 304 Not Modified",
2633 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2634 "Server: server2\n"
2635 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2636 ""
2637 };
2638
2639 // This is two days in the future from the original response's last-modified
2640 // date!
2641 const char* kExtraRequestHeaders =
2642 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\n";
2643
2644 ConditionalizedRequestUpdatesCacheHelper(
2645 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2646 }
2647
2648 // Test that when doing an externally conditionalized if-none-match
2649 // if the etag does not match the cache entry's etag, then we do not use the
2650 // response (304) to update the cache.
2651 TEST(HttpCache, ConditionalizedRequestUpdatesCache7) {
2652 static const Response kNetResponse1 = {
2653 "HTTP/1.1 200 OK",
2654 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2655 "Etag: \"Foo1\"\n"
2656 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2657 "body1"
2658 };
2659
2660 // Second network response for |kUrl|.
2661 static const Response kNetResponse2 = {
2662 "HTTP/1.1 304 Not Modified",
2663 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2664 "Etag: \"Foo2\"\n"
2665 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2666 ""
2667 };
2668
2669 // Different etag from original response.
2670 const char* kExtraRequestHeaders = "If-None-Match: \"Foo2\"\n";
2671
2672 ConditionalizedRequestUpdatesCacheHelper(
2673 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2674 }
2675
2676 // Test that doing an externally conditionalized request with both if-none-match
2677 // and if-modified-since updates the cache.
2678 TEST(HttpCache, ConditionalizedRequestUpdatesCache8) {
2679 static const Response kNetResponse1 = {
2680 "HTTP/1.1 200 OK",
2681 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2682 "Etag: \"Foo1\"\n"
2683 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2684 "body1"
2685 };
2686
2687 // Second network response for |kUrl|.
2688 static const Response kNetResponse2 = {
2689 "HTTP/1.1 200 OK",
2690 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2691 "Etag: \"Foo2\"\n"
2692 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2693 "body2"
2694 };
2695
2696 const char* kExtraRequestHeaders =
2697 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
2698 "If-None-Match: \"Foo1\"\r\n";
2699
2700 ConditionalizedRequestUpdatesCacheHelper(
2701 kNetResponse1, kNetResponse2, kNetResponse2, kExtraRequestHeaders);
2702 }
2703
2704 // Test that doing an externally conditionalized request with both if-none-match
2705 // and if-modified-since does not update the cache with only one match.
2706 TEST(HttpCache, ConditionalizedRequestUpdatesCache9) {
2707 static const Response kNetResponse1 = {
2708 "HTTP/1.1 200 OK",
2709 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2710 "Etag: \"Foo1\"\n"
2711 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2712 "body1"
2713 };
2714
2715 // Second network response for |kUrl|.
2716 static const Response kNetResponse2 = {
2717 "HTTP/1.1 200 OK",
2718 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2719 "Etag: \"Foo2\"\n"
2720 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2721 "body2"
2722 };
2723
2724 // The etag doesn't match what we have stored.
2725 const char* kExtraRequestHeaders =
2726 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n"
2727 "If-None-Match: \"Foo2\"\n";
2728
2729 ConditionalizedRequestUpdatesCacheHelper(
2730 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2731 }
2732
2733 // Test that doing an externally conditionalized request with both if-none-match
2734 // and if-modified-since does not update the cache with only one match.
2735 TEST(HttpCache, ConditionalizedRequestUpdatesCache10) {
2736 static const Response kNetResponse1 = {
2737 "HTTP/1.1 200 OK",
2738 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2739 "Etag: \"Foo1\"\n"
2740 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2741 "body1"
2742 };
2743
2744 // Second network response for |kUrl|.
2745 static const Response kNetResponse2 = {
2746 "HTTP/1.1 200 OK",
2747 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2748 "Etag: \"Foo2\"\n"
2749 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2750 "body2"
2751 };
2752
2753 // The modification date doesn't match what we have stored.
2754 const char* kExtraRequestHeaders =
2755 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\n"
2756 "If-None-Match: \"Foo1\"\n";
2757
2758 ConditionalizedRequestUpdatesCacheHelper(
2759 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2760 }
2761
2762 // Test that doing an externally conditionalized request with two conflicting
2763 // headers does not update the cache.
2764 TEST(HttpCache, ConditionalizedRequestUpdatesCache11) {
2765 static const Response kNetResponse1 = {
2766 "HTTP/1.1 200 OK",
2767 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2768 "Etag: \"Foo1\"\n"
2769 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2770 "body1"
2771 };
2772
2773 // Second network response for |kUrl|.
2774 static const Response kNetResponse2 = {
2775 "HTTP/1.1 200 OK",
2776 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2777 "Etag: \"Foo2\"\n"
2778 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2779 "body2"
2780 };
2781
2782 // Two dates, the second matches what we have stored.
2783 const char* kExtraRequestHeaders =
2784 "If-Modified-Since: Mon, 04 Feb 2008 22:38:21 GMT\n"
2785 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n";
2786
2787 ConditionalizedRequestUpdatesCacheHelper(
2788 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2789 }
2790
2791 TEST(HttpCache, UrlContainingHash) {
2792 MockHttpCache cache;
2793
2794 // Do a typical GET request -- should write an entry into our cache.
2795 MockTransaction trans(kTypicalGET_Transaction);
2796 RunTransactionTest(cache.http_cache(), trans);
2797
2798 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2799 EXPECT_EQ(0, cache.disk_cache()->open_count());
2800 EXPECT_EQ(1, cache.disk_cache()->create_count());
2801
2802 // Request the same URL, but this time with a reference section (hash).
2803 // Since the cache key strips the hash sections, this should be a cache hit.
2804 std::string url_with_hash = std::string(trans.url) + "#multiple#hashes";
2805 trans.url = url_with_hash.c_str();
2806 trans.load_flags = net::LOAD_ONLY_FROM_CACHE;
2807
2808 RunTransactionTest(cache.http_cache(), trans);
2809
2810 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2811 EXPECT_EQ(1, cache.disk_cache()->open_count());
2812 EXPECT_EQ(1, cache.disk_cache()->create_count());
2813 }
2814
2815 TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Miss) {
2816 MockHttpCache cache;
2817
2818 // Test that we skip the cache for POST requests. Eventually, we will want
2819 // to cache these, but we'll still have cases where skipping the cache makes
2820 // sense, so we want to make sure that it works properly.
2821
2822 MockTransaction transaction(kSimplePOST_Transaction);
2823 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
2824
2825 MockHttpRequest request(transaction);
2826 TestOldCompletionCallback callback;
2827
2828 scoped_ptr<net::HttpTransaction> trans;
2829 int rv = cache.http_cache()->CreateTransaction(&trans);
2830 EXPECT_EQ(net::OK, rv);
2831 ASSERT_TRUE(trans.get());
2832
2833 rv = trans->Start(&request, &callback, net::BoundNetLog());
2834 if (rv == net::ERR_IO_PENDING)
2835 rv = callback.WaitForResult();
2836 ASSERT_EQ(net::ERR_CACHE_MISS, rv);
2837
2838 trans.reset();
2839
2840 EXPECT_EQ(0, cache.network_layer()->transaction_count());
2841 EXPECT_EQ(0, cache.disk_cache()->open_count());
2842 EXPECT_EQ(0, cache.disk_cache()->create_count());
2843 }
2844
2845 TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Hit) {
2846 MockHttpCache cache;
2847
2848 // Test that we hit the cache for POST requests.
2849
2850 MockTransaction transaction(kSimplePOST_Transaction);
2851
2852 const int64 kUploadId = 1; // Just a dummy value.
2853
2854 MockHttpRequest request(transaction);
2855 request.upload_data = new net::UploadData();
2856 request.upload_data->set_identifier(kUploadId);
2857 request.upload_data->AppendBytes("hello", 5);
2858
2859 // Populate the cache.
2860 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
2861
2862 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2863 EXPECT_EQ(0, cache.disk_cache()->open_count());
2864 EXPECT_EQ(1, cache.disk_cache()->create_count());
2865
2866 // Load from cache.
2867 request.load_flags |= net::LOAD_ONLY_FROM_CACHE;
2868 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
2869
2870 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2871 EXPECT_EQ(1, cache.disk_cache()->open_count());
2872 EXPECT_EQ(1, cache.disk_cache()->create_count());
2873 }
2874
2875 TEST(HttpCache, RangeGET_SkipsCache) {
2876 MockHttpCache cache;
2877
2878 // Test that we skip the cache for range GET requests. Eventually, we will
2879 // want to cache these, but we'll still have cases where skipping the cache
2880 // makes sense, so we want to make sure that it works properly.
2881
2882 RunTransactionTest(cache.http_cache(), kRangeGET_Transaction);
2883
2884 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2885 EXPECT_EQ(0, cache.disk_cache()->open_count());
2886 EXPECT_EQ(0, cache.disk_cache()->create_count());
2887
2888 MockTransaction transaction(kSimpleGET_Transaction);
2889 transaction.request_headers = "If-None-Match: foo";
2890 RunTransactionTest(cache.http_cache(), transaction);
2891
2892 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2893 EXPECT_EQ(0, cache.disk_cache()->open_count());
2894 EXPECT_EQ(0, cache.disk_cache()->create_count());
2895
2896 transaction.request_headers =
2897 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT";
2898 RunTransactionTest(cache.http_cache(), transaction);
2899
2900 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2901 EXPECT_EQ(0, cache.disk_cache()->open_count());
2902 EXPECT_EQ(0, cache.disk_cache()->create_count());
2903 }
2904
2905 // Test that we skip the cache for range requests that include a validation
2906 // header.
2907 TEST(HttpCache, RangeGET_SkipsCache2) {
2908 MockHttpCache cache;
2909
2910 MockTransaction transaction(kRangeGET_Transaction);
2911 transaction.request_headers = "If-None-Match: foo\r\n"
2912 EXTRA_HEADER
2913 "\r\nRange: bytes = 40-49";
2914 RunTransactionTest(cache.http_cache(), transaction);
2915
2916 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2917 EXPECT_EQ(0, cache.disk_cache()->open_count());
2918 EXPECT_EQ(0, cache.disk_cache()->create_count());
2919
2920 transaction.request_headers =
2921 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n"
2922 EXTRA_HEADER
2923 "\r\nRange: bytes = 40-49";
2924 RunTransactionTest(cache.http_cache(), transaction);
2925
2926 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2927 EXPECT_EQ(0, cache.disk_cache()->open_count());
2928 EXPECT_EQ(0, cache.disk_cache()->create_count());
2929
2930 transaction.request_headers = "If-Range: bla\r\n"
2931 EXTRA_HEADER
2932 "\r\nRange: bytes = 40-49\n";
2933 RunTransactionTest(cache.http_cache(), transaction);
2934
2935 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2936 EXPECT_EQ(0, cache.disk_cache()->open_count());
2937 EXPECT_EQ(0, cache.disk_cache()->create_count());
2938 }
2939
2940 // Tests that receiving 206 for a regular request is handled correctly.
2941 TEST(HttpCache, GET_Crazy206) {
2942 MockHttpCache cache;
2943
2944 // Write to the cache.
2945 MockTransaction transaction(kRangeGET_TransactionOK);
2946 AddMockTransaction(&transaction);
2947 transaction.request_headers = EXTRA_HEADER;
2948 transaction.handler = NULL;
2949 RunTransactionTest(cache.http_cache(), transaction);
2950
2951 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2952 EXPECT_EQ(0, cache.disk_cache()->open_count());
2953 EXPECT_EQ(1, cache.disk_cache()->create_count());
2954
2955 // This should read again from the net.
2956 RunTransactionTest(cache.http_cache(), transaction);
2957
2958 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2959 EXPECT_EQ(0, cache.disk_cache()->open_count());
2960 EXPECT_EQ(2, cache.disk_cache()->create_count());
2961 RemoveMockTransaction(&transaction);
2962 }
2963
2964 // Tests that we don't cache partial responses that can't be validated.
2965 TEST(HttpCache, RangeGET_NoStrongValidators) {
2966 MockHttpCache cache;
2967 std::string headers;
2968
2969 // Attempt to write to the cache (40-49).
2970 MockTransaction transaction(kRangeGET_TransactionOK);
2971 AddMockTransaction(&transaction);
2972 transaction.response_headers = "Content-Length: 10\n"
2973 "ETag: w/\"foo\"\n";
2974 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2975
2976 Verify206Response(headers, 40, 49);
2977 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2978 EXPECT_EQ(0, cache.disk_cache()->open_count());
2979 EXPECT_EQ(1, cache.disk_cache()->create_count());
2980
2981 // Now verify that there's no cached data.
2982 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2983 &headers);
2984
2985 Verify206Response(headers, 40, 49);
2986 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2987 EXPECT_EQ(0, cache.disk_cache()->open_count());
2988 EXPECT_EQ(2, cache.disk_cache()->create_count());
2989
2990 RemoveMockTransaction(&transaction);
2991 }
2992
2993 // Tests that we can cache range requests and fetch random blocks from the
2994 // cache and the network.
2995 TEST(HttpCache, RangeGET_OK) {
2996 MockHttpCache cache;
2997 AddMockTransaction(&kRangeGET_TransactionOK);
2998 std::string headers;
2999
3000 // Write to the cache (40-49).
3001 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3002 &headers);
3003
3004 Verify206Response(headers, 40, 49);
3005 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3006 EXPECT_EQ(0, cache.disk_cache()->open_count());
3007 EXPECT_EQ(1, cache.disk_cache()->create_count());
3008
3009 // Read from the cache (40-49).
3010 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3011 &headers);
3012
3013 Verify206Response(headers, 40, 49);
3014 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3015 EXPECT_EQ(1, cache.disk_cache()->open_count());
3016 EXPECT_EQ(1, cache.disk_cache()->create_count());
3017
3018 // Make sure we are done with the previous transaction.
3019 MessageLoop::current()->RunAllPending();
3020
3021 // Write to the cache (30-39).
3022 MockTransaction transaction(kRangeGET_TransactionOK);
3023 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
3024 transaction.data = "rg: 30-39 ";
3025 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3026
3027 Verify206Response(headers, 30, 39);
3028 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3029 EXPECT_EQ(2, cache.disk_cache()->open_count());
3030 EXPECT_EQ(1, cache.disk_cache()->create_count());
3031
3032 // Make sure we are done with the previous transaction.
3033 MessageLoop::current()->RunAllPending();
3034
3035 // Write and read from the cache (20-59).
3036 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
3037 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
3038 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3039
3040 Verify206Response(headers, 20, 59);
3041 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3042 EXPECT_EQ(3, cache.disk_cache()->open_count());
3043 EXPECT_EQ(1, cache.disk_cache()->create_count());
3044
3045 RemoveMockTransaction(&kRangeGET_TransactionOK);
3046 }
3047
3048 // Tests that we can cache range requests and fetch random blocks from the
3049 // cache and the network, with synchronous responses.
3050 TEST(HttpCache, RangeGET_SyncOK) {
3051 MockHttpCache cache;
3052
3053 MockTransaction transaction(kRangeGET_TransactionOK);
3054 transaction.test_mode = TEST_MODE_SYNC_ALL;
3055 AddMockTransaction(&transaction);
3056
3057 // Write to the cache (40-49).
3058 std::string headers;
3059 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3060
3061 Verify206Response(headers, 40, 49);
3062 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3063 EXPECT_EQ(0, cache.disk_cache()->open_count());
3064 EXPECT_EQ(1, cache.disk_cache()->create_count());
3065
3066 // Read from the cache (40-49).
3067 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3068
3069 Verify206Response(headers, 40, 49);
3070 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3071 EXPECT_EQ(0, cache.disk_cache()->open_count());
3072 EXPECT_EQ(1, cache.disk_cache()->create_count());
3073
3074 // Make sure we are done with the previous transaction.
3075 MessageLoop::current()->RunAllPending();
3076
3077 // Write to the cache (30-39).
3078 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
3079 transaction.data = "rg: 30-39 ";
3080 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3081
3082 Verify206Response(headers, 30, 39);
3083 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3084 EXPECT_EQ(1, cache.disk_cache()->open_count());
3085 EXPECT_EQ(1, cache.disk_cache()->create_count());
3086
3087 // Make sure we are done with the previous transaction.
3088 MessageLoop::current()->RunAllPending();
3089
3090 // Write and read from the cache (20-59).
3091 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
3092 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
3093 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3094
3095 Verify206Response(headers, 20, 59);
3096 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3097 EXPECT_EQ(2, cache.disk_cache()->open_count());
3098 EXPECT_EQ(1, cache.disk_cache()->create_count());
3099
3100 RemoveMockTransaction(&transaction);
3101 }
3102
3103 // Tests that we don't revalidate an entry unless we are required to do so.
3104 TEST(HttpCache, RangeGET_Revalidate1) {
3105 MockHttpCache cache;
3106 std::string headers;
3107
3108 // Write to the cache (40-49).
3109 MockTransaction transaction(kRangeGET_TransactionOK);
3110 transaction.response_headers =
3111 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
3112 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n" // Should never expire.
3113 "ETag: \"foo\"\n"
3114 "Accept-Ranges: bytes\n"
3115 "Content-Length: 10\n";
3116 AddMockTransaction(&transaction);
3117 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3118
3119 Verify206Response(headers, 40, 49);
3120 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3121 EXPECT_EQ(0, cache.disk_cache()->open_count());
3122 EXPECT_EQ(1, cache.disk_cache()->create_count());
3123
3124 // Read from the cache (40-49).
3125 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3126 Verify206Response(headers, 40, 49);
3127
3128 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3129 EXPECT_EQ(1, cache.disk_cache()->open_count());
3130 EXPECT_EQ(1, cache.disk_cache()->create_count());
3131
3132 // Read again forcing the revalidation.
3133 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
3134 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3135
3136 Verify206Response(headers, 40, 49);
3137 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3138 EXPECT_EQ(1, cache.disk_cache()->open_count());
3139 EXPECT_EQ(1, cache.disk_cache()->create_count());
3140
3141 RemoveMockTransaction(&transaction);
3142 }
3143
3144 // Checks that we revalidate an entry when the headers say so.
3145 TEST(HttpCache, RangeGET_Revalidate2) {
3146 MockHttpCache cache;
3147 std::string headers;
3148
3149 // Write to the cache (40-49).
3150 MockTransaction transaction(kRangeGET_TransactionOK);
3151 transaction.response_headers =
3152 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
3153 "Expires: Sat, 18 Apr 2009 01:10:43 GMT\n" // Expired.
3154 "ETag: \"foo\"\n"
3155 "Accept-Ranges: bytes\n"
3156 "Content-Length: 10\n";
3157 AddMockTransaction(&transaction);
3158 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3159
3160 Verify206Response(headers, 40, 49);
3161 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3162 EXPECT_EQ(0, cache.disk_cache()->open_count());
3163 EXPECT_EQ(1, cache.disk_cache()->create_count());
3164
3165 // Read from the cache (40-49).
3166 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3167 Verify206Response(headers, 40, 49);
3168
3169 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3170 EXPECT_EQ(1, cache.disk_cache()->open_count());
3171 EXPECT_EQ(1, cache.disk_cache()->create_count());
3172
3173 RemoveMockTransaction(&transaction);
3174 }
3175
3176 // Tests that we deal with 304s for range requests.
3177 TEST(HttpCache, RangeGET_304) {
3178 MockHttpCache cache;
3179 AddMockTransaction(&kRangeGET_TransactionOK);
3180 std::string headers;
3181
3182 // Write to the cache (40-49).
3183 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3184 &headers);
3185
3186 Verify206Response(headers, 40, 49);
3187 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3188 EXPECT_EQ(0, cache.disk_cache()->open_count());
3189 EXPECT_EQ(1, cache.disk_cache()->create_count());
3190
3191 // Read from the cache (40-49).
3192 RangeTransactionServer handler;
3193 handler.set_not_modified(true);
3194 MockTransaction transaction(kRangeGET_TransactionOK);
3195 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
3196 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3197
3198 Verify206Response(headers, 40, 49);
3199 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3200 EXPECT_EQ(1, cache.disk_cache()->open_count());
3201 EXPECT_EQ(1, cache.disk_cache()->create_count());
3202
3203 RemoveMockTransaction(&kRangeGET_TransactionOK);
3204 }
3205
3206 // Tests that we deal with 206s when revalidating range requests.
3207 TEST(HttpCache, RangeGET_ModifiedResult) {
3208 MockHttpCache cache;
3209 AddMockTransaction(&kRangeGET_TransactionOK);
3210 std::string headers;
3211
3212 // Write to the cache (40-49).
3213 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3214 &headers);
3215
3216 Verify206Response(headers, 40, 49);
3217 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3218 EXPECT_EQ(0, cache.disk_cache()->open_count());
3219 EXPECT_EQ(1, cache.disk_cache()->create_count());
3220
3221 // Attempt to read from the cache (40-49).
3222 RangeTransactionServer handler;
3223 handler.set_modified(true);
3224 MockTransaction transaction(kRangeGET_TransactionOK);
3225 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
3226 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3227
3228 Verify206Response(headers, 40, 49);
3229 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3230 EXPECT_EQ(1, cache.disk_cache()->open_count());
3231 EXPECT_EQ(1, cache.disk_cache()->create_count());
3232
3233 // And the entry should be gone.
3234 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
3235 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3236 EXPECT_EQ(1, cache.disk_cache()->open_count());
3237 EXPECT_EQ(2, cache.disk_cache()->create_count());
3238
3239 RemoveMockTransaction(&kRangeGET_TransactionOK);
3240 }
3241
3242 // Tests that we can cache range requests when the start or end is unknown.
3243 // We start with one suffix request, followed by a request from a given point.
3244 TEST(HttpCache, UnknownRangeGET_1) {
3245 MockHttpCache cache;
3246 AddMockTransaction(&kRangeGET_TransactionOK);
3247 std::string headers;
3248
3249 // Write to the cache (70-79).
3250 MockTransaction transaction(kRangeGET_TransactionOK);
3251 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
3252 transaction.data = "rg: 70-79 ";
3253 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3254
3255 Verify206Response(headers, 70, 79);
3256 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3257 EXPECT_EQ(0, cache.disk_cache()->open_count());
3258 EXPECT_EQ(1, cache.disk_cache()->create_count());
3259
3260 // Make sure we are done with the previous transaction.
3261 MessageLoop::current()->RunAllPending();
3262
3263 // Write and read from the cache (60-79).
3264 transaction.request_headers = "Range: bytes = 60-\r\n" EXTRA_HEADER;
3265 transaction.data = "rg: 60-69 rg: 70-79 ";
3266 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3267
3268 Verify206Response(headers, 60, 79);
3269 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3270 EXPECT_EQ(1, cache.disk_cache()->open_count());
3271 EXPECT_EQ(1, cache.disk_cache()->create_count());
3272
3273 RemoveMockTransaction(&kRangeGET_TransactionOK);
3274 }
3275
3276 // Tests that we can cache range requests when the start or end is unknown.
3277 // We start with one request from a given point, followed by a suffix request.
3278 // We'll also verify that synchronous cache responses work as intended.
3279 TEST(HttpCache, UnknownRangeGET_2) {
3280 MockHttpCache cache;
3281 std::string headers;
3282
3283 MockTransaction transaction(kRangeGET_TransactionOK);
3284 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
3285 TEST_MODE_SYNC_CACHE_READ |
3286 TEST_MODE_SYNC_CACHE_WRITE;
3287 AddMockTransaction(&transaction);
3288
3289 // Write to the cache (70-79).
3290 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
3291 transaction.data = "rg: 70-79 ";
3292 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3293
3294 Verify206Response(headers, 70, 79);
3295 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3296 EXPECT_EQ(0, cache.disk_cache()->open_count());
3297 EXPECT_EQ(1, cache.disk_cache()->create_count());
3298
3299 // Make sure we are done with the previous transaction.
3300 MessageLoop::current()->RunAllPending();
3301
3302 // Write and read from the cache (60-79).
3303 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
3304 transaction.data = "rg: 60-69 rg: 70-79 ";
3305 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3306
3307 Verify206Response(headers, 60, 79);
3308 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3309 EXPECT_EQ(1, cache.disk_cache()->open_count());
3310 EXPECT_EQ(1, cache.disk_cache()->create_count());
3311
3312 RemoveMockTransaction(&transaction);
3313 }
3314
3315 // Tests that receiving Not Modified when asking for an open range doesn't mess
3316 // up things.
3317 TEST(HttpCache, UnknownRangeGET_304) {
3318 MockHttpCache cache;
3319 std::string headers;
3320
3321 MockTransaction transaction(kRangeGET_TransactionOK);
3322 AddMockTransaction(&transaction);
3323
3324 RangeTransactionServer handler;
3325 handler.set_not_modified(true);
3326
3327 // Ask for the end of the file, without knowing the length.
3328 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
3329 transaction.data = "";
3330 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3331
3332 // We just bypass the cache.
3333 EXPECT_EQ(0U, headers.find("HTTP/1.1 304 Not Modified\n"));
3334 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3335 EXPECT_EQ(0, cache.disk_cache()->open_count());
3336 EXPECT_EQ(1, cache.disk_cache()->create_count());
3337
3338 RunTransactionTest(cache.http_cache(), transaction);
3339 EXPECT_EQ(2, cache.disk_cache()->create_count());
3340
3341 RemoveMockTransaction(&transaction);
3342 }
3343
3344 // Tests that we can handle non-range requests when we have cached a range.
3345 TEST(HttpCache, GET_Previous206) {
3346 MockHttpCache cache;
3347 AddMockTransaction(&kRangeGET_TransactionOK);
3348 std::string headers;
3349
3350 // Write to the cache (40-49).
3351 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3352 &headers);
3353
3354 Verify206Response(headers, 40, 49);
3355 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3356 EXPECT_EQ(0, cache.disk_cache()->open_count());
3357 EXPECT_EQ(1, cache.disk_cache()->create_count());
3358
3359 // Write and read from the cache (0-79), when not asked for a range.
3360 MockTransaction transaction(kRangeGET_TransactionOK);
3361 transaction.request_headers = EXTRA_HEADER;
3362 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
3363 "rg: 50-59 rg: 60-69 rg: 70-79 ";
3364 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3365
3366 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
3367 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3368 EXPECT_EQ(1, cache.disk_cache()->open_count());
3369 EXPECT_EQ(1, cache.disk_cache()->create_count());
3370
3371 RemoveMockTransaction(&kRangeGET_TransactionOK);
3372 }
3373
3374 // Tests that we can handle non-range requests when we have cached the first
3375 // part of the object and the server replies with 304 (Not Modified).
3376 TEST(HttpCache, GET_Previous206_NotModified) {
3377 MockHttpCache cache;
3378
3379 MockTransaction transaction(kRangeGET_TransactionOK);
3380 AddMockTransaction(&transaction);
3381 std::string headers;
3382
3383 // Write to the cache (0-9).
3384 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
3385 transaction.data = "rg: 00-09 ";
3386 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3387 Verify206Response(headers, 0, 9);
3388
3389 // Write to the cache (70-79).
3390 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
3391 transaction.data = "rg: 70-79 ";
3392 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3393 Verify206Response(headers, 70, 79);
3394
3395 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3396 EXPECT_EQ(1, cache.disk_cache()->open_count());
3397 EXPECT_EQ(1, cache.disk_cache()->create_count());
3398
3399 // Read from the cache (0-9), write and read from cache (10 - 79).
3400 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
3401 transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER;
3402 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
3403 "rg: 50-59 rg: 60-69 rg: 70-79 ";
3404 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3405
3406 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
3407 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3408 EXPECT_EQ(2, cache.disk_cache()->open_count());
3409 EXPECT_EQ(1, cache.disk_cache()->create_count());
3410
3411 RemoveMockTransaction(&transaction);
3412 }
3413
3414 // Tests that we can handle a regular request to a sparse entry, that results in
3415 // new content provided by the server (206).
3416 TEST(HttpCache, GET_Previous206_NewContent) {
3417 MockHttpCache cache;
3418 AddMockTransaction(&kRangeGET_TransactionOK);
3419 std::string headers;
3420
3421 // Write to the cache (0-9).
3422 MockTransaction transaction(kRangeGET_TransactionOK);
3423 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
3424 transaction.data = "rg: 00-09 ";
3425 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3426
3427 Verify206Response(headers, 0, 9);
3428 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3429 EXPECT_EQ(0, cache.disk_cache()->open_count());
3430 EXPECT_EQ(1, cache.disk_cache()->create_count());
3431
3432 // Now we'll issue a request without any range that should result first in a
3433 // 206 (when revalidating), and then in a weird standard answer: the test
3434 // server will not modify the response so we'll get the default range... a
3435 // real server will answer with 200.
3436 MockTransaction transaction2(kRangeGET_TransactionOK);
3437 transaction2.request_headers = EXTRA_HEADER;
3438 transaction2.load_flags |= net::LOAD_VALIDATE_CACHE;
3439 transaction2.data = "Not a range";
3440 RangeTransactionServer handler;
3441 handler.set_modified(true);
3442 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
3443
3444 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
3445 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3446 EXPECT_EQ(1, cache.disk_cache()->open_count());
3447 EXPECT_EQ(1, cache.disk_cache()->create_count());
3448
3449 // Verify that the previous request deleted the entry.
3450 RunTransactionTest(cache.http_cache(), transaction);
3451 EXPECT_EQ(2, cache.disk_cache()->create_count());
3452
3453 RemoveMockTransaction(&transaction);
3454 }
3455
3456 // Tests that we can handle cached 206 responses that are not sparse.
3457 TEST(HttpCache, GET_Previous206_NotSparse) {
3458 MockHttpCache cache;
3459
3460 // Create a disk cache entry that stores 206 headers while not being sparse.
3461 disk_cache::Entry* entry;
3462 ASSERT_TRUE(cache.CreateBackendEntry(kSimpleGET_Transaction.url, &entry,
3463 NULL));
3464
3465 std::string raw_headers(kRangeGET_TransactionOK.status);
3466 raw_headers.append("\n");
3467 raw_headers.append(kRangeGET_TransactionOK.response_headers);
3468 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
3469 raw_headers.size());
3470
3471 net::HttpResponseInfo response;
3472 response.headers = new net::HttpResponseHeaders(raw_headers);
3473 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
3474
3475 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500));
3476 int len = static_cast<int>(base::strlcpy(buf->data(),
3477 kRangeGET_TransactionOK.data, 500));
3478 TestOldCompletionCallback cb;
3479 int rv = entry->WriteData(1, 0, buf, len, &cb, true);
3480 EXPECT_EQ(len, cb.GetResult(rv));
3481 entry->Close();
3482
3483 // Now see that we don't use the stored entry.
3484 std::string headers;
3485 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction,
3486 &headers);
3487
3488 // We are expecting a 200.
3489 std::string expected_headers(kSimpleGET_Transaction.status);
3490 expected_headers.append("\n");
3491 expected_headers.append(kSimpleGET_Transaction.response_headers);
3492 EXPECT_EQ(expected_headers, headers);
3493 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3494 EXPECT_EQ(1, cache.disk_cache()->open_count());
3495 EXPECT_EQ(2, cache.disk_cache()->create_count());
3496 }
3497
3498 // Tests that we can handle cached 206 responses that are not sparse. This time
3499 // we issue a range request and expect to receive a range.
3500 TEST(HttpCache, RangeGET_Previous206_NotSparse_2) {
3501 MockHttpCache cache;
3502 AddMockTransaction(&kRangeGET_TransactionOK);
3503
3504 // Create a disk cache entry that stores 206 headers while not being sparse.
3505 disk_cache::Entry* entry;
3506 ASSERT_TRUE(cache.CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
3507 NULL));
3508
3509 std::string raw_headers(kRangeGET_TransactionOK.status);
3510 raw_headers.append("\n");
3511 raw_headers.append(kRangeGET_TransactionOK.response_headers);
3512 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
3513 raw_headers.size());
3514
3515 net::HttpResponseInfo response;
3516 response.headers = new net::HttpResponseHeaders(raw_headers);
3517 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
3518
3519 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500));
3520 int len = static_cast<int>(base::strlcpy(buf->data(),
3521 kRangeGET_TransactionOK.data, 500));
3522 TestOldCompletionCallback cb;
3523 int rv = entry->WriteData(1, 0, buf, len, &cb, true);
3524 EXPECT_EQ(len, cb.GetResult(rv));
3525 entry->Close();
3526
3527 // Now see that we don't use the stored entry.
3528 std::string headers;
3529 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3530 &headers);
3531
3532 // We are expecting a 206.
3533 Verify206Response(headers, 40, 49);
3534 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3535 EXPECT_EQ(1, cache.disk_cache()->open_count());
3536 EXPECT_EQ(2, cache.disk_cache()->create_count());
3537
3538 RemoveMockTransaction(&kRangeGET_TransactionOK);
3539 }
3540
3541 // Tests that we can handle cached 206 responses that can't be validated.
3542 TEST(HttpCache, GET_Previous206_NotValidation) {
3543 MockHttpCache cache;
3544
3545 // Create a disk cache entry that stores 206 headers.
3546 disk_cache::Entry* entry;
3547 ASSERT_TRUE(cache.CreateBackendEntry(kSimpleGET_Transaction.url, &entry,
3548 NULL));
3549
3550 // Make sure that the headers cannot be validated with the server.
3551 std::string raw_headers(kRangeGET_TransactionOK.status);
3552 raw_headers.append("\n");
3553 raw_headers.append("Content-Length: 80\n");
3554 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
3555 raw_headers.size());
3556
3557 net::HttpResponseInfo response;
3558 response.headers = new net::HttpResponseHeaders(raw_headers);
3559 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
3560
3561 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500));
3562 int len = static_cast<int>(base::strlcpy(buf->data(),
3563 kRangeGET_TransactionOK.data, 500));
3564 TestOldCompletionCallback cb;
3565 int rv = entry->WriteData(1, 0, buf, len, &cb, true);
3566 EXPECT_EQ(len, cb.GetResult(rv));
3567 entry->Close();
3568
3569 // Now see that we don't use the stored entry.
3570 std::string headers;
3571 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction,
3572 &headers);
3573
3574 // We are expecting a 200.
3575 std::string expected_headers(kSimpleGET_Transaction.status);
3576 expected_headers.append("\n");
3577 expected_headers.append(kSimpleGET_Transaction.response_headers);
3578 EXPECT_EQ(expected_headers, headers);
3579 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3580 EXPECT_EQ(1, cache.disk_cache()->open_count());
3581 EXPECT_EQ(2, cache.disk_cache()->create_count());
3582 }
3583
3584 // Tests that we can handle range requests with cached 200 responses.
3585 TEST(HttpCache, RangeGET_Previous200) {
3586 MockHttpCache cache;
3587
3588 // Store the whole thing with status 200.
3589 MockTransaction transaction(kTypicalGET_Transaction);
3590 transaction.url = kRangeGET_TransactionOK.url;
3591 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
3592 "rg: 50-59 rg: 60-69 rg: 70-79 ";
3593 AddMockTransaction(&transaction);
3594 RunTransactionTest(cache.http_cache(), transaction);
3595 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3596 EXPECT_EQ(0, cache.disk_cache()->open_count());
3597 EXPECT_EQ(1, cache.disk_cache()->create_count());
3598
3599 RemoveMockTransaction(&transaction);
3600 AddMockTransaction(&kRangeGET_TransactionOK);
3601
3602 // Now see that we use the stored entry.
3603 std::string headers;
3604 MockTransaction transaction2(kRangeGET_TransactionOK);
3605 RangeTransactionServer handler;
3606 handler.set_not_modified(true);
3607 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
3608
3609 // We are expecting a 206.
3610 Verify206Response(headers, 40, 49);
3611 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3612 EXPECT_EQ(1, cache.disk_cache()->open_count());
3613 EXPECT_EQ(1, cache.disk_cache()->create_count());
3614
3615 // The last transaction has finished so make sure the entry is deactivated.
3616 MessageLoop::current()->RunAllPending();
3617
3618 // Make a request for an invalid range.
3619 MockTransaction transaction3(kRangeGET_TransactionOK);
3620 transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER;
3621 transaction3.data = "";
3622 transaction3.load_flags = net::LOAD_PREFERRING_CACHE;
3623 RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers);
3624 EXPECT_EQ(2, cache.disk_cache()->open_count());
3625 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
3626 EXPECT_NE(std::string::npos, headers.find("Content-Range: bytes 0-0/80"));
3627 EXPECT_NE(std::string::npos, headers.find("Content-Length: 0"));
3628
3629 // Make sure the entry is deactivated.
3630 MessageLoop::current()->RunAllPending();
3631
3632 // Even though the request was invalid, we should have the entry.
3633 RunTransactionTest(cache.http_cache(), transaction2);
3634 EXPECT_EQ(3, cache.disk_cache()->open_count());
3635
3636 // Make sure the entry is deactivated.
3637 MessageLoop::current()->RunAllPending();
3638
3639 // Now we should receive a range from the server and drop the stored entry.
3640 handler.set_not_modified(false);
3641 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
3642 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
3643 Verify206Response(headers, 40, 49);
3644 EXPECT_EQ(5, cache.network_layer()->transaction_count());
3645 EXPECT_EQ(4, cache.disk_cache()->open_count());
3646 EXPECT_EQ(1, cache.disk_cache()->create_count());
3647
3648 RunTransactionTest(cache.http_cache(), transaction2);
3649 EXPECT_EQ(2, cache.disk_cache()->create_count());
3650
3651 RemoveMockTransaction(&kRangeGET_TransactionOK);
3652 }
3653
3654 // Tests that we can handle a 200 response when dealing with sparse entries.
3655 TEST(HttpCache, RangeRequestResultsIn200) {
3656 MockHttpCache cache;
3657 AddMockTransaction(&kRangeGET_TransactionOK);
3658 std::string headers;
3659
3660 // Write to the cache (70-79).
3661 MockTransaction transaction(kRangeGET_TransactionOK);
3662 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
3663 transaction.data = "rg: 70-79 ";
3664 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3665
3666 Verify206Response(headers, 70, 79);
3667 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3668 EXPECT_EQ(0, cache.disk_cache()->open_count());
3669 EXPECT_EQ(1, cache.disk_cache()->create_count());
3670
3671 // Now we'll issue a request that results in a plain 200 response, but to
3672 // the to the same URL that we used to store sparse data, and making sure
3673 // that we ask for a range.
3674 RemoveMockTransaction(&kRangeGET_TransactionOK);
3675 MockTransaction transaction2(kSimpleGET_Transaction);
3676 transaction2.url = kRangeGET_TransactionOK.url;
3677 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
3678 AddMockTransaction(&transaction2);
3679
3680 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
3681
3682 std::string expected_headers(kSimpleGET_Transaction.status);
3683 expected_headers.append("\n");
3684 expected_headers.append(kSimpleGET_Transaction.response_headers);
3685 EXPECT_EQ(expected_headers, headers);
3686 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3687 EXPECT_EQ(1, cache.disk_cache()->open_count());
3688 EXPECT_EQ(1, cache.disk_cache()->create_count());
3689
3690 RemoveMockTransaction(&transaction2);
3691 }
3692
3693 // Tests that a range request that falls outside of the size that we know about
3694 // only deletes the entry if the resource has indeed changed.
3695 TEST(HttpCache, RangeGET_MoreThanCurrentSize) {
3696 MockHttpCache cache;
3697 AddMockTransaction(&kRangeGET_TransactionOK);
3698 std::string headers;
3699
3700 // Write to the cache (40-49).
3701 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3702 &headers);
3703
3704 Verify206Response(headers, 40, 49);
3705 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3706 EXPECT_EQ(0, cache.disk_cache()->open_count());
3707 EXPECT_EQ(1, cache.disk_cache()->create_count());
3708
3709 // A weird request should not delete this entry. Ask for bytes 120-.
3710 MockTransaction transaction(kRangeGET_TransactionOK);
3711 transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER;
3712 transaction.data = "";
3713 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3714
3715 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
3716 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3717 EXPECT_EQ(1, cache.disk_cache()->open_count());
3718 EXPECT_EQ(1, cache.disk_cache()->create_count());
3719
3720 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
3721 EXPECT_EQ(2, cache.disk_cache()->open_count());
3722 EXPECT_EQ(1, cache.disk_cache()->create_count());
3723
3724 RemoveMockTransaction(&kRangeGET_TransactionOK);
3725 }
3726
3727 // Tests that we don't delete a sparse entry when we cancel a request.
3728 TEST(HttpCache, RangeGET_Cancel) {
3729 MockHttpCache cache;
3730 AddMockTransaction(&kRangeGET_TransactionOK);
3731
3732 MockHttpRequest request(kRangeGET_TransactionOK);
3733
3734 Context* c = new Context();
3735 int rv = cache.http_cache()->CreateTransaction(&c->trans);
3736 EXPECT_EQ(net::OK, rv);
3737
3738 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
3739 if (rv == net::ERR_IO_PENDING)
3740 rv = c->callback.WaitForResult();
3741
3742 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3743 EXPECT_EQ(0, cache.disk_cache()->open_count());
3744 EXPECT_EQ(1, cache.disk_cache()->create_count());
3745
3746 // Make sure that the entry has some data stored.
3747 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
3748 rv = c->trans->Read(buf, buf->size(), &c->callback);
3749 if (rv == net::ERR_IO_PENDING)
3750 rv = c->callback.WaitForResult();
3751 EXPECT_EQ(buf->size(), rv);
3752
3753 // Destroy the transaction.
3754 delete c;
3755
3756 // Verify that the entry has not been deleted.
3757 disk_cache::Entry* entry;
3758 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
3759 entry->Close();
3760 RemoveMockTransaction(&kRangeGET_TransactionOK);
3761 }
3762
3763 // Tests that we don't delete a sparse entry when we start a new request after
3764 // cancelling the previous one.
3765 TEST(HttpCache, RangeGET_Cancel2) {
3766 MockHttpCache cache;
3767 AddMockTransaction(&kRangeGET_TransactionOK);
3768
3769 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
3770 MockHttpRequest request(kRangeGET_TransactionOK);
3771 request.load_flags |= net::LOAD_VALIDATE_CACHE;
3772
3773 Context* c = new Context();
3774 int rv = cache.http_cache()->CreateTransaction(&c->trans);
3775 EXPECT_EQ(net::OK, rv);
3776
3777 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
3778 if (rv == net::ERR_IO_PENDING)
3779 rv = c->callback.WaitForResult();
3780
3781 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3782 EXPECT_EQ(1, cache.disk_cache()->open_count());
3783 EXPECT_EQ(1, cache.disk_cache()->create_count());
3784
3785 // Make sure that we revalidate the entry and read from the cache (a single
3786 // read will return while waiting for the network).
3787 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5));
3788 rv = c->trans->Read(buf, buf->size(), &c->callback);
3789 EXPECT_EQ(5, c->callback.GetResult(rv));
3790 rv = c->trans->Read(buf, buf->size(), &c->callback);
3791 EXPECT_EQ(net::ERR_IO_PENDING, rv);
3792
3793 // Destroy the transaction before completing the read.
3794 delete c;
3795
3796 // We have the read and the delete (OnProcessPendingQueue) waiting on the
3797 // message loop. This means that a new transaction will just reuse the same
3798 // active entry (no open or create).
3799
3800 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
3801
3802 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3803 EXPECT_EQ(1, cache.disk_cache()->open_count());
3804 EXPECT_EQ(1, cache.disk_cache()->create_count());
3805 RemoveMockTransaction(&kRangeGET_TransactionOK);
3806 }
3807
3808 // A slight variation of the previous test, this time we cancel two requests in
3809 // a row, making sure that the second is waiting for the entry to be ready.
3810 TEST(HttpCache, RangeGET_Cancel3) {
3811 MockHttpCache cache;
3812 AddMockTransaction(&kRangeGET_TransactionOK);
3813
3814 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
3815 MockHttpRequest request(kRangeGET_TransactionOK);
3816 request.load_flags |= net::LOAD_VALIDATE_CACHE;
3817
3818 Context* c = new Context();
3819 int rv = cache.http_cache()->CreateTransaction(&c->trans);
3820 EXPECT_EQ(net::OK, rv);
3821
3822 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
3823 EXPECT_EQ(net::ERR_IO_PENDING, rv);
3824 rv = c->callback.WaitForResult();
3825
3826 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3827 EXPECT_EQ(1, cache.disk_cache()->open_count());
3828 EXPECT_EQ(1, cache.disk_cache()->create_count());
3829
3830 // Make sure that we revalidate the entry and read from the cache (a single
3831 // read will return while waiting for the network).
3832 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5));
3833 rv = c->trans->Read(buf, buf->size(), &c->callback);
3834 EXPECT_EQ(5, c->callback.GetResult(rv));
3835 rv = c->trans->Read(buf, buf->size(), &c->callback);
3836 EXPECT_EQ(net::ERR_IO_PENDING, rv);
3837
3838 // Destroy the transaction before completing the read.
3839 delete c;
3840
3841 // We have the read and the delete (OnProcessPendingQueue) waiting on the
3842 // message loop. This means that a new transaction will just reuse the same
3843 // active entry (no open or create).
3844
3845 c = new Context();
3846 rv = cache.http_cache()->CreateTransaction(&c->trans);
3847 EXPECT_EQ(net::OK, rv);
3848
3849 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
3850 EXPECT_EQ(net::ERR_IO_PENDING, rv);
3851
3852 MockDiskEntry::IgnoreCallbacks(true);
3853 MessageLoop::current()->RunAllPending();
3854 MockDiskEntry::IgnoreCallbacks(false);
3855
3856 // The new transaction is waiting for the query range callback.
3857 delete c;
3858
3859 // And we should not crash when the callback is delivered.
3860 MessageLoop::current()->RunAllPending();
3861
3862 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3863 EXPECT_EQ(1, cache.disk_cache()->open_count());
3864 EXPECT_EQ(1, cache.disk_cache()->create_count());
3865 RemoveMockTransaction(&kRangeGET_TransactionOK);
3866 }
3867
3868 // Tests that an invalid range response results in no cached entry.
3869 TEST(HttpCache, RangeGET_InvalidResponse1) {
3870 MockHttpCache cache;
3871 std::string headers;
3872
3873 MockTransaction transaction(kRangeGET_TransactionOK);
3874 transaction.handler = NULL;
3875 transaction.response_headers = "Content-Range: bytes 40-49/45\n"
3876 "Content-Length: 10\n";
3877 AddMockTransaction(&transaction);
3878 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3879
3880 std::string expected(transaction.status);
3881 expected.append("\n");
3882 expected.append(transaction.response_headers);
3883 EXPECT_EQ(expected, headers);
3884
3885 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3886 EXPECT_EQ(0, cache.disk_cache()->open_count());
3887 EXPECT_EQ(1, cache.disk_cache()->create_count());
3888
3889 // Verify that we don't have a cached entry.
3890 disk_cache::Entry* entry;
3891 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
3892
3893 RemoveMockTransaction(&kRangeGET_TransactionOK);
3894 }
3895
3896 // Tests that we reject a range that doesn't match the content-length.
3897 TEST(HttpCache, RangeGET_InvalidResponse2) {
3898 MockHttpCache cache;
3899 std::string headers;
3900
3901 MockTransaction transaction(kRangeGET_TransactionOK);
3902 transaction.handler = NULL;
3903 transaction.response_headers = "Content-Range: bytes 40-49/80\n"
3904 "Content-Length: 20\n";
3905 AddMockTransaction(&transaction);
3906 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3907
3908 std::string expected(transaction.status);
3909 expected.append("\n");
3910 expected.append(transaction.response_headers);
3911 EXPECT_EQ(expected, headers);
3912
3913 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3914 EXPECT_EQ(0, cache.disk_cache()->open_count());
3915 EXPECT_EQ(1, cache.disk_cache()->create_count());
3916
3917 // Verify that we don't have a cached entry.
3918 disk_cache::Entry* entry;
3919 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
3920
3921 RemoveMockTransaction(&kRangeGET_TransactionOK);
3922 }
3923
3924 // Tests that if a server tells us conflicting information about a resource we
3925 // ignore the response.
3926 TEST(HttpCache, RangeGET_InvalidResponse3) {
3927 MockHttpCache cache;
3928 std::string headers;
3929
3930 MockTransaction transaction(kRangeGET_TransactionOK);
3931 transaction.handler = NULL;
3932 transaction.request_headers = "Range: bytes = 50-59\r\n" EXTRA_HEADER;
3933 std::string response_headers(transaction.response_headers);
3934 response_headers.append("Content-Range: bytes 50-59/160\n");
3935 transaction.response_headers = response_headers.c_str();
3936 AddMockTransaction(&transaction);
3937 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3938
3939 Verify206Response(headers, 50, 59);
3940 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3941 EXPECT_EQ(0, cache.disk_cache()->open_count());
3942 EXPECT_EQ(1, cache.disk_cache()->create_count());
3943
3944 RemoveMockTransaction(&transaction);
3945 AddMockTransaction(&kRangeGET_TransactionOK);
3946
3947 // This transaction will report a resource size of 80 bytes, and we think it's
3948 // 160 so we should ignore the response.
3949 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3950 &headers);
3951
3952 Verify206Response(headers, 40, 49);
3953 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3954 EXPECT_EQ(1, cache.disk_cache()->open_count());
3955 EXPECT_EQ(1, cache.disk_cache()->create_count());
3956
3957 // Verify that we cached the first response but not the second one.
3958 disk_cache::Entry* en;
3959 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &en));
3960
3961 int64 cached_start = 0;
3962 TestOldCompletionCallback cb;
3963 int rv = en->GetAvailableRange(40, 20, &cached_start, &cb);
3964 EXPECT_EQ(10, cb.GetResult(rv));
3965 EXPECT_EQ(50, cached_start);
3966 en->Close();
3967
3968 RemoveMockTransaction(&kRangeGET_TransactionOK);
3969 }
3970
3971 // Tests that we handle large range values properly.
3972 TEST(HttpCache, RangeGET_LargeValues) {
3973 // We need a real sparse cache for this test.
3974 MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024));
3975 std::string headers;
3976
3977 MockTransaction transaction(kRangeGET_TransactionOK);
3978 transaction.handler = NULL;
3979 transaction.request_headers = "Range: bytes = 4294967288-4294967297\r\n"
3980 EXTRA_HEADER;
3981 transaction.response_headers =
3982 "ETag: \"foo\"\n"
3983 "Content-Range: bytes 4294967288-4294967297/4294967299\n"
3984 "Content-Length: 10\n";
3985 AddMockTransaction(&transaction);
3986 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3987
3988 std::string expected(transaction.status);
3989 expected.append("\n");
3990 expected.append(transaction.response_headers);
3991 EXPECT_EQ(expected, headers);
3992
3993 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3994
3995 // Verify that we have a cached entry.
3996 disk_cache::Entry* en;
3997 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &en));
3998 en->Close();
3999
4000 RemoveMockTransaction(&kRangeGET_TransactionOK);
4001 }
4002
4003 // Tests that we don't crash with a range request if the disk cache was not
4004 // initialized properly.
4005 TEST(HttpCache, RangeGET_NoDiskCache) {
4006 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
4007 factory->set_fail(true);
4008 factory->FinishCreation(); // We'll complete synchronously.
4009 MockHttpCache cache(factory);
4010
4011 AddMockTransaction(&kRangeGET_TransactionOK);
4012
4013 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4014 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4015
4016 RemoveMockTransaction(&kRangeGET_TransactionOK);
4017 }
4018
4019 // Tests that we handle byte range requests that skip the cache.
4020 TEST(HttpCache, RangeHEAD) {
4021 MockHttpCache cache;
4022 AddMockTransaction(&kRangeGET_TransactionOK);
4023
4024 MockTransaction transaction(kRangeGET_TransactionOK);
4025 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
4026 transaction.method = "HEAD";
4027 transaction.data = "rg: 70-79 ";
4028
4029 std::string headers;
4030 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4031
4032 Verify206Response(headers, 70, 79);
4033 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4034 EXPECT_EQ(0, cache.disk_cache()->open_count());
4035 EXPECT_EQ(0, cache.disk_cache()->create_count());
4036
4037 RemoveMockTransaction(&kRangeGET_TransactionOK);
4038 }
4039
4040 // Tests that we don't crash when after reading from the cache we issue a
4041 // request for the next range and the server gives us a 200 synchronously.
4042 TEST(HttpCache, RangeGET_FastFlakyServer) {
4043 MockHttpCache cache;
4044
4045 MockTransaction transaction(kRangeGET_TransactionOK);
4046 transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER;
4047 transaction.test_mode = TEST_MODE_SYNC_NET_START;
4048 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
4049 AddMockTransaction(&transaction);
4050
4051 // Write to the cache.
4052 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4053
4054 // And now read from the cache and the network.
4055 RangeTransactionServer handler;
4056 handler.set_bad_200(true);
4057 transaction.data = "Not a range";
4058 RunTransactionTest(cache.http_cache(), transaction);
4059
4060 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4061 EXPECT_EQ(1, cache.disk_cache()->open_count());
4062 EXPECT_EQ(1, cache.disk_cache()->create_count());
4063
4064 RemoveMockTransaction(&transaction);
4065 }
4066
4067 // Tests that when the server gives us less data than expected, we don't keep
4068 // asking for more data.
4069 TEST(HttpCache, RangeGET_FastFlakyServer2) {
4070 MockHttpCache cache;
4071
4072 // First, check with an empty cache (WRITE mode).
4073 MockTransaction transaction(kRangeGET_TransactionOK);
4074 transaction.request_headers = "Range: bytes = 40-49\r\n" EXTRA_HEADER;
4075 transaction.data = "rg: 40-"; // Less than expected.
4076 transaction.handler = NULL;
4077 std::string headers(transaction.response_headers);
4078 headers.append("Content-Range: bytes 40-49/80\n");
4079 transaction.response_headers = headers.c_str();
4080
4081 AddMockTransaction(&transaction);
4082
4083 // Write to the cache.
4084 RunTransactionTest(cache.http_cache(), transaction);
4085
4086 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4087 EXPECT_EQ(0, cache.disk_cache()->open_count());
4088 EXPECT_EQ(1, cache.disk_cache()->create_count());
4089
4090 // Now verify that even in READ_WRITE mode, we forward the bad response to
4091 // the caller.
4092 transaction.request_headers = "Range: bytes = 60-69\r\n" EXTRA_HEADER;
4093 transaction.data = "rg: 60-"; // Less than expected.
4094 headers = kRangeGET_TransactionOK.response_headers;
4095 headers.append("Content-Range: bytes 60-69/80\n");
4096 transaction.response_headers = headers.c_str();
4097
4098 RunTransactionTest(cache.http_cache(), transaction);
4099
4100 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4101 EXPECT_EQ(1, cache.disk_cache()->open_count());
4102 EXPECT_EQ(1, cache.disk_cache()->create_count());
4103
4104 RemoveMockTransaction(&transaction);
4105 }
4106
4107 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
4108 // This test hits a NOTREACHED so it is a release mode only test.
4109 TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) {
4110 MockHttpCache cache;
4111 AddMockTransaction(&kRangeGET_TransactionOK);
4112
4113 // Write to the cache (40-49).
4114 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4115 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4116 EXPECT_EQ(0, cache.disk_cache()->open_count());
4117 EXPECT_EQ(1, cache.disk_cache()->create_count());
4118
4119 // Force this transaction to read from the cache.
4120 MockTransaction transaction(kRangeGET_TransactionOK);
4121 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
4122
4123 MockHttpRequest request(transaction);
4124 TestOldCompletionCallback callback;
4125
4126 scoped_ptr<net::HttpTransaction> trans;
4127 int rv = cache.http_cache()->CreateTransaction(&trans);
4128 EXPECT_EQ(net::OK, rv);
4129 ASSERT_TRUE(trans.get());
4130
4131 rv = trans->Start(&request, &callback, net::BoundNetLog());
4132 if (rv == net::ERR_IO_PENDING)
4133 rv = callback.WaitForResult();
4134 ASSERT_EQ(net::ERR_CACHE_MISS, rv);
4135
4136 trans.reset();
4137
4138 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4139 EXPECT_EQ(1, cache.disk_cache()->open_count());
4140 EXPECT_EQ(1, cache.disk_cache()->create_count());
4141
4142 RemoveMockTransaction(&kRangeGET_TransactionOK);
4143 }
4144 #endif
4145
4146 // Tests the handling of the "truncation" flag.
4147 TEST(HttpCache, WriteResponseInfo_Truncated) {
4148 MockHttpCache cache;
4149 disk_cache::Entry* entry;
4150 ASSERT_TRUE(cache.CreateBackendEntry("http://www.google.com", &entry,
4151 NULL));
4152
4153 std::string headers("HTTP/1.1 200 OK");
4154 headers = net::HttpUtil::AssembleRawHeaders(headers.data(), headers.size());
4155 net::HttpResponseInfo response;
4156 response.headers = new net::HttpResponseHeaders(headers);
4157
4158 // Set the last argument for this to be an incomplete request.
4159 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
4160 bool truncated = false;
4161 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
4162 EXPECT_TRUE(truncated);
4163
4164 // And now test the opposite case.
4165 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
4166 truncated = true;
4167 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
4168 EXPECT_FALSE(truncated);
4169 entry->Close();
4170 }
4171
4172 // Tests basic pickling/unpickling of HttpResponseInfo.
4173 TEST(HttpCache, PersistHttpResponseInfo) {
4174 // Set some fields (add more if needed.)
4175 net::HttpResponseInfo response1;
4176 response1.was_cached = false;
4177 response1.socket_address = net::HostPortPair("1.2.3.4", 80);
4178 response1.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK");
4179
4180 // Pickle.
4181 Pickle pickle;
4182 response1.Persist(&pickle, false, false);
4183
4184 // Unpickle.
4185 net::HttpResponseInfo response2;
4186 bool response_truncated;
4187 EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated));
4188 EXPECT_FALSE(response_truncated);
4189
4190 // Verify fields.
4191 EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag.
4192 EXPECT_EQ("1.2.3.4", response2.socket_address.host());
4193 EXPECT_EQ(80, response2.socket_address.port());
4194 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
4195 }
4196
4197 // Tests that we delete an entry when the request is cancelled before starting
4198 // to read from the network.
4199 TEST(HttpCache, DoomOnDestruction) {
4200 MockHttpCache cache;
4201
4202 MockHttpRequest request(kSimpleGET_Transaction);
4203
4204 Context* c = new Context();
4205 int rv = cache.http_cache()->CreateTransaction(&c->trans);
4206 EXPECT_EQ(net::OK, rv);
4207
4208 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
4209 if (rv == net::ERR_IO_PENDING)
4210 c->result = c->callback.WaitForResult();
4211
4212 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4213 EXPECT_EQ(0, cache.disk_cache()->open_count());
4214 EXPECT_EQ(1, cache.disk_cache()->create_count());
4215
4216 // Destroy the transaction. We only have the headers so we should delete this
4217 // entry.
4218 delete c;
4219
4220 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
4221
4222 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4223 EXPECT_EQ(0, cache.disk_cache()->open_count());
4224 EXPECT_EQ(2, cache.disk_cache()->create_count());
4225 }
4226
4227 // Tests that we delete an entry when the request is cancelled if the response
4228 // does not have content-length and strong validators.
4229 TEST(HttpCache, DoomOnDestruction2) {
4230 MockHttpCache cache;
4231
4232 MockHttpRequest request(kSimpleGET_Transaction);
4233
4234 Context* c = new Context();
4235 int rv = cache.http_cache()->CreateTransaction(&c->trans);
4236 EXPECT_EQ(net::OK, rv);
4237
4238 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
4239 if (rv == net::ERR_IO_PENDING)
4240 rv = c->callback.WaitForResult();
4241
4242 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4243 EXPECT_EQ(0, cache.disk_cache()->open_count());
4244 EXPECT_EQ(1, cache.disk_cache()->create_count());
4245
4246 // Make sure that the entry has some data stored.
4247 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
4248 rv = c->trans->Read(buf, buf->size(), &c->callback);
4249 if (rv == net::ERR_IO_PENDING)
4250 rv = c->callback.WaitForResult();
4251 EXPECT_EQ(buf->size(), rv);
4252
4253 // Destroy the transaction.
4254 delete c;
4255
4256 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
4257
4258 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4259 EXPECT_EQ(0, cache.disk_cache()->open_count());
4260 EXPECT_EQ(2, cache.disk_cache()->create_count());
4261 }
4262
4263 // Tests that we delete an entry when the request is cancelled if the response
4264 // has an "Accept-Ranges: none" header.
4265 TEST(HttpCache, DoomOnDestruction3) {
4266 MockHttpCache cache;
4267
4268 MockTransaction transaction(kSimpleGET_Transaction);
4269 transaction.response_headers =
4270 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
4271 "Content-Length: 22\n"
4272 "Accept-Ranges: none\n"
4273 "Etag: foopy\n";
4274 AddMockTransaction(&transaction);
4275 MockHttpRequest request(transaction);
4276
4277 Context* c = new Context();
4278 int rv = cache.http_cache()->CreateTransaction(&c->trans);
4279 EXPECT_EQ(net::OK, rv);
4280
4281 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
4282 if (rv == net::ERR_IO_PENDING)
4283 rv = c->callback.WaitForResult();
4284
4285 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4286 EXPECT_EQ(0, cache.disk_cache()->open_count());
4287 EXPECT_EQ(1, cache.disk_cache()->create_count());
4288
4289 // Make sure that the entry has some data stored.
4290 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
4291 rv = c->trans->Read(buf, buf->size(), &c->callback);
4292 if (rv == net::ERR_IO_PENDING)
4293 rv = c->callback.WaitForResult();
4294 EXPECT_EQ(buf->size(), rv);
4295
4296 // Destroy the transaction.
4297 delete c;
4298
4299 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
4300
4301 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4302 EXPECT_EQ(0, cache.disk_cache()->open_count());
4303 EXPECT_EQ(2, cache.disk_cache()->create_count());
4304
4305 RemoveMockTransaction(&transaction);
4306 }
4307
4308 // Tests that we mark an entry as incomplete when the request is cancelled.
4309 TEST(HttpCache, SetTruncatedFlag) {
4310 MockHttpCache cache;
4311
4312 MockTransaction transaction(kSimpleGET_Transaction);
4313 transaction.response_headers =
4314 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
4315 "Content-Length: 22\n"
4316 "Etag: foopy\n";
4317 AddMockTransaction(&transaction);
4318 MockHttpRequest request(transaction);
4319
4320 scoped_ptr<Context> c(new Context());
4321 int rv = cache.http_cache()->CreateTransaction(&c->trans);
4322 EXPECT_EQ(net::OK, rv);
4323
4324 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
4325 if (rv == net::ERR_IO_PENDING)
4326 rv = c->callback.WaitForResult();
4327
4328 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4329 EXPECT_EQ(0, cache.disk_cache()->open_count());
4330 EXPECT_EQ(1, cache.disk_cache()->create_count());
4331
4332 // Make sure that the entry has some data stored.
4333 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10));
4334 rv = c->trans->Read(buf, buf->size(), &c->callback);
4335 if (rv == net::ERR_IO_PENDING)
4336 rv = c->callback.WaitForResult();
4337 EXPECT_EQ(buf->size(), rv);
4338
4339 // We want to cancel the request when the transaction is busy.
4340 rv = c->trans->Read(buf, buf->size(), &c->callback);
4341 EXPECT_EQ(net::ERR_IO_PENDING, rv);
4342 EXPECT_FALSE(c->callback.have_result());
4343
4344 g_test_mode = TEST_MODE_SYNC_ALL;
4345
4346 // Destroy the transaction.
4347 c->trans.reset();
4348 g_test_mode = 0;
4349
4350 // Make sure that we don't invoke the callback. We may have an issue if the
4351 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
4352 // could end up with the transaction being deleted twice if we send any
4353 // notification from the transaction destructor (see http://crbug.com/31723).
4354 EXPECT_FALSE(c->callback.have_result());
4355
4356 // Verify that the entry is marked as incomplete.
4357 disk_cache::Entry* entry;
4358 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
4359 net::HttpResponseInfo response;
4360 bool truncated = false;
4361 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
4362 EXPECT_TRUE(truncated);
4363 entry->Close();
4364
4365 RemoveMockTransaction(&transaction);
4366 }
4367
4368 // Tests that we don't mark an entry as truncated when we read everything.
4369 TEST(HttpCache, DontSetTruncatedFlag) {
4370 MockHttpCache cache;
4371
4372 MockTransaction transaction(kSimpleGET_Transaction);
4373 transaction.response_headers =
4374 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
4375 "Content-Length: 22\n"
4376 "Etag: foopy\n";
4377 AddMockTransaction(&transaction);
4378 MockHttpRequest request(transaction);
4379
4380 scoped_ptr<Context> c(new Context());
4381 int rv = cache.http_cache()->CreateTransaction(&c->trans);
4382 EXPECT_EQ(net::OK, rv);
4383
4384 rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
4385 EXPECT_EQ(net::OK, c->callback.GetResult(rv));
4386
4387 // Read everything.
4388 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(22));
4389 rv = c->trans->Read(buf, buf->size(), &c->callback);
4390 EXPECT_EQ(buf->size(), c->callback.GetResult(rv));
4391
4392 // Destroy the transaction.
4393 c->trans.reset();
4394
4395 // Verify that the entry is not marked as truncated.
4396 disk_cache::Entry* entry;
4397 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
4398 net::HttpResponseInfo response;
4399 bool truncated = true;
4400 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
4401 EXPECT_FALSE(truncated);
4402 entry->Close();
4403
4404 RemoveMockTransaction(&transaction);
4405 }
4406
4407 // Tests that we can continue with a request that was interrupted.
4408 TEST(HttpCache, GET_IncompleteResource) {
4409 MockHttpCache cache;
4410 AddMockTransaction(&kRangeGET_TransactionOK);
4411
4412 std::string raw_headers("HTTP/1.1 200 OK\n"
4413 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4414 "ETag: \"foo\"\n"
4415 "Accept-Ranges: bytes\n"
4416 "Content-Length: 80\n");
4417 CreateTruncatedEntry(raw_headers, &cache);
4418
4419 // Now make a regular request.
4420 std::string headers;
4421 MockTransaction transaction(kRangeGET_TransactionOK);
4422 transaction.request_headers = EXTRA_HEADER;
4423 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
4424 "rg: 50-59 rg: 60-69 rg: 70-79 ";
4425 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4426
4427 // We update the headers with the ones received while revalidating.
4428 std::string expected_headers(
4429 "HTTP/1.1 200 OK\n"
4430 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4431 "Accept-Ranges: bytes\n"
4432 "ETag: \"foo\"\n"
4433 "Content-Length: 80\n");
4434
4435 EXPECT_EQ(expected_headers, headers);
4436 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4437 EXPECT_EQ(1, cache.disk_cache()->open_count());
4438 EXPECT_EQ(1, cache.disk_cache()->create_count());
4439
4440 // Verify that the disk entry was updated.
4441 disk_cache::Entry* entry;
4442 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
4443 EXPECT_EQ(80, entry->GetDataSize(1));
4444 bool truncated = true;
4445 net::HttpResponseInfo response;
4446 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
4447 EXPECT_FALSE(truncated);
4448 entry->Close();
4449
4450 RemoveMockTransaction(&kRangeGET_TransactionOK);
4451 }
4452
4453 // Tests that we delete truncated entries if the server changes its mind midway.
4454 TEST(HttpCache, GET_IncompleteResource2) {
4455 MockHttpCache cache;
4456 AddMockTransaction(&kRangeGET_TransactionOK);
4457
4458 // Content-length will be intentionally bad.
4459 std::string raw_headers("HTTP/1.1 200 OK\n"
4460 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4461 "ETag: \"foo\"\n"
4462 "Accept-Ranges: bytes\n"
4463 "Content-Length: 50\n");
4464 CreateTruncatedEntry(raw_headers, &cache);
4465
4466 // Now make a regular request. We expect the code to fail the validation and
4467 // retry the request without using byte ranges.
4468 std::string headers;
4469 MockTransaction transaction(kRangeGET_TransactionOK);
4470 transaction.request_headers = EXTRA_HEADER;
4471 transaction.data = "Not a range";
4472 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4473
4474 // The server will return 200 instead of a byte range.
4475 std::string expected_headers(
4476 "HTTP/1.1 200 OK\n"
4477 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
4478
4479 EXPECT_EQ(expected_headers, headers);
4480 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4481 EXPECT_EQ(1, cache.disk_cache()->open_count());
4482 EXPECT_EQ(1, cache.disk_cache()->create_count());
4483
4484 // Verify that the disk entry was deleted.
4485 disk_cache::Entry* entry;
4486 ASSERT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
4487 RemoveMockTransaction(&kRangeGET_TransactionOK);
4488 }
4489
4490 // Tests that we always validate a truncated request.
4491 TEST(HttpCache, GET_IncompleteResource3) {
4492 MockHttpCache cache;
4493 AddMockTransaction(&kRangeGET_TransactionOK);
4494
4495 // This should not require validation for 10 hours.
4496 std::string raw_headers("HTTP/1.1 200 OK\n"
4497 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
4498 "ETag: \"foo\"\n"
4499 "Cache-Control: max-age= 36000\n"
4500 "Accept-Ranges: bytes\n"
4501 "Content-Length: 80\n");
4502 CreateTruncatedEntry(raw_headers, &cache);
4503
4504 // Now make a regular request.
4505 std::string headers;
4506 MockTransaction transaction(kRangeGET_TransactionOK);
4507 transaction.request_headers = EXTRA_HEADER;
4508 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
4509 "rg: 50-59 rg: 60-69 rg: 70-79 ";
4510
4511 scoped_ptr<Context> c(new Context);
4512 EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans));
4513
4514 MockHttpRequest request(transaction);
4515 int rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
4516 EXPECT_EQ(net::OK, c->callback.GetResult(rv));
4517
4518 // We should have checked with the server before finishing Start().
4519 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4520 EXPECT_EQ(1, cache.disk_cache()->open_count());
4521 EXPECT_EQ(1, cache.disk_cache()->create_count());
4522
4523 RemoveMockTransaction(&kRangeGET_TransactionOK);
4524 }
4525
4526 // Tests that we cache a 200 response to the validation request.
4527 TEST(HttpCache, GET_IncompleteResource4) {
4528 MockHttpCache cache;
4529 AddMockTransaction(&kRangeGET_TransactionOK);
4530
4531 std::string raw_headers("HTTP/1.1 200 OK\n"
4532 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
4533 "ETag: \"foo\"\n"
4534 "Accept-Ranges: bytes\n"
4535 "Content-Length: 80\n");
4536 CreateTruncatedEntry(raw_headers, &cache);
4537
4538 // Now make a regular request.
4539 std::string headers;
4540 MockTransaction transaction(kRangeGET_TransactionOK);
4541 transaction.request_headers = EXTRA_HEADER;
4542 transaction.data = "Not a range";
4543 RangeTransactionServer handler;
4544 handler.set_bad_200(true);
4545 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4546
4547 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4548 EXPECT_EQ(1, cache.disk_cache()->open_count());
4549 EXPECT_EQ(1, cache.disk_cache()->create_count());
4550
4551 // Verify that the disk entry was updated.
4552 disk_cache::Entry* entry;
4553 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
4554 EXPECT_EQ(11, entry->GetDataSize(1));
4555 bool truncated = true;
4556 net::HttpResponseInfo response;
4557 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
4558 EXPECT_FALSE(truncated);
4559 entry->Close();
4560
4561 RemoveMockTransaction(&kRangeGET_TransactionOK);
4562 }
4563
4564 // Tests that when we cancel a request that was interrupted, we mark it again
4565 // as truncated.
4566 TEST(HttpCache, GET_CancelIncompleteResource) {
4567 MockHttpCache cache;
4568 AddMockTransaction(&kRangeGET_TransactionOK);
4569
4570 std::string raw_headers("HTTP/1.1 200 OK\n"
4571 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
4572 "ETag: \"foo\"\n"
4573 "Accept-Ranges: bytes\n"
4574 "Content-Length: 80\n");
4575 CreateTruncatedEntry(raw_headers, &cache);
4576
4577 // Now make a regular request.
4578 MockTransaction transaction(kRangeGET_TransactionOK);
4579 transaction.request_headers = EXTRA_HEADER;
4580
4581 MockHttpRequest request(transaction);
4582 Context* c = new Context();
4583 EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans));
4584
4585 int rv = c->trans->Start(&request, &c->callback, net::BoundNetLog());
4586 EXPECT_EQ(net::OK, c->callback.GetResult(rv));
4587
4588 // Read 20 bytes from the cache, and 10 from the net.
4589 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
4590 rv = c->trans->Read(buf, 20, &c->callback);
4591 EXPECT_EQ(20, c->callback.GetResult(rv));
4592 rv = c->trans->Read(buf, 10, &c->callback);
4593 EXPECT_EQ(10, c->callback.GetResult(rv));
4594
4595 // At this point, we are already reading so canceling the request should leave
4596 // a truncated one.
4597 delete c;
4598
4599 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4600 EXPECT_EQ(1, cache.disk_cache()->open_count());
4601 EXPECT_EQ(1, cache.disk_cache()->create_count());
4602
4603 // Verify that the disk entry was updated: now we have 30 bytes.
4604 disk_cache::Entry* entry;
4605 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
4606 EXPECT_EQ(30, entry->GetDataSize(1));
4607 bool truncated = false;
4608 net::HttpResponseInfo response;
4609 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
4610 EXPECT_TRUE(truncated);
4611 entry->Close();
4612 RemoveMockTransaction(&kRangeGET_TransactionOK);
4613 }
4614
4615 // Tests that we can handle range requests when we have a truncated entry.
4616 TEST(HttpCache, RangeGET_IncompleteResource) {
4617 MockHttpCache cache;
4618 AddMockTransaction(&kRangeGET_TransactionOK);
4619
4620 // Content-length will be intentionally bogus.
4621 std::string raw_headers("HTTP/1.1 200 OK\n"
4622 "Last-Modified: something\n"
4623 "ETag: \"foo\"\n"
4624 "Accept-Ranges: bytes\n"
4625 "Content-Length: 10\n");
4626 CreateTruncatedEntry(raw_headers, &cache);
4627
4628 // Now make a range request.
4629 std::string headers;
4630 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4631 &headers);
4632
4633 Verify206Response(headers, 40, 49);
4634 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4635 EXPECT_EQ(1, cache.disk_cache()->open_count());
4636 EXPECT_EQ(2, cache.disk_cache()->create_count());
4637
4638 RemoveMockTransaction(&kRangeGET_TransactionOK);
4639 }
4640
4641 TEST(HttpCache, SyncRead) {
4642 MockHttpCache cache;
4643
4644 // This test ensures that a read that completes synchronously does not cause
4645 // any problems.
4646
4647 ScopedMockTransaction transaction(kSimpleGET_Transaction);
4648 transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START |
4649 TEST_MODE_SYNC_CACHE_READ |
4650 TEST_MODE_SYNC_CACHE_WRITE);
4651
4652 MockHttpRequest r1(transaction),
4653 r2(transaction),
4654 r3(transaction);
4655
4656 TestTransactionConsumer c1(cache.http_cache()),
4657 c2(cache.http_cache()),
4658 c3(cache.http_cache());
4659
4660 c1.Start(&r1, net::BoundNetLog());
4661
4662 r2.load_flags |= net::LOAD_ONLY_FROM_CACHE;
4663 c2.Start(&r2, net::BoundNetLog());
4664
4665 r3.load_flags |= net::LOAD_ONLY_FROM_CACHE;
4666 c3.Start(&r3, net::BoundNetLog());
4667
4668 MessageLoop::current()->Run();
4669
4670 EXPECT_TRUE(c1.is_done());
4671 EXPECT_TRUE(c2.is_done());
4672 EXPECT_TRUE(c3.is_done());
4673
4674 EXPECT_EQ(net::OK, c1.error());
4675 EXPECT_EQ(net::OK, c2.error());
4676 EXPECT_EQ(net::OK, c3.error());
4677 }
4678
4679 TEST(HttpCache, ValidationResultsIn200) {
4680 MockHttpCache cache;
4681
4682 // This test ensures that a conditional request, which results in a 200
4683 // instead of a 304, properly truncates the existing response data.
4684
4685 // write to the cache
4686 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
4687
4688 // force this transaction to validate the cache
4689 MockTransaction transaction(kETagGET_Transaction);
4690 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
4691 RunTransactionTest(cache.http_cache(), transaction);
4692
4693 // read from the cache
4694 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
4695 }
4696
4697 TEST(HttpCache, CachedRedirect) {
4698 MockHttpCache cache;
4699
4700 ScopedMockTransaction kTestTransaction(kSimpleGET_Transaction);
4701 kTestTransaction.status = "HTTP/1.1 301 Moved Permanently";
4702 kTestTransaction.response_headers = "Location: http://www.bar.com/\n";
4703
4704 MockHttpRequest request(kTestTransaction);
4705 TestOldCompletionCallback callback;
4706
4707 // write to the cache
4708 {
4709 scoped_ptr<net::HttpTransaction> trans;
4710 int rv = cache.http_cache()->CreateTransaction(&trans);
4711 EXPECT_EQ(net::OK, rv);
4712 ASSERT_TRUE(trans.get());
4713
4714 rv = trans->Start(&request, &callback, net::BoundNetLog());
4715 if (rv == net::ERR_IO_PENDING)
4716 rv = callback.WaitForResult();
4717 ASSERT_EQ(net::OK, rv);
4718
4719 const net::HttpResponseInfo* info = trans->GetResponseInfo();
4720 ASSERT_TRUE(info);
4721
4722 EXPECT_EQ(info->headers->response_code(), 301);
4723
4724 std::string location;
4725 info->headers->EnumerateHeader(NULL, "Location", &location);
4726 EXPECT_EQ(location, "http://www.bar.com/");
4727
4728 // Destroy transaction when going out of scope. We have not actually
4729 // read the response body -- want to test that it is still getting cached.
4730 }
4731 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4732 EXPECT_EQ(0, cache.disk_cache()->open_count());
4733 EXPECT_EQ(1, cache.disk_cache()->create_count());
4734
4735 // read from the cache
4736 {
4737 scoped_ptr<net::HttpTransaction> trans;
4738 int rv = cache.http_cache()->CreateTransaction(&trans);
4739 EXPECT_EQ(net::OK, rv);
4740 ASSERT_TRUE(trans.get());
4741
4742 rv = trans->Start(&request, &callback, net::BoundNetLog());
4743 if (rv == net::ERR_IO_PENDING)
4744 rv = callback.WaitForResult();
4745 ASSERT_EQ(net::OK, rv);
4746
4747 const net::HttpResponseInfo* info = trans->GetResponseInfo();
4748 ASSERT_TRUE(info);
4749
4750 EXPECT_EQ(info->headers->response_code(), 301);
4751
4752 std::string location;
4753 info->headers->EnumerateHeader(NULL, "Location", &location);
4754 EXPECT_EQ(location, "http://www.bar.com/");
4755
4756 // Destroy transaction when going out of scope. We have not actually
4757 // read the response body -- want to test that it is still getting cached.
4758 }
4759 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4760 EXPECT_EQ(1, cache.disk_cache()->open_count());
4761 EXPECT_EQ(1, cache.disk_cache()->create_count());
4762 }
4763
4764 TEST(HttpCache, CacheControlNoStore) {
4765 MockHttpCache cache;
4766
4767 ScopedMockTransaction transaction(kSimpleGET_Transaction);
4768 transaction.response_headers = "cache-control: no-store\n";
4769
4770 // initial load
4771 RunTransactionTest(cache.http_cache(), transaction);
4772
4773 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4774 EXPECT_EQ(0, cache.disk_cache()->open_count());
4775 EXPECT_EQ(1, cache.disk_cache()->create_count());
4776
4777 // try loading again; it should result in a network fetch
4778 RunTransactionTest(cache.http_cache(), transaction);
4779
4780 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4781 EXPECT_EQ(0, cache.disk_cache()->open_count());
4782 EXPECT_EQ(2, cache.disk_cache()->create_count());
4783
4784 disk_cache::Entry* entry;
4785 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
4786 }
4787
4788 TEST(HttpCache, CacheControlNoStore2) {
4789 // this test is similar to the above test, except that the initial response
4790 // is cachable, but when it is validated, no-store is received causing the
4791 // cached document to be deleted.
4792 MockHttpCache cache;
4793
4794 ScopedMockTransaction transaction(kETagGET_Transaction);
4795
4796 // initial load
4797 RunTransactionTest(cache.http_cache(), transaction);
4798
4799 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4800 EXPECT_EQ(0, cache.disk_cache()->open_count());
4801 EXPECT_EQ(1, cache.disk_cache()->create_count());
4802
4803 // try loading again; it should result in a network fetch
4804 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
4805 transaction.response_headers = "cache-control: no-store\n";
4806 RunTransactionTest(cache.http_cache(), transaction);
4807
4808 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4809 EXPECT_EQ(1, cache.disk_cache()->open_count());
4810 EXPECT_EQ(1, cache.disk_cache()->create_count());
4811
4812 disk_cache::Entry* entry;
4813 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
4814 }
4815
4816 TEST(HttpCache, CacheControlNoStore3) {
4817 // this test is similar to the above test, except that the response is a 304
4818 // instead of a 200. this should never happen in practice, but it seems like
4819 // a good thing to verify that we still destroy the cache entry.
4820 MockHttpCache cache;
4821
4822 ScopedMockTransaction transaction(kETagGET_Transaction);
4823
4824 // initial load
4825 RunTransactionTest(cache.http_cache(), transaction);
4826
4827 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4828 EXPECT_EQ(0, cache.disk_cache()->open_count());
4829 EXPECT_EQ(1, cache.disk_cache()->create_count());
4830
4831 // try loading again; it should result in a network fetch
4832 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
4833 transaction.response_headers = "cache-control: no-store\n";
4834 transaction.status = "HTTP/1.1 304 Not Modified";
4835 RunTransactionTest(cache.http_cache(), transaction);
4836
4837 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4838 EXPECT_EQ(1, cache.disk_cache()->open_count());
4839 EXPECT_EQ(1, cache.disk_cache()->create_count());
4840
4841 disk_cache::Entry* entry;
4842 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
4843 }
4844
4845 // Ensure that we don't cache requests served over bad HTTPS.
4846 TEST(HttpCache, SimpleGET_SSLError) {
4847 MockHttpCache cache;
4848
4849 MockTransaction transaction = kSimpleGET_Transaction;
4850 transaction.cert_status = net::CERT_STATUS_REVOKED;
4851 ScopedMockTransaction scoped_transaction(transaction);
4852
4853 // write to the cache
4854 RunTransactionTest(cache.http_cache(), transaction);
4855
4856 // Test that it was not cached.
4857 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
4858
4859 MockHttpRequest request(transaction);
4860 TestOldCompletionCallback callback;
4861
4862 scoped_ptr<net::HttpTransaction> trans;
4863 int rv = cache.http_cache()->CreateTransaction(&trans);
4864 EXPECT_EQ(net::OK, rv);
4865 ASSERT_TRUE(trans.get());
4866
4867 rv = trans->Start(&request, &callback, net::BoundNetLog());
4868 if (rv == net::ERR_IO_PENDING)
4869 rv = callback.WaitForResult();
4870 ASSERT_EQ(net::ERR_CACHE_MISS, rv);
4871 }
4872
4873 // Ensure that we don't crash by if left-behind transactions.
4874 TEST(HttpCache, OutlivedTransactions) {
4875 MockHttpCache* cache = new MockHttpCache;
4876
4877 scoped_ptr<net::HttpTransaction> trans;
4878 int rv = cache->http_cache()->CreateTransaction(&trans);
4879 EXPECT_EQ(net::OK, rv);
4880
4881 delete cache;
4882 trans.reset();
4883 }
4884
4885 // Test that the disabled mode works.
4886 TEST(HttpCache, CacheDisabledMode) {
4887 MockHttpCache cache;
4888
4889 // write to the cache
4890 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
4891
4892 // go into disabled mode
4893 cache.http_cache()->set_mode(net::HttpCache::DISABLE);
4894
4895 // force this transaction to write to the cache again
4896 MockTransaction transaction(kSimpleGET_Transaction);
4897
4898 RunTransactionTest(cache.http_cache(), transaction);
4899
4900 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4901 EXPECT_EQ(0, cache.disk_cache()->open_count());
4902 EXPECT_EQ(1, cache.disk_cache()->create_count());
4903 }
4904
4905 // Other tests check that the response headers of the cached response
4906 // get updated on 304. Here we specifically check that the
4907 // HttpResponseHeaders::request_time and HttpResponseHeaders::response_time
4908 // fields also gets updated.
4909 // http://crbug.com/20594.
4910 TEST(HttpCache, UpdatesRequestResponseTimeOn304) {
4911 MockHttpCache cache;
4912
4913 const char* kUrl = "http://foobar";
4914 const char* kData = "body";
4915
4916 MockTransaction mock_network_response = { 0 };
4917 mock_network_response.url = kUrl;
4918
4919 AddMockTransaction(&mock_network_response);
4920
4921 // Request |kUrl|, causing |kNetResponse1| to be written to the cache.
4922
4923 MockTransaction request = { 0 };
4924 request.url = kUrl;
4925 request.method = "GET";
4926 request.request_headers = "";
4927 request.data = kData;
4928
4929 static const Response kNetResponse1 = {
4930 "HTTP/1.1 200 OK",
4931 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
4932 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
4933 kData
4934 };
4935
4936 kNetResponse1.AssignTo(&mock_network_response);
4937
4938 RunTransactionTest(cache.http_cache(), request);
4939
4940 // Request |kUrl| again, this time validating the cache and getting
4941 // a 304 back.
4942
4943 request.load_flags = net::LOAD_VALIDATE_CACHE;
4944
4945 static const Response kNetResponse2 = {
4946 "HTTP/1.1 304 Not Modified",
4947 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n",
4948 ""
4949 };
4950
4951 kNetResponse2.AssignTo(&mock_network_response);
4952
4953 base::Time request_time = base::Time() + base::TimeDelta::FromHours(1234);
4954 base::Time response_time = base::Time() + base::TimeDelta::FromHours(1235);
4955
4956 mock_network_response.request_time = request_time;
4957 mock_network_response.response_time = response_time;
4958
4959 net::HttpResponseInfo response;
4960 RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response);
4961
4962 // The request and response times should have been updated.
4963 EXPECT_EQ(request_time.ToInternalValue(),
4964 response.request_time.ToInternalValue());
4965 EXPECT_EQ(response_time.ToInternalValue(),
4966 response.response_time.ToInternalValue());
4967
4968 std::string headers;
4969 response.headers->GetNormalizedHeaders(&headers);
4970
4971 EXPECT_EQ("HTTP/1.1 200 OK\n"
4972 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
4973 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
4974 headers);
4975
4976 RemoveMockTransaction(&mock_network_response);
4977 }
4978
4979 // Tests that we can write metadata to an entry.
4980 TEST(HttpCache, WriteMetadata_OK) {
4981 MockHttpCache cache;
4982
4983 // Write to the cache
4984 net::HttpResponseInfo response;
4985 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
4986 &response);
4987 EXPECT_TRUE(response.metadata.get() == NULL);
4988
4989 // Trivial call.
4990 cache.http_cache()->WriteMetadata(GURL("foo"), Time::Now(), NULL, 0);
4991
4992 // Write meta data to the same entry.
4993 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50));
4994 memset(buf->data(), 0, buf->size());
4995 base::strlcpy(buf->data(), "Hi there", buf->size());
4996 cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
4997 response.response_time, buf, buf->size());
4998
4999 // Release the buffer before the operation takes place.
5000 buf = NULL;
5001
5002 // Makes sure we finish pending operations.
5003 MessageLoop::current()->RunAllPending();
5004
5005 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
5006 &response);
5007 ASSERT_TRUE(response.metadata.get() != NULL);
5008 EXPECT_EQ(50, response.metadata->size());
5009 EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
5010
5011 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5012 EXPECT_EQ(2, cache.disk_cache()->open_count());
5013 EXPECT_EQ(1, cache.disk_cache()->create_count());
5014 }
5015
5016 // Tests that we only write metadata to an entry if the time stamp matches.
5017 TEST(HttpCache, WriteMetadata_Fail) {
5018 MockHttpCache cache;
5019
5020 // Write to the cache
5021 net::HttpResponseInfo response;
5022 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
5023 &response);
5024 EXPECT_TRUE(response.metadata.get() == NULL);
5025
5026 // Attempt to write meta data to the same entry.
5027 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50));
5028 memset(buf->data(), 0, buf->size());
5029 base::strlcpy(buf->data(), "Hi there", buf->size());
5030 base::Time expected_time = response.response_time -
5031 base::TimeDelta::FromMilliseconds(20);
5032 cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
5033 expected_time, buf, buf->size());
5034
5035 // Makes sure we finish pending operations.
5036 MessageLoop::current()->RunAllPending();
5037
5038 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
5039 &response);
5040 EXPECT_TRUE(response.metadata.get() == NULL);
5041
5042 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5043 EXPECT_EQ(2, cache.disk_cache()->open_count());
5044 EXPECT_EQ(1, cache.disk_cache()->create_count());
5045 }
5046
5047 // Tests that we can read metadata after validating the entry and with READ mode
5048 // transactions.
5049 TEST(HttpCache, ReadMetadata) {
5050 MockHttpCache cache;
5051
5052 // Write to the cache
5053 net::HttpResponseInfo response;
5054 RunTransactionTestWithResponseInfo(cache.http_cache(),
5055 kTypicalGET_Transaction, &response);
5056 EXPECT_TRUE(response.metadata.get() == NULL);
5057
5058 // Write meta data to the same entry.
5059 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50));
5060 memset(buf->data(), 0, buf->size());
5061 base::strlcpy(buf->data(), "Hi there", buf->size());
5062 cache.http_cache()->WriteMetadata(GURL(kTypicalGET_Transaction.url),
5063 response.response_time, buf, buf->size());
5064
5065 // Makes sure we finish pending operations.
5066 MessageLoop::current()->RunAllPending();
5067
5068 // Start with a READ mode transaction.
5069 MockTransaction trans1(kTypicalGET_Transaction);
5070 trans1.load_flags = net::LOAD_ONLY_FROM_CACHE;
5071
5072 RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response);
5073 ASSERT_TRUE(response.metadata.get() != NULL);
5074 EXPECT_EQ(50, response.metadata->size());
5075 EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
5076
5077 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5078 EXPECT_EQ(2, cache.disk_cache()->open_count());
5079 EXPECT_EQ(1, cache.disk_cache()->create_count());
5080 MessageLoop::current()->RunAllPending();
5081
5082 // Now make sure that the entry is re-validated with the server.
5083 trans1.load_flags = net::LOAD_VALIDATE_CACHE;
5084 trans1.status = "HTTP/1.1 304 Not Modified";
5085 AddMockTransaction(&trans1);
5086
5087 response.metadata = NULL;
5088 RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response);
5089 EXPECT_TRUE(response.metadata.get() != NULL);
5090
5091 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5092 EXPECT_EQ(3, cache.disk_cache()->open_count());
5093 EXPECT_EQ(1, cache.disk_cache()->create_count());
5094 MessageLoop::current()->RunAllPending();
5095 RemoveMockTransaction(&trans1);
5096
5097 // Now return 200 when validating the entry so the metadata will be lost.
5098 MockTransaction trans2(kTypicalGET_Transaction);
5099 trans2.load_flags = net::LOAD_VALIDATE_CACHE;
5100 RunTransactionTestWithResponseInfo(cache.http_cache(), trans2, &response);
5101 EXPECT_TRUE(response.metadata.get() == NULL);
5102
5103 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5104 EXPECT_EQ(4, cache.disk_cache()->open_count());
5105 EXPECT_EQ(1, cache.disk_cache()->create_count());
5106 }
5107
5108 // Tests that we don't mark entries as truncated when a filter detects the end
5109 // of the stream.
5110 TEST(HttpCache, FilterCompletion) {
5111 MockHttpCache cache;
5112 TestOldCompletionCallback callback;
5113
5114 {
5115 scoped_ptr<net::HttpTransaction> trans;
5116 int rv = cache.http_cache()->CreateTransaction(&trans);
5117 EXPECT_EQ(net::OK, rv);
5118
5119 MockHttpRequest request(kSimpleGET_Transaction);
5120 rv = trans->Start(&request, &callback, net::BoundNetLog());
5121 EXPECT_EQ(net::OK, callback.GetResult(rv));
5122
5123 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
5124 rv = trans->Read(buf, 256, &callback);
5125 EXPECT_GT(callback.GetResult(rv), 0);
5126
5127 // Now make sure that the entry is preserved.
5128 trans->DoneReading();
5129 }
5130
5131 // Make sure that the ActiveEntry is gone.
5132 MessageLoop::current()->RunAllPending();
5133
5134 // Read from the cache.
5135 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5136
5137 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5138 EXPECT_EQ(1, cache.disk_cache()->open_count());
5139 EXPECT_EQ(1, cache.disk_cache()->create_count());
5140 }
5141
5142 // Tests that we detect truncated rersources from the net when there is
5143 // a Content-Length header.
5144 TEST(HttpCache, TruncatedByContentLength) {
5145 MockHttpCache cache;
5146 TestOldCompletionCallback callback;
5147
5148 MockTransaction transaction(kSimpleGET_Transaction);
5149 AddMockTransaction(&transaction);
5150 transaction.response_headers = "Cache-Control: max-age=10000\n"
5151 "Content-Length: 100\n";
5152 RunTransactionTest(cache.http_cache(), transaction);
5153 RemoveMockTransaction(&transaction);
5154
5155 // Read from the cache.
5156 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5157
5158 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5159 EXPECT_EQ(0, cache.disk_cache()->open_count());
5160 EXPECT_EQ(2, cache.disk_cache()->create_count());
5161 }
5162
5163 // Tests that we actually flag entries as truncated when we detect an error
5164 // from the net.
5165 TEST(HttpCache, TruncatedByContentLength2) {
5166 MockHttpCache cache;
5167 TestOldCompletionCallback callback;
5168
5169 MockTransaction transaction(kSimpleGET_Transaction);
5170 AddMockTransaction(&transaction);
5171 transaction.response_headers = "Cache-Control: max-age=10000\n"
5172 "Content-Length: 100\n"
5173 "Etag: foo\n";
5174 RunTransactionTest(cache.http_cache(), transaction);
5175 RemoveMockTransaction(&transaction);
5176
5177 // Verify that the entry is marked as incomplete.
5178 disk_cache::Entry* entry;
5179 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
5180 net::HttpResponseInfo response;
5181 bool truncated = false;
5182 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5183 EXPECT_TRUE(truncated);
5184 entry->Close();
5185 }
5186
5187 //-----------------------------------------------------------------------------
5188 // DiskCacheBasedSSLHostInfo tests
5189
5190 class DeleteSSLHostInfoOldCompletionCallback : public TestOldCompletionCallback {
5191 public:
5192 explicit DeleteSSLHostInfoOldCompletionCallback(net::SSLHostInfo* ssl_host_inf o)
5193 : ssl_host_info_(ssl_host_info) {}
5194
5195 virtual void RunWithParams(const Tuple1<int>& params) {
5196 delete ssl_host_info_;
5197 TestOldCompletionCallback::RunWithParams(params);
5198 }
5199
5200 private:
5201 net::SSLHostInfo* ssl_host_info_;
5202 };
5203
5204 // Tests that we can delete a DiskCacheBasedSSLHostInfo object in a
5205 // completion callback for DiskCacheBasedSSLHostInfo::WaitForDataReady.
5206 TEST(DiskCacheBasedSSLHostInfo, DeleteInCallback) {
5207 net::CertVerifier cert_verifier;
5208 // Use the blocking mock backend factory to force asynchronous completion
5209 // of ssl_host_info->WaitForDataReady(), so that the callback will run.
5210 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
5211 MockHttpCache cache(factory);
5212 net::SSLConfig ssl_config;
5213 net::SSLHostInfo* ssl_host_info =
5214 new net::DiskCacheBasedSSLHostInfo("https://www.verisign.com", ssl_config,
5215 &cert_verifier, cache.http_cache());
5216 ssl_host_info->Start();
5217 DeleteSSLHostInfoOldCompletionCallback callback(ssl_host_info);
5218 int rv = ssl_host_info->WaitForDataReady(&callback);
5219 EXPECT_EQ(net::ERR_IO_PENDING, rv);
5220 // Now complete the backend creation and let the callback run.
5221 factory->FinishCreation();
5222 EXPECT_EQ(net::OK, callback.GetResult(rv));
5223 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698