[Sync] Remove periodic sync for Chrome for Android
[chromium-blink-merge.git] / net / http / http_cache_unittest.cc
blob017334302a3114862ae04bf5562e4badac113230
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_cache.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/test/simple_test_clock.h"
17 #include "net/base/cache_type.h"
18 #include "net/base/elements_upload_data_stream.h"
19 #include "net/base/host_port_pair.h"
20 #include "net/base/load_flags.h"
21 #include "net/base/load_timing_info.h"
22 #include "net/base/load_timing_info_test_util.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/upload_bytes_element_reader.h"
25 #include "net/cert/cert_status_flags.h"
26 #include "net/disk_cache/disk_cache.h"
27 #include "net/http/http_byte_range.h"
28 #include "net/http/http_cache_transaction.h"
29 #include "net/http/http_request_headers.h"
30 #include "net/http/http_request_info.h"
31 #include "net/http/http_response_headers.h"
32 #include "net/http/http_response_info.h"
33 #include "net/http/http_transaction.h"
34 #include "net/http/http_transaction_test_util.h"
35 #include "net/http/http_util.h"
36 #include "net/http/mock_http_cache.h"
37 #include "net/log/test_net_log.h"
38 #include "net/log/test_net_log_entry.h"
39 #include "net/log/test_net_log_util.h"
40 #include "net/socket/client_socket_handle.h"
41 #include "net/ssl/ssl_cert_request_info.h"
42 #include "net/websockets/websocket_handshake_stream_base.h"
43 #include "testing/gtest/include/gtest/gtest.h"
45 using base::Time;
47 namespace net {
49 namespace {
51 // Tests the load timing values of a request that goes through a
52 // MockNetworkTransaction.
53 void TestLoadTimingNetworkRequest(const LoadTimingInfo& load_timing_info) {
54 EXPECT_FALSE(load_timing_info.socket_reused);
55 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
57 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
58 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
60 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
61 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
62 EXPECT_LE(load_timing_info.connect_timing.connect_end,
63 load_timing_info.send_start);
65 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
67 // Set by URLRequest / URLRequestHttpJob, at a higher level.
68 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
69 EXPECT_TRUE(load_timing_info.request_start.is_null());
70 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
73 // Tests the load timing values of a request that receives a cached response.
74 void TestLoadTimingCachedResponse(const LoadTimingInfo& load_timing_info) {
75 EXPECT_FALSE(load_timing_info.socket_reused);
76 EXPECT_EQ(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
78 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
79 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
81 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
83 // Only the send start / end times should be sent, and they should have the
84 // same value.
85 EXPECT_FALSE(load_timing_info.send_start.is_null());
86 EXPECT_EQ(load_timing_info.send_start, load_timing_info.send_end);
88 // Set by URLRequest / URLRequestHttpJob, at a higher level.
89 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
90 EXPECT_TRUE(load_timing_info.request_start.is_null());
91 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
94 class DeleteCacheCompletionCallback : public TestCompletionCallbackBase {
95 public:
96 explicit DeleteCacheCompletionCallback(MockHttpCache* cache)
97 : cache_(cache),
98 callback_(base::Bind(&DeleteCacheCompletionCallback::OnComplete,
99 base::Unretained(this))) {
102 const CompletionCallback& callback() const { return callback_; }
104 private:
105 void OnComplete(int result) {
106 delete cache_;
107 SetResult(result);
110 MockHttpCache* cache_;
111 CompletionCallback callback_;
113 DISALLOW_COPY_AND_ASSIGN(DeleteCacheCompletionCallback);
116 //-----------------------------------------------------------------------------
117 // helpers
119 void ReadAndVerifyTransaction(HttpTransaction* trans,
120 const MockTransaction& trans_info) {
121 std::string content;
122 int rv = ReadTransaction(trans, &content);
124 EXPECT_EQ(OK, rv);
125 std::string expected(trans_info.data);
126 EXPECT_EQ(expected, content);
129 void RunTransactionTestBase(HttpCache* cache,
130 const MockTransaction& trans_info,
131 const MockHttpRequest& request,
132 HttpResponseInfo* response_info,
133 const BoundNetLog& net_log,
134 LoadTimingInfo* load_timing_info,
135 int64* received_bytes) {
136 TestCompletionCallback callback;
138 // write to the cache
140 scoped_ptr<HttpTransaction> trans;
141 int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &trans);
142 EXPECT_EQ(OK, rv);
143 ASSERT_TRUE(trans.get());
145 rv = trans->Start(&request, callback.callback(), net_log);
146 if (rv == ERR_IO_PENDING)
147 rv = callback.WaitForResult();
148 ASSERT_EQ(trans_info.return_code, rv);
150 if (OK != rv)
151 return;
153 const HttpResponseInfo* response = trans->GetResponseInfo();
154 ASSERT_TRUE(response);
156 if (response_info)
157 *response_info = *response;
159 if (load_timing_info) {
160 // If a fake network connection is used, need a NetLog to get a fake socket
161 // ID.
162 EXPECT_TRUE(net_log.net_log());
163 *load_timing_info = LoadTimingInfo();
164 trans->GetLoadTimingInfo(load_timing_info);
167 ReadAndVerifyTransaction(trans.get(), trans_info);
169 if (received_bytes)
170 *received_bytes = trans->GetTotalReceivedBytes();
173 void RunTransactionTestWithRequest(HttpCache* cache,
174 const MockTransaction& trans_info,
175 const MockHttpRequest& request,
176 HttpResponseInfo* response_info) {
177 RunTransactionTestBase(cache, trans_info, request, response_info,
178 BoundNetLog(), NULL, NULL);
181 void RunTransactionTestAndGetTiming(HttpCache* cache,
182 const MockTransaction& trans_info,
183 const BoundNetLog& log,
184 LoadTimingInfo* load_timing_info) {
185 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
186 NULL, log, load_timing_info, NULL);
189 void RunTransactionTest(HttpCache* cache, const MockTransaction& trans_info) {
190 RunTransactionTestAndGetTiming(cache, trans_info, BoundNetLog(), NULL);
193 void RunTransactionTestWithLog(HttpCache* cache,
194 const MockTransaction& trans_info,
195 const BoundNetLog& log) {
196 RunTransactionTestAndGetTiming(cache, trans_info, log, NULL);
199 void RunTransactionTestWithResponseInfo(HttpCache* cache,
200 const MockTransaction& trans_info,
201 HttpResponseInfo* response) {
202 RunTransactionTestWithRequest(cache, trans_info, MockHttpRequest(trans_info),
203 response);
206 void RunTransactionTestWithResponseInfoAndGetTiming(
207 HttpCache* cache,
208 const MockTransaction& trans_info,
209 HttpResponseInfo* response,
210 const BoundNetLog& log,
211 LoadTimingInfo* load_timing_info) {
212 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
213 response, log, load_timing_info, NULL);
216 void RunTransactionTestWithResponse(HttpCache* cache,
217 const MockTransaction& trans_info,
218 std::string* response_headers) {
219 HttpResponseInfo response;
220 RunTransactionTestWithResponseInfo(cache, trans_info, &response);
221 response.headers->GetNormalizedHeaders(response_headers);
224 void RunTransactionTestWithResponseAndGetTiming(
225 HttpCache* cache,
226 const MockTransaction& trans_info,
227 std::string* response_headers,
228 const BoundNetLog& log,
229 LoadTimingInfo* load_timing_info) {
230 HttpResponseInfo response;
231 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
232 &response, log, load_timing_info, NULL);
233 response.headers->GetNormalizedHeaders(response_headers);
236 // This class provides a handler for kFastNoStoreGET_Transaction so that the
237 // no-store header can be included on demand.
238 class FastTransactionServer {
239 public:
240 FastTransactionServer() {
241 no_store = false;
243 ~FastTransactionServer() {}
245 void set_no_store(bool value) { no_store = value; }
247 static void FastNoStoreHandler(const HttpRequestInfo* request,
248 std::string* response_status,
249 std::string* response_headers,
250 std::string* response_data) {
251 if (no_store)
252 *response_headers = "Cache-Control: no-store\n";
255 private:
256 static bool no_store;
257 DISALLOW_COPY_AND_ASSIGN(FastTransactionServer);
259 bool FastTransactionServer::no_store;
261 const MockTransaction kFastNoStoreGET_Transaction = {
262 "http://www.google.com/nostore",
263 "GET",
264 base::Time(),
266 LOAD_VALIDATE_CACHE,
267 "HTTP/1.1 200 OK",
268 "Cache-Control: max-age=10000\n",
269 base::Time(),
270 "<html><body>Google Blah Blah</body></html>",
271 TEST_MODE_SYNC_NET_START,
272 &FastTransactionServer::FastNoStoreHandler,
274 OK};
276 // This class provides a handler for kRangeGET_TransactionOK so that the range
277 // request can be served on demand.
278 class RangeTransactionServer {
279 public:
280 RangeTransactionServer() {
281 not_modified_ = false;
282 modified_ = false;
283 bad_200_ = false;
285 ~RangeTransactionServer() {
286 not_modified_ = false;
287 modified_ = false;
288 bad_200_ = false;
291 // Returns only 416 or 304 when set.
292 void set_not_modified(bool value) { not_modified_ = value; }
294 // Returns 206 when revalidating a range (instead of 304).
295 void set_modified(bool value) { modified_ = value; }
297 // Returns 200 instead of 206 (a malformed response overall).
298 void set_bad_200(bool value) { bad_200_ = value; }
300 // Other than regular range related behavior (and the flags mentioned above),
301 // the server reacts to requests headers like so:
302 // X-Require-Mock-Auth -> return 401.
303 // X-Return-Default-Range -> assume 40-49 was requested.
304 static void RangeHandler(const HttpRequestInfo* request,
305 std::string* response_status,
306 std::string* response_headers,
307 std::string* response_data);
309 private:
310 static bool not_modified_;
311 static bool modified_;
312 static bool bad_200_;
313 DISALLOW_COPY_AND_ASSIGN(RangeTransactionServer);
315 bool RangeTransactionServer::not_modified_ = false;
316 bool RangeTransactionServer::modified_ = false;
317 bool RangeTransactionServer::bad_200_ = false;
319 // A dummy extra header that must be preserved on a given request.
321 // EXTRA_HEADER_LINE doesn't include a line terminator because it
322 // will be passed to AddHeaderFromString() which doesn't accept them.
323 #define EXTRA_HEADER_LINE "Extra: header"
325 // EXTRA_HEADER contains a line terminator, as expected by
326 // AddHeadersFromString() (_not_ AddHeaderFromString()).
327 #define EXTRA_HEADER EXTRA_HEADER_LINE "\r\n"
329 static const char kExtraHeaderKey[] = "Extra";
331 // Static.
332 void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request,
333 std::string* response_status,
334 std::string* response_headers,
335 std::string* response_data) {
336 if (request->extra_headers.IsEmpty()) {
337 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
338 response_data->clear();
339 return;
342 // We want to make sure we don't delete extra headers.
343 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
345 if (request->extra_headers.HasHeader("X-Require-Mock-Auth") &&
346 !request->extra_headers.HasHeader("Authorization")) {
347 response_status->assign("HTTP/1.1 401 Unauthorized");
348 response_data->assign("WWW-Authenticate: Foo\n");
349 return;
352 if (not_modified_) {
353 response_status->assign("HTTP/1.1 304 Not Modified");
354 response_data->clear();
355 return;
358 std::vector<HttpByteRange> ranges;
359 std::string range_header;
360 if (!request->extra_headers.GetHeader(HttpRequestHeaders::kRange,
361 &range_header) ||
362 !HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ ||
363 ranges.size() != 1) {
364 // This is not a byte range request. We return 200.
365 response_status->assign("HTTP/1.1 200 OK");
366 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT");
367 response_data->assign("Not a range");
368 return;
371 // We can handle this range request.
372 HttpByteRange byte_range = ranges[0];
374 if (request->extra_headers.HasHeader("X-Return-Default-Range")) {
375 byte_range.set_first_byte_position(40);
376 byte_range.set_last_byte_position(49);
379 if (byte_range.first_byte_position() > 79) {
380 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
381 response_data->clear();
382 return;
385 EXPECT_TRUE(byte_range.ComputeBounds(80));
386 int start = static_cast<int>(byte_range.first_byte_position());
387 int end = static_cast<int>(byte_range.last_byte_position());
389 EXPECT_LT(end, 80);
391 std::string content_range = base::StringPrintf(
392 "Content-Range: bytes %d-%d/80\n", start, end);
393 response_headers->append(content_range);
395 if (!request->extra_headers.HasHeader("If-None-Match") || modified_) {
396 std::string data;
397 if (end == start) {
398 EXPECT_EQ(0, end % 10);
399 data = "r";
400 } else {
401 EXPECT_EQ(9, (end - start) % 10);
402 for (int block_start = start; block_start < end; block_start += 10) {
403 base::StringAppendF(&data, "rg: %02d-%02d ",
404 block_start, block_start + 9);
407 *response_data = data;
409 if (end - start != 9) {
410 // We also have to fix content-length.
411 int len = end - start + 1;
412 std::string content_length = base::StringPrintf("Content-Length: %d\n",
413 len);
414 response_headers->replace(response_headers->find("Content-Length:"),
415 content_length.size(), content_length);
417 } else {
418 response_status->assign("HTTP/1.1 304 Not Modified");
419 response_data->clear();
423 const MockTransaction kRangeGET_TransactionOK = {
424 "http://www.google.com/range",
425 "GET",
426 base::Time(),
427 "Range: bytes = 40-49\r\n" EXTRA_HEADER,
428 LOAD_NORMAL,
429 "HTTP/1.1 206 Partial Content",
430 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
431 "ETag: \"foo\"\n"
432 "Accept-Ranges: bytes\n"
433 "Content-Length: 10\n",
434 base::Time(),
435 "rg: 40-49 ",
436 TEST_MODE_NORMAL,
437 &RangeTransactionServer::RangeHandler,
439 OK};
441 const char kFullRangeData[] =
442 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 "
443 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 ";
445 // Verifies the response headers (|response|) match a partial content
446 // response for the range starting at |start| and ending at |end|.
447 void Verify206Response(std::string response, int start, int end) {
448 std::string raw_headers(
449 HttpUtil::AssembleRawHeaders(response.data(), response.size()));
450 scoped_refptr<HttpResponseHeaders> headers(
451 new HttpResponseHeaders(raw_headers));
453 ASSERT_EQ(206, headers->response_code());
455 int64 range_start, range_end, object_size;
456 ASSERT_TRUE(
457 headers->GetContentRange(&range_start, &range_end, &object_size));
458 int64 content_length = headers->GetContentLength();
460 int length = end - start + 1;
461 ASSERT_EQ(length, content_length);
462 ASSERT_EQ(start, range_start);
463 ASSERT_EQ(end, range_end);
466 // Creates a truncated entry that can be resumed using byte ranges.
467 void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) {
468 // Create a disk cache entry that stores an incomplete resource.
469 disk_cache::Entry* entry;
470 ASSERT_TRUE(cache->CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
471 NULL));
473 raw_headers =
474 HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size());
476 HttpResponseInfo response;
477 response.response_time = base::Time::Now();
478 response.request_time = base::Time::Now();
479 response.headers = new HttpResponseHeaders(raw_headers);
480 // Set the last argument for this to be an incomplete request.
481 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
483 scoped_refptr<IOBuffer> buf(new IOBuffer(100));
484 int len = static_cast<int>(base::strlcpy(buf->data(),
485 "rg: 00-09 rg: 10-19 ", 100));
486 TestCompletionCallback cb;
487 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
488 EXPECT_EQ(len, cb.GetResult(rv));
489 entry->Close();
492 // Helper to represent a network HTTP response.
493 struct Response {
494 // Set this response into |trans|.
495 void AssignTo(MockTransaction* trans) const {
496 trans->status = status;
497 trans->response_headers = headers;
498 trans->data = body;
501 std::string status_and_headers() const {
502 return std::string(status) + "\n" + std::string(headers);
505 const char* status;
506 const char* headers;
507 const char* body;
510 struct Context {
511 Context() : result(ERR_IO_PENDING) {}
513 int result;
514 TestCompletionCallback callback;
515 scoped_ptr<HttpTransaction> trans;
518 class FakeWebSocketHandshakeStreamCreateHelper
519 : public WebSocketHandshakeStreamBase::CreateHelper {
520 public:
521 ~FakeWebSocketHandshakeStreamCreateHelper() override {}
522 WebSocketHandshakeStreamBase* CreateBasicStream(
523 scoped_ptr<ClientSocketHandle> connect,
524 bool using_proxy) override {
525 return NULL;
527 WebSocketHandshakeStreamBase* CreateSpdyStream(
528 const base::WeakPtr<SpdySession>& session,
529 bool use_relative_url) override {
530 return NULL;
534 // Returns true if |entry| is not one of the log types paid attention to in this
535 // test. Note that TYPE_HTTP_CACHE_WRITE_INFO and TYPE_HTTP_CACHE_*_DATA are
536 // ignored.
537 bool ShouldIgnoreLogEntry(const TestNetLogEntry& entry) {
538 switch (entry.type) {
539 case NetLog::TYPE_HTTP_CACHE_GET_BACKEND:
540 case NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY:
541 case NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY:
542 case NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY:
543 case NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY:
544 case NetLog::TYPE_HTTP_CACHE_READ_INFO:
545 return false;
546 default:
547 return true;
551 // Modifies |entries| to only include log entries created by the cache layer and
552 // asserted on in these tests.
553 void FilterLogEntries(TestNetLogEntry::List* entries) {
554 entries->erase(std::remove_if(entries->begin(), entries->end(),
555 &ShouldIgnoreLogEntry),
556 entries->end());
559 bool LogContainsEventType(const BoundTestNetLog& log,
560 NetLog::EventType expected) {
561 TestNetLogEntry::List entries;
562 log.GetEntries(&entries);
563 for (size_t i = 0; i < entries.size(); i++) {
564 if (entries[i].type == expected)
565 return true;
567 return false;
570 } // namespace
573 //-----------------------------------------------------------------------------
574 // Tests.
576 TEST(HttpCache, CreateThenDestroy) {
577 MockHttpCache cache;
579 scoped_ptr<HttpTransaction> trans;
580 EXPECT_EQ(OK, cache.CreateTransaction(&trans));
581 ASSERT_TRUE(trans.get());
584 TEST(HttpCache, GetBackend) {
585 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(0));
587 disk_cache::Backend* backend;
588 TestCompletionCallback cb;
589 // This will lazily initialize the backend.
590 int rv = cache.http_cache()->GetBackend(&backend, cb.callback());
591 EXPECT_EQ(OK, cb.GetResult(rv));
594 TEST(HttpCache, SimpleGET) {
595 MockHttpCache cache;
596 BoundTestNetLog log;
597 LoadTimingInfo load_timing_info;
599 // Write to the cache.
600 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
601 log.bound(), &load_timing_info);
603 EXPECT_EQ(1, cache.network_layer()->transaction_count());
604 EXPECT_EQ(0, cache.disk_cache()->open_count());
605 EXPECT_EQ(1, cache.disk_cache()->create_count());
606 TestLoadTimingNetworkRequest(load_timing_info);
609 TEST(HttpCache, SimpleGETNoDiskCache) {
610 MockHttpCache cache;
612 cache.disk_cache()->set_fail_requests();
614 BoundTestNetLog log;
615 LoadTimingInfo load_timing_info;
617 // Read from the network, and don't use the cache.
618 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
619 log.bound(), &load_timing_info);
621 // Check that the NetLog was filled as expected.
622 // (We attempted to both Open and Create entries, but both failed).
623 TestNetLogEntry::List entries;
624 log.GetEntries(&entries);
625 FilterLogEntries(&entries);
627 EXPECT_EQ(6u, entries.size());
628 EXPECT_TRUE(
629 LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
630 EXPECT_TRUE(
631 LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
632 EXPECT_TRUE(
633 LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
634 EXPECT_TRUE(
635 LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
636 EXPECT_TRUE(
637 LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
638 EXPECT_TRUE(
639 LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
641 EXPECT_EQ(1, cache.network_layer()->transaction_count());
642 EXPECT_EQ(0, cache.disk_cache()->open_count());
643 EXPECT_EQ(0, cache.disk_cache()->create_count());
644 TestLoadTimingNetworkRequest(load_timing_info);
647 TEST(HttpCache, SimpleGETNoDiskCache2) {
648 // This will initialize a cache object with NULL backend.
649 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
650 factory->set_fail(true);
651 factory->FinishCreation(); // We'll complete synchronously.
652 MockHttpCache cache(factory);
654 // Read from the network, and don't use the cache.
655 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
657 EXPECT_EQ(1, cache.network_layer()->transaction_count());
658 EXPECT_FALSE(cache.http_cache()->GetCurrentBackend());
661 // Tests that IOBuffers are not referenced after IO completes.
662 TEST(HttpCache, ReleaseBuffer) {
663 MockHttpCache cache;
665 // Write to the cache.
666 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
668 MockHttpRequest request(kSimpleGET_Transaction);
669 scoped_ptr<HttpTransaction> trans;
670 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
672 const int kBufferSize = 10;
673 scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
674 ReleaseBufferCompletionCallback cb(buffer.get());
676 int rv = trans->Start(&request, cb.callback(), BoundNetLog());
677 EXPECT_EQ(OK, cb.GetResult(rv));
679 rv = trans->Read(buffer.get(), kBufferSize, cb.callback());
680 EXPECT_EQ(kBufferSize, cb.GetResult(rv));
683 TEST(HttpCache, SimpleGETWithDiskFailures) {
684 MockHttpCache cache;
686 cache.disk_cache()->set_soft_failures(true);
688 // Read from the network, and fail to write to the cache.
689 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
691 EXPECT_EQ(1, cache.network_layer()->transaction_count());
692 EXPECT_EQ(0, cache.disk_cache()->open_count());
693 EXPECT_EQ(1, cache.disk_cache()->create_count());
695 // This one should see an empty cache again.
696 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
698 EXPECT_EQ(2, cache.network_layer()->transaction_count());
699 EXPECT_EQ(0, cache.disk_cache()->open_count());
700 EXPECT_EQ(2, cache.disk_cache()->create_count());
703 // Tests that disk failures after the transaction has started don't cause the
704 // request to fail.
705 TEST(HttpCache, SimpleGETWithDiskFailures2) {
706 MockHttpCache cache;
708 MockHttpRequest request(kSimpleGET_Transaction);
710 scoped_ptr<Context> c(new Context());
711 int rv = cache.CreateTransaction(&c->trans);
712 ASSERT_EQ(OK, rv);
714 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
715 EXPECT_EQ(ERR_IO_PENDING, rv);
716 rv = c->callback.WaitForResult();
718 // Start failing request now.
719 cache.disk_cache()->set_soft_failures(true);
721 // We have to open the entry again to propagate the failure flag.
722 disk_cache::Entry* en;
723 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &en));
724 en->Close();
726 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
727 c.reset();
729 EXPECT_EQ(1, cache.network_layer()->transaction_count());
730 EXPECT_EQ(1, cache.disk_cache()->open_count());
731 EXPECT_EQ(1, cache.disk_cache()->create_count());
733 // This one should see an empty cache again.
734 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
736 EXPECT_EQ(2, cache.network_layer()->transaction_count());
737 EXPECT_EQ(1, cache.disk_cache()->open_count());
738 EXPECT_EQ(2, cache.disk_cache()->create_count());
741 // Tests that we handle failures to read from the cache.
742 TEST(HttpCache, SimpleGETWithDiskFailures3) {
743 MockHttpCache cache;
745 // Read from the network, and write to the cache.
746 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
748 EXPECT_EQ(1, cache.network_layer()->transaction_count());
749 EXPECT_EQ(0, cache.disk_cache()->open_count());
750 EXPECT_EQ(1, cache.disk_cache()->create_count());
752 cache.disk_cache()->set_soft_failures(true);
754 // Now fail to read from the cache.
755 scoped_ptr<Context> c(new Context());
756 int rv = cache.CreateTransaction(&c->trans);
757 ASSERT_EQ(OK, rv);
759 MockHttpRequest request(kSimpleGET_Transaction);
760 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
761 EXPECT_EQ(OK, c->callback.GetResult(rv));
763 // Now verify that the entry was removed from the cache.
764 cache.disk_cache()->set_soft_failures(false);
766 EXPECT_EQ(2, cache.network_layer()->transaction_count());
767 EXPECT_EQ(1, cache.disk_cache()->open_count());
768 EXPECT_EQ(2, cache.disk_cache()->create_count());
770 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
772 EXPECT_EQ(3, cache.network_layer()->transaction_count());
773 EXPECT_EQ(1, cache.disk_cache()->open_count());
774 EXPECT_EQ(3, cache.disk_cache()->create_count());
777 TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
778 MockHttpCache cache;
780 BoundTestNetLog log;
781 LoadTimingInfo load_timing_info;
783 // Write to the cache.
784 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
785 log.bound(), &load_timing_info);
787 // Check that the NetLog was filled as expected.
788 TestNetLogEntry::List entries;
789 log.GetEntries(&entries);
790 FilterLogEntries(&entries);
792 EXPECT_EQ(8u, entries.size());
793 EXPECT_TRUE(
794 LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
795 EXPECT_TRUE(
796 LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
797 EXPECT_TRUE(
798 LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
799 EXPECT_TRUE(
800 LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
801 EXPECT_TRUE(
802 LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
803 EXPECT_TRUE(
804 LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
805 EXPECT_TRUE(
806 LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
807 EXPECT_TRUE(
808 LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
810 TestLoadTimingNetworkRequest(load_timing_info);
812 // Force this transaction to read from the cache.
813 MockTransaction transaction(kSimpleGET_Transaction);
814 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
816 log.Clear();
818 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
819 &load_timing_info);
821 // Check that the NetLog was filled as expected.
822 log.GetEntries(&entries);
823 FilterLogEntries(&entries);
825 EXPECT_EQ(8u, entries.size());
826 EXPECT_TRUE(
827 LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
828 EXPECT_TRUE(
829 LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
830 EXPECT_TRUE(
831 LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
832 EXPECT_TRUE(
833 LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
834 EXPECT_TRUE(
835 LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
836 EXPECT_TRUE(
837 LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
838 EXPECT_TRUE(
839 LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_READ_INFO));
840 EXPECT_TRUE(
841 LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_READ_INFO));
843 EXPECT_EQ(1, cache.network_layer()->transaction_count());
844 EXPECT_EQ(1, cache.disk_cache()->open_count());
845 EXPECT_EQ(1, cache.disk_cache()->create_count());
846 TestLoadTimingCachedResponse(load_timing_info);
849 TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Miss) {
850 MockHttpCache cache;
852 // force this transaction to read from the cache
853 MockTransaction transaction(kSimpleGET_Transaction);
854 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
856 MockHttpRequest request(transaction);
857 TestCompletionCallback callback;
859 scoped_ptr<HttpTransaction> trans;
860 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
862 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
863 if (rv == ERR_IO_PENDING)
864 rv = callback.WaitForResult();
865 ASSERT_EQ(ERR_CACHE_MISS, rv);
867 trans.reset();
869 EXPECT_EQ(0, cache.network_layer()->transaction_count());
870 EXPECT_EQ(0, cache.disk_cache()->open_count());
871 EXPECT_EQ(0, cache.disk_cache()->create_count());
874 TEST(HttpCache, SimpleGET_LoadPreferringCache_Hit) {
875 MockHttpCache cache;
877 // write to the cache
878 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
880 // force this transaction to read from the cache if valid
881 MockTransaction transaction(kSimpleGET_Transaction);
882 transaction.load_flags |= LOAD_PREFERRING_CACHE;
884 RunTransactionTest(cache.http_cache(), transaction);
886 EXPECT_EQ(1, cache.network_layer()->transaction_count());
887 EXPECT_EQ(1, cache.disk_cache()->open_count());
888 EXPECT_EQ(1, cache.disk_cache()->create_count());
891 TEST(HttpCache, SimpleGET_LoadPreferringCache_Miss) {
892 MockHttpCache cache;
894 // force this transaction to read from the cache if valid
895 MockTransaction transaction(kSimpleGET_Transaction);
896 transaction.load_flags |= LOAD_PREFERRING_CACHE;
898 RunTransactionTest(cache.http_cache(), transaction);
900 EXPECT_EQ(1, cache.network_layer()->transaction_count());
901 EXPECT_EQ(0, cache.disk_cache()->open_count());
902 EXPECT_EQ(1, cache.disk_cache()->create_count());
905 // Tests LOAD_PREFERRING_CACHE in the presence of vary headers.
906 TEST(HttpCache, SimpleGET_LoadPreferringCache_VaryMatch) {
907 MockHttpCache cache;
909 // Write to the cache.
910 MockTransaction transaction(kSimpleGET_Transaction);
911 transaction.request_headers = "Foo: bar\r\n";
912 transaction.response_headers = "Cache-Control: max-age=10000\n"
913 "Vary: Foo\n";
914 AddMockTransaction(&transaction);
915 RunTransactionTest(cache.http_cache(), transaction);
917 // Read from the cache.
918 transaction.load_flags |= LOAD_PREFERRING_CACHE;
919 RunTransactionTest(cache.http_cache(), transaction);
921 EXPECT_EQ(1, cache.network_layer()->transaction_count());
922 EXPECT_EQ(1, cache.disk_cache()->open_count());
923 EXPECT_EQ(1, cache.disk_cache()->create_count());
924 RemoveMockTransaction(&transaction);
927 // Tests LOAD_PREFERRING_CACHE in the presence of vary headers.
928 TEST(HttpCache, SimpleGET_LoadPreferringCache_VaryMismatch) {
929 MockHttpCache cache;
931 // Write to the cache.
932 MockTransaction transaction(kSimpleGET_Transaction);
933 transaction.request_headers = "Foo: bar\r\n";
934 transaction.response_headers = "Cache-Control: max-age=10000\n"
935 "Vary: Foo\n";
936 AddMockTransaction(&transaction);
937 RunTransactionTest(cache.http_cache(), transaction);
939 // Attempt to read from the cache... this is a vary mismatch that must reach
940 // the network again.
941 transaction.load_flags |= LOAD_PREFERRING_CACHE;
942 transaction.request_headers = "Foo: none\r\n";
943 BoundTestNetLog log;
944 LoadTimingInfo load_timing_info;
945 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
946 &load_timing_info);
948 EXPECT_EQ(2, cache.network_layer()->transaction_count());
949 EXPECT_EQ(1, cache.disk_cache()->open_count());
950 EXPECT_EQ(1, cache.disk_cache()->create_count());
951 TestLoadTimingNetworkRequest(load_timing_info);
952 RemoveMockTransaction(&transaction);
955 // Tests that was_cached was set properly on a failure, even if the cached
956 // response wasn't returned.
957 TEST(HttpCache, SimpleGET_CacheSignal_Failure) {
958 MockHttpCache cache;
960 // Prime cache.
961 MockTransaction transaction(kSimpleGET_Transaction);
962 transaction.response_headers = "Cache-Control: no-cache\n";
964 AddMockTransaction(&transaction);
965 RunTransactionTest(cache.http_cache(), transaction);
966 EXPECT_EQ(1, cache.network_layer()->transaction_count());
967 EXPECT_EQ(1, cache.disk_cache()->create_count());
968 RemoveMockTransaction(&transaction);
970 // Network failure with error; should fail but have was_cached set.
971 transaction.return_code = ERR_FAILED;
972 AddMockTransaction(&transaction);
974 MockHttpRequest request(transaction);
975 TestCompletionCallback callback;
976 scoped_ptr<HttpTransaction> trans;
977 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
978 EXPECT_EQ(OK, rv);
979 ASSERT_TRUE(trans.get());
980 rv = trans->Start(&request, callback.callback(), BoundNetLog());
981 EXPECT_EQ(ERR_FAILED, callback.GetResult(rv));
983 const HttpResponseInfo* response_info = trans->GetResponseInfo();
984 ASSERT_TRUE(response_info);
985 EXPECT_TRUE(response_info->was_cached);
986 EXPECT_EQ(2, cache.network_layer()->transaction_count());
988 RemoveMockTransaction(&transaction);
991 // Confirm if we have an empty cache, a read is marked as network verified.
992 TEST(HttpCache, SimpleGET_NetworkAccessed_Network) {
993 MockHttpCache cache;
995 // write to the cache
996 HttpResponseInfo response_info;
997 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
998 &response_info);
1000 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1001 EXPECT_EQ(0, cache.disk_cache()->open_count());
1002 EXPECT_EQ(1, cache.disk_cache()->create_count());
1003 EXPECT_TRUE(response_info.network_accessed);
1006 // Confirm if we have a fresh entry in cache, it isn't marked as
1007 // network verified.
1008 TEST(HttpCache, SimpleGET_NetworkAccessed_Cache) {
1009 MockHttpCache cache;
1011 // Prime cache.
1012 MockTransaction transaction(kSimpleGET_Transaction);
1014 RunTransactionTest(cache.http_cache(), transaction);
1015 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1016 EXPECT_EQ(1, cache.disk_cache()->create_count());
1018 // Re-run transaction; make sure we don't mark the network as accessed.
1019 HttpResponseInfo response_info;
1020 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
1021 &response_info);
1023 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1024 EXPECT_FALSE(response_info.server_data_unavailable);
1025 EXPECT_FALSE(response_info.network_accessed);
1028 TEST(HttpCache, SimpleGET_LoadBypassCache) {
1029 MockHttpCache cache;
1031 // Write to the cache.
1032 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1034 // Force this transaction to write to the cache again.
1035 MockTransaction transaction(kSimpleGET_Transaction);
1036 transaction.load_flags |= LOAD_BYPASS_CACHE;
1038 BoundTestNetLog log;
1039 LoadTimingInfo load_timing_info;
1041 // Write to the cache.
1042 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
1043 &load_timing_info);
1045 // Check that the NetLog was filled as expected.
1046 TestNetLogEntry::List entries;
1047 log.GetEntries(&entries);
1048 FilterLogEntries(&entries);
1050 EXPECT_EQ(8u, entries.size());
1051 EXPECT_TRUE(
1052 LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1053 EXPECT_TRUE(
1054 LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1055 EXPECT_TRUE(
1056 LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
1057 EXPECT_TRUE(
1058 LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
1059 EXPECT_TRUE(
1060 LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1061 EXPECT_TRUE(
1062 LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1063 EXPECT_TRUE(
1064 LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1065 EXPECT_TRUE(
1066 LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1068 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1069 EXPECT_EQ(0, cache.disk_cache()->open_count());
1070 EXPECT_EQ(2, cache.disk_cache()->create_count());
1071 TestLoadTimingNetworkRequest(load_timing_info);
1074 TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit) {
1075 MockHttpCache cache;
1077 // write to the cache
1078 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1080 // force this transaction to write to the cache again
1081 MockTransaction transaction(kSimpleGET_Transaction);
1082 transaction.request_headers = "pragma: no-cache\r\n";
1084 RunTransactionTest(cache.http_cache(), transaction);
1086 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1087 EXPECT_EQ(0, cache.disk_cache()->open_count());
1088 EXPECT_EQ(2, cache.disk_cache()->create_count());
1091 TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit2) {
1092 MockHttpCache cache;
1094 // write to the cache
1095 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1097 // force this transaction to write to the cache again
1098 MockTransaction transaction(kSimpleGET_Transaction);
1099 transaction.request_headers = "cache-control: no-cache\r\n";
1101 RunTransactionTest(cache.http_cache(), transaction);
1103 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1104 EXPECT_EQ(0, cache.disk_cache()->open_count());
1105 EXPECT_EQ(2, cache.disk_cache()->create_count());
1108 TEST(HttpCache, SimpleGET_LoadValidateCache) {
1109 MockHttpCache cache;
1111 // Write to the cache.
1112 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1114 // Read from the cache.
1115 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1117 // Force this transaction to validate the cache.
1118 MockTransaction transaction(kSimpleGET_Transaction);
1119 transaction.load_flags |= LOAD_VALIDATE_CACHE;
1121 HttpResponseInfo response_info;
1122 BoundTestNetLog log;
1123 LoadTimingInfo load_timing_info;
1124 RunTransactionTestWithResponseInfoAndGetTiming(
1125 cache.http_cache(), transaction, &response_info, log.bound(),
1126 &load_timing_info);
1128 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1129 EXPECT_EQ(1, cache.disk_cache()->open_count());
1130 EXPECT_EQ(1, cache.disk_cache()->create_count());
1131 EXPECT_TRUE(response_info.network_accessed);
1132 TestLoadTimingNetworkRequest(load_timing_info);
1135 TEST(HttpCache, SimpleGET_LoadValidateCache_Implicit) {
1136 MockHttpCache cache;
1138 // write to the cache
1139 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1141 // read from the cache
1142 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1144 // force this transaction to validate the cache
1145 MockTransaction transaction(kSimpleGET_Transaction);
1146 transaction.request_headers = "cache-control: max-age=0\r\n";
1148 RunTransactionTest(cache.http_cache(), transaction);
1150 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1151 EXPECT_EQ(1, cache.disk_cache()->open_count());
1152 EXPECT_EQ(1, cache.disk_cache()->create_count());
1155 static void PreserveRequestHeaders_Handler(const HttpRequestInfo* request,
1156 std::string* response_status,
1157 std::string* response_headers,
1158 std::string* response_data) {
1159 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
1162 // Tests that we don't remove extra headers for simple requests.
1163 TEST(HttpCache, SimpleGET_PreserveRequestHeaders) {
1164 MockHttpCache cache;
1166 MockTransaction transaction(kSimpleGET_Transaction);
1167 transaction.handler = PreserveRequestHeaders_Handler;
1168 transaction.request_headers = EXTRA_HEADER;
1169 transaction.response_headers = "Cache-Control: max-age=0\n";
1170 AddMockTransaction(&transaction);
1172 // Write, then revalidate the entry.
1173 RunTransactionTest(cache.http_cache(), transaction);
1174 RunTransactionTest(cache.http_cache(), transaction);
1176 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1177 EXPECT_EQ(1, cache.disk_cache()->open_count());
1178 EXPECT_EQ(1, cache.disk_cache()->create_count());
1179 RemoveMockTransaction(&transaction);
1182 // Tests that we don't remove extra headers for conditionalized requests.
1183 TEST(HttpCache, ConditionalizedGET_PreserveRequestHeaders) {
1184 MockHttpCache cache;
1186 // Write to the cache.
1187 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
1189 MockTransaction transaction(kETagGET_Transaction);
1190 transaction.handler = PreserveRequestHeaders_Handler;
1191 transaction.request_headers = "If-None-Match: \"foopy\"\r\n"
1192 EXTRA_HEADER;
1193 AddMockTransaction(&transaction);
1195 RunTransactionTest(cache.http_cache(), transaction);
1197 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1198 EXPECT_EQ(1, cache.disk_cache()->open_count());
1199 EXPECT_EQ(1, cache.disk_cache()->create_count());
1200 RemoveMockTransaction(&transaction);
1203 TEST(HttpCache, SimpleGET_ManyReaders) {
1204 MockHttpCache cache;
1206 MockHttpRequest request(kSimpleGET_Transaction);
1208 std::vector<Context*> context_list;
1209 const int kNumTransactions = 5;
1211 for (int i = 0; i < kNumTransactions; ++i) {
1212 context_list.push_back(new Context());
1213 Context* c = context_list[i];
1215 c->result = cache.CreateTransaction(&c->trans);
1216 ASSERT_EQ(OK, c->result);
1217 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
1219 c->result =
1220 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1223 // All requests are waiting for the active entry.
1224 for (int i = 0; i < kNumTransactions; ++i) {
1225 Context* c = context_list[i];
1226 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
1229 // Allow all requests to move from the Create queue to the active entry.
1230 base::MessageLoop::current()->RunUntilIdle();
1232 // The first request should be a writer at this point, and the subsequent
1233 // requests should be pending.
1235 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1236 EXPECT_EQ(0, cache.disk_cache()->open_count());
1237 EXPECT_EQ(1, cache.disk_cache()->create_count());
1239 // All requests depend on the writer, and the writer is between Start and
1240 // Read, i.e. idle.
1241 for (int i = 0; i < kNumTransactions; ++i) {
1242 Context* c = context_list[i];
1243 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
1246 for (int i = 0; i < kNumTransactions; ++i) {
1247 Context* c = context_list[i];
1248 if (c->result == ERR_IO_PENDING)
1249 c->result = c->callback.WaitForResult();
1250 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1253 // We should not have had to re-open the disk entry
1255 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1256 EXPECT_EQ(0, cache.disk_cache()->open_count());
1257 EXPECT_EQ(1, cache.disk_cache()->create_count());
1259 for (int i = 0; i < kNumTransactions; ++i) {
1260 Context* c = context_list[i];
1261 delete c;
1265 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4769.
1266 // If cancelling a request is racing with another request for the same resource
1267 // finishing, we have to make sure that we remove both transactions from the
1268 // entry.
1269 TEST(HttpCache, SimpleGET_RacingReaders) {
1270 MockHttpCache cache;
1272 MockHttpRequest request(kSimpleGET_Transaction);
1273 MockHttpRequest reader_request(kSimpleGET_Transaction);
1274 reader_request.load_flags = LOAD_ONLY_FROM_CACHE;
1276 std::vector<Context*> context_list;
1277 const int kNumTransactions = 5;
1279 for (int i = 0; i < kNumTransactions; ++i) {
1280 context_list.push_back(new Context());
1281 Context* c = context_list[i];
1283 c->result = cache.CreateTransaction(&c->trans);
1284 ASSERT_EQ(OK, c->result);
1286 MockHttpRequest* this_request = &request;
1287 if (i == 1 || i == 2)
1288 this_request = &reader_request;
1290 c->result =
1291 c->trans->Start(this_request, c->callback.callback(), BoundNetLog());
1294 // Allow all requests to move from the Create queue to the active entry.
1295 base::MessageLoop::current()->RunUntilIdle();
1297 // The first request should be a writer at this point, and the subsequent
1298 // requests should be pending.
1300 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1301 EXPECT_EQ(0, cache.disk_cache()->open_count());
1302 EXPECT_EQ(1, cache.disk_cache()->create_count());
1304 Context* c = context_list[0];
1305 ASSERT_EQ(ERR_IO_PENDING, c->result);
1306 c->result = c->callback.WaitForResult();
1307 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1309 // Now we have 2 active readers and two queued transactions.
1311 EXPECT_EQ(LOAD_STATE_IDLE, context_list[2]->trans->GetLoadState());
1312 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE,
1313 context_list[3]->trans->GetLoadState());
1315 c = context_list[1];
1316 ASSERT_EQ(ERR_IO_PENDING, c->result);
1317 c->result = c->callback.WaitForResult();
1318 if (c->result == OK)
1319 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1321 // At this point we have one reader, two pending transactions and a task on
1322 // the queue to move to the next transaction. Now we cancel the request that
1323 // is the current reader, and expect the queued task to be able to start the
1324 // next request.
1326 c = context_list[2];
1327 c->trans.reset();
1329 for (int i = 3; i < kNumTransactions; ++i) {
1330 Context* c = context_list[i];
1331 if (c->result == ERR_IO_PENDING)
1332 c->result = c->callback.WaitForResult();
1333 if (c->result == OK)
1334 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1337 // We should not have had to re-open the disk entry.
1339 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1340 EXPECT_EQ(0, cache.disk_cache()->open_count());
1341 EXPECT_EQ(1, cache.disk_cache()->create_count());
1343 for (int i = 0; i < kNumTransactions; ++i) {
1344 Context* c = context_list[i];
1345 delete c;
1349 // Tests that we can doom an entry with pending transactions and delete one of
1350 // the pending transactions before the first one completes.
1351 // See http://code.google.com/p/chromium/issues/detail?id=25588
1352 TEST(HttpCache, SimpleGET_DoomWithPending) {
1353 // We need simultaneous doomed / not_doomed entries so let's use a real cache.
1354 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
1356 MockHttpRequest request(kSimpleGET_Transaction);
1357 MockHttpRequest writer_request(kSimpleGET_Transaction);
1358 writer_request.load_flags = LOAD_BYPASS_CACHE;
1360 ScopedVector<Context> context_list;
1361 const int kNumTransactions = 4;
1363 for (int i = 0; i < kNumTransactions; ++i) {
1364 context_list.push_back(new Context());
1365 Context* c = context_list[i];
1367 c->result = cache.CreateTransaction(&c->trans);
1368 ASSERT_EQ(OK, c->result);
1370 MockHttpRequest* this_request = &request;
1371 if (i == 3)
1372 this_request = &writer_request;
1374 c->result =
1375 c->trans->Start(this_request, c->callback.callback(), BoundNetLog());
1378 // The first request should be a writer at this point, and the two subsequent
1379 // requests should be pending. The last request doomed the first entry.
1381 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1383 // Cancel the first queued transaction.
1384 delete context_list[1];
1385 context_list.get()[1] = NULL;
1387 for (int i = 0; i < kNumTransactions; ++i) {
1388 if (i == 1)
1389 continue;
1390 Context* c = context_list[i];
1391 ASSERT_EQ(ERR_IO_PENDING, c->result);
1392 c->result = c->callback.WaitForResult();
1393 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1397 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4731.
1398 // We may attempt to delete an entry synchronously with the act of adding a new
1399 // transaction to said entry.
1400 TEST(HttpCache, FastNoStoreGET_DoneWithPending) {
1401 MockHttpCache cache;
1403 // The headers will be served right from the call to Start() the request.
1404 MockHttpRequest request(kFastNoStoreGET_Transaction);
1405 FastTransactionServer request_handler;
1406 AddMockTransaction(&kFastNoStoreGET_Transaction);
1408 std::vector<Context*> context_list;
1409 const int kNumTransactions = 3;
1411 for (int i = 0; i < kNumTransactions; ++i) {
1412 context_list.push_back(new Context());
1413 Context* c = context_list[i];
1415 c->result = cache.CreateTransaction(&c->trans);
1416 ASSERT_EQ(OK, c->result);
1418 c->result =
1419 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1422 // Allow all requests to move from the Create queue to the active entry.
1423 base::MessageLoop::current()->RunUntilIdle();
1425 // The first request should be a writer at this point, and the subsequent
1426 // requests should be pending.
1428 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1429 EXPECT_EQ(0, cache.disk_cache()->open_count());
1430 EXPECT_EQ(1, cache.disk_cache()->create_count());
1432 // Now, make sure that the second request asks for the entry not to be stored.
1433 request_handler.set_no_store(true);
1435 for (int i = 0; i < kNumTransactions; ++i) {
1436 Context* c = context_list[i];
1437 if (c->result == ERR_IO_PENDING)
1438 c->result = c->callback.WaitForResult();
1439 ReadAndVerifyTransaction(c->trans.get(), kFastNoStoreGET_Transaction);
1440 delete c;
1443 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1444 EXPECT_EQ(0, cache.disk_cache()->open_count());
1445 EXPECT_EQ(2, cache.disk_cache()->create_count());
1447 RemoveMockTransaction(&kFastNoStoreGET_Transaction);
1450 TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) {
1451 MockHttpCache cache;
1453 MockHttpRequest request(kSimpleGET_Transaction);
1455 std::vector<Context*> context_list;
1456 const int kNumTransactions = 2;
1458 for (int i = 0; i < kNumTransactions; ++i) {
1459 context_list.push_back(new Context());
1460 Context* c = context_list[i];
1462 c->result = cache.CreateTransaction(&c->trans);
1463 ASSERT_EQ(OK, c->result);
1465 c->result =
1466 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1469 // Allow all requests to move from the Create queue to the active entry.
1470 base::MessageLoop::current()->RunUntilIdle();
1472 // The first request should be a writer at this point, and the subsequent
1473 // requests should be pending.
1475 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1476 EXPECT_EQ(0, cache.disk_cache()->open_count());
1477 EXPECT_EQ(1, cache.disk_cache()->create_count());
1479 for (int i = 0; i < kNumTransactions; ++i) {
1480 Context* c = context_list[i];
1481 if (c->result == ERR_IO_PENDING)
1482 c->result = c->callback.WaitForResult();
1483 // Destroy only the first transaction.
1484 if (i == 0) {
1485 delete c;
1486 context_list[i] = NULL;
1490 // Complete the rest of the transactions.
1491 for (int i = 1; i < kNumTransactions; ++i) {
1492 Context* c = context_list[i];
1493 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1496 // We should have had to re-open the disk entry.
1498 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1499 EXPECT_EQ(0, cache.disk_cache()->open_count());
1500 EXPECT_EQ(2, cache.disk_cache()->create_count());
1502 for (int i = 1; i < kNumTransactions; ++i) {
1503 Context* c = context_list[i];
1504 delete c;
1508 // Tests that we can cancel requests that are queued waiting to open the disk
1509 // cache entry.
1510 TEST(HttpCache, SimpleGET_ManyWriters_CancelCreate) {
1511 MockHttpCache cache;
1513 MockHttpRequest request(kSimpleGET_Transaction);
1515 std::vector<Context*> context_list;
1516 const int kNumTransactions = 5;
1518 for (int i = 0; i < kNumTransactions; i++) {
1519 context_list.push_back(new Context());
1520 Context* c = context_list[i];
1522 c->result = cache.CreateTransaction(&c->trans);
1523 ASSERT_EQ(OK, c->result);
1525 c->result =
1526 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1529 // The first request should be creating the disk cache entry and the others
1530 // should be pending.
1532 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1533 EXPECT_EQ(0, cache.disk_cache()->open_count());
1534 EXPECT_EQ(1, cache.disk_cache()->create_count());
1536 // Cancel a request from the pending queue.
1537 delete context_list[3];
1538 context_list[3] = NULL;
1540 // Cancel the request that is creating the entry. This will force the pending
1541 // operations to restart.
1542 delete context_list[0];
1543 context_list[0] = NULL;
1545 // Complete the rest of the transactions.
1546 for (int i = 1; i < kNumTransactions; i++) {
1547 Context* c = context_list[i];
1548 if (c) {
1549 c->result = c->callback.GetResult(c->result);
1550 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1554 // We should have had to re-create the disk entry.
1556 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1557 EXPECT_EQ(0, cache.disk_cache()->open_count());
1558 EXPECT_EQ(2, cache.disk_cache()->create_count());
1560 for (int i = 1; i < kNumTransactions; ++i) {
1561 delete context_list[i];
1565 // Tests that we can cancel a single request to open a disk cache entry.
1566 TEST(HttpCache, SimpleGET_CancelCreate) {
1567 MockHttpCache cache;
1569 MockHttpRequest request(kSimpleGET_Transaction);
1571 Context* c = new Context();
1573 c->result = cache.CreateTransaction(&c->trans);
1574 ASSERT_EQ(OK, c->result);
1576 c->result = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1577 EXPECT_EQ(ERR_IO_PENDING, c->result);
1579 // Release the reference that the mock disk cache keeps for this entry, so
1580 // that we test that the http cache handles the cancellation correctly.
1581 cache.disk_cache()->ReleaseAll();
1582 delete c;
1584 base::MessageLoop::current()->RunUntilIdle();
1585 EXPECT_EQ(1, cache.disk_cache()->create_count());
1588 // Tests that we delete/create entries even if multiple requests are queued.
1589 TEST(HttpCache, SimpleGET_ManyWriters_BypassCache) {
1590 MockHttpCache cache;
1592 MockHttpRequest request(kSimpleGET_Transaction);
1593 request.load_flags = LOAD_BYPASS_CACHE;
1595 std::vector<Context*> context_list;
1596 const int kNumTransactions = 5;
1598 for (int i = 0; i < kNumTransactions; i++) {
1599 context_list.push_back(new Context());
1600 Context* c = context_list[i];
1602 c->result = cache.CreateTransaction(&c->trans);
1603 ASSERT_EQ(OK, c->result);
1605 c->result =
1606 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1609 // The first request should be deleting the disk cache entry and the others
1610 // should be pending.
1612 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1613 EXPECT_EQ(0, cache.disk_cache()->open_count());
1614 EXPECT_EQ(0, cache.disk_cache()->create_count());
1616 // Complete the transactions.
1617 for (int i = 0; i < kNumTransactions; i++) {
1618 Context* c = context_list[i];
1619 c->result = c->callback.GetResult(c->result);
1620 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1623 // We should have had to re-create the disk entry multiple times.
1625 EXPECT_EQ(5, cache.network_layer()->transaction_count());
1626 EXPECT_EQ(0, cache.disk_cache()->open_count());
1627 EXPECT_EQ(5, cache.disk_cache()->create_count());
1629 for (int i = 0; i < kNumTransactions; ++i) {
1630 delete context_list[i];
1634 // Tests that a (simulated) timeout allows transactions waiting on the cache
1635 // lock to continue.
1636 TEST(HttpCache, SimpleGET_WriterTimeout) {
1637 MockHttpCache cache;
1638 cache.BypassCacheLock();
1640 MockHttpRequest request(kSimpleGET_Transaction);
1641 Context c1, c2;
1642 ASSERT_EQ(OK, cache.CreateTransaction(&c1.trans));
1643 ASSERT_EQ(ERR_IO_PENDING,
1644 c1.trans->Start(&request, c1.callback.callback(), BoundNetLog()));
1645 ASSERT_EQ(OK, cache.CreateTransaction(&c2.trans));
1646 ASSERT_EQ(ERR_IO_PENDING,
1647 c2.trans->Start(&request, c2.callback.callback(), BoundNetLog()));
1649 // The second request is queued after the first one.
1651 c2.callback.WaitForResult();
1652 ReadAndVerifyTransaction(c2.trans.get(), kSimpleGET_Transaction);
1654 // Complete the first transaction.
1655 c1.callback.WaitForResult();
1656 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
1659 TEST(HttpCache, SimpleGET_AbandonedCacheRead) {
1660 MockHttpCache cache;
1662 // write to the cache
1663 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1665 MockHttpRequest request(kSimpleGET_Transaction);
1666 TestCompletionCallback callback;
1668 scoped_ptr<HttpTransaction> trans;
1669 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
1670 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1671 if (rv == ERR_IO_PENDING)
1672 rv = callback.WaitForResult();
1673 ASSERT_EQ(OK, rv);
1675 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
1676 rv = trans->Read(buf.get(), 256, callback.callback());
1677 EXPECT_EQ(ERR_IO_PENDING, rv);
1679 // Test that destroying the transaction while it is reading from the cache
1680 // works properly.
1681 trans.reset();
1683 // Make sure we pump any pending events, which should include a call to
1684 // HttpCache::Transaction::OnCacheReadCompleted.
1685 base::MessageLoop::current()->RunUntilIdle();
1688 // Tests that we can delete the HttpCache and deal with queued transactions
1689 // ("waiting for the backend" as opposed to Active or Doomed entries).
1690 TEST(HttpCache, SimpleGET_ManyWriters_DeleteCache) {
1691 scoped_ptr<MockHttpCache> cache(new MockHttpCache(
1692 new MockBackendNoCbFactory()));
1694 MockHttpRequest request(kSimpleGET_Transaction);
1696 std::vector<Context*> context_list;
1697 const int kNumTransactions = 5;
1699 for (int i = 0; i < kNumTransactions; i++) {
1700 context_list.push_back(new Context());
1701 Context* c = context_list[i];
1703 c->result = cache->CreateTransaction(&c->trans);
1704 ASSERT_EQ(OK, c->result);
1706 c->result =
1707 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1710 // The first request should be creating the disk cache entry and the others
1711 // should be pending.
1713 EXPECT_EQ(0, cache->network_layer()->transaction_count());
1714 EXPECT_EQ(0, cache->disk_cache()->open_count());
1715 EXPECT_EQ(0, cache->disk_cache()->create_count());
1717 cache.reset();
1719 // There is not much to do with the transactions at this point... they are
1720 // waiting for a callback that will not fire.
1721 for (int i = 0; i < kNumTransactions; ++i) {
1722 delete context_list[i];
1726 // Tests that we queue requests when initializing the backend.
1727 TEST(HttpCache, SimpleGET_WaitForBackend) {
1728 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1729 MockHttpCache cache(factory);
1731 MockHttpRequest request0(kSimpleGET_Transaction);
1732 MockHttpRequest request1(kTypicalGET_Transaction);
1733 MockHttpRequest request2(kETagGET_Transaction);
1735 std::vector<Context*> context_list;
1736 const int kNumTransactions = 3;
1738 for (int i = 0; i < kNumTransactions; i++) {
1739 context_list.push_back(new Context());
1740 Context* c = context_list[i];
1742 c->result = cache.CreateTransaction(&c->trans);
1743 ASSERT_EQ(OK, c->result);
1746 context_list[0]->result = context_list[0]->trans->Start(
1747 &request0, context_list[0]->callback.callback(), BoundNetLog());
1748 context_list[1]->result = context_list[1]->trans->Start(
1749 &request1, context_list[1]->callback.callback(), BoundNetLog());
1750 context_list[2]->result = context_list[2]->trans->Start(
1751 &request2, context_list[2]->callback.callback(), BoundNetLog());
1753 // Just to make sure that everything is still pending.
1754 base::MessageLoop::current()->RunUntilIdle();
1756 // The first request should be creating the disk cache.
1757 EXPECT_FALSE(context_list[0]->callback.have_result());
1759 factory->FinishCreation();
1761 base::MessageLoop::current()->RunUntilIdle();
1762 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1763 EXPECT_EQ(3, cache.disk_cache()->create_count());
1765 for (int i = 0; i < kNumTransactions; ++i) {
1766 EXPECT_TRUE(context_list[i]->callback.have_result());
1767 delete context_list[i];
1771 // Tests that we can cancel requests that are queued waiting for the backend
1772 // to be initialized.
1773 TEST(HttpCache, SimpleGET_WaitForBackend_CancelCreate) {
1774 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1775 MockHttpCache cache(factory);
1777 MockHttpRequest request0(kSimpleGET_Transaction);
1778 MockHttpRequest request1(kTypicalGET_Transaction);
1779 MockHttpRequest request2(kETagGET_Transaction);
1781 std::vector<Context*> context_list;
1782 const int kNumTransactions = 3;
1784 for (int i = 0; i < kNumTransactions; i++) {
1785 context_list.push_back(new Context());
1786 Context* c = context_list[i];
1788 c->result = cache.CreateTransaction(&c->trans);
1789 ASSERT_EQ(OK, c->result);
1792 context_list[0]->result = context_list[0]->trans->Start(
1793 &request0, context_list[0]->callback.callback(), BoundNetLog());
1794 context_list[1]->result = context_list[1]->trans->Start(
1795 &request1, context_list[1]->callback.callback(), BoundNetLog());
1796 context_list[2]->result = context_list[2]->trans->Start(
1797 &request2, context_list[2]->callback.callback(), BoundNetLog());
1799 // Just to make sure that everything is still pending.
1800 base::MessageLoop::current()->RunUntilIdle();
1802 // The first request should be creating the disk cache.
1803 EXPECT_FALSE(context_list[0]->callback.have_result());
1805 // Cancel a request from the pending queue.
1806 delete context_list[1];
1807 context_list[1] = NULL;
1809 // Cancel the request that is creating the entry.
1810 delete context_list[0];
1811 context_list[0] = NULL;
1813 // Complete the last transaction.
1814 factory->FinishCreation();
1816 context_list[2]->result =
1817 context_list[2]->callback.GetResult(context_list[2]->result);
1818 ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction);
1820 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1821 EXPECT_EQ(1, cache.disk_cache()->create_count());
1823 delete context_list[2];
1826 // Tests that we can delete the cache while creating the backend.
1827 TEST(HttpCache, DeleteCacheWaitingForBackend) {
1828 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1829 scoped_ptr<MockHttpCache> cache(new MockHttpCache(factory));
1831 MockHttpRequest request(kSimpleGET_Transaction);
1833 scoped_ptr<Context> c(new Context());
1834 c->result = cache->CreateTransaction(&c->trans);
1835 ASSERT_EQ(OK, c->result);
1837 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1839 // Just to make sure that everything is still pending.
1840 base::MessageLoop::current()->RunUntilIdle();
1842 // The request should be creating the disk cache.
1843 EXPECT_FALSE(c->callback.have_result());
1845 // We cannot call FinishCreation because the factory itself will go away with
1846 // the cache, so grab the callback and attempt to use it.
1847 CompletionCallback callback = factory->callback();
1848 scoped_ptr<disk_cache::Backend>* backend = factory->backend();
1850 cache.reset();
1851 base::MessageLoop::current()->RunUntilIdle();
1853 backend->reset();
1854 callback.Run(ERR_ABORTED);
1857 // Tests that we can delete the cache while creating the backend, from within
1858 // one of the callbacks.
1859 TEST(HttpCache, DeleteCacheWaitingForBackend2) {
1860 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1861 MockHttpCache* cache = new MockHttpCache(factory);
1863 DeleteCacheCompletionCallback cb(cache);
1864 disk_cache::Backend* backend;
1865 int rv = cache->http_cache()->GetBackend(&backend, cb.callback());
1866 EXPECT_EQ(ERR_IO_PENDING, rv);
1868 // Now let's queue a regular transaction
1869 MockHttpRequest request(kSimpleGET_Transaction);
1871 scoped_ptr<Context> c(new Context());
1872 c->result = cache->CreateTransaction(&c->trans);
1873 ASSERT_EQ(OK, c->result);
1875 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1877 // And another direct backend request.
1878 TestCompletionCallback cb2;
1879 rv = cache->http_cache()->GetBackend(&backend, cb2.callback());
1880 EXPECT_EQ(ERR_IO_PENDING, rv);
1882 // Just to make sure that everything is still pending.
1883 base::MessageLoop::current()->RunUntilIdle();
1885 // The request should be queued.
1886 EXPECT_FALSE(c->callback.have_result());
1888 // Generate the callback.
1889 factory->FinishCreation();
1890 rv = cb.WaitForResult();
1892 // The cache should be gone by now.
1893 base::MessageLoop::current()->RunUntilIdle();
1894 EXPECT_EQ(OK, c->callback.GetResult(c->result));
1895 EXPECT_FALSE(cb2.have_result());
1898 TEST(HttpCache, TypicalGET_ConditionalRequest) {
1899 MockHttpCache cache;
1901 // write to the cache
1902 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
1904 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1905 EXPECT_EQ(0, cache.disk_cache()->open_count());
1906 EXPECT_EQ(1, cache.disk_cache()->create_count());
1908 // Get the same URL again, but this time we expect it to result
1909 // in a conditional request.
1910 BoundTestNetLog log;
1911 LoadTimingInfo load_timing_info;
1912 RunTransactionTestAndGetTiming(cache.http_cache(), kTypicalGET_Transaction,
1913 log.bound(), &load_timing_info);
1915 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1916 EXPECT_EQ(1, cache.disk_cache()->open_count());
1917 EXPECT_EQ(1, cache.disk_cache()->create_count());
1918 TestLoadTimingNetworkRequest(load_timing_info);
1921 static void ETagGet_ConditionalRequest_Handler(const HttpRequestInfo* request,
1922 std::string* response_status,
1923 std::string* response_headers,
1924 std::string* response_data) {
1925 EXPECT_TRUE(
1926 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
1927 response_status->assign("HTTP/1.1 304 Not Modified");
1928 response_headers->assign(kETagGET_Transaction.response_headers);
1929 response_data->clear();
1932 TEST(HttpCache, ETagGET_ConditionalRequest_304) {
1933 MockHttpCache cache;
1935 ScopedMockTransaction transaction(kETagGET_Transaction);
1937 // write to the cache
1938 RunTransactionTest(cache.http_cache(), transaction);
1940 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1941 EXPECT_EQ(0, cache.disk_cache()->open_count());
1942 EXPECT_EQ(1, cache.disk_cache()->create_count());
1944 // Get the same URL again, but this time we expect it to result
1945 // in a conditional request.
1946 transaction.load_flags = LOAD_VALIDATE_CACHE;
1947 transaction.handler = ETagGet_ConditionalRequest_Handler;
1948 BoundTestNetLog log;
1949 LoadTimingInfo load_timing_info;
1950 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
1951 &load_timing_info);
1953 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1954 EXPECT_EQ(1, cache.disk_cache()->open_count());
1955 EXPECT_EQ(1, cache.disk_cache()->create_count());
1956 TestLoadTimingNetworkRequest(load_timing_info);
1959 class RevalidationServer {
1960 public:
1961 RevalidationServer() {
1962 s_etag_used_ = false;
1963 s_last_modified_used_ = false;
1966 bool EtagUsed() { return s_etag_used_; }
1967 bool LastModifiedUsed() { return s_last_modified_used_; }
1969 static void Handler(const HttpRequestInfo* request,
1970 std::string* response_status,
1971 std::string* response_headers,
1972 std::string* response_data);
1974 private:
1975 static bool s_etag_used_;
1976 static bool s_last_modified_used_;
1978 bool RevalidationServer::s_etag_used_ = false;
1979 bool RevalidationServer::s_last_modified_used_ = false;
1981 void RevalidationServer::Handler(const HttpRequestInfo* request,
1982 std::string* response_status,
1983 std::string* response_headers,
1984 std::string* response_data) {
1985 if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch))
1986 s_etag_used_ = true;
1988 if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfModifiedSince)) {
1989 s_last_modified_used_ = true;
1992 if (s_etag_used_ || s_last_modified_used_) {
1993 response_status->assign("HTTP/1.1 304 Not Modified");
1994 response_headers->assign(kTypicalGET_Transaction.response_headers);
1995 response_data->clear();
1996 } else {
1997 response_status->assign(kTypicalGET_Transaction.status);
1998 response_headers->assign(kTypicalGET_Transaction.response_headers);
1999 response_data->assign(kTypicalGET_Transaction.data);
2003 // Tests revalidation after a vary match.
2004 TEST(HttpCache, GET_ValidateCache_VaryMatch) {
2005 MockHttpCache cache;
2007 // Write to the cache.
2008 MockTransaction transaction(kTypicalGET_Transaction);
2009 transaction.request_headers = "Foo: bar\r\n";
2010 transaction.response_headers =
2011 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
2012 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2013 "Etag: \"foopy\"\n"
2014 "Cache-Control: max-age=0\n"
2015 "Vary: Foo\n";
2016 AddMockTransaction(&transaction);
2017 RunTransactionTest(cache.http_cache(), transaction);
2019 // Read from the cache.
2020 RevalidationServer server;
2021 transaction.handler = server.Handler;
2022 BoundTestNetLog log;
2023 LoadTimingInfo load_timing_info;
2024 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
2025 &load_timing_info);
2027 EXPECT_TRUE(server.EtagUsed());
2028 EXPECT_TRUE(server.LastModifiedUsed());
2029 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2030 EXPECT_EQ(1, cache.disk_cache()->open_count());
2031 EXPECT_EQ(1, cache.disk_cache()->create_count());
2032 TestLoadTimingNetworkRequest(load_timing_info);
2033 RemoveMockTransaction(&transaction);
2036 // Tests revalidation after a vary mismatch if etag is present.
2037 TEST(HttpCache, GET_ValidateCache_VaryMismatch) {
2038 MockHttpCache cache;
2040 // Write to the cache.
2041 MockTransaction transaction(kTypicalGET_Transaction);
2042 transaction.request_headers = "Foo: bar\r\n";
2043 transaction.response_headers =
2044 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
2045 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2046 "Etag: \"foopy\"\n"
2047 "Cache-Control: max-age=0\n"
2048 "Vary: Foo\n";
2049 AddMockTransaction(&transaction);
2050 RunTransactionTest(cache.http_cache(), transaction);
2052 // Read from the cache and revalidate the entry.
2053 RevalidationServer server;
2054 transaction.handler = server.Handler;
2055 transaction.request_headers = "Foo: none\r\n";
2056 BoundTestNetLog log;
2057 LoadTimingInfo load_timing_info;
2058 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
2059 &load_timing_info);
2061 EXPECT_TRUE(server.EtagUsed());
2062 EXPECT_FALSE(server.LastModifiedUsed());
2063 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2064 EXPECT_EQ(1, cache.disk_cache()->open_count());
2065 EXPECT_EQ(1, cache.disk_cache()->create_count());
2066 TestLoadTimingNetworkRequest(load_timing_info);
2067 RemoveMockTransaction(&transaction);
2070 // Tests lack of revalidation after a vary mismatch and no etag.
2071 TEST(HttpCache, GET_DontValidateCache_VaryMismatch) {
2072 MockHttpCache cache;
2074 // Write to the cache.
2075 MockTransaction transaction(kTypicalGET_Transaction);
2076 transaction.request_headers = "Foo: bar\r\n";
2077 transaction.response_headers =
2078 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
2079 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2080 "Cache-Control: max-age=0\n"
2081 "Vary: Foo\n";
2082 AddMockTransaction(&transaction);
2083 RunTransactionTest(cache.http_cache(), transaction);
2085 // Read from the cache and don't revalidate the entry.
2086 RevalidationServer server;
2087 transaction.handler = server.Handler;
2088 transaction.request_headers = "Foo: none\r\n";
2089 BoundTestNetLog log;
2090 LoadTimingInfo load_timing_info;
2091 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
2092 &load_timing_info);
2094 EXPECT_FALSE(server.EtagUsed());
2095 EXPECT_FALSE(server.LastModifiedUsed());
2096 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2097 EXPECT_EQ(1, cache.disk_cache()->open_count());
2098 EXPECT_EQ(1, cache.disk_cache()->create_count());
2099 TestLoadTimingNetworkRequest(load_timing_info);
2100 RemoveMockTransaction(&transaction);
2103 // Tests that a new vary header provided when revalidating an entry is saved.
2104 TEST(HttpCache, GET_ValidateCache_VaryMatch_UpdateVary) {
2105 MockHttpCache cache;
2107 // Write to the cache.
2108 ScopedMockTransaction transaction(kTypicalGET_Transaction);
2109 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
2110 transaction.response_headers =
2111 "Etag: \"foopy\"\n"
2112 "Cache-Control: max-age=0\n"
2113 "Vary: Foo\n";
2114 RunTransactionTest(cache.http_cache(), transaction);
2116 // Validate the entry and change the vary field in the response.
2117 transaction.request_headers = "Foo: bar\r\n Name: none\r\n";
2118 transaction.status = "HTTP/1.1 304 Not Modified";
2119 transaction.response_headers =
2120 "Etag: \"foopy\"\n"
2121 "Cache-Control: max-age=3600\n"
2122 "Vary: Name\n";
2123 RunTransactionTest(cache.http_cache(), transaction);
2125 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2126 EXPECT_EQ(1, cache.disk_cache()->open_count());
2127 EXPECT_EQ(1, cache.disk_cache()->create_count());
2129 // Make sure that the ActiveEntry is gone.
2130 base::RunLoop().RunUntilIdle();
2132 // Generate a vary mismatch.
2133 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
2134 RunTransactionTest(cache.http_cache(), transaction);
2136 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2137 EXPECT_EQ(2, cache.disk_cache()->open_count());
2138 EXPECT_EQ(1, cache.disk_cache()->create_count());
2141 // Tests that new request headers causing a vary mismatch are paired with the
2142 // new response when the server says the old response can be used.
2143 TEST(HttpCache, GET_ValidateCache_VaryMismatch_UpdateRequestHeader) {
2144 MockHttpCache cache;
2146 // Write to the cache.
2147 ScopedMockTransaction transaction(kTypicalGET_Transaction);
2148 transaction.request_headers = "Foo: bar\r\n";
2149 transaction.response_headers =
2150 "Etag: \"foopy\"\n"
2151 "Cache-Control: max-age=3600\n"
2152 "Vary: Foo\n";
2153 RunTransactionTest(cache.http_cache(), transaction);
2155 // Vary-mismatch validation receives 304.
2156 transaction.request_headers = "Foo: none\r\n";
2157 transaction.status = "HTTP/1.1 304 Not Modified";
2158 RunTransactionTest(cache.http_cache(), transaction);
2160 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2161 EXPECT_EQ(1, cache.disk_cache()->open_count());
2162 EXPECT_EQ(1, cache.disk_cache()->create_count());
2164 // Make sure that the ActiveEntry is gone.
2165 base::RunLoop().RunUntilIdle();
2167 // Generate a vary mismatch.
2168 transaction.request_headers = "Foo: bar\r\n";
2169 RunTransactionTest(cache.http_cache(), transaction);
2171 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2172 EXPECT_EQ(2, cache.disk_cache()->open_count());
2173 EXPECT_EQ(1, cache.disk_cache()->create_count());
2176 // Tests that a 304 without vary headers doesn't delete the previously stored
2177 // vary data after a vary match revalidation.
2178 TEST(HttpCache, GET_ValidateCache_VaryMatch_DontDeleteVary) {
2179 MockHttpCache cache;
2181 // Write to the cache.
2182 ScopedMockTransaction transaction(kTypicalGET_Transaction);
2183 transaction.request_headers = "Foo: bar\r\n";
2184 transaction.response_headers =
2185 "Etag: \"foopy\"\n"
2186 "Cache-Control: max-age=0\n"
2187 "Vary: Foo\n";
2188 RunTransactionTest(cache.http_cache(), transaction);
2190 // Validate the entry and remove the vary field in the response.
2191 transaction.status = "HTTP/1.1 304 Not Modified";
2192 transaction.response_headers =
2193 "Etag: \"foopy\"\n"
2194 "Cache-Control: max-age=3600\n";
2195 RunTransactionTest(cache.http_cache(), transaction);
2197 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2198 EXPECT_EQ(1, cache.disk_cache()->open_count());
2199 EXPECT_EQ(1, cache.disk_cache()->create_count());
2201 // Make sure that the ActiveEntry is gone.
2202 base::RunLoop().RunUntilIdle();
2204 // Generate a vary mismatch.
2205 transaction.request_headers = "Foo: none\r\n";
2206 RunTransactionTest(cache.http_cache(), transaction);
2208 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2209 EXPECT_EQ(2, cache.disk_cache()->open_count());
2210 EXPECT_EQ(1, cache.disk_cache()->create_count());
2213 // Tests that a 304 without vary headers doesn't delete the previously stored
2214 // vary data after a vary mismatch.
2215 TEST(HttpCache, GET_ValidateCache_VaryMismatch_DontDeleteVary) {
2216 MockHttpCache cache;
2218 // Write to the cache.
2219 ScopedMockTransaction transaction(kTypicalGET_Transaction);
2220 transaction.request_headers = "Foo: bar\r\n";
2221 transaction.response_headers =
2222 "Etag: \"foopy\"\n"
2223 "Cache-Control: max-age=3600\n"
2224 "Vary: Foo\n";
2225 RunTransactionTest(cache.http_cache(), transaction);
2227 // Vary-mismatch validation receives 304 and no vary header.
2228 transaction.request_headers = "Foo: none\r\n";
2229 transaction.status = "HTTP/1.1 304 Not Modified";
2230 transaction.response_headers =
2231 "Etag: \"foopy\"\n"
2232 "Cache-Control: max-age=3600\n";
2233 RunTransactionTest(cache.http_cache(), transaction);
2235 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2236 EXPECT_EQ(1, cache.disk_cache()->open_count());
2237 EXPECT_EQ(1, cache.disk_cache()->create_count());
2239 // Make sure that the ActiveEntry is gone.
2240 base::RunLoop().RunUntilIdle();
2242 // Generate a vary mismatch.
2243 transaction.request_headers = "Foo: bar\r\n";
2244 RunTransactionTest(cache.http_cache(), transaction);
2246 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2247 EXPECT_EQ(2, cache.disk_cache()->open_count());
2248 EXPECT_EQ(1, cache.disk_cache()->create_count());
2251 static void ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo* request,
2252 std::string* response_status,
2253 std::string* response_headers,
2254 std::string* response_data) {
2255 EXPECT_FALSE(
2256 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
2259 TEST(HttpCache, ETagGET_Http10) {
2260 MockHttpCache cache;
2262 ScopedMockTransaction transaction(kETagGET_Transaction);
2263 transaction.status = "HTTP/1.0 200 OK";
2265 // Write to the cache.
2266 RunTransactionTest(cache.http_cache(), transaction);
2268 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2269 EXPECT_EQ(0, cache.disk_cache()->open_count());
2270 EXPECT_EQ(1, cache.disk_cache()->create_count());
2272 // Get the same URL again, without generating a conditional request.
2273 transaction.load_flags = LOAD_VALIDATE_CACHE;
2274 transaction.handler = ETagGet_UnconditionalRequest_Handler;
2275 RunTransactionTest(cache.http_cache(), transaction);
2277 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2278 EXPECT_EQ(1, cache.disk_cache()->open_count());
2279 EXPECT_EQ(1, cache.disk_cache()->create_count());
2282 TEST(HttpCache, ETagGET_Http10_Range) {
2283 MockHttpCache cache;
2285 ScopedMockTransaction transaction(kETagGET_Transaction);
2286 transaction.status = "HTTP/1.0 200 OK";
2288 // Write to the cache.
2289 RunTransactionTest(cache.http_cache(), transaction);
2291 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2292 EXPECT_EQ(0, cache.disk_cache()->open_count());
2293 EXPECT_EQ(1, cache.disk_cache()->create_count());
2295 // Get the same URL again, but use a byte range request.
2296 transaction.load_flags = LOAD_VALIDATE_CACHE;
2297 transaction.handler = ETagGet_UnconditionalRequest_Handler;
2298 transaction.request_headers = "Range: bytes = 5-\r\n";
2299 RunTransactionTest(cache.http_cache(), transaction);
2301 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2302 EXPECT_EQ(1, cache.disk_cache()->open_count());
2303 EXPECT_EQ(2, cache.disk_cache()->create_count());
2306 static void ETagGet_ConditionalRequest_NoStore_Handler(
2307 const HttpRequestInfo* request,
2308 std::string* response_status,
2309 std::string* response_headers,
2310 std::string* response_data) {
2311 EXPECT_TRUE(
2312 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
2313 response_status->assign("HTTP/1.1 304 Not Modified");
2314 response_headers->assign("Cache-Control: no-store\n");
2315 response_data->clear();
2318 TEST(HttpCache, ETagGET_ConditionalRequest_304_NoStore) {
2319 MockHttpCache cache;
2321 ScopedMockTransaction transaction(kETagGET_Transaction);
2323 // Write to the cache.
2324 RunTransactionTest(cache.http_cache(), transaction);
2326 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2327 EXPECT_EQ(0, cache.disk_cache()->open_count());
2328 EXPECT_EQ(1, cache.disk_cache()->create_count());
2330 // Get the same URL again, but this time we expect it to result
2331 // in a conditional request.
2332 transaction.load_flags = LOAD_VALIDATE_CACHE;
2333 transaction.handler = ETagGet_ConditionalRequest_NoStore_Handler;
2334 RunTransactionTest(cache.http_cache(), transaction);
2336 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2337 EXPECT_EQ(1, cache.disk_cache()->open_count());
2338 EXPECT_EQ(1, cache.disk_cache()->create_count());
2340 ScopedMockTransaction transaction2(kETagGET_Transaction);
2342 // Write to the cache again. This should create a new entry.
2343 RunTransactionTest(cache.http_cache(), transaction2);
2345 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2346 EXPECT_EQ(1, cache.disk_cache()->open_count());
2347 EXPECT_EQ(2, cache.disk_cache()->create_count());
2350 // Helper that does 4 requests using HttpCache:
2352 // (1) loads |kUrl| -- expects |net_response_1| to be returned.
2353 // (2) loads |kUrl| from cache only -- expects |net_response_1| to be returned.
2354 // (3) loads |kUrl| using |extra_request_headers| -- expects |net_response_2| to
2355 // be returned.
2356 // (4) loads |kUrl| from cache only -- expects |cached_response_2| to be
2357 // returned.
2358 static void ConditionalizedRequestUpdatesCacheHelper(
2359 const Response& net_response_1,
2360 const Response& net_response_2,
2361 const Response& cached_response_2,
2362 const char* extra_request_headers) {
2363 MockHttpCache cache;
2365 // The URL we will be requesting.
2366 const char kUrl[] = "http://foobar.com/main.css";
2368 // Junk network response.
2369 static const Response kUnexpectedResponse = {
2370 "HTTP/1.1 500 Unexpected",
2371 "Server: unexpected_header",
2372 "unexpected body"
2375 // We will control the network layer's responses for |kUrl| using
2376 // |mock_network_response|.
2377 MockTransaction mock_network_response = { 0 };
2378 mock_network_response.url = kUrl;
2379 AddMockTransaction(&mock_network_response);
2381 // Request |kUrl| for the first time. It should hit the network and
2382 // receive |kNetResponse1|, which it saves into the HTTP cache.
2384 MockTransaction request = { 0 };
2385 request.url = kUrl;
2386 request.method = "GET";
2387 request.request_headers = "";
2389 net_response_1.AssignTo(&mock_network_response); // Network mock.
2390 net_response_1.AssignTo(&request); // Expected result.
2392 std::string response_headers;
2393 RunTransactionTestWithResponse(
2394 cache.http_cache(), request, &response_headers);
2396 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
2397 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2398 EXPECT_EQ(0, cache.disk_cache()->open_count());
2399 EXPECT_EQ(1, cache.disk_cache()->create_count());
2401 // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP
2402 // cache, so we don't hit the network.
2404 request.load_flags = LOAD_ONLY_FROM_CACHE;
2406 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
2407 net_response_1.AssignTo(&request); // Expected result.
2409 RunTransactionTestWithResponse(
2410 cache.http_cache(), request, &response_headers);
2412 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
2413 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2414 EXPECT_EQ(1, cache.disk_cache()->open_count());
2415 EXPECT_EQ(1, cache.disk_cache()->create_count());
2417 // Request |kUrl| yet again, but this time give the request an
2418 // "If-Modified-Since" header. This will cause the request to re-hit the
2419 // network. However now the network response is going to be
2420 // different -- this simulates a change made to the CSS file.
2422 request.request_headers = extra_request_headers;
2423 request.load_flags = LOAD_NORMAL;
2425 net_response_2.AssignTo(&mock_network_response); // Network mock.
2426 net_response_2.AssignTo(&request); // Expected result.
2428 RunTransactionTestWithResponse(
2429 cache.http_cache(), request, &response_headers);
2431 EXPECT_EQ(net_response_2.status_and_headers(), response_headers);
2432 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2433 EXPECT_EQ(1, cache.disk_cache()->open_count());
2434 EXPECT_EQ(1, cache.disk_cache()->create_count());
2436 // Finally, request |kUrl| again. This request should be serviced from
2437 // the cache. Moreover, the value in the cache should be |kNetResponse2|
2438 // and NOT |kNetResponse1|. The previous step should have replaced the
2439 // value in the cache with the modified response.
2441 request.request_headers = "";
2442 request.load_flags = LOAD_ONLY_FROM_CACHE;
2444 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
2445 cached_response_2.AssignTo(&request); // Expected result.
2447 RunTransactionTestWithResponse(
2448 cache.http_cache(), request, &response_headers);
2450 EXPECT_EQ(cached_response_2.status_and_headers(), response_headers);
2451 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2452 EXPECT_EQ(2, cache.disk_cache()->open_count());
2453 EXPECT_EQ(1, cache.disk_cache()->create_count());
2455 RemoveMockTransaction(&mock_network_response);
2458 // Check that when an "if-modified-since" header is attached
2459 // to the request, the result still updates the cached entry.
2460 TEST(HttpCache, ConditionalizedRequestUpdatesCache1) {
2461 // First network response for |kUrl|.
2462 static const Response kNetResponse1 = {
2463 "HTTP/1.1 200 OK",
2464 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2465 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2466 "body1"
2469 // Second network response for |kUrl|.
2470 static const Response kNetResponse2 = {
2471 "HTTP/1.1 200 OK",
2472 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2473 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2474 "body2"
2477 const char extra_headers[] =
2478 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
2480 ConditionalizedRequestUpdatesCacheHelper(
2481 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
2484 // Check that when an "if-none-match" header is attached
2485 // to the request, the result updates the cached entry.
2486 TEST(HttpCache, ConditionalizedRequestUpdatesCache2) {
2487 // First network response for |kUrl|.
2488 static const Response kNetResponse1 = {
2489 "HTTP/1.1 200 OK",
2490 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2491 "Etag: \"ETAG1\"\n"
2492 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
2493 "body1"
2496 // Second network response for |kUrl|.
2497 static const Response kNetResponse2 = {
2498 "HTTP/1.1 200 OK",
2499 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2500 "Etag: \"ETAG2\"\n"
2501 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
2502 "body2"
2505 const char extra_headers[] = "If-None-Match: \"ETAG1\"\r\n";
2507 ConditionalizedRequestUpdatesCacheHelper(
2508 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
2511 // Check that when an "if-modified-since" header is attached
2512 // to a request, the 304 (not modified result) result updates the cached
2513 // headers, and the 304 response is returned rather than the cached response.
2514 TEST(HttpCache, ConditionalizedRequestUpdatesCache3) {
2515 // First network response for |kUrl|.
2516 static const Response kNetResponse1 = {
2517 "HTTP/1.1 200 OK",
2518 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2519 "Server: server1\n"
2520 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2521 "body1"
2524 // Second network response for |kUrl|.
2525 static const Response kNetResponse2 = {
2526 "HTTP/1.1 304 Not Modified",
2527 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2528 "Server: server2\n"
2529 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2533 static const Response kCachedResponse2 = {
2534 "HTTP/1.1 200 OK",
2535 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2536 "Server: server2\n"
2537 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2538 "body1"
2541 const char extra_headers[] =
2542 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
2544 ConditionalizedRequestUpdatesCacheHelper(
2545 kNetResponse1, kNetResponse2, kCachedResponse2, extra_headers);
2548 // Test that when doing an externally conditionalized if-modified-since
2549 // and there is no corresponding cache entry, a new cache entry is NOT
2550 // created (304 response).
2551 TEST(HttpCache, ConditionalizedRequestUpdatesCache4) {
2552 MockHttpCache cache;
2554 const char kUrl[] = "http://foobar.com/main.css";
2556 static const Response kNetResponse = {
2557 "HTTP/1.1 304 Not Modified",
2558 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2559 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2563 const char kExtraRequestHeaders[] =
2564 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
2566 // We will control the network layer's responses for |kUrl| using
2567 // |mock_network_response|.
2568 MockTransaction mock_network_response = { 0 };
2569 mock_network_response.url = kUrl;
2570 AddMockTransaction(&mock_network_response);
2572 MockTransaction request = { 0 };
2573 request.url = kUrl;
2574 request.method = "GET";
2575 request.request_headers = kExtraRequestHeaders;
2577 kNetResponse.AssignTo(&mock_network_response); // Network mock.
2578 kNetResponse.AssignTo(&request); // Expected result.
2580 std::string response_headers;
2581 RunTransactionTestWithResponse(
2582 cache.http_cache(), request, &response_headers);
2584 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
2585 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2586 EXPECT_EQ(0, cache.disk_cache()->open_count());
2587 EXPECT_EQ(0, cache.disk_cache()->create_count());
2589 RemoveMockTransaction(&mock_network_response);
2592 // Test that when doing an externally conditionalized if-modified-since
2593 // and there is no corresponding cache entry, a new cache entry is NOT
2594 // created (200 response).
2595 TEST(HttpCache, ConditionalizedRequestUpdatesCache5) {
2596 MockHttpCache cache;
2598 const char kUrl[] = "http://foobar.com/main.css";
2600 static const Response kNetResponse = {
2601 "HTTP/1.1 200 OK",
2602 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2603 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2604 "foobar!!!"
2607 const char kExtraRequestHeaders[] =
2608 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
2610 // We will control the network layer's responses for |kUrl| using
2611 // |mock_network_response|.
2612 MockTransaction mock_network_response = { 0 };
2613 mock_network_response.url = kUrl;
2614 AddMockTransaction(&mock_network_response);
2616 MockTransaction request = { 0 };
2617 request.url = kUrl;
2618 request.method = "GET";
2619 request.request_headers = kExtraRequestHeaders;
2621 kNetResponse.AssignTo(&mock_network_response); // Network mock.
2622 kNetResponse.AssignTo(&request); // Expected result.
2624 std::string response_headers;
2625 RunTransactionTestWithResponse(
2626 cache.http_cache(), request, &response_headers);
2628 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
2629 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2630 EXPECT_EQ(0, cache.disk_cache()->open_count());
2631 EXPECT_EQ(0, cache.disk_cache()->create_count());
2633 RemoveMockTransaction(&mock_network_response);
2636 // Test that when doing an externally conditionalized if-modified-since
2637 // if the date does not match the cache entry's last-modified date,
2638 // then we do NOT use the response (304) to update the cache.
2639 // (the if-modified-since date is 2 days AFTER the cache's modification date).
2640 TEST(HttpCache, ConditionalizedRequestUpdatesCache6) {
2641 static const Response kNetResponse1 = {
2642 "HTTP/1.1 200 OK",
2643 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2644 "Server: server1\n"
2645 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2646 "body1"
2649 // Second network response for |kUrl|.
2650 static const Response kNetResponse2 = {
2651 "HTTP/1.1 304 Not Modified",
2652 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2653 "Server: server2\n"
2654 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2658 // This is two days in the future from the original response's last-modified
2659 // date!
2660 const char kExtraRequestHeaders[] =
2661 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n";
2663 ConditionalizedRequestUpdatesCacheHelper(
2664 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2667 // Test that when doing an externally conditionalized if-none-match
2668 // if the etag does not match the cache entry's etag, then we do not use the
2669 // response (304) to update the cache.
2670 TEST(HttpCache, ConditionalizedRequestUpdatesCache7) {
2671 static const Response kNetResponse1 = {
2672 "HTTP/1.1 200 OK",
2673 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2674 "Etag: \"Foo1\"\n"
2675 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2676 "body1"
2679 // Second network response for |kUrl|.
2680 static const Response kNetResponse2 = {
2681 "HTTP/1.1 304 Not Modified",
2682 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2683 "Etag: \"Foo2\"\n"
2684 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2688 // Different etag from original response.
2689 const char kExtraRequestHeaders[] = "If-None-Match: \"Foo2\"\r\n";
2691 ConditionalizedRequestUpdatesCacheHelper(
2692 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2695 // Test that doing an externally conditionalized request with both if-none-match
2696 // and if-modified-since updates the cache.
2697 TEST(HttpCache, ConditionalizedRequestUpdatesCache8) {
2698 static const Response kNetResponse1 = {
2699 "HTTP/1.1 200 OK",
2700 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2701 "Etag: \"Foo1\"\n"
2702 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2703 "body1"
2706 // Second network response for |kUrl|.
2707 static const Response kNetResponse2 = {
2708 "HTTP/1.1 200 OK",
2709 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2710 "Etag: \"Foo2\"\n"
2711 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2712 "body2"
2715 const char kExtraRequestHeaders[] =
2716 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
2717 "If-None-Match: \"Foo1\"\r\n";
2719 ConditionalizedRequestUpdatesCacheHelper(
2720 kNetResponse1, kNetResponse2, kNetResponse2, kExtraRequestHeaders);
2723 // Test that doing an externally conditionalized request with both if-none-match
2724 // and if-modified-since does not update the cache with only one match.
2725 TEST(HttpCache, ConditionalizedRequestUpdatesCache9) {
2726 static const Response kNetResponse1 = {
2727 "HTTP/1.1 200 OK",
2728 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2729 "Etag: \"Foo1\"\n"
2730 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2731 "body1"
2734 // Second network response for |kUrl|.
2735 static const Response kNetResponse2 = {
2736 "HTTP/1.1 200 OK",
2737 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2738 "Etag: \"Foo2\"\n"
2739 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2740 "body2"
2743 // The etag doesn't match what we have stored.
2744 const char kExtraRequestHeaders[] =
2745 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
2746 "If-None-Match: \"Foo2\"\r\n";
2748 ConditionalizedRequestUpdatesCacheHelper(
2749 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2752 // Test that doing an externally conditionalized request with both if-none-match
2753 // and if-modified-since does not update the cache with only one match.
2754 TEST(HttpCache, ConditionalizedRequestUpdatesCache10) {
2755 static const Response kNetResponse1 = {
2756 "HTTP/1.1 200 OK",
2757 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2758 "Etag: \"Foo1\"\n"
2759 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2760 "body1"
2763 // Second network response for |kUrl|.
2764 static const Response kNetResponse2 = {
2765 "HTTP/1.1 200 OK",
2766 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2767 "Etag: \"Foo2\"\n"
2768 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2769 "body2"
2772 // The modification date doesn't match what we have stored.
2773 const char kExtraRequestHeaders[] =
2774 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n"
2775 "If-None-Match: \"Foo1\"\r\n";
2777 ConditionalizedRequestUpdatesCacheHelper(
2778 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2781 TEST(HttpCache, UrlContainingHash) {
2782 MockHttpCache cache;
2784 // Do a typical GET request -- should write an entry into our cache.
2785 MockTransaction trans(kTypicalGET_Transaction);
2786 RunTransactionTest(cache.http_cache(), trans);
2788 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2789 EXPECT_EQ(0, cache.disk_cache()->open_count());
2790 EXPECT_EQ(1, cache.disk_cache()->create_count());
2792 // Request the same URL, but this time with a reference section (hash).
2793 // Since the cache key strips the hash sections, this should be a cache hit.
2794 std::string url_with_hash = std::string(trans.url) + "#multiple#hashes";
2795 trans.url = url_with_hash.c_str();
2796 trans.load_flags = LOAD_ONLY_FROM_CACHE;
2798 RunTransactionTest(cache.http_cache(), trans);
2800 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2801 EXPECT_EQ(1, cache.disk_cache()->open_count());
2802 EXPECT_EQ(1, cache.disk_cache()->create_count());
2805 // Tests that we skip the cache for POST requests that do not have an upload
2806 // identifier.
2807 TEST(HttpCache, SimplePOST_SkipsCache) {
2808 MockHttpCache cache;
2810 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
2812 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2813 EXPECT_EQ(0, cache.disk_cache()->open_count());
2814 EXPECT_EQ(0, cache.disk_cache()->create_count());
2817 // Tests POST handling with a disabled cache (no DCHECK).
2818 TEST(HttpCache, SimplePOST_DisabledCache) {
2819 MockHttpCache cache;
2820 cache.http_cache()->set_mode(HttpCache::Mode::DISABLE);
2822 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
2824 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2825 EXPECT_EQ(0, cache.disk_cache()->open_count());
2826 EXPECT_EQ(0, cache.disk_cache()->create_count());
2829 TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Miss) {
2830 MockHttpCache cache;
2832 MockTransaction transaction(kSimplePOST_Transaction);
2833 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
2835 MockHttpRequest request(transaction);
2836 TestCompletionCallback callback;
2838 scoped_ptr<HttpTransaction> trans;
2839 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
2840 ASSERT_TRUE(trans.get());
2842 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2843 ASSERT_EQ(ERR_CACHE_MISS, callback.GetResult(rv));
2845 trans.reset();
2847 EXPECT_EQ(0, cache.network_layer()->transaction_count());
2848 EXPECT_EQ(0, cache.disk_cache()->open_count());
2849 EXPECT_EQ(0, cache.disk_cache()->create_count());
2852 TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Hit) {
2853 MockHttpCache cache;
2855 // Test that we hit the cache for POST requests.
2857 MockTransaction transaction(kSimplePOST_Transaction);
2859 const int64 kUploadId = 1; // Just a dummy value.
2861 ScopedVector<UploadElementReader> element_readers;
2862 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2863 ElementsUploadDataStream upload_data_stream(element_readers.Pass(),
2864 kUploadId);
2865 MockHttpRequest request(transaction);
2866 request.upload_data_stream = &upload_data_stream;
2868 // Populate the cache.
2869 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
2871 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2872 EXPECT_EQ(0, cache.disk_cache()->open_count());
2873 EXPECT_EQ(1, cache.disk_cache()->create_count());
2875 // Load from cache.
2876 request.load_flags |= LOAD_ONLY_FROM_CACHE;
2877 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
2879 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2880 EXPECT_EQ(1, cache.disk_cache()->open_count());
2881 EXPECT_EQ(1, cache.disk_cache()->create_count());
2884 // Test that we don't hit the cache for POST requests if there is a byte range.
2885 TEST(HttpCache, SimplePOST_WithRanges) {
2886 MockHttpCache cache;
2888 MockTransaction transaction(kSimplePOST_Transaction);
2889 transaction.request_headers = "Range: bytes = 0-4\r\n";
2891 const int64 kUploadId = 1; // Just a dummy value.
2893 ScopedVector<UploadElementReader> element_readers;
2894 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2895 ElementsUploadDataStream upload_data_stream(element_readers.Pass(),
2896 kUploadId);
2898 MockHttpRequest request(transaction);
2899 request.upload_data_stream = &upload_data_stream;
2901 // Attempt to populate the cache.
2902 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
2904 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2905 EXPECT_EQ(0, cache.disk_cache()->open_count());
2906 EXPECT_EQ(0, cache.disk_cache()->create_count());
2909 // Tests that a POST is cached separately from a previously cached GET.
2910 TEST(HttpCache, SimplePOST_SeparateCache) {
2911 MockHttpCache cache;
2913 ScopedVector<UploadElementReader> element_readers;
2914 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2915 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1);
2917 MockTransaction transaction(kSimplePOST_Transaction);
2918 MockHttpRequest req1(transaction);
2919 req1.upload_data_stream = &upload_data_stream;
2921 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
2923 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2924 EXPECT_EQ(0, cache.disk_cache()->open_count());
2925 EXPECT_EQ(1, cache.disk_cache()->create_count());
2927 transaction.method = "GET";
2928 MockHttpRequest req2(transaction);
2930 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
2932 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2933 EXPECT_EQ(0, cache.disk_cache()->open_count());
2934 EXPECT_EQ(2, cache.disk_cache()->create_count());
2937 // Tests that a successful POST invalidates a previously cached GET.
2938 TEST(HttpCache, SimplePOST_Invalidate_205) {
2939 MockHttpCache cache;
2941 MockTransaction transaction(kSimpleGET_Transaction);
2942 AddMockTransaction(&transaction);
2943 MockHttpRequest req1(transaction);
2945 // Attempt to populate the cache.
2946 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
2948 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2949 EXPECT_EQ(0, cache.disk_cache()->open_count());
2950 EXPECT_EQ(1, cache.disk_cache()->create_count());
2952 ScopedVector<UploadElementReader> element_readers;
2953 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2954 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1);
2956 transaction.method = "POST";
2957 transaction.status = "HTTP/1.1 205 No Content";
2958 MockHttpRequest req2(transaction);
2959 req2.upload_data_stream = &upload_data_stream;
2961 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
2963 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2964 EXPECT_EQ(0, cache.disk_cache()->open_count());
2965 EXPECT_EQ(2, cache.disk_cache()->create_count());
2967 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
2969 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2970 EXPECT_EQ(0, cache.disk_cache()->open_count());
2971 EXPECT_EQ(3, cache.disk_cache()->create_count());
2972 RemoveMockTransaction(&transaction);
2975 // Tests that a successful POST invalidates a previously cached GET, even when
2976 // there is no upload identifier.
2977 TEST(HttpCache, SimplePOST_NoUploadId_Invalidate_205) {
2978 MockHttpCache cache;
2980 MockTransaction transaction(kSimpleGET_Transaction);
2981 AddMockTransaction(&transaction);
2982 MockHttpRequest req1(transaction);
2984 // Attempt to populate the cache.
2985 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
2987 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2988 EXPECT_EQ(0, cache.disk_cache()->open_count());
2989 EXPECT_EQ(1, cache.disk_cache()->create_count());
2991 ScopedVector<UploadElementReader> element_readers;
2992 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2993 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
2995 transaction.method = "POST";
2996 transaction.status = "HTTP/1.1 205 No Content";
2997 MockHttpRequest req2(transaction);
2998 req2.upload_data_stream = &upload_data_stream;
3000 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3002 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3003 EXPECT_EQ(0, cache.disk_cache()->open_count());
3004 EXPECT_EQ(1, cache.disk_cache()->create_count());
3006 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3008 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3009 EXPECT_EQ(0, cache.disk_cache()->open_count());
3010 EXPECT_EQ(2, cache.disk_cache()->create_count());
3011 RemoveMockTransaction(&transaction);
3014 // Tests that processing a POST before creating the backend doesn't crash.
3015 TEST(HttpCache, SimplePOST_NoUploadId_NoBackend) {
3016 // This will initialize a cache object with NULL backend.
3017 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
3018 factory->set_fail(true);
3019 factory->FinishCreation();
3020 MockHttpCache cache(factory);
3022 ScopedVector<UploadElementReader> element_readers;
3023 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3024 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3026 MockTransaction transaction(kSimplePOST_Transaction);
3027 AddMockTransaction(&transaction);
3028 MockHttpRequest req(transaction);
3029 req.upload_data_stream = &upload_data_stream;
3031 RunTransactionTestWithRequest(cache.http_cache(), transaction, req, NULL);
3033 RemoveMockTransaction(&transaction);
3036 // Tests that we don't invalidate entries as a result of a failed POST.
3037 TEST(HttpCache, SimplePOST_DontInvalidate_100) {
3038 MockHttpCache cache;
3040 MockTransaction transaction(kSimpleGET_Transaction);
3041 AddMockTransaction(&transaction);
3042 MockHttpRequest req1(transaction);
3044 // Attempt to populate the cache.
3045 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3047 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3048 EXPECT_EQ(0, cache.disk_cache()->open_count());
3049 EXPECT_EQ(1, cache.disk_cache()->create_count());
3051 ScopedVector<UploadElementReader> element_readers;
3052 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3053 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1);
3055 transaction.method = "POST";
3056 transaction.status = "HTTP/1.1 100 Continue";
3057 MockHttpRequest req2(transaction);
3058 req2.upload_data_stream = &upload_data_stream;
3060 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3062 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3063 EXPECT_EQ(0, cache.disk_cache()->open_count());
3064 EXPECT_EQ(2, cache.disk_cache()->create_count());
3066 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3068 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3069 EXPECT_EQ(1, cache.disk_cache()->open_count());
3070 EXPECT_EQ(2, cache.disk_cache()->create_count());
3071 RemoveMockTransaction(&transaction);
3074 // Tests that a HEAD request is not cached by itself.
3075 TEST(HttpCache, SimpleHEAD_LoadOnlyFromCache_Miss) {
3076 MockHttpCache cache;
3077 MockTransaction transaction(kSimplePOST_Transaction);
3078 AddMockTransaction(&transaction);
3079 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3080 transaction.method = "HEAD";
3082 MockHttpRequest request(transaction);
3083 TestCompletionCallback callback;
3085 scoped_ptr<HttpTransaction> trans;
3086 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
3087 ASSERT_TRUE(trans.get());
3089 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3090 ASSERT_EQ(ERR_CACHE_MISS, callback.GetResult(rv));
3092 trans.reset();
3094 EXPECT_EQ(0, cache.network_layer()->transaction_count());
3095 EXPECT_EQ(0, cache.disk_cache()->open_count());
3096 EXPECT_EQ(0, cache.disk_cache()->create_count());
3097 RemoveMockTransaction(&transaction);
3100 // Tests that a HEAD request is served from a cached GET.
3101 TEST(HttpCache, SimpleHEAD_LoadOnlyFromCache_Hit) {
3102 MockHttpCache cache;
3103 MockTransaction transaction(kSimpleGET_Transaction);
3104 AddMockTransaction(&transaction);
3106 // Populate the cache.
3107 RunTransactionTest(cache.http_cache(), transaction);
3109 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3110 EXPECT_EQ(0, cache.disk_cache()->open_count());
3111 EXPECT_EQ(1, cache.disk_cache()->create_count());
3113 // Load from cache.
3114 transaction.method = "HEAD";
3115 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3116 transaction.data = "";
3117 RunTransactionTest(cache.http_cache(), transaction);
3119 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3120 EXPECT_EQ(1, cache.disk_cache()->open_count());
3121 EXPECT_EQ(1, cache.disk_cache()->create_count());
3122 RemoveMockTransaction(&transaction);
3125 // Tests that a read-only request served from the cache preserves CL.
3126 TEST(HttpCache, SimpleHEAD_ContentLengthOnHit_Read) {
3127 MockHttpCache cache;
3128 MockTransaction transaction(kSimpleGET_Transaction);
3129 AddMockTransaction(&transaction);
3130 transaction.response_headers = "Content-Length: 42\n";
3132 // Populate the cache.
3133 RunTransactionTest(cache.http_cache(), transaction);
3135 // Load from cache.
3136 transaction.method = "HEAD";
3137 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3138 transaction.data = "";
3139 std::string headers;
3141 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3143 EXPECT_EQ("HTTP/1.1 200 OK\nContent-Length: 42\n", headers);
3144 RemoveMockTransaction(&transaction);
3147 // Tests that a read-write request served from the cache preserves CL.
3148 TEST(HttpCache, ETagHEAD_ContentLengthOnHit_ReadWrite) {
3149 MockHttpCache cache;
3150 MockTransaction transaction(kETagGET_Transaction);
3151 AddMockTransaction(&transaction);
3152 std::string server_headers(kETagGET_Transaction.response_headers);
3153 server_headers.append("Content-Length: 42\n");
3154 transaction.response_headers = server_headers.data();
3156 // Populate the cache.
3157 RunTransactionTest(cache.http_cache(), transaction);
3159 // Load from cache.
3160 transaction.method = "HEAD";
3161 transaction.data = "";
3162 std::string headers;
3164 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3166 EXPECT_NE(std::string::npos, headers.find("Content-Length: 42\n"));
3167 RemoveMockTransaction(&transaction);
3170 // Tests that a HEAD request that includes byte ranges bypasses the cache.
3171 TEST(HttpCache, SimpleHEAD_WithRanges) {
3172 MockHttpCache cache;
3173 MockTransaction transaction(kSimpleGET_Transaction);
3174 AddMockTransaction(&transaction);
3176 // Populate the cache.
3177 RunTransactionTest(cache.http_cache(), transaction);
3179 // Load from cache.
3180 transaction.method = "HEAD";
3181 transaction.request_headers = "Range: bytes = 0-4\r\n";
3182 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3183 transaction.return_code = ERR_CACHE_MISS;
3184 RunTransactionTest(cache.http_cache(), transaction);
3186 EXPECT_EQ(0, cache.disk_cache()->open_count());
3187 EXPECT_EQ(1, cache.disk_cache()->create_count());
3188 RemoveMockTransaction(&transaction);
3191 // Tests that a HEAD request can be served from a partialy cached resource.
3192 TEST(HttpCache, SimpleHEAD_WithCachedRanges) {
3193 MockHttpCache cache;
3194 AddMockTransaction(&kRangeGET_TransactionOK);
3196 // Write to the cache (40-49).
3197 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
3198 RemoveMockTransaction(&kRangeGET_TransactionOK);
3200 MockTransaction transaction(kSimpleGET_Transaction);
3202 transaction.url = kRangeGET_TransactionOK.url;
3203 transaction.method = "HEAD";
3204 transaction.data = "";
3205 AddMockTransaction(&transaction);
3206 std::string headers;
3208 // Load from cache.
3209 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3211 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
3212 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
3213 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
3214 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3215 EXPECT_EQ(1, cache.disk_cache()->open_count());
3216 EXPECT_EQ(1, cache.disk_cache()->create_count());
3217 RemoveMockTransaction(&transaction);
3220 // Tests that a HEAD request can be served from a truncated resource.
3221 TEST(HttpCache, SimpleHEAD_WithTruncatedEntry) {
3222 MockHttpCache cache;
3223 AddMockTransaction(&kRangeGET_TransactionOK);
3225 std::string raw_headers("HTTP/1.1 200 OK\n"
3226 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
3227 "ETag: \"foo\"\n"
3228 "Accept-Ranges: bytes\n"
3229 "Content-Length: 80\n");
3230 CreateTruncatedEntry(raw_headers, &cache);
3231 RemoveMockTransaction(&kRangeGET_TransactionOK);
3233 MockTransaction transaction(kSimpleGET_Transaction);
3235 transaction.url = kRangeGET_TransactionOK.url;
3236 transaction.method = "HEAD";
3237 transaction.data = "";
3238 AddMockTransaction(&transaction);
3239 std::string headers;
3241 // Load from cache.
3242 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3244 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
3245 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
3246 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
3247 EXPECT_EQ(0, cache.network_layer()->transaction_count());
3248 EXPECT_EQ(1, cache.disk_cache()->open_count());
3249 EXPECT_EQ(1, cache.disk_cache()->create_count());
3250 RemoveMockTransaction(&transaction);
3253 // Tests that a HEAD request updates the cached response.
3254 TEST(HttpCache, TypicalHEAD_UpdatesResponse) {
3255 MockHttpCache cache;
3256 MockTransaction transaction(kTypicalGET_Transaction);
3257 AddMockTransaction(&transaction);
3259 // Populate the cache.
3260 RunTransactionTest(cache.http_cache(), transaction);
3262 // Update the cache.
3263 transaction.method = "HEAD";
3264 transaction.response_headers = "Foo: bar\n";
3265 transaction.data = "";
3266 transaction.status = "HTTP/1.1 304 Not Modified\n";
3267 std::string headers;
3268 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3269 RemoveMockTransaction(&transaction);
3271 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
3272 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3274 MockTransaction transaction2(kTypicalGET_Transaction);
3275 AddMockTransaction(&transaction2);
3277 // Make sure we are done with the previous transaction.
3278 base::MessageLoop::current()->RunUntilIdle();
3280 // Load from the cache.
3281 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE;
3282 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
3284 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
3285 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3286 EXPECT_EQ(2, cache.disk_cache()->open_count());
3287 EXPECT_EQ(1, cache.disk_cache()->create_count());
3288 RemoveMockTransaction(&transaction2);
3291 // Tests that an externally conditionalized HEAD request updates the cache.
3292 TEST(HttpCache, TypicalHEAD_ConditionalizedRequestUpdatesResponse) {
3293 MockHttpCache cache;
3294 MockTransaction transaction(kTypicalGET_Transaction);
3295 AddMockTransaction(&transaction);
3297 // Populate the cache.
3298 RunTransactionTest(cache.http_cache(), transaction);
3300 // Update the cache.
3301 transaction.method = "HEAD";
3302 transaction.request_headers =
3303 "If-Modified-Since: Wed, 28 Nov 2007 00:40:09 GMT\r\n";
3304 transaction.response_headers = "Foo: bar\n";
3305 transaction.data = "";
3306 transaction.status = "HTTP/1.1 304 Not Modified\n";
3307 std::string headers;
3308 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3309 RemoveMockTransaction(&transaction);
3311 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 304 Not Modified\n"));
3312 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3314 MockTransaction transaction2(kTypicalGET_Transaction);
3315 AddMockTransaction(&transaction2);
3317 // Make sure we are done with the previous transaction.
3318 base::MessageLoop::current()->RunUntilIdle();
3320 // Load from the cache.
3321 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE;
3322 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
3324 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
3325 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3326 EXPECT_EQ(2, cache.disk_cache()->open_count());
3327 EXPECT_EQ(1, cache.disk_cache()->create_count());
3328 RemoveMockTransaction(&transaction2);
3331 // Tests that a HEAD request invalidates an old cached entry.
3332 TEST(HttpCache, SimpleHEAD_InvalidatesEntry) {
3333 MockHttpCache cache;
3334 MockTransaction transaction(kTypicalGET_Transaction);
3335 AddMockTransaction(&transaction);
3337 // Populate the cache.
3338 RunTransactionTest(cache.http_cache(), transaction);
3340 // Update the cache.
3341 transaction.method = "HEAD";
3342 transaction.data = "";
3343 RunTransactionTest(cache.http_cache(), transaction);
3344 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3346 // Load from the cache.
3347 transaction.method = "GET";
3348 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3349 transaction.return_code = ERR_CACHE_MISS;
3350 RunTransactionTest(cache.http_cache(), transaction);
3352 RemoveMockTransaction(&transaction);
3355 // Tests that we do not cache the response of a PUT.
3356 TEST(HttpCache, SimplePUT_Miss) {
3357 MockHttpCache cache;
3359 MockTransaction transaction(kSimplePOST_Transaction);
3360 transaction.method = "PUT";
3362 ScopedVector<UploadElementReader> element_readers;
3363 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3364 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3366 MockHttpRequest request(transaction);
3367 request.upload_data_stream = &upload_data_stream;
3369 // Attempt to populate the cache.
3370 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
3372 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3373 EXPECT_EQ(0, cache.disk_cache()->open_count());
3374 EXPECT_EQ(0, cache.disk_cache()->create_count());
3377 // Tests that we invalidate entries as a result of a PUT.
3378 TEST(HttpCache, SimplePUT_Invalidate) {
3379 MockHttpCache cache;
3381 MockTransaction transaction(kSimpleGET_Transaction);
3382 MockHttpRequest req1(transaction);
3384 // Attempt to populate the cache.
3385 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3387 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3388 EXPECT_EQ(0, cache.disk_cache()->open_count());
3389 EXPECT_EQ(1, cache.disk_cache()->create_count());
3391 ScopedVector<UploadElementReader> element_readers;
3392 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3393 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3395 transaction.method = "PUT";
3396 MockHttpRequest req2(transaction);
3397 req2.upload_data_stream = &upload_data_stream;
3399 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3401 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3402 EXPECT_EQ(1, cache.disk_cache()->open_count());
3403 EXPECT_EQ(1, cache.disk_cache()->create_count());
3405 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3407 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3408 EXPECT_EQ(1, cache.disk_cache()->open_count());
3409 EXPECT_EQ(2, cache.disk_cache()->create_count());
3412 // Tests that we invalidate entries as a result of a PUT.
3413 TEST(HttpCache, SimplePUT_Invalidate_305) {
3414 MockHttpCache cache;
3416 MockTransaction transaction(kSimpleGET_Transaction);
3417 AddMockTransaction(&transaction);
3418 MockHttpRequest req1(transaction);
3420 // Attempt to populate the cache.
3421 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3423 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3424 EXPECT_EQ(0, cache.disk_cache()->open_count());
3425 EXPECT_EQ(1, cache.disk_cache()->create_count());
3427 ScopedVector<UploadElementReader> element_readers;
3428 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3429 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3431 transaction.method = "PUT";
3432 transaction.status = "HTTP/1.1 305 Use Proxy";
3433 MockHttpRequest req2(transaction);
3434 req2.upload_data_stream = &upload_data_stream;
3436 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3438 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3439 EXPECT_EQ(1, cache.disk_cache()->open_count());
3440 EXPECT_EQ(1, cache.disk_cache()->create_count());
3442 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3444 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3445 EXPECT_EQ(1, cache.disk_cache()->open_count());
3446 EXPECT_EQ(2, cache.disk_cache()->create_count());
3447 RemoveMockTransaction(&transaction);
3450 // Tests that we don't invalidate entries as a result of a failed PUT.
3451 TEST(HttpCache, SimplePUT_DontInvalidate_404) {
3452 MockHttpCache cache;
3454 MockTransaction transaction(kSimpleGET_Transaction);
3455 AddMockTransaction(&transaction);
3456 MockHttpRequest req1(transaction);
3458 // Attempt to populate the cache.
3459 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3461 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3462 EXPECT_EQ(0, cache.disk_cache()->open_count());
3463 EXPECT_EQ(1, cache.disk_cache()->create_count());
3465 ScopedVector<UploadElementReader> element_readers;
3466 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3467 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3469 transaction.method = "PUT";
3470 transaction.status = "HTTP/1.1 404 Not Found";
3471 MockHttpRequest req2(transaction);
3472 req2.upload_data_stream = &upload_data_stream;
3474 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3476 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3477 EXPECT_EQ(1, cache.disk_cache()->open_count());
3478 EXPECT_EQ(1, cache.disk_cache()->create_count());
3480 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3482 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3483 EXPECT_EQ(2, cache.disk_cache()->open_count());
3484 EXPECT_EQ(1, cache.disk_cache()->create_count());
3485 RemoveMockTransaction(&transaction);
3488 // Tests that we do not cache the response of a DELETE.
3489 TEST(HttpCache, SimpleDELETE_Miss) {
3490 MockHttpCache cache;
3492 MockTransaction transaction(kSimplePOST_Transaction);
3493 transaction.method = "DELETE";
3495 ScopedVector<UploadElementReader> element_readers;
3496 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3497 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3499 MockHttpRequest request(transaction);
3500 request.upload_data_stream = &upload_data_stream;
3502 // Attempt to populate the cache.
3503 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
3505 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3506 EXPECT_EQ(0, cache.disk_cache()->open_count());
3507 EXPECT_EQ(0, cache.disk_cache()->create_count());
3510 // Tests that we invalidate entries as a result of a DELETE.
3511 TEST(HttpCache, SimpleDELETE_Invalidate) {
3512 MockHttpCache cache;
3514 MockTransaction transaction(kSimpleGET_Transaction);
3515 MockHttpRequest req1(transaction);
3517 // Attempt to populate the cache.
3518 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3520 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3521 EXPECT_EQ(0, cache.disk_cache()->open_count());
3522 EXPECT_EQ(1, cache.disk_cache()->create_count());
3524 ScopedVector<UploadElementReader> element_readers;
3525 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3526 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3528 transaction.method = "DELETE";
3529 MockHttpRequest req2(transaction);
3530 req2.upload_data_stream = &upload_data_stream;
3532 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3534 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3535 EXPECT_EQ(1, cache.disk_cache()->open_count());
3536 EXPECT_EQ(1, cache.disk_cache()->create_count());
3538 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3540 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3541 EXPECT_EQ(1, cache.disk_cache()->open_count());
3542 EXPECT_EQ(2, cache.disk_cache()->create_count());
3545 // Tests that we invalidate entries as a result of a DELETE.
3546 TEST(HttpCache, SimpleDELETE_Invalidate_301) {
3547 MockHttpCache cache;
3549 MockTransaction transaction(kSimpleGET_Transaction);
3550 AddMockTransaction(&transaction);
3552 // Attempt to populate the cache.
3553 RunTransactionTest(cache.http_cache(), transaction);
3555 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3556 EXPECT_EQ(0, cache.disk_cache()->open_count());
3557 EXPECT_EQ(1, cache.disk_cache()->create_count());
3559 transaction.method = "DELETE";
3560 transaction.status = "HTTP/1.1 301 Moved Permanently ";
3562 RunTransactionTest(cache.http_cache(), transaction);
3564 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3565 EXPECT_EQ(1, cache.disk_cache()->open_count());
3566 EXPECT_EQ(1, cache.disk_cache()->create_count());
3568 transaction.method = "GET";
3569 RunTransactionTest(cache.http_cache(), transaction);
3571 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3572 EXPECT_EQ(1, cache.disk_cache()->open_count());
3573 EXPECT_EQ(2, cache.disk_cache()->create_count());
3574 RemoveMockTransaction(&transaction);
3577 // Tests that we don't invalidate entries as a result of a failed DELETE.
3578 TEST(HttpCache, SimpleDELETE_DontInvalidate_416) {
3579 MockHttpCache cache;
3581 MockTransaction transaction(kSimpleGET_Transaction);
3582 AddMockTransaction(&transaction);
3584 // Attempt to populate the cache.
3585 RunTransactionTest(cache.http_cache(), transaction);
3587 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3588 EXPECT_EQ(0, cache.disk_cache()->open_count());
3589 EXPECT_EQ(1, cache.disk_cache()->create_count());
3591 transaction.method = "DELETE";
3592 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
3594 RunTransactionTest(cache.http_cache(), transaction);
3596 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3597 EXPECT_EQ(1, cache.disk_cache()->open_count());
3598 EXPECT_EQ(1, cache.disk_cache()->create_count());
3600 transaction.method = "GET";
3601 transaction.status = "HTTP/1.1 200 OK";
3602 RunTransactionTest(cache.http_cache(), transaction);
3604 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3605 EXPECT_EQ(2, cache.disk_cache()->open_count());
3606 EXPECT_EQ(1, cache.disk_cache()->create_count());
3607 RemoveMockTransaction(&transaction);
3610 // Tests that we don't invalidate entries after a failed network transaction.
3611 TEST(HttpCache, SimpleGET_DontInvalidateOnFailure) {
3612 MockHttpCache cache;
3614 // Populate the cache.
3615 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
3616 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3618 // Fail the network request.
3619 MockTransaction transaction(kSimpleGET_Transaction);
3620 transaction.return_code = ERR_FAILED;
3621 transaction.load_flags |= LOAD_VALIDATE_CACHE;
3623 AddMockTransaction(&transaction);
3624 RunTransactionTest(cache.http_cache(), transaction);
3625 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3626 RemoveMockTransaction(&transaction);
3628 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
3629 transaction.return_code = OK;
3630 AddMockTransaction(&transaction);
3631 RunTransactionTest(cache.http_cache(), transaction);
3633 // Make sure the transaction didn't reach the network.
3634 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3635 RemoveMockTransaction(&transaction);
3638 TEST(HttpCache, RangeGET_SkipsCache) {
3639 MockHttpCache cache;
3641 // Test that we skip the cache for range GET requests. Eventually, we will
3642 // want to cache these, but we'll still have cases where skipping the cache
3643 // makes sense, so we want to make sure that it works properly.
3645 RunTransactionTest(cache.http_cache(), kRangeGET_Transaction);
3647 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3648 EXPECT_EQ(0, cache.disk_cache()->open_count());
3649 EXPECT_EQ(0, cache.disk_cache()->create_count());
3651 MockTransaction transaction(kSimpleGET_Transaction);
3652 transaction.request_headers = "If-None-Match: foo\r\n";
3653 RunTransactionTest(cache.http_cache(), transaction);
3655 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3656 EXPECT_EQ(0, cache.disk_cache()->open_count());
3657 EXPECT_EQ(0, cache.disk_cache()->create_count());
3659 transaction.request_headers =
3660 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n";
3661 RunTransactionTest(cache.http_cache(), transaction);
3663 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3664 EXPECT_EQ(0, cache.disk_cache()->open_count());
3665 EXPECT_EQ(0, cache.disk_cache()->create_count());
3668 // Test that we skip the cache for range requests that include a validation
3669 // header.
3670 TEST(HttpCache, RangeGET_SkipsCache2) {
3671 MockHttpCache cache;
3673 MockTransaction transaction(kRangeGET_Transaction);
3674 transaction.request_headers = "If-None-Match: foo\r\n"
3675 EXTRA_HEADER
3676 "Range: bytes = 40-49\r\n";
3677 RunTransactionTest(cache.http_cache(), transaction);
3679 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3680 EXPECT_EQ(0, cache.disk_cache()->open_count());
3681 EXPECT_EQ(0, cache.disk_cache()->create_count());
3683 transaction.request_headers =
3684 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n"
3685 EXTRA_HEADER
3686 "Range: bytes = 40-49\r\n";
3687 RunTransactionTest(cache.http_cache(), transaction);
3689 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3690 EXPECT_EQ(0, cache.disk_cache()->open_count());
3691 EXPECT_EQ(0, cache.disk_cache()->create_count());
3693 transaction.request_headers = "If-Range: bla\r\n"
3694 EXTRA_HEADER
3695 "Range: bytes = 40-49\r\n";
3696 RunTransactionTest(cache.http_cache(), transaction);
3698 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3699 EXPECT_EQ(0, cache.disk_cache()->open_count());
3700 EXPECT_EQ(0, cache.disk_cache()->create_count());
3703 TEST(HttpCache, SimpleGET_DoesntLogHeaders) {
3704 MockHttpCache cache;
3706 BoundTestNetLog log;
3707 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction,
3708 log.bound());
3710 EXPECT_FALSE(LogContainsEventType(
3711 log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS));
3714 TEST(HttpCache, RangeGET_LogsHeaders) {
3715 MockHttpCache cache;
3717 BoundTestNetLog log;
3718 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_Transaction,
3719 log.bound());
3721 EXPECT_TRUE(LogContainsEventType(
3722 log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS));
3725 TEST(HttpCache, ExternalValidation_LogsHeaders) {
3726 MockHttpCache cache;
3728 BoundTestNetLog log;
3729 MockTransaction transaction(kSimpleGET_Transaction);
3730 transaction.request_headers = "If-None-Match: foo\r\n" EXTRA_HEADER;
3731 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
3733 EXPECT_TRUE(LogContainsEventType(
3734 log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS));
3737 TEST(HttpCache, SpecialHeaders_LogsHeaders) {
3738 MockHttpCache cache;
3740 BoundTestNetLog log;
3741 MockTransaction transaction(kSimpleGET_Transaction);
3742 transaction.request_headers = "cache-control: no-cache\r\n" EXTRA_HEADER;
3743 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
3745 EXPECT_TRUE(LogContainsEventType(
3746 log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS));
3749 // Tests that receiving 206 for a regular request is handled correctly.
3750 TEST(HttpCache, GET_Crazy206) {
3751 MockHttpCache cache;
3753 // Write to the cache.
3754 MockTransaction transaction(kRangeGET_TransactionOK);
3755 AddMockTransaction(&transaction);
3756 transaction.request_headers = EXTRA_HEADER;
3757 transaction.handler = NULL;
3758 RunTransactionTest(cache.http_cache(), transaction);
3760 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3761 EXPECT_EQ(0, cache.disk_cache()->open_count());
3762 EXPECT_EQ(1, cache.disk_cache()->create_count());
3764 // This should read again from the net.
3765 RunTransactionTest(cache.http_cache(), transaction);
3767 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3768 EXPECT_EQ(0, cache.disk_cache()->open_count());
3769 EXPECT_EQ(2, cache.disk_cache()->create_count());
3770 RemoveMockTransaction(&transaction);
3773 // Tests that receiving 416 for a regular request is handled correctly.
3774 TEST(HttpCache, GET_Crazy416) {
3775 MockHttpCache cache;
3777 // Write to the cache.
3778 MockTransaction transaction(kSimpleGET_Transaction);
3779 AddMockTransaction(&transaction);
3780 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
3781 RunTransactionTest(cache.http_cache(), transaction);
3783 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3784 EXPECT_EQ(0, cache.disk_cache()->open_count());
3785 EXPECT_EQ(1, cache.disk_cache()->create_count());
3787 RemoveMockTransaction(&transaction);
3790 // Tests that we don't store partial responses that can't be validated.
3791 TEST(HttpCache, RangeGET_NoStrongValidators) {
3792 MockHttpCache cache;
3793 std::string headers;
3795 // Attempt to write to the cache (40-49).
3796 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3797 transaction.response_headers = "Content-Length: 10\n"
3798 "Cache-Control: max-age=3600\n"
3799 "ETag: w/\"foo\"\n";
3800 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3802 Verify206Response(headers, 40, 49);
3803 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3804 EXPECT_EQ(0, cache.disk_cache()->open_count());
3805 EXPECT_EQ(1, cache.disk_cache()->create_count());
3807 // Now verify that there's no cached data.
3808 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3809 &headers);
3811 Verify206Response(headers, 40, 49);
3812 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3813 EXPECT_EQ(0, cache.disk_cache()->open_count());
3814 EXPECT_EQ(2, cache.disk_cache()->create_count());
3817 // Tests failures to conditionalize byte range requests.
3818 TEST(HttpCache, RangeGET_NoConditionalization) {
3819 MockHttpCache cache;
3820 cache.FailConditionalizations();
3821 std::string headers;
3823 // Write to the cache (40-49).
3824 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3825 transaction.response_headers = "Content-Length: 10\n"
3826 "ETag: \"foo\"\n";
3827 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3829 Verify206Response(headers, 40, 49);
3830 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3831 EXPECT_EQ(0, cache.disk_cache()->open_count());
3832 EXPECT_EQ(1, cache.disk_cache()->create_count());
3834 // Now verify that the cached data is not used.
3835 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3836 &headers);
3838 Verify206Response(headers, 40, 49);
3839 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3840 EXPECT_EQ(1, cache.disk_cache()->open_count());
3841 EXPECT_EQ(2, cache.disk_cache()->create_count());
3844 // Tests that restarting a partial request when the cached data cannot be
3845 // revalidated logs an event.
3846 TEST(HttpCache, RangeGET_NoValidation_LogsRestart) {
3847 MockHttpCache cache;
3848 cache.FailConditionalizations();
3850 // Write to the cache (40-49).
3851 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3852 transaction.response_headers = "Content-Length: 10\n"
3853 "ETag: \"foo\"\n";
3854 RunTransactionTest(cache.http_cache(), transaction);
3856 // Now verify that the cached data is not used.
3857 BoundTestNetLog log;
3858 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_TransactionOK,
3859 log.bound());
3861 EXPECT_TRUE(LogContainsEventType(
3862 log, NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST));
3865 // Tests that a failure to conditionalize a regular request (no range) with a
3866 // sparse entry results in a full response.
3867 TEST(HttpCache, GET_NoConditionalization) {
3868 MockHttpCache cache;
3869 cache.FailConditionalizations();
3870 std::string headers;
3872 // Write to the cache (40-49).
3873 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3874 transaction.response_headers = "Content-Length: 10\n"
3875 "ETag: \"foo\"\n";
3876 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3878 Verify206Response(headers, 40, 49);
3879 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3880 EXPECT_EQ(0, cache.disk_cache()->open_count());
3881 EXPECT_EQ(1, cache.disk_cache()->create_count());
3883 // Now verify that the cached data is not used.
3884 // Don't ask for a range. The cache will attempt to use the cached data but
3885 // should discard it as it cannot be validated. A regular request should go
3886 // to the server and a new entry should be created.
3887 transaction.request_headers = EXTRA_HEADER;
3888 transaction.data = "Not a range";
3889 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3891 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
3892 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3893 EXPECT_EQ(1, cache.disk_cache()->open_count());
3894 EXPECT_EQ(2, cache.disk_cache()->create_count());
3896 // The last response was saved.
3897 RunTransactionTest(cache.http_cache(), transaction);
3898 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3899 EXPECT_EQ(2, cache.disk_cache()->open_count());
3900 EXPECT_EQ(2, cache.disk_cache()->create_count());
3903 // Verifies that conditionalization failures when asking for a range that would
3904 // require the cache to modify the range to ask, result in a network request
3905 // that matches the user's one.
3906 TEST(HttpCache, RangeGET_NoConditionalization2) {
3907 MockHttpCache cache;
3908 cache.FailConditionalizations();
3909 std::string headers;
3911 // Write to the cache (40-49).
3912 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3913 transaction.response_headers = "Content-Length: 10\n"
3914 "ETag: \"foo\"\n";
3915 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3917 Verify206Response(headers, 40, 49);
3918 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3919 EXPECT_EQ(0, cache.disk_cache()->open_count());
3920 EXPECT_EQ(1, cache.disk_cache()->create_count());
3922 // Now verify that the cached data is not used.
3923 // Ask for a range that extends before and after the cached data so that the
3924 // cache would normally mix data from three sources. After deleting the entry,
3925 // the response will come from a single network request.
3926 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
3927 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
3928 transaction.response_headers = kRangeGET_TransactionOK.response_headers;
3929 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3931 Verify206Response(headers, 20, 59);
3932 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3933 EXPECT_EQ(1, cache.disk_cache()->open_count());
3934 EXPECT_EQ(2, cache.disk_cache()->create_count());
3936 // The last response was saved.
3937 RunTransactionTest(cache.http_cache(), transaction);
3938 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3939 EXPECT_EQ(2, cache.disk_cache()->open_count());
3940 EXPECT_EQ(2, cache.disk_cache()->create_count());
3943 // Tests that we cache partial responses that lack content-length.
3944 TEST(HttpCache, RangeGET_NoContentLength) {
3945 MockHttpCache cache;
3946 std::string headers;
3948 // Attempt to write to the cache (40-49).
3949 MockTransaction transaction(kRangeGET_TransactionOK);
3950 AddMockTransaction(&transaction);
3951 transaction.response_headers = "ETag: \"foo\"\n"
3952 "Accept-Ranges: bytes\n"
3953 "Content-Range: bytes 40-49/80\n";
3954 transaction.handler = NULL;
3955 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3957 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3958 EXPECT_EQ(0, cache.disk_cache()->open_count());
3959 EXPECT_EQ(1, cache.disk_cache()->create_count());
3961 // Now verify that there's no cached data.
3962 transaction.handler = &RangeTransactionServer::RangeHandler;
3963 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3964 &headers);
3966 Verify206Response(headers, 40, 49);
3967 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3968 EXPECT_EQ(1, cache.disk_cache()->open_count());
3969 EXPECT_EQ(1, cache.disk_cache()->create_count());
3971 RemoveMockTransaction(&transaction);
3974 // Tests that we can cache range requests and fetch random blocks from the
3975 // cache and the network.
3976 TEST(HttpCache, RangeGET_OK) {
3977 MockHttpCache cache;
3978 AddMockTransaction(&kRangeGET_TransactionOK);
3979 std::string headers;
3981 // Write to the cache (40-49).
3982 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3983 &headers);
3985 Verify206Response(headers, 40, 49);
3986 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3987 EXPECT_EQ(0, cache.disk_cache()->open_count());
3988 EXPECT_EQ(1, cache.disk_cache()->create_count());
3990 // Read from the cache (40-49).
3991 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3992 &headers);
3994 Verify206Response(headers, 40, 49);
3995 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3996 EXPECT_EQ(1, cache.disk_cache()->open_count());
3997 EXPECT_EQ(1, cache.disk_cache()->create_count());
3999 // Make sure we are done with the previous transaction.
4000 base::MessageLoop::current()->RunUntilIdle();
4002 // Write to the cache (30-39).
4003 MockTransaction transaction(kRangeGET_TransactionOK);
4004 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
4005 transaction.data = "rg: 30-39 ";
4006 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4008 Verify206Response(headers, 30, 39);
4009 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4010 EXPECT_EQ(2, cache.disk_cache()->open_count());
4011 EXPECT_EQ(1, cache.disk_cache()->create_count());
4013 // Make sure we are done with the previous transaction.
4014 base::MessageLoop::current()->RunUntilIdle();
4016 // Write and read from the cache (20-59).
4017 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
4018 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
4019 BoundTestNetLog log;
4020 LoadTimingInfo load_timing_info;
4021 RunTransactionTestWithResponseAndGetTiming(
4022 cache.http_cache(), transaction, &headers, log.bound(),
4023 &load_timing_info);
4025 Verify206Response(headers, 20, 59);
4026 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4027 EXPECT_EQ(3, cache.disk_cache()->open_count());
4028 EXPECT_EQ(1, cache.disk_cache()->create_count());
4029 TestLoadTimingNetworkRequest(load_timing_info);
4031 RemoveMockTransaction(&kRangeGET_TransactionOK);
4034 // Tests that we can cache range requests and fetch random blocks from the
4035 // cache and the network, with synchronous responses.
4036 TEST(HttpCache, RangeGET_SyncOK) {
4037 MockHttpCache cache;
4039 MockTransaction transaction(kRangeGET_TransactionOK);
4040 transaction.test_mode = TEST_MODE_SYNC_ALL;
4041 AddMockTransaction(&transaction);
4043 // Write to the cache (40-49).
4044 std::string headers;
4045 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4047 Verify206Response(headers, 40, 49);
4048 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4049 EXPECT_EQ(0, cache.disk_cache()->open_count());
4050 EXPECT_EQ(1, cache.disk_cache()->create_count());
4052 // Read from the cache (40-49).
4053 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4055 Verify206Response(headers, 40, 49);
4056 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4057 EXPECT_EQ(0, cache.disk_cache()->open_count());
4058 EXPECT_EQ(1, cache.disk_cache()->create_count());
4060 // Make sure we are done with the previous transaction.
4061 base::MessageLoop::current()->RunUntilIdle();
4063 // Write to the cache (30-39).
4064 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
4065 transaction.data = "rg: 30-39 ";
4066 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4068 Verify206Response(headers, 30, 39);
4069 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4070 EXPECT_EQ(1, cache.disk_cache()->open_count());
4071 EXPECT_EQ(1, cache.disk_cache()->create_count());
4073 // Make sure we are done with the previous transaction.
4074 base::MessageLoop::current()->RunUntilIdle();
4076 // Write and read from the cache (20-59).
4077 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
4078 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
4079 BoundTestNetLog log;
4080 LoadTimingInfo load_timing_info;
4081 RunTransactionTestWithResponseAndGetTiming(
4082 cache.http_cache(), transaction, &headers, log.bound(),
4083 &load_timing_info);
4085 Verify206Response(headers, 20, 59);
4086 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4087 EXPECT_EQ(2, cache.disk_cache()->open_count());
4088 EXPECT_EQ(1, cache.disk_cache()->create_count());
4089 TestLoadTimingNetworkRequest(load_timing_info);
4091 RemoveMockTransaction(&transaction);
4094 // Tests that we don't revalidate an entry unless we are required to do so.
4095 TEST(HttpCache, RangeGET_Revalidate1) {
4096 MockHttpCache cache;
4097 std::string headers;
4099 // Write to the cache (40-49).
4100 MockTransaction transaction(kRangeGET_TransactionOK);
4101 transaction.response_headers =
4102 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
4103 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n" // Should never expire.
4104 "ETag: \"foo\"\n"
4105 "Accept-Ranges: bytes\n"
4106 "Content-Length: 10\n";
4107 AddMockTransaction(&transaction);
4108 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4110 Verify206Response(headers, 40, 49);
4111 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4112 EXPECT_EQ(0, cache.disk_cache()->open_count());
4113 EXPECT_EQ(1, cache.disk_cache()->create_count());
4115 // Read from the cache (40-49).
4116 BoundTestNetLog log;
4117 LoadTimingInfo load_timing_info;
4118 RunTransactionTestWithResponseAndGetTiming(
4119 cache.http_cache(), transaction, &headers, log.bound(),
4120 &load_timing_info);
4122 Verify206Response(headers, 40, 49);
4123 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4124 EXPECT_EQ(1, cache.disk_cache()->open_count());
4125 EXPECT_EQ(1, cache.disk_cache()->create_count());
4126 TestLoadTimingCachedResponse(load_timing_info);
4128 // Read again forcing the revalidation.
4129 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4130 RunTransactionTestWithResponseAndGetTiming(
4131 cache.http_cache(), transaction, &headers, log.bound(),
4132 &load_timing_info);
4134 Verify206Response(headers, 40, 49);
4135 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4136 EXPECT_EQ(1, cache.disk_cache()->open_count());
4137 EXPECT_EQ(1, cache.disk_cache()->create_count());
4138 TestLoadTimingNetworkRequest(load_timing_info);
4140 RemoveMockTransaction(&transaction);
4143 // Checks that we revalidate an entry when the headers say so.
4144 TEST(HttpCache, RangeGET_Revalidate2) {
4145 MockHttpCache cache;
4146 std::string headers;
4148 // Write to the cache (40-49).
4149 MockTransaction transaction(kRangeGET_TransactionOK);
4150 transaction.response_headers =
4151 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
4152 "Expires: Sat, 18 Apr 2009 01:10:43 GMT\n" // Expired.
4153 "ETag: \"foo\"\n"
4154 "Accept-Ranges: bytes\n"
4155 "Content-Length: 10\n";
4156 AddMockTransaction(&transaction);
4157 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4159 Verify206Response(headers, 40, 49);
4160 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4161 EXPECT_EQ(0, cache.disk_cache()->open_count());
4162 EXPECT_EQ(1, cache.disk_cache()->create_count());
4164 // Read from the cache (40-49).
4165 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4166 Verify206Response(headers, 40, 49);
4168 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4169 EXPECT_EQ(1, cache.disk_cache()->open_count());
4170 EXPECT_EQ(1, cache.disk_cache()->create_count());
4172 RemoveMockTransaction(&transaction);
4175 // Tests that we deal with 304s for range requests.
4176 TEST(HttpCache, RangeGET_304) {
4177 MockHttpCache cache;
4178 AddMockTransaction(&kRangeGET_TransactionOK);
4179 std::string headers;
4181 // Write to the cache (40-49).
4182 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4183 &headers);
4185 Verify206Response(headers, 40, 49);
4186 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4187 EXPECT_EQ(0, cache.disk_cache()->open_count());
4188 EXPECT_EQ(1, cache.disk_cache()->create_count());
4190 // Read from the cache (40-49).
4191 RangeTransactionServer handler;
4192 handler.set_not_modified(true);
4193 MockTransaction transaction(kRangeGET_TransactionOK);
4194 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4195 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4197 Verify206Response(headers, 40, 49);
4198 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4199 EXPECT_EQ(1, cache.disk_cache()->open_count());
4200 EXPECT_EQ(1, cache.disk_cache()->create_count());
4202 RemoveMockTransaction(&kRangeGET_TransactionOK);
4205 // Tests that we deal with 206s when revalidating range requests.
4206 TEST(HttpCache, RangeGET_ModifiedResult) {
4207 MockHttpCache cache;
4208 AddMockTransaction(&kRangeGET_TransactionOK);
4209 std::string headers;
4211 // Write to the cache (40-49).
4212 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4213 &headers);
4215 Verify206Response(headers, 40, 49);
4216 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4217 EXPECT_EQ(0, cache.disk_cache()->open_count());
4218 EXPECT_EQ(1, cache.disk_cache()->create_count());
4220 // Attempt to read from the cache (40-49).
4221 RangeTransactionServer handler;
4222 handler.set_modified(true);
4223 MockTransaction transaction(kRangeGET_TransactionOK);
4224 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4225 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4227 Verify206Response(headers, 40, 49);
4228 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4229 EXPECT_EQ(1, cache.disk_cache()->open_count());
4230 EXPECT_EQ(1, cache.disk_cache()->create_count());
4232 // And the entry should be gone.
4233 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4234 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4235 EXPECT_EQ(1, cache.disk_cache()->open_count());
4236 EXPECT_EQ(2, cache.disk_cache()->create_count());
4238 RemoveMockTransaction(&kRangeGET_TransactionOK);
4241 // Tests that when a server returns 206 with a sub-range of the requested range,
4242 // and there is nothing stored in the cache, the returned response is passed to
4243 // the caller as is. In this context, a subrange means a response that starts
4244 // with the same byte that was requested, but that is not the whole range that
4245 // was requested.
4246 TEST(HttpCache, RangeGET_206ReturnsSubrangeRange_NoCachedContent) {
4247 MockHttpCache cache;
4248 std::string headers;
4250 // Request a large range (40-59). The server sends 40-49.
4251 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4252 transaction.request_headers = "Range: bytes = 40-59\r\n" EXTRA_HEADER;
4253 transaction.response_headers =
4254 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4255 "ETag: \"foo\"\n"
4256 "Accept-Ranges: bytes\n"
4257 "Content-Length: 10\n"
4258 "Content-Range: bytes 40-49/80\n";
4259 transaction.handler = nullptr;
4260 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4262 Verify206Response(headers, 40, 49);
4263 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4264 EXPECT_EQ(0, cache.disk_cache()->open_count());
4265 EXPECT_EQ(1, cache.disk_cache()->create_count());
4268 // Tests that when a server returns 206 with a sub-range of the requested range,
4269 // and there was an entry stored in the cache, the cache gets out of the way.
4270 TEST(HttpCache, RangeGET_206ReturnsSubrangeRange_CachedContent) {
4271 MockHttpCache cache;
4272 std::string headers;
4274 // Write to the cache (70-79).
4275 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4276 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4277 transaction.data = "rg: 70-79 ";
4278 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4279 Verify206Response(headers, 70, 79);
4281 // Request a large range (40-79). The cache will ask the server for 40-59.
4282 // The server returns 40-49. The cache should consider the server confused and
4283 // abort caching, restarting the request without caching.
4284 transaction.request_headers = "Range: bytes = 40-79\r\n" EXTRA_HEADER;
4285 transaction.response_headers =
4286 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4287 "ETag: \"foo\"\n"
4288 "Accept-Ranges: bytes\n"
4289 "Content-Length: 10\n"
4290 "Content-Range: bytes 40-49/80\n";
4291 transaction.handler = nullptr;
4292 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4294 // Two new network requests were issued, one from the cache and another after
4295 // deleting the entry.
4296 Verify206Response(headers, 40, 49);
4297 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4298 EXPECT_EQ(1, cache.disk_cache()->open_count());
4299 EXPECT_EQ(1, cache.disk_cache()->create_count());
4301 // The entry was deleted.
4302 RunTransactionTest(cache.http_cache(), transaction);
4303 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4304 EXPECT_EQ(1, cache.disk_cache()->open_count());
4305 EXPECT_EQ(2, cache.disk_cache()->create_count());
4308 // Tests that when a server returns 206 with a sub-range of the requested range,
4309 // and there was an entry stored in the cache, the cache gets out of the way,
4310 // when the caller is not using ranges.
4311 TEST(HttpCache, GET_206ReturnsSubrangeRange_CachedContent) {
4312 MockHttpCache cache;
4313 std::string headers;
4315 // Write to the cache (70-79).
4316 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4317 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4318 transaction.data = "rg: 70-79 ";
4319 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4320 Verify206Response(headers, 70, 79);
4322 // Don't ask for a range. The cache will ask the server for 0-69.
4323 // The server returns 40-49. The cache should consider the server confused and
4324 // abort caching, restarting the request.
4325 // The second network request should not be a byte range request so the server
4326 // should return 200 + "Not a range"
4327 transaction.request_headers = "X-Return-Default-Range:\r\n" EXTRA_HEADER;
4328 transaction.data = "Not a range";
4329 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4331 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4332 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4333 EXPECT_EQ(1, cache.disk_cache()->open_count());
4334 EXPECT_EQ(1, cache.disk_cache()->create_count());
4336 // The entry was deleted.
4337 RunTransactionTest(cache.http_cache(), transaction);
4338 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4339 EXPECT_EQ(1, cache.disk_cache()->open_count());
4340 EXPECT_EQ(2, cache.disk_cache()->create_count());
4343 // Tests that when a server returns 206 with a random range and there is
4344 // nothing stored in the cache, the returned response is passed to the caller
4345 // as is. In this context, a WrongRange means that the returned range may or may
4346 // not have any relationship with the requested range (may or may not be
4347 // contained). The important part is that the first byte doesn't match the first
4348 // requested byte.
4349 TEST(HttpCache, RangeGET_206ReturnsWrongRange_NoCachedContent) {
4350 MockHttpCache cache;
4351 std::string headers;
4353 // Request a large range (30-59). The server sends (40-49).
4354 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4355 transaction.request_headers = "Range: bytes = 30-59\r\n" EXTRA_HEADER;
4356 transaction.response_headers =
4357 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4358 "ETag: \"foo\"\n"
4359 "Accept-Ranges: bytes\n"
4360 "Content-Length: 10\n"
4361 "Content-Range: bytes 40-49/80\n";
4362 transaction.handler = nullptr;
4363 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4365 Verify206Response(headers, 40, 49);
4366 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4367 EXPECT_EQ(0, cache.disk_cache()->open_count());
4368 EXPECT_EQ(1, cache.disk_cache()->create_count());
4370 // The entry was deleted.
4371 RunTransactionTest(cache.http_cache(), transaction);
4372 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4373 EXPECT_EQ(0, cache.disk_cache()->open_count());
4374 EXPECT_EQ(2, cache.disk_cache()->create_count());
4377 // Tests that when a server returns 206 with a random range and there is
4378 // an entry stored in the cache, the cache gets out of the way.
4379 TEST(HttpCache, RangeGET_206ReturnsWrongRange_CachedContent) {
4380 MockHttpCache cache;
4381 std::string headers;
4383 // Write to the cache (70-79).
4384 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4385 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4386 transaction.data = "rg: 70-79 ";
4387 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4388 Verify206Response(headers, 70, 79);
4390 // Request a large range (30-79). The cache will ask the server for 30-69.
4391 // The server returns 40-49. The cache should consider the server confused and
4392 // abort caching, returning the weird range to the caller.
4393 transaction.request_headers = "Range: bytes = 30-79\r\n" EXTRA_HEADER;
4394 transaction.response_headers =
4395 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4396 "ETag: \"foo\"\n"
4397 "Accept-Ranges: bytes\n"
4398 "Content-Length: 10\n"
4399 "Content-Range: bytes 40-49/80\n";
4400 transaction.handler = nullptr;
4401 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4403 Verify206Response(headers, 40, 49);
4404 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4405 EXPECT_EQ(1, cache.disk_cache()->open_count());
4406 EXPECT_EQ(1, cache.disk_cache()->create_count());
4408 // The entry was deleted.
4409 RunTransactionTest(cache.http_cache(), transaction);
4410 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4411 EXPECT_EQ(1, cache.disk_cache()->open_count());
4412 EXPECT_EQ(2, cache.disk_cache()->create_count());
4415 // Tests that when a caller asks for a range beyond EOF, with an empty cache,
4416 // the response matches the one provided by the server.
4417 TEST(HttpCache, RangeGET_206ReturnsSmallerFile_NoCachedContent) {
4418 MockHttpCache cache;
4419 std::string headers;
4421 // Request a large range (70-99). The server sends 70-79.
4422 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4423 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
4424 transaction.data = "rg: 70-79 ";
4425 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4427 Verify206Response(headers, 70, 79);
4428 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4429 EXPECT_EQ(0, cache.disk_cache()->open_count());
4430 EXPECT_EQ(1, cache.disk_cache()->create_count());
4432 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4433 EXPECT_EQ(1, cache.disk_cache()->open_count());
4436 // Tests that when a caller asks for a range beyond EOF, with a cached entry,
4437 // the cache automatically fixes the request.
4438 TEST(HttpCache, RangeGET_206ReturnsSmallerFile_CachedContent) {
4439 MockHttpCache cache;
4440 std::string headers;
4442 // Write to the cache (40-49).
4443 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4444 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4446 // Request a large range (70-99). The server sends 70-79.
4447 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
4448 transaction.data = "rg: 70-79 ";
4449 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4451 Verify206Response(headers, 70, 79);
4452 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4453 EXPECT_EQ(1, cache.disk_cache()->open_count());
4454 EXPECT_EQ(1, cache.disk_cache()->create_count());
4456 // The entry was not deleted (the range was automatically fixed).
4457 RunTransactionTest(cache.http_cache(), transaction);
4458 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4459 EXPECT_EQ(2, cache.disk_cache()->open_count());
4460 EXPECT_EQ(1, cache.disk_cache()->create_count());
4463 // Tests that when a caller asks for a not-satisfiable range, the server's
4464 // response is forwarded to the caller.
4465 TEST(HttpCache, RangeGET_416_NoCachedContent) {
4466 MockHttpCache cache;
4467 std::string headers;
4469 // Request a range beyond EOF (80-99).
4470 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4471 transaction.request_headers = "Range: bytes = 80-99\r\n" EXTRA_HEADER;
4472 transaction.data = "";
4473 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
4474 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4476 EXPECT_EQ(0U, headers.find(transaction.status));
4477 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4478 EXPECT_EQ(0, cache.disk_cache()->open_count());
4479 EXPECT_EQ(1, cache.disk_cache()->create_count());
4481 // The entry was deleted.
4482 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4483 EXPECT_EQ(2, cache.disk_cache()->create_count());
4486 // Tests that we cache 301s for range requests.
4487 TEST(HttpCache, RangeGET_301) {
4488 MockHttpCache cache;
4489 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4490 transaction.status = "HTTP/1.1 301 Moved Permanently";
4491 transaction.response_headers = "Location: http://www.bar.com/\n";
4492 transaction.data = "";
4493 transaction.handler = NULL;
4495 // Write to the cache.
4496 RunTransactionTest(cache.http_cache(), transaction);
4497 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4498 EXPECT_EQ(0, cache.disk_cache()->open_count());
4499 EXPECT_EQ(1, cache.disk_cache()->create_count());
4501 // Read from the cache.
4502 RunTransactionTest(cache.http_cache(), transaction);
4503 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4504 EXPECT_EQ(1, cache.disk_cache()->open_count());
4505 EXPECT_EQ(1, cache.disk_cache()->create_count());
4508 // Tests that we can cache range requests when the start or end is unknown.
4509 // We start with one suffix request, followed by a request from a given point.
4510 TEST(HttpCache, UnknownRangeGET_1) {
4511 MockHttpCache cache;
4512 AddMockTransaction(&kRangeGET_TransactionOK);
4513 std::string headers;
4515 // Write to the cache (70-79).
4516 MockTransaction transaction(kRangeGET_TransactionOK);
4517 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
4518 transaction.data = "rg: 70-79 ";
4519 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4521 Verify206Response(headers, 70, 79);
4522 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4523 EXPECT_EQ(0, cache.disk_cache()->open_count());
4524 EXPECT_EQ(1, cache.disk_cache()->create_count());
4526 // Make sure we are done with the previous transaction.
4527 base::MessageLoop::current()->RunUntilIdle();
4529 // Write and read from the cache (60-79).
4530 transaction.request_headers = "Range: bytes = 60-\r\n" EXTRA_HEADER;
4531 transaction.data = "rg: 60-69 rg: 70-79 ";
4532 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4534 Verify206Response(headers, 60, 79);
4535 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4536 EXPECT_EQ(1, cache.disk_cache()->open_count());
4537 EXPECT_EQ(1, cache.disk_cache()->create_count());
4539 RemoveMockTransaction(&kRangeGET_TransactionOK);
4542 // Tests that we can cache range requests when the start or end is unknown.
4543 // We start with one request from a given point, followed by a suffix request.
4544 // We'll also verify that synchronous cache responses work as intended.
4545 TEST(HttpCache, UnknownRangeGET_2) {
4546 MockHttpCache cache;
4547 std::string headers;
4549 MockTransaction transaction(kRangeGET_TransactionOK);
4550 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
4551 TEST_MODE_SYNC_CACHE_READ |
4552 TEST_MODE_SYNC_CACHE_WRITE;
4553 AddMockTransaction(&transaction);
4555 // Write to the cache (70-79).
4556 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
4557 transaction.data = "rg: 70-79 ";
4558 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4560 Verify206Response(headers, 70, 79);
4561 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4562 EXPECT_EQ(0, cache.disk_cache()->open_count());
4563 EXPECT_EQ(1, cache.disk_cache()->create_count());
4565 // Make sure we are done with the previous transaction.
4566 base::MessageLoop::current()->RunUntilIdle();
4568 // Write and read from the cache (60-79).
4569 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
4570 transaction.data = "rg: 60-69 rg: 70-79 ";
4571 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4573 Verify206Response(headers, 60, 79);
4574 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4575 EXPECT_EQ(1, cache.disk_cache()->open_count());
4576 EXPECT_EQ(1, cache.disk_cache()->create_count());
4578 RemoveMockTransaction(&transaction);
4581 // Tests that receiving Not Modified when asking for an open range doesn't mess
4582 // up things.
4583 TEST(HttpCache, UnknownRangeGET_304) {
4584 MockHttpCache cache;
4585 std::string headers;
4587 MockTransaction transaction(kRangeGET_TransactionOK);
4588 AddMockTransaction(&transaction);
4590 RangeTransactionServer handler;
4591 handler.set_not_modified(true);
4593 // Ask for the end of the file, without knowing the length.
4594 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
4595 transaction.data = "";
4596 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4598 // We just bypass the cache.
4599 EXPECT_EQ(0U, headers.find("HTTP/1.1 304 Not Modified\n"));
4600 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4601 EXPECT_EQ(0, cache.disk_cache()->open_count());
4602 EXPECT_EQ(1, cache.disk_cache()->create_count());
4604 RunTransactionTest(cache.http_cache(), transaction);
4605 EXPECT_EQ(2, cache.disk_cache()->create_count());
4607 RemoveMockTransaction(&transaction);
4610 // Tests that we can handle non-range requests when we have cached a range.
4611 TEST(HttpCache, GET_Previous206) {
4612 MockHttpCache cache;
4613 AddMockTransaction(&kRangeGET_TransactionOK);
4614 std::string headers;
4615 BoundTestNetLog log;
4616 LoadTimingInfo load_timing_info;
4618 // Write to the cache (40-49).
4619 RunTransactionTestWithResponseAndGetTiming(
4620 cache.http_cache(), kRangeGET_TransactionOK, &headers, log.bound(),
4621 &load_timing_info);
4623 Verify206Response(headers, 40, 49);
4624 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4625 EXPECT_EQ(0, cache.disk_cache()->open_count());
4626 EXPECT_EQ(1, cache.disk_cache()->create_count());
4627 TestLoadTimingNetworkRequest(load_timing_info);
4629 // Write and read from the cache (0-79), when not asked for a range.
4630 MockTransaction transaction(kRangeGET_TransactionOK);
4631 transaction.request_headers = EXTRA_HEADER;
4632 transaction.data = kFullRangeData;
4633 RunTransactionTestWithResponseAndGetTiming(
4634 cache.http_cache(), transaction, &headers, log.bound(),
4635 &load_timing_info);
4637 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4638 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4639 EXPECT_EQ(1, cache.disk_cache()->open_count());
4640 EXPECT_EQ(1, cache.disk_cache()->create_count());
4641 TestLoadTimingNetworkRequest(load_timing_info);
4643 RemoveMockTransaction(&kRangeGET_TransactionOK);
4646 // Tests that we can handle non-range requests when we have cached the first
4647 // part of the object and the server replies with 304 (Not Modified).
4648 TEST(HttpCache, GET_Previous206_NotModified) {
4649 MockHttpCache cache;
4651 MockTransaction transaction(kRangeGET_TransactionOK);
4652 AddMockTransaction(&transaction);
4653 std::string headers;
4654 BoundTestNetLog log;
4655 LoadTimingInfo load_timing_info;
4657 // Write to the cache (0-9).
4658 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
4659 transaction.data = "rg: 00-09 ";
4660 RunTransactionTestWithResponseAndGetTiming(
4661 cache.http_cache(), transaction, &headers, log.bound(),
4662 &load_timing_info);
4663 Verify206Response(headers, 0, 9);
4664 TestLoadTimingNetworkRequest(load_timing_info);
4666 // Write to the cache (70-79).
4667 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4668 transaction.data = "rg: 70-79 ";
4669 RunTransactionTestWithResponseAndGetTiming(
4670 cache.http_cache(), transaction, &headers, log.bound(),
4671 &load_timing_info);
4672 Verify206Response(headers, 70, 79);
4674 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4675 EXPECT_EQ(1, cache.disk_cache()->open_count());
4676 EXPECT_EQ(1, cache.disk_cache()->create_count());
4677 TestLoadTimingNetworkRequest(load_timing_info);
4679 // Read from the cache (0-9), write and read from cache (10 - 79).
4680 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4681 transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER;
4682 transaction.data = kFullRangeData;
4683 RunTransactionTestWithResponseAndGetTiming(
4684 cache.http_cache(), transaction, &headers, log.bound(),
4685 &load_timing_info);
4687 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4688 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4689 EXPECT_EQ(2, cache.disk_cache()->open_count());
4690 EXPECT_EQ(1, cache.disk_cache()->create_count());
4691 TestLoadTimingNetworkRequest(load_timing_info);
4693 RemoveMockTransaction(&transaction);
4696 // Tests that we can handle a regular request to a sparse entry, that results in
4697 // new content provided by the server (206).
4698 TEST(HttpCache, GET_Previous206_NewContent) {
4699 MockHttpCache cache;
4700 AddMockTransaction(&kRangeGET_TransactionOK);
4701 std::string headers;
4703 // Write to the cache (0-9).
4704 MockTransaction transaction(kRangeGET_TransactionOK);
4705 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
4706 transaction.data = "rg: 00-09 ";
4707 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4709 Verify206Response(headers, 0, 9);
4710 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4711 EXPECT_EQ(0, cache.disk_cache()->open_count());
4712 EXPECT_EQ(1, cache.disk_cache()->create_count());
4714 // Now we'll issue a request without any range that should result first in a
4715 // 206 (when revalidating), and then in a weird standard answer: the test
4716 // server will not modify the response so we'll get the default range... a
4717 // real server will answer with 200.
4718 MockTransaction transaction2(kRangeGET_TransactionOK);
4719 transaction2.request_headers = EXTRA_HEADER;
4720 transaction2.load_flags |= LOAD_VALIDATE_CACHE;
4721 transaction2.data = "Not a range";
4722 RangeTransactionServer handler;
4723 handler.set_modified(true);
4724 BoundTestNetLog log;
4725 LoadTimingInfo load_timing_info;
4726 RunTransactionTestWithResponseAndGetTiming(
4727 cache.http_cache(), transaction2, &headers, log.bound(),
4728 &load_timing_info);
4730 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4731 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4732 EXPECT_EQ(1, cache.disk_cache()->open_count());
4733 EXPECT_EQ(1, cache.disk_cache()->create_count());
4734 TestLoadTimingNetworkRequest(load_timing_info);
4736 // Verify that the previous request deleted the entry.
4737 RunTransactionTest(cache.http_cache(), transaction);
4738 EXPECT_EQ(2, cache.disk_cache()->create_count());
4740 RemoveMockTransaction(&transaction);
4743 // Tests that we can handle cached 206 responses that are not sparse.
4744 TEST(HttpCache, GET_Previous206_NotSparse) {
4745 MockHttpCache cache;
4747 // Create a disk cache entry that stores 206 headers while not being sparse.
4748 disk_cache::Entry* entry;
4749 ASSERT_TRUE(cache.CreateBackendEntry(kSimpleGET_Transaction.url, &entry,
4750 NULL));
4752 std::string raw_headers(kRangeGET_TransactionOK.status);
4753 raw_headers.append("\n");
4754 raw_headers.append(kRangeGET_TransactionOK.response_headers);
4755 raw_headers =
4756 HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size());
4758 HttpResponseInfo response;
4759 response.headers = new HttpResponseHeaders(raw_headers);
4760 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
4762 scoped_refptr<IOBuffer> buf(new IOBuffer(500));
4763 int len = static_cast<int>(base::strlcpy(buf->data(),
4764 kRangeGET_TransactionOK.data, 500));
4765 TestCompletionCallback cb;
4766 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
4767 EXPECT_EQ(len, cb.GetResult(rv));
4768 entry->Close();
4770 // Now see that we don't use the stored entry.
4771 std::string headers;
4772 BoundTestNetLog log;
4773 LoadTimingInfo load_timing_info;
4774 RunTransactionTestWithResponseAndGetTiming(
4775 cache.http_cache(), kSimpleGET_Transaction, &headers, log.bound(),
4776 &load_timing_info);
4778 // We are expecting a 200.
4779 std::string expected_headers(kSimpleGET_Transaction.status);
4780 expected_headers.append("\n");
4781 expected_headers.append(kSimpleGET_Transaction.response_headers);
4782 EXPECT_EQ(expected_headers, headers);
4783 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4784 EXPECT_EQ(1, cache.disk_cache()->open_count());
4785 EXPECT_EQ(2, cache.disk_cache()->create_count());
4786 TestLoadTimingNetworkRequest(load_timing_info);
4789 // Tests that we can handle cached 206 responses that are not sparse. This time
4790 // we issue a range request and expect to receive a range.
4791 TEST(HttpCache, RangeGET_Previous206_NotSparse_2) {
4792 MockHttpCache cache;
4793 AddMockTransaction(&kRangeGET_TransactionOK);
4795 // Create a disk cache entry that stores 206 headers while not being sparse.
4796 disk_cache::Entry* entry;
4797 ASSERT_TRUE(cache.CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
4798 NULL));
4800 std::string raw_headers(kRangeGET_TransactionOK.status);
4801 raw_headers.append("\n");
4802 raw_headers.append(kRangeGET_TransactionOK.response_headers);
4803 raw_headers =
4804 HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size());
4806 HttpResponseInfo response;
4807 response.headers = new HttpResponseHeaders(raw_headers);
4808 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
4810 scoped_refptr<IOBuffer> buf(new IOBuffer(500));
4811 int len = static_cast<int>(base::strlcpy(buf->data(),
4812 kRangeGET_TransactionOK.data, 500));
4813 TestCompletionCallback cb;
4814 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
4815 EXPECT_EQ(len, cb.GetResult(rv));
4816 entry->Close();
4818 // Now see that we don't use the stored entry.
4819 std::string headers;
4820 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4821 &headers);
4823 // We are expecting a 206.
4824 Verify206Response(headers, 40, 49);
4825 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4826 EXPECT_EQ(1, cache.disk_cache()->open_count());
4827 EXPECT_EQ(2, cache.disk_cache()->create_count());
4829 RemoveMockTransaction(&kRangeGET_TransactionOK);
4832 // Tests that we can handle cached 206 responses that can't be validated.
4833 TEST(HttpCache, GET_Previous206_NotValidation) {
4834 MockHttpCache cache;
4836 // Create a disk cache entry that stores 206 headers.
4837 disk_cache::Entry* entry;
4838 ASSERT_TRUE(cache.CreateBackendEntry(kSimpleGET_Transaction.url, &entry,
4839 NULL));
4841 // Make sure that the headers cannot be validated with the server.
4842 std::string raw_headers(kRangeGET_TransactionOK.status);
4843 raw_headers.append("\n");
4844 raw_headers.append("Content-Length: 80\n");
4845 raw_headers =
4846 HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size());
4848 HttpResponseInfo response;
4849 response.headers = new HttpResponseHeaders(raw_headers);
4850 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
4852 scoped_refptr<IOBuffer> buf(new IOBuffer(500));
4853 int len = static_cast<int>(base::strlcpy(buf->data(),
4854 kRangeGET_TransactionOK.data, 500));
4855 TestCompletionCallback cb;
4856 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
4857 EXPECT_EQ(len, cb.GetResult(rv));
4858 entry->Close();
4860 // Now see that we don't use the stored entry.
4861 std::string headers;
4862 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction,
4863 &headers);
4865 // We are expecting a 200.
4866 std::string expected_headers(kSimpleGET_Transaction.status);
4867 expected_headers.append("\n");
4868 expected_headers.append(kSimpleGET_Transaction.response_headers);
4869 EXPECT_EQ(expected_headers, headers);
4870 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4871 EXPECT_EQ(1, cache.disk_cache()->open_count());
4872 EXPECT_EQ(2, cache.disk_cache()->create_count());
4875 // Tests that we can handle range requests with cached 200 responses.
4876 TEST(HttpCache, RangeGET_Previous200) {
4877 MockHttpCache cache;
4879 // Store the whole thing with status 200.
4880 MockTransaction transaction(kTypicalGET_Transaction);
4881 transaction.url = kRangeGET_TransactionOK.url;
4882 transaction.data = kFullRangeData;
4883 AddMockTransaction(&transaction);
4884 RunTransactionTest(cache.http_cache(), transaction);
4885 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4886 EXPECT_EQ(0, cache.disk_cache()->open_count());
4887 EXPECT_EQ(1, cache.disk_cache()->create_count());
4889 RemoveMockTransaction(&transaction);
4890 AddMockTransaction(&kRangeGET_TransactionOK);
4892 // Now see that we use the stored entry.
4893 std::string headers;
4894 MockTransaction transaction2(kRangeGET_TransactionOK);
4895 RangeTransactionServer handler;
4896 handler.set_not_modified(true);
4897 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
4899 // We are expecting a 206.
4900 Verify206Response(headers, 40, 49);
4901 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4902 EXPECT_EQ(1, cache.disk_cache()->open_count());
4903 EXPECT_EQ(1, cache.disk_cache()->create_count());
4905 // The last transaction has finished so make sure the entry is deactivated.
4906 base::MessageLoop::current()->RunUntilIdle();
4908 // Make a request for an invalid range.
4909 MockTransaction transaction3(kRangeGET_TransactionOK);
4910 transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER;
4911 transaction3.data = transaction.data;
4912 transaction3.load_flags = LOAD_PREFERRING_CACHE;
4913 RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers);
4914 EXPECT_EQ(2, cache.disk_cache()->open_count());
4915 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 "));
4916 EXPECT_EQ(std::string::npos, headers.find("Content-Range:"));
4917 EXPECT_EQ(std::string::npos, headers.find("Content-Length: 80"));
4919 // Make sure the entry is deactivated.
4920 base::MessageLoop::current()->RunUntilIdle();
4922 // Even though the request was invalid, we should have the entry.
4923 RunTransactionTest(cache.http_cache(), transaction2);
4924 EXPECT_EQ(3, cache.disk_cache()->open_count());
4926 // Make sure the entry is deactivated.
4927 base::MessageLoop::current()->RunUntilIdle();
4929 // Now we should receive a range from the server and drop the stored entry.
4930 handler.set_not_modified(false);
4931 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
4932 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
4933 Verify206Response(headers, 40, 49);
4934 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4935 EXPECT_EQ(4, cache.disk_cache()->open_count());
4936 EXPECT_EQ(1, cache.disk_cache()->create_count());
4938 RunTransactionTest(cache.http_cache(), transaction2);
4939 EXPECT_EQ(2, cache.disk_cache()->create_count());
4941 RemoveMockTransaction(&kRangeGET_TransactionOK);
4944 // Tests that we can handle a 200 response when dealing with sparse entries.
4945 TEST(HttpCache, RangeRequestResultsIn200) {
4946 MockHttpCache cache;
4947 AddMockTransaction(&kRangeGET_TransactionOK);
4948 std::string headers;
4950 // Write to the cache (70-79).
4951 MockTransaction transaction(kRangeGET_TransactionOK);
4952 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
4953 transaction.data = "rg: 70-79 ";
4954 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4956 Verify206Response(headers, 70, 79);
4957 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4958 EXPECT_EQ(0, cache.disk_cache()->open_count());
4959 EXPECT_EQ(1, cache.disk_cache()->create_count());
4961 // Now we'll issue a request that results in a plain 200 response, but to
4962 // the to the same URL that we used to store sparse data, and making sure
4963 // that we ask for a range.
4964 RemoveMockTransaction(&kRangeGET_TransactionOK);
4965 MockTransaction transaction2(kSimpleGET_Transaction);
4966 transaction2.url = kRangeGET_TransactionOK.url;
4967 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
4968 AddMockTransaction(&transaction2);
4970 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
4972 std::string expected_headers(kSimpleGET_Transaction.status);
4973 expected_headers.append("\n");
4974 expected_headers.append(kSimpleGET_Transaction.response_headers);
4975 EXPECT_EQ(expected_headers, headers);
4976 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4977 EXPECT_EQ(1, cache.disk_cache()->open_count());
4978 EXPECT_EQ(1, cache.disk_cache()->create_count());
4980 RemoveMockTransaction(&transaction2);
4983 // Tests that a range request that falls outside of the size that we know about
4984 // only deletes the entry if the resource has indeed changed.
4985 TEST(HttpCache, RangeGET_MoreThanCurrentSize) {
4986 MockHttpCache cache;
4987 AddMockTransaction(&kRangeGET_TransactionOK);
4988 std::string headers;
4990 // Write to the cache (40-49).
4991 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4992 &headers);
4994 Verify206Response(headers, 40, 49);
4995 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4996 EXPECT_EQ(0, cache.disk_cache()->open_count());
4997 EXPECT_EQ(1, cache.disk_cache()->create_count());
4999 // A weird request should not delete this entry. Ask for bytes 120-.
5000 MockTransaction transaction(kRangeGET_TransactionOK);
5001 transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER;
5002 transaction.data = "";
5003 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5005 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
5006 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5007 EXPECT_EQ(1, cache.disk_cache()->open_count());
5008 EXPECT_EQ(1, cache.disk_cache()->create_count());
5010 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5011 EXPECT_EQ(2, cache.disk_cache()->open_count());
5012 EXPECT_EQ(1, cache.disk_cache()->create_count());
5014 RemoveMockTransaction(&kRangeGET_TransactionOK);
5017 // Tests that we don't delete a sparse entry when we cancel a request.
5018 TEST(HttpCache, RangeGET_Cancel) {
5019 MockHttpCache cache;
5020 AddMockTransaction(&kRangeGET_TransactionOK);
5022 MockHttpRequest request(kRangeGET_TransactionOK);
5024 Context* c = new Context();
5025 int rv = cache.CreateTransaction(&c->trans);
5026 ASSERT_EQ(OK, rv);
5028 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5029 if (rv == ERR_IO_PENDING)
5030 rv = c->callback.WaitForResult();
5032 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5033 EXPECT_EQ(0, cache.disk_cache()->open_count());
5034 EXPECT_EQ(1, cache.disk_cache()->create_count());
5036 // Make sure that the entry has some data stored.
5037 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10));
5038 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5039 if (rv == ERR_IO_PENDING)
5040 rv = c->callback.WaitForResult();
5041 EXPECT_EQ(buf->size(), rv);
5043 // Destroy the transaction.
5044 delete c;
5046 // Verify that the entry has not been deleted.
5047 disk_cache::Entry* entry;
5048 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5049 entry->Close();
5050 RemoveMockTransaction(&kRangeGET_TransactionOK);
5053 // Tests that we don't delete a sparse entry when we start a new request after
5054 // cancelling the previous one.
5055 TEST(HttpCache, RangeGET_Cancel2) {
5056 MockHttpCache cache;
5057 AddMockTransaction(&kRangeGET_TransactionOK);
5059 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5060 MockHttpRequest request(kRangeGET_TransactionOK);
5061 request.load_flags |= LOAD_VALIDATE_CACHE;
5063 Context* c = new Context();
5064 int rv = cache.CreateTransaction(&c->trans);
5065 ASSERT_EQ(OK, rv);
5067 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5068 if (rv == ERR_IO_PENDING)
5069 rv = c->callback.WaitForResult();
5071 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5072 EXPECT_EQ(1, cache.disk_cache()->open_count());
5073 EXPECT_EQ(1, cache.disk_cache()->create_count());
5075 // Make sure that we revalidate the entry and read from the cache (a single
5076 // read will return while waiting for the network).
5077 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5));
5078 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5079 EXPECT_EQ(5, c->callback.GetResult(rv));
5080 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5081 EXPECT_EQ(ERR_IO_PENDING, rv);
5083 // Destroy the transaction before completing the read.
5084 delete c;
5086 // We have the read and the delete (OnProcessPendingQueue) waiting on the
5087 // message loop. This means that a new transaction will just reuse the same
5088 // active entry (no open or create).
5090 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5092 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5093 EXPECT_EQ(1, cache.disk_cache()->open_count());
5094 EXPECT_EQ(1, cache.disk_cache()->create_count());
5095 RemoveMockTransaction(&kRangeGET_TransactionOK);
5098 // A slight variation of the previous test, this time we cancel two requests in
5099 // a row, making sure that the second is waiting for the entry to be ready.
5100 TEST(HttpCache, RangeGET_Cancel3) {
5101 MockHttpCache cache;
5102 AddMockTransaction(&kRangeGET_TransactionOK);
5104 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5105 MockHttpRequest request(kRangeGET_TransactionOK);
5106 request.load_flags |= LOAD_VALIDATE_CACHE;
5108 Context* c = new Context();
5109 int rv = cache.CreateTransaction(&c->trans);
5110 ASSERT_EQ(OK, rv);
5112 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5113 EXPECT_EQ(ERR_IO_PENDING, rv);
5114 rv = c->callback.WaitForResult();
5116 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5117 EXPECT_EQ(1, cache.disk_cache()->open_count());
5118 EXPECT_EQ(1, cache.disk_cache()->create_count());
5120 // Make sure that we revalidate the entry and read from the cache (a single
5121 // read will return while waiting for the network).
5122 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5));
5123 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5124 EXPECT_EQ(5, c->callback.GetResult(rv));
5125 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5126 EXPECT_EQ(ERR_IO_PENDING, rv);
5128 // Destroy the transaction before completing the read.
5129 delete c;
5131 // We have the read and the delete (OnProcessPendingQueue) waiting on the
5132 // message loop. This means that a new transaction will just reuse the same
5133 // active entry (no open or create).
5135 c = new Context();
5136 rv = cache.CreateTransaction(&c->trans);
5137 ASSERT_EQ(OK, rv);
5139 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5140 EXPECT_EQ(ERR_IO_PENDING, rv);
5142 MockDiskEntry::IgnoreCallbacks(true);
5143 base::MessageLoop::current()->RunUntilIdle();
5144 MockDiskEntry::IgnoreCallbacks(false);
5146 // The new transaction is waiting for the query range callback.
5147 delete c;
5149 // And we should not crash when the callback is delivered.
5150 base::MessageLoop::current()->RunUntilIdle();
5152 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5153 EXPECT_EQ(1, cache.disk_cache()->open_count());
5154 EXPECT_EQ(1, cache.disk_cache()->create_count());
5155 RemoveMockTransaction(&kRangeGET_TransactionOK);
5158 // Tests that an invalid range response results in no cached entry.
5159 TEST(HttpCache, RangeGET_InvalidResponse1) {
5160 MockHttpCache cache;
5161 std::string headers;
5163 MockTransaction transaction(kRangeGET_TransactionOK);
5164 transaction.handler = NULL;
5165 transaction.response_headers = "Content-Range: bytes 40-49/45\n"
5166 "Content-Length: 10\n";
5167 AddMockTransaction(&transaction);
5168 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5170 std::string expected(transaction.status);
5171 expected.append("\n");
5172 expected.append(transaction.response_headers);
5173 EXPECT_EQ(expected, headers);
5175 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5176 EXPECT_EQ(0, cache.disk_cache()->open_count());
5177 EXPECT_EQ(1, cache.disk_cache()->create_count());
5179 // Verify that we don't have a cached entry.
5180 disk_cache::Entry* entry;
5181 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5183 RemoveMockTransaction(&kRangeGET_TransactionOK);
5186 // Tests that we reject a range that doesn't match the content-length.
5187 TEST(HttpCache, RangeGET_InvalidResponse2) {
5188 MockHttpCache cache;
5189 std::string headers;
5191 MockTransaction transaction(kRangeGET_TransactionOK);
5192 transaction.handler = NULL;
5193 transaction.response_headers = "Content-Range: bytes 40-49/80\n"
5194 "Content-Length: 20\n";
5195 AddMockTransaction(&transaction);
5196 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5198 std::string expected(transaction.status);
5199 expected.append("\n");
5200 expected.append(transaction.response_headers);
5201 EXPECT_EQ(expected, headers);
5203 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5204 EXPECT_EQ(0, cache.disk_cache()->open_count());
5205 EXPECT_EQ(1, cache.disk_cache()->create_count());
5207 // Verify that we don't have a cached entry.
5208 disk_cache::Entry* entry;
5209 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5211 RemoveMockTransaction(&kRangeGET_TransactionOK);
5214 // Tests that if a server tells us conflicting information about a resource we
5215 // drop the entry.
5216 TEST(HttpCache, RangeGET_InvalidResponse3) {
5217 MockHttpCache cache;
5218 std::string headers;
5220 MockTransaction transaction(kRangeGET_TransactionOK);
5221 transaction.handler = NULL;
5222 transaction.request_headers = "Range: bytes = 50-59\r\n" EXTRA_HEADER;
5223 std::string response_headers(transaction.response_headers);
5224 response_headers.append("Content-Range: bytes 50-59/160\n");
5225 transaction.response_headers = response_headers.c_str();
5226 AddMockTransaction(&transaction);
5227 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5229 Verify206Response(headers, 50, 59);
5230 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5231 EXPECT_EQ(0, cache.disk_cache()->open_count());
5232 EXPECT_EQ(1, cache.disk_cache()->create_count());
5234 RemoveMockTransaction(&transaction);
5235 AddMockTransaction(&kRangeGET_TransactionOK);
5237 // This transaction will report a resource size of 80 bytes, and we think it's
5238 // 160 so we should ignore the response.
5239 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
5240 &headers);
5242 Verify206Response(headers, 40, 49);
5243 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5244 EXPECT_EQ(1, cache.disk_cache()->open_count());
5245 EXPECT_EQ(1, cache.disk_cache()->create_count());
5247 // Verify that the entry is gone.
5248 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5249 EXPECT_EQ(1, cache.disk_cache()->open_count());
5250 EXPECT_EQ(2, cache.disk_cache()->create_count());
5251 RemoveMockTransaction(&kRangeGET_TransactionOK);
5254 // Tests that we handle large range values properly.
5255 TEST(HttpCache, RangeGET_LargeValues) {
5256 // We need a real sparse cache for this test.
5257 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
5258 std::string headers;
5260 MockTransaction transaction(kRangeGET_TransactionOK);
5261 transaction.handler = NULL;
5262 transaction.request_headers = "Range: bytes = 4294967288-4294967297\r\n"
5263 EXTRA_HEADER;
5264 transaction.response_headers =
5265 "ETag: \"foo\"\n"
5266 "Content-Range: bytes 4294967288-4294967297/4294967299\n"
5267 "Content-Length: 10\n";
5268 AddMockTransaction(&transaction);
5269 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5271 std::string expected(transaction.status);
5272 expected.append("\n");
5273 expected.append(transaction.response_headers);
5274 EXPECT_EQ(expected, headers);
5276 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5278 // Verify that we have a cached entry.
5279 disk_cache::Entry* en;
5280 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &en));
5281 en->Close();
5283 RemoveMockTransaction(&kRangeGET_TransactionOK);
5286 // Tests that we don't crash with a range request if the disk cache was not
5287 // initialized properly.
5288 TEST(HttpCache, RangeGET_NoDiskCache) {
5289 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
5290 factory->set_fail(true);
5291 factory->FinishCreation(); // We'll complete synchronously.
5292 MockHttpCache cache(factory);
5294 AddMockTransaction(&kRangeGET_TransactionOK);
5296 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5297 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5299 RemoveMockTransaction(&kRangeGET_TransactionOK);
5302 // Tests that we handle byte range requests that skip the cache.
5303 TEST(HttpCache, RangeHEAD) {
5304 MockHttpCache cache;
5305 AddMockTransaction(&kRangeGET_TransactionOK);
5307 MockTransaction transaction(kRangeGET_TransactionOK);
5308 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
5309 transaction.method = "HEAD";
5310 transaction.data = "rg: 70-79 ";
5312 std::string headers;
5313 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5315 Verify206Response(headers, 70, 79);
5316 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5317 EXPECT_EQ(0, cache.disk_cache()->open_count());
5318 EXPECT_EQ(0, cache.disk_cache()->create_count());
5320 RemoveMockTransaction(&kRangeGET_TransactionOK);
5323 // Tests that we don't crash when after reading from the cache we issue a
5324 // request for the next range and the server gives us a 200 synchronously.
5325 TEST(HttpCache, RangeGET_FastFlakyServer) {
5326 MockHttpCache cache;
5328 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
5329 transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER;
5330 transaction.test_mode = TEST_MODE_SYNC_NET_START;
5331 transaction.load_flags |= LOAD_VALIDATE_CACHE;
5333 // Write to the cache.
5334 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5336 // And now read from the cache and the network.
5337 RangeTransactionServer handler;
5338 handler.set_bad_200(true);
5339 transaction.data = "Not a range";
5340 BoundTestNetLog log;
5341 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
5343 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5344 EXPECT_EQ(1, cache.disk_cache()->open_count());
5345 EXPECT_EQ(1, cache.disk_cache()->create_count());
5346 EXPECT_TRUE(LogContainsEventType(
5347 log, NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST));
5350 // Tests that when the server gives us less data than expected, we don't keep
5351 // asking for more data.
5352 TEST(HttpCache, RangeGET_FastFlakyServer2) {
5353 MockHttpCache cache;
5355 // First, check with an empty cache (WRITE mode).
5356 MockTransaction transaction(kRangeGET_TransactionOK);
5357 transaction.request_headers = "Range: bytes = 40-49\r\n" EXTRA_HEADER;
5358 transaction.data = "rg: 40-"; // Less than expected.
5359 transaction.handler = NULL;
5360 std::string headers(transaction.response_headers);
5361 headers.append("Content-Range: bytes 40-49/80\n");
5362 transaction.response_headers = headers.c_str();
5364 AddMockTransaction(&transaction);
5366 // Write to the cache.
5367 RunTransactionTest(cache.http_cache(), transaction);
5369 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5370 EXPECT_EQ(0, cache.disk_cache()->open_count());
5371 EXPECT_EQ(1, cache.disk_cache()->create_count());
5373 // Now verify that even in READ_WRITE mode, we forward the bad response to
5374 // the caller.
5375 transaction.request_headers = "Range: bytes = 60-69\r\n" EXTRA_HEADER;
5376 transaction.data = "rg: 60-"; // Less than expected.
5377 headers = kRangeGET_TransactionOK.response_headers;
5378 headers.append("Content-Range: bytes 60-69/80\n");
5379 transaction.response_headers = headers.c_str();
5381 RunTransactionTest(cache.http_cache(), transaction);
5383 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5384 EXPECT_EQ(1, cache.disk_cache()->open_count());
5385 EXPECT_EQ(1, cache.disk_cache()->create_count());
5387 RemoveMockTransaction(&transaction);
5390 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
5391 // This test hits a NOTREACHED so it is a release mode only test.
5392 TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) {
5393 MockHttpCache cache;
5394 AddMockTransaction(&kRangeGET_TransactionOK);
5396 // Write to the cache (40-49).
5397 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5398 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5399 EXPECT_EQ(0, cache.disk_cache()->open_count());
5400 EXPECT_EQ(1, cache.disk_cache()->create_count());
5402 // Force this transaction to read from the cache.
5403 MockTransaction transaction(kRangeGET_TransactionOK);
5404 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
5406 MockHttpRequest request(transaction);
5407 TestCompletionCallback callback;
5409 scoped_ptr<HttpTransaction> trans;
5410 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
5411 EXPECT_EQ(OK, rv);
5412 ASSERT_TRUE(trans.get());
5414 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5415 if (rv == ERR_IO_PENDING)
5416 rv = callback.WaitForResult();
5417 ASSERT_EQ(ERR_CACHE_MISS, rv);
5419 trans.reset();
5421 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5422 EXPECT_EQ(1, cache.disk_cache()->open_count());
5423 EXPECT_EQ(1, cache.disk_cache()->create_count());
5425 RemoveMockTransaction(&kRangeGET_TransactionOK);
5427 #endif
5429 // Tests the handling of the "truncation" flag.
5430 TEST(HttpCache, WriteResponseInfo_Truncated) {
5431 MockHttpCache cache;
5432 disk_cache::Entry* entry;
5433 ASSERT_TRUE(cache.CreateBackendEntry("http://www.google.com", &entry,
5434 NULL));
5436 std::string headers("HTTP/1.1 200 OK");
5437 headers = HttpUtil::AssembleRawHeaders(headers.data(), headers.size());
5438 HttpResponseInfo response;
5439 response.headers = new HttpResponseHeaders(headers);
5441 // Set the last argument for this to be an incomplete request.
5442 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
5443 bool truncated = false;
5444 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5445 EXPECT_TRUE(truncated);
5447 // And now test the opposite case.
5448 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
5449 truncated = true;
5450 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5451 EXPECT_FALSE(truncated);
5452 entry->Close();
5455 // Tests basic pickling/unpickling of HttpResponseInfo.
5456 TEST(HttpCache, PersistHttpResponseInfo) {
5457 // Set some fields (add more if needed.)
5458 HttpResponseInfo response1;
5459 response1.was_cached = false;
5460 response1.socket_address = HostPortPair("1.2.3.4", 80);
5461 response1.headers = new HttpResponseHeaders("HTTP/1.1 200 OK");
5463 // Pickle.
5464 Pickle pickle;
5465 response1.Persist(&pickle, false, false);
5467 // Unpickle.
5468 HttpResponseInfo response2;
5469 bool response_truncated;
5470 EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated));
5471 EXPECT_FALSE(response_truncated);
5473 // Verify fields.
5474 EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag.
5475 EXPECT_EQ("1.2.3.4", response2.socket_address.host());
5476 EXPECT_EQ(80, response2.socket_address.port());
5477 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5480 // Tests that we delete an entry when the request is cancelled before starting
5481 // to read from the network.
5482 TEST(HttpCache, DoomOnDestruction) {
5483 MockHttpCache cache;
5485 MockHttpRequest request(kSimpleGET_Transaction);
5487 Context* c = new Context();
5488 int rv = cache.CreateTransaction(&c->trans);
5489 ASSERT_EQ(OK, rv);
5491 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5492 if (rv == ERR_IO_PENDING)
5493 c->result = c->callback.WaitForResult();
5495 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5496 EXPECT_EQ(0, cache.disk_cache()->open_count());
5497 EXPECT_EQ(1, cache.disk_cache()->create_count());
5499 // Destroy the transaction. We only have the headers so we should delete this
5500 // entry.
5501 delete c;
5503 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5505 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5506 EXPECT_EQ(0, cache.disk_cache()->open_count());
5507 EXPECT_EQ(2, cache.disk_cache()->create_count());
5510 // Tests that we delete an entry when the request is cancelled if the response
5511 // does not have content-length and strong validators.
5512 TEST(HttpCache, DoomOnDestruction2) {
5513 MockHttpCache cache;
5515 MockHttpRequest request(kSimpleGET_Transaction);
5517 Context* c = new Context();
5518 int rv = cache.CreateTransaction(&c->trans);
5519 ASSERT_EQ(OK, rv);
5521 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5522 if (rv == ERR_IO_PENDING)
5523 rv = c->callback.WaitForResult();
5525 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5526 EXPECT_EQ(0, cache.disk_cache()->open_count());
5527 EXPECT_EQ(1, cache.disk_cache()->create_count());
5529 // Make sure that the entry has some data stored.
5530 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10));
5531 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5532 if (rv == ERR_IO_PENDING)
5533 rv = c->callback.WaitForResult();
5534 EXPECT_EQ(buf->size(), rv);
5536 // Destroy the transaction.
5537 delete c;
5539 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5541 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5542 EXPECT_EQ(0, cache.disk_cache()->open_count());
5543 EXPECT_EQ(2, cache.disk_cache()->create_count());
5546 // Tests that we delete an entry when the request is cancelled if the response
5547 // has an "Accept-Ranges: none" header.
5548 TEST(HttpCache, DoomOnDestruction3) {
5549 MockHttpCache cache;
5551 MockTransaction transaction(kSimpleGET_Transaction);
5552 transaction.response_headers =
5553 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
5554 "Content-Length: 22\n"
5555 "Accept-Ranges: none\n"
5556 "Etag: \"foopy\"\n";
5557 AddMockTransaction(&transaction);
5558 MockHttpRequest request(transaction);
5560 Context* c = new Context();
5561 int rv = cache.CreateTransaction(&c->trans);
5562 ASSERT_EQ(OK, rv);
5564 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5565 if (rv == ERR_IO_PENDING)
5566 rv = c->callback.WaitForResult();
5568 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5569 EXPECT_EQ(0, cache.disk_cache()->open_count());
5570 EXPECT_EQ(1, cache.disk_cache()->create_count());
5572 // Make sure that the entry has some data stored.
5573 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10));
5574 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5575 if (rv == ERR_IO_PENDING)
5576 rv = c->callback.WaitForResult();
5577 EXPECT_EQ(buf->size(), rv);
5579 // Destroy the transaction.
5580 delete c;
5582 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5584 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5585 EXPECT_EQ(0, cache.disk_cache()->open_count());
5586 EXPECT_EQ(2, cache.disk_cache()->create_count());
5588 RemoveMockTransaction(&transaction);
5591 // Tests that we mark an entry as incomplete when the request is cancelled.
5592 TEST(HttpCache, SetTruncatedFlag) {
5593 MockHttpCache cache;
5595 MockTransaction transaction(kSimpleGET_Transaction);
5596 transaction.response_headers =
5597 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
5598 "Content-Length: 22\n"
5599 "Etag: \"foopy\"\n";
5600 AddMockTransaction(&transaction);
5601 MockHttpRequest request(transaction);
5603 scoped_ptr<Context> c(new Context());
5605 int rv = cache.CreateTransaction(&c->trans);
5606 ASSERT_EQ(OK, rv);
5608 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5609 if (rv == ERR_IO_PENDING)
5610 rv = c->callback.WaitForResult();
5612 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5613 EXPECT_EQ(0, cache.disk_cache()->open_count());
5614 EXPECT_EQ(1, cache.disk_cache()->create_count());
5616 // Make sure that the entry has some data stored.
5617 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10));
5618 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5619 if (rv == ERR_IO_PENDING)
5620 rv = c->callback.WaitForResult();
5621 EXPECT_EQ(buf->size(), rv);
5623 // We want to cancel the request when the transaction is busy.
5624 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5625 EXPECT_EQ(ERR_IO_PENDING, rv);
5626 EXPECT_FALSE(c->callback.have_result());
5628 MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL);
5630 // Destroy the transaction.
5631 c->trans.reset();
5632 MockHttpCache::SetTestMode(0);
5635 // Make sure that we don't invoke the callback. We may have an issue if the
5636 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
5637 // could end up with the transaction being deleted twice if we send any
5638 // notification from the transaction destructor (see http://crbug.com/31723).
5639 EXPECT_FALSE(c->callback.have_result());
5641 // Verify that the entry is marked as incomplete.
5642 disk_cache::Entry* entry;
5643 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
5644 HttpResponseInfo response;
5645 bool truncated = false;
5646 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5647 EXPECT_TRUE(truncated);
5648 entry->Close();
5650 RemoveMockTransaction(&transaction);
5653 // Tests that we don't mark an entry as truncated when we read everything.
5654 TEST(HttpCache, DontSetTruncatedFlag) {
5655 MockHttpCache cache;
5657 MockTransaction transaction(kSimpleGET_Transaction);
5658 transaction.response_headers =
5659 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
5660 "Content-Length: 22\n"
5661 "Etag: \"foopy\"\n";
5662 AddMockTransaction(&transaction);
5663 MockHttpRequest request(transaction);
5665 scoped_ptr<Context> c(new Context());
5666 int rv = cache.CreateTransaction(&c->trans);
5667 ASSERT_EQ(OK, rv);
5669 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5670 EXPECT_EQ(OK, c->callback.GetResult(rv));
5672 // Read everything.
5673 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(22));
5674 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5675 EXPECT_EQ(buf->size(), c->callback.GetResult(rv));
5677 // Destroy the transaction.
5678 c->trans.reset();
5680 // Verify that the entry is not marked as truncated.
5681 disk_cache::Entry* entry;
5682 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
5683 HttpResponseInfo response;
5684 bool truncated = true;
5685 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5686 EXPECT_FALSE(truncated);
5687 entry->Close();
5689 RemoveMockTransaction(&transaction);
5692 // Tests that we can continue with a request that was interrupted.
5693 TEST(HttpCache, GET_IncompleteResource) {
5694 MockHttpCache cache;
5695 AddMockTransaction(&kRangeGET_TransactionOK);
5697 std::string raw_headers("HTTP/1.1 200 OK\n"
5698 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5699 "ETag: \"foo\"\n"
5700 "Accept-Ranges: bytes\n"
5701 "Content-Length: 80\n");
5702 CreateTruncatedEntry(raw_headers, &cache);
5704 // Now make a regular request.
5705 std::string headers;
5706 MockTransaction transaction(kRangeGET_TransactionOK);
5707 transaction.request_headers = EXTRA_HEADER;
5708 transaction.data = kFullRangeData;
5709 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5711 // We update the headers with the ones received while revalidating.
5712 std::string expected_headers(
5713 "HTTP/1.1 200 OK\n"
5714 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5715 "Accept-Ranges: bytes\n"
5716 "ETag: \"foo\"\n"
5717 "Content-Length: 80\n");
5719 EXPECT_EQ(expected_headers, headers);
5720 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5721 EXPECT_EQ(1, cache.disk_cache()->open_count());
5722 EXPECT_EQ(1, cache.disk_cache()->create_count());
5724 // Verify that the disk entry was updated.
5725 disk_cache::Entry* entry;
5726 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5727 EXPECT_EQ(80, entry->GetDataSize(1));
5728 bool truncated = true;
5729 HttpResponseInfo response;
5730 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5731 EXPECT_FALSE(truncated);
5732 entry->Close();
5734 RemoveMockTransaction(&kRangeGET_TransactionOK);
5737 // Tests the handling of no-store when revalidating a truncated entry.
5738 TEST(HttpCache, GET_IncompleteResource_NoStore) {
5739 MockHttpCache cache;
5740 AddMockTransaction(&kRangeGET_TransactionOK);
5742 std::string raw_headers("HTTP/1.1 200 OK\n"
5743 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5744 "ETag: \"foo\"\n"
5745 "Accept-Ranges: bytes\n"
5746 "Content-Length: 80\n");
5747 CreateTruncatedEntry(raw_headers, &cache);
5748 RemoveMockTransaction(&kRangeGET_TransactionOK);
5750 // Now make a regular request.
5751 MockTransaction transaction(kRangeGET_TransactionOK);
5752 transaction.request_headers = EXTRA_HEADER;
5753 std::string response_headers(transaction.response_headers);
5754 response_headers += ("Cache-Control: no-store\n");
5755 transaction.response_headers = response_headers.c_str();
5756 transaction.data = kFullRangeData;
5757 AddMockTransaction(&transaction);
5759 std::string headers;
5760 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5762 // We update the headers with the ones received while revalidating.
5763 std::string expected_headers(
5764 "HTTP/1.1 200 OK\n"
5765 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5766 "Accept-Ranges: bytes\n"
5767 "Cache-Control: no-store\n"
5768 "ETag: \"foo\"\n"
5769 "Content-Length: 80\n");
5771 EXPECT_EQ(expected_headers, headers);
5772 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5773 EXPECT_EQ(1, cache.disk_cache()->open_count());
5774 EXPECT_EQ(1, cache.disk_cache()->create_count());
5776 // Verify that the disk entry was deleted.
5777 disk_cache::Entry* entry;
5778 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5779 RemoveMockTransaction(&transaction);
5782 // Tests cancelling a request after the server sent no-store.
5783 TEST(HttpCache, GET_IncompleteResource_Cancel) {
5784 MockHttpCache cache;
5785 AddMockTransaction(&kRangeGET_TransactionOK);
5787 std::string raw_headers("HTTP/1.1 200 OK\n"
5788 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5789 "ETag: \"foo\"\n"
5790 "Accept-Ranges: bytes\n"
5791 "Content-Length: 80\n");
5792 CreateTruncatedEntry(raw_headers, &cache);
5793 RemoveMockTransaction(&kRangeGET_TransactionOK);
5795 // Now make a regular request.
5796 MockTransaction transaction(kRangeGET_TransactionOK);
5797 transaction.request_headers = EXTRA_HEADER;
5798 std::string response_headers(transaction.response_headers);
5799 response_headers += ("Cache-Control: no-store\n");
5800 transaction.response_headers = response_headers.c_str();
5801 transaction.data = kFullRangeData;
5802 AddMockTransaction(&transaction);
5804 MockHttpRequest request(transaction);
5805 Context* c = new Context();
5807 int rv = cache.CreateTransaction(&c->trans);
5808 ASSERT_EQ(OK, rv);
5810 // Queue another request to this transaction. We have to start this request
5811 // before the first one gets the response from the server and dooms the entry,
5812 // otherwise it will just create a new entry without being queued to the first
5813 // request.
5814 Context* pending = new Context();
5815 ASSERT_EQ(OK, cache.CreateTransaction(&pending->trans));
5817 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5818 EXPECT_EQ(ERR_IO_PENDING,
5819 pending->trans->Start(&request, pending->callback.callback(),
5820 BoundNetLog()));
5821 EXPECT_EQ(OK, c->callback.GetResult(rv));
5823 // Make sure that the entry has some data stored.
5824 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5));
5825 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5826 EXPECT_EQ(5, c->callback.GetResult(rv));
5828 // Cancel the requests.
5829 delete c;
5830 delete pending;
5832 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5833 EXPECT_EQ(1, cache.disk_cache()->open_count());
5834 EXPECT_EQ(2, cache.disk_cache()->create_count());
5836 base::MessageLoop::current()->RunUntilIdle();
5837 RemoveMockTransaction(&transaction);
5840 // Tests that we delete truncated entries if the server changes its mind midway.
5841 TEST(HttpCache, GET_IncompleteResource2) {
5842 MockHttpCache cache;
5843 AddMockTransaction(&kRangeGET_TransactionOK);
5845 // Content-length will be intentionally bad.
5846 std::string raw_headers("HTTP/1.1 200 OK\n"
5847 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5848 "ETag: \"foo\"\n"
5849 "Accept-Ranges: bytes\n"
5850 "Content-Length: 50\n");
5851 CreateTruncatedEntry(raw_headers, &cache);
5853 // Now make a regular request. We expect the code to fail the validation and
5854 // retry the request without using byte ranges.
5855 std::string headers;
5856 MockTransaction transaction(kRangeGET_TransactionOK);
5857 transaction.request_headers = EXTRA_HEADER;
5858 transaction.data = "Not a range";
5859 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5861 // The server will return 200 instead of a byte range.
5862 std::string expected_headers(
5863 "HTTP/1.1 200 OK\n"
5864 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
5866 EXPECT_EQ(expected_headers, headers);
5867 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5868 EXPECT_EQ(1, cache.disk_cache()->open_count());
5869 EXPECT_EQ(1, cache.disk_cache()->create_count());
5871 // Verify that the disk entry was deleted.
5872 disk_cache::Entry* entry;
5873 ASSERT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5874 RemoveMockTransaction(&kRangeGET_TransactionOK);
5877 // Tests that we always validate a truncated request.
5878 TEST(HttpCache, GET_IncompleteResource3) {
5879 MockHttpCache cache;
5880 AddMockTransaction(&kRangeGET_TransactionOK);
5882 // This should not require validation for 10 hours.
5883 std::string raw_headers("HTTP/1.1 200 OK\n"
5884 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
5885 "ETag: \"foo\"\n"
5886 "Cache-Control: max-age= 36000\n"
5887 "Accept-Ranges: bytes\n"
5888 "Content-Length: 80\n");
5889 CreateTruncatedEntry(raw_headers, &cache);
5891 // Now make a regular request.
5892 std::string headers;
5893 MockTransaction transaction(kRangeGET_TransactionOK);
5894 transaction.request_headers = EXTRA_HEADER;
5895 transaction.data = kFullRangeData;
5897 scoped_ptr<Context> c(new Context);
5898 int rv = cache.CreateTransaction(&c->trans);
5899 ASSERT_EQ(OK, rv);
5901 MockHttpRequest request(transaction);
5902 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5903 EXPECT_EQ(OK, c->callback.GetResult(rv));
5905 // We should have checked with the server before finishing Start().
5906 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5907 EXPECT_EQ(1, cache.disk_cache()->open_count());
5908 EXPECT_EQ(1, cache.disk_cache()->create_count());
5910 RemoveMockTransaction(&kRangeGET_TransactionOK);
5913 // Tests that we handle 401s for truncated resources.
5914 TEST(HttpCache, GET_IncompleteResourceWithAuth) {
5915 MockHttpCache cache;
5916 AddMockTransaction(&kRangeGET_TransactionOK);
5918 std::string raw_headers("HTTP/1.1 200 OK\n"
5919 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5920 "ETag: \"foo\"\n"
5921 "Accept-Ranges: bytes\n"
5922 "Content-Length: 80\n");
5923 CreateTruncatedEntry(raw_headers, &cache);
5925 // Now make a regular request.
5926 MockTransaction transaction(kRangeGET_TransactionOK);
5927 transaction.request_headers = "X-Require-Mock-Auth: dummy\r\n"
5928 EXTRA_HEADER;
5929 transaction.data = kFullRangeData;
5930 RangeTransactionServer handler;
5932 scoped_ptr<Context> c(new Context);
5933 int rv = cache.CreateTransaction(&c->trans);
5934 ASSERT_EQ(OK, rv);
5936 MockHttpRequest request(transaction);
5937 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5938 EXPECT_EQ(OK, c->callback.GetResult(rv));
5940 const HttpResponseInfo* response = c->trans->GetResponseInfo();
5941 ASSERT_TRUE(response);
5942 ASSERT_EQ(401, response->headers->response_code());
5943 rv = c->trans->RestartWithAuth(AuthCredentials(), c->callback.callback());
5944 EXPECT_EQ(OK, c->callback.GetResult(rv));
5945 response = c->trans->GetResponseInfo();
5946 ASSERT_TRUE(response);
5947 ASSERT_EQ(200, response->headers->response_code());
5949 ReadAndVerifyTransaction(c->trans.get(), transaction);
5950 c.reset(); // The destructor could delete the entry.
5951 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5953 // Verify that the entry was not deleted.
5954 disk_cache::Entry* entry;
5955 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5956 entry->Close();
5958 RemoveMockTransaction(&kRangeGET_TransactionOK);
5961 // Tests that we cache a 200 response to the validation request.
5962 TEST(HttpCache, GET_IncompleteResource4) {
5963 MockHttpCache cache;
5964 AddMockTransaction(&kRangeGET_TransactionOK);
5966 std::string raw_headers("HTTP/1.1 200 OK\n"
5967 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
5968 "ETag: \"foo\"\n"
5969 "Accept-Ranges: bytes\n"
5970 "Content-Length: 80\n");
5971 CreateTruncatedEntry(raw_headers, &cache);
5973 // Now make a regular request.
5974 std::string headers;
5975 MockTransaction transaction(kRangeGET_TransactionOK);
5976 transaction.request_headers = EXTRA_HEADER;
5977 transaction.data = "Not a range";
5978 RangeTransactionServer handler;
5979 handler.set_bad_200(true);
5980 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5982 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5983 EXPECT_EQ(1, cache.disk_cache()->open_count());
5984 EXPECT_EQ(1, cache.disk_cache()->create_count());
5986 // Verify that the disk entry was updated.
5987 disk_cache::Entry* entry;
5988 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5989 EXPECT_EQ(11, entry->GetDataSize(1));
5990 bool truncated = true;
5991 HttpResponseInfo response;
5992 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5993 EXPECT_FALSE(truncated);
5994 entry->Close();
5996 RemoveMockTransaction(&kRangeGET_TransactionOK);
5999 // Tests that when we cancel a request that was interrupted, we mark it again
6000 // as truncated.
6001 TEST(HttpCache, GET_CancelIncompleteResource) {
6002 MockHttpCache cache;
6003 AddMockTransaction(&kRangeGET_TransactionOK);
6005 std::string raw_headers("HTTP/1.1 200 OK\n"
6006 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
6007 "ETag: \"foo\"\n"
6008 "Accept-Ranges: bytes\n"
6009 "Content-Length: 80\n");
6010 CreateTruncatedEntry(raw_headers, &cache);
6012 // Now make a regular request.
6013 MockTransaction transaction(kRangeGET_TransactionOK);
6014 transaction.request_headers = EXTRA_HEADER;
6016 MockHttpRequest request(transaction);
6017 Context* c = new Context();
6018 int rv = cache.CreateTransaction(&c->trans);
6019 ASSERT_EQ(OK, rv);
6021 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
6022 EXPECT_EQ(OK, c->callback.GetResult(rv));
6024 // Read 20 bytes from the cache, and 10 from the net.
6025 scoped_refptr<IOBuffer> buf(new IOBuffer(100));
6026 rv = c->trans->Read(buf.get(), 20, c->callback.callback());
6027 EXPECT_EQ(20, c->callback.GetResult(rv));
6028 rv = c->trans->Read(buf.get(), 10, c->callback.callback());
6029 EXPECT_EQ(10, c->callback.GetResult(rv));
6031 // At this point, we are already reading so canceling the request should leave
6032 // a truncated one.
6033 delete c;
6035 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6036 EXPECT_EQ(1, cache.disk_cache()->open_count());
6037 EXPECT_EQ(1, cache.disk_cache()->create_count());
6039 // Verify that the disk entry was updated: now we have 30 bytes.
6040 disk_cache::Entry* entry;
6041 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
6042 EXPECT_EQ(30, entry->GetDataSize(1));
6043 bool truncated = false;
6044 HttpResponseInfo response;
6045 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6046 EXPECT_TRUE(truncated);
6047 entry->Close();
6048 RemoveMockTransaction(&kRangeGET_TransactionOK);
6051 // Tests that we can handle range requests when we have a truncated entry.
6052 TEST(HttpCache, RangeGET_IncompleteResource) {
6053 MockHttpCache cache;
6054 AddMockTransaction(&kRangeGET_TransactionOK);
6056 // Content-length will be intentionally bogus.
6057 std::string raw_headers("HTTP/1.1 200 OK\n"
6058 "Last-Modified: something\n"
6059 "ETag: \"foo\"\n"
6060 "Accept-Ranges: bytes\n"
6061 "Content-Length: 10\n");
6062 CreateTruncatedEntry(raw_headers, &cache);
6064 // Now make a range request.
6065 std::string headers;
6066 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
6067 &headers);
6069 Verify206Response(headers, 40, 49);
6070 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6071 EXPECT_EQ(1, cache.disk_cache()->open_count());
6072 EXPECT_EQ(2, cache.disk_cache()->create_count());
6074 RemoveMockTransaction(&kRangeGET_TransactionOK);
6077 TEST(HttpCache, SyncRead) {
6078 MockHttpCache cache;
6080 // This test ensures that a read that completes synchronously does not cause
6081 // any problems.
6083 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6084 transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START |
6085 TEST_MODE_SYNC_CACHE_READ |
6086 TEST_MODE_SYNC_CACHE_WRITE);
6088 MockHttpRequest r1(transaction),
6089 r2(transaction),
6090 r3(transaction);
6092 TestTransactionConsumer c1(DEFAULT_PRIORITY, cache.http_cache()),
6093 c2(DEFAULT_PRIORITY, cache.http_cache()),
6094 c3(DEFAULT_PRIORITY, cache.http_cache());
6096 c1.Start(&r1, BoundNetLog());
6098 r2.load_flags |= LOAD_ONLY_FROM_CACHE;
6099 c2.Start(&r2, BoundNetLog());
6101 r3.load_flags |= LOAD_ONLY_FROM_CACHE;
6102 c3.Start(&r3, BoundNetLog());
6104 base::MessageLoop::current()->Run();
6106 EXPECT_TRUE(c1.is_done());
6107 EXPECT_TRUE(c2.is_done());
6108 EXPECT_TRUE(c3.is_done());
6110 EXPECT_EQ(OK, c1.error());
6111 EXPECT_EQ(OK, c2.error());
6112 EXPECT_EQ(OK, c3.error());
6115 TEST(HttpCache, ValidationResultsIn200) {
6116 MockHttpCache cache;
6118 // This test ensures that a conditional request, which results in a 200
6119 // instead of a 304, properly truncates the existing response data.
6121 // write to the cache
6122 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
6124 // force this transaction to validate the cache
6125 MockTransaction transaction(kETagGET_Transaction);
6126 transaction.load_flags |= LOAD_VALIDATE_CACHE;
6127 RunTransactionTest(cache.http_cache(), transaction);
6129 // read from the cache
6130 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
6133 TEST(HttpCache, CachedRedirect) {
6134 MockHttpCache cache;
6136 ScopedMockTransaction kTestTransaction(kSimpleGET_Transaction);
6137 kTestTransaction.status = "HTTP/1.1 301 Moved Permanently";
6138 kTestTransaction.response_headers = "Location: http://www.bar.com/\n";
6140 MockHttpRequest request(kTestTransaction);
6141 TestCompletionCallback callback;
6143 // Write to the cache.
6145 scoped_ptr<HttpTransaction> trans;
6146 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6148 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6149 if (rv == ERR_IO_PENDING)
6150 rv = callback.WaitForResult();
6151 ASSERT_EQ(OK, rv);
6153 const HttpResponseInfo* info = trans->GetResponseInfo();
6154 ASSERT_TRUE(info);
6156 EXPECT_EQ(info->headers->response_code(), 301);
6158 std::string location;
6159 info->headers->EnumerateHeader(NULL, "Location", &location);
6160 EXPECT_EQ(location, "http://www.bar.com/");
6162 // Mark the transaction as completed so it is cached.
6163 trans->DoneReading();
6165 // Destroy transaction when going out of scope. We have not actually
6166 // read the response body -- want to test that it is still getting cached.
6168 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6169 EXPECT_EQ(0, cache.disk_cache()->open_count());
6170 EXPECT_EQ(1, cache.disk_cache()->create_count());
6172 // Active entries in the cache are not retired synchronously. Make
6173 // sure the next run hits the MockHttpCache and open_count is
6174 // correct.
6175 base::MessageLoop::current()->RunUntilIdle();
6177 // Read from the cache.
6179 scoped_ptr<HttpTransaction> trans;
6180 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6182 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6183 if (rv == ERR_IO_PENDING)
6184 rv = callback.WaitForResult();
6185 ASSERT_EQ(OK, rv);
6187 const HttpResponseInfo* info = trans->GetResponseInfo();
6188 ASSERT_TRUE(info);
6190 EXPECT_EQ(info->headers->response_code(), 301);
6192 std::string location;
6193 info->headers->EnumerateHeader(NULL, "Location", &location);
6194 EXPECT_EQ(location, "http://www.bar.com/");
6196 // Mark the transaction as completed so it is cached.
6197 trans->DoneReading();
6199 // Destroy transaction when going out of scope. We have not actually
6200 // read the response body -- want to test that it is still getting cached.
6202 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6203 EXPECT_EQ(1, cache.disk_cache()->open_count());
6204 EXPECT_EQ(1, cache.disk_cache()->create_count());
6207 // Verify that no-cache resources are stored in cache, but are not fetched from
6208 // cache during normal loads.
6209 TEST(HttpCache, CacheControlNoCacheNormalLoad) {
6210 MockHttpCache cache;
6212 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6213 transaction.response_headers = "cache-control: no-cache\n";
6215 // Initial load.
6216 RunTransactionTest(cache.http_cache(), transaction);
6218 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6219 EXPECT_EQ(0, cache.disk_cache()->open_count());
6220 EXPECT_EQ(1, cache.disk_cache()->create_count());
6222 // Try loading again; it should result in a network fetch.
6223 RunTransactionTest(cache.http_cache(), transaction);
6225 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6226 EXPECT_EQ(1, cache.disk_cache()->open_count());
6227 EXPECT_EQ(1, cache.disk_cache()->create_count());
6229 disk_cache::Entry* entry;
6230 EXPECT_TRUE(cache.OpenBackendEntry(transaction.url, &entry));
6231 entry->Close();
6234 // Verify that no-cache resources are stored in cache and fetched from cache
6235 // when the LOAD_PREFERRING_CACHE flag is set.
6236 TEST(HttpCache, CacheControlNoCacheHistoryLoad) {
6237 MockHttpCache cache;
6239 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6240 transaction.response_headers = "cache-control: no-cache\n";
6242 // Initial load.
6243 RunTransactionTest(cache.http_cache(), transaction);
6245 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6246 EXPECT_EQ(0, cache.disk_cache()->open_count());
6247 EXPECT_EQ(1, cache.disk_cache()->create_count());
6249 // Try loading again with LOAD_PREFERRING_CACHE.
6250 transaction.load_flags = LOAD_PREFERRING_CACHE;
6251 RunTransactionTest(cache.http_cache(), transaction);
6253 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6254 EXPECT_EQ(1, cache.disk_cache()->open_count());
6255 EXPECT_EQ(1, cache.disk_cache()->create_count());
6257 disk_cache::Entry* entry;
6258 EXPECT_TRUE(cache.OpenBackendEntry(transaction.url, &entry));
6259 entry->Close();
6262 TEST(HttpCache, CacheControlNoStore) {
6263 MockHttpCache cache;
6265 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6266 transaction.response_headers = "cache-control: no-store\n";
6268 // initial load
6269 RunTransactionTest(cache.http_cache(), transaction);
6271 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6272 EXPECT_EQ(0, cache.disk_cache()->open_count());
6273 EXPECT_EQ(1, cache.disk_cache()->create_count());
6275 // try loading again; it should result in a network fetch
6276 RunTransactionTest(cache.http_cache(), transaction);
6278 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6279 EXPECT_EQ(0, cache.disk_cache()->open_count());
6280 EXPECT_EQ(2, cache.disk_cache()->create_count());
6282 disk_cache::Entry* entry;
6283 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
6286 TEST(HttpCache, CacheControlNoStore2) {
6287 // this test is similar to the above test, except that the initial response
6288 // is cachable, but when it is validated, no-store is received causing the
6289 // cached document to be deleted.
6290 MockHttpCache cache;
6292 ScopedMockTransaction transaction(kETagGET_Transaction);
6294 // initial load
6295 RunTransactionTest(cache.http_cache(), transaction);
6297 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6298 EXPECT_EQ(0, cache.disk_cache()->open_count());
6299 EXPECT_EQ(1, cache.disk_cache()->create_count());
6301 // try loading again; it should result in a network fetch
6302 transaction.load_flags = LOAD_VALIDATE_CACHE;
6303 transaction.response_headers = "cache-control: no-store\n";
6304 RunTransactionTest(cache.http_cache(), transaction);
6306 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6307 EXPECT_EQ(1, cache.disk_cache()->open_count());
6308 EXPECT_EQ(1, cache.disk_cache()->create_count());
6310 disk_cache::Entry* entry;
6311 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
6314 TEST(HttpCache, CacheControlNoStore3) {
6315 // this test is similar to the above test, except that the response is a 304
6316 // instead of a 200. this should never happen in practice, but it seems like
6317 // a good thing to verify that we still destroy the cache entry.
6318 MockHttpCache cache;
6320 ScopedMockTransaction transaction(kETagGET_Transaction);
6322 // initial load
6323 RunTransactionTest(cache.http_cache(), transaction);
6325 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6326 EXPECT_EQ(0, cache.disk_cache()->open_count());
6327 EXPECT_EQ(1, cache.disk_cache()->create_count());
6329 // try loading again; it should result in a network fetch
6330 transaction.load_flags = LOAD_VALIDATE_CACHE;
6331 transaction.response_headers = "cache-control: no-store\n";
6332 transaction.status = "HTTP/1.1 304 Not Modified";
6333 RunTransactionTest(cache.http_cache(), transaction);
6335 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6336 EXPECT_EQ(1, cache.disk_cache()->open_count());
6337 EXPECT_EQ(1, cache.disk_cache()->create_count());
6339 disk_cache::Entry* entry;
6340 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
6343 // Ensure that we don't cache requests served over bad HTTPS.
6344 TEST(HttpCache, SimpleGET_SSLError) {
6345 MockHttpCache cache;
6347 MockTransaction transaction = kSimpleGET_Transaction;
6348 transaction.cert_status = CERT_STATUS_REVOKED;
6349 ScopedMockTransaction scoped_transaction(transaction);
6351 // write to the cache
6352 RunTransactionTest(cache.http_cache(), transaction);
6354 // Test that it was not cached.
6355 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
6357 MockHttpRequest request(transaction);
6358 TestCompletionCallback callback;
6360 scoped_ptr<HttpTransaction> trans;
6361 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6363 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6364 if (rv == ERR_IO_PENDING)
6365 rv = callback.WaitForResult();
6366 ASSERT_EQ(ERR_CACHE_MISS, rv);
6369 // Ensure that we don't crash by if left-behind transactions.
6370 TEST(HttpCache, OutlivedTransactions) {
6371 MockHttpCache* cache = new MockHttpCache;
6373 scoped_ptr<HttpTransaction> trans;
6374 EXPECT_EQ(OK, cache->CreateTransaction(&trans));
6376 delete cache;
6377 trans.reset();
6380 // Test that the disabled mode works.
6381 TEST(HttpCache, CacheDisabledMode) {
6382 MockHttpCache cache;
6384 // write to the cache
6385 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6387 // go into disabled mode
6388 cache.http_cache()->set_mode(HttpCache::DISABLE);
6390 // force this transaction to write to the cache again
6391 MockTransaction transaction(kSimpleGET_Transaction);
6393 RunTransactionTest(cache.http_cache(), transaction);
6395 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6396 EXPECT_EQ(0, cache.disk_cache()->open_count());
6397 EXPECT_EQ(1, cache.disk_cache()->create_count());
6400 // Other tests check that the response headers of the cached response
6401 // get updated on 304. Here we specifically check that the
6402 // HttpResponseHeaders::request_time and HttpResponseHeaders::response_time
6403 // fields also gets updated.
6404 // http://crbug.com/20594.
6405 TEST(HttpCache, UpdatesRequestResponseTimeOn304) {
6406 MockHttpCache cache;
6408 const char kUrl[] = "http://foobar";
6409 const char kData[] = "body";
6411 MockTransaction mock_network_response = { 0 };
6412 mock_network_response.url = kUrl;
6414 AddMockTransaction(&mock_network_response);
6416 // Request |kUrl|, causing |kNetResponse1| to be written to the cache.
6418 MockTransaction request = { 0 };
6419 request.url = kUrl;
6420 request.method = "GET";
6421 request.request_headers = "\r\n";
6422 request.data = kData;
6424 static const Response kNetResponse1 = {
6425 "HTTP/1.1 200 OK",
6426 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6427 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6428 kData
6431 kNetResponse1.AssignTo(&mock_network_response);
6433 RunTransactionTest(cache.http_cache(), request);
6435 // Request |kUrl| again, this time validating the cache and getting
6436 // a 304 back.
6438 request.load_flags = LOAD_VALIDATE_CACHE;
6440 static const Response kNetResponse2 = {
6441 "HTTP/1.1 304 Not Modified",
6442 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n",
6446 kNetResponse2.AssignTo(&mock_network_response);
6448 base::Time request_time = base::Time() + base::TimeDelta::FromHours(1234);
6449 base::Time response_time = base::Time() + base::TimeDelta::FromHours(1235);
6451 mock_network_response.request_time = request_time;
6452 mock_network_response.response_time = response_time;
6454 HttpResponseInfo response;
6455 RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response);
6457 // The request and response times should have been updated.
6458 EXPECT_EQ(request_time.ToInternalValue(),
6459 response.request_time.ToInternalValue());
6460 EXPECT_EQ(response_time.ToInternalValue(),
6461 response.response_time.ToInternalValue());
6463 std::string headers;
6464 response.headers->GetNormalizedHeaders(&headers);
6466 EXPECT_EQ("HTTP/1.1 200 OK\n"
6467 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6468 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6469 headers);
6471 RemoveMockTransaction(&mock_network_response);
6474 // Tests that we can write metadata to an entry.
6475 TEST(HttpCache, WriteMetadata_OK) {
6476 MockHttpCache cache;
6478 // Write to the cache
6479 HttpResponseInfo response;
6480 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
6481 &response);
6482 EXPECT_TRUE(response.metadata.get() == NULL);
6484 // Trivial call.
6485 cache.http_cache()->WriteMetadata(GURL("foo"), DEFAULT_PRIORITY, Time::Now(),
6486 NULL, 0);
6488 // Write meta data to the same entry.
6489 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50));
6490 memset(buf->data(), 0, buf->size());
6491 base::strlcpy(buf->data(), "Hi there", buf->size());
6492 cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
6493 DEFAULT_PRIORITY, response.response_time,
6494 buf.get(), buf->size());
6496 // Release the buffer before the operation takes place.
6497 buf = NULL;
6499 // Makes sure we finish pending operations.
6500 base::MessageLoop::current()->RunUntilIdle();
6502 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
6503 &response);
6504 ASSERT_TRUE(response.metadata.get() != NULL);
6505 EXPECT_EQ(50, response.metadata->size());
6506 EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
6508 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6509 EXPECT_EQ(2, cache.disk_cache()->open_count());
6510 EXPECT_EQ(1, cache.disk_cache()->create_count());
6513 // Tests that we only write metadata to an entry if the time stamp matches.
6514 TEST(HttpCache, WriteMetadata_Fail) {
6515 MockHttpCache cache;
6517 // Write to the cache
6518 HttpResponseInfo response;
6519 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
6520 &response);
6521 EXPECT_TRUE(response.metadata.get() == NULL);
6523 // Attempt to write meta data to the same entry.
6524 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50));
6525 memset(buf->data(), 0, buf->size());
6526 base::strlcpy(buf->data(), "Hi there", buf->size());
6527 base::Time expected_time = response.response_time -
6528 base::TimeDelta::FromMilliseconds(20);
6529 cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
6530 DEFAULT_PRIORITY, expected_time, buf.get(),
6531 buf->size());
6533 // Makes sure we finish pending operations.
6534 base::MessageLoop::current()->RunUntilIdle();
6536 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
6537 &response);
6538 EXPECT_TRUE(response.metadata.get() == NULL);
6540 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6541 EXPECT_EQ(2, cache.disk_cache()->open_count());
6542 EXPECT_EQ(1, cache.disk_cache()->create_count());
6545 // Tests that we can read metadata after validating the entry and with READ mode
6546 // transactions.
6547 TEST(HttpCache, ReadMetadata) {
6548 MockHttpCache cache;
6550 // Write to the cache
6551 HttpResponseInfo response;
6552 RunTransactionTestWithResponseInfo(cache.http_cache(),
6553 kTypicalGET_Transaction, &response);
6554 EXPECT_TRUE(response.metadata.get() == NULL);
6556 // Write meta data to the same entry.
6557 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50));
6558 memset(buf->data(), 0, buf->size());
6559 base::strlcpy(buf->data(), "Hi there", buf->size());
6560 cache.http_cache()->WriteMetadata(GURL(kTypicalGET_Transaction.url),
6561 DEFAULT_PRIORITY, response.response_time,
6562 buf.get(), buf->size());
6564 // Makes sure we finish pending operations.
6565 base::MessageLoop::current()->RunUntilIdle();
6567 // Start with a READ mode transaction.
6568 MockTransaction trans1(kTypicalGET_Transaction);
6569 trans1.load_flags = LOAD_ONLY_FROM_CACHE;
6571 RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response);
6572 ASSERT_TRUE(response.metadata.get() != NULL);
6573 EXPECT_EQ(50, response.metadata->size());
6574 EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
6576 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6577 EXPECT_EQ(2, cache.disk_cache()->open_count());
6578 EXPECT_EQ(1, cache.disk_cache()->create_count());
6579 base::MessageLoop::current()->RunUntilIdle();
6581 // Now make sure that the entry is re-validated with the server.
6582 trans1.load_flags = LOAD_VALIDATE_CACHE;
6583 trans1.status = "HTTP/1.1 304 Not Modified";
6584 AddMockTransaction(&trans1);
6586 response.metadata = NULL;
6587 RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response);
6588 EXPECT_TRUE(response.metadata.get() != NULL);
6590 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6591 EXPECT_EQ(3, cache.disk_cache()->open_count());
6592 EXPECT_EQ(1, cache.disk_cache()->create_count());
6593 base::MessageLoop::current()->RunUntilIdle();
6594 RemoveMockTransaction(&trans1);
6596 // Now return 200 when validating the entry so the metadata will be lost.
6597 MockTransaction trans2(kTypicalGET_Transaction);
6598 trans2.load_flags = LOAD_VALIDATE_CACHE;
6599 RunTransactionTestWithResponseInfo(cache.http_cache(), trans2, &response);
6600 EXPECT_TRUE(response.metadata.get() == NULL);
6602 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6603 EXPECT_EQ(4, cache.disk_cache()->open_count());
6604 EXPECT_EQ(1, cache.disk_cache()->create_count());
6607 // Tests that we don't mark entries as truncated when a filter detects the end
6608 // of the stream.
6609 TEST(HttpCache, FilterCompletion) {
6610 MockHttpCache cache;
6611 TestCompletionCallback callback;
6614 scoped_ptr<HttpTransaction> trans;
6615 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6617 MockHttpRequest request(kSimpleGET_Transaction);
6618 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6619 EXPECT_EQ(OK, callback.GetResult(rv));
6621 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6622 rv = trans->Read(buf.get(), 256, callback.callback());
6623 EXPECT_GT(callback.GetResult(rv), 0);
6625 // Now make sure that the entry is preserved.
6626 trans->DoneReading();
6629 // Make sure that the ActiveEntry is gone.
6630 base::MessageLoop::current()->RunUntilIdle();
6632 // Read from the cache.
6633 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6635 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6636 EXPECT_EQ(1, cache.disk_cache()->open_count());
6637 EXPECT_EQ(1, cache.disk_cache()->create_count());
6640 // Tests that we don't mark entries as truncated and release the cache
6641 // entry when DoneReading() is called before any Read() calls, such as
6642 // for a redirect.
6643 TEST(HttpCache, DoneReading) {
6644 MockHttpCache cache;
6645 TestCompletionCallback callback;
6647 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6648 transaction.data = "";
6650 scoped_ptr<HttpTransaction> trans;
6651 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6653 MockHttpRequest request(transaction);
6654 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6655 EXPECT_EQ(OK, callback.GetResult(rv));
6657 trans->DoneReading();
6658 // Leave the transaction around.
6660 // Make sure that the ActiveEntry is gone.
6661 base::MessageLoop::current()->RunUntilIdle();
6663 // Read from the cache. This should not deadlock.
6664 RunTransactionTest(cache.http_cache(), transaction);
6666 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6667 EXPECT_EQ(1, cache.disk_cache()->open_count());
6668 EXPECT_EQ(1, cache.disk_cache()->create_count());
6671 // Tests that we stop caching when told.
6672 TEST(HttpCache, StopCachingDeletesEntry) {
6673 MockHttpCache cache;
6674 TestCompletionCallback callback;
6675 MockHttpRequest request(kSimpleGET_Transaction);
6678 scoped_ptr<HttpTransaction> trans;
6679 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6681 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6682 EXPECT_EQ(OK, callback.GetResult(rv));
6684 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6685 rv = trans->Read(buf.get(), 10, callback.callback());
6686 EXPECT_EQ(10, callback.GetResult(rv));
6688 trans->StopCaching();
6690 // We should be able to keep reading.
6691 rv = trans->Read(buf.get(), 256, callback.callback());
6692 EXPECT_GT(callback.GetResult(rv), 0);
6693 rv = trans->Read(buf.get(), 256, callback.callback());
6694 EXPECT_EQ(0, callback.GetResult(rv));
6697 // Make sure that the ActiveEntry is gone.
6698 base::MessageLoop::current()->RunUntilIdle();
6700 // Verify that the entry is gone.
6701 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6703 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6704 EXPECT_EQ(0, cache.disk_cache()->open_count());
6705 EXPECT_EQ(2, cache.disk_cache()->create_count());
6708 // Tests that we stop caching when told, even if DoneReading is called
6709 // after StopCaching.
6710 TEST(HttpCache, StopCachingThenDoneReadingDeletesEntry) {
6711 MockHttpCache cache;
6712 TestCompletionCallback callback;
6713 MockHttpRequest request(kSimpleGET_Transaction);
6716 scoped_ptr<HttpTransaction> trans;
6717 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6719 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6720 EXPECT_EQ(OK, callback.GetResult(rv));
6722 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6723 rv = trans->Read(buf.get(), 10, callback.callback());
6724 EXPECT_EQ(10, callback.GetResult(rv));
6726 trans->StopCaching();
6728 // We should be able to keep reading.
6729 rv = trans->Read(buf.get(), 256, callback.callback());
6730 EXPECT_GT(callback.GetResult(rv), 0);
6731 rv = trans->Read(buf.get(), 256, callback.callback());
6732 EXPECT_EQ(0, callback.GetResult(rv));
6734 // We should be able to call DoneReading.
6735 trans->DoneReading();
6738 // Make sure that the ActiveEntry is gone.
6739 base::MessageLoop::current()->RunUntilIdle();
6741 // Verify that the entry is gone.
6742 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6744 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6745 EXPECT_EQ(0, cache.disk_cache()->open_count());
6746 EXPECT_EQ(2, cache.disk_cache()->create_count());
6749 // Tests that we stop caching when told, when using auth.
6750 TEST(HttpCache, StopCachingWithAuthDeletesEntry) {
6751 MockHttpCache cache;
6752 TestCompletionCallback callback;
6753 MockTransaction mock_transaction(kSimpleGET_Transaction);
6754 mock_transaction.status = "HTTP/1.1 401 Unauthorized";
6755 AddMockTransaction(&mock_transaction);
6756 MockHttpRequest request(mock_transaction);
6759 scoped_ptr<HttpTransaction> trans;
6760 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6762 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6763 EXPECT_EQ(OK, callback.GetResult(rv));
6765 trans->StopCaching();
6767 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6768 rv = trans->Read(buf.get(), 10, callback.callback());
6769 EXPECT_EQ(callback.GetResult(rv), 10);
6771 RemoveMockTransaction(&mock_transaction);
6773 // Make sure that the ActiveEntry is gone.
6774 base::MessageLoop::current()->RunUntilIdle();
6776 // Verify that the entry is gone.
6777 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6779 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6780 EXPECT_EQ(0, cache.disk_cache()->open_count());
6781 EXPECT_EQ(2, cache.disk_cache()->create_count());
6784 // Tests that when we are told to stop caching we don't throw away valid data.
6785 TEST(HttpCache, StopCachingSavesEntry) {
6786 MockHttpCache cache;
6787 TestCompletionCallback callback;
6788 MockHttpRequest request(kSimpleGET_Transaction);
6791 scoped_ptr<HttpTransaction> trans;
6792 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6794 // Force a response that can be resumed.
6795 MockTransaction mock_transaction(kSimpleGET_Transaction);
6796 AddMockTransaction(&mock_transaction);
6797 mock_transaction.response_headers = "Cache-Control: max-age=10000\n"
6798 "Content-Length: 42\n"
6799 "Etag: \"foo\"\n";
6801 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6802 EXPECT_EQ(OK, callback.GetResult(rv));
6804 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6805 rv = trans->Read(buf.get(), 10, callback.callback());
6806 EXPECT_EQ(callback.GetResult(rv), 10);
6808 trans->StopCaching();
6810 // We should be able to keep reading.
6811 rv = trans->Read(buf.get(), 256, callback.callback());
6812 EXPECT_GT(callback.GetResult(rv), 0);
6813 rv = trans->Read(buf.get(), 256, callback.callback());
6814 EXPECT_EQ(callback.GetResult(rv), 0);
6816 RemoveMockTransaction(&mock_transaction);
6819 // Verify that the entry is marked as incomplete.
6820 disk_cache::Entry* entry;
6821 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
6822 HttpResponseInfo response;
6823 bool truncated = false;
6824 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6825 EXPECT_TRUE(truncated);
6826 entry->Close();
6829 // Tests that we handle truncated enries when StopCaching is called.
6830 TEST(HttpCache, StopCachingTruncatedEntry) {
6831 MockHttpCache cache;
6832 TestCompletionCallback callback;
6833 MockHttpRequest request(kRangeGET_TransactionOK);
6834 request.extra_headers.Clear();
6835 request.extra_headers.AddHeaderFromString(EXTRA_HEADER_LINE);
6836 AddMockTransaction(&kRangeGET_TransactionOK);
6838 std::string raw_headers("HTTP/1.1 200 OK\n"
6839 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
6840 "ETag: \"foo\"\n"
6841 "Accept-Ranges: bytes\n"
6842 "Content-Length: 80\n");
6843 CreateTruncatedEntry(raw_headers, &cache);
6846 // Now make a regular request.
6847 scoped_ptr<HttpTransaction> trans;
6848 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6850 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6851 EXPECT_EQ(OK, callback.GetResult(rv));
6853 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6854 rv = trans->Read(buf.get(), 10, callback.callback());
6855 EXPECT_EQ(callback.GetResult(rv), 10);
6857 // This is actually going to do nothing.
6858 trans->StopCaching();
6860 // We should be able to keep reading.
6861 rv = trans->Read(buf.get(), 256, callback.callback());
6862 EXPECT_GT(callback.GetResult(rv), 0);
6863 rv = trans->Read(buf.get(), 256, callback.callback());
6864 EXPECT_GT(callback.GetResult(rv), 0);
6865 rv = trans->Read(buf.get(), 256, callback.callback());
6866 EXPECT_EQ(callback.GetResult(rv), 0);
6869 // Verify that the disk entry was updated.
6870 disk_cache::Entry* entry;
6871 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
6872 EXPECT_EQ(80, entry->GetDataSize(1));
6873 bool truncated = true;
6874 HttpResponseInfo response;
6875 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6876 EXPECT_FALSE(truncated);
6877 entry->Close();
6879 RemoveMockTransaction(&kRangeGET_TransactionOK);
6882 // Tests that we detect truncated resources from the net when there is
6883 // a Content-Length header.
6884 TEST(HttpCache, TruncatedByContentLength) {
6885 MockHttpCache cache;
6886 TestCompletionCallback callback;
6888 MockTransaction transaction(kSimpleGET_Transaction);
6889 AddMockTransaction(&transaction);
6890 transaction.response_headers = "Cache-Control: max-age=10000\n"
6891 "Content-Length: 100\n";
6892 RunTransactionTest(cache.http_cache(), transaction);
6893 RemoveMockTransaction(&transaction);
6895 // Read from the cache.
6896 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6898 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6899 EXPECT_EQ(0, cache.disk_cache()->open_count());
6900 EXPECT_EQ(2, cache.disk_cache()->create_count());
6903 // Tests that we actually flag entries as truncated when we detect an error
6904 // from the net.
6905 TEST(HttpCache, TruncatedByContentLength2) {
6906 MockHttpCache cache;
6907 TestCompletionCallback callback;
6909 MockTransaction transaction(kSimpleGET_Transaction);
6910 AddMockTransaction(&transaction);
6911 transaction.response_headers = "Cache-Control: max-age=10000\n"
6912 "Content-Length: 100\n"
6913 "Etag: \"foo\"\n";
6914 RunTransactionTest(cache.http_cache(), transaction);
6915 RemoveMockTransaction(&transaction);
6917 // Verify that the entry is marked as incomplete.
6918 disk_cache::Entry* entry;
6919 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
6920 HttpResponseInfo response;
6921 bool truncated = false;
6922 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6923 EXPECT_TRUE(truncated);
6924 entry->Close();
6927 // Make sure that calling SetPriority on a cache transaction passes on
6928 // its priority updates to its underlying network transaction.
6929 TEST(HttpCache, SetPriority) {
6930 MockHttpCache cache;
6932 scoped_ptr<HttpTransaction> trans;
6933 ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(IDLE, &trans));
6935 // Shouldn't crash, but doesn't do anything either.
6936 trans->SetPriority(LOW);
6938 EXPECT_FALSE(cache.network_layer()->last_transaction());
6939 EXPECT_EQ(DEFAULT_PRIORITY,
6940 cache.network_layer()->last_create_transaction_priority());
6942 HttpRequestInfo info;
6943 info.url = GURL(kSimpleGET_Transaction.url);
6944 TestCompletionCallback callback;
6945 EXPECT_EQ(ERR_IO_PENDING,
6946 trans->Start(&info, callback.callback(), BoundNetLog()));
6948 EXPECT_TRUE(cache.network_layer()->last_transaction());
6949 if (cache.network_layer()->last_transaction()) {
6950 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
6951 EXPECT_EQ(LOW, cache.network_layer()->last_transaction()->priority());
6954 trans->SetPriority(HIGHEST);
6956 if (cache.network_layer()->last_transaction()) {
6957 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
6958 EXPECT_EQ(HIGHEST, cache.network_layer()->last_transaction()->priority());
6961 EXPECT_EQ(OK, callback.WaitForResult());
6964 // Make sure that calling SetWebSocketHandshakeStreamCreateHelper on a cache
6965 // transaction passes on its argument to the underlying network transaction.
6966 TEST(HttpCache, SetWebSocketHandshakeStreamCreateHelper) {
6967 MockHttpCache cache;
6969 FakeWebSocketHandshakeStreamCreateHelper create_helper;
6970 scoped_ptr<HttpTransaction> trans;
6971 ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(IDLE, &trans));
6973 EXPECT_FALSE(cache.network_layer()->last_transaction());
6975 HttpRequestInfo info;
6976 info.url = GURL(kSimpleGET_Transaction.url);
6977 TestCompletionCallback callback;
6978 EXPECT_EQ(ERR_IO_PENDING,
6979 trans->Start(&info, callback.callback(), BoundNetLog()));
6981 ASSERT_TRUE(cache.network_layer()->last_transaction());
6982 EXPECT_FALSE(cache.network_layer()->last_transaction()->
6983 websocket_handshake_stream_create_helper());
6984 trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper);
6985 EXPECT_EQ(&create_helper,
6986 cache.network_layer()->last_transaction()->
6987 websocket_handshake_stream_create_helper());
6988 EXPECT_EQ(OK, callback.WaitForResult());
6991 // Make sure that a cache transaction passes on its priority to
6992 // newly-created network transactions.
6993 TEST(HttpCache, SetPriorityNewTransaction) {
6994 MockHttpCache cache;
6995 AddMockTransaction(&kRangeGET_TransactionOK);
6997 std::string raw_headers("HTTP/1.1 200 OK\n"
6998 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
6999 "ETag: \"foo\"\n"
7000 "Accept-Ranges: bytes\n"
7001 "Content-Length: 80\n");
7002 CreateTruncatedEntry(raw_headers, &cache);
7004 // Now make a regular request.
7005 std::string headers;
7006 MockTransaction transaction(kRangeGET_TransactionOK);
7007 transaction.request_headers = EXTRA_HEADER;
7008 transaction.data = kFullRangeData;
7010 scoped_ptr<HttpTransaction> trans;
7011 ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(MEDIUM, &trans));
7012 EXPECT_EQ(DEFAULT_PRIORITY,
7013 cache.network_layer()->last_create_transaction_priority());
7015 MockHttpRequest info(transaction);
7016 TestCompletionCallback callback;
7017 EXPECT_EQ(ERR_IO_PENDING,
7018 trans->Start(&info, callback.callback(), BoundNetLog()));
7019 EXPECT_EQ(OK, callback.WaitForResult());
7021 EXPECT_EQ(MEDIUM, cache.network_layer()->last_create_transaction_priority());
7023 trans->SetPriority(HIGHEST);
7024 // Should trigger a new network transaction and pick up the new
7025 // priority.
7026 ReadAndVerifyTransaction(trans.get(), transaction);
7028 EXPECT_EQ(HIGHEST, cache.network_layer()->last_create_transaction_priority());
7030 RemoveMockTransaction(&kRangeGET_TransactionOK);
7033 int64 RunTransactionAndGetReceivedBytes(
7034 MockHttpCache& cache,
7035 const MockTransaction& trans_info) {
7036 int64 received_bytes = -1;
7037 RunTransactionTestBase(cache.http_cache(), trans_info,
7038 MockHttpRequest(trans_info), NULL, BoundNetLog(), NULL,
7039 &received_bytes);
7040 return received_bytes;
7043 int64 TransactionSize(const MockTransaction& transaction) {
7044 return strlen(transaction.status) + strlen(transaction.response_headers) +
7045 strlen(transaction.data);
7048 TEST(HttpCache, ReceivedBytesCacheMissAndThenHit) {
7049 MockHttpCache cache;
7051 MockTransaction transaction(kSimpleGET_Transaction);
7052 int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7053 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7055 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7056 EXPECT_EQ(0, received_bytes);
7059 TEST(HttpCache, ReceivedBytesConditionalRequest304) {
7060 MockHttpCache cache;
7062 ScopedMockTransaction transaction(kETagGET_Transaction);
7063 int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7064 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7066 transaction.load_flags = LOAD_VALIDATE_CACHE;
7067 transaction.handler = ETagGet_ConditionalRequest_Handler;
7068 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7069 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7072 TEST(HttpCache, ReceivedBytesConditionalRequest200) {
7073 MockHttpCache cache;
7075 MockTransaction transaction(kTypicalGET_Transaction);
7076 transaction.request_headers = "Foo: bar\r\n";
7077 transaction.response_headers =
7078 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
7079 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
7080 "Etag: \"foopy\"\n"
7081 "Cache-Control: max-age=0\n"
7082 "Vary: Foo\n";
7083 AddMockTransaction(&transaction);
7084 int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7085 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7087 RevalidationServer server;
7088 transaction.handler = server.Handler;
7089 transaction.request_headers = "Foo: none\r\n";
7090 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7091 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7093 RemoveMockTransaction(&transaction);
7096 TEST(HttpCache, ReceivedBytesRange) {
7097 MockHttpCache cache;
7098 AddMockTransaction(&kRangeGET_TransactionOK);
7099 MockTransaction transaction(kRangeGET_TransactionOK);
7101 // Read bytes 40-49 from the network.
7102 int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7103 int64 range_response_size = TransactionSize(transaction);
7104 EXPECT_EQ(range_response_size, received_bytes);
7106 // Read bytes 40-49 from the cache.
7107 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7108 EXPECT_EQ(0, received_bytes);
7109 base::MessageLoop::current()->RunUntilIdle();
7111 // Read bytes 30-39 from the network.
7112 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
7113 transaction.data = "rg: 30-39 ";
7114 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7115 EXPECT_EQ(range_response_size, received_bytes);
7116 base::MessageLoop::current()->RunUntilIdle();
7118 // Read bytes 20-29 and 50-59 from the network, bytes 30-49 from the cache.
7119 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
7120 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
7121 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7122 EXPECT_EQ(range_response_size * 2, received_bytes);
7124 RemoveMockTransaction(&kRangeGET_TransactionOK);
7127 class HttpCachePrefetchValidationTest : public ::testing::Test {
7128 protected:
7129 static const int kMaxAgeSecs = 100;
7130 static const int kRequireValidationSecs = kMaxAgeSecs + 1;
7132 HttpCachePrefetchValidationTest() : transaction_(kSimpleGET_Transaction) {
7133 DCHECK_LT(kMaxAgeSecs, prefetch_reuse_mins() * kNumSecondsPerMinute);
7135 clock_ = new base::SimpleTestClock();
7136 cache_.http_cache()->SetClockForTesting(make_scoped_ptr(clock_));
7137 cache_.network_layer()->SetClock(clock_);
7139 transaction_.response_headers = "Cache-Control: max-age=100\n";
7142 bool TransactionRequiredNetwork(int load_flags) {
7143 int pre_transaction_count = transaction_count();
7144 transaction_.load_flags = load_flags;
7145 RunTransactionTest(cache_.http_cache(), transaction_);
7146 return pre_transaction_count != transaction_count();
7149 void AdvanceTime(int seconds) {
7150 clock_->Advance(base::TimeDelta::FromSeconds(seconds));
7153 int prefetch_reuse_mins() { return HttpCache::kPrefetchReuseMins; }
7155 // How many times this test has sent requests to the (fake) origin
7156 // server. Every test case needs to make at least one request to initialise
7157 // the cache.
7158 int transaction_count() {
7159 return cache_.network_layer()->transaction_count();
7162 MockHttpCache cache_;
7163 ScopedMockTransaction transaction_;
7164 std::string response_headers_;
7165 base::SimpleTestClock* clock_;
7168 TEST_F(HttpCachePrefetchValidationTest, SkipValidationShortlyAfterPrefetch) {
7169 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7170 AdvanceTime(kRequireValidationSecs);
7171 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7174 TEST_F(HttpCachePrefetchValidationTest, ValidateLongAfterPrefetch) {
7175 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7176 AdvanceTime(prefetch_reuse_mins() * kNumSecondsPerMinute);
7177 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7180 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceOnly) {
7181 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7182 AdvanceTime(kRequireValidationSecs);
7183 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7184 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7187 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceReadOnly) {
7188 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7189 AdvanceTime(kRequireValidationSecs);
7190 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_ONLY_FROM_CACHE));
7191 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7194 TEST_F(HttpCachePrefetchValidationTest, BypassCacheOverwritesPrefetch) {
7195 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7196 AdvanceTime(kRequireValidationSecs);
7197 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_BYPASS_CACHE));
7198 AdvanceTime(kRequireValidationSecs);
7199 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7202 TEST_F(HttpCachePrefetchValidationTest,
7203 SkipValidationOnExistingEntryThatNeedsValidation) {
7204 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7205 AdvanceTime(kRequireValidationSecs);
7206 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7207 AdvanceTime(kRequireValidationSecs);
7208 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7209 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7212 TEST_F(HttpCachePrefetchValidationTest,
7213 SkipValidationOnExistingEntryThatDoesNotNeedValidation) {
7214 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7215 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
7216 AdvanceTime(kRequireValidationSecs);
7217 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7218 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7221 TEST_F(HttpCachePrefetchValidationTest, PrefetchMultipleTimes) {
7222 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7223 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
7224 AdvanceTime(kRequireValidationSecs);
7225 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7228 TEST_F(HttpCachePrefetchValidationTest, ValidateOnDelayedSecondPrefetch) {
7229 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7230 AdvanceTime(kRequireValidationSecs);
7231 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7232 AdvanceTime(kRequireValidationSecs);
7233 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7236 // Framework for tests of stale-while-revalidate related functionality. With
7237 // the default settings (age=3601,stale-while-revalidate=7200,max-age=3600) it
7238 // will trigger the stale-while-revalidate asynchronous revalidation. Setting
7239 // |age_| to < 3600 will prevent any revalidation, and |age_| > 10800 will cause
7240 // synchronous revalidation.
7241 class HttpCacheStaleWhileRevalidateTest : public ::testing::Test {
7242 protected:
7243 HttpCacheStaleWhileRevalidateTest()
7244 : transaction_(kSimpleGET_Transaction),
7245 age_(3601),
7246 stale_while_revalidate_(7200),
7247 validator_("Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT") {
7248 cache_.http_cache()->set_use_stale_while_revalidate_for_testing(true);
7251 // RunTransactionTest() with the arguments from this fixture.
7252 void RunFixtureTransactionTest() {
7253 std::string response_headers = base::StringPrintf(
7254 "%s\n"
7255 "Age: %d\n"
7256 "Cache-Control: max-age=3600,stale-while-revalidate=%d\n",
7257 validator_.c_str(),
7258 age_,
7259 stale_while_revalidate_);
7260 transaction_.response_headers = response_headers.c_str();
7261 RunTransactionTest(cache_.http_cache(), transaction_);
7262 transaction_.response_headers = "";
7265 // How many times this test has sent requests to the (fake) origin
7266 // server. Every test case needs to make at least one request to initialise
7267 // the cache.
7268 int transaction_count() {
7269 return cache_.network_layer()->transaction_count();
7272 // How many times an existing cache entry was opened during the test case.
7273 int open_count() { return cache_.disk_cache()->open_count(); }
7275 MockHttpCache cache_;
7276 ScopedMockTransaction transaction_;
7277 int age_;
7278 int stale_while_revalidate_;
7279 std::string validator_;
7282 static void CheckResourceFreshnessHeader(const HttpRequestInfo* request,
7283 std::string* response_status,
7284 std::string* response_headers,
7285 std::string* response_data) {
7286 std::string value;
7287 EXPECT_TRUE(request->extra_headers.GetHeader("Resource-Freshness", &value));
7288 EXPECT_EQ("max-age=3600,stale-while-revalidate=7200,age=10801", value);
7291 // Verify that the Resource-Freshness header is sent on a revalidation if the
7292 // stale-while-revalidate directive was on the response.
7293 TEST_F(HttpCacheStaleWhileRevalidateTest, ResourceFreshnessHeaderSent) {
7294 age_ = 10801; // Outside the stale-while-revalidate window.
7296 // Write to the cache.
7297 RunFixtureTransactionTest();
7299 EXPECT_EQ(1, transaction_count());
7301 // Send the request again and check that Resource-Freshness header is added.
7302 transaction_.handler = CheckResourceFreshnessHeader;
7304 RunFixtureTransactionTest();
7306 EXPECT_EQ(2, transaction_count());
7309 static void CheckResourceFreshnessAbsent(const HttpRequestInfo* request,
7310 std::string* response_status,
7311 std::string* response_headers,
7312 std::string* response_data) {
7313 EXPECT_FALSE(request->extra_headers.HasHeader("Resource-Freshness"));
7316 // Verify that the Resource-Freshness header is not sent when
7317 // stale-while-revalidate is 0.
7318 TEST_F(HttpCacheStaleWhileRevalidateTest, ResourceFreshnessHeaderNotSent) {
7319 age_ = 10801;
7320 stale_while_revalidate_ = 0;
7322 // Write to the cache.
7323 RunFixtureTransactionTest();
7325 EXPECT_EQ(1, transaction_count());
7327 // Send the request again and check that Resource-Freshness header is absent.
7328 transaction_.handler = CheckResourceFreshnessAbsent;
7330 RunFixtureTransactionTest();
7332 EXPECT_EQ(2, transaction_count());
7335 // Verify that when stale-while-revalidate applies the response is read from
7336 // cache.
7337 TEST_F(HttpCacheStaleWhileRevalidateTest, ReadFromCache) {
7338 // Write to the cache.
7339 RunFixtureTransactionTest();
7341 EXPECT_EQ(0, open_count());
7342 EXPECT_EQ(1, transaction_count());
7344 // Read back from the cache.
7345 RunFixtureTransactionTest();
7347 EXPECT_EQ(1, open_count());
7348 EXPECT_EQ(1, transaction_count());
7351 // Verify that when stale-while-revalidate applies an asynchronous request is
7352 // sent.
7353 TEST_F(HttpCacheStaleWhileRevalidateTest, AsyncRequestSent) {
7354 // Write to the cache.
7355 RunFixtureTransactionTest();
7357 EXPECT_EQ(1, transaction_count());
7359 // Read back from the cache.
7360 RunFixtureTransactionTest();
7362 EXPECT_EQ(1, transaction_count());
7364 // Let the async request execute.
7365 base::RunLoop().RunUntilIdle();
7366 EXPECT_EQ(2, transaction_count());
7369 // Verify that tearing down the HttpCache with an async revalidation in progress
7370 // does not break anything (this test is most likely to find problems when run
7371 // with a memory checker such as AddressSanitizer).
7372 TEST_F(HttpCacheStaleWhileRevalidateTest, AsyncTearDown) {
7373 // Write to the cache.
7374 RunFixtureTransactionTest();
7376 // Read back from the cache.
7377 RunFixtureTransactionTest();
7380 static void CheckIfModifiedSinceHeader(const HttpRequestInfo* request,
7381 std::string* response_status,
7382 std::string* response_headers,
7383 std::string* response_data) {
7384 std::string value;
7385 EXPECT_TRUE(request->extra_headers.GetHeader("If-Modified-Since", &value));
7386 EXPECT_EQ("Sat, 18 Apr 2007 01:10:43 GMT", value);
7389 // Verify that the async revalidation contains an If-Modified-Since header.
7390 TEST_F(HttpCacheStaleWhileRevalidateTest, AsyncRequestIfModifiedSince) {
7391 // Write to the cache.
7392 RunFixtureTransactionTest();
7394 transaction_.handler = CheckIfModifiedSinceHeader;
7396 // Read back from the cache.
7397 RunFixtureTransactionTest();
7400 static void CheckIfNoneMatchHeader(const HttpRequestInfo* request,
7401 std::string* response_status,
7402 std::string* response_headers,
7403 std::string* response_data) {
7404 std::string value;
7405 EXPECT_TRUE(request->extra_headers.GetHeader("If-None-Match", &value));
7406 EXPECT_EQ("\"40a1-1320-4f6adefa22a40\"", value);
7409 // If the response had ETag rather than Last-Modified, then that is used to
7410 // conditionalise the response.
7411 TEST_F(HttpCacheStaleWhileRevalidateTest, AsyncRequestIfNoneMatch) {
7412 validator_ = "Etag: \"40a1-1320-4f6adefa22a40\"";
7414 // Write to the cache.
7415 RunFixtureTransactionTest();
7417 transaction_.handler = CheckIfNoneMatchHeader;
7419 // Read back from the cache.
7420 RunFixtureTransactionTest();
7423 static void CheckResourceFreshnessHeaderPresent(const HttpRequestInfo* request,
7424 std::string* response_status,
7425 std::string* response_headers,
7426 std::string* response_data) {
7427 EXPECT_TRUE(request->extra_headers.HasHeader("Resource-Freshness"));
7430 TEST_F(HttpCacheStaleWhileRevalidateTest, AsyncRequestHasResourceFreshness) {
7431 // Write to the cache.
7432 RunFixtureTransactionTest();
7434 transaction_.handler = CheckResourceFreshnessHeaderPresent;
7436 // Read back from the cache.
7437 RunFixtureTransactionTest();
7440 // Verify that when age > max-age + stale-while-revalidate stale results are
7441 // not returned.
7442 TEST_F(HttpCacheStaleWhileRevalidateTest, NotAppliedIfTooStale) {
7443 age_ = 10801;
7445 // Write to the cache.
7446 RunFixtureTransactionTest();
7448 EXPECT_EQ(0, open_count());
7449 EXPECT_EQ(1, transaction_count());
7451 // Reading back reads from the network.
7452 RunFixtureTransactionTest();
7454 EXPECT_EQ(1, open_count());
7455 EXPECT_EQ(2, transaction_count());
7458 // HEAD requests should be able to take advantage of stale-while-revalidate.
7459 TEST_F(HttpCacheStaleWhileRevalidateTest, WorksForHeadMethod) {
7460 // Write to the cache. This has to be a GET request; HEAD requests don't
7461 // create new cache entries.
7462 RunFixtureTransactionTest();
7464 EXPECT_EQ(0, open_count());
7465 EXPECT_EQ(1, transaction_count());
7467 // Read back from the cache, and trigger an asynchronous HEAD request.
7468 transaction_.method = "HEAD";
7469 transaction_.data = "";
7471 RunFixtureTransactionTest();
7473 EXPECT_EQ(1, open_count());
7474 EXPECT_EQ(1, transaction_count());
7476 // Let the network request proceed.
7477 base::RunLoop().RunUntilIdle();
7479 EXPECT_EQ(2, transaction_count());
7482 // POST requests should not use stale-while-revalidate.
7483 TEST_F(HttpCacheStaleWhileRevalidateTest, NotAppliedToPost) {
7484 transaction_ = ScopedMockTransaction(kSimplePOST_Transaction);
7486 // Write to the cache.
7487 RunFixtureTransactionTest();
7489 EXPECT_EQ(0, open_count());
7490 EXPECT_EQ(1, transaction_count());
7492 // Reading back reads from the network.
7493 RunFixtureTransactionTest();
7495 EXPECT_EQ(0, open_count());
7496 EXPECT_EQ(2, transaction_count());
7499 static void CheckUrlMatches(const HttpRequestInfo* request,
7500 std::string* response_status,
7501 std::string* response_headers,
7502 std::string* response_data) {
7503 EXPECT_EQ("http://www.google.com/", request->url.spec());
7506 // Async revalidation is issued to the original URL.
7507 TEST_F(HttpCacheStaleWhileRevalidateTest, AsyncRequestUrlMatches) {
7508 transaction_.url = "http://www.google.com/";
7509 // Write to the cache.
7510 RunFixtureTransactionTest();
7512 // Read back from the cache.
7513 RunFixtureTransactionTest();
7515 EXPECT_EQ(1, transaction_count());
7517 transaction_.handler = CheckUrlMatches;
7519 // Let the async request execute and perform the check.
7520 base::RunLoop().RunUntilIdle();
7521 EXPECT_EQ(2, transaction_count());
7524 class SyncLoadFlagTest : public HttpCacheStaleWhileRevalidateTest,
7525 public ::testing::WithParamInterface<int> {};
7527 // Flags which should always cause the request to be synchronous.
7528 TEST_P(SyncLoadFlagTest, MustBeSynchronous) {
7529 transaction_.load_flags |= GetParam();
7530 // Write to the cache.
7531 RunFixtureTransactionTest();
7533 EXPECT_EQ(1, transaction_count());
7535 // Reading back reads from the network.
7536 RunFixtureTransactionTest();
7538 EXPECT_EQ(2, transaction_count());
7541 INSTANTIATE_TEST_CASE_P(HttpCacheStaleWhileRevalidate,
7542 SyncLoadFlagTest,
7543 ::testing::Values(LOAD_VALIDATE_CACHE,
7544 LOAD_BYPASS_CACHE,
7545 LOAD_DISABLE_CACHE));
7547 TEST_F(HttpCacheStaleWhileRevalidateTest,
7548 PreferringCacheDoesNotTriggerAsyncRequest) {
7549 transaction_.load_flags |= LOAD_PREFERRING_CACHE;
7550 // Write to the cache.
7551 RunFixtureTransactionTest();
7553 EXPECT_EQ(1, transaction_count());
7555 // Reading back reads from the cache.
7556 RunFixtureTransactionTest();
7558 EXPECT_EQ(1, transaction_count());
7560 // If there was an async transaction created, it would run now.
7561 base::RunLoop().RunUntilIdle();
7563 // There was no async transaction.
7564 EXPECT_EQ(1, transaction_count());
7567 TEST_F(HttpCacheStaleWhileRevalidateTest, NotUsedWhenDisabled) {
7568 cache_.http_cache()->set_use_stale_while_revalidate_for_testing(false);
7569 // Write to the cache.
7570 RunFixtureTransactionTest();
7572 EXPECT_EQ(1, transaction_count());
7574 // A synchronous revalidation is performed.
7575 RunFixtureTransactionTest();
7577 EXPECT_EQ(2, transaction_count());
7580 TEST_F(HttpCacheStaleWhileRevalidateTest,
7581 OnlyFromCacheDoesNotTriggerAsyncRequest) {
7582 transaction_.load_flags |= LOAD_ONLY_FROM_CACHE;
7583 transaction_.return_code = ERR_CACHE_MISS;
7585 // Writing to the cache should fail, because we are avoiding the network.
7586 RunFixtureTransactionTest();
7588 EXPECT_EQ(0, transaction_count());
7590 base::RunLoop().RunUntilIdle();
7592 // Still nothing.
7593 EXPECT_EQ(0, transaction_count());
7596 // A certificate error during an asynchronous fetch should cause the next fetch
7597 // to proceed synchronously.
7598 // TODO(ricea): In future, only certificate errors which require user
7599 // interaction should fail the asynchronous revalidation, and they should cause
7600 // the next revalidation to be synchronous rather than requiring a total
7601 // refetch. This test will need to be updated appropriately.
7602 TEST_F(HttpCacheStaleWhileRevalidateTest, CertificateErrorCausesRefetch) {
7603 // Write to the cache.
7604 RunFixtureTransactionTest();
7606 EXPECT_EQ(1, transaction_count());
7608 // Now read back. RunTransactionTestBase() expects to receive the network
7609 // error back from the HttpCache::Transaction, but since the cache request
7610 // will return OK we need to duplicate some of its implementation here.
7611 transaction_.return_code = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
7612 TestCompletionCallback callback;
7613 scoped_ptr<HttpTransaction> trans;
7614 int rv = cache_.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
7615 EXPECT_EQ(OK, rv);
7616 ASSERT_TRUE(trans.get());
7618 MockHttpRequest request(transaction_);
7619 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7620 ASSERT_EQ(ERR_IO_PENDING, rv);
7621 ASSERT_EQ(OK, callback.WaitForResult());
7622 ReadAndVerifyTransaction(trans.get(), transaction_);
7624 EXPECT_EQ(1, transaction_count());
7626 // Allow the asynchronous fetch to run.
7627 base::RunLoop().RunUntilIdle();
7629 EXPECT_EQ(2, transaction_count());
7631 // Now run the transaction again. It should run synchronously.
7632 transaction_.return_code = OK;
7633 RunFixtureTransactionTest();
7635 EXPECT_EQ(3, transaction_count());
7638 // Ensure that the response cached by the asynchronous request is not truncated,
7639 // even if the server is slow.
7640 TEST_F(HttpCacheStaleWhileRevalidateTest, EntireResponseCached) {
7641 transaction_.test_mode = TEST_MODE_SLOW_READ;
7642 // Write to the cache.
7643 RunFixtureTransactionTest();
7645 // Read back from the cache.
7646 RunFixtureTransactionTest();
7648 // Let the async request execute.
7649 base::RunLoop().RunUntilIdle();
7651 // The cache entry should still be complete.
7652 transaction_.load_flags = LOAD_ONLY_FROM_CACHE;
7653 RunFixtureTransactionTest();
7656 // Verify that there are no race conditions in the completely synchronous case.
7657 TEST_F(HttpCacheStaleWhileRevalidateTest, SynchronousCaseWorks) {
7658 transaction_.test_mode = TEST_MODE_SYNC_ALL;
7659 // Write to the cache.
7660 RunFixtureTransactionTest();
7662 EXPECT_EQ(1, transaction_count());
7664 // Read back from the cache.
7665 RunFixtureTransactionTest();
7667 EXPECT_EQ(1, transaction_count());
7669 // Let the async request execute.
7670 base::RunLoop().RunUntilIdle();
7671 EXPECT_EQ(2, transaction_count());
7674 static void CheckLoadFlagsAsyncRevalidation(const HttpRequestInfo* request,
7675 std::string* response_status,
7676 std::string* response_headers,
7677 std::string* response_data) {
7678 EXPECT_EQ(LOAD_ASYNC_REVALIDATION, request->load_flags);
7681 // Check that the load flags on the async request are the same as the load flags
7682 // on the original request, plus LOAD_ASYNC_REVALIDATION.
7683 TEST_F(HttpCacheStaleWhileRevalidateTest, LoadFlagsAsyncRevalidation) {
7684 transaction_.load_flags = LOAD_NORMAL;
7685 // Write to the cache.
7686 RunFixtureTransactionTest();
7688 EXPECT_EQ(1, transaction_count());
7690 // Read back from the cache.
7691 RunFixtureTransactionTest();
7693 EXPECT_EQ(1, transaction_count());
7695 transaction_.handler = CheckLoadFlagsAsyncRevalidation;
7696 // Let the async request execute.
7697 base::RunLoop().RunUntilIdle();
7698 EXPECT_EQ(2, transaction_count());
7701 static void SimpleMockAuthHandler(const HttpRequestInfo* request,
7702 std::string* response_status,
7703 std::string* response_headers,
7704 std::string* response_data) {
7705 if (request->extra_headers.HasHeader("X-Require-Mock-Auth") &&
7706 !request->extra_headers.HasHeader("Authorization")) {
7707 response_status->assign("HTTP/1.1 401 Unauthorized");
7708 response_headers->assign("WWW-Authenticate: Basic realm=\"mars\"\n");
7709 return;
7711 response_status->assign("HTTP/1.1 200 OK");
7714 TEST_F(HttpCacheStaleWhileRevalidateTest, RestartForAuth) {
7715 // Write to the cache.
7716 RunFixtureTransactionTest();
7718 EXPECT_EQ(1, transaction_count());
7720 // Now make the transaction require auth.
7721 transaction_.request_headers = "X-Require-Mock-Auth: dummy\r\n\r\n";
7722 transaction_.handler = SimpleMockAuthHandler;
7724 // Read back from the cache.
7725 RunFixtureTransactionTest();
7727 EXPECT_EQ(1, transaction_count());
7729 // Let the async request execute.
7730 base::RunLoop().RunUntilIdle();
7732 EXPECT_EQ(2, transaction_count());
7735 // Tests that we allow multiple simultaneous, non-overlapping transactions to
7736 // take place on a sparse entry.
7737 TEST(HttpCache, RangeGET_MultipleRequests) {
7738 MockHttpCache cache;
7740 // Create a transaction for bytes 0-9.
7741 MockHttpRequest request(kRangeGET_TransactionOK);
7742 MockTransaction transaction(kRangeGET_TransactionOK);
7743 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
7744 transaction.data = "rg: 00-09 ";
7745 AddMockTransaction(&transaction);
7747 TestCompletionCallback callback;
7748 scoped_ptr<HttpTransaction> trans;
7749 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
7750 EXPECT_EQ(OK, rv);
7751 ASSERT_TRUE(trans.get());
7753 // Start our transaction.
7754 trans->Start(&request, callback.callback(), BoundNetLog());
7756 // A second transaction on a different part of the file (the default
7757 // kRangeGET_TransactionOK requests 40-49) should not be blocked by
7758 // the already pending transaction.
7759 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
7761 // Let the first transaction complete.
7762 callback.WaitForResult();
7764 RemoveMockTransaction(&transaction);
7767 // Makes sure that a request stops using the cache when the response headers
7768 // with "Cache-Control: no-store" arrives. That means that another request for
7769 // the same URL can be processed before the response body of the original
7770 // request arrives.
7771 TEST(HttpCache, NoStoreResponseShouldNotBlockFollowingRequests) {
7772 MockHttpCache cache;
7773 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
7774 mock_transaction.response_headers = "Cache-Control: no-store\n";
7775 MockHttpRequest request(mock_transaction);
7777 scoped_ptr<Context> first(new Context);
7778 first->result = cache.CreateTransaction(&first->trans);
7779 ASSERT_EQ(OK, first->result);
7780 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
7781 first->result =
7782 first->trans->Start(&request, first->callback.callback(), BoundNetLog());
7783 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, first->trans->GetLoadState());
7785 base::MessageLoop::current()->RunUntilIdle();
7786 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
7787 ASSERT_TRUE(first->trans->GetResponseInfo());
7788 EXPECT_TRUE(first->trans->GetResponseInfo()->headers->HasHeaderValue(
7789 "Cache-Control", "no-store"));
7790 // Here we have read the response header but not read the response body yet.
7792 // Let us create the second (read) transaction.
7793 scoped_ptr<Context> second(new Context);
7794 second->result = cache.CreateTransaction(&second->trans);
7795 ASSERT_EQ(OK, second->result);
7796 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
7797 second->result = second->trans->Start(&request, second->callback.callback(),
7798 BoundNetLog());
7800 // Here the second transaction proceeds without reading the first body.
7801 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, second->trans->GetLoadState());
7802 base::MessageLoop::current()->RunUntilIdle();
7803 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
7804 ASSERT_TRUE(second->trans->GetResponseInfo());
7805 EXPECT_TRUE(second->trans->GetResponseInfo()->headers->HasHeaderValue(
7806 "Cache-Control", "no-store"));
7807 ReadAndVerifyTransaction(second->trans.get(), kSimpleGET_Transaction);
7810 } // namespace net