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