blob: 153fccdc8c1f1efa3f4ce55ec3722d7dcc1b5b88 [file] [log] [blame]
[email protected]8bf26f49a2009-06-12 17:35:501// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
5#include "net/http/http_cache.h"
6
[email protected]23144032008-09-08 20:51:307#include "base/hash_tables.h"
initial.commit586acc5fe2008-07-26 22:42:528#include "base/message_loop.h"
[email protected]d5b94c72009-10-26 16:51:109#include "base/scoped_vector.h"
initial.commit586acc5fe2008-07-26 22:42:5210#include "base/string_util.h"
11#include "net/base/net_errors.h"
12#include "net/base/load_flags.h"
[email protected]baff44a2009-09-06 00:48:1013#include "net/base/load_log_unittest.h"
[email protected]207d58c72009-09-04 18:59:2914#include "net/base/ssl_cert_request_info.h"
initial.commit586acc5fe2008-07-26 22:42:5215#include "net/disk_cache/disk_cache.h"
[email protected]8bf26f49a2009-06-12 17:35:5016#include "net/http/http_byte_range.h"
initial.commit586acc5fe2008-07-26 22:42:5217#include "net/http/http_request_info.h"
[email protected]95792eb12009-06-22 21:30:4018#include "net/http/http_response_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5219#include "net/http/http_response_info.h"
20#include "net/http/http_transaction.h"
21#include "net/http/http_transaction_unittest.h"
[email protected]8bf26f49a2009-06-12 17:35:5022#include "net/http/http_util.h"
initial.commit586acc5fe2008-07-26 22:42:5223#include "testing/gtest/include/gtest/gtest.h"
24
[email protected]e1acf6f2008-10-27 20:43:3325using base::Time;
26
initial.commit586acc5fe2008-07-26 22:42:5227namespace {
28
29//-----------------------------------------------------------------------------
30// mock disk cache (a very basic memory cache implementation)
31
32class MockDiskEntry : public disk_cache::Entry,
33 public base::RefCounted<MockDiskEntry> {
34 public:
[email protected]e7f29642009-03-02 22:53:1835 MockDiskEntry()
[email protected]06e62ba2009-10-08 23:07:3936 : test_mode_(0), doomed_(false), sparse_(false), fail_requests_(false),
37 busy_(false), delayed_(false) {
initial.commit586acc5fe2008-07-26 22:42:5238 }
39
[email protected]6f40bf72009-07-23 17:52:3740 explicit MockDiskEntry(const std::string& key)
[email protected]06e62ba2009-10-08 23:07:3941 : key_(key), doomed_(false), sparse_(false), fail_requests_(false),
42 busy_(false), delayed_(false) {
[email protected]96bac982009-03-24 18:20:0643 //
44 // 'key' is prefixed with an identifier if it corresponds to a cached POST.
45 // Skip past that to locate the actual URL.
46 //
47 // TODO(darin): It breaks the abstraction a bit that we assume 'key' is an
48 // URL corresponding to a registered MockTransaction. It would be good to
49 // have another way to access the test_mode.
50 //
51 GURL url;
52 if (isdigit(key[0])) {
53 size_t slash = key.find('/');
54 DCHECK(slash != std::string::npos);
55 url = GURL(key.substr(slash + 1));
56 } else {
57 url = GURL(key);
58 }
59 const MockTransaction* t = FindMockTransaction(url);
initial.commit586acc5fe2008-07-26 22:42:5260 DCHECK(t);
61 test_mode_ = t->test_mode;
62 }
63
64 ~MockDiskEntry() {
65 }
66
67 bool is_doomed() const { return doomed_; }
68
69 virtual void Doom() {
70 doomed_ = true;
71 }
72
73 virtual void Close() {
74 Release();
75 }
76
77 virtual std::string GetKey() const {
[email protected]37095fe2009-08-07 00:13:1278 if (fail_requests_)
79 return std::string();
initial.commit586acc5fe2008-07-26 22:42:5280 return key_;
81 }
82
83 virtual Time GetLastUsed() const {
84 return Time::FromInternalValue(0);
85 }
86
87 virtual Time GetLastModified() const {
88 return Time::FromInternalValue(0);
89 }
90
91 virtual int32 GetDataSize(int index) const {
92 DCHECK(index >= 0 && index < 2);
93 return static_cast<int32>(data_[index].size());
94 }
95
[email protected]74a85ce2009-02-12 00:03:1996 virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
initial.commit586acc5fe2008-07-26 22:42:5297 net::CompletionCallback* callback) {
98 DCHECK(index >= 0 && index < 2);
99
[email protected]37095fe2009-08-07 00:13:12100 if (fail_requests_)
101 return net::ERR_CACHE_READ_FAILURE;
102
initial.commit586acc5fe2008-07-26 22:42:52103 if (offset < 0 || offset > static_cast<int>(data_[index].size()))
104 return net::ERR_FAILED;
[email protected]cad155b2008-09-23 14:44:27105 if (static_cast<size_t>(offset) == data_[index].size())
initial.commit586acc5fe2008-07-26 22:42:52106 return 0;
107
108 int num = std::min(buf_len, static_cast<int>(data_[index].size()) - offset);
[email protected]74a85ce2009-02-12 00:03:19109 memcpy(buf->data(), &data_[index][offset], num);
initial.commit586acc5fe2008-07-26 22:42:52110
111 if (!callback || (test_mode_ & TEST_MODE_SYNC_CACHE_READ))
112 return num;
113
114 CallbackLater(callback, num);
115 return net::ERR_IO_PENDING;
116 }
117
[email protected]74a85ce2009-02-12 00:03:19118 virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len,
initial.commit586acc5fe2008-07-26 22:42:52119 net::CompletionCallback* callback, bool truncate) {
120 DCHECK(index >= 0 && index < 2);
121 DCHECK(truncate);
122
[email protected]37095fe2009-08-07 00:13:12123 if (fail_requests_)
124 return net::ERR_CACHE_READ_FAILURE;
125
initial.commit586acc5fe2008-07-26 22:42:52126 if (offset < 0 || offset > static_cast<int>(data_[index].size()))
127 return net::ERR_FAILED;
128
129 data_[index].resize(offset + buf_len);
130 if (buf_len)
[email protected]74a85ce2009-02-12 00:03:19131 memcpy(&data_[index][offset], buf->data(), buf_len);
[email protected]73cae572009-10-22 18:36:19132
133 if (!callback || (test_mode_ & TEST_MODE_SYNC_CACHE_WRITE))
134 return buf_len;
135
136 CallbackLater(callback, buf_len);
137 return net::ERR_IO_PENDING;
initial.commit586acc5fe2008-07-26 22:42:52138 }
139
[email protected]a2068a612009-06-04 21:43:49140 virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
141 net::CompletionCallback* completion_callback) {
[email protected]06e62ba2009-10-08 23:07:39142 if (!sparse_ || busy_)
[email protected]a2068a612009-06-04 21:43:49143 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
144 if (offset < 0)
145 return net::ERR_FAILED;
146
[email protected]37095fe2009-08-07 00:13:12147 if (fail_requests_)
148 return net::ERR_CACHE_READ_FAILURE;
149
[email protected]a2068a612009-06-04 21:43:49150 DCHECK(offset < kint32max);
151 int real_offset = static_cast<int>(offset);
152 if (!buf_len)
153 return 0;
154
155 int num = std::min(static_cast<int>(data_[1].size()) - real_offset,
156 buf_len);
157 memcpy(buf->data(), &data_[1][real_offset], num);
158
159 if (!completion_callback || (test_mode_ & TEST_MODE_SYNC_CACHE_READ))
160 return num;
161
162 CallbackLater(completion_callback, num);
[email protected]06e62ba2009-10-08 23:07:39163 busy_ = true;
164 delayed_ = false;
[email protected]a2068a612009-06-04 21:43:49165 return net::ERR_IO_PENDING;
166 }
167
168 virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
169 net::CompletionCallback* completion_callback) {
[email protected]06e62ba2009-10-08 23:07:39170 if (busy_)
171 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
[email protected]a2068a612009-06-04 21:43:49172 if (!sparse_) {
173 if (data_[1].size())
174 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
175 sparse_ = true;
176 }
177 if (offset < 0)
178 return net::ERR_FAILED;
179 if (!buf_len)
180 return 0;
181
[email protected]37095fe2009-08-07 00:13:12182 if (fail_requests_)
183 return net::ERR_CACHE_READ_FAILURE;
184
[email protected]a2068a612009-06-04 21:43:49185 DCHECK(offset < kint32max);
186 int real_offset = static_cast<int>(offset);
187
188 if (static_cast<int>(data_[1].size()) < real_offset + buf_len)
189 data_[1].resize(real_offset + buf_len);
190
191 memcpy(&data_[1][real_offset], buf->data(), buf_len);
[email protected]73cae572009-10-22 18:36:19192 if (!completion_callback || (test_mode_ & TEST_MODE_SYNC_CACHE_WRITE))
193 return buf_len;
194
195 CallbackLater(completion_callback, buf_len);
196 return net::ERR_IO_PENDING;
[email protected]a2068a612009-06-04 21:43:49197 }
198
199 virtual int GetAvailableRange(int64 offset, int len, int64* start) {
[email protected]06e62ba2009-10-08 23:07:39200 if (!sparse_ || busy_)
[email protected]a2068a612009-06-04 21:43:49201 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
202 if (offset < 0)
203 return net::ERR_FAILED;
204
[email protected]37095fe2009-08-07 00:13:12205 if (fail_requests_)
206 return net::ERR_CACHE_READ_FAILURE;
207
[email protected]a2068a612009-06-04 21:43:49208 *start = offset;
209 DCHECK(offset < kint32max);
210 int real_offset = static_cast<int>(offset);
211 if (static_cast<int>(data_[1].size()) < real_offset)
212 return 0;
213
214 int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len);
215 int count = 0;
216 for (; num > 0; num--, real_offset++) {
217 if (!count) {
218 if (data_[1][real_offset]) {
219 count++;
220 *start = real_offset;
221 }
222 } else {
223 if (!data_[1][real_offset])
224 break;
225 count++;
226 }
227 }
228 return count;
229 }
230
[email protected]06e62ba2009-10-08 23:07:39231 virtual void CancelSparseIO() { cancel_ = true; }
232
233 virtual int ReadyForSparseIO(net::CompletionCallback* completion_callback) {
234 if (!cancel_)
235 return net::OK;
236
237 cancel_ = false;
238 DCHECK(completion_callback);
239 if (test_mode_ & TEST_MODE_SYNC_CACHE_READ)
240 return net::OK;
241
242 // The pending operation is already in the message loop (and hopefuly
243 // already in the second pass). Just notify the caller that it finished.
244 CallbackLater(completion_callback, 0);
245 return net::ERR_IO_PENDING;
246 }
247
[email protected]37095fe2009-08-07 00:13:12248 // Fail most subsequent requests.
249 void set_fail_requests() { fail_requests_ = true; }
250
initial.commit586acc5fe2008-07-26 22:42:52251 private:
252 // Unlike the callbacks for MockHttpTransaction, we want this one to run even
253 // if the consumer called Close on the MockDiskEntry. We achieve that by
254 // leveraging the fact that this class is reference counted.
255 void CallbackLater(net::CompletionCallback* callback, int result) {
256 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
257 &MockDiskEntry::RunCallback, callback, result));
258 }
259 void RunCallback(net::CompletionCallback* callback, int result) {
[email protected]06e62ba2009-10-08 23:07:39260 if (busy_) {
261 // This is kind of hacky, but controlling the behavior of just this entry
262 // from a test is sort of complicated. What we really want to do is
263 // delay the delivery of a sparse IO operation a little more so that the
264 // request start operation (async) will finish without seeing the end of
265 // this operation (already posted to the message loop)... and without
266 // just delaying for n mS (which may cause trouble with slow bots). So
267 // we re-post this operation (all async sparse IO operations will take two
268 // trips trhough the message loop instead of one).
269 if (!delayed_) {
270 delayed_ = true;
271 return CallbackLater(callback, result);
272 }
273 }
274 busy_ = false;
initial.commit586acc5fe2008-07-26 22:42:52275 callback->Run(result);
276 }
277
278 std::string key_;
279 std::vector<char> data_[2];
280 int test_mode_;
281 bool doomed_;
[email protected]a2068a612009-06-04 21:43:49282 bool sparse_;
[email protected]37095fe2009-08-07 00:13:12283 bool fail_requests_;
[email protected]06e62ba2009-10-08 23:07:39284 bool busy_;
285 bool delayed_;
286 static bool cancel_;
initial.commit586acc5fe2008-07-26 22:42:52287};
288
[email protected]06e62ba2009-10-08 23:07:39289// Static.
290bool MockDiskEntry::cancel_ = false;
291
initial.commit586acc5fe2008-07-26 22:42:52292class MockDiskCache : public disk_cache::Backend {
293 public:
[email protected]37095fe2009-08-07 00:13:12294 MockDiskCache()
295 : open_count_(0), create_count_(0), fail_requests_(false),
296 soft_failures_(false) {
initial.commit586acc5fe2008-07-26 22:42:52297 }
298
299 ~MockDiskCache() {
300 EntryMap::iterator it = entries_.begin();
301 for (; it != entries_.end(); ++it)
302 it->second->Release();
303 }
304
305 virtual int32 GetEntryCount() const {
306 return static_cast<int32>(entries_.size());
307 }
308
309 virtual bool OpenEntry(const std::string& key, disk_cache::Entry** entry) {
310 if (fail_requests_)
311 return false;
312
313 EntryMap::iterator it = entries_.find(key);
314 if (it == entries_.end())
315 return false;
316
317 if (it->second->is_doomed()) {
318 it->second->Release();
319 entries_.erase(it);
320 return false;
321 }
322
323 open_count_++;
324
325 it->second->AddRef();
326 *entry = it->second;
327
[email protected]37095fe2009-08-07 00:13:12328 if (soft_failures_)
329 it->second->set_fail_requests();
330
initial.commit586acc5fe2008-07-26 22:42:52331 return true;
332 }
333
334 virtual bool CreateEntry(const std::string& key, disk_cache::Entry** entry) {
335 if (fail_requests_)
336 return false;
337
338 EntryMap::iterator it = entries_.find(key);
339 DCHECK(it == entries_.end());
340
341 create_count_++;
342
343 MockDiskEntry* new_entry = new MockDiskEntry(key);
344
345 new_entry->AddRef();
346 entries_[key] = new_entry;
347
348 new_entry->AddRef();
349 *entry = new_entry;
350
[email protected]37095fe2009-08-07 00:13:12351 if (soft_failures_)
352 new_entry->set_fail_requests();
353
initial.commit586acc5fe2008-07-26 22:42:52354 return true;
355 }
356
357 virtual bool DoomEntry(const std::string& key) {
358 EntryMap::iterator it = entries_.find(key);
359 if (it != entries_.end()) {
360 it->second->Release();
361 entries_.erase(it);
362 }
363 return true;
364 }
365
366 virtual bool DoomAllEntries() {
367 return false;
368 }
369
370 virtual bool DoomEntriesBetween(const Time initial_time,
371 const Time end_time) {
372 return true;
373 }
374
375 virtual bool DoomEntriesSince(const Time initial_time) {
376 return true;
377 }
378
379 virtual bool OpenNextEntry(void** iter, disk_cache::Entry** next_entry) {
380 return false;
381 }
382
383 virtual void EndEnumeration(void** iter) {}
384
385 virtual void GetStats(
386 std::vector<std::pair<std::string, std::string> >* stats) {
387 }
388
389 // returns number of times a cache entry was successfully opened
390 int open_count() const { return open_count_; }
391
392 // returns number of times a cache entry was successfully created
393 int create_count() const { return create_count_; }
394
395 // Fail any subsequent CreateEntry and OpenEntry.
396 void set_fail_requests() { fail_requests_ = true; }
397
[email protected]37095fe2009-08-07 00:13:12398 // Return entries that fail some of their requests.
399 void set_soft_failures(bool value) { soft_failures_ = value; }
400
initial.commit586acc5fe2008-07-26 22:42:52401 private:
[email protected]23144032008-09-08 20:51:30402 typedef base::hash_map<std::string, MockDiskEntry*> EntryMap;
initial.commit586acc5fe2008-07-26 22:42:52403 EntryMap entries_;
404 int open_count_;
405 int create_count_;
406 bool fail_requests_;
[email protected]37095fe2009-08-07 00:13:12407 bool soft_failures_;
initial.commit586acc5fe2008-07-26 22:42:52408};
409
410class MockHttpCache {
411 public:
412 MockHttpCache() : http_cache_(new MockNetworkLayer(), new MockDiskCache()) {
413 }
414
[email protected]7eab0d2262009-10-14 22:05:54415 explicit MockHttpCache(disk_cache::Backend* disk_cache)
416 : http_cache_(new MockNetworkLayer(), disk_cache) {
417 }
418
initial.commit586acc5fe2008-07-26 22:42:52419 net::HttpCache* http_cache() { return &http_cache_; }
420
421 MockNetworkLayer* network_layer() {
422 return static_cast<MockNetworkLayer*>(http_cache_.network_layer());
423 }
424 MockDiskCache* disk_cache() {
425 return static_cast<MockDiskCache*>(http_cache_.disk_cache());
426 }
427
428 private:
429 net::HttpCache http_cache_;
430};
431
432
433//-----------------------------------------------------------------------------
434// helpers
435
436void ReadAndVerifyTransaction(net::HttpTransaction* trans,
437 const MockTransaction& trans_info) {
438 std::string content;
439 int rv = ReadTransaction(trans, &content);
440
441 EXPECT_EQ(net::OK, rv);
[email protected]bded84c2009-07-23 00:36:06442 std::string expected(trans_info.data);
443 EXPECT_EQ(expected, content);
initial.commit586acc5fe2008-07-26 22:42:52444}
445
[email protected]baff44a2009-09-06 00:48:10446void RunTransactionTestWithRequestAndLog(net::HttpCache* cache,
447 const MockTransaction& trans_info,
448 const MockHttpRequest& request,
449 net::HttpResponseInfo* response_info,
450 net::LoadLog* load_log) {
initial.commit586acc5fe2008-07-26 22:42:52451 TestCompletionCallback callback;
452
453 // write to the cache
454
[email protected]1638d602009-09-24 03:49:17455 scoped_ptr<net::HttpTransaction> trans;
456 int rv = cache->CreateTransaction(&trans);
457 EXPECT_EQ(net::OK, rv);
[email protected]af4876d2008-10-21 23:10:57458 ASSERT_TRUE(trans.get());
initial.commit586acc5fe2008-07-26 22:42:52459
[email protected]1638d602009-09-24 03:49:17460 rv = trans->Start(&request, &callback, load_log);
initial.commit586acc5fe2008-07-26 22:42:52461 if (rv == net::ERR_IO_PENDING)
462 rv = callback.WaitForResult();
463 ASSERT_EQ(net::OK, rv);
464
465 const net::HttpResponseInfo* response = trans->GetResponseInfo();
466 ASSERT_TRUE(response);
467
[email protected]207d58c72009-09-04 18:59:29468 if (response_info)
469 *response_info = *response;
[email protected]95792eb12009-06-22 21:30:40470
[email protected]af4876d2008-10-21 23:10:57471 ReadAndVerifyTransaction(trans.get(), trans_info);
initial.commit586acc5fe2008-07-26 22:42:52472}
473
[email protected]baff44a2009-09-06 00:48:10474void RunTransactionTestWithRequest(net::HttpCache* cache,
475 const MockTransaction& trans_info,
476 const MockHttpRequest& request,
477 net::HttpResponseInfo* response_info) {
478 RunTransactionTestWithRequestAndLog(cache, trans_info, request,
479 response_info, NULL);
480}
481
482void RunTransactionTestWithLog(net::HttpCache* cache,
483 const MockTransaction& trans_info,
484 net::LoadLog* log) {
485 RunTransactionTestWithRequestAndLog(
486 cache, trans_info, MockHttpRequest(trans_info), NULL, log);
487}
488
[email protected]96bac982009-03-24 18:20:06489void RunTransactionTest(net::HttpCache* cache,
490 const MockTransaction& trans_info) {
[email protected]baff44a2009-09-06 00:48:10491 RunTransactionTestWithLog(cache, trans_info, NULL);
[email protected]95792eb12009-06-22 21:30:40492}
493
[email protected]207d58c72009-09-04 18:59:29494void RunTransactionTestWithResponseInfo(net::HttpCache* cache,
495 const MockTransaction& trans_info,
496 net::HttpResponseInfo* response) {
497 RunTransactionTestWithRequest(
498 cache, trans_info, MockHttpRequest(trans_info), response);
499}
500
[email protected]95792eb12009-06-22 21:30:40501void RunTransactionTestWithResponse(net::HttpCache* cache,
502 const MockTransaction& trans_info,
503 std::string* response_headers) {
[email protected]207d58c72009-09-04 18:59:29504 net::HttpResponseInfo response;
505 RunTransactionTestWithResponseInfo(cache, trans_info, &response);
506 response.headers->GetNormalizedHeaders(response_headers);
[email protected]96bac982009-03-24 18:20:06507}
508
[email protected]b367d9a52009-02-27 01:02:51509// This class provides a handler for kFastNoStoreGET_Transaction so that the
510// no-store header can be included on demand.
511class FastTransactionServer {
512 public:
513 FastTransactionServer() {
514 no_store = false;
515 }
516 ~FastTransactionServer() {}
517
518 void set_no_store(bool value) { no_store = value; }
519
520 static void FastNoStoreHandler(const net::HttpRequestInfo* request,
521 std::string* response_status,
522 std::string* response_headers,
523 std::string* response_data) {
524 if (no_store)
525 *response_headers = "Cache-Control: no-store\n";
526 }
527
528 private:
529 static bool no_store;
530 DISALLOW_COPY_AND_ASSIGN(FastTransactionServer);
531};
532bool FastTransactionServer::no_store;
533
534const MockTransaction kFastNoStoreGET_Transaction = {
535 "http://www.google.com/nostore",
536 "GET",
[email protected]ca2f19e2009-09-04 22:53:16537 base::Time(),
[email protected]b367d9a52009-02-27 01:02:51538 "",
539 net::LOAD_VALIDATE_CACHE,
540 "HTTP/1.1 200 OK",
541 "Cache-Control: max-age=10000\n",
[email protected]207d58c72009-09-04 18:59:29542 base::Time(),
[email protected]b367d9a52009-02-27 01:02:51543 "<html><body>Google Blah Blah</body></html>",
544 TEST_MODE_SYNC_NET_START,
545 &FastTransactionServer::FastNoStoreHandler,
546 0
547};
548
[email protected]8bf26f49a2009-06-12 17:35:50549// This class provides a handler for kRangeGET_TransactionOK so that the range
550// request can be served on demand.
551class RangeTransactionServer {
552 public:
553 RangeTransactionServer() {
[email protected]e5dad132009-08-18 00:53:41554 not_modified_ = false;
[email protected]a79837892009-08-20 21:18:29555 modified_ = false;
[email protected]8bf26f49a2009-06-12 17:35:50556 }
[email protected]e5dad132009-08-18 00:53:41557 ~RangeTransactionServer() {
558 not_modified_ = false;
[email protected]a79837892009-08-20 21:18:29559 modified_ = false;
[email protected]e5dad132009-08-18 00:53:41560 }
[email protected]8bf26f49a2009-06-12 17:35:50561
[email protected]a79837892009-08-20 21:18:29562 // Returns only 416 or 304 when set.
[email protected]e5dad132009-08-18 00:53:41563 void set_not_modified(bool value) { not_modified_ = value; }
[email protected]8bf26f49a2009-06-12 17:35:50564
[email protected]a79837892009-08-20 21:18:29565 // Returns 206 when revalidating a range (instead of 304).
566 void set_modified(bool value) { modified_ = value; }
567
[email protected]8bf26f49a2009-06-12 17:35:50568 static void RangeHandler(const net::HttpRequestInfo* request,
569 std::string* response_status,
570 std::string* response_headers,
571 std::string* response_data);
572
573 private:
[email protected]e5dad132009-08-18 00:53:41574 static bool not_modified_;
[email protected]a79837892009-08-20 21:18:29575 static bool modified_;
[email protected]8bf26f49a2009-06-12 17:35:50576 DISALLOW_COPY_AND_ASSIGN(RangeTransactionServer);
577};
[email protected]e5dad132009-08-18 00:53:41578bool RangeTransactionServer::not_modified_ = false;
[email protected]a79837892009-08-20 21:18:29579bool RangeTransactionServer::modified_ = false;
[email protected]8bf26f49a2009-06-12 17:35:50580
[email protected]e75e8af2009-11-03 00:04:20581// A dummy extra header that must be preserved on a given request.
582// TODO(rvargas): Add tests using this without byte ranges.
583#define EXTRA_HEADER "Extra: header\r\n"
584
[email protected]8bf26f49a2009-06-12 17:35:50585// Static.
586void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request,
587 std::string* response_status,
588 std::string* response_headers,
589 std::string* response_data) {
[email protected]44f873a62009-08-12 00:14:48590 if (request->extra_headers.empty()) {
591 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
[email protected]8bf26f49a2009-06-12 17:35:50592 return;
[email protected]44f873a62009-08-12 00:14:48593 }
[email protected]8bf26f49a2009-06-12 17:35:50594
[email protected]e75e8af2009-11-03 00:04:20595 // We want to make sure we don't delete extra headers.
596 if (request->extra_headers.find(EXTRA_HEADER) == std::string::npos) {
597 response_status->assign("HTTP/1.1 403 Forbidden");
598 return;
599 }
600
[email protected]e5dad132009-08-18 00:53:41601 if (not_modified_) {
602 response_status->assign("HTTP/1.1 304 Not Modified");
603 return;
604 }
605
[email protected]8bf26f49a2009-06-12 17:35:50606 std::vector<net::HttpByteRange> ranges;
607 if (!net::HttpUtil::ParseRanges(request->extra_headers, &ranges) ||
608 ranges.size() != 1)
609 return;
610 // We can handle this range request.
611 net::HttpByteRange byte_range = ranges[0];
[email protected]e5dad132009-08-18 00:53:41612 if (byte_range.first_byte_position() > 79) {
613 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
614 return;
615 }
616
[email protected]8bf26f49a2009-06-12 17:35:50617 EXPECT_TRUE(byte_range.ComputeBounds(80));
618 int start = static_cast<int>(byte_range.first_byte_position());
619 int end = static_cast<int>(byte_range.last_byte_position());
620
621 EXPECT_LT(end, 80);
622
623 std::string content_range = StringPrintf("Content-Range: bytes %d-%d/80\n",
624 start, end);
625 response_headers->append(content_range);
626
[email protected]a79837892009-08-20 21:18:29627 if (request->extra_headers.find("If-None-Match") == std::string::npos ||
628 modified_) {
[email protected]44f873a62009-08-12 00:14:48629 EXPECT_EQ(9, (end - start) % 10);
630 std::string data;
631 for (int block_start = start; block_start < end; block_start += 10)
632 StringAppendF(&data, "rg: %02d-%02d ", block_start, block_start + 9);
[email protected]8bf26f49a2009-06-12 17:35:50633 *response_data = data;
[email protected]44f873a62009-08-12 00:14:48634
635 if (end - start != 9) {
636 // We also have to fix content-length.
637 int len = end - start + 1;
638 EXPECT_EQ(0, len % 10);
639 std::string content_length = StringPrintf("Content-Length: %d\n", len);
640 response_headers->replace(response_headers->find("Content-Length:"),
641 content_length.size(), content_length);
642 }
[email protected]8bf26f49a2009-06-12 17:35:50643 } else {
644 response_status->assign("HTTP/1.1 304 Not Modified");
645 response_data->clear();
646 }
647}
648
649const MockTransaction kRangeGET_TransactionOK = {
650 "http://www.google.com/range",
651 "GET",
[email protected]ca2f19e2009-09-04 22:53:16652 base::Time(),
[email protected]e75e8af2009-11-03 00:04:20653 "Range: bytes = 40-49\r\n"
654 EXTRA_HEADER,
[email protected]8bf26f49a2009-06-12 17:35:50655 net::LOAD_NORMAL,
656 "HTTP/1.1 206 Partial Content",
657 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
658 "ETag: \"foo\"\n"
659 "Accept-Ranges: bytes\n"
660 "Content-Length: 10\n",
[email protected]207d58c72009-09-04 18:59:29661 base::Time(),
[email protected]8bf26f49a2009-06-12 17:35:50662 "rg: 40-49 ",
663 TEST_MODE_NORMAL,
664 &RangeTransactionServer::RangeHandler,
665 0
666};
667
[email protected]95792eb12009-06-22 21:30:40668// Returns true if the response headers (|response|) match a partial content
669// response for the range starting at |start| and ending at |end|.
670bool Verify206Response(std::string response, int start, int end) {
671 std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(),
672 response.size()));
673 scoped_refptr<net::HttpResponseHeaders> headers =
674 new net::HttpResponseHeaders(raw_headers);
675
676 if (206 != headers->response_code())
677 return false;
678
679 int64 range_start, range_end, object_size;
680 if (!headers->GetContentRange(&range_start, &range_end, &object_size))
681 return false;
682 int64 content_length = headers->GetContentLength();
683
684 int length = end - start + 1;
685 if (content_length != length)
686 return false;
687
688 if (range_start != start)
689 return false;
690
691 if (range_end != end)
692 return false;
693
694 return true;
695}
696
[email protected]bded84c2009-07-23 00:36:06697// Helper to represent a network HTTP response.
698struct Response {
699 // Set this response into |trans|.
700 void AssignTo(MockTransaction* trans) const {
701 trans->status = status;
702 trans->response_headers = headers;
703 trans->data = body;
704 }
705
706 std::string status_and_headers() const {
707 return std::string(status) + "\n" + std::string(headers);
708 }
709
710 const char* status;
711 const char* headers;
712 const char* body;
713};
714
[email protected]73cae572009-10-22 18:36:19715struct Context {
716 Context() : result(net::ERR_IO_PENDING) {}
717
718 int result;
719 TestCompletionCallback callback;
720 scoped_ptr<net::HttpTransaction> trans;
721};
722
initial.commit586acc5fe2008-07-26 22:42:52723} // namespace
724
725
726//-----------------------------------------------------------------------------
727// tests
728
729
730TEST(HttpCache, CreateThenDestroy) {
731 MockHttpCache cache;
732
[email protected]1638d602009-09-24 03:49:17733 scoped_ptr<net::HttpTransaction> trans;
734 int rv = cache.http_cache()->CreateTransaction(&trans);
735 EXPECT_EQ(net::OK, rv);
[email protected]af4876d2008-10-21 23:10:57736 ASSERT_TRUE(trans.get());
initial.commit586acc5fe2008-07-26 22:42:52737}
738
739TEST(HttpCache, SimpleGET) {
740 MockHttpCache cache;
741
742 // write to the cache
743 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
744
745 EXPECT_EQ(1, cache.network_layer()->transaction_count());
746 EXPECT_EQ(0, cache.disk_cache()->open_count());
747 EXPECT_EQ(1, cache.disk_cache()->create_count());
748}
749
750TEST(HttpCache, SimpleGETNoDiskCache) {
751 MockHttpCache cache;
752
753 cache.disk_cache()->set_fail_requests();
754
[email protected]baff44a2009-09-06 00:48:10755 scoped_refptr<net::LoadLog> log(new net::LoadLog);
756
initial.commit586acc5fe2008-07-26 22:42:52757 // Read from the network, and don't use the cache.
[email protected]baff44a2009-09-06 00:48:10758 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction, log);
759
760 // Check that the LoadLog was filled as expected.
761 // (We attempted to both Open and Create entries, but both failed).
762 EXPECT_EQ(4u, log->events().size());
763 net::ExpectLogContains(log, 0, net::LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY,
764 net::LoadLog::PHASE_BEGIN);
765 net::ExpectLogContains(log, 1, net::LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY,
766 net::LoadLog::PHASE_END);
767 net::ExpectLogContains(log, 2, net::LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY,
768 net::LoadLog::PHASE_BEGIN);
769 net::ExpectLogContains(log, 3, net::LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY,
770 net::LoadLog::PHASE_END);
initial.commit586acc5fe2008-07-26 22:42:52771
772 EXPECT_EQ(1, cache.network_layer()->transaction_count());
773 EXPECT_EQ(0, cache.disk_cache()->open_count());
774 EXPECT_EQ(0, cache.disk_cache()->create_count());
775}
776
[email protected]37095fe2009-08-07 00:13:12777TEST(HttpCache, SimpleGETWithDiskFailures) {
778 MockHttpCache cache;
779
780 cache.disk_cache()->set_soft_failures(true);
781
782 // Read from the network, and fail to write to the cache.
783 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
784
785 EXPECT_EQ(1, cache.network_layer()->transaction_count());
786 EXPECT_EQ(0, cache.disk_cache()->open_count());
787 EXPECT_EQ(1, cache.disk_cache()->create_count());
788
789 // This one should see an empty cache again.
790 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
791
792 EXPECT_EQ(2, cache.network_layer()->transaction_count());
793 EXPECT_EQ(0, cache.disk_cache()->open_count());
794 EXPECT_EQ(2, cache.disk_cache()->create_count());
795}
796
[email protected]73cae572009-10-22 18:36:19797// Tests that disk failures after the transaction has started don't cause the
798// request to fail.
799TEST(HttpCache, SimpleGETWithDiskFailures2) {
800 MockHttpCache cache;
801
802 MockHttpRequest request(kSimpleGET_Transaction);
803
804 scoped_ptr<Context> c(new Context());
805 int rv = cache.http_cache()->CreateTransaction(&c->trans);
806 EXPECT_EQ(net::OK, rv);
807
808 rv = c->trans->Start(&request, &c->callback, NULL);
809 EXPECT_EQ(net::ERR_IO_PENDING, rv);
810 rv = c->callback.WaitForResult();
811
812 // Start failing request now.
813 cache.disk_cache()->set_soft_failures(true);
814
815 // We have to open the entry again to propagate the failure flag.
816 disk_cache::Entry* en;
817 ASSERT_TRUE(cache.disk_cache()->OpenEntry(kSimpleGET_Transaction.url, &en));
818 en->Close();
819
820 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
821 c.reset();
822
823 EXPECT_EQ(1, cache.network_layer()->transaction_count());
824 EXPECT_EQ(1, cache.disk_cache()->open_count());
825 EXPECT_EQ(1, cache.disk_cache()->create_count());
826
827 // This one should see an empty cache again.
828 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
829
830 EXPECT_EQ(2, cache.network_layer()->transaction_count());
831 EXPECT_EQ(1, cache.disk_cache()->open_count());
832 EXPECT_EQ(2, cache.disk_cache()->create_count());
833}
834
initial.commit586acc5fe2008-07-26 22:42:52835TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
836 MockHttpCache cache;
837
[email protected]baff44a2009-09-06 00:48:10838 scoped_refptr<net::LoadLog> log(new net::LoadLog);
839
initial.commit586acc5fe2008-07-26 22:42:52840 // write to the cache
[email protected]baff44a2009-09-06 00:48:10841 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction, log);
842
843 // Check that the LoadLog was filled as expected.
844 EXPECT_EQ(6u, log->events().size());
845 net::ExpectLogContains(log, 0, net::LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY,
846 net::LoadLog::PHASE_BEGIN);
847 net::ExpectLogContains(log, 1, net::LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY,
848 net::LoadLog::PHASE_END);
849 net::ExpectLogContains(log, 2, net::LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY,
850 net::LoadLog::PHASE_BEGIN);
851 net::ExpectLogContains(log, 3, net::LoadLog::TYPE_HTTP_CACHE_CREATE_ENTRY,
852 net::LoadLog::PHASE_END);
853 net::ExpectLogContains(log, 4, net::LoadLog::TYPE_HTTP_CACHE_WAITING,
854 net::LoadLog::PHASE_BEGIN);
855 net::ExpectLogContains(log, 5, net::LoadLog::TYPE_HTTP_CACHE_WAITING,
856 net::LoadLog::PHASE_END);
initial.commit586acc5fe2008-07-26 22:42:52857
858 // force this transaction to read from the cache
859 MockTransaction transaction(kSimpleGET_Transaction);
860 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
861
[email protected]baff44a2009-09-06 00:48:10862 log = new net::LoadLog;
863
864 RunTransactionTestWithLog(cache.http_cache(), transaction, log);
865
866 // Check that the LoadLog was filled as expected.
867 EXPECT_EQ(6u, log->events().size());
868 net::ExpectLogContains(log, 0, net::LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY,
869 net::LoadLog::PHASE_BEGIN);
870 net::ExpectLogContains(log, 1, net::LoadLog::TYPE_HTTP_CACHE_OPEN_ENTRY,
871 net::LoadLog::PHASE_END);
872 net::ExpectLogContains(log, 2, net::LoadLog::TYPE_HTTP_CACHE_WAITING,
873 net::LoadLog::PHASE_BEGIN);
874 net::ExpectLogContains(log, 3, net::LoadLog::TYPE_HTTP_CACHE_WAITING,
875 net::LoadLog::PHASE_END);
876 net::ExpectLogContains(log, 4, net::LoadLog::TYPE_HTTP_CACHE_READ_INFO,
877 net::LoadLog::PHASE_BEGIN);
878 net::ExpectLogContains(log, 5, net::LoadLog::TYPE_HTTP_CACHE_READ_INFO,
879 net::LoadLog::PHASE_END);
initial.commit586acc5fe2008-07-26 22:42:52880
881 EXPECT_EQ(1, cache.network_layer()->transaction_count());
882 EXPECT_EQ(1, cache.disk_cache()->open_count());
883 EXPECT_EQ(1, cache.disk_cache()->create_count());
884}
885
886TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Miss) {
887 MockHttpCache cache;
888
889 // force this transaction to read from the cache
890 MockTransaction transaction(kSimpleGET_Transaction);
891 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
892
893 MockHttpRequest request(transaction);
894 TestCompletionCallback callback;
895
[email protected]1638d602009-09-24 03:49:17896 scoped_ptr<net::HttpTransaction> trans;
897 int rv = cache.http_cache()->CreateTransaction(&trans);
898 EXPECT_EQ(net::OK, rv);
[email protected]af4876d2008-10-21 23:10:57899 ASSERT_TRUE(trans.get());
initial.commit586acc5fe2008-07-26 22:42:52900
[email protected]1638d602009-09-24 03:49:17901 rv = trans->Start(&request, &callback, NULL);
initial.commit586acc5fe2008-07-26 22:42:52902 if (rv == net::ERR_IO_PENDING)
903 rv = callback.WaitForResult();
904 ASSERT_EQ(net::ERR_CACHE_MISS, rv);
905
[email protected]af4876d2008-10-21 23:10:57906 trans.reset();
initial.commit586acc5fe2008-07-26 22:42:52907
908 EXPECT_EQ(0, cache.network_layer()->transaction_count());
909 EXPECT_EQ(0, cache.disk_cache()->open_count());
910 EXPECT_EQ(0, cache.disk_cache()->create_count());
911}
912
913TEST(HttpCache, SimpleGET_LoadPreferringCache_Hit) {
914 MockHttpCache cache;
915
916 // write to the cache
917 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
918
919 // force this transaction to read from the cache if valid
920 MockTransaction transaction(kSimpleGET_Transaction);
921 transaction.load_flags |= net::LOAD_PREFERRING_CACHE;
922
923 RunTransactionTest(cache.http_cache(), transaction);
924
925 EXPECT_EQ(1, cache.network_layer()->transaction_count());
926 EXPECT_EQ(1, cache.disk_cache()->open_count());
927 EXPECT_EQ(1, cache.disk_cache()->create_count());
928}
929
930TEST(HttpCache, SimpleGET_LoadPreferringCache_Miss) {
931 MockHttpCache cache;
932
933 // force this transaction to read from the cache if valid
934 MockTransaction transaction(kSimpleGET_Transaction);
935 transaction.load_flags |= net::LOAD_PREFERRING_CACHE;
936
937 RunTransactionTest(cache.http_cache(), transaction);
938
939 EXPECT_EQ(1, cache.network_layer()->transaction_count());
940 EXPECT_EQ(0, cache.disk_cache()->open_count());
941 EXPECT_EQ(1, cache.disk_cache()->create_count());
942}
943
944TEST(HttpCache, SimpleGET_LoadBypassCache) {
945 MockHttpCache cache;
946
947 // write to the cache
948 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
949
950 // force this transaction to write to the cache again
951 MockTransaction transaction(kSimpleGET_Transaction);
952 transaction.load_flags |= net::LOAD_BYPASS_CACHE;
953
954 RunTransactionTest(cache.http_cache(), transaction);
955
956 EXPECT_EQ(2, cache.network_layer()->transaction_count());
957 EXPECT_EQ(0, cache.disk_cache()->open_count());
958 EXPECT_EQ(2, cache.disk_cache()->create_count());
959}
960
961TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit) {
962 MockHttpCache cache;
963
964 // write to the cache
965 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
966
967 // force this transaction to write to the cache again
968 MockTransaction transaction(kSimpleGET_Transaction);
969 transaction.request_headers = "pragma: no-cache";
970
971 RunTransactionTest(cache.http_cache(), transaction);
972
973 EXPECT_EQ(2, cache.network_layer()->transaction_count());
974 EXPECT_EQ(0, cache.disk_cache()->open_count());
975 EXPECT_EQ(2, cache.disk_cache()->create_count());
976}
977
978TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit2) {
979 MockHttpCache cache;
980
981 // write to the cache
982 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
983
984 // force this transaction to write to the cache again
985 MockTransaction transaction(kSimpleGET_Transaction);
986 transaction.request_headers = "cache-control: no-cache";
987
988 RunTransactionTest(cache.http_cache(), transaction);
989
990 EXPECT_EQ(2, cache.network_layer()->transaction_count());
991 EXPECT_EQ(0, cache.disk_cache()->open_count());
992 EXPECT_EQ(2, cache.disk_cache()->create_count());
993}
994
995TEST(HttpCache, SimpleGET_LoadValidateCache) {
996 MockHttpCache cache;
997
998 // write to the cache
999 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1000
1001 // read from the cache
1002 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1003
1004 // force this transaction to validate the cache
1005 MockTransaction transaction(kSimpleGET_Transaction);
1006 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
1007
1008 RunTransactionTest(cache.http_cache(), transaction);
1009
1010 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1011 EXPECT_EQ(1, cache.disk_cache()->open_count());
1012 EXPECT_EQ(1, cache.disk_cache()->create_count());
1013}
1014
1015TEST(HttpCache, SimpleGET_LoadValidateCache_Implicit) {
1016 MockHttpCache cache;
1017
1018 // write to the cache
1019 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1020
1021 // read from the cache
1022 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1023
1024 // force this transaction to validate the cache
1025 MockTransaction transaction(kSimpleGET_Transaction);
1026 transaction.request_headers = "cache-control: max-age=0";
1027
1028 RunTransactionTest(cache.http_cache(), transaction);
1029
1030 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1031 EXPECT_EQ(1, cache.disk_cache()->open_count());
1032 EXPECT_EQ(1, cache.disk_cache()->create_count());
1033}
1034
initial.commit586acc5fe2008-07-26 22:42:521035TEST(HttpCache, SimpleGET_ManyReaders) {
1036 MockHttpCache cache;
1037
1038 MockHttpRequest request(kSimpleGET_Transaction);
1039
initial.commit586acc5fe2008-07-26 22:42:521040 std::vector<Context*> context_list;
1041 const int kNumTransactions = 5;
1042
1043 for (int i = 0; i < kNumTransactions; ++i) {
[email protected]1638d602009-09-24 03:49:171044 context_list.push_back(new Context());
initial.commit586acc5fe2008-07-26 22:42:521045 Context* c = context_list[i];
[email protected]1638d602009-09-24 03:49:171046
1047 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1048 EXPECT_EQ(net::OK, c->result);
1049
1050 c->result = c->trans->Start(&request, &c->callback, NULL);
initial.commit586acc5fe2008-07-26 22:42:521051 }
1052
1053 // the first request should be a writer at this point, and the subsequent
1054 // requests should be pending.
1055
1056 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1057 EXPECT_EQ(0, cache.disk_cache()->open_count());
1058 EXPECT_EQ(1, cache.disk_cache()->create_count());
1059
1060 for (int i = 0; i < kNumTransactions; ++i) {
1061 Context* c = context_list[i];
1062 if (c->result == net::ERR_IO_PENDING)
1063 c->result = c->callback.WaitForResult();
[email protected]af4876d2008-10-21 23:10:571064 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
initial.commit586acc5fe2008-07-26 22:42:521065 }
1066
1067 // we should not have had to re-open the disk entry
1068
1069 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1070 EXPECT_EQ(0, cache.disk_cache()->open_count());
1071 EXPECT_EQ(1, cache.disk_cache()->create_count());
1072
1073 for (int i = 0; i < kNumTransactions; ++i) {
1074 Context* c = context_list[i];
initial.commit586acc5fe2008-07-26 22:42:521075 delete c;
1076 }
1077}
1078
[email protected]e1891642009-01-07 18:30:571079// This is a test for http://code.google.com/p/chromium/issues/detail?id=4769.
1080// If cancelling a request is racing with another request for the same resource
1081// finishing, we have to make sure that we remove both transactions from the
1082// entry.
1083TEST(HttpCache, SimpleGET_RacingReaders) {
1084 MockHttpCache cache;
1085
1086 MockHttpRequest request(kSimpleGET_Transaction);
1087 MockHttpRequest reader_request(kSimpleGET_Transaction);
1088 reader_request.load_flags = net::LOAD_ONLY_FROM_CACHE;
1089
1090 std::vector<Context*> context_list;
1091 const int kNumTransactions = 5;
1092
1093 for (int i = 0; i < kNumTransactions; ++i) {
[email protected]1638d602009-09-24 03:49:171094 context_list.push_back(new Context());
[email protected]e1891642009-01-07 18:30:571095 Context* c = context_list[i];
[email protected]1638d602009-09-24 03:49:171096
1097 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1098 EXPECT_EQ(net::OK, c->result);
1099
[email protected]e1891642009-01-07 18:30:571100 MockHttpRequest* this_request = &request;
1101 if (i == 1 || i == 2)
1102 this_request = &reader_request;
1103
[email protected]1638d602009-09-24 03:49:171104 c->result = c->trans->Start(this_request, &c->callback, NULL);
[email protected]e1891642009-01-07 18:30:571105 }
1106
1107 // The first request should be a writer at this point, and the subsequent
1108 // requests should be pending.
1109
1110 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1111 EXPECT_EQ(0, cache.disk_cache()->open_count());
1112 EXPECT_EQ(1, cache.disk_cache()->create_count());
1113
1114 Context* c = context_list[0];
1115 ASSERT_EQ(net::ERR_IO_PENDING, c->result);
1116 c->result = c->callback.WaitForResult();
1117 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1118
1119 // Now we have 2 active readers and two queued transactions.
1120
1121 c = context_list[1];
1122 ASSERT_EQ(net::ERR_IO_PENDING, c->result);
1123 c->result = c->callback.WaitForResult();
[email protected]37095fe2009-08-07 00:13:121124 if (c->result == net::OK)
1125 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
[email protected]e1891642009-01-07 18:30:571126
1127 // At this point we have one reader, two pending transactions and a task on
1128 // the queue to move to the next transaction. Now we cancel the request that
1129 // is the current reader, and expect the queued task to be able to start the
1130 // next request.
1131
1132 c = context_list[2];
1133 c->trans.reset();
1134
1135 for (int i = 3; i < kNumTransactions; ++i) {
1136 Context* c = context_list[i];
1137 if (c->result == net::ERR_IO_PENDING)
1138 c->result = c->callback.WaitForResult();
[email protected]37095fe2009-08-07 00:13:121139 if (c->result == net::OK)
1140 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
[email protected]e1891642009-01-07 18:30:571141 }
1142
1143 // We should not have had to re-open the disk entry.
1144
1145 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1146 EXPECT_EQ(0, cache.disk_cache()->open_count());
1147 EXPECT_EQ(1, cache.disk_cache()->create_count());
1148
1149 for (int i = 0; i < kNumTransactions; ++i) {
1150 Context* c = context_list[i];
1151 delete c;
1152 }
1153}
1154
[email protected]d5b94c72009-10-26 16:51:101155// Tests that we can doom an entry with pending transactions and delete one of
1156// the pending transactions before the first one completes.
1157// See http://code.google.com/p/chromium/issues/detail?id=25588
1158TEST(HttpCache, SimpleGET_DoomWithPending) {
1159 // We need simultaneous doomed / not_doomed entries so let's use a real cache.
1160 disk_cache::Backend* disk_cache =
1161 disk_cache::CreateInMemoryCacheBackend(1024 * 1024);
1162 MockHttpCache cache(disk_cache);
1163
1164 MockHttpRequest request(kSimpleGET_Transaction);
1165 MockHttpRequest writer_request(kSimpleGET_Transaction);
1166 writer_request.load_flags = net::LOAD_BYPASS_CACHE;
1167
1168 ScopedVector<Context> context_list;
1169 const int kNumTransactions = 4;
1170
1171 for (int i = 0; i < kNumTransactions; ++i) {
1172 context_list.push_back(new Context());
1173 Context* c = context_list[i];
1174
1175 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1176 EXPECT_EQ(net::OK, c->result);
1177
1178 MockHttpRequest* this_request = &request;
1179 if (i == 3)
1180 this_request = &writer_request;
1181
1182 c->result = c->trans->Start(this_request, &c->callback, NULL);
1183 }
1184
1185 // The first request should be a writer at this point, and the two subsequent
1186 // requests should be pending. The last request doomed the first entry.
1187
1188 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1189
1190 // Cancel the first queued transaction.
1191 delete context_list[1];
1192 context_list.get()[1] = NULL;
1193
1194 for (int i = 0; i < kNumTransactions; ++i) {
1195 if (i == 1)
1196 continue;
1197 Context* c = context_list[i];
1198 ASSERT_EQ(net::ERR_IO_PENDING, c->result);
1199 c->result = c->callback.WaitForResult();
1200 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1201 }
1202}
1203
[email protected]b367d9a52009-02-27 01:02:511204// This is a test for http://code.google.com/p/chromium/issues/detail?id=4731.
1205// We may attempt to delete an entry synchronously with the act of adding a new
1206// transaction to said entry.
1207TEST(HttpCache, FastNoStoreGET_DoneWithPending) {
1208 MockHttpCache cache;
1209
1210 // The headers will be served right from the call to Start() the request.
1211 MockHttpRequest request(kFastNoStoreGET_Transaction);
1212 FastTransactionServer request_handler;
1213 AddMockTransaction(&kFastNoStoreGET_Transaction);
1214
1215 std::vector<Context*> context_list;
1216 const int kNumTransactions = 3;
1217
1218 for (int i = 0; i < kNumTransactions; ++i) {
[email protected]1638d602009-09-24 03:49:171219 context_list.push_back(new Context());
[email protected]b367d9a52009-02-27 01:02:511220 Context* c = context_list[i];
[email protected]1638d602009-09-24 03:49:171221
1222 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1223 EXPECT_EQ(net::OK, c->result);
1224
1225 c->result = c->trans->Start(&request, &c->callback, NULL);
[email protected]b367d9a52009-02-27 01:02:511226 }
1227
1228 // The first request should be a writer at this point, and the subsequent
1229 // requests should be pending.
1230
1231 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1232 EXPECT_EQ(0, cache.disk_cache()->open_count());
1233 EXPECT_EQ(1, cache.disk_cache()->create_count());
1234
1235 // Now, make sure that the second request asks for the entry not to be stored.
1236 request_handler.set_no_store(true);
1237
1238 for (int i = 0; i < kNumTransactions; ++i) {
1239 Context* c = context_list[i];
1240 if (c->result == net::ERR_IO_PENDING)
1241 c->result = c->callback.WaitForResult();
1242 ReadAndVerifyTransaction(c->trans.get(), kFastNoStoreGET_Transaction);
1243 delete c;
1244 }
1245
1246 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1247 EXPECT_EQ(0, cache.disk_cache()->open_count());
1248 EXPECT_EQ(2, cache.disk_cache()->create_count());
1249
1250 RemoveMockTransaction(&kFastNoStoreGET_Transaction);
1251}
1252
initial.commit586acc5fe2008-07-26 22:42:521253TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) {
1254 MockHttpCache cache;
1255
1256 MockHttpRequest request(kSimpleGET_Transaction);
1257
initial.commit586acc5fe2008-07-26 22:42:521258 std::vector<Context*> context_list;
1259 const int kNumTransactions = 2;
1260
1261 for (int i = 0; i < kNumTransactions; ++i) {
[email protected]1638d602009-09-24 03:49:171262 context_list.push_back(new Context());
initial.commit586acc5fe2008-07-26 22:42:521263 Context* c = context_list[i];
[email protected]1638d602009-09-24 03:49:171264
1265 c->result = cache.http_cache()->CreateTransaction(&c->trans);
1266 EXPECT_EQ(net::OK, c->result);
1267
1268 c->result = c->trans->Start(&request, &c->callback, NULL);
initial.commit586acc5fe2008-07-26 22:42:521269 }
1270
1271 // the first request should be a writer at this point, and the subsequent
1272 // requests should be pending.
1273
1274 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1275 EXPECT_EQ(0, cache.disk_cache()->open_count());
1276 EXPECT_EQ(1, cache.disk_cache()->create_count());
1277
1278 for (int i = 0; i < kNumTransactions; ++i) {
1279 Context* c = context_list[i];
1280 if (c->result == net::ERR_IO_PENDING)
1281 c->result = c->callback.WaitForResult();
1282 // destroy only the first transaction
1283 if (i == 0) {
initial.commit586acc5fe2008-07-26 22:42:521284 delete c;
1285 context_list[i] = NULL;
1286 }
1287 }
1288
1289 // complete the rest of the transactions
1290 for (int i = 1; i < kNumTransactions; ++i) {
1291 Context* c = context_list[i];
[email protected]af4876d2008-10-21 23:10:571292 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
initial.commit586acc5fe2008-07-26 22:42:521293 }
1294
1295 // we should have had to re-open the disk entry
1296
1297 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1298 EXPECT_EQ(0, cache.disk_cache()->open_count());
1299 EXPECT_EQ(2, cache.disk_cache()->create_count());
1300
1301 for (int i = 1; i < kNumTransactions; ++i) {
1302 Context* c = context_list[i];
initial.commit586acc5fe2008-07-26 22:42:521303 delete c;
1304 }
1305}
1306
1307TEST(HttpCache, SimpleGET_AbandonedCacheRead) {
1308 MockHttpCache cache;
1309
1310 // write to the cache
1311 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1312
1313 MockHttpRequest request(kSimpleGET_Transaction);
1314 TestCompletionCallback callback;
1315
[email protected]1638d602009-09-24 03:49:171316 scoped_ptr<net::HttpTransaction> trans;
1317 int rv = cache.http_cache()->CreateTransaction(&trans);
1318 EXPECT_EQ(net::OK, rv);
1319 rv = trans->Start(&request, &callback, NULL);
initial.commit586acc5fe2008-07-26 22:42:521320 if (rv == net::ERR_IO_PENDING)
1321 rv = callback.WaitForResult();
1322 ASSERT_EQ(net::OK, rv);
1323
[email protected]9dea9e1f2009-01-29 00:30:471324 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(256);
1325 rv = trans->Read(buf, 256, &callback);
initial.commit586acc5fe2008-07-26 22:42:521326 EXPECT_EQ(net::ERR_IO_PENDING, rv);
1327
1328 // Test that destroying the transaction while it is reading from the cache
1329 // works properly.
[email protected]af4876d2008-10-21 23:10:571330 trans.reset();
initial.commit586acc5fe2008-07-26 22:42:521331
1332 // Make sure we pump any pending events, which should include a call to
1333 // HttpCache::Transaction::OnCacheReadCompleted.
[email protected]295039bd2008-08-15 04:32:571334 MessageLoop::current()->RunAllPending();
initial.commit586acc5fe2008-07-26 22:42:521335}
1336
1337TEST(HttpCache, TypicalGET_ConditionalRequest) {
1338 MockHttpCache cache;
1339
1340 // write to the cache
1341 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
1342
1343 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1344 EXPECT_EQ(0, cache.disk_cache()->open_count());
1345 EXPECT_EQ(1, cache.disk_cache()->create_count());
1346
1347 // get the same URL again, but this time we expect it to result
1348 // in a conditional request.
1349 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
1350
1351 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1352 EXPECT_EQ(1, cache.disk_cache()->open_count());
1353 EXPECT_EQ(1, cache.disk_cache()->create_count());
1354}
1355
1356static void ETagGet_ConditionalRequest_Handler(
1357 const net::HttpRequestInfo* request,
1358 std::string* response_status,
1359 std::string* response_headers,
1360 std::string* response_data) {
[email protected]72d1e592009-03-10 17:39:461361 EXPECT_TRUE(request->extra_headers.find("If-None-Match") !=
1362 std::string::npos);
initial.commit586acc5fe2008-07-26 22:42:521363 response_status->assign("HTTP/1.1 304 Not Modified");
1364 response_headers->assign(kETagGET_Transaction.response_headers);
1365 response_data->clear();
1366}
1367
1368TEST(HttpCache, ETagGET_ConditionalRequest_304) {
1369 MockHttpCache cache;
1370
1371 ScopedMockTransaction transaction(kETagGET_Transaction);
1372
1373 // write to the cache
1374 RunTransactionTest(cache.http_cache(), transaction);
1375
1376 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1377 EXPECT_EQ(0, cache.disk_cache()->open_count());
1378 EXPECT_EQ(1, cache.disk_cache()->create_count());
1379
1380 // get the same URL again, but this time we expect it to result
1381 // in a conditional request.
1382 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
1383 transaction.handler = ETagGet_ConditionalRequest_Handler;
1384 RunTransactionTest(cache.http_cache(), transaction);
1385
1386 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1387 EXPECT_EQ(1, cache.disk_cache()->open_count());
1388 EXPECT_EQ(1, cache.disk_cache()->create_count());
1389}
1390
[email protected]b7d05ab2008-12-09 19:18:411391static void ETagGet_ConditionalRequest_NoStore_Handler(
1392 const net::HttpRequestInfo* request,
1393 std::string* response_status,
1394 std::string* response_headers,
1395 std::string* response_data) {
1396 EXPECT_TRUE(request->extra_headers.find("If-None-Match") !=
1397 std::string::npos);
1398 response_status->assign("HTTP/1.1 304 Not Modified");
1399 response_headers->assign("Cache-Control: no-store\n");
1400 response_data->clear();
1401}
1402
1403TEST(HttpCache, ETagGET_ConditionalRequest_304_NoStore) {
1404 MockHttpCache cache;
1405
1406 ScopedMockTransaction transaction(kETagGET_Transaction);
1407
1408 // Write to the cache.
1409 RunTransactionTest(cache.http_cache(), transaction);
1410
1411 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1412 EXPECT_EQ(0, cache.disk_cache()->open_count());
1413 EXPECT_EQ(1, cache.disk_cache()->create_count());
1414
1415 // Get the same URL again, but this time we expect it to result
1416 // in a conditional request.
1417 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
1418 transaction.handler = ETagGet_ConditionalRequest_NoStore_Handler;
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 ScopedMockTransaction transaction2(kETagGET_Transaction);
1426
1427 // Write to the cache again. This should create a new entry.
1428 RunTransactionTest(cache.http_cache(), transaction2);
1429
1430 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1431 EXPECT_EQ(1, cache.disk_cache()->open_count());
1432 EXPECT_EQ(2, cache.disk_cache()->create_count());
1433}
1434
initial.commit586acc5fe2008-07-26 22:42:521435TEST(HttpCache, SimplePOST_SkipsCache) {
1436 MockHttpCache cache;
1437
[email protected]96bac982009-03-24 18:20:061438 // Test that we skip the cache for POST requests that do not have an upload
1439 // identifier.
initial.commit586acc5fe2008-07-26 22:42:521440
1441 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
1442
1443 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1444 EXPECT_EQ(0, cache.disk_cache()->open_count());
1445 EXPECT_EQ(0, cache.disk_cache()->create_count());
1446}
1447
[email protected]4de4fb12009-08-03 22:11:181448// Helper that does 4 requests using HttpCache:
1449//
1450// (1) loads |kUrl| -- expects |net_response_1| to be returned.
1451// (2) loads |kUrl| from cache only -- expects |net_response_1| to be returned.
1452// (3) loads |kUrl| using |extra_request_headers| -- expects |net_response_2| to
1453// be returned.
1454// (4) loads |kUrl| from cache only -- expects |cached_response_2| to be
1455// returned.
1456static void ConditionalizedRequestUpdatesCacheHelper(
1457 const Response& net_response_1,
1458 const Response& net_response_2,
1459 const Response& cached_response_2,
1460 const char* extra_request_headers) {
[email protected]bded84c2009-07-23 00:36:061461 MockHttpCache cache;
1462
1463 // The URL we will be requesting.
1464 const char* kUrl = "http://foobar.com/main.css";
1465
[email protected]bded84c2009-07-23 00:36:061466 // Junk network response.
1467 static const Response kUnexpectedResponse = {
1468 "HTTP/1.1 500 Unexpected",
1469 "Server: unexpected_header",
1470 "unexpected body"
1471 };
1472
1473 // We will control the network layer's responses for |kUrl| using
1474 // |mock_network_response|.
1475 MockTransaction mock_network_response = { 0 };
1476 mock_network_response.url = kUrl;
1477 AddMockTransaction(&mock_network_response);
1478
1479 // Request |kUrl| for the first time. It should hit the network and
1480 // receive |kNetResponse1|, which it saves into the HTTP cache.
1481
1482 MockTransaction request = { 0 };
1483 request.url = kUrl;
1484 request.method = "GET";
1485 request.request_headers = "";
1486
[email protected]4de4fb12009-08-03 22:11:181487 net_response_1.AssignTo(&mock_network_response); // Network mock.
1488 net_response_1.AssignTo(&request); // Expected result.
[email protected]bded84c2009-07-23 00:36:061489
1490 std::string response_headers;
1491 RunTransactionTestWithResponse(
1492 cache.http_cache(), request, &response_headers);
1493
[email protected]4de4fb12009-08-03 22:11:181494 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
[email protected]bded84c2009-07-23 00:36:061495 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1496 EXPECT_EQ(0, cache.disk_cache()->open_count());
1497 EXPECT_EQ(1, cache.disk_cache()->create_count());
1498
[email protected]6f40bf72009-07-23 17:52:371499 // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP
[email protected]bded84c2009-07-23 00:36:061500 // cache, so we don't hit the network.
1501
[email protected]4de4fb12009-08-03 22:11:181502 request.load_flags = net::LOAD_ONLY_FROM_CACHE;
1503
[email protected]bded84c2009-07-23 00:36:061504 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
[email protected]4de4fb12009-08-03 22:11:181505 net_response_1.AssignTo(&request); // Expected result.
[email protected]bded84c2009-07-23 00:36:061506
1507 RunTransactionTestWithResponse(
1508 cache.http_cache(), request, &response_headers);
1509
[email protected]4de4fb12009-08-03 22:11:181510 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
[email protected]bded84c2009-07-23 00:36:061511 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1512 EXPECT_EQ(1, cache.disk_cache()->open_count());
1513 EXPECT_EQ(1, cache.disk_cache()->create_count());
1514
1515 // Request |kUrl| yet again, but this time give the request an
1516 // "If-Modified-Since" header. This will cause the request to re-hit the
1517 // network. However now the network response is going to be
1518 // different -- this simulates a change made to the CSS file.
1519
[email protected]4de4fb12009-08-03 22:11:181520 request.request_headers = extra_request_headers;
1521 request.load_flags = net::LOAD_NORMAL;
[email protected]bded84c2009-07-23 00:36:061522
[email protected]4de4fb12009-08-03 22:11:181523 net_response_2.AssignTo(&mock_network_response); // Network mock.
1524 net_response_2.AssignTo(&request); // Expected result.
[email protected]bded84c2009-07-23 00:36:061525
1526 RunTransactionTestWithResponse(
1527 cache.http_cache(), request, &response_headers);
1528
[email protected]4de4fb12009-08-03 22:11:181529 EXPECT_EQ(net_response_2.status_and_headers(), response_headers);
[email protected]bded84c2009-07-23 00:36:061530 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1531 EXPECT_EQ(1, cache.disk_cache()->open_count());
1532 EXPECT_EQ(1, cache.disk_cache()->create_count());
1533
1534 // Finally, request |kUrl| again. This request should be serviced from
1535 // the cache. Moreover, the value in the cache should be |kNetResponse2|
1536 // and NOT |kNetResponse1|. The previous step should have replaced the
1537 // value in the cache with the modified response.
1538
1539 request.request_headers = "";
[email protected]4de4fb12009-08-03 22:11:181540 request.load_flags = net::LOAD_ONLY_FROM_CACHE;
[email protected]bded84c2009-07-23 00:36:061541
1542 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
[email protected]4de4fb12009-08-03 22:11:181543 cached_response_2.AssignTo(&request); // Expected result.
[email protected]bded84c2009-07-23 00:36:061544
1545 RunTransactionTestWithResponse(
1546 cache.http_cache(), request, &response_headers);
1547
[email protected]4de4fb12009-08-03 22:11:181548 EXPECT_EQ(cached_response_2.status_and_headers(), response_headers);
[email protected]bded84c2009-07-23 00:36:061549 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1550 EXPECT_EQ(2, cache.disk_cache()->open_count());
1551 EXPECT_EQ(1, cache.disk_cache()->create_count());
1552
1553 RemoveMockTransaction(&mock_network_response);
1554}
1555
[email protected]4de4fb12009-08-03 22:11:181556// Check that when an "if-modified-since" header is attached
1557// to the request, the result still updates the cached entry.
1558TEST(HttpCache, ConditionalizedRequestUpdatesCache1) {
1559 // First network response for |kUrl|.
1560 static const Response kNetResponse1 = {
1561 "HTTP/1.1 200 OK",
1562 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1563 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1564 "body1"
1565 };
1566
1567 // Second network response for |kUrl|.
1568 static const Response kNetResponse2 = {
1569 "HTTP/1.1 200 OK",
1570 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1571 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
1572 "body2"
1573 };
1574
1575 const char* extra_headers =
1576 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n";
1577
1578 ConditionalizedRequestUpdatesCacheHelper(
1579 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
1580}
1581
1582// Check that when an "if-none-match" header is attached
1583// to the request, the result updates the cached entry.
1584TEST(HttpCache, ConditionalizedRequestUpdatesCache2) {
1585 // First network response for |kUrl|.
1586 static const Response kNetResponse1 = {
1587 "HTTP/1.1 200 OK",
1588 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1589 "Etag: \"ETAG1\"\n"
1590 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
1591 "body1"
1592 };
1593
1594 // Second network response for |kUrl|.
1595 static const Response kNetResponse2 = {
1596 "HTTP/1.1 200 OK",
1597 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1598 "Etag: \"ETAG2\"\n"
1599 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
1600 "body2"
1601 };
1602
1603 const char* extra_headers = "If-None-Match: \"ETAG1\"\n";
1604
1605 ConditionalizedRequestUpdatesCacheHelper(
1606 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
1607}
1608
1609// Check that when an "if-modified-since" header is attached
1610// to a request, the 304 (not modified result) result updates the cached
1611// headers, and the 304 response is returned rather than the cached response.
1612TEST(HttpCache, ConditionalizedRequestUpdatesCache3) {
1613 // First network response for |kUrl|.
1614 static const Response kNetResponse1 = {
1615 "HTTP/1.1 200 OK",
1616 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1617 "Server: server1\n"
1618 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1619 "body1"
1620 };
1621
1622 // Second network response for |kUrl|.
1623 static const Response kNetResponse2 = {
1624 "HTTP/1.1 304 Not Modified",
1625 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1626 "Server: server2\n"
1627 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1628 ""
1629 };
1630
1631 static const Response kCachedResponse2 = {
1632 "HTTP/1.1 200 OK",
1633 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1634 "Server: server2\n"
1635 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1636 "body1"
1637 };
1638
1639 const char* extra_headers =
1640 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n";
1641
1642 ConditionalizedRequestUpdatesCacheHelper(
1643 kNetResponse1, kNetResponse2, kCachedResponse2, extra_headers);
1644}
1645
1646// Test that when doing an externally conditionalized if-modified-since
1647// and there is no corresponding cache entry, a new cache entry is NOT
1648// created (304 response).
1649TEST(HttpCache, ConditionalizedRequestUpdatesCache4) {
1650 MockHttpCache cache;
1651
1652 const char* kUrl = "http://foobar.com/main.css";
1653
1654 static const Response kNetResponse = {
1655 "HTTP/1.1 304 Not Modified",
1656 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1657 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1658 ""
1659 };
1660
1661 const char* kExtraRequestHeaders =
1662 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n";
1663
1664 // We will control the network layer's responses for |kUrl| using
1665 // |mock_network_response|.
1666 MockTransaction mock_network_response = { 0 };
1667 mock_network_response.url = kUrl;
1668 AddMockTransaction(&mock_network_response);
1669
1670 MockTransaction request = { 0 };
1671 request.url = kUrl;
1672 request.method = "GET";
1673 request.request_headers = kExtraRequestHeaders;
1674
1675 kNetResponse.AssignTo(&mock_network_response); // Network mock.
1676 kNetResponse.AssignTo(&request); // Expected result.
1677
1678 std::string response_headers;
1679 RunTransactionTestWithResponse(
1680 cache.http_cache(), request, &response_headers);
1681
1682 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
1683 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1684 EXPECT_EQ(0, cache.disk_cache()->open_count());
1685 EXPECT_EQ(0, cache.disk_cache()->create_count());
1686
1687 RemoveMockTransaction(&mock_network_response);
1688}
1689
1690// Test that when doing an externally conditionalized if-modified-since
1691// and there is no corresponding cache entry, a new cache entry is NOT
1692// created (200 response).
1693TEST(HttpCache, ConditionalizedRequestUpdatesCache5) {
1694 MockHttpCache cache;
1695
1696 const char* kUrl = "http://foobar.com/main.css";
1697
1698 static const Response kNetResponse = {
1699 "HTTP/1.1 200 OK",
1700 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1701 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1702 "foobar!!!"
1703 };
1704
1705 const char* kExtraRequestHeaders =
1706 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n";
1707
1708 // We will control the network layer's responses for |kUrl| using
1709 // |mock_network_response|.
1710 MockTransaction mock_network_response = { 0 };
1711 mock_network_response.url = kUrl;
1712 AddMockTransaction(&mock_network_response);
1713
1714 MockTransaction request = { 0 };
1715 request.url = kUrl;
1716 request.method = "GET";
1717 request.request_headers = kExtraRequestHeaders;
1718
1719 kNetResponse.AssignTo(&mock_network_response); // Network mock.
1720 kNetResponse.AssignTo(&request); // Expected result.
1721
1722 std::string response_headers;
1723 RunTransactionTestWithResponse(
1724 cache.http_cache(), request, &response_headers);
1725
1726 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
1727 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1728 EXPECT_EQ(0, cache.disk_cache()->open_count());
1729 EXPECT_EQ(0, cache.disk_cache()->create_count());
1730
1731 RemoveMockTransaction(&mock_network_response);
1732}
1733
1734// Test that when doing an externally conditionalized if-modified-since
1735// if the date does not match the cache entry's last-modified date,
1736// then we do NOT use the response (304) to update the cache.
1737// (the if-modified-since date is 2 days AFTER the cache's modification date).
1738TEST(HttpCache, ConditionalizedRequestUpdatesCache6) {
1739 static const Response kNetResponse1 = {
1740 "HTTP/1.1 200 OK",
1741 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1742 "Server: server1\n"
1743 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1744 "body1"
1745 };
1746
1747 // Second network response for |kUrl|.
1748 static const Response kNetResponse2 = {
1749 "HTTP/1.1 304 Not Modified",
1750 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1751 "Server: server2\n"
1752 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1753 ""
1754 };
1755
1756 // This is two days in the future from the original response's last-modified
1757 // date!
1758 const char* kExtraRequestHeaders =
1759 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\n";
1760
1761 ConditionalizedRequestUpdatesCacheHelper(
1762 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
1763}
1764
1765// Test that when doing an externally conditionalized if-none-match
1766// if the etag does not match the cache entry's etag, then we do not use the
1767// response (304) to update the cache.
1768TEST(HttpCache, ConditionalizedRequestUpdatesCache7) {
1769 static const Response kNetResponse1 = {
1770 "HTTP/1.1 200 OK",
1771 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1772 "Etag: \"Foo1\"\n"
1773 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1774 "body1"
1775 };
1776
1777 // Second network response for |kUrl|.
1778 static const Response kNetResponse2 = {
1779 "HTTP/1.1 304 Not Modified",
1780 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1781 "Etag: \"Foo2\"\n"
1782 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1783 ""
1784 };
1785
1786 // Different etag from original response.
1787 const char* kExtraRequestHeaders = "If-None-Match: \"Foo2\"\n";
1788
1789 ConditionalizedRequestUpdatesCacheHelper(
1790 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
1791}
1792
[email protected]f2ee7452009-11-02 21:43:021793// Test that doing an externally conditionalized request with both if-none-match
1794// and if-modified-since updates the cache.
1795TEST(HttpCache, ConditionalizedRequestUpdatesCache8) {
1796 static const Response kNetResponse1 = {
1797 "HTTP/1.1 200 OK",
1798 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1799 "Etag: \"Foo1\"\n"
1800 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1801 "body1"
1802 };
1803
1804 // Second network response for |kUrl|.
1805 static const Response kNetResponse2 = {
1806 "HTTP/1.1 200 OK",
1807 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1808 "Etag: \"Foo2\"\n"
1809 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
1810 "body2"
1811 };
1812
1813 const char* kExtraRequestHeaders =
1814 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n"
1815 "If-None-Match: \"Foo1\"\n";
1816
1817 ConditionalizedRequestUpdatesCacheHelper(
1818 kNetResponse1, kNetResponse2, kNetResponse2, kExtraRequestHeaders);
1819}
1820
1821// Test that doing an externally conditionalized request with both if-none-match
1822// and if-modified-since does not update the cache with only one match.
1823TEST(HttpCache, ConditionalizedRequestUpdatesCache9) {
1824 static const Response kNetResponse1 = {
1825 "HTTP/1.1 200 OK",
1826 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1827 "Etag: \"Foo1\"\n"
1828 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1829 "body1"
1830 };
1831
1832 // Second network response for |kUrl|.
1833 static const Response kNetResponse2 = {
1834 "HTTP/1.1 200 OK",
1835 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1836 "Etag: \"Foo2\"\n"
1837 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
1838 "body2"
1839 };
1840
1841 // The etag doesn't match what we have stored.
1842 const char* kExtraRequestHeaders =
1843 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n"
1844 "If-None-Match: \"Foo2\"\n";
1845
1846 ConditionalizedRequestUpdatesCacheHelper(
1847 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
1848}
1849
1850// Test that doing an externally conditionalized request with both if-none-match
1851// and if-modified-since does not update the cache with only one match.
1852TEST(HttpCache, ConditionalizedRequestUpdatesCache10) {
1853 static const Response kNetResponse1 = {
1854 "HTTP/1.1 200 OK",
1855 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1856 "Etag: \"Foo1\"\n"
1857 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1858 "body1"
1859 };
1860
1861 // Second network response for |kUrl|.
1862 static const Response kNetResponse2 = {
1863 "HTTP/1.1 200 OK",
1864 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1865 "Etag: \"Foo2\"\n"
1866 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
1867 "body2"
1868 };
1869
1870 // The modification date doesn't match what we have stored.
1871 const char* kExtraRequestHeaders =
1872 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\n"
1873 "If-None-Match: \"Foo1\"\n";
1874
1875 ConditionalizedRequestUpdatesCacheHelper(
1876 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
1877}
1878
1879// Test that doing an externally conditionalized request with two conflicting
1880// headers does not update the cache.
1881TEST(HttpCache, ConditionalizedRequestUpdatesCache11) {
1882 static const Response kNetResponse1 = {
1883 "HTTP/1.1 200 OK",
1884 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
1885 "Etag: \"Foo1\"\n"
1886 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
1887 "body1"
1888 };
1889
1890 // Second network response for |kUrl|.
1891 static const Response kNetResponse2 = {
1892 "HTTP/1.1 200 OK",
1893 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
1894 "Etag: \"Foo2\"\n"
1895 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
1896 "body2"
1897 };
1898
1899 // Two dates, the second matches what we have stored.
1900 const char* kExtraRequestHeaders =
1901 "If-Modified-Since: Mon, 04 Feb 2008 22:38:21 GMT\n"
1902 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\n";
1903
1904 ConditionalizedRequestUpdatesCacheHelper(
1905 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
1906}
1907
[email protected]6f40bf72009-07-23 17:52:371908TEST(HttpCache, UrlContainingHash) {
1909 MockHttpCache cache;
1910
1911 // Do a typical GET request -- should write an entry into our cache.
1912 MockTransaction trans(kTypicalGET_Transaction);
1913 RunTransactionTest(cache.http_cache(), trans);
1914
1915 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1916 EXPECT_EQ(0, cache.disk_cache()->open_count());
1917 EXPECT_EQ(1, cache.disk_cache()->create_count());
1918
1919 // Request the same URL, but this time with a reference section (hash).
1920 // Since the cache key strips the hash sections, this should be a cache hit.
1921 std::string url_with_hash = std::string(trans.url) + "#multiple#hashes";
1922 trans.url = url_with_hash.c_str();
1923 trans.load_flags = net::LOAD_ONLY_FROM_CACHE;
1924
1925 RunTransactionTest(cache.http_cache(), trans);
1926
1927 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1928 EXPECT_EQ(1, cache.disk_cache()->open_count());
1929 EXPECT_EQ(1, cache.disk_cache()->create_count());
1930}
1931
initial.commit586acc5fe2008-07-26 22:42:521932TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Miss) {
1933 MockHttpCache cache;
1934
1935 // Test that we skip the cache for POST requests. Eventually, we will want
1936 // to cache these, but we'll still have cases where skipping the cache makes
1937 // sense, so we want to make sure that it works properly.
1938
1939 MockTransaction transaction(kSimplePOST_Transaction);
1940 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
1941
1942 MockHttpRequest request(transaction);
1943 TestCompletionCallback callback;
1944
[email protected]1638d602009-09-24 03:49:171945 scoped_ptr<net::HttpTransaction> trans;
1946 int rv = cache.http_cache()->CreateTransaction(&trans);
1947 EXPECT_EQ(net::OK, rv);
[email protected]af4876d2008-10-21 23:10:571948 ASSERT_TRUE(trans.get());
initial.commit586acc5fe2008-07-26 22:42:521949
[email protected]1638d602009-09-24 03:49:171950 rv = trans->Start(&request, &callback, NULL);
initial.commit586acc5fe2008-07-26 22:42:521951 if (rv == net::ERR_IO_PENDING)
1952 rv = callback.WaitForResult();
1953 ASSERT_EQ(net::ERR_CACHE_MISS, rv);
1954
[email protected]af4876d2008-10-21 23:10:571955 trans.reset();
initial.commit586acc5fe2008-07-26 22:42:521956
1957 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1958 EXPECT_EQ(0, cache.disk_cache()->open_count());
1959 EXPECT_EQ(0, cache.disk_cache()->create_count());
1960}
1961
[email protected]96bac982009-03-24 18:20:061962TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Hit) {
1963 MockHttpCache cache;
1964
1965 // Test that we hit the cache for POST requests.
1966
1967 MockTransaction transaction(kSimplePOST_Transaction);
1968
1969 const int64 kUploadId = 1; // Just a dummy value.
1970
1971 MockHttpRequest request(transaction);
1972 request.upload_data = new net::UploadData();
1973 request.upload_data->set_identifier(kUploadId);
1974 request.upload_data->AppendBytes("hello", 5);
1975
1976 // Populate the cache.
[email protected]95792eb12009-06-22 21:30:401977 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
[email protected]96bac982009-03-24 18:20:061978
1979 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1980 EXPECT_EQ(0, cache.disk_cache()->open_count());
1981 EXPECT_EQ(1, cache.disk_cache()->create_count());
1982
1983 // Load from cache.
1984 request.load_flags |= net::LOAD_ONLY_FROM_CACHE;
[email protected]95792eb12009-06-22 21:30:401985 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
[email protected]96bac982009-03-24 18:20:061986
1987 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1988 EXPECT_EQ(1, cache.disk_cache()->open_count());
1989 EXPECT_EQ(1, cache.disk_cache()->create_count());
1990}
1991
initial.commit586acc5fe2008-07-26 22:42:521992TEST(HttpCache, RangeGET_SkipsCache) {
1993 MockHttpCache cache;
1994
[email protected]8bf26f49a2009-06-12 17:35:501995 // Test that we skip the cache for range GET requests. Eventually, we will
1996 // want to cache these, but we'll still have cases where skipping the cache
1997 // makes sense, so we want to make sure that it works properly.
initial.commit586acc5fe2008-07-26 22:42:521998
1999 RunTransactionTest(cache.http_cache(), kRangeGET_Transaction);
2000
2001 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2002 EXPECT_EQ(0, cache.disk_cache()->open_count());
2003 EXPECT_EQ(0, cache.disk_cache()->create_count());
2004
2005 MockTransaction transaction(kSimpleGET_Transaction);
2006 transaction.request_headers = "If-None-Match: foo";
2007 RunTransactionTest(cache.http_cache(), transaction);
2008
2009 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2010 EXPECT_EQ(0, cache.disk_cache()->open_count());
2011 EXPECT_EQ(0, cache.disk_cache()->create_count());
2012
[email protected]72d1e592009-03-10 17:39:462013 transaction.request_headers =
2014 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT";
initial.commit586acc5fe2008-07-26 22:42:522015 RunTransactionTest(cache.http_cache(), transaction);
2016
2017 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2018 EXPECT_EQ(0, cache.disk_cache()->open_count());
2019 EXPECT_EQ(0, cache.disk_cache()->create_count());
2020}
2021
[email protected]86291440d2009-08-28 18:46:352022// Test that we skip the cache for range requests that include a validation
2023// header.
2024TEST(HttpCache, RangeGET_SkipsCache2) {
2025 MockHttpCache cache;
2026 cache.http_cache()->set_enable_range_support(true);
2027
2028 MockTransaction transaction(kRangeGET_Transaction);
2029 transaction.request_headers = "If-None-Match: foo\n"
[email protected]e75e8af2009-11-03 00:04:202030 EXTRA_HEADER
[email protected]86291440d2009-08-28 18:46:352031 "Range: bytes = 40-49\n";
2032 RunTransactionTest(cache.http_cache(), transaction);
2033
2034 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2035 EXPECT_EQ(0, cache.disk_cache()->open_count());
2036 EXPECT_EQ(0, cache.disk_cache()->create_count());
2037
2038 transaction.request_headers =
2039 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\n"
[email protected]e75e8af2009-11-03 00:04:202040 EXTRA_HEADER
[email protected]86291440d2009-08-28 18:46:352041 "Range: bytes = 40-49\n";
2042 RunTransactionTest(cache.http_cache(), transaction);
2043
2044 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2045 EXPECT_EQ(0, cache.disk_cache()->open_count());
2046 EXPECT_EQ(0, cache.disk_cache()->create_count());
2047
2048 transaction.request_headers = "If-Range: bla\n"
[email protected]e75e8af2009-11-03 00:04:202049 EXTRA_HEADER
[email protected]86291440d2009-08-28 18:46:352050 "Range: bytes = 40-49\n";
2051 RunTransactionTest(cache.http_cache(), transaction);
2052
2053 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2054 EXPECT_EQ(0, cache.disk_cache()->open_count());
2055 EXPECT_EQ(0, cache.disk_cache()->create_count());
2056}
2057
[email protected]e5dad132009-08-18 00:53:412058// Tests that receiving 206 for a regular request is handled correctly.
[email protected]7ee4c4072009-06-30 18:49:472059TEST(HttpCache, GET_Crazy206) {
2060 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312061 cache.http_cache()->set_enable_range_support(true);
[email protected]7ee4c4072009-06-30 18:49:472062
[email protected]7ee4c4072009-06-30 18:49:472063 // Write to the cache.
2064 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]44f873a62009-08-12 00:14:482065 AddMockTransaction(&transaction);
[email protected]e75e8af2009-11-03 00:04:202066 transaction.request_headers = EXTRA_HEADER;
[email protected]44f873a62009-08-12 00:14:482067 transaction.handler = NULL;
[email protected]7ee4c4072009-06-30 18:49:472068 RunTransactionTest(cache.http_cache(), transaction);
2069
2070 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2071 EXPECT_EQ(0, cache.disk_cache()->open_count());
2072 EXPECT_EQ(1, cache.disk_cache()->create_count());
2073
2074 // This should read again from the net.
2075 RunTransactionTest(cache.http_cache(), transaction);
2076
2077 EXPECT_EQ(2, cache.network_layer()->transaction_count());
[email protected]21f659d2009-08-24 17:59:312078 EXPECT_EQ(0, cache.disk_cache()->open_count());
2079 EXPECT_EQ(2, cache.disk_cache()->create_count());
[email protected]44f873a62009-08-12 00:14:482080 RemoveMockTransaction(&transaction);
[email protected]7ee4c4072009-06-30 18:49:472081}
2082
[email protected]e5dad132009-08-18 00:53:412083// Tests that we can cache range requests and fetch random blocks from the
2084// cache and the network.
[email protected]21f659d2009-08-24 17:59:312085TEST(HttpCache, RangeGET_OK) {
[email protected]8bf26f49a2009-06-12 17:35:502086 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312087 cache.http_cache()->set_enable_range_support(true);
[email protected]8bf26f49a2009-06-12 17:35:502088 AddMockTransaction(&kRangeGET_TransactionOK);
[email protected]95792eb12009-06-22 21:30:402089 std::string headers;
[email protected]8bf26f49a2009-06-12 17:35:502090
[email protected]95792eb12009-06-22 21:30:402091 // Write to the cache (40-49).
2092 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2093 &headers);
2094
2095 EXPECT_TRUE(Verify206Response(headers, 40, 49));
[email protected]8bf26f49a2009-06-12 17:35:502096 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2097 EXPECT_EQ(0, cache.disk_cache()->open_count());
2098 EXPECT_EQ(1, cache.disk_cache()->create_count());
2099
2100 // Read from the cache (40-49).
[email protected]95792eb12009-06-22 21:30:402101 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2102 &headers);
[email protected]8bf26f49a2009-06-12 17:35:502103
[email protected]95792eb12009-06-22 21:30:402104 EXPECT_TRUE(Verify206Response(headers, 40, 49));
[email protected]8bf26f49a2009-06-12 17:35:502105 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2106 EXPECT_EQ(1, cache.disk_cache()->open_count());
2107 EXPECT_EQ(1, cache.disk_cache()->create_count());
2108
2109 // Make sure we are done with the previous transaction.
2110 MessageLoop::current()->RunAllPending();
2111
2112 // Write to the cache (30-39).
2113 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]e75e8af2009-11-03 00:04:202114 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
[email protected]8bf26f49a2009-06-12 17:35:502115 transaction.data = "rg: 30-39 ";
[email protected]95792eb12009-06-22 21:30:402116 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
[email protected]8bf26f49a2009-06-12 17:35:502117
[email protected]95792eb12009-06-22 21:30:402118 EXPECT_TRUE(Verify206Response(headers, 30, 39));
[email protected]8bf26f49a2009-06-12 17:35:502119 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2120 EXPECT_EQ(2, cache.disk_cache()->open_count());
2121 EXPECT_EQ(1, cache.disk_cache()->create_count());
2122
2123 // Make sure we are done with the previous transaction.
2124 MessageLoop::current()->RunAllPending();
2125
2126 // Write and read from the cache (20-59).
[email protected]e75e8af2009-11-03 00:04:202127 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
[email protected]8bf26f49a2009-06-12 17:35:502128 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
[email protected]95792eb12009-06-22 21:30:402129 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
[email protected]8bf26f49a2009-06-12 17:35:502130
[email protected]95792eb12009-06-22 21:30:402131 EXPECT_TRUE(Verify206Response(headers, 20, 59));
[email protected]44f873a62009-08-12 00:14:482132 EXPECT_EQ(5, cache.network_layer()->transaction_count());
[email protected]8bf26f49a2009-06-12 17:35:502133 EXPECT_EQ(3, cache.disk_cache()->open_count());
2134 EXPECT_EQ(1, cache.disk_cache()->create_count());
2135
2136 RemoveMockTransaction(&kRangeGET_TransactionOK);
2137}
2138
[email protected]e5dad132009-08-18 00:53:412139// Tests that we deal with 304s for range requests.
[email protected]21f659d2009-08-24 17:59:312140TEST(HttpCache, RangeGET_304) {
[email protected]e5dad132009-08-18 00:53:412141 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312142 cache.http_cache()->set_enable_range_support(true);
[email protected]e5dad132009-08-18 00:53:412143 AddMockTransaction(&kRangeGET_TransactionOK);
2144 std::string headers;
2145
2146 // Write to the cache (40-49).
2147 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2148 &headers);
2149
2150 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2151 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2152 EXPECT_EQ(0, cache.disk_cache()->open_count());
2153 EXPECT_EQ(1, cache.disk_cache()->create_count());
2154
2155 // Read from the cache (40-49).
2156 RangeTransactionServer handler;
2157 handler.set_not_modified(true);
2158 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2159 &headers);
2160
2161 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2162 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2163 EXPECT_EQ(1, cache.disk_cache()->open_count());
2164 EXPECT_EQ(1, cache.disk_cache()->create_count());
2165
2166 RemoveMockTransaction(&kRangeGET_TransactionOK);
2167}
2168
[email protected]a79837892009-08-20 21:18:292169// Tests that we deal with 206s when revalidating range requests.
[email protected]21f659d2009-08-24 17:59:312170TEST(HttpCache, RangeGET_ModifiedResult) {
[email protected]a79837892009-08-20 21:18:292171 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312172 cache.http_cache()->set_enable_range_support(true);
[email protected]a79837892009-08-20 21:18:292173 AddMockTransaction(&kRangeGET_TransactionOK);
2174 std::string headers;
2175
2176 // Write to the cache (40-49).
2177 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2178 &headers);
2179
2180 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2181 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2182 EXPECT_EQ(0, cache.disk_cache()->open_count());
2183 EXPECT_EQ(1, cache.disk_cache()->create_count());
2184
2185 // Attempt to read from the cache (40-49).
2186 RangeTransactionServer handler;
2187 handler.set_modified(true);
2188 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2189 &headers);
2190
2191 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2192 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2193 EXPECT_EQ(1, cache.disk_cache()->open_count());
2194 EXPECT_EQ(1, cache.disk_cache()->create_count());
2195
2196 // And the entry should be gone.
2197 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
2198 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2199 EXPECT_EQ(1, cache.disk_cache()->open_count());
2200 EXPECT_EQ(2, cache.disk_cache()->create_count());
2201
2202 RemoveMockTransaction(&kRangeGET_TransactionOK);
2203}
2204
[email protected]e5dad132009-08-18 00:53:412205// Tests that we can cache range requests when the start or end is unknown.
2206// We start with one suffix request, followed by a request from a given point.
[email protected]21f659d2009-08-24 17:59:312207TEST(HttpCache, UnknownRangeGET_1) {
[email protected]67fe45c2009-06-24 17:44:572208 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312209 cache.http_cache()->set_enable_range_support(true);
[email protected]67fe45c2009-06-24 17:44:572210 AddMockTransaction(&kRangeGET_TransactionOK);
[email protected]67fe45c2009-06-24 17:44:572211 std::string headers;
2212
2213 // Write to the cache (70-79).
2214 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]e75e8af2009-11-03 00:04:202215 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
[email protected]67fe45c2009-06-24 17:44:572216 transaction.data = "rg: 70-79 ";
2217 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2218
2219 EXPECT_TRUE(Verify206Response(headers, 70, 79));
2220 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2221 EXPECT_EQ(0, cache.disk_cache()->open_count());
2222 EXPECT_EQ(1, cache.disk_cache()->create_count());
2223
2224 // Make sure we are done with the previous transaction.
2225 MessageLoop::current()->RunAllPending();
2226
2227 // Write and read from the cache (60-79).
[email protected]e75e8af2009-11-03 00:04:202228 transaction.request_headers = "Range: bytes = 60-\r\n" EXTRA_HEADER;
[email protected]67fe45c2009-06-24 17:44:572229 transaction.data = "rg: 60-69 rg: 70-79 ";
2230 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2231
2232 EXPECT_TRUE(Verify206Response(headers, 60, 79));
[email protected]44f873a62009-08-12 00:14:482233 EXPECT_EQ(2, cache.network_layer()->transaction_count());
[email protected]67fe45c2009-06-24 17:44:572234 EXPECT_EQ(1, cache.disk_cache()->open_count());
2235 EXPECT_EQ(1, cache.disk_cache()->create_count());
2236
2237 RemoveMockTransaction(&kRangeGET_TransactionOK);
2238}
2239
[email protected]e5dad132009-08-18 00:53:412240// Tests that we can cache range requests when the start or end is unknown.
2241// We start with one request from a given point, followed by a suffix request.
2242// We'll also verify that synchronous cache responses work as intended.
[email protected]21f659d2009-08-24 17:59:312243TEST(HttpCache, UnknownRangeGET_2) {
[email protected]67fe45c2009-06-24 17:44:572244 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312245 cache.http_cache()->set_enable_range_support(true);
[email protected]67fe45c2009-06-24 17:44:572246 std::string headers;
2247
[email protected]67fe45c2009-06-24 17:44:572248 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]44f873a62009-08-12 00:14:482249 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
[email protected]73cae572009-10-22 18:36:192250 TEST_MODE_SYNC_CACHE_READ |
2251 TEST_MODE_SYNC_CACHE_WRITE;
[email protected]44f873a62009-08-12 00:14:482252 AddMockTransaction(&transaction);
2253
2254 // Write to the cache (70-79).
[email protected]e75e8af2009-11-03 00:04:202255 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
[email protected]67fe45c2009-06-24 17:44:572256 transaction.data = "rg: 70-79 ";
2257 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2258
2259 EXPECT_TRUE(Verify206Response(headers, 70, 79));
2260 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2261 EXPECT_EQ(0, cache.disk_cache()->open_count());
2262 EXPECT_EQ(1, cache.disk_cache()->create_count());
2263
2264 // Make sure we are done with the previous transaction.
2265 MessageLoop::current()->RunAllPending();
2266
2267 // Write and read from the cache (60-79).
[email protected]e75e8af2009-11-03 00:04:202268 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
[email protected]67fe45c2009-06-24 17:44:572269 transaction.data = "rg: 60-69 rg: 70-79 ";
2270 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2271
2272 EXPECT_TRUE(Verify206Response(headers, 60, 79));
[email protected]44f873a62009-08-12 00:14:482273 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2274 EXPECT_EQ(1, cache.disk_cache()->open_count());
2275 EXPECT_EQ(1, cache.disk_cache()->create_count());
2276
2277 RemoveMockTransaction(&transaction);
2278}
2279
[email protected]e5dad132009-08-18 00:53:412280// Tests that receiving Not Modified when asking for an open range doesn't mess
2281// up things.
[email protected]21f659d2009-08-24 17:59:312282TEST(HttpCache, UnknownRangeGET_304) {
[email protected]e5dad132009-08-18 00:53:412283 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312284 cache.http_cache()->set_enable_range_support(true);
[email protected]e5dad132009-08-18 00:53:412285 std::string headers;
2286
2287 MockTransaction transaction(kRangeGET_TransactionOK);
2288 AddMockTransaction(&transaction);
2289
2290 RangeTransactionServer handler;
2291 handler.set_not_modified(true);
2292
2293 // Ask for the end of the file, without knowing the length.
[email protected]e75e8af2009-11-03 00:04:202294 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
[email protected]e5dad132009-08-18 00:53:412295 transaction.data = "rg: 70-79 ";
2296 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2297
2298 // We just bypass the cache.
2299 EXPECT_EQ(0U, headers.find("HTTP/1.1 304 Not Modified\n"));
2300 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2301 EXPECT_EQ(0, cache.disk_cache()->open_count());
2302 EXPECT_EQ(1, cache.disk_cache()->create_count());
2303
2304 RunTransactionTest(cache.http_cache(), transaction);
2305 EXPECT_EQ(2, cache.disk_cache()->create_count());
2306
2307 RemoveMockTransaction(&transaction);
2308}
2309
2310// Tests that we can handle non-range requests when we have cached a range.
[email protected]21f659d2009-08-24 17:59:312311TEST(HttpCache, GET_Previous206) {
[email protected]44f873a62009-08-12 00:14:482312 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312313 cache.http_cache()->set_enable_range_support(true);
[email protected]44f873a62009-08-12 00:14:482314 AddMockTransaction(&kRangeGET_TransactionOK);
[email protected]44f873a62009-08-12 00:14:482315 std::string headers;
2316
2317 // Write to the cache (40-49).
2318 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2319 &headers);
2320
2321 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2322 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2323 EXPECT_EQ(0, cache.disk_cache()->open_count());
2324 EXPECT_EQ(1, cache.disk_cache()->create_count());
2325
2326 // Write and read from the cache (0-79), when not asked for a range.
2327 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]e75e8af2009-11-03 00:04:202328 transaction.request_headers = EXTRA_HEADER;
[email protected]44f873a62009-08-12 00:14:482329 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
2330 "rg: 50-59 rg: 60-69 rg: 70-79 ";
2331 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2332
2333 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
[email protected]67fe45c2009-06-24 17:44:572334 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2335 EXPECT_EQ(1, cache.disk_cache()->open_count());
2336 EXPECT_EQ(1, cache.disk_cache()->create_count());
2337
2338 RemoveMockTransaction(&kRangeGET_TransactionOK);
2339}
2340
[email protected]d9adff2c2009-09-05 01:15:452341// Tests that we can handle non-range requests when we have cached the first
2342// part of the object and server replies with 304 (Not Modified).
2343TEST(HttpCache, GET_Previous206_NotModified) {
2344 MockHttpCache cache;
2345 cache.http_cache()->set_enable_range_support(true);
2346
2347 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]e75e8af2009-11-03 00:04:202348 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
[email protected]d9adff2c2009-09-05 01:15:452349 transaction.data = "rg: 00-09 ";
2350 AddMockTransaction(&transaction);
2351 std::string headers;
2352
2353 // Write to the cache (0-9).
2354 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2355
2356 EXPECT_TRUE(Verify206Response(headers, 0, 9));
2357 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2358 EXPECT_EQ(0, cache.disk_cache()->open_count());
2359 EXPECT_EQ(1, cache.disk_cache()->create_count());
2360
2361 // Read from the cache (0-9), write and read from cache (10 - 79),
2362 MockTransaction transaction2(kRangeGET_TransactionOK);
[email protected]e75e8af2009-11-03 00:04:202363 transaction2.request_headers = "Foo: bar\r\n" EXTRA_HEADER;
[email protected]d9adff2c2009-09-05 01:15:452364 transaction2.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
2365 "rg: 50-59 rg: 60-69 rg: 70-79 ";
2366 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
2367
2368 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
2369 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2370 EXPECT_EQ(1, cache.disk_cache()->open_count());
2371 EXPECT_EQ(1, cache.disk_cache()->create_count());
2372
2373 RemoveMockTransaction(&transaction);
2374}
2375
[email protected]e5dad132009-08-18 00:53:412376// Tests that we can handle cached 206 responses that are not sparse.
[email protected]21f659d2009-08-24 17:59:312377TEST(HttpCache, GET_Previous206_NotSparse) {
[email protected]44f873a62009-08-12 00:14:482378 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312379 cache.http_cache()->set_enable_range_support(true);
[email protected]44f873a62009-08-12 00:14:482380
[email protected]44f873a62009-08-12 00:14:482381 // Create a disk cache entry that stores 206 headers while not being sparse.
2382 disk_cache::Entry* entry;
2383 ASSERT_TRUE(cache.disk_cache()->CreateEntry(kSimpleGET_Transaction.url,
2384 &entry));
2385
2386 std::string raw_headers(kRangeGET_TransactionOK.status);
2387 raw_headers.append("\n");
2388 raw_headers.append(kRangeGET_TransactionOK.response_headers);
2389 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
2390 raw_headers.size());
2391
2392 net::HttpResponseInfo response;
2393 response.headers = new net::HttpResponseHeaders(raw_headers);
[email protected]28accfe2009-09-04 23:36:332394 EXPECT_TRUE(net::HttpCache::WriteResponseInfo(entry, &response, true, false));
[email protected]44f873a62009-08-12 00:14:482395
2396 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500));
2397 int len = static_cast<int>(base::strlcpy(buf->data(),
2398 kRangeGET_TransactionOK.data, 500));
2399 EXPECT_EQ(len, entry->WriteData(1, 0, buf, len, NULL, true));
2400 entry->Close();
2401
2402 // Now see that we don't use the stored entry.
2403 std::string headers;
2404 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction,
2405 &headers);
2406
2407 // We are expecting a 200.
2408 std::string expected_headers(kSimpleGET_Transaction.status);
2409 expected_headers.append("\n");
2410 expected_headers.append(kSimpleGET_Transaction.response_headers);
2411 EXPECT_EQ(expected_headers, headers);
2412 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2413 EXPECT_EQ(1, cache.disk_cache()->open_count());
2414 EXPECT_EQ(2, cache.disk_cache()->create_count());
2415}
2416
[email protected]e5dad132009-08-18 00:53:412417// Tests that we can handle cached 206 responses that are not sparse. This time
2418// we issue a range request and expect to receive a range.
[email protected]21f659d2009-08-24 17:59:312419TEST(HttpCache, RangeGET_Previous206_NotSparse_2) {
[email protected]44f873a62009-08-12 00:14:482420 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312421 cache.http_cache()->set_enable_range_support(true);
[email protected]44f873a62009-08-12 00:14:482422 AddMockTransaction(&kRangeGET_TransactionOK);
2423
[email protected]44f873a62009-08-12 00:14:482424 // Create a disk cache entry that stores 206 headers while not being sparse.
2425 disk_cache::Entry* entry;
2426 ASSERT_TRUE(cache.disk_cache()->CreateEntry(kRangeGET_TransactionOK.url,
2427 &entry));
2428
2429 std::string raw_headers(kRangeGET_TransactionOK.status);
2430 raw_headers.append("\n");
2431 raw_headers.append(kRangeGET_TransactionOK.response_headers);
2432 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
2433 raw_headers.size());
2434
2435 net::HttpResponseInfo response;
2436 response.headers = new net::HttpResponseHeaders(raw_headers);
[email protected]28accfe2009-09-04 23:36:332437 EXPECT_TRUE(net::HttpCache::WriteResponseInfo(entry, &response, true, false));
[email protected]44f873a62009-08-12 00:14:482438
2439 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500));
2440 int len = static_cast<int>(base::strlcpy(buf->data(),
2441 kRangeGET_TransactionOK.data, 500));
2442 EXPECT_EQ(len, entry->WriteData(1, 0, buf, len, NULL, true));
2443 entry->Close();
2444
2445 // Now see that we don't use the stored entry.
2446 std::string headers;
2447 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2448 &headers);
2449
2450 // We are expecting a 206.
2451 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2452 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2453 EXPECT_EQ(1, cache.disk_cache()->open_count());
2454 EXPECT_EQ(2, cache.disk_cache()->create_count());
2455
2456 RemoveMockTransaction(&kRangeGET_TransactionOK);
2457}
2458
[email protected]e5dad132009-08-18 00:53:412459// Tests that we can handle range requests with cached 200 responses.
[email protected]21f659d2009-08-24 17:59:312460TEST(HttpCache, RangeGET_Previous200) {
[email protected]e5dad132009-08-18 00:53:412461 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312462 cache.http_cache()->set_enable_range_support(true);
[email protected]e5dad132009-08-18 00:53:412463
2464 // Store the whole thing with status 200.
2465 MockTransaction transaction(kTypicalGET_Transaction);
2466 transaction.url = kRangeGET_TransactionOK.url;
2467 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
2468 "rg: 50-59 rg: 60-69 rg: 70-79 ";
2469 AddMockTransaction(&transaction);
2470 RunTransactionTest(cache.http_cache(), transaction);
2471 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2472 EXPECT_EQ(0, cache.disk_cache()->open_count());
2473 EXPECT_EQ(1, cache.disk_cache()->create_count());
2474
2475 RemoveMockTransaction(&transaction);
2476 AddMockTransaction(&kRangeGET_TransactionOK);
2477
2478 // Now see that we use the stored entry.
2479 std::string headers;
2480 MockTransaction transaction2(kRangeGET_TransactionOK);
2481 RangeTransactionServer handler;
2482 handler.set_not_modified(true);
2483 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
2484
2485 // We are expecting a 206.
2486 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2487 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2488 EXPECT_EQ(1, cache.disk_cache()->open_count());
2489 EXPECT_EQ(1, cache.disk_cache()->create_count());
2490
[email protected]8f28d632009-10-01 22:09:212491 // The last transaction has finished so make sure the entry is deactivated.
2492 MessageLoop::current()->RunAllPending();
2493
[email protected]e5dad132009-08-18 00:53:412494 // Now we should receive a range from the server and drop the stored entry.
2495 handler.set_not_modified(false);
2496 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
2497 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
2498 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2499 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2500 EXPECT_EQ(2, cache.disk_cache()->open_count());
2501 EXPECT_EQ(1, cache.disk_cache()->create_count());
2502
2503 RunTransactionTest(cache.http_cache(), transaction2);
2504 EXPECT_EQ(2, cache.disk_cache()->create_count());
2505
2506 RemoveMockTransaction(&kRangeGET_TransactionOK);
2507}
2508
2509// Tests that we can handle a 200 response when dealing with sparse entries.
[email protected]21f659d2009-08-24 17:59:312510TEST(HttpCache, RangeRequestResultsIn200) {
[email protected]44f873a62009-08-12 00:14:482511 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312512 cache.http_cache()->set_enable_range_support(true);
[email protected]44f873a62009-08-12 00:14:482513 AddMockTransaction(&kRangeGET_TransactionOK);
[email protected]44f873a62009-08-12 00:14:482514 std::string headers;
2515
2516 // Write to the cache (70-79).
2517 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]e75e8af2009-11-03 00:04:202518 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
[email protected]44f873a62009-08-12 00:14:482519 transaction.data = "rg: 70-79 ";
2520 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2521
2522 EXPECT_TRUE(Verify206Response(headers, 70, 79));
2523 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2524 EXPECT_EQ(0, cache.disk_cache()->open_count());
2525 EXPECT_EQ(1, cache.disk_cache()->create_count());
2526
2527 // Now we'll issue a request that results in a plain 200 response, but to
2528 // the to the same URL that we used to store sparse data, and making sure
2529 // that we ask for a range.
2530 RemoveMockTransaction(&kRangeGET_TransactionOK);
2531 MockTransaction transaction2(kSimpleGET_Transaction);
2532 transaction2.url = kRangeGET_TransactionOK.url;
2533 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
2534 AddMockTransaction(&transaction2);
2535
2536 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
2537
2538 std::string expected_headers(kSimpleGET_Transaction.status);
2539 expected_headers.append("\n");
2540 expected_headers.append(kSimpleGET_Transaction.response_headers);
2541 EXPECT_EQ(expected_headers, headers);
2542 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2543 EXPECT_EQ(1, cache.disk_cache()->open_count());
2544 EXPECT_EQ(1, cache.disk_cache()->create_count());
2545
2546 RemoveMockTransaction(&transaction2);
2547}
2548
[email protected]e5dad132009-08-18 00:53:412549// Tests that a range request that falls outside of the size that we know about
2550// only deletes the entry if the resource has indeed changed.
[email protected]21f659d2009-08-24 17:59:312551TEST(HttpCache, RangeGET_MoreThanCurrentSize) {
[email protected]e5dad132009-08-18 00:53:412552 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312553 cache.http_cache()->set_enable_range_support(true);
[email protected]e5dad132009-08-18 00:53:412554 AddMockTransaction(&kRangeGET_TransactionOK);
2555 std::string headers;
2556
2557 // Write to the cache (40-49).
2558 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2559 &headers);
2560
2561 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2562 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2563 EXPECT_EQ(0, cache.disk_cache()->open_count());
2564 EXPECT_EQ(1, cache.disk_cache()->create_count());
2565
2566 // A weird request should not delete this entry. Ask for bytes 120-.
2567 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]e75e8af2009-11-03 00:04:202568 transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER;
[email protected]e5dad132009-08-18 00:53:412569 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2570
2571 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
2572 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2573 EXPECT_EQ(1, cache.disk_cache()->open_count());
2574 EXPECT_EQ(1, cache.disk_cache()->create_count());
2575
2576 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
2577 EXPECT_EQ(2, cache.disk_cache()->open_count());
2578 EXPECT_EQ(1, cache.disk_cache()->create_count());
2579
2580 RemoveMockTransaction(&kRangeGET_TransactionOK);
2581}
2582
[email protected]2c8528532009-09-09 16:55:222583// Tests that we don't delete a sparse entry when we cancel a request.
2584TEST(HttpCache, RangeGET_Cancel) {
2585 MockHttpCache cache;
2586 cache.http_cache()->set_enable_range_support(true);
2587 AddMockTransaction(&kRangeGET_TransactionOK);
2588
2589 MockHttpRequest request(kRangeGET_TransactionOK);
2590
[email protected]1638d602009-09-24 03:49:172591 Context* c = new Context();
2592 int rv = cache.http_cache()->CreateTransaction(&c->trans);
2593 EXPECT_EQ(net::OK, rv);
[email protected]2c8528532009-09-09 16:55:222594
[email protected]1638d602009-09-24 03:49:172595 rv = c->trans->Start(&request, &c->callback, NULL);
[email protected]2c8528532009-09-09 16:55:222596 if (rv == net::ERR_IO_PENDING)
2597 rv = c->callback.WaitForResult();
2598
2599 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2600 EXPECT_EQ(0, cache.disk_cache()->open_count());
2601 EXPECT_EQ(1, cache.disk_cache()->create_count());
2602
2603 // Make sure that the entry has some data stored.
2604 scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
2605 rv = c->trans->Read(buf, buf->size(), &c->callback);
2606 if (rv == net::ERR_IO_PENDING)
2607 rv = c->callback.WaitForResult();
2608 EXPECT_EQ(buf->size(), rv);
2609
2610 // Destroy the transaction.
2611 delete c;
2612
2613 // Verify that the entry has not been deleted.
2614 disk_cache::Entry* entry;
2615 ASSERT_TRUE(cache.disk_cache()->OpenEntry(kRangeGET_TransactionOK.url,
2616 &entry));
2617 entry->Close();
2618 RemoveMockTransaction(&kRangeGET_TransactionOK);
2619}
2620
[email protected]06e62ba2009-10-08 23:07:392621// Tests that we don't delete a sparse entry when we start a new request after
2622// cancelling the previous one.
2623TEST(HttpCache, RangeGET_Cancel2) {
2624 MockHttpCache cache;
2625 cache.http_cache()->set_enable_range_support(true);
2626 AddMockTransaction(&kRangeGET_TransactionOK);
2627
2628 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
2629 MockHttpRequest request(kRangeGET_TransactionOK);
2630
2631 Context* c = new Context();
2632 int rv = cache.http_cache()->CreateTransaction(&c->trans);
2633 EXPECT_EQ(net::OK, rv);
2634
2635 rv = c->trans->Start(&request, &c->callback, NULL);
2636 if (rv == net::ERR_IO_PENDING)
2637 rv = c->callback.WaitForResult();
2638
2639 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2640 EXPECT_EQ(1, cache.disk_cache()->open_count());
2641 EXPECT_EQ(1, cache.disk_cache()->create_count());
2642
2643 // Make sure that we revalidate the entry and read from the cache (a single
2644 // read will return while waiting for the network).
2645 scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(5);
2646 rv = c->trans->Read(buf, buf->size(), &c->callback);
2647 EXPECT_EQ(net::ERR_IO_PENDING, rv);
2648 rv = c->callback.WaitForResult();
2649 rv = c->trans->Read(buf, buf->size(), &c->callback);
2650 EXPECT_EQ(net::ERR_IO_PENDING, rv);
2651
2652 // Destroy the transaction before completing the read.
2653 delete c;
2654
2655 // We have the read and the delete (OnProcessPendingQueue) waiting on the
2656 // message loop. This means that a new transaction will just reuse the same
2657 // active entry (no open or create).
2658
2659 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
2660
2661 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2662 EXPECT_EQ(1, cache.disk_cache()->open_count());
2663 EXPECT_EQ(1, cache.disk_cache()->create_count());
2664 RemoveMockTransaction(&kRangeGET_TransactionOK);
2665}
2666
[email protected]7eab0d2262009-10-14 22:05:542667// Tests that an invalid range response results in no cached entry.
2668TEST(HttpCache, RangeGET_InvalidResponse1) {
2669 MockHttpCache cache;
2670 cache.http_cache()->set_enable_range_support(true);
2671 std::string headers;
2672
2673 MockTransaction transaction(kRangeGET_TransactionOK);
2674 transaction.handler = NULL;
2675 transaction.response_headers = "Content-Range: bytes 40-49/45\n"
2676 "Content-Length: 10\n";
2677 AddMockTransaction(&transaction);
2678 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2679
2680 std::string expected(transaction.status);
2681 expected.append("\n");
2682 expected.append(transaction.response_headers);
2683 EXPECT_EQ(expected, headers);
2684
2685 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2686 EXPECT_EQ(0, cache.disk_cache()->open_count());
2687 EXPECT_EQ(1, cache.disk_cache()->create_count());
2688
2689 // Verify that we don't have a cached entry.
2690 disk_cache::Entry* en;
2691 ASSERT_FALSE(cache.disk_cache()->OpenEntry(kRangeGET_TransactionOK.url, &en));
2692
2693 RemoveMockTransaction(&kRangeGET_TransactionOK);
2694}
2695
2696// Tests that we reject a range that doesn't match the content-length.
2697TEST(HttpCache, RangeGET_InvalidResponse2) {
2698 MockHttpCache cache;
2699 cache.http_cache()->set_enable_range_support(true);
2700 std::string headers;
2701
2702 MockTransaction transaction(kRangeGET_TransactionOK);
2703 transaction.handler = NULL;
2704 transaction.response_headers = "Content-Range: bytes 40-49/80\n"
2705 "Content-Length: 20\n";
2706 AddMockTransaction(&transaction);
2707 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2708
2709 std::string expected(transaction.status);
2710 expected.append("\n");
2711 expected.append(transaction.response_headers);
2712 EXPECT_EQ(expected, headers);
2713
2714 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2715 EXPECT_EQ(0, cache.disk_cache()->open_count());
2716 EXPECT_EQ(1, cache.disk_cache()->create_count());
2717
2718 // Verify that we don't have a cached entry.
2719 disk_cache::Entry* en;
2720 ASSERT_FALSE(cache.disk_cache()->OpenEntry(kRangeGET_TransactionOK.url, &en));
2721
2722 RemoveMockTransaction(&kRangeGET_TransactionOK);
2723}
2724
2725// Tests that if a server tells us conflicting information about a resource we
2726// ignore the response.
2727TEST(HttpCache, RangeGET_InvalidResponse3) {
2728 MockHttpCache cache;
2729 cache.http_cache()->set_enable_range_support(true);
2730 std::string headers;
2731
2732 MockTransaction transaction(kRangeGET_TransactionOK);
2733 transaction.handler = NULL;
[email protected]e75e8af2009-11-03 00:04:202734 transaction.request_headers = "Range: bytes = 50-59\r\n" EXTRA_HEADER;
[email protected]7eab0d2262009-10-14 22:05:542735 std::string response_headers(transaction.response_headers);
2736 response_headers.append("Content-Range: bytes 50-59/160\n");
2737 transaction.response_headers = response_headers.c_str();
2738 AddMockTransaction(&transaction);
2739 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2740
2741 EXPECT_TRUE(Verify206Response(headers, 50, 59));
2742 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2743 EXPECT_EQ(0, cache.disk_cache()->open_count());
2744 EXPECT_EQ(1, cache.disk_cache()->create_count());
2745
2746 RemoveMockTransaction(&transaction);
2747 AddMockTransaction(&kRangeGET_TransactionOK);
2748
2749 // This transaction will report a resource size of 80 bytes, and we think it's
2750 // 160 so we should ignore the response.
2751 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
2752 &headers);
2753
2754 EXPECT_TRUE(Verify206Response(headers, 40, 49));
2755 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2756 EXPECT_EQ(1, cache.disk_cache()->open_count());
2757 EXPECT_EQ(1, cache.disk_cache()->create_count());
2758
2759 // Verify that we cached the first response but not the second one.
2760 disk_cache::Entry* en;
2761 ASSERT_TRUE(cache.disk_cache()->OpenEntry(kRangeGET_TransactionOK.url, &en));
2762 int64 cached_start = 0;
2763 EXPECT_EQ(10, en->GetAvailableRange(40, 20, &cached_start));
2764 EXPECT_EQ(50, cached_start);
2765 en->Close();
2766
2767 RemoveMockTransaction(&kRangeGET_TransactionOK);
2768}
2769
2770// Tests that we handle large range values properly.
2771TEST(HttpCache, RangeGET_LargeValues) {
2772 // We need a real sparse cache for this test.
2773 disk_cache::Backend* disk_cache =
2774 disk_cache::CreateInMemoryCacheBackend(1024 * 1024);
2775 MockHttpCache cache(disk_cache);
2776 cache.http_cache()->set_enable_range_support(true);
2777 std::string headers;
2778
2779 MockTransaction transaction(kRangeGET_TransactionOK);
2780 transaction.handler = NULL;
[email protected]e75e8af2009-11-03 00:04:202781 transaction.request_headers = "Range: bytes = 4294967288-4294967297\r\n"
2782 EXTRA_HEADER;
[email protected]7eab0d2262009-10-14 22:05:542783 transaction.response_headers =
2784 "Content-Range: bytes 4294967288-4294967297/4294967299\n"
2785 "Content-Length: 10\n";
2786 AddMockTransaction(&transaction);
2787 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2788
2789 std::string expected(transaction.status);
2790 expected.append("\n");
2791 expected.append(transaction.response_headers);
2792 EXPECT_EQ(expected, headers);
2793
2794 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2795
2796 // Verify that we have a cached entry.
2797 disk_cache::Entry* en;
2798 ASSERT_TRUE(cache.disk_cache()->OpenEntry(kRangeGET_TransactionOK.url, &en));
2799 en->Close();
2800
2801 RemoveMockTransaction(&kRangeGET_TransactionOK);
2802}
2803
[email protected]93e78442009-10-27 04:46:322804// Tests that we don't crash with a range request if the disk cache was not
2805// initialized properly.
2806TEST(HttpCache, RangeGET_NoDiskCache) {
2807 MockHttpCache cache(NULL);
2808 cache.http_cache()->set_enable_range_support(true);
2809 AddMockTransaction(&kRangeGET_TransactionOK);
2810
2811 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
2812 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2813
2814 RemoveMockTransaction(&kRangeGET_TransactionOK);
2815}
2816
[email protected]e5dad132009-08-18 00:53:412817#ifdef NDEBUG
2818// This test hits a NOTREACHED so it is a release mode only test.
[email protected]21f659d2009-08-24 17:59:312819TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) {
[email protected]e5dad132009-08-18 00:53:412820 MockHttpCache cache;
[email protected]21f659d2009-08-24 17:59:312821 cache.http_cache()->set_enable_range_support(true);
[email protected]e5dad132009-08-18 00:53:412822 AddMockTransaction(&kRangeGET_TransactionOK);
2823
2824 // Write to the cache (40-49).
2825 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
2826 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2827 EXPECT_EQ(0, cache.disk_cache()->open_count());
2828 EXPECT_EQ(1, cache.disk_cache()->create_count());
2829
2830 // Force this transaction to read from the cache.
2831 MockTransaction transaction(kRangeGET_TransactionOK);
2832 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
2833
2834 MockHttpRequest request(transaction);
2835 TestCompletionCallback callback;
2836
[email protected]1638d602009-09-24 03:49:172837 scoped_ptr<net::HttpTransaction> trans;
2838 int rv = cache.http_cache()->CreateTransaction(&trans);
2839 EXPECT_EQ(net::OK, rv);
[email protected]e5dad132009-08-18 00:53:412840 ASSERT_TRUE(trans.get());
2841
[email protected]6330b6c2009-09-24 04:07:372842 rv = trans->Start(&request, &callback, NULL);
[email protected]e5dad132009-08-18 00:53:412843 if (rv == net::ERR_IO_PENDING)
2844 rv = callback.WaitForResult();
2845 ASSERT_EQ(net::ERR_CACHE_MISS, rv);
2846
2847 trans.reset();
2848
2849 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2850 EXPECT_EQ(1, cache.disk_cache()->open_count());
2851 EXPECT_EQ(1, cache.disk_cache()->create_count());
2852
2853 RemoveMockTransaction(&kRangeGET_TransactionOK);
2854}
2855#endif
2856
[email protected]28accfe2009-09-04 23:36:332857// Tests the handling of the "truncation" flag.
2858TEST(HttpCache, WriteResponseInfo_Truncated) {
2859 MockHttpCache cache;
2860 disk_cache::Entry* entry;
2861 ASSERT_TRUE(cache.disk_cache()->CreateEntry("http://www.google.com", &entry));
2862
2863 std::string headers("HTTP/1.1 200 OK");
2864 headers = net::HttpUtil::AssembleRawHeaders(headers.data(), headers.size());
2865 net::HttpResponseInfo response;
2866 response.headers = new net::HttpResponseHeaders(headers);
2867
2868 // Set the last argument for this to be an incomplete request.
2869 EXPECT_TRUE(net::HttpCache::WriteResponseInfo(entry, &response, true, true));
2870 bool truncated = false;
2871 EXPECT_TRUE(net::HttpCache::ReadResponseInfo(entry, &response, &truncated));
2872 EXPECT_TRUE(truncated);
2873
2874 // And now test the opposite case.
2875 EXPECT_TRUE(net::HttpCache::WriteResponseInfo(entry, &response, true, false));
2876 truncated = true;
2877 EXPECT_TRUE(net::HttpCache::ReadResponseInfo(entry, &response, &truncated));
2878 EXPECT_FALSE(truncated);
2879 entry->Close();
2880}
2881
2882// Tests that we delete an entry when the request is cancelled before starting
2883// to read from the network.
2884TEST(HttpCache, DoomOnDestruction) {
2885 MockHttpCache cache;
2886 cache.http_cache()->set_enable_range_support(true);
2887
2888 MockHttpRequest request(kSimpleGET_Transaction);
2889
[email protected]1638d602009-09-24 03:49:172890 Context* c = new Context();
2891 int rv = cache.http_cache()->CreateTransaction(&c->trans);
2892 EXPECT_EQ(net::OK, rv);
[email protected]28accfe2009-09-04 23:36:332893
[email protected]1638d602009-09-24 03:49:172894 rv = c->trans->Start(&request, &c->callback, NULL);
[email protected]28accfe2009-09-04 23:36:332895 if (rv == net::ERR_IO_PENDING)
2896 c->result = c->callback.WaitForResult();
2897
2898 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2899 EXPECT_EQ(0, cache.disk_cache()->open_count());
2900 EXPECT_EQ(1, cache.disk_cache()->create_count());
2901
2902 // Destroy the transaction. We only have the headers so we should delete this
2903 // entry.
2904 delete c;
2905
2906 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
2907
2908 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2909 EXPECT_EQ(0, cache.disk_cache()->open_count());
2910 EXPECT_EQ(2, cache.disk_cache()->create_count());
2911}
2912
2913// Tests that we mark an entry as incomplete when the request is cancelled.
2914TEST(HttpCache, Set_Truncated_Flag) {
2915 MockHttpCache cache;
2916 cache.http_cache()->set_enable_range_support(true);
2917
2918 MockHttpRequest request(kSimpleGET_Transaction);
2919
[email protected]1638d602009-09-24 03:49:172920 Context* c = new Context();
2921 int rv = cache.http_cache()->CreateTransaction(&c->trans);
2922 EXPECT_EQ(net::OK, rv);
[email protected]28accfe2009-09-04 23:36:332923
[email protected]1638d602009-09-24 03:49:172924 rv = c->trans->Start(&request, &c->callback, NULL);
[email protected]28accfe2009-09-04 23:36:332925 if (rv == net::ERR_IO_PENDING)
2926 rv = c->callback.WaitForResult();
2927
2928 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2929 EXPECT_EQ(0, cache.disk_cache()->open_count());
2930 EXPECT_EQ(1, cache.disk_cache()->create_count());
2931
2932 // Make sure that the entry has some data stored.
2933 scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(10);
2934 rv = c->trans->Read(buf, buf->size(), &c->callback);
2935 if (rv == net::ERR_IO_PENDING)
2936 rv = c->callback.WaitForResult();
2937 EXPECT_EQ(buf->size(), rv);
2938
2939 // Destroy the transaction.
2940 delete c;
2941
2942 // Verify that the entry is marked as incomplete.
2943 disk_cache::Entry* entry;
2944 ASSERT_TRUE(cache.disk_cache()->OpenEntry(kSimpleGET_Transaction.url,
2945 &entry));
2946 net::HttpResponseInfo response;
2947 bool truncated = false;
2948 EXPECT_TRUE(net::HttpCache::ReadResponseInfo(entry, &response, &truncated));
2949 EXPECT_TRUE(truncated);
2950 entry->Close();
2951}
2952
2953// Tests that we can continue with a request that was interrupted.
2954TEST(HttpCache, GET_IncompleteResource) {
2955 MockHttpCache cache;
2956 cache.http_cache()->set_enable_range_support(true);
2957 AddMockTransaction(&kRangeGET_TransactionOK);
2958
2959 // Create a disk cache entry that stores an incomplete resource.
2960 disk_cache::Entry* entry;
2961 ASSERT_TRUE(cache.disk_cache()->CreateEntry(kRangeGET_TransactionOK.url,
2962 &entry));
2963
2964 // Content-length will be intentionally bogus.
2965 std::string raw_headers("HTTP/1.1 200 OK\n"
2966 "Last-Modified: something\n"
2967 "ETag: \"foo\"\n"
2968 "Accept-Ranges: bytes\n"
2969 "Content-Length: 10\n");
2970 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
2971 raw_headers.size());
2972
2973 net::HttpResponseInfo response;
2974 response.headers = new net::HttpResponseHeaders(raw_headers);
2975 // Set the last argument for this to be an incomplete request.
2976 EXPECT_TRUE(net::HttpCache::WriteResponseInfo(entry, &response, true, true));
2977
2978 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
2979 int len = static_cast<int>(base::strlcpy(buf->data(),
2980 "rg: 00-09 rg: 10-19 ", 100));
2981 EXPECT_EQ(len, entry->WriteData(1, 0, buf, len, NULL, true));
2982
2983 // Now make a regular request.
2984 std::string headers;
2985 MockTransaction transaction(kRangeGET_TransactionOK);
[email protected]e75e8af2009-11-03 00:04:202986 transaction.request_headers = EXTRA_HEADER;
[email protected]28accfe2009-09-04 23:36:332987 transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49 "
2988 "rg: 50-59 rg: 60-69 rg: 70-79 ";
2989 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
2990
2991 // We update the headers with the ones received while revalidating.
2992 std::string expected_headers(
2993 "HTTP/1.1 200 OK\n"
2994 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
2995 "Accept-Ranges: bytes\n"
2996 "ETag: \"foo\"\n"
2997 "Content-Length: 10\n");
2998
2999 EXPECT_EQ(expected_headers, headers);
3000 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3001 EXPECT_EQ(1, cache.disk_cache()->open_count());
3002 EXPECT_EQ(1, cache.disk_cache()->create_count());
3003
3004 RemoveMockTransaction(&kRangeGET_TransactionOK);
3005
3006 // Verify that the disk entry was updated.
3007 EXPECT_EQ(80, entry->GetDataSize(1));
3008 bool truncated = true;
3009 EXPECT_TRUE(net::HttpCache::ReadResponseInfo(entry, &response, &truncated));
3010 EXPECT_FALSE(truncated);
3011 entry->Close();
3012}
3013
[email protected]ecd8becb2009-10-02 17:57:453014// Tests that we can handle range requests when we have a truncated entry.
3015TEST(HttpCache, RangeGET_IncompleteResource) {
3016 MockHttpCache cache;
3017 cache.http_cache()->set_enable_range_support(true);
3018 AddMockTransaction(&kRangeGET_TransactionOK);
3019
3020 // Create a disk cache entry that stores an incomplete resource.
3021 disk_cache::Entry* entry;
3022 ASSERT_TRUE(cache.disk_cache()->CreateEntry(kRangeGET_TransactionOK.url,
3023 &entry));
3024
3025 // Content-length will be intentionally bogus.
3026 std::string raw_headers("HTTP/1.1 200 OK\n"
3027 "Last-Modified: something\n"
3028 "ETag: \"foo\"\n"
3029 "Accept-Ranges: bytes\n"
3030 "Content-Length: 10\n");
3031 raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
3032 raw_headers.size());
3033
3034 net::HttpResponseInfo response;
3035 response.headers = new net::HttpResponseHeaders(raw_headers);
3036 // Set the last argument for this to be an incomplete request.
3037 EXPECT_TRUE(net::HttpCache::WriteResponseInfo(entry, &response, true, true));
3038
3039 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
3040 int len = static_cast<int>(base::strlcpy(buf->data(),
3041 "rg: 00-09 rg: 10-19 ", 100));
3042 EXPECT_EQ(len, entry->WriteData(1, 0, buf, len, NULL, true));
3043 entry->Close();
3044
3045 // Now make a range request.
3046 std::string headers;
3047 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3048 &headers);
3049
3050 EXPECT_TRUE(Verify206Response(headers, 40, 49));
3051 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3052 EXPECT_EQ(1, cache.disk_cache()->open_count());
3053 EXPECT_EQ(2, cache.disk_cache()->create_count());
3054
3055 RemoveMockTransaction(&kRangeGET_TransactionOK);
3056}
3057
initial.commit586acc5fe2008-07-26 22:42:523058TEST(HttpCache, SyncRead) {
3059 MockHttpCache cache;
3060
3061 // This test ensures that a read that completes synchronously does not cause
3062 // any problems.
3063
3064 ScopedMockTransaction transaction(kSimpleGET_Transaction);
3065 transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START |
[email protected]73cae572009-10-22 18:36:193066 TEST_MODE_SYNC_CACHE_READ |
3067 TEST_MODE_SYNC_CACHE_WRITE);
initial.commit586acc5fe2008-07-26 22:42:523068
3069 MockHttpRequest r1(transaction),
3070 r2(transaction),
3071 r3(transaction);
3072
3073 TestTransactionConsumer c1(cache.http_cache()),
3074 c2(cache.http_cache()),
3075 c3(cache.http_cache());
3076
[email protected]684970b2009-08-14 04:54:463077 c1.Start(&r1, NULL);
initial.commit586acc5fe2008-07-26 22:42:523078
3079 r2.load_flags |= net::LOAD_ONLY_FROM_CACHE;
[email protected]684970b2009-08-14 04:54:463080 c2.Start(&r2, NULL);
initial.commit586acc5fe2008-07-26 22:42:523081
3082 r3.load_flags |= net::LOAD_ONLY_FROM_CACHE;
[email protected]684970b2009-08-14 04:54:463083 c3.Start(&r3, NULL);
initial.commit586acc5fe2008-07-26 22:42:523084
3085 MessageLoop::current()->Run();
3086
3087 EXPECT_TRUE(c1.is_done());
3088 EXPECT_TRUE(c2.is_done());
3089 EXPECT_TRUE(c3.is_done());
3090
3091 EXPECT_EQ(net::OK, c1.error());
3092 EXPECT_EQ(net::OK, c2.error());
3093 EXPECT_EQ(net::OK, c3.error());
3094}
3095
3096TEST(HttpCache, ValidationResultsIn200) {
3097 MockHttpCache cache;
3098
3099 // This test ensures that a conditional request, which results in a 200
3100 // instead of a 304, properly truncates the existing response data.
3101
3102 // write to the cache
3103 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
3104
3105 // force this transaction to validate the cache
3106 MockTransaction transaction(kETagGET_Transaction);
3107 transaction.load_flags |= net::LOAD_VALIDATE_CACHE;
3108 RunTransactionTest(cache.http_cache(), transaction);
3109
3110 // read from the cache
3111 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
3112}
3113
3114TEST(HttpCache, CachedRedirect) {
3115 MockHttpCache cache;
3116
3117 ScopedMockTransaction kTestTransaction(kSimpleGET_Transaction);
3118 kTestTransaction.status = "HTTP/1.1 301 Moved Permanently";
3119 kTestTransaction.response_headers = "Location: http://www.bar.com/\n";
3120
3121 MockHttpRequest request(kTestTransaction);
3122 TestCompletionCallback callback;
3123
3124 // write to the cache
3125 {
[email protected]1638d602009-09-24 03:49:173126 scoped_ptr<net::HttpTransaction> trans;
3127 int rv = cache.http_cache()->CreateTransaction(&trans);
3128 EXPECT_EQ(net::OK, rv);
[email protected]af4876d2008-10-21 23:10:573129 ASSERT_TRUE(trans.get());
initial.commit586acc5fe2008-07-26 22:42:523130
[email protected]1638d602009-09-24 03:49:173131 rv = trans->Start(&request, &callback, NULL);
initial.commit586acc5fe2008-07-26 22:42:523132 if (rv == net::ERR_IO_PENDING)
3133 rv = callback.WaitForResult();
3134 ASSERT_EQ(net::OK, rv);
3135
3136 const net::HttpResponseInfo* info = trans->GetResponseInfo();
3137 ASSERT_TRUE(info);
3138
3139 EXPECT_EQ(info->headers->response_code(), 301);
3140
3141 std::string location;
3142 info->headers->EnumerateHeader(NULL, "Location", &location);
3143 EXPECT_EQ(location, "http://www.bar.com/");
3144
[email protected]af4876d2008-10-21 23:10:573145 // Destroy transaction when going out of scope. We have not actually
3146 // read the response body -- want to test that it is still getting cached.
initial.commit586acc5fe2008-07-26 22:42:523147 }
3148 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3149 EXPECT_EQ(0, cache.disk_cache()->open_count());
3150 EXPECT_EQ(1, cache.disk_cache()->create_count());
3151
3152 // read from the cache
3153 {
[email protected]1638d602009-09-24 03:49:173154 scoped_ptr<net::HttpTransaction> trans;
3155 int rv = cache.http_cache()->CreateTransaction(&trans);
3156 EXPECT_EQ(net::OK, rv);
[email protected]af4876d2008-10-21 23:10:573157 ASSERT_TRUE(trans.get());
initial.commit586acc5fe2008-07-26 22:42:523158
[email protected]1638d602009-09-24 03:49:173159 rv = trans->Start(&request, &callback, NULL);
initial.commit586acc5fe2008-07-26 22:42:523160 if (rv == net::ERR_IO_PENDING)
3161 rv = callback.WaitForResult();
3162 ASSERT_EQ(net::OK, rv);
3163
3164 const net::HttpResponseInfo* info = trans->GetResponseInfo();
3165 ASSERT_TRUE(info);
3166
3167 EXPECT_EQ(info->headers->response_code(), 301);
3168
3169 std::string location;
3170 info->headers->EnumerateHeader(NULL, "Location", &location);
3171 EXPECT_EQ(location, "http://www.bar.com/");
3172
[email protected]af4876d2008-10-21 23:10:573173 // Destroy transaction when going out of scope. We have not actually
3174 // read the response body -- want to test that it is still getting cached.
initial.commit586acc5fe2008-07-26 22:42:523175 }
3176 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3177 EXPECT_EQ(1, cache.disk_cache()->open_count());
3178 EXPECT_EQ(1, cache.disk_cache()->create_count());
3179}
3180
3181TEST(HttpCache, CacheControlNoStore) {
3182 MockHttpCache cache;
3183
3184 ScopedMockTransaction transaction(kSimpleGET_Transaction);
3185 transaction.response_headers = "cache-control: no-store\n";
3186
3187 // initial load
3188 RunTransactionTest(cache.http_cache(), transaction);
3189
3190 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3191 EXPECT_EQ(0, cache.disk_cache()->open_count());
3192 EXPECT_EQ(1, cache.disk_cache()->create_count());
3193
3194 // try loading again; it should result in a network fetch
3195 RunTransactionTest(cache.http_cache(), transaction);
3196
3197 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3198 EXPECT_EQ(0, cache.disk_cache()->open_count());
3199 EXPECT_EQ(2, cache.disk_cache()->create_count());
3200
3201 disk_cache::Entry* entry;
3202 bool exists = cache.disk_cache()->OpenEntry(transaction.url, &entry);
3203 EXPECT_FALSE(exists);
3204}
3205
3206TEST(HttpCache, CacheControlNoStore2) {
3207 // this test is similar to the above test, except that the initial response
3208 // is cachable, but when it is validated, no-store is received causing the
3209 // cached document to be deleted.
3210 MockHttpCache cache;
3211
3212 ScopedMockTransaction transaction(kETagGET_Transaction);
3213
3214 // initial load
3215 RunTransactionTest(cache.http_cache(), transaction);
3216
3217 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3218 EXPECT_EQ(0, cache.disk_cache()->open_count());
3219 EXPECT_EQ(1, cache.disk_cache()->create_count());
3220
3221 // try loading again; it should result in a network fetch
3222 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
3223 transaction.response_headers = "cache-control: no-store\n";
3224 RunTransactionTest(cache.http_cache(), transaction);
3225
3226 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3227 EXPECT_EQ(1, cache.disk_cache()->open_count());
3228 EXPECT_EQ(1, cache.disk_cache()->create_count());
3229
3230 disk_cache::Entry* entry;
3231 bool exists = cache.disk_cache()->OpenEntry(transaction.url, &entry);
3232 EXPECT_FALSE(exists);
3233}
3234
3235TEST(HttpCache, CacheControlNoStore3) {
3236 // this test is similar to the above test, except that the response is a 304
3237 // instead of a 200. this should never happen in practice, but it seems like
3238 // a good thing to verify that we still destroy the cache entry.
3239 MockHttpCache cache;
3240
3241 ScopedMockTransaction transaction(kETagGET_Transaction);
3242
3243 // initial load
3244 RunTransactionTest(cache.http_cache(), transaction);
3245
3246 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3247 EXPECT_EQ(0, cache.disk_cache()->open_count());
3248 EXPECT_EQ(1, cache.disk_cache()->create_count());
3249
3250 // try loading again; it should result in a network fetch
3251 transaction.load_flags = net::LOAD_VALIDATE_CACHE;
3252 transaction.response_headers = "cache-control: no-store\n";
3253 transaction.status = "HTTP/1.1 304 Not Modified";
3254 RunTransactionTest(cache.http_cache(), transaction);
3255
3256 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3257 EXPECT_EQ(1, cache.disk_cache()->open_count());
3258 EXPECT_EQ(1, cache.disk_cache()->create_count());
3259
3260 disk_cache::Entry* entry;
3261 bool exists = cache.disk_cache()->OpenEntry(transaction.url, &entry);
3262 EXPECT_FALSE(exists);
3263}
3264
3265// Ensure that we don't cache requests served over bad HTTPS.
3266TEST(HttpCache, SimpleGET_SSLError) {
3267 MockHttpCache cache;
3268
3269 MockTransaction transaction = kSimpleGET_Transaction;
3270 transaction.cert_status = net::CERT_STATUS_REVOKED;
3271 ScopedMockTransaction scoped_transaction(transaction);
3272
3273 // write to the cache
3274 RunTransactionTest(cache.http_cache(), transaction);
3275
3276 // Test that it was not cached.
3277 transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE;
3278
3279 MockHttpRequest request(transaction);
3280 TestCompletionCallback callback;
3281
[email protected]1638d602009-09-24 03:49:173282 scoped_ptr<net::HttpTransaction> trans;
3283 int rv = cache.http_cache()->CreateTransaction(&trans);
3284 EXPECT_EQ(net::OK, rv);
[email protected]af4876d2008-10-21 23:10:573285 ASSERT_TRUE(trans.get());
initial.commit586acc5fe2008-07-26 22:42:523286
[email protected]1638d602009-09-24 03:49:173287 rv = trans->Start(&request, &callback, NULL);
initial.commit586acc5fe2008-07-26 22:42:523288 if (rv == net::ERR_IO_PENDING)
3289 rv = callback.WaitForResult();
3290 ASSERT_EQ(net::ERR_CACHE_MISS, rv);
initial.commit586acc5fe2008-07-26 22:42:523291}
[email protected]3e2d38d2009-02-14 02:01:183292
3293// Ensure that we don't crash by if left-behind transactions.
3294TEST(HttpCache, OutlivedTransactions) {
3295 MockHttpCache* cache = new MockHttpCache;
3296
[email protected]1638d602009-09-24 03:49:173297 scoped_ptr<net::HttpTransaction> trans;
3298 int rv = cache->http_cache()->CreateTransaction(&trans);
3299 EXPECT_EQ(net::OK, rv);
3300
[email protected]b367d9a52009-02-27 01:02:513301 delete cache;
[email protected]1638d602009-09-24 03:49:173302 trans.reset();
[email protected]3e2d38d2009-02-14 02:01:183303}
[email protected]981797002009-06-05 07:14:153304
3305// Test that the disabled mode works.
3306TEST(HttpCache, CacheDisabledMode) {
3307 MockHttpCache cache;
3308
3309 // write to the cache
3310 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
3311
3312 // go into disabled mode
3313 cache.http_cache()->set_mode(net::HttpCache::DISABLE);
3314
3315 // force this transaction to write to the cache again
3316 MockTransaction transaction(kSimpleGET_Transaction);
3317
3318 RunTransactionTest(cache.http_cache(), transaction);
3319
3320 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3321 EXPECT_EQ(0, cache.disk_cache()->open_count());
3322 EXPECT_EQ(1, cache.disk_cache()->create_count());
3323}
[email protected]207d58c72009-09-04 18:59:293324
3325// Other tests check that the response headers of the cached response
3326// get updated on 304. Here we specifically check that the
[email protected]ca2f19e2009-09-04 22:53:163327// HttpResponseHeaders::request_time and HttpResponseHeaders::response_time
3328// fields also gets updated.
[email protected]207d58c72009-09-04 18:59:293329// http://crbug.com/20594.
[email protected]ca2f19e2009-09-04 22:53:163330TEST(HttpCache, UpdatesRequestResponseTimeOn304) {
[email protected]207d58c72009-09-04 18:59:293331 MockHttpCache cache;
3332
3333 const char* kUrl = "http://foobar";
3334 const char* kData = "body";
3335
3336 MockTransaction mock_network_response = { 0 };
3337 mock_network_response.url = kUrl;
3338
3339 AddMockTransaction(&mock_network_response);
3340
3341 // Request |kUrl|, causing |kNetResponse1| to be written to the cache.
3342
3343 MockTransaction request = { 0 };
3344 request.url = kUrl;
3345 request.method = "GET";
3346 request.request_headers = "";
3347 request.data = kData;
3348
3349 static const Response kNetResponse1 = {
3350 "HTTP/1.1 200 OK",
3351 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
3352 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
3353 kData
3354 };
3355
3356 kNetResponse1.AssignTo(&mock_network_response);
3357
3358 RunTransactionTest(cache.http_cache(), request);
3359
3360 // Request |kUrl| again, this time validating the cache and getting
3361 // a 304 back.
3362
3363 request.load_flags = net::LOAD_VALIDATE_CACHE;
3364
3365 static const Response kNetResponse2 = {
3366 "HTTP/1.1 304 Not Modified",
3367 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n",
3368 ""
3369 };
3370
3371 kNetResponse2.AssignTo(&mock_network_response);
3372
[email protected]ca2f19e2009-09-04 22:53:163373 base::Time request_time = base::Time() + base::TimeDelta::FromHours(1234);
3374 base::Time response_time = base::Time() + base::TimeDelta::FromHours(1235);
3375
3376 mock_network_response.request_time = request_time;
3377 mock_network_response.response_time = response_time;
[email protected]207d58c72009-09-04 18:59:293378
3379 net::HttpResponseInfo response;
3380 RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response);
3381
[email protected]ca2f19e2009-09-04 22:53:163382 // The request and response times should have been updated.
3383 EXPECT_EQ(request_time.ToInternalValue(),
3384 response.request_time.ToInternalValue());
3385 EXPECT_EQ(response_time.ToInternalValue(),
[email protected]207d58c72009-09-04 18:59:293386 response.response_time.ToInternalValue());
3387
3388 std::string headers;
3389 response.headers->GetNormalizedHeaders(&headers);
3390
3391 EXPECT_EQ("HTTP/1.1 200 OK\n"
3392 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
3393 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
3394 headers);
3395
3396 RemoveMockTransaction(&mock_network_response);
3397}