media: Add RAPPOR metrics for EME usage.
[chromium-blink-merge.git] / net / http / http_cache_unittest.cc
blobf490444356fb1240f22e71fc3f443d0815b3a86b
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/test_data_directory.h"
25 #include "net/base/upload_bytes_element_reader.h"
26 #include "net/cert/cert_status_flags.h"
27 #include "net/cert/x509_certificate.h"
28 #include "net/disk_cache/disk_cache.h"
29 #include "net/http/http_byte_range.h"
30 #include "net/http/http_cache_transaction.h"
31 #include "net/http/http_request_headers.h"
32 #include "net/http/http_request_info.h"
33 #include "net/http/http_response_headers.h"
34 #include "net/http/http_response_info.h"
35 #include "net/http/http_transaction.h"
36 #include "net/http/http_transaction_test_util.h"
37 #include "net/http/http_util.h"
38 #include "net/http/mock_http_cache.h"
39 #include "net/log/test_net_log.h"
40 #include "net/log/test_net_log_entry.h"
41 #include "net/log/test_net_log_util.h"
42 #include "net/socket/client_socket_handle.h"
43 #include "net/ssl/ssl_cert_request_info.h"
44 #include "net/ssl/ssl_connection_status_flags.h"
45 #include "net/test/cert_test_util.h"
46 #include "net/websockets/websocket_handshake_stream_base.h"
47 #include "testing/gtest/include/gtest/gtest.h"
49 using base::Time;
51 namespace net {
53 namespace {
55 // Tests the load timing values of a request that goes through a
56 // MockNetworkTransaction.
57 void TestLoadTimingNetworkRequest(const LoadTimingInfo& load_timing_info) {
58 EXPECT_FALSE(load_timing_info.socket_reused);
59 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
61 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
62 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
64 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
65 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
66 EXPECT_LE(load_timing_info.connect_timing.connect_end,
67 load_timing_info.send_start);
69 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
71 // Set by URLRequest / URLRequestHttpJob, at a higher level.
72 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
73 EXPECT_TRUE(load_timing_info.request_start.is_null());
74 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
77 // Tests the load timing values of a request that receives a cached response.
78 void TestLoadTimingCachedResponse(const LoadTimingInfo& load_timing_info) {
79 EXPECT_FALSE(load_timing_info.socket_reused);
80 EXPECT_EQ(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
82 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
83 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
85 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
87 // Only the send start / end times should be sent, and they should have the
88 // same value.
89 EXPECT_FALSE(load_timing_info.send_start.is_null());
90 EXPECT_EQ(load_timing_info.send_start, load_timing_info.send_end);
92 // Set by URLRequest / URLRequestHttpJob, at a higher level.
93 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
94 EXPECT_TRUE(load_timing_info.request_start.is_null());
95 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
98 class DeleteCacheCompletionCallback : public TestCompletionCallbackBase {
99 public:
100 explicit DeleteCacheCompletionCallback(MockHttpCache* cache)
101 : cache_(cache),
102 callback_(base::Bind(&DeleteCacheCompletionCallback::OnComplete,
103 base::Unretained(this))) {
106 const CompletionCallback& callback() const { return callback_; }
108 private:
109 void OnComplete(int result) {
110 delete cache_;
111 SetResult(result);
114 MockHttpCache* cache_;
115 CompletionCallback callback_;
117 DISALLOW_COPY_AND_ASSIGN(DeleteCacheCompletionCallback);
120 //-----------------------------------------------------------------------------
121 // helpers
123 void ReadAndVerifyTransaction(HttpTransaction* trans,
124 const MockTransaction& trans_info) {
125 std::string content;
126 int rv = ReadTransaction(trans, &content);
128 EXPECT_EQ(OK, rv);
129 std::string expected(trans_info.data);
130 EXPECT_EQ(expected, content);
133 void RunTransactionTestBase(HttpCache* cache,
134 const MockTransaction& trans_info,
135 const MockHttpRequest& request,
136 HttpResponseInfo* response_info,
137 const BoundNetLog& net_log,
138 LoadTimingInfo* load_timing_info,
139 int64* received_bytes) {
140 TestCompletionCallback callback;
142 // write to the cache
144 scoped_ptr<HttpTransaction> trans;
145 int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &trans);
146 EXPECT_EQ(OK, rv);
147 ASSERT_TRUE(trans.get());
149 rv = trans->Start(&request, callback.callback(), net_log);
150 if (rv == ERR_IO_PENDING)
151 rv = callback.WaitForResult();
152 ASSERT_EQ(trans_info.return_code, rv);
154 if (OK != rv)
155 return;
157 const HttpResponseInfo* response = trans->GetResponseInfo();
158 ASSERT_TRUE(response);
160 if (response_info)
161 *response_info = *response;
163 if (load_timing_info) {
164 // If a fake network connection is used, need a NetLog to get a fake socket
165 // ID.
166 EXPECT_TRUE(net_log.net_log());
167 *load_timing_info = LoadTimingInfo();
168 trans->GetLoadTimingInfo(load_timing_info);
171 ReadAndVerifyTransaction(trans.get(), trans_info);
173 if (received_bytes)
174 *received_bytes = trans->GetTotalReceivedBytes();
177 void RunTransactionTestWithRequest(HttpCache* cache,
178 const MockTransaction& trans_info,
179 const MockHttpRequest& request,
180 HttpResponseInfo* response_info) {
181 RunTransactionTestBase(cache, trans_info, request, response_info,
182 BoundNetLog(), NULL, NULL);
185 void RunTransactionTestAndGetTiming(HttpCache* cache,
186 const MockTransaction& trans_info,
187 const BoundNetLog& log,
188 LoadTimingInfo* load_timing_info) {
189 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
190 NULL, log, load_timing_info, NULL);
193 void RunTransactionTest(HttpCache* cache, const MockTransaction& trans_info) {
194 RunTransactionTestAndGetTiming(cache, trans_info, BoundNetLog(), NULL);
197 void RunTransactionTestWithLog(HttpCache* cache,
198 const MockTransaction& trans_info,
199 const BoundNetLog& log) {
200 RunTransactionTestAndGetTiming(cache, trans_info, log, NULL);
203 void RunTransactionTestWithResponseInfo(HttpCache* cache,
204 const MockTransaction& trans_info,
205 HttpResponseInfo* response) {
206 RunTransactionTestWithRequest(cache, trans_info, MockHttpRequest(trans_info),
207 response);
210 void RunTransactionTestWithResponseInfoAndGetTiming(
211 HttpCache* cache,
212 const MockTransaction& trans_info,
213 HttpResponseInfo* response,
214 const BoundNetLog& log,
215 LoadTimingInfo* load_timing_info) {
216 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
217 response, log, load_timing_info, NULL);
220 void RunTransactionTestWithResponse(HttpCache* cache,
221 const MockTransaction& trans_info,
222 std::string* response_headers) {
223 HttpResponseInfo response;
224 RunTransactionTestWithResponseInfo(cache, trans_info, &response);
225 response.headers->GetNormalizedHeaders(response_headers);
228 void RunTransactionTestWithResponseAndGetTiming(
229 HttpCache* cache,
230 const MockTransaction& trans_info,
231 std::string* response_headers,
232 const BoundNetLog& log,
233 LoadTimingInfo* load_timing_info) {
234 HttpResponseInfo response;
235 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
236 &response, log, load_timing_info, NULL);
237 response.headers->GetNormalizedHeaders(response_headers);
240 // This class provides a handler for kFastNoStoreGET_Transaction so that the
241 // no-store header can be included on demand.
242 class FastTransactionServer {
243 public:
244 FastTransactionServer() {
245 no_store = false;
247 ~FastTransactionServer() {}
249 void set_no_store(bool value) { no_store = value; }
251 static void FastNoStoreHandler(const HttpRequestInfo* request,
252 std::string* response_status,
253 std::string* response_headers,
254 std::string* response_data) {
255 if (no_store)
256 *response_headers = "Cache-Control: no-store\n";
259 private:
260 static bool no_store;
261 DISALLOW_COPY_AND_ASSIGN(FastTransactionServer);
263 bool FastTransactionServer::no_store;
265 const MockTransaction kFastNoStoreGET_Transaction = {
266 "http://www.google.com/nostore",
267 "GET",
268 base::Time(),
270 LOAD_VALIDATE_CACHE,
271 "HTTP/1.1 200 OK",
272 "Cache-Control: max-age=10000\n",
273 base::Time(),
274 "<html><body>Google Blah Blah</body></html>",
275 TEST_MODE_SYNC_NET_START,
276 &FastTransactionServer::FastNoStoreHandler,
277 nullptr,
280 OK};
282 // This class provides a handler for kRangeGET_TransactionOK so that the range
283 // request can be served on demand.
284 class RangeTransactionServer {
285 public:
286 RangeTransactionServer() {
287 not_modified_ = false;
288 modified_ = false;
289 bad_200_ = false;
291 ~RangeTransactionServer() {
292 not_modified_ = false;
293 modified_ = false;
294 bad_200_ = false;
297 // Returns only 416 or 304 when set.
298 void set_not_modified(bool value) { not_modified_ = value; }
300 // Returns 206 when revalidating a range (instead of 304).
301 void set_modified(bool value) { modified_ = value; }
303 // Returns 200 instead of 206 (a malformed response overall).
304 void set_bad_200(bool value) { bad_200_ = value; }
306 // Other than regular range related behavior (and the flags mentioned above),
307 // the server reacts to requests headers like so:
308 // X-Require-Mock-Auth -> return 401.
309 // X-Require-Mock-Auth-Alt -> return 401.
310 // X-Return-Default-Range -> assume 40-49 was requested.
311 // The -Alt variant doesn't cause the MockNetworkTransaction to
312 // report that it IsReadyToRestartForAuth().
313 static void RangeHandler(const HttpRequestInfo* request,
314 std::string* response_status,
315 std::string* response_headers,
316 std::string* response_data);
318 private:
319 static bool not_modified_;
320 static bool modified_;
321 static bool bad_200_;
322 DISALLOW_COPY_AND_ASSIGN(RangeTransactionServer);
324 bool RangeTransactionServer::not_modified_ = false;
325 bool RangeTransactionServer::modified_ = false;
326 bool RangeTransactionServer::bad_200_ = false;
328 // A dummy extra header that must be preserved on a given request.
330 // EXTRA_HEADER_LINE doesn't include a line terminator because it
331 // will be passed to AddHeaderFromString() which doesn't accept them.
332 #define EXTRA_HEADER_LINE "Extra: header"
334 // EXTRA_HEADER contains a line terminator, as expected by
335 // AddHeadersFromString() (_not_ AddHeaderFromString()).
336 #define EXTRA_HEADER EXTRA_HEADER_LINE "\r\n"
338 static const char kExtraHeaderKey[] = "Extra";
340 // Static.
341 void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request,
342 std::string* response_status,
343 std::string* response_headers,
344 std::string* response_data) {
345 if (request->extra_headers.IsEmpty()) {
346 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
347 response_data->clear();
348 return;
351 // We want to make sure we don't delete extra headers.
352 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
354 bool require_auth =
355 request->extra_headers.HasHeader("X-Require-Mock-Auth") ||
356 request->extra_headers.HasHeader("X-Require-Mock-Auth-Alt");
358 if (require_auth && !request->extra_headers.HasHeader("Authorization")) {
359 response_status->assign("HTTP/1.1 401 Unauthorized");
360 response_data->assign("WWW-Authenticate: Foo\n");
361 return;
364 if (not_modified_) {
365 response_status->assign("HTTP/1.1 304 Not Modified");
366 response_data->clear();
367 return;
370 std::vector<HttpByteRange> ranges;
371 std::string range_header;
372 if (!request->extra_headers.GetHeader(HttpRequestHeaders::kRange,
373 &range_header) ||
374 !HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ ||
375 ranges.size() != 1) {
376 // This is not a byte range request. We return 200.
377 response_status->assign("HTTP/1.1 200 OK");
378 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT");
379 response_data->assign("Not a range");
380 return;
383 // We can handle this range request.
384 HttpByteRange byte_range = ranges[0];
386 if (request->extra_headers.HasHeader("X-Return-Default-Range")) {
387 byte_range.set_first_byte_position(40);
388 byte_range.set_last_byte_position(49);
391 if (byte_range.first_byte_position() > 79) {
392 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
393 response_data->clear();
394 return;
397 EXPECT_TRUE(byte_range.ComputeBounds(80));
398 int start = static_cast<int>(byte_range.first_byte_position());
399 int end = static_cast<int>(byte_range.last_byte_position());
401 EXPECT_LT(end, 80);
403 std::string content_range = base::StringPrintf(
404 "Content-Range: bytes %d-%d/80\n", start, end);
405 response_headers->append(content_range);
407 if (!request->extra_headers.HasHeader("If-None-Match") || modified_) {
408 std::string data;
409 if (end == start) {
410 EXPECT_EQ(0, end % 10);
411 data = "r";
412 } else {
413 EXPECT_EQ(9, (end - start) % 10);
414 for (int block_start = start; block_start < end; block_start += 10) {
415 base::StringAppendF(&data, "rg: %02d-%02d ",
416 block_start, block_start + 9);
419 *response_data = data;
421 if (end - start != 9) {
422 // We also have to fix content-length.
423 int len = end - start + 1;
424 std::string content_length = base::StringPrintf("Content-Length: %d\n",
425 len);
426 response_headers->replace(response_headers->find("Content-Length:"),
427 content_length.size(), content_length);
429 } else {
430 response_status->assign("HTTP/1.1 304 Not Modified");
431 response_data->clear();
435 const MockTransaction kRangeGET_TransactionOK = {
436 "http://www.google.com/range",
437 "GET",
438 base::Time(),
439 "Range: bytes = 40-49\r\n" EXTRA_HEADER,
440 LOAD_NORMAL,
441 "HTTP/1.1 206 Partial Content",
442 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
443 "ETag: \"foo\"\n"
444 "Accept-Ranges: bytes\n"
445 "Content-Length: 10\n",
446 base::Time(),
447 "rg: 40-49 ",
448 TEST_MODE_NORMAL,
449 &RangeTransactionServer::RangeHandler,
450 nullptr,
453 OK};
455 const char kFullRangeData[] =
456 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 "
457 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 ";
459 // Verifies the response headers (|response|) match a partial content
460 // response for the range starting at |start| and ending at |end|.
461 void Verify206Response(std::string response, int start, int end) {
462 std::string raw_headers(
463 HttpUtil::AssembleRawHeaders(response.data(), response.size()));
464 scoped_refptr<HttpResponseHeaders> headers(
465 new HttpResponseHeaders(raw_headers));
467 ASSERT_EQ(206, headers->response_code());
469 int64 range_start, range_end, object_size;
470 ASSERT_TRUE(
471 headers->GetContentRange(&range_start, &range_end, &object_size));
472 int64 content_length = headers->GetContentLength();
474 int length = end - start + 1;
475 ASSERT_EQ(length, content_length);
476 ASSERT_EQ(start, range_start);
477 ASSERT_EQ(end, range_end);
480 // Creates a truncated entry that can be resumed using byte ranges.
481 void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) {
482 // Create a disk cache entry that stores an incomplete resource.
483 disk_cache::Entry* entry;
484 ASSERT_TRUE(cache->CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
485 NULL));
487 raw_headers =
488 HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size());
490 HttpResponseInfo response;
491 response.response_time = base::Time::Now();
492 response.request_time = base::Time::Now();
493 response.headers = new HttpResponseHeaders(raw_headers);
494 // Set the last argument for this to be an incomplete request.
495 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
497 scoped_refptr<IOBuffer> buf(new IOBuffer(100));
498 int len = static_cast<int>(base::strlcpy(buf->data(),
499 "rg: 00-09 rg: 10-19 ", 100));
500 TestCompletionCallback cb;
501 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
502 EXPECT_EQ(len, cb.GetResult(rv));
503 entry->Close();
506 // Helper to represent a network HTTP response.
507 struct Response {
508 // Set this response into |trans|.
509 void AssignTo(MockTransaction* trans) const {
510 trans->status = status;
511 trans->response_headers = headers;
512 trans->data = body;
515 std::string status_and_headers() const {
516 return std::string(status) + "\n" + std::string(headers);
519 const char* status;
520 const char* headers;
521 const char* body;
524 struct Context {
525 Context() : result(ERR_IO_PENDING) {}
527 int result;
528 TestCompletionCallback callback;
529 scoped_ptr<HttpTransaction> trans;
532 class FakeWebSocketHandshakeStreamCreateHelper
533 : public WebSocketHandshakeStreamBase::CreateHelper {
534 public:
535 ~FakeWebSocketHandshakeStreamCreateHelper() override {}
536 WebSocketHandshakeStreamBase* CreateBasicStream(
537 scoped_ptr<ClientSocketHandle> connect,
538 bool using_proxy) override {
539 return NULL;
541 WebSocketHandshakeStreamBase* CreateSpdyStream(
542 const base::WeakPtr<SpdySession>& session,
543 bool use_relative_url) override {
544 return NULL;
548 // Returns true if |entry| is not one of the log types paid attention to in this
549 // test. Note that TYPE_HTTP_CACHE_WRITE_INFO and TYPE_HTTP_CACHE_*_DATA are
550 // ignored.
551 bool ShouldIgnoreLogEntry(const TestNetLogEntry& entry) {
552 switch (entry.type) {
553 case NetLog::TYPE_HTTP_CACHE_GET_BACKEND:
554 case NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY:
555 case NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY:
556 case NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY:
557 case NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY:
558 case NetLog::TYPE_HTTP_CACHE_READ_INFO:
559 return false;
560 default:
561 return true;
565 // Modifies |entries| to only include log entries created by the cache layer and
566 // asserted on in these tests.
567 void FilterLogEntries(TestNetLogEntry::List* entries) {
568 entries->erase(std::remove_if(entries->begin(), entries->end(),
569 &ShouldIgnoreLogEntry),
570 entries->end());
573 bool LogContainsEventType(const BoundTestNetLog& log,
574 NetLog::EventType expected) {
575 TestNetLogEntry::List entries;
576 log.GetEntries(&entries);
577 for (size_t i = 0; i < entries.size(); i++) {
578 if (entries[i].type == expected)
579 return true;
581 return false;
584 } // namespace
587 //-----------------------------------------------------------------------------
588 // Tests.
590 TEST(HttpCache, CreateThenDestroy) {
591 MockHttpCache cache;
593 scoped_ptr<HttpTransaction> trans;
594 EXPECT_EQ(OK, cache.CreateTransaction(&trans));
595 ASSERT_TRUE(trans.get());
598 TEST(HttpCache, GetBackend) {
599 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(0));
601 disk_cache::Backend* backend;
602 TestCompletionCallback cb;
603 // This will lazily initialize the backend.
604 int rv = cache.http_cache()->GetBackend(&backend, cb.callback());
605 EXPECT_EQ(OK, cb.GetResult(rv));
608 TEST(HttpCache, SimpleGET) {
609 MockHttpCache cache;
610 BoundTestNetLog log;
611 LoadTimingInfo load_timing_info;
613 // Write to the cache.
614 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
615 log.bound(), &load_timing_info);
617 EXPECT_EQ(1, cache.network_layer()->transaction_count());
618 EXPECT_EQ(0, cache.disk_cache()->open_count());
619 EXPECT_EQ(1, cache.disk_cache()->create_count());
620 TestLoadTimingNetworkRequest(load_timing_info);
623 TEST(HttpCache, SimpleGETNoDiskCache) {
624 MockHttpCache cache;
626 cache.disk_cache()->set_fail_requests();
628 BoundTestNetLog log;
629 LoadTimingInfo load_timing_info;
631 // Read from the network, and don't use the cache.
632 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
633 log.bound(), &load_timing_info);
635 // Check that the NetLog was filled as expected.
636 // (We attempted to both Open and Create entries, but both failed).
637 TestNetLogEntry::List entries;
638 log.GetEntries(&entries);
639 FilterLogEntries(&entries);
641 EXPECT_EQ(6u, entries.size());
642 EXPECT_TRUE(
643 LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
644 EXPECT_TRUE(
645 LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
646 EXPECT_TRUE(
647 LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
648 EXPECT_TRUE(
649 LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
650 EXPECT_TRUE(
651 LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
652 EXPECT_TRUE(
653 LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
655 EXPECT_EQ(1, cache.network_layer()->transaction_count());
656 EXPECT_EQ(0, cache.disk_cache()->open_count());
657 EXPECT_EQ(0, cache.disk_cache()->create_count());
658 TestLoadTimingNetworkRequest(load_timing_info);
661 TEST(HttpCache, SimpleGETNoDiskCache2) {
662 // This will initialize a cache object with NULL backend.
663 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
664 factory->set_fail(true);
665 factory->FinishCreation(); // We'll complete synchronously.
666 MockHttpCache cache(factory);
668 // Read from the network, and don't use the cache.
669 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
671 EXPECT_EQ(1, cache.network_layer()->transaction_count());
672 EXPECT_FALSE(cache.http_cache()->GetCurrentBackend());
675 // Tests that IOBuffers are not referenced after IO completes.
676 TEST(HttpCache, ReleaseBuffer) {
677 MockHttpCache cache;
679 // Write to the cache.
680 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
682 MockHttpRequest request(kSimpleGET_Transaction);
683 scoped_ptr<HttpTransaction> trans;
684 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
686 const int kBufferSize = 10;
687 scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
688 ReleaseBufferCompletionCallback cb(buffer.get());
690 int rv = trans->Start(&request, cb.callback(), BoundNetLog());
691 EXPECT_EQ(OK, cb.GetResult(rv));
693 rv = trans->Read(buffer.get(), kBufferSize, cb.callback());
694 EXPECT_EQ(kBufferSize, cb.GetResult(rv));
697 TEST(HttpCache, SimpleGETWithDiskFailures) {
698 MockHttpCache cache;
700 cache.disk_cache()->set_soft_failures(true);
702 // Read from the network, and fail to write to the cache.
703 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
705 EXPECT_EQ(1, cache.network_layer()->transaction_count());
706 EXPECT_EQ(0, cache.disk_cache()->open_count());
707 EXPECT_EQ(1, cache.disk_cache()->create_count());
709 // This one should see an empty cache again.
710 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
712 EXPECT_EQ(2, cache.network_layer()->transaction_count());
713 EXPECT_EQ(0, cache.disk_cache()->open_count());
714 EXPECT_EQ(2, cache.disk_cache()->create_count());
717 // Tests that disk failures after the transaction has started don't cause the
718 // request to fail.
719 TEST(HttpCache, SimpleGETWithDiskFailures2) {
720 MockHttpCache cache;
722 MockHttpRequest request(kSimpleGET_Transaction);
724 scoped_ptr<Context> c(new Context());
725 int rv = cache.CreateTransaction(&c->trans);
726 ASSERT_EQ(OK, rv);
728 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
729 EXPECT_EQ(ERR_IO_PENDING, rv);
730 rv = c->callback.WaitForResult();
732 // Start failing request now.
733 cache.disk_cache()->set_soft_failures(true);
735 // We have to open the entry again to propagate the failure flag.
736 disk_cache::Entry* en;
737 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &en));
738 en->Close();
740 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
741 c.reset();
743 EXPECT_EQ(1, cache.network_layer()->transaction_count());
744 EXPECT_EQ(1, cache.disk_cache()->open_count());
745 EXPECT_EQ(1, cache.disk_cache()->create_count());
747 // This one should see an empty cache again.
748 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
750 EXPECT_EQ(2, cache.network_layer()->transaction_count());
751 EXPECT_EQ(1, cache.disk_cache()->open_count());
752 EXPECT_EQ(2, cache.disk_cache()->create_count());
755 // Tests that we handle failures to read from the cache.
756 TEST(HttpCache, SimpleGETWithDiskFailures3) {
757 MockHttpCache cache;
759 // Read from the network, and write to the cache.
760 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
762 EXPECT_EQ(1, cache.network_layer()->transaction_count());
763 EXPECT_EQ(0, cache.disk_cache()->open_count());
764 EXPECT_EQ(1, cache.disk_cache()->create_count());
766 cache.disk_cache()->set_soft_failures(true);
768 // Now fail to read from the cache.
769 scoped_ptr<Context> c(new Context());
770 int rv = cache.CreateTransaction(&c->trans);
771 ASSERT_EQ(OK, rv);
773 MockHttpRequest request(kSimpleGET_Transaction);
774 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
775 EXPECT_EQ(OK, c->callback.GetResult(rv));
777 // Now verify that the entry was removed from the cache.
778 cache.disk_cache()->set_soft_failures(false);
780 EXPECT_EQ(2, cache.network_layer()->transaction_count());
781 EXPECT_EQ(1, cache.disk_cache()->open_count());
782 EXPECT_EQ(2, cache.disk_cache()->create_count());
784 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
786 EXPECT_EQ(3, cache.network_layer()->transaction_count());
787 EXPECT_EQ(1, cache.disk_cache()->open_count());
788 EXPECT_EQ(3, cache.disk_cache()->create_count());
791 TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) {
792 MockHttpCache cache;
794 BoundTestNetLog log;
795 LoadTimingInfo load_timing_info;
797 // Write to the cache.
798 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
799 log.bound(), &load_timing_info);
801 // Check that the NetLog was filled as expected.
802 TestNetLogEntry::List entries;
803 log.GetEntries(&entries);
804 FilterLogEntries(&entries);
806 EXPECT_EQ(8u, entries.size());
807 EXPECT_TRUE(
808 LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
809 EXPECT_TRUE(
810 LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
811 EXPECT_TRUE(
812 LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
813 EXPECT_TRUE(
814 LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
815 EXPECT_TRUE(
816 LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
817 EXPECT_TRUE(
818 LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
819 EXPECT_TRUE(
820 LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
821 EXPECT_TRUE(
822 LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
824 TestLoadTimingNetworkRequest(load_timing_info);
826 // Force this transaction to read from the cache.
827 MockTransaction transaction(kSimpleGET_Transaction);
828 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
830 log.Clear();
832 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
833 &load_timing_info);
835 // Check that the NetLog was filled as expected.
836 log.GetEntries(&entries);
837 FilterLogEntries(&entries);
839 EXPECT_EQ(8u, entries.size());
840 EXPECT_TRUE(
841 LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
842 EXPECT_TRUE(
843 LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
844 EXPECT_TRUE(
845 LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
846 EXPECT_TRUE(
847 LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY));
848 EXPECT_TRUE(
849 LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
850 EXPECT_TRUE(
851 LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
852 EXPECT_TRUE(
853 LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_READ_INFO));
854 EXPECT_TRUE(
855 LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_READ_INFO));
857 EXPECT_EQ(1, cache.network_layer()->transaction_count());
858 EXPECT_EQ(1, cache.disk_cache()->open_count());
859 EXPECT_EQ(1, cache.disk_cache()->create_count());
860 TestLoadTimingCachedResponse(load_timing_info);
863 TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Miss) {
864 MockHttpCache cache;
866 // force this transaction to read from the cache
867 MockTransaction transaction(kSimpleGET_Transaction);
868 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
870 MockHttpRequest request(transaction);
871 TestCompletionCallback callback;
873 scoped_ptr<HttpTransaction> trans;
874 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
876 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
877 if (rv == ERR_IO_PENDING)
878 rv = callback.WaitForResult();
879 ASSERT_EQ(ERR_CACHE_MISS, rv);
881 trans.reset();
883 EXPECT_EQ(0, cache.network_layer()->transaction_count());
884 EXPECT_EQ(0, cache.disk_cache()->open_count());
885 EXPECT_EQ(0, cache.disk_cache()->create_count());
888 TEST(HttpCache, SimpleGET_LoadPreferringCache_Hit) {
889 MockHttpCache cache;
891 // write to the cache
892 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
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(1, cache.disk_cache()->open_count());
902 EXPECT_EQ(1, cache.disk_cache()->create_count());
905 TEST(HttpCache, SimpleGET_LoadPreferringCache_Miss) {
906 MockHttpCache cache;
908 // force this transaction to read from the cache if valid
909 MockTransaction transaction(kSimpleGET_Transaction);
910 transaction.load_flags |= LOAD_PREFERRING_CACHE;
912 RunTransactionTest(cache.http_cache(), transaction);
914 EXPECT_EQ(1, cache.network_layer()->transaction_count());
915 EXPECT_EQ(0, cache.disk_cache()->open_count());
916 EXPECT_EQ(1, cache.disk_cache()->create_count());
919 // Tests LOAD_PREFERRING_CACHE in the presence of vary headers.
920 TEST(HttpCache, SimpleGET_LoadPreferringCache_VaryMatch) {
921 MockHttpCache cache;
923 // Write to the cache.
924 MockTransaction transaction(kSimpleGET_Transaction);
925 transaction.request_headers = "Foo: bar\r\n";
926 transaction.response_headers = "Cache-Control: max-age=10000\n"
927 "Vary: Foo\n";
928 AddMockTransaction(&transaction);
929 RunTransactionTest(cache.http_cache(), transaction);
931 // Read from the cache.
932 transaction.load_flags |= LOAD_PREFERRING_CACHE;
933 RunTransactionTest(cache.http_cache(), transaction);
935 EXPECT_EQ(1, cache.network_layer()->transaction_count());
936 EXPECT_EQ(1, cache.disk_cache()->open_count());
937 EXPECT_EQ(1, cache.disk_cache()->create_count());
938 RemoveMockTransaction(&transaction);
941 // Tests LOAD_PREFERRING_CACHE in the presence of vary headers.
942 TEST(HttpCache, SimpleGET_LoadPreferringCache_VaryMismatch) {
943 MockHttpCache cache;
945 // Write to the cache.
946 MockTransaction transaction(kSimpleGET_Transaction);
947 transaction.request_headers = "Foo: bar\r\n";
948 transaction.response_headers = "Cache-Control: max-age=10000\n"
949 "Vary: Foo\n";
950 AddMockTransaction(&transaction);
951 RunTransactionTest(cache.http_cache(), transaction);
953 // Attempt to read from the cache... this is a vary mismatch that must reach
954 // the network again.
955 transaction.load_flags |= LOAD_PREFERRING_CACHE;
956 transaction.request_headers = "Foo: none\r\n";
957 BoundTestNetLog log;
958 LoadTimingInfo load_timing_info;
959 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
960 &load_timing_info);
962 EXPECT_EQ(2, cache.network_layer()->transaction_count());
963 EXPECT_EQ(1, cache.disk_cache()->open_count());
964 EXPECT_EQ(1, cache.disk_cache()->create_count());
965 TestLoadTimingNetworkRequest(load_timing_info);
966 RemoveMockTransaction(&transaction);
969 // Tests that was_cached was set properly on a failure, even if the cached
970 // response wasn't returned.
971 TEST(HttpCache, SimpleGET_CacheSignal_Failure) {
972 MockHttpCache cache;
974 // Prime cache.
975 MockTransaction transaction(kSimpleGET_Transaction);
976 transaction.response_headers = "Cache-Control: no-cache\n";
978 AddMockTransaction(&transaction);
979 RunTransactionTest(cache.http_cache(), transaction);
980 EXPECT_EQ(1, cache.network_layer()->transaction_count());
981 EXPECT_EQ(1, cache.disk_cache()->create_count());
982 RemoveMockTransaction(&transaction);
984 // Network failure with error; should fail but have was_cached set.
985 transaction.return_code = ERR_FAILED;
986 AddMockTransaction(&transaction);
988 MockHttpRequest request(transaction);
989 TestCompletionCallback callback;
990 scoped_ptr<HttpTransaction> trans;
991 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
992 EXPECT_EQ(OK, rv);
993 ASSERT_TRUE(trans.get());
994 rv = trans->Start(&request, callback.callback(), BoundNetLog());
995 EXPECT_EQ(ERR_FAILED, callback.GetResult(rv));
997 const HttpResponseInfo* response_info = trans->GetResponseInfo();
998 ASSERT_TRUE(response_info);
999 EXPECT_TRUE(response_info->was_cached);
1000 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1002 RemoveMockTransaction(&transaction);
1005 // Confirm if we have an empty cache, a read is marked as network verified.
1006 TEST(HttpCache, SimpleGET_NetworkAccessed_Network) {
1007 MockHttpCache cache;
1009 // write to the cache
1010 HttpResponseInfo response_info;
1011 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
1012 &response_info);
1014 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1015 EXPECT_EQ(0, cache.disk_cache()->open_count());
1016 EXPECT_EQ(1, cache.disk_cache()->create_count());
1017 EXPECT_TRUE(response_info.network_accessed);
1020 // Confirm if we have a fresh entry in cache, it isn't marked as
1021 // network verified.
1022 TEST(HttpCache, SimpleGET_NetworkAccessed_Cache) {
1023 MockHttpCache cache;
1025 // Prime cache.
1026 MockTransaction transaction(kSimpleGET_Transaction);
1028 RunTransactionTest(cache.http_cache(), transaction);
1029 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1030 EXPECT_EQ(1, cache.disk_cache()->create_count());
1032 // Re-run transaction; make sure we don't mark the network as accessed.
1033 HttpResponseInfo response_info;
1034 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
1035 &response_info);
1037 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1038 EXPECT_FALSE(response_info.server_data_unavailable);
1039 EXPECT_FALSE(response_info.network_accessed);
1042 TEST(HttpCache, SimpleGET_LoadBypassCache) {
1043 MockHttpCache cache;
1045 // Write to the cache.
1046 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1048 // Force this transaction to write to the cache again.
1049 MockTransaction transaction(kSimpleGET_Transaction);
1050 transaction.load_flags |= LOAD_BYPASS_CACHE;
1052 BoundTestNetLog log;
1053 LoadTimingInfo load_timing_info;
1055 // Write to the cache.
1056 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
1057 &load_timing_info);
1059 // Check that the NetLog was filled as expected.
1060 TestNetLogEntry::List entries;
1061 log.GetEntries(&entries);
1062 FilterLogEntries(&entries);
1064 EXPECT_EQ(8u, entries.size());
1065 EXPECT_TRUE(
1066 LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1067 EXPECT_TRUE(
1068 LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND));
1069 EXPECT_TRUE(
1070 LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
1071 EXPECT_TRUE(
1072 LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY));
1073 EXPECT_TRUE(
1074 LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1075 EXPECT_TRUE(
1076 LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY));
1077 EXPECT_TRUE(
1078 LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1079 EXPECT_TRUE(
1080 LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY));
1082 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1083 EXPECT_EQ(0, cache.disk_cache()->open_count());
1084 EXPECT_EQ(2, cache.disk_cache()->create_count());
1085 TestLoadTimingNetworkRequest(load_timing_info);
1088 TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit) {
1089 MockHttpCache cache;
1091 // write to the cache
1092 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1094 // force this transaction to write to the cache again
1095 MockTransaction transaction(kSimpleGET_Transaction);
1096 transaction.request_headers = "pragma: no-cache\r\n";
1098 RunTransactionTest(cache.http_cache(), transaction);
1100 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1101 EXPECT_EQ(0, cache.disk_cache()->open_count());
1102 EXPECT_EQ(2, cache.disk_cache()->create_count());
1105 TEST(HttpCache, SimpleGET_LoadBypassCache_Implicit2) {
1106 MockHttpCache cache;
1108 // write to the cache
1109 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1111 // force this transaction to write to the cache again
1112 MockTransaction transaction(kSimpleGET_Transaction);
1113 transaction.request_headers = "cache-control: no-cache\r\n";
1115 RunTransactionTest(cache.http_cache(), transaction);
1117 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1118 EXPECT_EQ(0, cache.disk_cache()->open_count());
1119 EXPECT_EQ(2, cache.disk_cache()->create_count());
1122 TEST(HttpCache, SimpleGET_LoadValidateCache) {
1123 MockHttpCache cache;
1125 // Write to the cache.
1126 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1128 // Read from the cache.
1129 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1131 // Force this transaction to validate the cache.
1132 MockTransaction transaction(kSimpleGET_Transaction);
1133 transaction.load_flags |= LOAD_VALIDATE_CACHE;
1135 HttpResponseInfo response_info;
1136 BoundTestNetLog log;
1137 LoadTimingInfo load_timing_info;
1138 RunTransactionTestWithResponseInfoAndGetTiming(
1139 cache.http_cache(), transaction, &response_info, log.bound(),
1140 &load_timing_info);
1142 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1143 EXPECT_EQ(1, cache.disk_cache()->open_count());
1144 EXPECT_EQ(1, cache.disk_cache()->create_count());
1145 EXPECT_TRUE(response_info.network_accessed);
1146 TestLoadTimingNetworkRequest(load_timing_info);
1149 TEST(HttpCache, SimpleGET_LoadValidateCache_Implicit) {
1150 MockHttpCache cache;
1152 // write to the cache
1153 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1155 // read from the cache
1156 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1158 // force this transaction to validate the cache
1159 MockTransaction transaction(kSimpleGET_Transaction);
1160 transaction.request_headers = "cache-control: max-age=0\r\n";
1162 RunTransactionTest(cache.http_cache(), transaction);
1164 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1165 EXPECT_EQ(1, cache.disk_cache()->open_count());
1166 EXPECT_EQ(1, cache.disk_cache()->create_count());
1169 static void PreserveRequestHeaders_Handler(const HttpRequestInfo* request,
1170 std::string* response_status,
1171 std::string* response_headers,
1172 std::string* response_data) {
1173 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
1176 // Tests that we don't remove extra headers for simple requests.
1177 TEST(HttpCache, SimpleGET_PreserveRequestHeaders) {
1178 MockHttpCache cache;
1180 MockTransaction transaction(kSimpleGET_Transaction);
1181 transaction.handler = PreserveRequestHeaders_Handler;
1182 transaction.request_headers = EXTRA_HEADER;
1183 transaction.response_headers = "Cache-Control: max-age=0\n";
1184 AddMockTransaction(&transaction);
1186 // Write, then revalidate the entry.
1187 RunTransactionTest(cache.http_cache(), transaction);
1188 RunTransactionTest(cache.http_cache(), transaction);
1190 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1191 EXPECT_EQ(1, cache.disk_cache()->open_count());
1192 EXPECT_EQ(1, cache.disk_cache()->create_count());
1193 RemoveMockTransaction(&transaction);
1196 // Tests that we don't remove extra headers for conditionalized requests.
1197 TEST(HttpCache, ConditionalizedGET_PreserveRequestHeaders) {
1198 MockHttpCache cache;
1200 // Write to the cache.
1201 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
1203 MockTransaction transaction(kETagGET_Transaction);
1204 transaction.handler = PreserveRequestHeaders_Handler;
1205 transaction.request_headers = "If-None-Match: \"foopy\"\r\n"
1206 EXTRA_HEADER;
1207 AddMockTransaction(&transaction);
1209 RunTransactionTest(cache.http_cache(), transaction);
1211 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1212 EXPECT_EQ(1, cache.disk_cache()->open_count());
1213 EXPECT_EQ(1, cache.disk_cache()->create_count());
1214 RemoveMockTransaction(&transaction);
1217 TEST(HttpCache, SimpleGET_ManyReaders) {
1218 MockHttpCache cache;
1220 MockHttpRequest request(kSimpleGET_Transaction);
1222 std::vector<Context*> context_list;
1223 const int kNumTransactions = 5;
1225 for (int i = 0; i < kNumTransactions; ++i) {
1226 context_list.push_back(new Context());
1227 Context* c = context_list[i];
1229 c->result = cache.CreateTransaction(&c->trans);
1230 ASSERT_EQ(OK, c->result);
1231 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
1233 c->result =
1234 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1237 // All requests are waiting for the active entry.
1238 for (int i = 0; i < kNumTransactions; ++i) {
1239 Context* c = context_list[i];
1240 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
1243 // Allow all requests to move from the Create queue to the active entry.
1244 base::MessageLoop::current()->RunUntilIdle();
1246 // The first request should be a writer at this point, and the subsequent
1247 // requests should be pending.
1249 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1250 EXPECT_EQ(0, cache.disk_cache()->open_count());
1251 EXPECT_EQ(1, cache.disk_cache()->create_count());
1253 // All requests depend on the writer, and the writer is between Start and
1254 // Read, i.e. idle.
1255 for (int i = 0; i < kNumTransactions; ++i) {
1256 Context* c = context_list[i];
1257 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
1260 for (int i = 0; i < kNumTransactions; ++i) {
1261 Context* c = context_list[i];
1262 if (c->result == ERR_IO_PENDING)
1263 c->result = c->callback.WaitForResult();
1264 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1267 // We should not have had to re-open the disk entry
1269 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1270 EXPECT_EQ(0, cache.disk_cache()->open_count());
1271 EXPECT_EQ(1, cache.disk_cache()->create_count());
1273 for (int i = 0; i < kNumTransactions; ++i) {
1274 Context* c = context_list[i];
1275 delete c;
1279 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4769.
1280 // If cancelling a request is racing with another request for the same resource
1281 // finishing, we have to make sure that we remove both transactions from the
1282 // entry.
1283 TEST(HttpCache, SimpleGET_RacingReaders) {
1284 MockHttpCache cache;
1286 MockHttpRequest request(kSimpleGET_Transaction);
1287 MockHttpRequest reader_request(kSimpleGET_Transaction);
1288 reader_request.load_flags = LOAD_ONLY_FROM_CACHE;
1290 std::vector<Context*> context_list;
1291 const int kNumTransactions = 5;
1293 for (int i = 0; i < kNumTransactions; ++i) {
1294 context_list.push_back(new Context());
1295 Context* c = context_list[i];
1297 c->result = cache.CreateTransaction(&c->trans);
1298 ASSERT_EQ(OK, c->result);
1300 MockHttpRequest* this_request = &request;
1301 if (i == 1 || i == 2)
1302 this_request = &reader_request;
1304 c->result =
1305 c->trans->Start(this_request, c->callback.callback(), BoundNetLog());
1308 // Allow all requests to move from the Create queue to the active entry.
1309 base::MessageLoop::current()->RunUntilIdle();
1311 // The first request should be a writer at this point, and the subsequent
1312 // requests should be pending.
1314 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1315 EXPECT_EQ(0, cache.disk_cache()->open_count());
1316 EXPECT_EQ(1, cache.disk_cache()->create_count());
1318 Context* c = context_list[0];
1319 ASSERT_EQ(ERR_IO_PENDING, c->result);
1320 c->result = c->callback.WaitForResult();
1321 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1323 // Now we have 2 active readers and two queued transactions.
1325 EXPECT_EQ(LOAD_STATE_IDLE, context_list[2]->trans->GetLoadState());
1326 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE,
1327 context_list[3]->trans->GetLoadState());
1329 c = context_list[1];
1330 ASSERT_EQ(ERR_IO_PENDING, c->result);
1331 c->result = c->callback.WaitForResult();
1332 if (c->result == OK)
1333 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1335 // At this point we have one reader, two pending transactions and a task on
1336 // the queue to move to the next transaction. Now we cancel the request that
1337 // is the current reader, and expect the queued task to be able to start the
1338 // next request.
1340 c = context_list[2];
1341 c->trans.reset();
1343 for (int i = 3; i < kNumTransactions; ++i) {
1344 Context* c = context_list[i];
1345 if (c->result == ERR_IO_PENDING)
1346 c->result = c->callback.WaitForResult();
1347 if (c->result == OK)
1348 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1351 // We should not have had to re-open the disk entry.
1353 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1354 EXPECT_EQ(0, cache.disk_cache()->open_count());
1355 EXPECT_EQ(1, cache.disk_cache()->create_count());
1357 for (int i = 0; i < kNumTransactions; ++i) {
1358 Context* c = context_list[i];
1359 delete c;
1363 // Tests that we can doom an entry with pending transactions and delete one of
1364 // the pending transactions before the first one completes.
1365 // See http://code.google.com/p/chromium/issues/detail?id=25588
1366 TEST(HttpCache, SimpleGET_DoomWithPending) {
1367 // We need simultaneous doomed / not_doomed entries so let's use a real cache.
1368 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
1370 MockHttpRequest request(kSimpleGET_Transaction);
1371 MockHttpRequest writer_request(kSimpleGET_Transaction);
1372 writer_request.load_flags = LOAD_BYPASS_CACHE;
1374 ScopedVector<Context> context_list;
1375 const int kNumTransactions = 4;
1377 for (int i = 0; i < kNumTransactions; ++i) {
1378 context_list.push_back(new Context());
1379 Context* c = context_list[i];
1381 c->result = cache.CreateTransaction(&c->trans);
1382 ASSERT_EQ(OK, c->result);
1384 MockHttpRequest* this_request = &request;
1385 if (i == 3)
1386 this_request = &writer_request;
1388 c->result =
1389 c->trans->Start(this_request, c->callback.callback(), BoundNetLog());
1392 // The first request should be a writer at this point, and the two subsequent
1393 // requests should be pending. The last request doomed the first entry.
1395 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1397 // Cancel the first queued transaction.
1398 delete context_list[1];
1399 context_list.get()[1] = NULL;
1401 for (int i = 0; i < kNumTransactions; ++i) {
1402 if (i == 1)
1403 continue;
1404 Context* c = context_list[i];
1405 ASSERT_EQ(ERR_IO_PENDING, c->result);
1406 c->result = c->callback.WaitForResult();
1407 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1411 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4731.
1412 // We may attempt to delete an entry synchronously with the act of adding a new
1413 // transaction to said entry.
1414 TEST(HttpCache, FastNoStoreGET_DoneWithPending) {
1415 MockHttpCache cache;
1417 // The headers will be served right from the call to Start() the request.
1418 MockHttpRequest request(kFastNoStoreGET_Transaction);
1419 FastTransactionServer request_handler;
1420 AddMockTransaction(&kFastNoStoreGET_Transaction);
1422 std::vector<Context*> context_list;
1423 const int kNumTransactions = 3;
1425 for (int i = 0; i < kNumTransactions; ++i) {
1426 context_list.push_back(new Context());
1427 Context* c = context_list[i];
1429 c->result = cache.CreateTransaction(&c->trans);
1430 ASSERT_EQ(OK, c->result);
1432 c->result =
1433 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1436 // Allow all requests to move from the Create queue to the active entry.
1437 base::MessageLoop::current()->RunUntilIdle();
1439 // The first request should be a writer at this point, and the subsequent
1440 // requests should be pending.
1442 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1443 EXPECT_EQ(0, cache.disk_cache()->open_count());
1444 EXPECT_EQ(1, cache.disk_cache()->create_count());
1446 // Now, make sure that the second request asks for the entry not to be stored.
1447 request_handler.set_no_store(true);
1449 for (int i = 0; i < kNumTransactions; ++i) {
1450 Context* c = context_list[i];
1451 if (c->result == ERR_IO_PENDING)
1452 c->result = c->callback.WaitForResult();
1453 ReadAndVerifyTransaction(c->trans.get(), kFastNoStoreGET_Transaction);
1454 delete c;
1457 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1458 EXPECT_EQ(0, cache.disk_cache()->open_count());
1459 EXPECT_EQ(2, cache.disk_cache()->create_count());
1461 RemoveMockTransaction(&kFastNoStoreGET_Transaction);
1464 TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) {
1465 MockHttpCache cache;
1467 MockHttpRequest request(kSimpleGET_Transaction);
1469 std::vector<Context*> context_list;
1470 const int kNumTransactions = 2;
1472 for (int i = 0; i < kNumTransactions; ++i) {
1473 context_list.push_back(new Context());
1474 Context* c = context_list[i];
1476 c->result = cache.CreateTransaction(&c->trans);
1477 ASSERT_EQ(OK, c->result);
1479 c->result =
1480 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1483 // Allow all requests to move from the Create queue to the active entry.
1484 base::MessageLoop::current()->RunUntilIdle();
1486 // The first request should be a writer at this point, and the subsequent
1487 // requests should be pending.
1489 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1490 EXPECT_EQ(0, cache.disk_cache()->open_count());
1491 EXPECT_EQ(1, cache.disk_cache()->create_count());
1493 for (int i = 0; i < kNumTransactions; ++i) {
1494 Context* c = context_list[i];
1495 if (c->result == ERR_IO_PENDING)
1496 c->result = c->callback.WaitForResult();
1497 // Destroy only the first transaction.
1498 if (i == 0) {
1499 delete c;
1500 context_list[i] = NULL;
1504 // Complete the rest of the transactions.
1505 for (int i = 1; i < kNumTransactions; ++i) {
1506 Context* c = context_list[i];
1507 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1510 // We should have had to re-open the disk entry.
1512 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1513 EXPECT_EQ(0, cache.disk_cache()->open_count());
1514 EXPECT_EQ(2, cache.disk_cache()->create_count());
1516 for (int i = 1; i < kNumTransactions; ++i) {
1517 Context* c = context_list[i];
1518 delete c;
1522 // Tests that we can cancel requests that are queued waiting to open the disk
1523 // cache entry.
1524 TEST(HttpCache, SimpleGET_ManyWriters_CancelCreate) {
1525 MockHttpCache cache;
1527 MockHttpRequest request(kSimpleGET_Transaction);
1529 std::vector<Context*> context_list;
1530 const int kNumTransactions = 5;
1532 for (int i = 0; i < kNumTransactions; i++) {
1533 context_list.push_back(new Context());
1534 Context* c = context_list[i];
1536 c->result = cache.CreateTransaction(&c->trans);
1537 ASSERT_EQ(OK, c->result);
1539 c->result =
1540 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1543 // The first request should be creating the disk cache entry and the others
1544 // should be pending.
1546 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1547 EXPECT_EQ(0, cache.disk_cache()->open_count());
1548 EXPECT_EQ(1, cache.disk_cache()->create_count());
1550 // Cancel a request from the pending queue.
1551 delete context_list[3];
1552 context_list[3] = NULL;
1554 // Cancel the request that is creating the entry. This will force the pending
1555 // operations to restart.
1556 delete context_list[0];
1557 context_list[0] = NULL;
1559 // Complete the rest of the transactions.
1560 for (int i = 1; i < kNumTransactions; i++) {
1561 Context* c = context_list[i];
1562 if (c) {
1563 c->result = c->callback.GetResult(c->result);
1564 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1568 // We should have had to re-create the disk entry.
1570 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1571 EXPECT_EQ(0, cache.disk_cache()->open_count());
1572 EXPECT_EQ(2, cache.disk_cache()->create_count());
1574 for (int i = 1; i < kNumTransactions; ++i) {
1575 delete context_list[i];
1579 // Tests that we can cancel a single request to open a disk cache entry.
1580 TEST(HttpCache, SimpleGET_CancelCreate) {
1581 MockHttpCache cache;
1583 MockHttpRequest request(kSimpleGET_Transaction);
1585 Context* c = new Context();
1587 c->result = cache.CreateTransaction(&c->trans);
1588 ASSERT_EQ(OK, c->result);
1590 c->result = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1591 EXPECT_EQ(ERR_IO_PENDING, c->result);
1593 // Release the reference that the mock disk cache keeps for this entry, so
1594 // that we test that the http cache handles the cancellation correctly.
1595 cache.disk_cache()->ReleaseAll();
1596 delete c;
1598 base::MessageLoop::current()->RunUntilIdle();
1599 EXPECT_EQ(1, cache.disk_cache()->create_count());
1602 // Tests that we delete/create entries even if multiple requests are queued.
1603 TEST(HttpCache, SimpleGET_ManyWriters_BypassCache) {
1604 MockHttpCache cache;
1606 MockHttpRequest request(kSimpleGET_Transaction);
1607 request.load_flags = LOAD_BYPASS_CACHE;
1609 std::vector<Context*> context_list;
1610 const int kNumTransactions = 5;
1612 for (int i = 0; i < kNumTransactions; i++) {
1613 context_list.push_back(new Context());
1614 Context* c = context_list[i];
1616 c->result = cache.CreateTransaction(&c->trans);
1617 ASSERT_EQ(OK, c->result);
1619 c->result =
1620 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1623 // The first request should be deleting the disk cache entry and the others
1624 // should be pending.
1626 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1627 EXPECT_EQ(0, cache.disk_cache()->open_count());
1628 EXPECT_EQ(0, cache.disk_cache()->create_count());
1630 // Complete the transactions.
1631 for (int i = 0; i < kNumTransactions; i++) {
1632 Context* c = context_list[i];
1633 c->result = c->callback.GetResult(c->result);
1634 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1637 // We should have had to re-create the disk entry multiple times.
1639 EXPECT_EQ(5, cache.network_layer()->transaction_count());
1640 EXPECT_EQ(0, cache.disk_cache()->open_count());
1641 EXPECT_EQ(5, cache.disk_cache()->create_count());
1643 for (int i = 0; i < kNumTransactions; ++i) {
1644 delete context_list[i];
1648 // Tests that a (simulated) timeout allows transactions waiting on the cache
1649 // lock to continue.
1650 TEST(HttpCache, SimpleGET_WriterTimeout) {
1651 MockHttpCache cache;
1652 cache.BypassCacheLock();
1654 MockHttpRequest request(kSimpleGET_Transaction);
1655 Context c1, c2;
1656 ASSERT_EQ(OK, cache.CreateTransaction(&c1.trans));
1657 ASSERT_EQ(ERR_IO_PENDING,
1658 c1.trans->Start(&request, c1.callback.callback(), BoundNetLog()));
1659 ASSERT_EQ(OK, cache.CreateTransaction(&c2.trans));
1660 ASSERT_EQ(ERR_IO_PENDING,
1661 c2.trans->Start(&request, c2.callback.callback(), BoundNetLog()));
1663 // The second request is queued after the first one.
1665 c2.callback.WaitForResult();
1666 ReadAndVerifyTransaction(c2.trans.get(), kSimpleGET_Transaction);
1668 // Complete the first transaction.
1669 c1.callback.WaitForResult();
1670 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
1673 TEST(HttpCache, SimpleGET_AbandonedCacheRead) {
1674 MockHttpCache cache;
1676 // write to the cache
1677 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1679 MockHttpRequest request(kSimpleGET_Transaction);
1680 TestCompletionCallback callback;
1682 scoped_ptr<HttpTransaction> trans;
1683 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
1684 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1685 if (rv == ERR_IO_PENDING)
1686 rv = callback.WaitForResult();
1687 ASSERT_EQ(OK, rv);
1689 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
1690 rv = trans->Read(buf.get(), 256, callback.callback());
1691 EXPECT_EQ(ERR_IO_PENDING, rv);
1693 // Test that destroying the transaction while it is reading from the cache
1694 // works properly.
1695 trans.reset();
1697 // Make sure we pump any pending events, which should include a call to
1698 // HttpCache::Transaction::OnCacheReadCompleted.
1699 base::MessageLoop::current()->RunUntilIdle();
1702 // Tests that we can delete the HttpCache and deal with queued transactions
1703 // ("waiting for the backend" as opposed to Active or Doomed entries).
1704 TEST(HttpCache, SimpleGET_ManyWriters_DeleteCache) {
1705 scoped_ptr<MockHttpCache> cache(new MockHttpCache(
1706 new MockBackendNoCbFactory()));
1708 MockHttpRequest request(kSimpleGET_Transaction);
1710 std::vector<Context*> context_list;
1711 const int kNumTransactions = 5;
1713 for (int i = 0; i < kNumTransactions; i++) {
1714 context_list.push_back(new Context());
1715 Context* c = context_list[i];
1717 c->result = cache->CreateTransaction(&c->trans);
1718 ASSERT_EQ(OK, c->result);
1720 c->result =
1721 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1724 // The first request should be creating the disk cache entry and the others
1725 // should be pending.
1727 EXPECT_EQ(0, cache->network_layer()->transaction_count());
1728 EXPECT_EQ(0, cache->disk_cache()->open_count());
1729 EXPECT_EQ(0, cache->disk_cache()->create_count());
1731 cache.reset();
1733 // There is not much to do with the transactions at this point... they are
1734 // waiting for a callback that will not fire.
1735 for (int i = 0; i < kNumTransactions; ++i) {
1736 delete context_list[i];
1740 // Tests that we queue requests when initializing the backend.
1741 TEST(HttpCache, SimpleGET_WaitForBackend) {
1742 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1743 MockHttpCache cache(factory);
1745 MockHttpRequest request0(kSimpleGET_Transaction);
1746 MockHttpRequest request1(kTypicalGET_Transaction);
1747 MockHttpRequest request2(kETagGET_Transaction);
1749 std::vector<Context*> context_list;
1750 const int kNumTransactions = 3;
1752 for (int i = 0; i < kNumTransactions; i++) {
1753 context_list.push_back(new Context());
1754 Context* c = context_list[i];
1756 c->result = cache.CreateTransaction(&c->trans);
1757 ASSERT_EQ(OK, c->result);
1760 context_list[0]->result = context_list[0]->trans->Start(
1761 &request0, context_list[0]->callback.callback(), BoundNetLog());
1762 context_list[1]->result = context_list[1]->trans->Start(
1763 &request1, context_list[1]->callback.callback(), BoundNetLog());
1764 context_list[2]->result = context_list[2]->trans->Start(
1765 &request2, context_list[2]->callback.callback(), BoundNetLog());
1767 // Just to make sure that everything is still pending.
1768 base::MessageLoop::current()->RunUntilIdle();
1770 // The first request should be creating the disk cache.
1771 EXPECT_FALSE(context_list[0]->callback.have_result());
1773 factory->FinishCreation();
1775 base::MessageLoop::current()->RunUntilIdle();
1776 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1777 EXPECT_EQ(3, cache.disk_cache()->create_count());
1779 for (int i = 0; i < kNumTransactions; ++i) {
1780 EXPECT_TRUE(context_list[i]->callback.have_result());
1781 delete context_list[i];
1785 // Tests that we can cancel requests that are queued waiting for the backend
1786 // to be initialized.
1787 TEST(HttpCache, SimpleGET_WaitForBackend_CancelCreate) {
1788 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1789 MockHttpCache cache(factory);
1791 MockHttpRequest request0(kSimpleGET_Transaction);
1792 MockHttpRequest request1(kTypicalGET_Transaction);
1793 MockHttpRequest request2(kETagGET_Transaction);
1795 std::vector<Context*> context_list;
1796 const int kNumTransactions = 3;
1798 for (int i = 0; i < kNumTransactions; i++) {
1799 context_list.push_back(new Context());
1800 Context* c = context_list[i];
1802 c->result = cache.CreateTransaction(&c->trans);
1803 ASSERT_EQ(OK, c->result);
1806 context_list[0]->result = context_list[0]->trans->Start(
1807 &request0, context_list[0]->callback.callback(), BoundNetLog());
1808 context_list[1]->result = context_list[1]->trans->Start(
1809 &request1, context_list[1]->callback.callback(), BoundNetLog());
1810 context_list[2]->result = context_list[2]->trans->Start(
1811 &request2, context_list[2]->callback.callback(), BoundNetLog());
1813 // Just to make sure that everything is still pending.
1814 base::MessageLoop::current()->RunUntilIdle();
1816 // The first request should be creating the disk cache.
1817 EXPECT_FALSE(context_list[0]->callback.have_result());
1819 // Cancel a request from the pending queue.
1820 delete context_list[1];
1821 context_list[1] = NULL;
1823 // Cancel the request that is creating the entry.
1824 delete context_list[0];
1825 context_list[0] = NULL;
1827 // Complete the last transaction.
1828 factory->FinishCreation();
1830 context_list[2]->result =
1831 context_list[2]->callback.GetResult(context_list[2]->result);
1832 ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction);
1834 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1835 EXPECT_EQ(1, cache.disk_cache()->create_count());
1837 delete context_list[2];
1840 // Tests that we can delete the cache while creating the backend.
1841 TEST(HttpCache, DeleteCacheWaitingForBackend) {
1842 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1843 scoped_ptr<MockHttpCache> cache(new MockHttpCache(factory));
1845 MockHttpRequest request(kSimpleGET_Transaction);
1847 scoped_ptr<Context> c(new Context());
1848 c->result = cache->CreateTransaction(&c->trans);
1849 ASSERT_EQ(OK, c->result);
1851 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1853 // Just to make sure that everything is still pending.
1854 base::MessageLoop::current()->RunUntilIdle();
1856 // The request should be creating the disk cache.
1857 EXPECT_FALSE(c->callback.have_result());
1859 // We cannot call FinishCreation because the factory itself will go away with
1860 // the cache, so grab the callback and attempt to use it.
1861 CompletionCallback callback = factory->callback();
1862 scoped_ptr<disk_cache::Backend>* backend = factory->backend();
1864 cache.reset();
1865 base::MessageLoop::current()->RunUntilIdle();
1867 backend->reset();
1868 callback.Run(ERR_ABORTED);
1871 // Tests that we can delete the cache while creating the backend, from within
1872 // one of the callbacks.
1873 TEST(HttpCache, DeleteCacheWaitingForBackend2) {
1874 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
1875 MockHttpCache* cache = new MockHttpCache(factory);
1877 DeleteCacheCompletionCallback cb(cache);
1878 disk_cache::Backend* backend;
1879 int rv = cache->http_cache()->GetBackend(&backend, cb.callback());
1880 EXPECT_EQ(ERR_IO_PENDING, rv);
1882 // Now let's queue a regular transaction
1883 MockHttpRequest request(kSimpleGET_Transaction);
1885 scoped_ptr<Context> c(new Context());
1886 c->result = cache->CreateTransaction(&c->trans);
1887 ASSERT_EQ(OK, c->result);
1889 c->trans->Start(&request, c->callback.callback(), BoundNetLog());
1891 // And another direct backend request.
1892 TestCompletionCallback cb2;
1893 rv = cache->http_cache()->GetBackend(&backend, cb2.callback());
1894 EXPECT_EQ(ERR_IO_PENDING, rv);
1896 // Just to make sure that everything is still pending.
1897 base::MessageLoop::current()->RunUntilIdle();
1899 // The request should be queued.
1900 EXPECT_FALSE(c->callback.have_result());
1902 // Generate the callback.
1903 factory->FinishCreation();
1904 rv = cb.WaitForResult();
1906 // The cache should be gone by now.
1907 base::MessageLoop::current()->RunUntilIdle();
1908 EXPECT_EQ(OK, c->callback.GetResult(c->result));
1909 EXPECT_FALSE(cb2.have_result());
1912 TEST(HttpCache, TypicalGET_ConditionalRequest) {
1913 MockHttpCache cache;
1915 // write to the cache
1916 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
1918 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1919 EXPECT_EQ(0, cache.disk_cache()->open_count());
1920 EXPECT_EQ(1, cache.disk_cache()->create_count());
1922 // Get the same URL again, but this time we expect it to result
1923 // in a conditional request.
1924 BoundTestNetLog log;
1925 LoadTimingInfo load_timing_info;
1926 RunTransactionTestAndGetTiming(cache.http_cache(), kTypicalGET_Transaction,
1927 log.bound(), &load_timing_info);
1929 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1930 EXPECT_EQ(1, cache.disk_cache()->open_count());
1931 EXPECT_EQ(1, cache.disk_cache()->create_count());
1932 TestLoadTimingNetworkRequest(load_timing_info);
1935 static void ETagGet_ConditionalRequest_Handler(const HttpRequestInfo* request,
1936 std::string* response_status,
1937 std::string* response_headers,
1938 std::string* response_data) {
1939 EXPECT_TRUE(
1940 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
1941 response_status->assign("HTTP/1.1 304 Not Modified");
1942 response_headers->assign(kETagGET_Transaction.response_headers);
1943 response_data->clear();
1946 TEST(HttpCache, ETagGET_ConditionalRequest_304) {
1947 MockHttpCache cache;
1949 ScopedMockTransaction transaction(kETagGET_Transaction);
1951 // write to the cache
1952 RunTransactionTest(cache.http_cache(), transaction);
1954 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1955 EXPECT_EQ(0, cache.disk_cache()->open_count());
1956 EXPECT_EQ(1, cache.disk_cache()->create_count());
1958 // Get the same URL again, but this time we expect it to result
1959 // in a conditional request.
1960 transaction.load_flags = LOAD_VALIDATE_CACHE;
1961 transaction.handler = ETagGet_ConditionalRequest_Handler;
1962 BoundTestNetLog log;
1963 LoadTimingInfo load_timing_info;
1964 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
1965 &load_timing_info);
1967 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1968 EXPECT_EQ(1, cache.disk_cache()->open_count());
1969 EXPECT_EQ(1, cache.disk_cache()->create_count());
1970 TestLoadTimingNetworkRequest(load_timing_info);
1973 class RevalidationServer {
1974 public:
1975 RevalidationServer() {
1976 s_etag_used_ = false;
1977 s_last_modified_used_ = false;
1980 bool EtagUsed() { return s_etag_used_; }
1981 bool LastModifiedUsed() { return s_last_modified_used_; }
1983 static void Handler(const HttpRequestInfo* request,
1984 std::string* response_status,
1985 std::string* response_headers,
1986 std::string* response_data);
1988 private:
1989 static bool s_etag_used_;
1990 static bool s_last_modified_used_;
1992 bool RevalidationServer::s_etag_used_ = false;
1993 bool RevalidationServer::s_last_modified_used_ = false;
1995 void RevalidationServer::Handler(const HttpRequestInfo* request,
1996 std::string* response_status,
1997 std::string* response_headers,
1998 std::string* response_data) {
1999 if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch))
2000 s_etag_used_ = true;
2002 if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfModifiedSince)) {
2003 s_last_modified_used_ = true;
2006 if (s_etag_used_ || s_last_modified_used_) {
2007 response_status->assign("HTTP/1.1 304 Not Modified");
2008 response_headers->assign(kTypicalGET_Transaction.response_headers);
2009 response_data->clear();
2010 } else {
2011 response_status->assign(kTypicalGET_Transaction.status);
2012 response_headers->assign(kTypicalGET_Transaction.response_headers);
2013 response_data->assign(kTypicalGET_Transaction.data);
2017 // Tests revalidation after a vary match.
2018 TEST(HttpCache, GET_ValidateCache_VaryMatch) {
2019 MockHttpCache cache;
2021 // Write to the cache.
2022 MockTransaction transaction(kTypicalGET_Transaction);
2023 transaction.request_headers = "Foo: bar\r\n";
2024 transaction.response_headers =
2025 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
2026 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2027 "Etag: \"foopy\"\n"
2028 "Cache-Control: max-age=0\n"
2029 "Vary: Foo\n";
2030 AddMockTransaction(&transaction);
2031 RunTransactionTest(cache.http_cache(), transaction);
2033 // Read from the cache.
2034 RevalidationServer server;
2035 transaction.handler = server.Handler;
2036 BoundTestNetLog log;
2037 LoadTimingInfo load_timing_info;
2038 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
2039 &load_timing_info);
2041 EXPECT_TRUE(server.EtagUsed());
2042 EXPECT_TRUE(server.LastModifiedUsed());
2043 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2044 EXPECT_EQ(1, cache.disk_cache()->open_count());
2045 EXPECT_EQ(1, cache.disk_cache()->create_count());
2046 TestLoadTimingNetworkRequest(load_timing_info);
2047 RemoveMockTransaction(&transaction);
2050 // Tests revalidation after a vary mismatch if etag is present.
2051 TEST(HttpCache, GET_ValidateCache_VaryMismatch) {
2052 MockHttpCache cache;
2054 // Write to the cache.
2055 MockTransaction transaction(kTypicalGET_Transaction);
2056 transaction.request_headers = "Foo: bar\r\n";
2057 transaction.response_headers =
2058 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
2059 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2060 "Etag: \"foopy\"\n"
2061 "Cache-Control: max-age=0\n"
2062 "Vary: Foo\n";
2063 AddMockTransaction(&transaction);
2064 RunTransactionTest(cache.http_cache(), transaction);
2066 // Read from the cache and revalidate the entry.
2067 RevalidationServer server;
2068 transaction.handler = server.Handler;
2069 transaction.request_headers = "Foo: none\r\n";
2070 BoundTestNetLog log;
2071 LoadTimingInfo load_timing_info;
2072 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
2073 &load_timing_info);
2075 EXPECT_TRUE(server.EtagUsed());
2076 EXPECT_FALSE(server.LastModifiedUsed());
2077 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2078 EXPECT_EQ(1, cache.disk_cache()->open_count());
2079 EXPECT_EQ(1, cache.disk_cache()->create_count());
2080 TestLoadTimingNetworkRequest(load_timing_info);
2081 RemoveMockTransaction(&transaction);
2084 // Tests lack of revalidation after a vary mismatch and no etag.
2085 TEST(HttpCache, GET_DontValidateCache_VaryMismatch) {
2086 MockHttpCache cache;
2088 // Write to the cache.
2089 MockTransaction transaction(kTypicalGET_Transaction);
2090 transaction.request_headers = "Foo: bar\r\n";
2091 transaction.response_headers =
2092 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
2093 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2094 "Cache-Control: max-age=0\n"
2095 "Vary: Foo\n";
2096 AddMockTransaction(&transaction);
2097 RunTransactionTest(cache.http_cache(), transaction);
2099 // Read from the cache and don't revalidate the entry.
2100 RevalidationServer server;
2101 transaction.handler = server.Handler;
2102 transaction.request_headers = "Foo: none\r\n";
2103 BoundTestNetLog log;
2104 LoadTimingInfo load_timing_info;
2105 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
2106 &load_timing_info);
2108 EXPECT_FALSE(server.EtagUsed());
2109 EXPECT_FALSE(server.LastModifiedUsed());
2110 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2111 EXPECT_EQ(1, cache.disk_cache()->open_count());
2112 EXPECT_EQ(1, cache.disk_cache()->create_count());
2113 TestLoadTimingNetworkRequest(load_timing_info);
2114 RemoveMockTransaction(&transaction);
2117 // Tests that a new vary header provided when revalidating an entry is saved.
2118 TEST(HttpCache, GET_ValidateCache_VaryMatch_UpdateVary) {
2119 MockHttpCache cache;
2121 // Write to the cache.
2122 ScopedMockTransaction transaction(kTypicalGET_Transaction);
2123 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
2124 transaction.response_headers =
2125 "Etag: \"foopy\"\n"
2126 "Cache-Control: max-age=0\n"
2127 "Vary: Foo\n";
2128 RunTransactionTest(cache.http_cache(), transaction);
2130 // Validate the entry and change the vary field in the response.
2131 transaction.request_headers = "Foo: bar\r\n Name: none\r\n";
2132 transaction.status = "HTTP/1.1 304 Not Modified";
2133 transaction.response_headers =
2134 "Etag: \"foopy\"\n"
2135 "Cache-Control: max-age=3600\n"
2136 "Vary: Name\n";
2137 RunTransactionTest(cache.http_cache(), transaction);
2139 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2140 EXPECT_EQ(1, cache.disk_cache()->open_count());
2141 EXPECT_EQ(1, cache.disk_cache()->create_count());
2143 // Make sure that the ActiveEntry is gone.
2144 base::RunLoop().RunUntilIdle();
2146 // Generate a vary mismatch.
2147 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
2148 RunTransactionTest(cache.http_cache(), transaction);
2150 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2151 EXPECT_EQ(2, cache.disk_cache()->open_count());
2152 EXPECT_EQ(1, cache.disk_cache()->create_count());
2155 // Tests that new request headers causing a vary mismatch are paired with the
2156 // new response when the server says the old response can be used.
2157 TEST(HttpCache, GET_ValidateCache_VaryMismatch_UpdateRequestHeader) {
2158 MockHttpCache cache;
2160 // Write to the cache.
2161 ScopedMockTransaction transaction(kTypicalGET_Transaction);
2162 transaction.request_headers = "Foo: bar\r\n";
2163 transaction.response_headers =
2164 "Etag: \"foopy\"\n"
2165 "Cache-Control: max-age=3600\n"
2166 "Vary: Foo\n";
2167 RunTransactionTest(cache.http_cache(), transaction);
2169 // Vary-mismatch validation receives 304.
2170 transaction.request_headers = "Foo: none\r\n";
2171 transaction.status = "HTTP/1.1 304 Not Modified";
2172 RunTransactionTest(cache.http_cache(), transaction);
2174 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2175 EXPECT_EQ(1, cache.disk_cache()->open_count());
2176 EXPECT_EQ(1, cache.disk_cache()->create_count());
2178 // Make sure that the ActiveEntry is gone.
2179 base::RunLoop().RunUntilIdle();
2181 // Generate a vary mismatch.
2182 transaction.request_headers = "Foo: bar\r\n";
2183 RunTransactionTest(cache.http_cache(), transaction);
2185 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2186 EXPECT_EQ(2, cache.disk_cache()->open_count());
2187 EXPECT_EQ(1, cache.disk_cache()->create_count());
2190 // Tests that a 304 without vary headers doesn't delete the previously stored
2191 // vary data after a vary match revalidation.
2192 TEST(HttpCache, GET_ValidateCache_VaryMatch_DontDeleteVary) {
2193 MockHttpCache cache;
2195 // Write to the cache.
2196 ScopedMockTransaction transaction(kTypicalGET_Transaction);
2197 transaction.request_headers = "Foo: bar\r\n";
2198 transaction.response_headers =
2199 "Etag: \"foopy\"\n"
2200 "Cache-Control: max-age=0\n"
2201 "Vary: Foo\n";
2202 RunTransactionTest(cache.http_cache(), transaction);
2204 // Validate the entry and remove the vary field in the response.
2205 transaction.status = "HTTP/1.1 304 Not Modified";
2206 transaction.response_headers =
2207 "Etag: \"foopy\"\n"
2208 "Cache-Control: max-age=3600\n";
2209 RunTransactionTest(cache.http_cache(), transaction);
2211 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2212 EXPECT_EQ(1, cache.disk_cache()->open_count());
2213 EXPECT_EQ(1, cache.disk_cache()->create_count());
2215 // Make sure that the ActiveEntry is gone.
2216 base::RunLoop().RunUntilIdle();
2218 // Generate a vary mismatch.
2219 transaction.request_headers = "Foo: none\r\n";
2220 RunTransactionTest(cache.http_cache(), transaction);
2222 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2223 EXPECT_EQ(2, cache.disk_cache()->open_count());
2224 EXPECT_EQ(1, cache.disk_cache()->create_count());
2227 // Tests that a 304 without vary headers doesn't delete the previously stored
2228 // vary data after a vary mismatch.
2229 TEST(HttpCache, GET_ValidateCache_VaryMismatch_DontDeleteVary) {
2230 MockHttpCache cache;
2232 // Write to the cache.
2233 ScopedMockTransaction transaction(kTypicalGET_Transaction);
2234 transaction.request_headers = "Foo: bar\r\n";
2235 transaction.response_headers =
2236 "Etag: \"foopy\"\n"
2237 "Cache-Control: max-age=3600\n"
2238 "Vary: Foo\n";
2239 RunTransactionTest(cache.http_cache(), transaction);
2241 // Vary-mismatch validation receives 304 and no vary header.
2242 transaction.request_headers = "Foo: none\r\n";
2243 transaction.status = "HTTP/1.1 304 Not Modified";
2244 transaction.response_headers =
2245 "Etag: \"foopy\"\n"
2246 "Cache-Control: max-age=3600\n";
2247 RunTransactionTest(cache.http_cache(), transaction);
2249 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2250 EXPECT_EQ(1, cache.disk_cache()->open_count());
2251 EXPECT_EQ(1, cache.disk_cache()->create_count());
2253 // Make sure that the ActiveEntry is gone.
2254 base::RunLoop().RunUntilIdle();
2256 // Generate a vary mismatch.
2257 transaction.request_headers = "Foo: bar\r\n";
2258 RunTransactionTest(cache.http_cache(), transaction);
2260 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2261 EXPECT_EQ(2, cache.disk_cache()->open_count());
2262 EXPECT_EQ(1, cache.disk_cache()->create_count());
2265 static void ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo* request,
2266 std::string* response_status,
2267 std::string* response_headers,
2268 std::string* response_data) {
2269 EXPECT_FALSE(
2270 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
2273 TEST(HttpCache, ETagGET_Http10) {
2274 MockHttpCache cache;
2276 ScopedMockTransaction transaction(kETagGET_Transaction);
2277 transaction.status = "HTTP/1.0 200 OK";
2279 // Write to the cache.
2280 RunTransactionTest(cache.http_cache(), transaction);
2282 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2283 EXPECT_EQ(0, cache.disk_cache()->open_count());
2284 EXPECT_EQ(1, cache.disk_cache()->create_count());
2286 // Get the same URL again, without generating a conditional request.
2287 transaction.load_flags = LOAD_VALIDATE_CACHE;
2288 transaction.handler = ETagGet_UnconditionalRequest_Handler;
2289 RunTransactionTest(cache.http_cache(), transaction);
2291 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2292 EXPECT_EQ(1, cache.disk_cache()->open_count());
2293 EXPECT_EQ(1, cache.disk_cache()->create_count());
2296 TEST(HttpCache, ETagGET_Http10_Range) {
2297 MockHttpCache cache;
2299 ScopedMockTransaction transaction(kETagGET_Transaction);
2300 transaction.status = "HTTP/1.0 200 OK";
2302 // Write to the cache.
2303 RunTransactionTest(cache.http_cache(), transaction);
2305 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2306 EXPECT_EQ(0, cache.disk_cache()->open_count());
2307 EXPECT_EQ(1, cache.disk_cache()->create_count());
2309 // Get the same URL again, but use a byte range request.
2310 transaction.load_flags = LOAD_VALIDATE_CACHE;
2311 transaction.handler = ETagGet_UnconditionalRequest_Handler;
2312 transaction.request_headers = "Range: bytes = 5-\r\n";
2313 RunTransactionTest(cache.http_cache(), transaction);
2315 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2316 EXPECT_EQ(1, cache.disk_cache()->open_count());
2317 EXPECT_EQ(2, cache.disk_cache()->create_count());
2320 static void ETagGet_ConditionalRequest_NoStore_Handler(
2321 const HttpRequestInfo* request,
2322 std::string* response_status,
2323 std::string* response_headers,
2324 std::string* response_data) {
2325 EXPECT_TRUE(
2326 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
2327 response_status->assign("HTTP/1.1 304 Not Modified");
2328 response_headers->assign("Cache-Control: no-store\n");
2329 response_data->clear();
2332 TEST(HttpCache, ETagGET_ConditionalRequest_304_NoStore) {
2333 MockHttpCache cache;
2335 ScopedMockTransaction transaction(kETagGET_Transaction);
2337 // Write to the cache.
2338 RunTransactionTest(cache.http_cache(), transaction);
2340 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2341 EXPECT_EQ(0, cache.disk_cache()->open_count());
2342 EXPECT_EQ(1, cache.disk_cache()->create_count());
2344 // Get the same URL again, but this time we expect it to result
2345 // in a conditional request.
2346 transaction.load_flags = LOAD_VALIDATE_CACHE;
2347 transaction.handler = ETagGet_ConditionalRequest_NoStore_Handler;
2348 RunTransactionTest(cache.http_cache(), transaction);
2350 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2351 EXPECT_EQ(1, cache.disk_cache()->open_count());
2352 EXPECT_EQ(1, cache.disk_cache()->create_count());
2354 ScopedMockTransaction transaction2(kETagGET_Transaction);
2356 // Write to the cache again. This should create a new entry.
2357 RunTransactionTest(cache.http_cache(), transaction2);
2359 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2360 EXPECT_EQ(1, cache.disk_cache()->open_count());
2361 EXPECT_EQ(2, cache.disk_cache()->create_count());
2364 // Helper that does 4 requests using HttpCache:
2366 // (1) loads |kUrl| -- expects |net_response_1| to be returned.
2367 // (2) loads |kUrl| from cache only -- expects |net_response_1| to be returned.
2368 // (3) loads |kUrl| using |extra_request_headers| -- expects |net_response_2| to
2369 // be returned.
2370 // (4) loads |kUrl| from cache only -- expects |cached_response_2| to be
2371 // returned.
2372 static void ConditionalizedRequestUpdatesCacheHelper(
2373 const Response& net_response_1,
2374 const Response& net_response_2,
2375 const Response& cached_response_2,
2376 const char* extra_request_headers) {
2377 MockHttpCache cache;
2379 // The URL we will be requesting.
2380 const char kUrl[] = "http://foobar.com/main.css";
2382 // Junk network response.
2383 static const Response kUnexpectedResponse = {
2384 "HTTP/1.1 500 Unexpected",
2385 "Server: unexpected_header",
2386 "unexpected body"
2389 // We will control the network layer's responses for |kUrl| using
2390 // |mock_network_response|.
2391 MockTransaction mock_network_response = { 0 };
2392 mock_network_response.url = kUrl;
2393 AddMockTransaction(&mock_network_response);
2395 // Request |kUrl| for the first time. It should hit the network and
2396 // receive |kNetResponse1|, which it saves into the HTTP cache.
2398 MockTransaction request = { 0 };
2399 request.url = kUrl;
2400 request.method = "GET";
2401 request.request_headers = "";
2403 net_response_1.AssignTo(&mock_network_response); // Network mock.
2404 net_response_1.AssignTo(&request); // Expected result.
2406 std::string response_headers;
2407 RunTransactionTestWithResponse(
2408 cache.http_cache(), request, &response_headers);
2410 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
2411 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2412 EXPECT_EQ(0, cache.disk_cache()->open_count());
2413 EXPECT_EQ(1, cache.disk_cache()->create_count());
2415 // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP
2416 // cache, so we don't hit the network.
2418 request.load_flags = LOAD_ONLY_FROM_CACHE;
2420 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
2421 net_response_1.AssignTo(&request); // Expected result.
2423 RunTransactionTestWithResponse(
2424 cache.http_cache(), request, &response_headers);
2426 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
2427 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2428 EXPECT_EQ(1, cache.disk_cache()->open_count());
2429 EXPECT_EQ(1, cache.disk_cache()->create_count());
2431 // Request |kUrl| yet again, but this time give the request an
2432 // "If-Modified-Since" header. This will cause the request to re-hit the
2433 // network. However now the network response is going to be
2434 // different -- this simulates a change made to the CSS file.
2436 request.request_headers = extra_request_headers;
2437 request.load_flags = LOAD_NORMAL;
2439 net_response_2.AssignTo(&mock_network_response); // Network mock.
2440 net_response_2.AssignTo(&request); // Expected result.
2442 RunTransactionTestWithResponse(
2443 cache.http_cache(), request, &response_headers);
2445 EXPECT_EQ(net_response_2.status_and_headers(), response_headers);
2446 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2447 EXPECT_EQ(1, cache.disk_cache()->open_count());
2448 EXPECT_EQ(1, cache.disk_cache()->create_count());
2450 // Finally, request |kUrl| again. This request should be serviced from
2451 // the cache. Moreover, the value in the cache should be |kNetResponse2|
2452 // and NOT |kNetResponse1|. The previous step should have replaced the
2453 // value in the cache with the modified response.
2455 request.request_headers = "";
2456 request.load_flags = LOAD_ONLY_FROM_CACHE;
2458 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
2459 cached_response_2.AssignTo(&request); // Expected result.
2461 RunTransactionTestWithResponse(
2462 cache.http_cache(), request, &response_headers);
2464 EXPECT_EQ(cached_response_2.status_and_headers(), response_headers);
2465 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2466 EXPECT_EQ(2, cache.disk_cache()->open_count());
2467 EXPECT_EQ(1, cache.disk_cache()->create_count());
2469 RemoveMockTransaction(&mock_network_response);
2472 // Check that when an "if-modified-since" header is attached
2473 // to the request, the result still updates the cached entry.
2474 TEST(HttpCache, ConditionalizedRequestUpdatesCache1) {
2475 // First network response for |kUrl|.
2476 static const Response kNetResponse1 = {
2477 "HTTP/1.1 200 OK",
2478 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2479 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2480 "body1"
2483 // Second network response for |kUrl|.
2484 static const Response kNetResponse2 = {
2485 "HTTP/1.1 200 OK",
2486 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2487 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2488 "body2"
2491 const char extra_headers[] =
2492 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
2494 ConditionalizedRequestUpdatesCacheHelper(
2495 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
2498 // Check that when an "if-none-match" header is attached
2499 // to the request, the result updates the cached entry.
2500 TEST(HttpCache, ConditionalizedRequestUpdatesCache2) {
2501 // First network response for |kUrl|.
2502 static const Response kNetResponse1 = {
2503 "HTTP/1.1 200 OK",
2504 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2505 "Etag: \"ETAG1\"\n"
2506 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
2507 "body1"
2510 // Second network response for |kUrl|.
2511 static const Response kNetResponse2 = {
2512 "HTTP/1.1 200 OK",
2513 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2514 "Etag: \"ETAG2\"\n"
2515 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
2516 "body2"
2519 const char extra_headers[] = "If-None-Match: \"ETAG1\"\r\n";
2521 ConditionalizedRequestUpdatesCacheHelper(
2522 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
2525 // Check that when an "if-modified-since" header is attached
2526 // to a request, the 304 (not modified result) result updates the cached
2527 // headers, and the 304 response is returned rather than the cached response.
2528 TEST(HttpCache, ConditionalizedRequestUpdatesCache3) {
2529 // First network response for |kUrl|.
2530 static const Response kNetResponse1 = {
2531 "HTTP/1.1 200 OK",
2532 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2533 "Server: server1\n"
2534 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2535 "body1"
2538 // Second network response for |kUrl|.
2539 static const Response kNetResponse2 = {
2540 "HTTP/1.1 304 Not Modified",
2541 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2542 "Server: server2\n"
2543 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2547 static const Response kCachedResponse2 = {
2548 "HTTP/1.1 200 OK",
2549 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2550 "Server: server2\n"
2551 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2552 "body1"
2555 const char extra_headers[] =
2556 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
2558 ConditionalizedRequestUpdatesCacheHelper(
2559 kNetResponse1, kNetResponse2, kCachedResponse2, extra_headers);
2562 // Test that when doing an externally conditionalized if-modified-since
2563 // and there is no corresponding cache entry, a new cache entry is NOT
2564 // created (304 response).
2565 TEST(HttpCache, ConditionalizedRequestUpdatesCache4) {
2566 MockHttpCache cache;
2568 const char kUrl[] = "http://foobar.com/main.css";
2570 static const Response kNetResponse = {
2571 "HTTP/1.1 304 Not Modified",
2572 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2573 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2577 const char kExtraRequestHeaders[] =
2578 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
2580 // We will control the network layer's responses for |kUrl| using
2581 // |mock_network_response|.
2582 MockTransaction mock_network_response = { 0 };
2583 mock_network_response.url = kUrl;
2584 AddMockTransaction(&mock_network_response);
2586 MockTransaction request = { 0 };
2587 request.url = kUrl;
2588 request.method = "GET";
2589 request.request_headers = kExtraRequestHeaders;
2591 kNetResponse.AssignTo(&mock_network_response); // Network mock.
2592 kNetResponse.AssignTo(&request); // Expected result.
2594 std::string response_headers;
2595 RunTransactionTestWithResponse(
2596 cache.http_cache(), request, &response_headers);
2598 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
2599 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2600 EXPECT_EQ(0, cache.disk_cache()->open_count());
2601 EXPECT_EQ(0, cache.disk_cache()->create_count());
2603 RemoveMockTransaction(&mock_network_response);
2606 // Test that when doing an externally conditionalized if-modified-since
2607 // and there is no corresponding cache entry, a new cache entry is NOT
2608 // created (200 response).
2609 TEST(HttpCache, ConditionalizedRequestUpdatesCache5) {
2610 MockHttpCache cache;
2612 const char kUrl[] = "http://foobar.com/main.css";
2614 static const Response kNetResponse = {
2615 "HTTP/1.1 200 OK",
2616 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2617 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2618 "foobar!!!"
2621 const char kExtraRequestHeaders[] =
2622 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
2624 // We will control the network layer's responses for |kUrl| using
2625 // |mock_network_response|.
2626 MockTransaction mock_network_response = { 0 };
2627 mock_network_response.url = kUrl;
2628 AddMockTransaction(&mock_network_response);
2630 MockTransaction request = { 0 };
2631 request.url = kUrl;
2632 request.method = "GET";
2633 request.request_headers = kExtraRequestHeaders;
2635 kNetResponse.AssignTo(&mock_network_response); // Network mock.
2636 kNetResponse.AssignTo(&request); // Expected result.
2638 std::string response_headers;
2639 RunTransactionTestWithResponse(
2640 cache.http_cache(), request, &response_headers);
2642 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
2643 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2644 EXPECT_EQ(0, cache.disk_cache()->open_count());
2645 EXPECT_EQ(0, cache.disk_cache()->create_count());
2647 RemoveMockTransaction(&mock_network_response);
2650 // Test that when doing an externally conditionalized if-modified-since
2651 // if the date does not match the cache entry's last-modified date,
2652 // then we do NOT use the response (304) to update the cache.
2653 // (the if-modified-since date is 2 days AFTER the cache's modification date).
2654 TEST(HttpCache, ConditionalizedRequestUpdatesCache6) {
2655 static const Response kNetResponse1 = {
2656 "HTTP/1.1 200 OK",
2657 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2658 "Server: server1\n"
2659 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2660 "body1"
2663 // Second network response for |kUrl|.
2664 static const Response kNetResponse2 = {
2665 "HTTP/1.1 304 Not Modified",
2666 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2667 "Server: server2\n"
2668 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2672 // This is two days in the future from the original response's last-modified
2673 // date!
2674 const char kExtraRequestHeaders[] =
2675 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n";
2677 ConditionalizedRequestUpdatesCacheHelper(
2678 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2681 // Test that when doing an externally conditionalized if-none-match
2682 // if the etag does not match the cache entry's etag, then we do not use the
2683 // response (304) to update the cache.
2684 TEST(HttpCache, ConditionalizedRequestUpdatesCache7) {
2685 static const Response kNetResponse1 = {
2686 "HTTP/1.1 200 OK",
2687 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2688 "Etag: \"Foo1\"\n"
2689 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2690 "body1"
2693 // Second network response for |kUrl|.
2694 static const Response kNetResponse2 = {
2695 "HTTP/1.1 304 Not Modified",
2696 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2697 "Etag: \"Foo2\"\n"
2698 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2702 // Different etag from original response.
2703 const char kExtraRequestHeaders[] = "If-None-Match: \"Foo2\"\r\n";
2705 ConditionalizedRequestUpdatesCacheHelper(
2706 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2709 // Test that doing an externally conditionalized request with both if-none-match
2710 // and if-modified-since updates the cache.
2711 TEST(HttpCache, ConditionalizedRequestUpdatesCache8) {
2712 static const Response kNetResponse1 = {
2713 "HTTP/1.1 200 OK",
2714 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2715 "Etag: \"Foo1\"\n"
2716 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2717 "body1"
2720 // Second network response for |kUrl|.
2721 static const Response kNetResponse2 = {
2722 "HTTP/1.1 200 OK",
2723 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2724 "Etag: \"Foo2\"\n"
2725 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2726 "body2"
2729 const char kExtraRequestHeaders[] =
2730 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
2731 "If-None-Match: \"Foo1\"\r\n";
2733 ConditionalizedRequestUpdatesCacheHelper(
2734 kNetResponse1, kNetResponse2, kNetResponse2, kExtraRequestHeaders);
2737 // Test that doing an externally conditionalized request with both if-none-match
2738 // and if-modified-since does not update the cache with only one match.
2739 TEST(HttpCache, ConditionalizedRequestUpdatesCache9) {
2740 static const Response kNetResponse1 = {
2741 "HTTP/1.1 200 OK",
2742 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2743 "Etag: \"Foo1\"\n"
2744 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2745 "body1"
2748 // Second network response for |kUrl|.
2749 static const Response kNetResponse2 = {
2750 "HTTP/1.1 200 OK",
2751 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2752 "Etag: \"Foo2\"\n"
2753 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2754 "body2"
2757 // The etag doesn't match what we have stored.
2758 const char kExtraRequestHeaders[] =
2759 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
2760 "If-None-Match: \"Foo2\"\r\n";
2762 ConditionalizedRequestUpdatesCacheHelper(
2763 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2766 // Test that doing an externally conditionalized request with both if-none-match
2767 // and if-modified-since does not update the cache with only one match.
2768 TEST(HttpCache, ConditionalizedRequestUpdatesCache10) {
2769 static const Response kNetResponse1 = {
2770 "HTTP/1.1 200 OK",
2771 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
2772 "Etag: \"Foo1\"\n"
2773 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
2774 "body1"
2777 // Second network response for |kUrl|.
2778 static const Response kNetResponse2 = {
2779 "HTTP/1.1 200 OK",
2780 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
2781 "Etag: \"Foo2\"\n"
2782 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
2783 "body2"
2786 // The modification date doesn't match what we have stored.
2787 const char kExtraRequestHeaders[] =
2788 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n"
2789 "If-None-Match: \"Foo1\"\r\n";
2791 ConditionalizedRequestUpdatesCacheHelper(
2792 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
2795 TEST(HttpCache, UrlContainingHash) {
2796 MockHttpCache cache;
2798 // Do a typical GET request -- should write an entry into our cache.
2799 MockTransaction trans(kTypicalGET_Transaction);
2800 RunTransactionTest(cache.http_cache(), trans);
2802 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2803 EXPECT_EQ(0, cache.disk_cache()->open_count());
2804 EXPECT_EQ(1, cache.disk_cache()->create_count());
2806 // Request the same URL, but this time with a reference section (hash).
2807 // Since the cache key strips the hash sections, this should be a cache hit.
2808 std::string url_with_hash = std::string(trans.url) + "#multiple#hashes";
2809 trans.url = url_with_hash.c_str();
2810 trans.load_flags = LOAD_ONLY_FROM_CACHE;
2812 RunTransactionTest(cache.http_cache(), trans);
2814 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2815 EXPECT_EQ(1, cache.disk_cache()->open_count());
2816 EXPECT_EQ(1, cache.disk_cache()->create_count());
2819 // Tests that we skip the cache for POST requests that do not have an upload
2820 // identifier.
2821 TEST(HttpCache, SimplePOST_SkipsCache) {
2822 MockHttpCache cache;
2824 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
2826 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2827 EXPECT_EQ(0, cache.disk_cache()->open_count());
2828 EXPECT_EQ(0, cache.disk_cache()->create_count());
2831 // Tests POST handling with a disabled cache (no DCHECK).
2832 TEST(HttpCache, SimplePOST_DisabledCache) {
2833 MockHttpCache cache;
2834 cache.http_cache()->set_mode(HttpCache::Mode::DISABLE);
2836 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
2838 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2839 EXPECT_EQ(0, cache.disk_cache()->open_count());
2840 EXPECT_EQ(0, cache.disk_cache()->create_count());
2843 TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Miss) {
2844 MockHttpCache cache;
2846 MockTransaction transaction(kSimplePOST_Transaction);
2847 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
2849 MockHttpRequest request(transaction);
2850 TestCompletionCallback callback;
2852 scoped_ptr<HttpTransaction> trans;
2853 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
2854 ASSERT_TRUE(trans.get());
2856 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2857 ASSERT_EQ(ERR_CACHE_MISS, callback.GetResult(rv));
2859 trans.reset();
2861 EXPECT_EQ(0, cache.network_layer()->transaction_count());
2862 EXPECT_EQ(0, cache.disk_cache()->open_count());
2863 EXPECT_EQ(0, cache.disk_cache()->create_count());
2866 TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Hit) {
2867 MockHttpCache cache;
2869 // Test that we hit the cache for POST requests.
2871 MockTransaction transaction(kSimplePOST_Transaction);
2873 const int64 kUploadId = 1; // Just a dummy value.
2875 ScopedVector<UploadElementReader> element_readers;
2876 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2877 ElementsUploadDataStream upload_data_stream(element_readers.Pass(),
2878 kUploadId);
2879 MockHttpRequest request(transaction);
2880 request.upload_data_stream = &upload_data_stream;
2882 // Populate the cache.
2883 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
2885 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2886 EXPECT_EQ(0, cache.disk_cache()->open_count());
2887 EXPECT_EQ(1, cache.disk_cache()->create_count());
2889 // Load from cache.
2890 request.load_flags |= LOAD_ONLY_FROM_CACHE;
2891 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
2893 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2894 EXPECT_EQ(1, cache.disk_cache()->open_count());
2895 EXPECT_EQ(1, cache.disk_cache()->create_count());
2898 // Test that we don't hit the cache for POST requests if there is a byte range.
2899 TEST(HttpCache, SimplePOST_WithRanges) {
2900 MockHttpCache cache;
2902 MockTransaction transaction(kSimplePOST_Transaction);
2903 transaction.request_headers = "Range: bytes = 0-4\r\n";
2905 const int64 kUploadId = 1; // Just a dummy value.
2907 ScopedVector<UploadElementReader> element_readers;
2908 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2909 ElementsUploadDataStream upload_data_stream(element_readers.Pass(),
2910 kUploadId);
2912 MockHttpRequest request(transaction);
2913 request.upload_data_stream = &upload_data_stream;
2915 // Attempt to populate the cache.
2916 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
2918 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2919 EXPECT_EQ(0, cache.disk_cache()->open_count());
2920 EXPECT_EQ(0, cache.disk_cache()->create_count());
2923 // Tests that a POST is cached separately from a previously cached GET.
2924 TEST(HttpCache, SimplePOST_SeparateCache) {
2925 MockHttpCache cache;
2927 ScopedVector<UploadElementReader> element_readers;
2928 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2929 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1);
2931 MockTransaction transaction(kSimplePOST_Transaction);
2932 MockHttpRequest req1(transaction);
2933 req1.upload_data_stream = &upload_data_stream;
2935 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
2937 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2938 EXPECT_EQ(0, cache.disk_cache()->open_count());
2939 EXPECT_EQ(1, cache.disk_cache()->create_count());
2941 transaction.method = "GET";
2942 MockHttpRequest req2(transaction);
2944 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
2946 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2947 EXPECT_EQ(0, cache.disk_cache()->open_count());
2948 EXPECT_EQ(2, cache.disk_cache()->create_count());
2951 // Tests that a successful POST invalidates a previously cached GET.
2952 TEST(HttpCache, SimplePOST_Invalidate_205) {
2953 MockHttpCache cache;
2955 MockTransaction transaction(kSimpleGET_Transaction);
2956 AddMockTransaction(&transaction);
2957 MockHttpRequest req1(transaction);
2959 // Attempt to populate the cache.
2960 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
2962 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2963 EXPECT_EQ(0, cache.disk_cache()->open_count());
2964 EXPECT_EQ(1, cache.disk_cache()->create_count());
2966 ScopedVector<UploadElementReader> element_readers;
2967 element_readers.push_back(new UploadBytesElementReader("hello", 5));
2968 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1);
2970 transaction.method = "POST";
2971 transaction.status = "HTTP/1.1 205 No Content";
2972 MockHttpRequest req2(transaction);
2973 req2.upload_data_stream = &upload_data_stream;
2975 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
2977 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2978 EXPECT_EQ(0, cache.disk_cache()->open_count());
2979 EXPECT_EQ(2, cache.disk_cache()->create_count());
2981 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
2983 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2984 EXPECT_EQ(0, cache.disk_cache()->open_count());
2985 EXPECT_EQ(3, cache.disk_cache()->create_count());
2986 RemoveMockTransaction(&transaction);
2989 // Tests that a successful POST invalidates a previously cached GET, even when
2990 // there is no upload identifier.
2991 TEST(HttpCache, SimplePOST_NoUploadId_Invalidate_205) {
2992 MockHttpCache cache;
2994 MockTransaction transaction(kSimpleGET_Transaction);
2995 AddMockTransaction(&transaction);
2996 MockHttpRequest req1(transaction);
2998 // Attempt to populate the cache.
2999 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3001 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3002 EXPECT_EQ(0, cache.disk_cache()->open_count());
3003 EXPECT_EQ(1, cache.disk_cache()->create_count());
3005 ScopedVector<UploadElementReader> element_readers;
3006 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3007 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3009 transaction.method = "POST";
3010 transaction.status = "HTTP/1.1 205 No Content";
3011 MockHttpRequest req2(transaction);
3012 req2.upload_data_stream = &upload_data_stream;
3014 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3016 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3017 EXPECT_EQ(0, cache.disk_cache()->open_count());
3018 EXPECT_EQ(1, cache.disk_cache()->create_count());
3020 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3022 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3023 EXPECT_EQ(0, cache.disk_cache()->open_count());
3024 EXPECT_EQ(2, cache.disk_cache()->create_count());
3025 RemoveMockTransaction(&transaction);
3028 // Tests that processing a POST before creating the backend doesn't crash.
3029 TEST(HttpCache, SimplePOST_NoUploadId_NoBackend) {
3030 // This will initialize a cache object with NULL backend.
3031 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
3032 factory->set_fail(true);
3033 factory->FinishCreation();
3034 MockHttpCache cache(factory);
3036 ScopedVector<UploadElementReader> element_readers;
3037 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3038 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3040 MockTransaction transaction(kSimplePOST_Transaction);
3041 AddMockTransaction(&transaction);
3042 MockHttpRequest req(transaction);
3043 req.upload_data_stream = &upload_data_stream;
3045 RunTransactionTestWithRequest(cache.http_cache(), transaction, req, NULL);
3047 RemoveMockTransaction(&transaction);
3050 // Tests that we don't invalidate entries as a result of a failed POST.
3051 TEST(HttpCache, SimplePOST_DontInvalidate_100) {
3052 MockHttpCache cache;
3054 MockTransaction transaction(kSimpleGET_Transaction);
3055 AddMockTransaction(&transaction);
3056 MockHttpRequest req1(transaction);
3058 // Attempt to populate the cache.
3059 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3061 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3062 EXPECT_EQ(0, cache.disk_cache()->open_count());
3063 EXPECT_EQ(1, cache.disk_cache()->create_count());
3065 ScopedVector<UploadElementReader> element_readers;
3066 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3067 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1);
3069 transaction.method = "POST";
3070 transaction.status = "HTTP/1.1 100 Continue";
3071 MockHttpRequest req2(transaction);
3072 req2.upload_data_stream = &upload_data_stream;
3074 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3076 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3077 EXPECT_EQ(0, cache.disk_cache()->open_count());
3078 EXPECT_EQ(2, cache.disk_cache()->create_count());
3080 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3082 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3083 EXPECT_EQ(1, cache.disk_cache()->open_count());
3084 EXPECT_EQ(2, cache.disk_cache()->create_count());
3085 RemoveMockTransaction(&transaction);
3088 // Tests that a HEAD request is not cached by itself.
3089 TEST(HttpCache, SimpleHEAD_LoadOnlyFromCache_Miss) {
3090 MockHttpCache cache;
3091 MockTransaction transaction(kSimplePOST_Transaction);
3092 AddMockTransaction(&transaction);
3093 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3094 transaction.method = "HEAD";
3096 MockHttpRequest request(transaction);
3097 TestCompletionCallback callback;
3099 scoped_ptr<HttpTransaction> trans;
3100 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
3101 ASSERT_TRUE(trans.get());
3103 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3104 ASSERT_EQ(ERR_CACHE_MISS, callback.GetResult(rv));
3106 trans.reset();
3108 EXPECT_EQ(0, cache.network_layer()->transaction_count());
3109 EXPECT_EQ(0, cache.disk_cache()->open_count());
3110 EXPECT_EQ(0, cache.disk_cache()->create_count());
3111 RemoveMockTransaction(&transaction);
3114 // Tests that a HEAD request is served from a cached GET.
3115 TEST(HttpCache, SimpleHEAD_LoadOnlyFromCache_Hit) {
3116 MockHttpCache cache;
3117 MockTransaction transaction(kSimpleGET_Transaction);
3118 AddMockTransaction(&transaction);
3120 // Populate the cache.
3121 RunTransactionTest(cache.http_cache(), transaction);
3123 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3124 EXPECT_EQ(0, cache.disk_cache()->open_count());
3125 EXPECT_EQ(1, cache.disk_cache()->create_count());
3127 // Load from cache.
3128 transaction.method = "HEAD";
3129 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3130 transaction.data = "";
3131 RunTransactionTest(cache.http_cache(), transaction);
3133 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3134 EXPECT_EQ(1, cache.disk_cache()->open_count());
3135 EXPECT_EQ(1, cache.disk_cache()->create_count());
3136 RemoveMockTransaction(&transaction);
3139 // Tests that a read-only request served from the cache preserves CL.
3140 TEST(HttpCache, SimpleHEAD_ContentLengthOnHit_Read) {
3141 MockHttpCache cache;
3142 MockTransaction transaction(kSimpleGET_Transaction);
3143 AddMockTransaction(&transaction);
3144 transaction.response_headers = "Content-Length: 42\n";
3146 // Populate the cache.
3147 RunTransactionTest(cache.http_cache(), transaction);
3149 // Load from cache.
3150 transaction.method = "HEAD";
3151 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3152 transaction.data = "";
3153 std::string headers;
3155 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3157 EXPECT_EQ("HTTP/1.1 200 OK\nContent-Length: 42\n", headers);
3158 RemoveMockTransaction(&transaction);
3161 // Tests that a read-write request served from the cache preserves CL.
3162 TEST(HttpCache, ETagHEAD_ContentLengthOnHit_ReadWrite) {
3163 MockHttpCache cache;
3164 MockTransaction transaction(kETagGET_Transaction);
3165 AddMockTransaction(&transaction);
3166 std::string server_headers(kETagGET_Transaction.response_headers);
3167 server_headers.append("Content-Length: 42\n");
3168 transaction.response_headers = server_headers.data();
3170 // Populate the cache.
3171 RunTransactionTest(cache.http_cache(), transaction);
3173 // Load from cache.
3174 transaction.method = "HEAD";
3175 transaction.data = "";
3176 std::string headers;
3178 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3180 EXPECT_NE(std::string::npos, headers.find("Content-Length: 42\n"));
3181 RemoveMockTransaction(&transaction);
3184 // Tests that a HEAD request that includes byte ranges bypasses the cache.
3185 TEST(HttpCache, SimpleHEAD_WithRanges) {
3186 MockHttpCache cache;
3187 MockTransaction transaction(kSimpleGET_Transaction);
3188 AddMockTransaction(&transaction);
3190 // Populate the cache.
3191 RunTransactionTest(cache.http_cache(), transaction);
3193 // Load from cache.
3194 transaction.method = "HEAD";
3195 transaction.request_headers = "Range: bytes = 0-4\r\n";
3196 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3197 transaction.return_code = ERR_CACHE_MISS;
3198 RunTransactionTest(cache.http_cache(), transaction);
3200 EXPECT_EQ(0, cache.disk_cache()->open_count());
3201 EXPECT_EQ(1, cache.disk_cache()->create_count());
3202 RemoveMockTransaction(&transaction);
3205 // Tests that a HEAD request can be served from a partialy cached resource.
3206 TEST(HttpCache, SimpleHEAD_WithCachedRanges) {
3207 MockHttpCache cache;
3208 AddMockTransaction(&kRangeGET_TransactionOK);
3210 // Write to the cache (40-49).
3211 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
3212 RemoveMockTransaction(&kRangeGET_TransactionOK);
3214 MockTransaction transaction(kSimpleGET_Transaction);
3216 transaction.url = kRangeGET_TransactionOK.url;
3217 transaction.method = "HEAD";
3218 transaction.data = "";
3219 AddMockTransaction(&transaction);
3220 std::string headers;
3222 // Load from cache.
3223 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3225 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
3226 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
3227 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
3228 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3229 EXPECT_EQ(1, cache.disk_cache()->open_count());
3230 EXPECT_EQ(1, cache.disk_cache()->create_count());
3231 RemoveMockTransaction(&transaction);
3234 // Tests that a HEAD request can be served from a truncated resource.
3235 TEST(HttpCache, SimpleHEAD_WithTruncatedEntry) {
3236 MockHttpCache cache;
3237 AddMockTransaction(&kRangeGET_TransactionOK);
3239 std::string raw_headers("HTTP/1.1 200 OK\n"
3240 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
3241 "ETag: \"foo\"\n"
3242 "Accept-Ranges: bytes\n"
3243 "Content-Length: 80\n");
3244 CreateTruncatedEntry(raw_headers, &cache);
3245 RemoveMockTransaction(&kRangeGET_TransactionOK);
3247 MockTransaction transaction(kSimpleGET_Transaction);
3249 transaction.url = kRangeGET_TransactionOK.url;
3250 transaction.method = "HEAD";
3251 transaction.data = "";
3252 AddMockTransaction(&transaction);
3253 std::string headers;
3255 // Load from cache.
3256 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3258 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
3259 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
3260 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
3261 EXPECT_EQ(0, cache.network_layer()->transaction_count());
3262 EXPECT_EQ(1, cache.disk_cache()->open_count());
3263 EXPECT_EQ(1, cache.disk_cache()->create_count());
3264 RemoveMockTransaction(&transaction);
3267 // Tests that a HEAD request updates the cached response.
3268 TEST(HttpCache, TypicalHEAD_UpdatesResponse) {
3269 MockHttpCache cache;
3270 MockTransaction transaction(kTypicalGET_Transaction);
3271 AddMockTransaction(&transaction);
3273 // Populate the cache.
3274 RunTransactionTest(cache.http_cache(), transaction);
3276 // Update the cache.
3277 transaction.method = "HEAD";
3278 transaction.response_headers = "Foo: bar\n";
3279 transaction.data = "";
3280 transaction.status = "HTTP/1.1 304 Not Modified\n";
3281 std::string headers;
3282 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3283 RemoveMockTransaction(&transaction);
3285 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
3286 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3288 MockTransaction transaction2(kTypicalGET_Transaction);
3289 AddMockTransaction(&transaction2);
3291 // Make sure we are done with the previous transaction.
3292 base::MessageLoop::current()->RunUntilIdle();
3294 // Load from the cache.
3295 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE;
3296 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
3298 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
3299 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3300 EXPECT_EQ(2, cache.disk_cache()->open_count());
3301 EXPECT_EQ(1, cache.disk_cache()->create_count());
3302 RemoveMockTransaction(&transaction2);
3305 // Tests that an externally conditionalized HEAD request updates the cache.
3306 TEST(HttpCache, TypicalHEAD_ConditionalizedRequestUpdatesResponse) {
3307 MockHttpCache cache;
3308 MockTransaction transaction(kTypicalGET_Transaction);
3309 AddMockTransaction(&transaction);
3311 // Populate the cache.
3312 RunTransactionTest(cache.http_cache(), transaction);
3314 // Update the cache.
3315 transaction.method = "HEAD";
3316 transaction.request_headers =
3317 "If-Modified-Since: Wed, 28 Nov 2007 00:40:09 GMT\r\n";
3318 transaction.response_headers = "Foo: bar\n";
3319 transaction.data = "";
3320 transaction.status = "HTTP/1.1 304 Not Modified\n";
3321 std::string headers;
3322 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3323 RemoveMockTransaction(&transaction);
3325 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 304 Not Modified\n"));
3326 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3328 MockTransaction transaction2(kTypicalGET_Transaction);
3329 AddMockTransaction(&transaction2);
3331 // Make sure we are done with the previous transaction.
3332 base::MessageLoop::current()->RunUntilIdle();
3334 // Load from the cache.
3335 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE;
3336 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
3338 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
3339 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3340 EXPECT_EQ(2, cache.disk_cache()->open_count());
3341 EXPECT_EQ(1, cache.disk_cache()->create_count());
3342 RemoveMockTransaction(&transaction2);
3345 // Tests that a HEAD request invalidates an old cached entry.
3346 TEST(HttpCache, SimpleHEAD_InvalidatesEntry) {
3347 MockHttpCache cache;
3348 MockTransaction transaction(kTypicalGET_Transaction);
3349 AddMockTransaction(&transaction);
3351 // Populate the cache.
3352 RunTransactionTest(cache.http_cache(), transaction);
3354 // Update the cache.
3355 transaction.method = "HEAD";
3356 transaction.data = "";
3357 RunTransactionTest(cache.http_cache(), transaction);
3358 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3360 // Load from the cache.
3361 transaction.method = "GET";
3362 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
3363 transaction.return_code = ERR_CACHE_MISS;
3364 RunTransactionTest(cache.http_cache(), transaction);
3366 RemoveMockTransaction(&transaction);
3369 // Tests that we do not cache the response of a PUT.
3370 TEST(HttpCache, SimplePUT_Miss) {
3371 MockHttpCache cache;
3373 MockTransaction transaction(kSimplePOST_Transaction);
3374 transaction.method = "PUT";
3376 ScopedVector<UploadElementReader> element_readers;
3377 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3378 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3380 MockHttpRequest request(transaction);
3381 request.upload_data_stream = &upload_data_stream;
3383 // Attempt to populate the cache.
3384 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
3386 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3387 EXPECT_EQ(0, cache.disk_cache()->open_count());
3388 EXPECT_EQ(0, cache.disk_cache()->create_count());
3391 // Tests that we invalidate entries as a result of a PUT.
3392 TEST(HttpCache, SimplePUT_Invalidate) {
3393 MockHttpCache cache;
3395 MockTransaction transaction(kSimpleGET_Transaction);
3396 MockHttpRequest req1(transaction);
3398 // Attempt to populate the cache.
3399 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3401 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3402 EXPECT_EQ(0, cache.disk_cache()->open_count());
3403 EXPECT_EQ(1, cache.disk_cache()->create_count());
3405 ScopedVector<UploadElementReader> element_readers;
3406 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3407 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3409 transaction.method = "PUT";
3410 MockHttpRequest req2(transaction);
3411 req2.upload_data_stream = &upload_data_stream;
3413 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3415 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3416 EXPECT_EQ(1, cache.disk_cache()->open_count());
3417 EXPECT_EQ(1, cache.disk_cache()->create_count());
3419 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3421 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3422 EXPECT_EQ(1, cache.disk_cache()->open_count());
3423 EXPECT_EQ(2, cache.disk_cache()->create_count());
3426 // Tests that we invalidate entries as a result of a PUT.
3427 TEST(HttpCache, SimplePUT_Invalidate_305) {
3428 MockHttpCache cache;
3430 MockTransaction transaction(kSimpleGET_Transaction);
3431 AddMockTransaction(&transaction);
3432 MockHttpRequest req1(transaction);
3434 // Attempt to populate the cache.
3435 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3437 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3438 EXPECT_EQ(0, cache.disk_cache()->open_count());
3439 EXPECT_EQ(1, cache.disk_cache()->create_count());
3441 ScopedVector<UploadElementReader> element_readers;
3442 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3443 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3445 transaction.method = "PUT";
3446 transaction.status = "HTTP/1.1 305 Use Proxy";
3447 MockHttpRequest req2(transaction);
3448 req2.upload_data_stream = &upload_data_stream;
3450 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3452 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3453 EXPECT_EQ(1, cache.disk_cache()->open_count());
3454 EXPECT_EQ(1, cache.disk_cache()->create_count());
3456 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3458 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3459 EXPECT_EQ(1, cache.disk_cache()->open_count());
3460 EXPECT_EQ(2, cache.disk_cache()->create_count());
3461 RemoveMockTransaction(&transaction);
3464 // Tests that we don't invalidate entries as a result of a failed PUT.
3465 TEST(HttpCache, SimplePUT_DontInvalidate_404) {
3466 MockHttpCache cache;
3468 MockTransaction transaction(kSimpleGET_Transaction);
3469 AddMockTransaction(&transaction);
3470 MockHttpRequest req1(transaction);
3472 // Attempt to populate the cache.
3473 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3475 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3476 EXPECT_EQ(0, cache.disk_cache()->open_count());
3477 EXPECT_EQ(1, cache.disk_cache()->create_count());
3479 ScopedVector<UploadElementReader> element_readers;
3480 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3481 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3483 transaction.method = "PUT";
3484 transaction.status = "HTTP/1.1 404 Not Found";
3485 MockHttpRequest req2(transaction);
3486 req2.upload_data_stream = &upload_data_stream;
3488 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3490 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3491 EXPECT_EQ(1, cache.disk_cache()->open_count());
3492 EXPECT_EQ(1, cache.disk_cache()->create_count());
3494 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3496 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3497 EXPECT_EQ(2, cache.disk_cache()->open_count());
3498 EXPECT_EQ(1, cache.disk_cache()->create_count());
3499 RemoveMockTransaction(&transaction);
3502 // Tests that we do not cache the response of a DELETE.
3503 TEST(HttpCache, SimpleDELETE_Miss) {
3504 MockHttpCache cache;
3506 MockTransaction transaction(kSimplePOST_Transaction);
3507 transaction.method = "DELETE";
3509 ScopedVector<UploadElementReader> element_readers;
3510 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3511 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3513 MockHttpRequest request(transaction);
3514 request.upload_data_stream = &upload_data_stream;
3516 // Attempt to populate the cache.
3517 RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL);
3519 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3520 EXPECT_EQ(0, cache.disk_cache()->open_count());
3521 EXPECT_EQ(0, cache.disk_cache()->create_count());
3524 // Tests that we invalidate entries as a result of a DELETE.
3525 TEST(HttpCache, SimpleDELETE_Invalidate) {
3526 MockHttpCache cache;
3528 MockTransaction transaction(kSimpleGET_Transaction);
3529 MockHttpRequest req1(transaction);
3531 // Attempt to populate the cache.
3532 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3534 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3535 EXPECT_EQ(0, cache.disk_cache()->open_count());
3536 EXPECT_EQ(1, cache.disk_cache()->create_count());
3538 ScopedVector<UploadElementReader> element_readers;
3539 element_readers.push_back(new UploadBytesElementReader("hello", 5));
3540 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
3542 transaction.method = "DELETE";
3543 MockHttpRequest req2(transaction);
3544 req2.upload_data_stream = &upload_data_stream;
3546 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, NULL);
3548 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3549 EXPECT_EQ(1, cache.disk_cache()->open_count());
3550 EXPECT_EQ(1, cache.disk_cache()->create_count());
3552 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, NULL);
3554 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3555 EXPECT_EQ(1, cache.disk_cache()->open_count());
3556 EXPECT_EQ(2, cache.disk_cache()->create_count());
3559 // Tests that we invalidate entries as a result of a DELETE.
3560 TEST(HttpCache, SimpleDELETE_Invalidate_301) {
3561 MockHttpCache cache;
3563 MockTransaction transaction(kSimpleGET_Transaction);
3564 AddMockTransaction(&transaction);
3566 // Attempt to populate the cache.
3567 RunTransactionTest(cache.http_cache(), transaction);
3569 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3570 EXPECT_EQ(0, cache.disk_cache()->open_count());
3571 EXPECT_EQ(1, cache.disk_cache()->create_count());
3573 transaction.method = "DELETE";
3574 transaction.status = "HTTP/1.1 301 Moved Permanently ";
3576 RunTransactionTest(cache.http_cache(), transaction);
3578 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3579 EXPECT_EQ(1, cache.disk_cache()->open_count());
3580 EXPECT_EQ(1, cache.disk_cache()->create_count());
3582 transaction.method = "GET";
3583 RunTransactionTest(cache.http_cache(), transaction);
3585 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3586 EXPECT_EQ(1, cache.disk_cache()->open_count());
3587 EXPECT_EQ(2, cache.disk_cache()->create_count());
3588 RemoveMockTransaction(&transaction);
3591 // Tests that we don't invalidate entries as a result of a failed DELETE.
3592 TEST(HttpCache, SimpleDELETE_DontInvalidate_416) {
3593 MockHttpCache cache;
3595 MockTransaction transaction(kSimpleGET_Transaction);
3596 AddMockTransaction(&transaction);
3598 // Attempt to populate the cache.
3599 RunTransactionTest(cache.http_cache(), transaction);
3601 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3602 EXPECT_EQ(0, cache.disk_cache()->open_count());
3603 EXPECT_EQ(1, cache.disk_cache()->create_count());
3605 transaction.method = "DELETE";
3606 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
3608 RunTransactionTest(cache.http_cache(), transaction);
3610 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3611 EXPECT_EQ(1, cache.disk_cache()->open_count());
3612 EXPECT_EQ(1, cache.disk_cache()->create_count());
3614 transaction.method = "GET";
3615 transaction.status = "HTTP/1.1 200 OK";
3616 RunTransactionTest(cache.http_cache(), transaction);
3618 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3619 EXPECT_EQ(2, cache.disk_cache()->open_count());
3620 EXPECT_EQ(1, cache.disk_cache()->create_count());
3621 RemoveMockTransaction(&transaction);
3624 // Tests that we don't invalidate entries after a failed network transaction.
3625 TEST(HttpCache, SimpleGET_DontInvalidateOnFailure) {
3626 MockHttpCache cache;
3628 // Populate the cache.
3629 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
3630 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3632 // Fail the network request.
3633 MockTransaction transaction(kSimpleGET_Transaction);
3634 transaction.return_code = ERR_FAILED;
3635 transaction.load_flags |= LOAD_VALIDATE_CACHE;
3637 AddMockTransaction(&transaction);
3638 RunTransactionTest(cache.http_cache(), transaction);
3639 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3640 RemoveMockTransaction(&transaction);
3642 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
3643 transaction.return_code = OK;
3644 AddMockTransaction(&transaction);
3645 RunTransactionTest(cache.http_cache(), transaction);
3647 // Make sure the transaction didn't reach the network.
3648 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3649 RemoveMockTransaction(&transaction);
3652 TEST(HttpCache, RangeGET_SkipsCache) {
3653 MockHttpCache cache;
3655 // Test that we skip the cache for range GET requests. Eventually, we will
3656 // want to cache these, but we'll still have cases where skipping the cache
3657 // makes sense, so we want to make sure that it works properly.
3659 RunTransactionTest(cache.http_cache(), kRangeGET_Transaction);
3661 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3662 EXPECT_EQ(0, cache.disk_cache()->open_count());
3663 EXPECT_EQ(0, cache.disk_cache()->create_count());
3665 MockTransaction transaction(kSimpleGET_Transaction);
3666 transaction.request_headers = "If-None-Match: foo\r\n";
3667 RunTransactionTest(cache.http_cache(), transaction);
3669 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3670 EXPECT_EQ(0, cache.disk_cache()->open_count());
3671 EXPECT_EQ(0, cache.disk_cache()->create_count());
3673 transaction.request_headers =
3674 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n";
3675 RunTransactionTest(cache.http_cache(), transaction);
3677 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3678 EXPECT_EQ(0, cache.disk_cache()->open_count());
3679 EXPECT_EQ(0, cache.disk_cache()->create_count());
3682 // Test that we skip the cache for range requests that include a validation
3683 // header.
3684 TEST(HttpCache, RangeGET_SkipsCache2) {
3685 MockHttpCache cache;
3687 MockTransaction transaction(kRangeGET_Transaction);
3688 transaction.request_headers = "If-None-Match: foo\r\n"
3689 EXTRA_HEADER
3690 "Range: bytes = 40-49\r\n";
3691 RunTransactionTest(cache.http_cache(), transaction);
3693 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3694 EXPECT_EQ(0, cache.disk_cache()->open_count());
3695 EXPECT_EQ(0, cache.disk_cache()->create_count());
3697 transaction.request_headers =
3698 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n"
3699 EXTRA_HEADER
3700 "Range: bytes = 40-49\r\n";
3701 RunTransactionTest(cache.http_cache(), transaction);
3703 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3704 EXPECT_EQ(0, cache.disk_cache()->open_count());
3705 EXPECT_EQ(0, cache.disk_cache()->create_count());
3707 transaction.request_headers = "If-Range: bla\r\n"
3708 EXTRA_HEADER
3709 "Range: bytes = 40-49\r\n";
3710 RunTransactionTest(cache.http_cache(), transaction);
3712 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3713 EXPECT_EQ(0, cache.disk_cache()->open_count());
3714 EXPECT_EQ(0, cache.disk_cache()->create_count());
3717 TEST(HttpCache, SimpleGET_DoesntLogHeaders) {
3718 MockHttpCache cache;
3720 BoundTestNetLog log;
3721 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction,
3722 log.bound());
3724 EXPECT_FALSE(LogContainsEventType(
3725 log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS));
3728 TEST(HttpCache, RangeGET_LogsHeaders) {
3729 MockHttpCache cache;
3731 BoundTestNetLog log;
3732 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_Transaction,
3733 log.bound());
3735 EXPECT_TRUE(LogContainsEventType(
3736 log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS));
3739 TEST(HttpCache, ExternalValidation_LogsHeaders) {
3740 MockHttpCache cache;
3742 BoundTestNetLog log;
3743 MockTransaction transaction(kSimpleGET_Transaction);
3744 transaction.request_headers = "If-None-Match: foo\r\n" EXTRA_HEADER;
3745 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
3747 EXPECT_TRUE(LogContainsEventType(
3748 log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS));
3751 TEST(HttpCache, SpecialHeaders_LogsHeaders) {
3752 MockHttpCache cache;
3754 BoundTestNetLog log;
3755 MockTransaction transaction(kSimpleGET_Transaction);
3756 transaction.request_headers = "cache-control: no-cache\r\n" EXTRA_HEADER;
3757 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
3759 EXPECT_TRUE(LogContainsEventType(
3760 log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS));
3763 // Tests that receiving 206 for a regular request is handled correctly.
3764 TEST(HttpCache, GET_Crazy206) {
3765 MockHttpCache cache;
3767 // Write to the cache.
3768 MockTransaction transaction(kRangeGET_TransactionOK);
3769 AddMockTransaction(&transaction);
3770 transaction.request_headers = EXTRA_HEADER;
3771 transaction.handler = NULL;
3772 RunTransactionTest(cache.http_cache(), transaction);
3774 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3775 EXPECT_EQ(0, cache.disk_cache()->open_count());
3776 EXPECT_EQ(1, cache.disk_cache()->create_count());
3778 // This should read again from the net.
3779 RunTransactionTest(cache.http_cache(), transaction);
3781 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3782 EXPECT_EQ(0, cache.disk_cache()->open_count());
3783 EXPECT_EQ(2, cache.disk_cache()->create_count());
3784 RemoveMockTransaction(&transaction);
3787 // Tests that receiving 416 for a regular request is handled correctly.
3788 TEST(HttpCache, GET_Crazy416) {
3789 MockHttpCache cache;
3791 // Write to the cache.
3792 MockTransaction transaction(kSimpleGET_Transaction);
3793 AddMockTransaction(&transaction);
3794 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
3795 RunTransactionTest(cache.http_cache(), transaction);
3797 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3798 EXPECT_EQ(0, cache.disk_cache()->open_count());
3799 EXPECT_EQ(1, cache.disk_cache()->create_count());
3801 RemoveMockTransaction(&transaction);
3804 // Tests that we don't store partial responses that can't be validated.
3805 TEST(HttpCache, RangeGET_NoStrongValidators) {
3806 MockHttpCache cache;
3807 std::string headers;
3809 // Attempt to write to the cache (40-49).
3810 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3811 transaction.response_headers = "Content-Length: 10\n"
3812 "Cache-Control: max-age=3600\n"
3813 "ETag: w/\"foo\"\n";
3814 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3816 Verify206Response(headers, 40, 49);
3817 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3818 EXPECT_EQ(0, cache.disk_cache()->open_count());
3819 EXPECT_EQ(1, cache.disk_cache()->create_count());
3821 // Now verify that there's no cached data.
3822 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3823 &headers);
3825 Verify206Response(headers, 40, 49);
3826 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3827 EXPECT_EQ(0, cache.disk_cache()->open_count());
3828 EXPECT_EQ(2, cache.disk_cache()->create_count());
3831 // Tests failures to conditionalize byte range requests.
3832 TEST(HttpCache, RangeGET_NoConditionalization) {
3833 MockHttpCache cache;
3834 cache.FailConditionalizations();
3835 std::string headers;
3837 // Write to the cache (40-49).
3838 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3839 transaction.response_headers = "Content-Length: 10\n"
3840 "ETag: \"foo\"\n";
3841 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3843 Verify206Response(headers, 40, 49);
3844 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3845 EXPECT_EQ(0, cache.disk_cache()->open_count());
3846 EXPECT_EQ(1, cache.disk_cache()->create_count());
3848 // Now verify that the cached data is not used.
3849 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3850 &headers);
3852 Verify206Response(headers, 40, 49);
3853 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3854 EXPECT_EQ(1, cache.disk_cache()->open_count());
3855 EXPECT_EQ(2, cache.disk_cache()->create_count());
3858 // Tests that restarting a partial request when the cached data cannot be
3859 // revalidated logs an event.
3860 TEST(HttpCache, RangeGET_NoValidation_LogsRestart) {
3861 MockHttpCache cache;
3862 cache.FailConditionalizations();
3864 // Write to the cache (40-49).
3865 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3866 transaction.response_headers = "Content-Length: 10\n"
3867 "ETag: \"foo\"\n";
3868 RunTransactionTest(cache.http_cache(), transaction);
3870 // Now verify that the cached data is not used.
3871 BoundTestNetLog log;
3872 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_TransactionOK,
3873 log.bound());
3875 EXPECT_TRUE(LogContainsEventType(
3876 log, NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST));
3879 // Tests that a failure to conditionalize a regular request (no range) with a
3880 // sparse entry results in a full response.
3881 TEST(HttpCache, GET_NoConditionalization) {
3882 MockHttpCache cache;
3883 cache.FailConditionalizations();
3884 std::string headers;
3886 // Write to the cache (40-49).
3887 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3888 transaction.response_headers = "Content-Length: 10\n"
3889 "ETag: \"foo\"\n";
3890 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3892 Verify206Response(headers, 40, 49);
3893 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3894 EXPECT_EQ(0, cache.disk_cache()->open_count());
3895 EXPECT_EQ(1, cache.disk_cache()->create_count());
3897 // Now verify that the cached data is not used.
3898 // Don't ask for a range. The cache will attempt to use the cached data but
3899 // should discard it as it cannot be validated. A regular request should go
3900 // to the server and a new entry should be created.
3901 transaction.request_headers = EXTRA_HEADER;
3902 transaction.data = "Not a range";
3903 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3905 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
3906 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3907 EXPECT_EQ(1, cache.disk_cache()->open_count());
3908 EXPECT_EQ(2, cache.disk_cache()->create_count());
3910 // The last response was saved.
3911 RunTransactionTest(cache.http_cache(), transaction);
3912 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3913 EXPECT_EQ(2, cache.disk_cache()->open_count());
3914 EXPECT_EQ(2, cache.disk_cache()->create_count());
3917 // Verifies that conditionalization failures when asking for a range that would
3918 // require the cache to modify the range to ask, result in a network request
3919 // that matches the user's one.
3920 TEST(HttpCache, RangeGET_NoConditionalization2) {
3921 MockHttpCache cache;
3922 cache.FailConditionalizations();
3923 std::string headers;
3925 // Write to the cache (40-49).
3926 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3927 transaction.response_headers = "Content-Length: 10\n"
3928 "ETag: \"foo\"\n";
3929 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3931 Verify206Response(headers, 40, 49);
3932 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3933 EXPECT_EQ(0, cache.disk_cache()->open_count());
3934 EXPECT_EQ(1, cache.disk_cache()->create_count());
3936 // Now verify that the cached data is not used.
3937 // Ask for a range that extends before and after the cached data so that the
3938 // cache would normally mix data from three sources. After deleting the entry,
3939 // the response will come from a single network request.
3940 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
3941 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
3942 transaction.response_headers = kRangeGET_TransactionOK.response_headers;
3943 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3945 Verify206Response(headers, 20, 59);
3946 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3947 EXPECT_EQ(1, cache.disk_cache()->open_count());
3948 EXPECT_EQ(2, cache.disk_cache()->create_count());
3950 // The last response was saved.
3951 RunTransactionTest(cache.http_cache(), transaction);
3952 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3953 EXPECT_EQ(2, cache.disk_cache()->open_count());
3954 EXPECT_EQ(2, cache.disk_cache()->create_count());
3957 // Tests that we cache partial responses that lack content-length.
3958 TEST(HttpCache, RangeGET_NoContentLength) {
3959 MockHttpCache cache;
3960 std::string headers;
3962 // Attempt to write to the cache (40-49).
3963 MockTransaction transaction(kRangeGET_TransactionOK);
3964 AddMockTransaction(&transaction);
3965 transaction.response_headers = "ETag: \"foo\"\n"
3966 "Accept-Ranges: bytes\n"
3967 "Content-Range: bytes 40-49/80\n";
3968 transaction.handler = NULL;
3969 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3971 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3972 EXPECT_EQ(0, cache.disk_cache()->open_count());
3973 EXPECT_EQ(1, cache.disk_cache()->create_count());
3975 // Now verify that there's no cached data.
3976 transaction.handler = &RangeTransactionServer::RangeHandler;
3977 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3978 &headers);
3980 Verify206Response(headers, 40, 49);
3981 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3982 EXPECT_EQ(1, cache.disk_cache()->open_count());
3983 EXPECT_EQ(1, cache.disk_cache()->create_count());
3985 RemoveMockTransaction(&transaction);
3988 // Tests that we can cache range requests and fetch random blocks from the
3989 // cache and the network.
3990 TEST(HttpCache, RangeGET_OK) {
3991 MockHttpCache cache;
3992 AddMockTransaction(&kRangeGET_TransactionOK);
3993 std::string headers;
3995 // Write to the cache (40-49).
3996 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
3997 &headers);
3999 Verify206Response(headers, 40, 49);
4000 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4001 EXPECT_EQ(0, cache.disk_cache()->open_count());
4002 EXPECT_EQ(1, cache.disk_cache()->create_count());
4004 // Read from the cache (40-49).
4005 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4006 &headers);
4008 Verify206Response(headers, 40, 49);
4009 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4010 EXPECT_EQ(1, 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 to the cache (30-39).
4017 MockTransaction transaction(kRangeGET_TransactionOK);
4018 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
4019 transaction.data = "rg: 30-39 ";
4020 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4022 Verify206Response(headers, 30, 39);
4023 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4024 EXPECT_EQ(2, cache.disk_cache()->open_count());
4025 EXPECT_EQ(1, cache.disk_cache()->create_count());
4027 // Make sure we are done with the previous transaction.
4028 base::MessageLoop::current()->RunUntilIdle();
4030 // Write and read from the cache (20-59).
4031 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
4032 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
4033 BoundTestNetLog log;
4034 LoadTimingInfo load_timing_info;
4035 RunTransactionTestWithResponseAndGetTiming(
4036 cache.http_cache(), transaction, &headers, log.bound(),
4037 &load_timing_info);
4039 Verify206Response(headers, 20, 59);
4040 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4041 EXPECT_EQ(3, cache.disk_cache()->open_count());
4042 EXPECT_EQ(1, cache.disk_cache()->create_count());
4043 TestLoadTimingNetworkRequest(load_timing_info);
4045 RemoveMockTransaction(&kRangeGET_TransactionOK);
4048 // Tests that we can cache range requests and fetch random blocks from the
4049 // cache and the network, with synchronous responses.
4050 TEST(HttpCache, RangeGET_SyncOK) {
4051 MockHttpCache cache;
4053 MockTransaction transaction(kRangeGET_TransactionOK);
4054 transaction.test_mode = TEST_MODE_SYNC_ALL;
4055 AddMockTransaction(&transaction);
4057 // Write to the cache (40-49).
4058 std::string headers;
4059 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4061 Verify206Response(headers, 40, 49);
4062 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4063 EXPECT_EQ(0, cache.disk_cache()->open_count());
4064 EXPECT_EQ(1, cache.disk_cache()->create_count());
4066 // Read from the cache (40-49).
4067 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4069 Verify206Response(headers, 40, 49);
4070 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4071 EXPECT_EQ(0, cache.disk_cache()->open_count());
4072 EXPECT_EQ(1, cache.disk_cache()->create_count());
4074 // Make sure we are done with the previous transaction.
4075 base::MessageLoop::current()->RunUntilIdle();
4077 // Write to the cache (30-39).
4078 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
4079 transaction.data = "rg: 30-39 ";
4080 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4082 Verify206Response(headers, 30, 39);
4083 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4084 EXPECT_EQ(1, cache.disk_cache()->open_count());
4085 EXPECT_EQ(1, cache.disk_cache()->create_count());
4087 // Make sure we are done with the previous transaction.
4088 base::MessageLoop::current()->RunUntilIdle();
4090 // Write and read from the cache (20-59).
4091 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
4092 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
4093 BoundTestNetLog log;
4094 LoadTimingInfo load_timing_info;
4095 RunTransactionTestWithResponseAndGetTiming(
4096 cache.http_cache(), transaction, &headers, log.bound(),
4097 &load_timing_info);
4099 Verify206Response(headers, 20, 59);
4100 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4101 EXPECT_EQ(2, cache.disk_cache()->open_count());
4102 EXPECT_EQ(1, cache.disk_cache()->create_count());
4103 TestLoadTimingNetworkRequest(load_timing_info);
4105 RemoveMockTransaction(&transaction);
4108 // Tests that we don't revalidate an entry unless we are required to do so.
4109 TEST(HttpCache, RangeGET_Revalidate1) {
4110 MockHttpCache cache;
4111 std::string headers;
4113 // Write to the cache (40-49).
4114 MockTransaction transaction(kRangeGET_TransactionOK);
4115 transaction.response_headers =
4116 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
4117 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n" // Should never expire.
4118 "ETag: \"foo\"\n"
4119 "Accept-Ranges: bytes\n"
4120 "Content-Length: 10\n";
4121 AddMockTransaction(&transaction);
4122 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4124 Verify206Response(headers, 40, 49);
4125 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4126 EXPECT_EQ(0, cache.disk_cache()->open_count());
4127 EXPECT_EQ(1, cache.disk_cache()->create_count());
4129 // Read from the cache (40-49).
4130 BoundTestNetLog log;
4131 LoadTimingInfo load_timing_info;
4132 RunTransactionTestWithResponseAndGetTiming(
4133 cache.http_cache(), transaction, &headers, log.bound(),
4134 &load_timing_info);
4136 Verify206Response(headers, 40, 49);
4137 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4138 EXPECT_EQ(1, cache.disk_cache()->open_count());
4139 EXPECT_EQ(1, cache.disk_cache()->create_count());
4140 TestLoadTimingCachedResponse(load_timing_info);
4142 // Read again forcing the revalidation.
4143 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4144 RunTransactionTestWithResponseAndGetTiming(
4145 cache.http_cache(), transaction, &headers, log.bound(),
4146 &load_timing_info);
4148 Verify206Response(headers, 40, 49);
4149 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4150 EXPECT_EQ(1, cache.disk_cache()->open_count());
4151 EXPECT_EQ(1, cache.disk_cache()->create_count());
4152 TestLoadTimingNetworkRequest(load_timing_info);
4154 RemoveMockTransaction(&transaction);
4157 // Checks that we revalidate an entry when the headers say so.
4158 TEST(HttpCache, RangeGET_Revalidate2) {
4159 MockHttpCache cache;
4160 std::string headers;
4162 // Write to the cache (40-49).
4163 MockTransaction transaction(kRangeGET_TransactionOK);
4164 transaction.response_headers =
4165 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
4166 "Expires: Sat, 18 Apr 2009 01:10:43 GMT\n" // Expired.
4167 "ETag: \"foo\"\n"
4168 "Accept-Ranges: bytes\n"
4169 "Content-Length: 10\n";
4170 AddMockTransaction(&transaction);
4171 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4173 Verify206Response(headers, 40, 49);
4174 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4175 EXPECT_EQ(0, cache.disk_cache()->open_count());
4176 EXPECT_EQ(1, cache.disk_cache()->create_count());
4178 // Read from the cache (40-49).
4179 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4180 Verify206Response(headers, 40, 49);
4182 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4183 EXPECT_EQ(1, cache.disk_cache()->open_count());
4184 EXPECT_EQ(1, cache.disk_cache()->create_count());
4186 RemoveMockTransaction(&transaction);
4189 // Tests that we deal with 304s for range requests.
4190 TEST(HttpCache, RangeGET_304) {
4191 MockHttpCache cache;
4192 AddMockTransaction(&kRangeGET_TransactionOK);
4193 std::string headers;
4195 // Write to the cache (40-49).
4196 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4197 &headers);
4199 Verify206Response(headers, 40, 49);
4200 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4201 EXPECT_EQ(0, cache.disk_cache()->open_count());
4202 EXPECT_EQ(1, cache.disk_cache()->create_count());
4204 // Read from the cache (40-49).
4205 RangeTransactionServer handler;
4206 handler.set_not_modified(true);
4207 MockTransaction transaction(kRangeGET_TransactionOK);
4208 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4209 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4211 Verify206Response(headers, 40, 49);
4212 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4213 EXPECT_EQ(1, cache.disk_cache()->open_count());
4214 EXPECT_EQ(1, cache.disk_cache()->create_count());
4216 RemoveMockTransaction(&kRangeGET_TransactionOK);
4219 // Tests that we deal with 206s when revalidating range requests.
4220 TEST(HttpCache, RangeGET_ModifiedResult) {
4221 MockHttpCache cache;
4222 AddMockTransaction(&kRangeGET_TransactionOK);
4223 std::string headers;
4225 // Write to the cache (40-49).
4226 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4227 &headers);
4229 Verify206Response(headers, 40, 49);
4230 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4231 EXPECT_EQ(0, cache.disk_cache()->open_count());
4232 EXPECT_EQ(1, cache.disk_cache()->create_count());
4234 // Attempt to read from the cache (40-49).
4235 RangeTransactionServer handler;
4236 handler.set_modified(true);
4237 MockTransaction transaction(kRangeGET_TransactionOK);
4238 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4239 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4241 Verify206Response(headers, 40, 49);
4242 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4243 EXPECT_EQ(1, cache.disk_cache()->open_count());
4244 EXPECT_EQ(1, cache.disk_cache()->create_count());
4246 // And the entry should be gone.
4247 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4248 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4249 EXPECT_EQ(1, cache.disk_cache()->open_count());
4250 EXPECT_EQ(2, cache.disk_cache()->create_count());
4252 RemoveMockTransaction(&kRangeGET_TransactionOK);
4255 // Tests that when a server returns 206 with a sub-range of the requested range,
4256 // and there is nothing stored in the cache, the returned response is passed to
4257 // the caller as is. In this context, a subrange means a response that starts
4258 // with the same byte that was requested, but that is not the whole range that
4259 // was requested.
4260 TEST(HttpCache, RangeGET_206ReturnsSubrangeRange_NoCachedContent) {
4261 MockHttpCache cache;
4262 std::string headers;
4264 // Request a large range (40-59). The server sends 40-49.
4265 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4266 transaction.request_headers = "Range: bytes = 40-59\r\n" EXTRA_HEADER;
4267 transaction.response_headers =
4268 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4269 "ETag: \"foo\"\n"
4270 "Accept-Ranges: bytes\n"
4271 "Content-Length: 10\n"
4272 "Content-Range: bytes 40-49/80\n";
4273 transaction.handler = nullptr;
4274 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4276 Verify206Response(headers, 40, 49);
4277 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4278 EXPECT_EQ(0, cache.disk_cache()->open_count());
4279 EXPECT_EQ(1, cache.disk_cache()->create_count());
4282 // Tests that when a server returns 206 with a sub-range of the requested range,
4283 // and there was an entry stored in the cache, the cache gets out of the way.
4284 TEST(HttpCache, RangeGET_206ReturnsSubrangeRange_CachedContent) {
4285 MockHttpCache cache;
4286 std::string headers;
4288 // Write to the cache (70-79).
4289 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4290 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4291 transaction.data = "rg: 70-79 ";
4292 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4293 Verify206Response(headers, 70, 79);
4295 // Request a large range (40-79). The cache will ask the server for 40-59.
4296 // The server returns 40-49. The cache should consider the server confused and
4297 // abort caching, restarting the request without caching.
4298 transaction.request_headers = "Range: bytes = 40-79\r\n" EXTRA_HEADER;
4299 transaction.response_headers =
4300 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4301 "ETag: \"foo\"\n"
4302 "Accept-Ranges: bytes\n"
4303 "Content-Length: 10\n"
4304 "Content-Range: bytes 40-49/80\n";
4305 transaction.handler = nullptr;
4306 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4308 // Two new network requests were issued, one from the cache and another after
4309 // deleting the entry.
4310 Verify206Response(headers, 40, 49);
4311 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4312 EXPECT_EQ(1, cache.disk_cache()->open_count());
4313 EXPECT_EQ(1, cache.disk_cache()->create_count());
4315 // The entry was deleted.
4316 RunTransactionTest(cache.http_cache(), transaction);
4317 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4318 EXPECT_EQ(1, cache.disk_cache()->open_count());
4319 EXPECT_EQ(2, cache.disk_cache()->create_count());
4322 // Tests that when a server returns 206 with a sub-range of the requested range,
4323 // and there was an entry stored in the cache, the cache gets out of the way,
4324 // when the caller is not using ranges.
4325 TEST(HttpCache, GET_206ReturnsSubrangeRange_CachedContent) {
4326 MockHttpCache cache;
4327 std::string headers;
4329 // Write to the cache (70-79).
4330 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4331 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4332 transaction.data = "rg: 70-79 ";
4333 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4334 Verify206Response(headers, 70, 79);
4336 // Don't ask for a range. The cache will ask the server for 0-69.
4337 // The server returns 40-49. The cache should consider the server confused and
4338 // abort caching, restarting the request.
4339 // The second network request should not be a byte range request so the server
4340 // should return 200 + "Not a range"
4341 transaction.request_headers = "X-Return-Default-Range:\r\n" EXTRA_HEADER;
4342 transaction.data = "Not a range";
4343 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4345 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4346 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4347 EXPECT_EQ(1, cache.disk_cache()->open_count());
4348 EXPECT_EQ(1, cache.disk_cache()->create_count());
4350 // The entry was deleted.
4351 RunTransactionTest(cache.http_cache(), transaction);
4352 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4353 EXPECT_EQ(1, cache.disk_cache()->open_count());
4354 EXPECT_EQ(2, cache.disk_cache()->create_count());
4357 // Tests that when a server returns 206 with a random range and there is
4358 // nothing stored in the cache, the returned response is passed to the caller
4359 // as is. In this context, a WrongRange means that the returned range may or may
4360 // not have any relationship with the requested range (may or may not be
4361 // contained). The important part is that the first byte doesn't match the first
4362 // requested byte.
4363 TEST(HttpCache, RangeGET_206ReturnsWrongRange_NoCachedContent) {
4364 MockHttpCache cache;
4365 std::string headers;
4367 // Request a large range (30-59). The server sends (40-49).
4368 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4369 transaction.request_headers = "Range: bytes = 30-59\r\n" EXTRA_HEADER;
4370 transaction.response_headers =
4371 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4372 "ETag: \"foo\"\n"
4373 "Accept-Ranges: bytes\n"
4374 "Content-Length: 10\n"
4375 "Content-Range: bytes 40-49/80\n";
4376 transaction.handler = nullptr;
4377 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4379 Verify206Response(headers, 40, 49);
4380 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4381 EXPECT_EQ(0, cache.disk_cache()->open_count());
4382 EXPECT_EQ(1, cache.disk_cache()->create_count());
4384 // The entry was deleted.
4385 RunTransactionTest(cache.http_cache(), transaction);
4386 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4387 EXPECT_EQ(0, cache.disk_cache()->open_count());
4388 EXPECT_EQ(2, cache.disk_cache()->create_count());
4391 // Tests that when a server returns 206 with a random range and there is
4392 // an entry stored in the cache, the cache gets out of the way.
4393 TEST(HttpCache, RangeGET_206ReturnsWrongRange_CachedContent) {
4394 MockHttpCache cache;
4395 std::string headers;
4397 // Write to the cache (70-79).
4398 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4399 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4400 transaction.data = "rg: 70-79 ";
4401 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4402 Verify206Response(headers, 70, 79);
4404 // Request a large range (30-79). The cache will ask the server for 30-69.
4405 // The server returns 40-49. The cache should consider the server confused and
4406 // abort caching, returning the weird range to the caller.
4407 transaction.request_headers = "Range: bytes = 30-79\r\n" EXTRA_HEADER;
4408 transaction.response_headers =
4409 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
4410 "ETag: \"foo\"\n"
4411 "Accept-Ranges: bytes\n"
4412 "Content-Length: 10\n"
4413 "Content-Range: bytes 40-49/80\n";
4414 transaction.handler = nullptr;
4415 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4417 Verify206Response(headers, 40, 49);
4418 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4419 EXPECT_EQ(1, cache.disk_cache()->open_count());
4420 EXPECT_EQ(1, cache.disk_cache()->create_count());
4422 // The entry was deleted.
4423 RunTransactionTest(cache.http_cache(), transaction);
4424 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4425 EXPECT_EQ(1, cache.disk_cache()->open_count());
4426 EXPECT_EQ(2, cache.disk_cache()->create_count());
4429 // Tests that when a caller asks for a range beyond EOF, with an empty cache,
4430 // the response matches the one provided by the server.
4431 TEST(HttpCache, RangeGET_206ReturnsSmallerFile_NoCachedContent) {
4432 MockHttpCache cache;
4433 std::string headers;
4435 // Request a large range (70-99). The server sends 70-79.
4436 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4437 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
4438 transaction.data = "rg: 70-79 ";
4439 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4441 Verify206Response(headers, 70, 79);
4442 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4443 EXPECT_EQ(0, cache.disk_cache()->open_count());
4444 EXPECT_EQ(1, cache.disk_cache()->create_count());
4446 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4447 EXPECT_EQ(1, cache.disk_cache()->open_count());
4450 // Tests that when a caller asks for a range beyond EOF, with a cached entry,
4451 // the cache automatically fixes the request.
4452 TEST(HttpCache, RangeGET_206ReturnsSmallerFile_CachedContent) {
4453 MockHttpCache cache;
4454 std::string headers;
4456 // Write to the cache (40-49).
4457 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4458 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4460 // Request a large range (70-99). The server sends 70-79.
4461 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
4462 transaction.data = "rg: 70-79 ";
4463 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4465 Verify206Response(headers, 70, 79);
4466 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4467 EXPECT_EQ(1, cache.disk_cache()->open_count());
4468 EXPECT_EQ(1, cache.disk_cache()->create_count());
4470 // The entry was not deleted (the range was automatically fixed).
4471 RunTransactionTest(cache.http_cache(), transaction);
4472 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4473 EXPECT_EQ(2, cache.disk_cache()->open_count());
4474 EXPECT_EQ(1, cache.disk_cache()->create_count());
4477 // Tests that when a caller asks for a not-satisfiable range, the server's
4478 // response is forwarded to the caller.
4479 TEST(HttpCache, RangeGET_416_NoCachedContent) {
4480 MockHttpCache cache;
4481 std::string headers;
4483 // Request a range beyond EOF (80-99).
4484 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4485 transaction.request_headers = "Range: bytes = 80-99\r\n" EXTRA_HEADER;
4486 transaction.data = "";
4487 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
4488 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4490 EXPECT_EQ(0U, headers.find(transaction.status));
4491 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4492 EXPECT_EQ(0, cache.disk_cache()->open_count());
4493 EXPECT_EQ(1, cache.disk_cache()->create_count());
4495 // The entry was deleted.
4496 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
4497 EXPECT_EQ(2, cache.disk_cache()->create_count());
4500 // Tests that we cache 301s for range requests.
4501 TEST(HttpCache, RangeGET_301) {
4502 MockHttpCache cache;
4503 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4504 transaction.status = "HTTP/1.1 301 Moved Permanently";
4505 transaction.response_headers = "Location: http://www.bar.com/\n";
4506 transaction.data = "";
4507 transaction.handler = NULL;
4509 // Write to the cache.
4510 RunTransactionTest(cache.http_cache(), transaction);
4511 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4512 EXPECT_EQ(0, cache.disk_cache()->open_count());
4513 EXPECT_EQ(1, cache.disk_cache()->create_count());
4515 // Read from the cache.
4516 RunTransactionTest(cache.http_cache(), transaction);
4517 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4518 EXPECT_EQ(1, cache.disk_cache()->open_count());
4519 EXPECT_EQ(1, cache.disk_cache()->create_count());
4522 // Tests that we can cache range requests when the start or end is unknown.
4523 // We start with one suffix request, followed by a request from a given point.
4524 TEST(HttpCache, UnknownRangeGET_1) {
4525 MockHttpCache cache;
4526 AddMockTransaction(&kRangeGET_TransactionOK);
4527 std::string headers;
4529 // Write to the cache (70-79).
4530 MockTransaction transaction(kRangeGET_TransactionOK);
4531 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
4532 transaction.data = "rg: 70-79 ";
4533 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4535 Verify206Response(headers, 70, 79);
4536 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4537 EXPECT_EQ(0, cache.disk_cache()->open_count());
4538 EXPECT_EQ(1, cache.disk_cache()->create_count());
4540 // Make sure we are done with the previous transaction.
4541 base::MessageLoop::current()->RunUntilIdle();
4543 // Write and read from the cache (60-79).
4544 transaction.request_headers = "Range: bytes = 60-\r\n" EXTRA_HEADER;
4545 transaction.data = "rg: 60-69 rg: 70-79 ";
4546 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4548 Verify206Response(headers, 60, 79);
4549 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4550 EXPECT_EQ(1, cache.disk_cache()->open_count());
4551 EXPECT_EQ(1, cache.disk_cache()->create_count());
4553 RemoveMockTransaction(&kRangeGET_TransactionOK);
4556 // Tests that we can cache range requests when the start or end is unknown.
4557 // We start with one request from a given point, followed by a suffix request.
4558 // We'll also verify that synchronous cache responses work as intended.
4559 TEST(HttpCache, UnknownRangeGET_2) {
4560 MockHttpCache cache;
4561 std::string headers;
4563 MockTransaction transaction(kRangeGET_TransactionOK);
4564 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
4565 TEST_MODE_SYNC_CACHE_READ |
4566 TEST_MODE_SYNC_CACHE_WRITE;
4567 AddMockTransaction(&transaction);
4569 // Write to the cache (70-79).
4570 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
4571 transaction.data = "rg: 70-79 ";
4572 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4574 Verify206Response(headers, 70, 79);
4575 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4576 EXPECT_EQ(0, cache.disk_cache()->open_count());
4577 EXPECT_EQ(1, cache.disk_cache()->create_count());
4579 // Make sure we are done with the previous transaction.
4580 base::MessageLoop::current()->RunUntilIdle();
4582 // Write and read from the cache (60-79).
4583 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
4584 transaction.data = "rg: 60-69 rg: 70-79 ";
4585 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4587 Verify206Response(headers, 60, 79);
4588 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4589 EXPECT_EQ(1, cache.disk_cache()->open_count());
4590 EXPECT_EQ(1, cache.disk_cache()->create_count());
4592 RemoveMockTransaction(&transaction);
4595 // Tests that receiving Not Modified when asking for an open range doesn't mess
4596 // up things.
4597 TEST(HttpCache, UnknownRangeGET_304) {
4598 MockHttpCache cache;
4599 std::string headers;
4601 MockTransaction transaction(kRangeGET_TransactionOK);
4602 AddMockTransaction(&transaction);
4604 RangeTransactionServer handler;
4605 handler.set_not_modified(true);
4607 // Ask for the end of the file, without knowing the length.
4608 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
4609 transaction.data = "";
4610 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4612 // We just bypass the cache.
4613 EXPECT_EQ(0U, headers.find("HTTP/1.1 304 Not Modified\n"));
4614 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4615 EXPECT_EQ(0, cache.disk_cache()->open_count());
4616 EXPECT_EQ(1, cache.disk_cache()->create_count());
4618 RunTransactionTest(cache.http_cache(), transaction);
4619 EXPECT_EQ(2, cache.disk_cache()->create_count());
4621 RemoveMockTransaction(&transaction);
4624 // Tests that we can handle non-range requests when we have cached a range.
4625 TEST(HttpCache, GET_Previous206) {
4626 MockHttpCache cache;
4627 AddMockTransaction(&kRangeGET_TransactionOK);
4628 std::string headers;
4629 BoundTestNetLog log;
4630 LoadTimingInfo load_timing_info;
4632 // Write to the cache (40-49).
4633 RunTransactionTestWithResponseAndGetTiming(
4634 cache.http_cache(), kRangeGET_TransactionOK, &headers, log.bound(),
4635 &load_timing_info);
4637 Verify206Response(headers, 40, 49);
4638 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4639 EXPECT_EQ(0, cache.disk_cache()->open_count());
4640 EXPECT_EQ(1, cache.disk_cache()->create_count());
4641 TestLoadTimingNetworkRequest(load_timing_info);
4643 // Write and read from the cache (0-79), when not asked for a range.
4644 MockTransaction transaction(kRangeGET_TransactionOK);
4645 transaction.request_headers = EXTRA_HEADER;
4646 transaction.data = kFullRangeData;
4647 RunTransactionTestWithResponseAndGetTiming(
4648 cache.http_cache(), transaction, &headers, log.bound(),
4649 &load_timing_info);
4651 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4652 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4653 EXPECT_EQ(1, cache.disk_cache()->open_count());
4654 EXPECT_EQ(1, cache.disk_cache()->create_count());
4655 TestLoadTimingNetworkRequest(load_timing_info);
4657 RemoveMockTransaction(&kRangeGET_TransactionOK);
4660 // Tests that we can handle non-range requests when we have cached the first
4661 // part of the object and the server replies with 304 (Not Modified).
4662 TEST(HttpCache, GET_Previous206_NotModified) {
4663 MockHttpCache cache;
4665 MockTransaction transaction(kRangeGET_TransactionOK);
4666 AddMockTransaction(&transaction);
4667 std::string headers;
4668 BoundTestNetLog log;
4669 LoadTimingInfo load_timing_info;
4671 // Write to the cache (0-9).
4672 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
4673 transaction.data = "rg: 00-09 ";
4674 RunTransactionTestWithResponseAndGetTiming(
4675 cache.http_cache(), transaction, &headers, log.bound(),
4676 &load_timing_info);
4677 Verify206Response(headers, 0, 9);
4678 TestLoadTimingNetworkRequest(load_timing_info);
4680 // Write to the cache (70-79).
4681 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4682 transaction.data = "rg: 70-79 ";
4683 RunTransactionTestWithResponseAndGetTiming(
4684 cache.http_cache(), transaction, &headers, log.bound(),
4685 &load_timing_info);
4686 Verify206Response(headers, 70, 79);
4688 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4689 EXPECT_EQ(1, cache.disk_cache()->open_count());
4690 EXPECT_EQ(1, cache.disk_cache()->create_count());
4691 TestLoadTimingNetworkRequest(load_timing_info);
4693 // Read from the cache (0-9), write and read from cache (10 - 79).
4694 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4695 transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER;
4696 transaction.data = kFullRangeData;
4697 RunTransactionTestWithResponseAndGetTiming(
4698 cache.http_cache(), transaction, &headers, log.bound(),
4699 &load_timing_info);
4701 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4702 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4703 EXPECT_EQ(2, cache.disk_cache()->open_count());
4704 EXPECT_EQ(1, cache.disk_cache()->create_count());
4705 TestLoadTimingNetworkRequest(load_timing_info);
4707 RemoveMockTransaction(&transaction);
4710 // Tests that we can handle a regular request to a sparse entry, that results in
4711 // new content provided by the server (206).
4712 TEST(HttpCache, GET_Previous206_NewContent) {
4713 MockHttpCache cache;
4714 AddMockTransaction(&kRangeGET_TransactionOK);
4715 std::string headers;
4717 // Write to the cache (0-9).
4718 MockTransaction transaction(kRangeGET_TransactionOK);
4719 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
4720 transaction.data = "rg: 00-09 ";
4721 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4723 Verify206Response(headers, 0, 9);
4724 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4725 EXPECT_EQ(0, cache.disk_cache()->open_count());
4726 EXPECT_EQ(1, cache.disk_cache()->create_count());
4728 // Now we'll issue a request without any range that should result first in a
4729 // 206 (when revalidating), and then in a weird standard answer: the test
4730 // server will not modify the response so we'll get the default range... a
4731 // real server will answer with 200.
4732 MockTransaction transaction2(kRangeGET_TransactionOK);
4733 transaction2.request_headers = EXTRA_HEADER;
4734 transaction2.load_flags |= LOAD_VALIDATE_CACHE;
4735 transaction2.data = "Not a range";
4736 RangeTransactionServer handler;
4737 handler.set_modified(true);
4738 BoundTestNetLog log;
4739 LoadTimingInfo load_timing_info;
4740 RunTransactionTestWithResponseAndGetTiming(
4741 cache.http_cache(), transaction2, &headers, log.bound(),
4742 &load_timing_info);
4744 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4745 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4746 EXPECT_EQ(1, cache.disk_cache()->open_count());
4747 EXPECT_EQ(1, cache.disk_cache()->create_count());
4748 TestLoadTimingNetworkRequest(load_timing_info);
4750 // Verify that the previous request deleted the entry.
4751 RunTransactionTest(cache.http_cache(), transaction);
4752 EXPECT_EQ(2, cache.disk_cache()->create_count());
4754 RemoveMockTransaction(&transaction);
4757 // Tests that we can handle cached 206 responses that are not sparse.
4758 TEST(HttpCache, GET_Previous206_NotSparse) {
4759 MockHttpCache cache;
4761 // Create a disk cache entry that stores 206 headers while not being sparse.
4762 disk_cache::Entry* entry;
4763 ASSERT_TRUE(cache.CreateBackendEntry(kSimpleGET_Transaction.url, &entry,
4764 NULL));
4766 std::string raw_headers(kRangeGET_TransactionOK.status);
4767 raw_headers.append("\n");
4768 raw_headers.append(kRangeGET_TransactionOK.response_headers);
4769 raw_headers =
4770 HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size());
4772 HttpResponseInfo response;
4773 response.headers = new HttpResponseHeaders(raw_headers);
4774 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
4776 scoped_refptr<IOBuffer> buf(new IOBuffer(500));
4777 int len = static_cast<int>(base::strlcpy(buf->data(),
4778 kRangeGET_TransactionOK.data, 500));
4779 TestCompletionCallback cb;
4780 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
4781 EXPECT_EQ(len, cb.GetResult(rv));
4782 entry->Close();
4784 // Now see that we don't use the stored entry.
4785 std::string headers;
4786 BoundTestNetLog log;
4787 LoadTimingInfo load_timing_info;
4788 RunTransactionTestWithResponseAndGetTiming(
4789 cache.http_cache(), kSimpleGET_Transaction, &headers, log.bound(),
4790 &load_timing_info);
4792 // We are expecting a 200.
4793 std::string expected_headers(kSimpleGET_Transaction.status);
4794 expected_headers.append("\n");
4795 expected_headers.append(kSimpleGET_Transaction.response_headers);
4796 EXPECT_EQ(expected_headers, headers);
4797 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4798 EXPECT_EQ(1, cache.disk_cache()->open_count());
4799 EXPECT_EQ(2, cache.disk_cache()->create_count());
4800 TestLoadTimingNetworkRequest(load_timing_info);
4803 // Tests that we can handle cached 206 responses that are not sparse. This time
4804 // we issue a range request and expect to receive a range.
4805 TEST(HttpCache, RangeGET_Previous206_NotSparse_2) {
4806 MockHttpCache cache;
4807 AddMockTransaction(&kRangeGET_TransactionOK);
4809 // Create a disk cache entry that stores 206 headers while not being sparse.
4810 disk_cache::Entry* entry;
4811 ASSERT_TRUE(cache.CreateBackendEntry(kRangeGET_TransactionOK.url, &entry,
4812 NULL));
4814 std::string raw_headers(kRangeGET_TransactionOK.status);
4815 raw_headers.append("\n");
4816 raw_headers.append(kRangeGET_TransactionOK.response_headers);
4817 raw_headers =
4818 HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size());
4820 HttpResponseInfo response;
4821 response.headers = new HttpResponseHeaders(raw_headers);
4822 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
4824 scoped_refptr<IOBuffer> buf(new IOBuffer(500));
4825 int len = static_cast<int>(base::strlcpy(buf->data(),
4826 kRangeGET_TransactionOK.data, 500));
4827 TestCompletionCallback cb;
4828 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
4829 EXPECT_EQ(len, cb.GetResult(rv));
4830 entry->Close();
4832 // Now see that we don't use the stored entry.
4833 std::string headers;
4834 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
4835 &headers);
4837 // We are expecting a 206.
4838 Verify206Response(headers, 40, 49);
4839 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4840 EXPECT_EQ(1, cache.disk_cache()->open_count());
4841 EXPECT_EQ(2, cache.disk_cache()->create_count());
4843 RemoveMockTransaction(&kRangeGET_TransactionOK);
4846 // Tests that we can handle cached 206 responses that can't be validated.
4847 TEST(HttpCache, GET_Previous206_NotValidation) {
4848 MockHttpCache cache;
4850 // Create a disk cache entry that stores 206 headers.
4851 disk_cache::Entry* entry;
4852 ASSERT_TRUE(cache.CreateBackendEntry(kSimpleGET_Transaction.url, &entry,
4853 NULL));
4855 // Make sure that the headers cannot be validated with the server.
4856 std::string raw_headers(kRangeGET_TransactionOK.status);
4857 raw_headers.append("\n");
4858 raw_headers.append("Content-Length: 80\n");
4859 raw_headers =
4860 HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size());
4862 HttpResponseInfo response;
4863 response.headers = new HttpResponseHeaders(raw_headers);
4864 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
4866 scoped_refptr<IOBuffer> buf(new IOBuffer(500));
4867 int len = static_cast<int>(base::strlcpy(buf->data(),
4868 kRangeGET_TransactionOK.data, 500));
4869 TestCompletionCallback cb;
4870 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
4871 EXPECT_EQ(len, cb.GetResult(rv));
4872 entry->Close();
4874 // Now see that we don't use the stored entry.
4875 std::string headers;
4876 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction,
4877 &headers);
4879 // We are expecting a 200.
4880 std::string expected_headers(kSimpleGET_Transaction.status);
4881 expected_headers.append("\n");
4882 expected_headers.append(kSimpleGET_Transaction.response_headers);
4883 EXPECT_EQ(expected_headers, headers);
4884 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4885 EXPECT_EQ(1, cache.disk_cache()->open_count());
4886 EXPECT_EQ(2, cache.disk_cache()->create_count());
4889 // Tests that we can handle range requests with cached 200 responses.
4890 TEST(HttpCache, RangeGET_Previous200) {
4891 MockHttpCache cache;
4893 // Store the whole thing with status 200.
4894 MockTransaction transaction(kTypicalGET_Transaction);
4895 transaction.url = kRangeGET_TransactionOK.url;
4896 transaction.data = kFullRangeData;
4897 AddMockTransaction(&transaction);
4898 RunTransactionTest(cache.http_cache(), transaction);
4899 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4900 EXPECT_EQ(0, cache.disk_cache()->open_count());
4901 EXPECT_EQ(1, cache.disk_cache()->create_count());
4903 RemoveMockTransaction(&transaction);
4904 AddMockTransaction(&kRangeGET_TransactionOK);
4906 // Now see that we use the stored entry.
4907 std::string headers;
4908 MockTransaction transaction2(kRangeGET_TransactionOK);
4909 RangeTransactionServer handler;
4910 handler.set_not_modified(true);
4911 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
4913 // We are expecting a 206.
4914 Verify206Response(headers, 40, 49);
4915 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4916 EXPECT_EQ(1, cache.disk_cache()->open_count());
4917 EXPECT_EQ(1, cache.disk_cache()->create_count());
4919 // The last transaction has finished so make sure the entry is deactivated.
4920 base::MessageLoop::current()->RunUntilIdle();
4922 // Make a request for an invalid range.
4923 MockTransaction transaction3(kRangeGET_TransactionOK);
4924 transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER;
4925 transaction3.data = transaction.data;
4926 transaction3.load_flags = LOAD_PREFERRING_CACHE;
4927 RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers);
4928 EXPECT_EQ(2, cache.disk_cache()->open_count());
4929 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 "));
4930 EXPECT_EQ(std::string::npos, headers.find("Content-Range:"));
4931 EXPECT_EQ(std::string::npos, headers.find("Content-Length: 80"));
4933 // Make sure the entry is deactivated.
4934 base::MessageLoop::current()->RunUntilIdle();
4936 // Even though the request was invalid, we should have the entry.
4937 RunTransactionTest(cache.http_cache(), transaction2);
4938 EXPECT_EQ(3, cache.disk_cache()->open_count());
4940 // Make sure the entry is deactivated.
4941 base::MessageLoop::current()->RunUntilIdle();
4943 // Now we should receive a range from the server and drop the stored entry.
4944 handler.set_not_modified(false);
4945 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
4946 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
4947 Verify206Response(headers, 40, 49);
4948 EXPECT_EQ(4, cache.network_layer()->transaction_count());
4949 EXPECT_EQ(4, cache.disk_cache()->open_count());
4950 EXPECT_EQ(1, cache.disk_cache()->create_count());
4952 RunTransactionTest(cache.http_cache(), transaction2);
4953 EXPECT_EQ(2, cache.disk_cache()->create_count());
4955 RemoveMockTransaction(&kRangeGET_TransactionOK);
4958 // Tests that we can handle a 200 response when dealing with sparse entries.
4959 TEST(HttpCache, RangeRequestResultsIn200) {
4960 MockHttpCache cache;
4961 AddMockTransaction(&kRangeGET_TransactionOK);
4962 std::string headers;
4964 // Write to the cache (70-79).
4965 MockTransaction transaction(kRangeGET_TransactionOK);
4966 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
4967 transaction.data = "rg: 70-79 ";
4968 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4970 Verify206Response(headers, 70, 79);
4971 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4972 EXPECT_EQ(0, cache.disk_cache()->open_count());
4973 EXPECT_EQ(1, cache.disk_cache()->create_count());
4975 // Now we'll issue a request that results in a plain 200 response, but to
4976 // the to the same URL that we used to store sparse data, and making sure
4977 // that we ask for a range.
4978 RemoveMockTransaction(&kRangeGET_TransactionOK);
4979 MockTransaction transaction2(kSimpleGET_Transaction);
4980 transaction2.url = kRangeGET_TransactionOK.url;
4981 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
4982 AddMockTransaction(&transaction2);
4984 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
4986 std::string expected_headers(kSimpleGET_Transaction.status);
4987 expected_headers.append("\n");
4988 expected_headers.append(kSimpleGET_Transaction.response_headers);
4989 EXPECT_EQ(expected_headers, headers);
4990 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4991 EXPECT_EQ(1, cache.disk_cache()->open_count());
4992 EXPECT_EQ(1, cache.disk_cache()->create_count());
4994 RemoveMockTransaction(&transaction2);
4997 // Tests that a range request that falls outside of the size that we know about
4998 // only deletes the entry if the resource has indeed changed.
4999 TEST(HttpCache, RangeGET_MoreThanCurrentSize) {
5000 MockHttpCache cache;
5001 AddMockTransaction(&kRangeGET_TransactionOK);
5002 std::string headers;
5004 // Write to the cache (40-49).
5005 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
5006 &headers);
5008 Verify206Response(headers, 40, 49);
5009 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5010 EXPECT_EQ(0, cache.disk_cache()->open_count());
5011 EXPECT_EQ(1, cache.disk_cache()->create_count());
5013 // A weird request should not delete this entry. Ask for bytes 120-.
5014 MockTransaction transaction(kRangeGET_TransactionOK);
5015 transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER;
5016 transaction.data = "";
5017 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5019 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
5020 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5021 EXPECT_EQ(1, cache.disk_cache()->open_count());
5022 EXPECT_EQ(1, cache.disk_cache()->create_count());
5024 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5025 EXPECT_EQ(2, cache.disk_cache()->open_count());
5026 EXPECT_EQ(1, cache.disk_cache()->create_count());
5028 RemoveMockTransaction(&kRangeGET_TransactionOK);
5031 // Tests that we don't delete a sparse entry when we cancel a request.
5032 TEST(HttpCache, RangeGET_Cancel) {
5033 MockHttpCache cache;
5034 AddMockTransaction(&kRangeGET_TransactionOK);
5036 MockHttpRequest request(kRangeGET_TransactionOK);
5038 Context* c = new Context();
5039 int rv = cache.CreateTransaction(&c->trans);
5040 ASSERT_EQ(OK, rv);
5042 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5043 if (rv == ERR_IO_PENDING)
5044 rv = c->callback.WaitForResult();
5046 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5047 EXPECT_EQ(0, cache.disk_cache()->open_count());
5048 EXPECT_EQ(1, cache.disk_cache()->create_count());
5050 // Make sure that the entry has some data stored.
5051 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10));
5052 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5053 if (rv == ERR_IO_PENDING)
5054 rv = c->callback.WaitForResult();
5055 EXPECT_EQ(buf->size(), rv);
5057 // Destroy the transaction.
5058 delete c;
5060 // Verify that the entry has not been deleted.
5061 disk_cache::Entry* entry;
5062 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5063 entry->Close();
5064 RemoveMockTransaction(&kRangeGET_TransactionOK);
5067 // Tests that we don't delete a sparse entry when we start a new request after
5068 // cancelling the previous one.
5069 TEST(HttpCache, RangeGET_Cancel2) {
5070 MockHttpCache cache;
5071 AddMockTransaction(&kRangeGET_TransactionOK);
5073 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5074 MockHttpRequest request(kRangeGET_TransactionOK);
5075 request.load_flags |= LOAD_VALIDATE_CACHE;
5077 Context* c = new Context();
5078 int rv = cache.CreateTransaction(&c->trans);
5079 ASSERT_EQ(OK, rv);
5081 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5082 if (rv == ERR_IO_PENDING)
5083 rv = c->callback.WaitForResult();
5085 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5086 EXPECT_EQ(1, cache.disk_cache()->open_count());
5087 EXPECT_EQ(1, cache.disk_cache()->create_count());
5089 // Make sure that we revalidate the entry and read from the cache (a single
5090 // read will return while waiting for the network).
5091 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5));
5092 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5093 EXPECT_EQ(5, c->callback.GetResult(rv));
5094 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5095 EXPECT_EQ(ERR_IO_PENDING, rv);
5097 // Destroy the transaction before completing the read.
5098 delete c;
5100 // We have the read and the delete (OnProcessPendingQueue) waiting on the
5101 // message loop. This means that a new transaction will just reuse the same
5102 // active entry (no open or create).
5104 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5106 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5107 EXPECT_EQ(1, cache.disk_cache()->open_count());
5108 EXPECT_EQ(1, cache.disk_cache()->create_count());
5109 RemoveMockTransaction(&kRangeGET_TransactionOK);
5112 // A slight variation of the previous test, this time we cancel two requests in
5113 // a row, making sure that the second is waiting for the entry to be ready.
5114 TEST(HttpCache, RangeGET_Cancel3) {
5115 MockHttpCache cache;
5116 AddMockTransaction(&kRangeGET_TransactionOK);
5118 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5119 MockHttpRequest request(kRangeGET_TransactionOK);
5120 request.load_flags |= LOAD_VALIDATE_CACHE;
5122 Context* c = new Context();
5123 int rv = cache.CreateTransaction(&c->trans);
5124 ASSERT_EQ(OK, rv);
5126 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5127 EXPECT_EQ(ERR_IO_PENDING, rv);
5128 rv = c->callback.WaitForResult();
5130 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5131 EXPECT_EQ(1, cache.disk_cache()->open_count());
5132 EXPECT_EQ(1, cache.disk_cache()->create_count());
5134 // Make sure that we revalidate the entry and read from the cache (a single
5135 // read will return while waiting for the network).
5136 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5));
5137 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5138 EXPECT_EQ(5, c->callback.GetResult(rv));
5139 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5140 EXPECT_EQ(ERR_IO_PENDING, rv);
5142 // Destroy the transaction before completing the read.
5143 delete c;
5145 // We have the read and the delete (OnProcessPendingQueue) waiting on the
5146 // message loop. This means that a new transaction will just reuse the same
5147 // active entry (no open or create).
5149 c = new Context();
5150 rv = cache.CreateTransaction(&c->trans);
5151 ASSERT_EQ(OK, rv);
5153 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5154 EXPECT_EQ(ERR_IO_PENDING, rv);
5156 MockDiskEntry::IgnoreCallbacks(true);
5157 base::MessageLoop::current()->RunUntilIdle();
5158 MockDiskEntry::IgnoreCallbacks(false);
5160 // The new transaction is waiting for the query range callback.
5161 delete c;
5163 // And we should not crash when the callback is delivered.
5164 base::MessageLoop::current()->RunUntilIdle();
5166 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5167 EXPECT_EQ(1, cache.disk_cache()->open_count());
5168 EXPECT_EQ(1, cache.disk_cache()->create_count());
5169 RemoveMockTransaction(&kRangeGET_TransactionOK);
5172 // Tests that an invalid range response results in no cached entry.
5173 TEST(HttpCache, RangeGET_InvalidResponse1) {
5174 MockHttpCache cache;
5175 std::string headers;
5177 MockTransaction transaction(kRangeGET_TransactionOK);
5178 transaction.handler = NULL;
5179 transaction.response_headers = "Content-Range: bytes 40-49/45\n"
5180 "Content-Length: 10\n";
5181 AddMockTransaction(&transaction);
5182 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5184 std::string expected(transaction.status);
5185 expected.append("\n");
5186 expected.append(transaction.response_headers);
5187 EXPECT_EQ(expected, headers);
5189 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5190 EXPECT_EQ(0, cache.disk_cache()->open_count());
5191 EXPECT_EQ(1, cache.disk_cache()->create_count());
5193 // Verify that we don't have a cached entry.
5194 disk_cache::Entry* entry;
5195 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5197 RemoveMockTransaction(&kRangeGET_TransactionOK);
5200 // Tests that we reject a range that doesn't match the content-length.
5201 TEST(HttpCache, RangeGET_InvalidResponse2) {
5202 MockHttpCache cache;
5203 std::string headers;
5205 MockTransaction transaction(kRangeGET_TransactionOK);
5206 transaction.handler = NULL;
5207 transaction.response_headers = "Content-Range: bytes 40-49/80\n"
5208 "Content-Length: 20\n";
5209 AddMockTransaction(&transaction);
5210 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5212 std::string expected(transaction.status);
5213 expected.append("\n");
5214 expected.append(transaction.response_headers);
5215 EXPECT_EQ(expected, headers);
5217 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5218 EXPECT_EQ(0, cache.disk_cache()->open_count());
5219 EXPECT_EQ(1, cache.disk_cache()->create_count());
5221 // Verify that we don't have a cached entry.
5222 disk_cache::Entry* entry;
5223 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5225 RemoveMockTransaction(&kRangeGET_TransactionOK);
5228 // Tests that if a server tells us conflicting information about a resource we
5229 // drop the entry.
5230 TEST(HttpCache, RangeGET_InvalidResponse3) {
5231 MockHttpCache cache;
5232 std::string headers;
5234 MockTransaction transaction(kRangeGET_TransactionOK);
5235 transaction.handler = NULL;
5236 transaction.request_headers = "Range: bytes = 50-59\r\n" EXTRA_HEADER;
5237 std::string response_headers(transaction.response_headers);
5238 response_headers.append("Content-Range: bytes 50-59/160\n");
5239 transaction.response_headers = response_headers.c_str();
5240 AddMockTransaction(&transaction);
5241 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5243 Verify206Response(headers, 50, 59);
5244 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5245 EXPECT_EQ(0, cache.disk_cache()->open_count());
5246 EXPECT_EQ(1, cache.disk_cache()->create_count());
5248 RemoveMockTransaction(&transaction);
5249 AddMockTransaction(&kRangeGET_TransactionOK);
5251 // This transaction will report a resource size of 80 bytes, and we think it's
5252 // 160 so we should ignore the response.
5253 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
5254 &headers);
5256 Verify206Response(headers, 40, 49);
5257 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5258 EXPECT_EQ(1, cache.disk_cache()->open_count());
5259 EXPECT_EQ(1, cache.disk_cache()->create_count());
5261 // Verify that the entry is gone.
5262 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5263 EXPECT_EQ(1, cache.disk_cache()->open_count());
5264 EXPECT_EQ(2, cache.disk_cache()->create_count());
5265 RemoveMockTransaction(&kRangeGET_TransactionOK);
5268 // Tests that we handle large range values properly.
5269 TEST(HttpCache, RangeGET_LargeValues) {
5270 // We need a real sparse cache for this test.
5271 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
5272 std::string headers;
5274 MockTransaction transaction(kRangeGET_TransactionOK);
5275 transaction.handler = NULL;
5276 transaction.request_headers = "Range: bytes = 4294967288-4294967297\r\n"
5277 EXTRA_HEADER;
5278 transaction.response_headers =
5279 "ETag: \"foo\"\n"
5280 "Content-Range: bytes 4294967288-4294967297/4294967299\n"
5281 "Content-Length: 10\n";
5282 AddMockTransaction(&transaction);
5283 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5285 std::string expected(transaction.status);
5286 expected.append("\n");
5287 expected.append(transaction.response_headers);
5288 EXPECT_EQ(expected, headers);
5290 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5292 // Verify that we have a cached entry.
5293 disk_cache::Entry* en;
5294 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &en));
5295 en->Close();
5297 RemoveMockTransaction(&kRangeGET_TransactionOK);
5300 // Tests that we don't crash with a range request if the disk cache was not
5301 // initialized properly.
5302 TEST(HttpCache, RangeGET_NoDiskCache) {
5303 MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
5304 factory->set_fail(true);
5305 factory->FinishCreation(); // We'll complete synchronously.
5306 MockHttpCache cache(factory);
5308 AddMockTransaction(&kRangeGET_TransactionOK);
5310 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5311 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5313 RemoveMockTransaction(&kRangeGET_TransactionOK);
5316 // Tests that we handle byte range requests that skip the cache.
5317 TEST(HttpCache, RangeHEAD) {
5318 MockHttpCache cache;
5319 AddMockTransaction(&kRangeGET_TransactionOK);
5321 MockTransaction transaction(kRangeGET_TransactionOK);
5322 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
5323 transaction.method = "HEAD";
5324 transaction.data = "rg: 70-79 ";
5326 std::string headers;
5327 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5329 Verify206Response(headers, 70, 79);
5330 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5331 EXPECT_EQ(0, cache.disk_cache()->open_count());
5332 EXPECT_EQ(0, cache.disk_cache()->create_count());
5334 RemoveMockTransaction(&kRangeGET_TransactionOK);
5337 // Tests that we don't crash when after reading from the cache we issue a
5338 // request for the next range and the server gives us a 200 synchronously.
5339 TEST(HttpCache, RangeGET_FastFlakyServer) {
5340 MockHttpCache cache;
5342 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
5343 transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER;
5344 transaction.test_mode = TEST_MODE_SYNC_NET_START;
5345 transaction.load_flags |= LOAD_VALIDATE_CACHE;
5347 // Write to the cache.
5348 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5350 // And now read from the cache and the network.
5351 RangeTransactionServer handler;
5352 handler.set_bad_200(true);
5353 transaction.data = "Not a range";
5354 BoundTestNetLog log;
5355 RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound());
5357 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5358 EXPECT_EQ(1, cache.disk_cache()->open_count());
5359 EXPECT_EQ(1, cache.disk_cache()->create_count());
5360 EXPECT_TRUE(LogContainsEventType(
5361 log, NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST));
5364 // Tests that when the server gives us less data than expected, we don't keep
5365 // asking for more data.
5366 TEST(HttpCache, RangeGET_FastFlakyServer2) {
5367 MockHttpCache cache;
5369 // First, check with an empty cache (WRITE mode).
5370 MockTransaction transaction(kRangeGET_TransactionOK);
5371 transaction.request_headers = "Range: bytes = 40-49\r\n" EXTRA_HEADER;
5372 transaction.data = "rg: 40-"; // Less than expected.
5373 transaction.handler = NULL;
5374 std::string headers(transaction.response_headers);
5375 headers.append("Content-Range: bytes 40-49/80\n");
5376 transaction.response_headers = headers.c_str();
5378 AddMockTransaction(&transaction);
5380 // Write to the cache.
5381 RunTransactionTest(cache.http_cache(), transaction);
5383 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5384 EXPECT_EQ(0, cache.disk_cache()->open_count());
5385 EXPECT_EQ(1, cache.disk_cache()->create_count());
5387 // Now verify that even in READ_WRITE mode, we forward the bad response to
5388 // the caller.
5389 transaction.request_headers = "Range: bytes = 60-69\r\n" EXTRA_HEADER;
5390 transaction.data = "rg: 60-"; // Less than expected.
5391 headers = kRangeGET_TransactionOK.response_headers;
5392 headers.append("Content-Range: bytes 60-69/80\n");
5393 transaction.response_headers = headers.c_str();
5395 RunTransactionTest(cache.http_cache(), transaction);
5397 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5398 EXPECT_EQ(1, cache.disk_cache()->open_count());
5399 EXPECT_EQ(1, cache.disk_cache()->create_count());
5401 RemoveMockTransaction(&transaction);
5404 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
5405 // This test hits a NOTREACHED so it is a release mode only test.
5406 TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) {
5407 MockHttpCache cache;
5408 AddMockTransaction(&kRangeGET_TransactionOK);
5410 // Write to the cache (40-49).
5411 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5412 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5413 EXPECT_EQ(0, cache.disk_cache()->open_count());
5414 EXPECT_EQ(1, cache.disk_cache()->create_count());
5416 // Force this transaction to read from the cache.
5417 MockTransaction transaction(kRangeGET_TransactionOK);
5418 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
5420 MockHttpRequest request(transaction);
5421 TestCompletionCallback callback;
5423 scoped_ptr<HttpTransaction> trans;
5424 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
5425 EXPECT_EQ(OK, rv);
5426 ASSERT_TRUE(trans.get());
5428 rv = trans->Start(&request, callback.callback(), BoundNetLog());
5429 if (rv == ERR_IO_PENDING)
5430 rv = callback.WaitForResult();
5431 ASSERT_EQ(ERR_CACHE_MISS, rv);
5433 trans.reset();
5435 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5436 EXPECT_EQ(1, cache.disk_cache()->open_count());
5437 EXPECT_EQ(1, cache.disk_cache()->create_count());
5439 RemoveMockTransaction(&kRangeGET_TransactionOK);
5441 #endif
5443 // Tests the handling of the "truncation" flag.
5444 TEST(HttpCache, WriteResponseInfo_Truncated) {
5445 MockHttpCache cache;
5446 disk_cache::Entry* entry;
5447 ASSERT_TRUE(cache.CreateBackendEntry("http://www.google.com", &entry,
5448 NULL));
5450 std::string headers("HTTP/1.1 200 OK");
5451 headers = HttpUtil::AssembleRawHeaders(headers.data(), headers.size());
5452 HttpResponseInfo response;
5453 response.headers = new HttpResponseHeaders(headers);
5455 // Set the last argument for this to be an incomplete request.
5456 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
5457 bool truncated = false;
5458 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5459 EXPECT_TRUE(truncated);
5461 // And now test the opposite case.
5462 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
5463 truncated = true;
5464 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5465 EXPECT_FALSE(truncated);
5466 entry->Close();
5469 // Tests basic pickling/unpickling of HttpResponseInfo.
5470 TEST(HttpCache, PersistHttpResponseInfo) {
5471 // Set some fields (add more if needed.)
5472 HttpResponseInfo response1;
5473 response1.was_cached = false;
5474 response1.socket_address = HostPortPair("1.2.3.4", 80);
5475 response1.headers = new HttpResponseHeaders("HTTP/1.1 200 OK");
5477 // Pickle.
5478 base::Pickle pickle;
5479 response1.Persist(&pickle, false, false);
5481 // Unpickle.
5482 HttpResponseInfo response2;
5483 bool response_truncated;
5484 EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated));
5485 EXPECT_FALSE(response_truncated);
5487 // Verify fields.
5488 EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag.
5489 EXPECT_EQ("1.2.3.4", response2.socket_address.host());
5490 EXPECT_EQ(80, response2.socket_address.port());
5491 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5494 // Tests that we delete an entry when the request is cancelled before starting
5495 // to read from the network.
5496 TEST(HttpCache, DoomOnDestruction) {
5497 MockHttpCache cache;
5499 MockHttpRequest request(kSimpleGET_Transaction);
5501 Context* c = new Context();
5502 int rv = cache.CreateTransaction(&c->trans);
5503 ASSERT_EQ(OK, rv);
5505 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5506 if (rv == ERR_IO_PENDING)
5507 c->result = c->callback.WaitForResult();
5509 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5510 EXPECT_EQ(0, cache.disk_cache()->open_count());
5511 EXPECT_EQ(1, cache.disk_cache()->create_count());
5513 // Destroy the transaction. We only have the headers so we should delete this
5514 // entry.
5515 delete c;
5517 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5519 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5520 EXPECT_EQ(0, cache.disk_cache()->open_count());
5521 EXPECT_EQ(2, cache.disk_cache()->create_count());
5524 // Tests that we delete an entry when the request is cancelled if the response
5525 // does not have content-length and strong validators.
5526 TEST(HttpCache, DoomOnDestruction2) {
5527 MockHttpCache cache;
5529 MockHttpRequest request(kSimpleGET_Transaction);
5531 Context* c = new Context();
5532 int rv = cache.CreateTransaction(&c->trans);
5533 ASSERT_EQ(OK, rv);
5535 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5536 if (rv == ERR_IO_PENDING)
5537 rv = c->callback.WaitForResult();
5539 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5540 EXPECT_EQ(0, cache.disk_cache()->open_count());
5541 EXPECT_EQ(1, cache.disk_cache()->create_count());
5543 // Make sure that the entry has some data stored.
5544 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10));
5545 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5546 if (rv == ERR_IO_PENDING)
5547 rv = c->callback.WaitForResult();
5548 EXPECT_EQ(buf->size(), rv);
5550 // Destroy the transaction.
5551 delete c;
5553 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5555 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5556 EXPECT_EQ(0, cache.disk_cache()->open_count());
5557 EXPECT_EQ(2, cache.disk_cache()->create_count());
5560 // Tests that we delete an entry when the request is cancelled if the response
5561 // has an "Accept-Ranges: none" header.
5562 TEST(HttpCache, DoomOnDestruction3) {
5563 MockHttpCache cache;
5565 MockTransaction transaction(kSimpleGET_Transaction);
5566 transaction.response_headers =
5567 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
5568 "Content-Length: 22\n"
5569 "Accept-Ranges: none\n"
5570 "Etag: \"foopy\"\n";
5571 AddMockTransaction(&transaction);
5572 MockHttpRequest request(transaction);
5574 Context* c = new Context();
5575 int rv = cache.CreateTransaction(&c->trans);
5576 ASSERT_EQ(OK, rv);
5578 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5579 if (rv == ERR_IO_PENDING)
5580 rv = c->callback.WaitForResult();
5582 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5583 EXPECT_EQ(0, cache.disk_cache()->open_count());
5584 EXPECT_EQ(1, cache.disk_cache()->create_count());
5586 // Make sure that the entry has some data stored.
5587 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10));
5588 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5589 if (rv == ERR_IO_PENDING)
5590 rv = c->callback.WaitForResult();
5591 EXPECT_EQ(buf->size(), rv);
5593 // Destroy the transaction.
5594 delete c;
5596 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5598 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5599 EXPECT_EQ(0, cache.disk_cache()->open_count());
5600 EXPECT_EQ(2, cache.disk_cache()->create_count());
5602 RemoveMockTransaction(&transaction);
5605 // Tests that we mark an entry as incomplete when the request is cancelled.
5606 TEST(HttpCache, SetTruncatedFlag) {
5607 MockHttpCache cache;
5609 MockTransaction transaction(kSimpleGET_Transaction);
5610 transaction.response_headers =
5611 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
5612 "Content-Length: 22\n"
5613 "Etag: \"foopy\"\n";
5614 AddMockTransaction(&transaction);
5615 MockHttpRequest request(transaction);
5617 scoped_ptr<Context> c(new Context());
5619 int rv = cache.CreateTransaction(&c->trans);
5620 ASSERT_EQ(OK, rv);
5622 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5623 if (rv == ERR_IO_PENDING)
5624 rv = c->callback.WaitForResult();
5626 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5627 EXPECT_EQ(0, cache.disk_cache()->open_count());
5628 EXPECT_EQ(1, cache.disk_cache()->create_count());
5630 // Make sure that the entry has some data stored.
5631 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10));
5632 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5633 if (rv == ERR_IO_PENDING)
5634 rv = c->callback.WaitForResult();
5635 EXPECT_EQ(buf->size(), rv);
5637 // We want to cancel the request when the transaction is busy.
5638 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5639 EXPECT_EQ(ERR_IO_PENDING, rv);
5640 EXPECT_FALSE(c->callback.have_result());
5642 MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL);
5644 // Destroy the transaction.
5645 c->trans.reset();
5646 MockHttpCache::SetTestMode(0);
5649 // Make sure that we don't invoke the callback. We may have an issue if the
5650 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
5651 // could end up with the transaction being deleted twice if we send any
5652 // notification from the transaction destructor (see http://crbug.com/31723).
5653 EXPECT_FALSE(c->callback.have_result());
5655 // Verify that the entry is marked as incomplete.
5656 disk_cache::Entry* entry;
5657 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
5658 HttpResponseInfo response;
5659 bool truncated = false;
5660 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5661 EXPECT_TRUE(truncated);
5662 entry->Close();
5664 RemoveMockTransaction(&transaction);
5667 // Tests that we don't mark an entry as truncated when we read everything.
5668 TEST(HttpCache, DontSetTruncatedFlag) {
5669 MockHttpCache cache;
5671 MockTransaction transaction(kSimpleGET_Transaction);
5672 transaction.response_headers =
5673 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
5674 "Content-Length: 22\n"
5675 "Etag: \"foopy\"\n";
5676 AddMockTransaction(&transaction);
5677 MockHttpRequest request(transaction);
5679 scoped_ptr<Context> c(new Context());
5680 int rv = cache.CreateTransaction(&c->trans);
5681 ASSERT_EQ(OK, rv);
5683 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5684 EXPECT_EQ(OK, c->callback.GetResult(rv));
5686 // Read everything.
5687 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(22));
5688 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5689 EXPECT_EQ(buf->size(), c->callback.GetResult(rv));
5691 // Destroy the transaction.
5692 c->trans.reset();
5694 // Verify that the entry is not marked as truncated.
5695 disk_cache::Entry* entry;
5696 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
5697 HttpResponseInfo response;
5698 bool truncated = true;
5699 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5700 EXPECT_FALSE(truncated);
5701 entry->Close();
5703 RemoveMockTransaction(&transaction);
5706 // Tests that we can continue with a request that was interrupted.
5707 TEST(HttpCache, GET_IncompleteResource) {
5708 MockHttpCache cache;
5709 AddMockTransaction(&kRangeGET_TransactionOK);
5711 std::string raw_headers("HTTP/1.1 200 OK\n"
5712 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5713 "ETag: \"foo\"\n"
5714 "Accept-Ranges: bytes\n"
5715 "Content-Length: 80\n");
5716 CreateTruncatedEntry(raw_headers, &cache);
5718 // Now make a regular request.
5719 std::string headers;
5720 MockTransaction transaction(kRangeGET_TransactionOK);
5721 transaction.request_headers = EXTRA_HEADER;
5722 transaction.data = kFullRangeData;
5723 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5725 // We update the headers with the ones received while revalidating.
5726 std::string expected_headers(
5727 "HTTP/1.1 200 OK\n"
5728 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5729 "Accept-Ranges: bytes\n"
5730 "ETag: \"foo\"\n"
5731 "Content-Length: 80\n");
5733 EXPECT_EQ(expected_headers, headers);
5734 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5735 EXPECT_EQ(1, cache.disk_cache()->open_count());
5736 EXPECT_EQ(1, cache.disk_cache()->create_count());
5738 // Verify that the disk entry was updated.
5739 disk_cache::Entry* entry;
5740 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5741 EXPECT_EQ(80, entry->GetDataSize(1));
5742 bool truncated = true;
5743 HttpResponseInfo response;
5744 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
5745 EXPECT_FALSE(truncated);
5746 entry->Close();
5748 RemoveMockTransaction(&kRangeGET_TransactionOK);
5751 // Tests the handling of no-store when revalidating a truncated entry.
5752 TEST(HttpCache, GET_IncompleteResource_NoStore) {
5753 MockHttpCache cache;
5754 AddMockTransaction(&kRangeGET_TransactionOK);
5756 std::string raw_headers("HTTP/1.1 200 OK\n"
5757 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5758 "ETag: \"foo\"\n"
5759 "Accept-Ranges: bytes\n"
5760 "Content-Length: 80\n");
5761 CreateTruncatedEntry(raw_headers, &cache);
5762 RemoveMockTransaction(&kRangeGET_TransactionOK);
5764 // Now make a regular request.
5765 MockTransaction transaction(kRangeGET_TransactionOK);
5766 transaction.request_headers = EXTRA_HEADER;
5767 std::string response_headers(transaction.response_headers);
5768 response_headers += ("Cache-Control: no-store\n");
5769 transaction.response_headers = response_headers.c_str();
5770 transaction.data = kFullRangeData;
5771 AddMockTransaction(&transaction);
5773 std::string headers;
5774 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5776 // We update the headers with the ones received while revalidating.
5777 std::string expected_headers(
5778 "HTTP/1.1 200 OK\n"
5779 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5780 "Accept-Ranges: bytes\n"
5781 "Cache-Control: no-store\n"
5782 "ETag: \"foo\"\n"
5783 "Content-Length: 80\n");
5785 EXPECT_EQ(expected_headers, headers);
5786 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5787 EXPECT_EQ(1, cache.disk_cache()->open_count());
5788 EXPECT_EQ(1, cache.disk_cache()->create_count());
5790 // Verify that the disk entry was deleted.
5791 disk_cache::Entry* entry;
5792 EXPECT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5793 RemoveMockTransaction(&transaction);
5796 // Tests cancelling a request after the server sent no-store.
5797 TEST(HttpCache, GET_IncompleteResource_Cancel) {
5798 MockHttpCache cache;
5799 AddMockTransaction(&kRangeGET_TransactionOK);
5801 std::string raw_headers("HTTP/1.1 200 OK\n"
5802 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5803 "ETag: \"foo\"\n"
5804 "Accept-Ranges: bytes\n"
5805 "Content-Length: 80\n");
5806 CreateTruncatedEntry(raw_headers, &cache);
5807 RemoveMockTransaction(&kRangeGET_TransactionOK);
5809 // Now make a regular request.
5810 MockTransaction transaction(kRangeGET_TransactionOK);
5811 transaction.request_headers = EXTRA_HEADER;
5812 std::string response_headers(transaction.response_headers);
5813 response_headers += ("Cache-Control: no-store\n");
5814 transaction.response_headers = response_headers.c_str();
5815 transaction.data = kFullRangeData;
5816 AddMockTransaction(&transaction);
5818 MockHttpRequest request(transaction);
5819 Context* c = new Context();
5821 int rv = cache.CreateTransaction(&c->trans);
5822 ASSERT_EQ(OK, rv);
5824 // Queue another request to this transaction. We have to start this request
5825 // before the first one gets the response from the server and dooms the entry,
5826 // otherwise it will just create a new entry without being queued to the first
5827 // request.
5828 Context* pending = new Context();
5829 ASSERT_EQ(OK, cache.CreateTransaction(&pending->trans));
5831 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5832 EXPECT_EQ(ERR_IO_PENDING,
5833 pending->trans->Start(&request, pending->callback.callback(),
5834 BoundNetLog()));
5835 EXPECT_EQ(OK, c->callback.GetResult(rv));
5837 // Make sure that the entry has some data stored.
5838 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5));
5839 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
5840 EXPECT_EQ(5, c->callback.GetResult(rv));
5842 // Cancel the requests.
5843 delete c;
5844 delete pending;
5846 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5847 EXPECT_EQ(1, cache.disk_cache()->open_count());
5848 EXPECT_EQ(2, cache.disk_cache()->create_count());
5850 base::MessageLoop::current()->RunUntilIdle();
5851 RemoveMockTransaction(&transaction);
5854 // Tests that we delete truncated entries if the server changes its mind midway.
5855 TEST(HttpCache, GET_IncompleteResource2) {
5856 MockHttpCache cache;
5857 AddMockTransaction(&kRangeGET_TransactionOK);
5859 // Content-length will be intentionally bad.
5860 std::string raw_headers("HTTP/1.1 200 OK\n"
5861 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5862 "ETag: \"foo\"\n"
5863 "Accept-Ranges: bytes\n"
5864 "Content-Length: 50\n");
5865 CreateTruncatedEntry(raw_headers, &cache);
5867 // Now make a regular request. We expect the code to fail the validation and
5868 // retry the request without using byte ranges.
5869 std::string headers;
5870 MockTransaction transaction(kRangeGET_TransactionOK);
5871 transaction.request_headers = EXTRA_HEADER;
5872 transaction.data = "Not a range";
5873 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5875 // The server will return 200 instead of a byte range.
5876 std::string expected_headers(
5877 "HTTP/1.1 200 OK\n"
5878 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
5880 EXPECT_EQ(expected_headers, headers);
5881 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5882 EXPECT_EQ(1, cache.disk_cache()->open_count());
5883 EXPECT_EQ(1, cache.disk_cache()->create_count());
5885 // Verify that the disk entry was deleted.
5886 disk_cache::Entry* entry;
5887 ASSERT_FALSE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5888 RemoveMockTransaction(&kRangeGET_TransactionOK);
5891 // Tests that we always validate a truncated request.
5892 TEST(HttpCache, GET_IncompleteResource3) {
5893 MockHttpCache cache;
5894 AddMockTransaction(&kRangeGET_TransactionOK);
5896 // This should not require validation for 10 hours.
5897 std::string raw_headers("HTTP/1.1 200 OK\n"
5898 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
5899 "ETag: \"foo\"\n"
5900 "Cache-Control: max-age= 36000\n"
5901 "Accept-Ranges: bytes\n"
5902 "Content-Length: 80\n");
5903 CreateTruncatedEntry(raw_headers, &cache);
5905 // Now make a regular request.
5906 std::string headers;
5907 MockTransaction transaction(kRangeGET_TransactionOK);
5908 transaction.request_headers = EXTRA_HEADER;
5909 transaction.data = kFullRangeData;
5911 scoped_ptr<Context> c(new Context);
5912 int rv = cache.CreateTransaction(&c->trans);
5913 ASSERT_EQ(OK, rv);
5915 MockHttpRequest request(transaction);
5916 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5917 EXPECT_EQ(OK, c->callback.GetResult(rv));
5919 // We should have checked with the server before finishing Start().
5920 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5921 EXPECT_EQ(1, cache.disk_cache()->open_count());
5922 EXPECT_EQ(1, cache.disk_cache()->create_count());
5924 RemoveMockTransaction(&kRangeGET_TransactionOK);
5927 // Tests that we handle 401s for truncated resources.
5928 TEST(HttpCache, GET_IncompleteResourceWithAuth) {
5929 MockHttpCache cache;
5930 AddMockTransaction(&kRangeGET_TransactionOK);
5932 std::string raw_headers("HTTP/1.1 200 OK\n"
5933 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5934 "ETag: \"foo\"\n"
5935 "Accept-Ranges: bytes\n"
5936 "Content-Length: 80\n");
5937 CreateTruncatedEntry(raw_headers, &cache);
5939 // Now make a regular request.
5940 MockTransaction transaction(kRangeGET_TransactionOK);
5941 transaction.request_headers = "X-Require-Mock-Auth: dummy\r\n"
5942 EXTRA_HEADER;
5943 transaction.data = kFullRangeData;
5944 RangeTransactionServer handler;
5946 scoped_ptr<Context> c(new Context);
5947 int rv = cache.CreateTransaction(&c->trans);
5948 ASSERT_EQ(OK, rv);
5950 MockHttpRequest request(transaction);
5951 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
5952 EXPECT_EQ(OK, c->callback.GetResult(rv));
5954 const HttpResponseInfo* response = c->trans->GetResponseInfo();
5955 ASSERT_TRUE(response);
5956 ASSERT_EQ(401, response->headers->response_code());
5957 rv = c->trans->RestartWithAuth(AuthCredentials(), c->callback.callback());
5958 EXPECT_EQ(OK, c->callback.GetResult(rv));
5959 response = c->trans->GetResponseInfo();
5960 ASSERT_TRUE(response);
5961 ASSERT_EQ(200, response->headers->response_code());
5963 ReadAndVerifyTransaction(c->trans.get(), transaction);
5964 c.reset(); // The destructor could delete the entry.
5965 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5967 // Verify that the entry was not deleted.
5968 disk_cache::Entry* entry;
5969 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
5970 entry->Close();
5972 RemoveMockTransaction(&kRangeGET_TransactionOK);
5975 // Test that the transaction won't retry failed partial requests
5976 // after it starts reading data. http://crbug.com/474835
5977 TEST(HttpCache, TransactionRetryLimit) {
5978 MockHttpCache cache;
5980 // Cache 0-9, so that we have data to read before failing.
5981 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
5982 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
5983 transaction.data = "rg: 00-09 ";
5985 // Write to the cache.
5986 RunTransactionTest(cache.http_cache(), transaction);
5987 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5989 // And now read from the cache and the network. 10-19 will get a
5990 // 401, but will have already returned 0-9.
5991 // We do not set X-Require-Mock-Auth because that causes the mock
5992 // network transaction to become IsReadyToRestartForAuth().
5993 transaction.request_headers =
5994 "Range: bytes = 0-79\r\n"
5995 "X-Require-Mock-Auth-Alt: dummy\r\n" EXTRA_HEADER;
5997 scoped_ptr<Context> c(new Context);
5998 int rv = cache.CreateTransaction(&c->trans);
5999 ASSERT_EQ(OK, rv);
6001 MockHttpRequest request(transaction);
6003 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
6004 if (rv == ERR_IO_PENDING)
6005 rv = c->callback.WaitForResult();
6006 std::string content;
6007 rv = ReadTransaction(c->trans.get(), &content);
6008 EXPECT_EQ(ERR_CACHE_AUTH_FAILURE_AFTER_READ, rv);
6011 // Tests that we cache a 200 response to the validation request.
6012 TEST(HttpCache, GET_IncompleteResource4) {
6013 MockHttpCache cache;
6014 AddMockTransaction(&kRangeGET_TransactionOK);
6016 std::string raw_headers("HTTP/1.1 200 OK\n"
6017 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
6018 "ETag: \"foo\"\n"
6019 "Accept-Ranges: bytes\n"
6020 "Content-Length: 80\n");
6021 CreateTruncatedEntry(raw_headers, &cache);
6023 // Now make a regular request.
6024 std::string headers;
6025 MockTransaction transaction(kRangeGET_TransactionOK);
6026 transaction.request_headers = EXTRA_HEADER;
6027 transaction.data = "Not a range";
6028 RangeTransactionServer handler;
6029 handler.set_bad_200(true);
6030 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
6032 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6033 EXPECT_EQ(1, cache.disk_cache()->open_count());
6034 EXPECT_EQ(1, cache.disk_cache()->create_count());
6036 // Verify that the disk entry was updated.
6037 disk_cache::Entry* entry;
6038 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
6039 EXPECT_EQ(11, entry->GetDataSize(1));
6040 bool truncated = true;
6041 HttpResponseInfo response;
6042 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6043 EXPECT_FALSE(truncated);
6044 entry->Close();
6046 RemoveMockTransaction(&kRangeGET_TransactionOK);
6049 // Tests that when we cancel a request that was interrupted, we mark it again
6050 // as truncated.
6051 TEST(HttpCache, GET_CancelIncompleteResource) {
6052 MockHttpCache cache;
6053 AddMockTransaction(&kRangeGET_TransactionOK);
6055 std::string raw_headers("HTTP/1.1 200 OK\n"
6056 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
6057 "ETag: \"foo\"\n"
6058 "Accept-Ranges: bytes\n"
6059 "Content-Length: 80\n");
6060 CreateTruncatedEntry(raw_headers, &cache);
6062 // Now make a regular request.
6063 MockTransaction transaction(kRangeGET_TransactionOK);
6064 transaction.request_headers = EXTRA_HEADER;
6066 MockHttpRequest request(transaction);
6067 Context* c = new Context();
6068 int rv = cache.CreateTransaction(&c->trans);
6069 ASSERT_EQ(OK, rv);
6071 rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog());
6072 EXPECT_EQ(OK, c->callback.GetResult(rv));
6074 // Read 20 bytes from the cache, and 10 from the net.
6075 scoped_refptr<IOBuffer> buf(new IOBuffer(100));
6076 rv = c->trans->Read(buf.get(), 20, c->callback.callback());
6077 EXPECT_EQ(20, c->callback.GetResult(rv));
6078 rv = c->trans->Read(buf.get(), 10, c->callback.callback());
6079 EXPECT_EQ(10, c->callback.GetResult(rv));
6081 // At this point, we are already reading so canceling the request should leave
6082 // a truncated one.
6083 delete c;
6085 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6086 EXPECT_EQ(1, cache.disk_cache()->open_count());
6087 EXPECT_EQ(1, cache.disk_cache()->create_count());
6089 // Verify that the disk entry was updated: now we have 30 bytes.
6090 disk_cache::Entry* entry;
6091 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
6092 EXPECT_EQ(30, entry->GetDataSize(1));
6093 bool truncated = false;
6094 HttpResponseInfo response;
6095 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6096 EXPECT_TRUE(truncated);
6097 entry->Close();
6098 RemoveMockTransaction(&kRangeGET_TransactionOK);
6101 // Tests that we can handle range requests when we have a truncated entry.
6102 TEST(HttpCache, RangeGET_IncompleteResource) {
6103 MockHttpCache cache;
6104 AddMockTransaction(&kRangeGET_TransactionOK);
6106 // Content-length will be intentionally bogus.
6107 std::string raw_headers("HTTP/1.1 200 OK\n"
6108 "Last-Modified: something\n"
6109 "ETag: \"foo\"\n"
6110 "Accept-Ranges: bytes\n"
6111 "Content-Length: 10\n");
6112 CreateTruncatedEntry(raw_headers, &cache);
6114 // Now make a range request.
6115 std::string headers;
6116 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
6117 &headers);
6119 Verify206Response(headers, 40, 49);
6120 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6121 EXPECT_EQ(1, cache.disk_cache()->open_count());
6122 EXPECT_EQ(2, cache.disk_cache()->create_count());
6124 RemoveMockTransaction(&kRangeGET_TransactionOK);
6127 TEST(HttpCache, SyncRead) {
6128 MockHttpCache cache;
6130 // This test ensures that a read that completes synchronously does not cause
6131 // any problems.
6133 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6134 transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START |
6135 TEST_MODE_SYNC_CACHE_READ |
6136 TEST_MODE_SYNC_CACHE_WRITE);
6138 MockHttpRequest r1(transaction),
6139 r2(transaction),
6140 r3(transaction);
6142 TestTransactionConsumer c1(DEFAULT_PRIORITY, cache.http_cache()),
6143 c2(DEFAULT_PRIORITY, cache.http_cache()),
6144 c3(DEFAULT_PRIORITY, cache.http_cache());
6146 c1.Start(&r1, BoundNetLog());
6148 r2.load_flags |= LOAD_ONLY_FROM_CACHE;
6149 c2.Start(&r2, BoundNetLog());
6151 r3.load_flags |= LOAD_ONLY_FROM_CACHE;
6152 c3.Start(&r3, BoundNetLog());
6154 base::MessageLoop::current()->Run();
6156 EXPECT_TRUE(c1.is_done());
6157 EXPECT_TRUE(c2.is_done());
6158 EXPECT_TRUE(c3.is_done());
6160 EXPECT_EQ(OK, c1.error());
6161 EXPECT_EQ(OK, c2.error());
6162 EXPECT_EQ(OK, c3.error());
6165 TEST(HttpCache, ValidationResultsIn200) {
6166 MockHttpCache cache;
6168 // This test ensures that a conditional request, which results in a 200
6169 // instead of a 304, properly truncates the existing response data.
6171 // write to the cache
6172 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
6174 // force this transaction to validate the cache
6175 MockTransaction transaction(kETagGET_Transaction);
6176 transaction.load_flags |= LOAD_VALIDATE_CACHE;
6177 RunTransactionTest(cache.http_cache(), transaction);
6179 // read from the cache
6180 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
6183 TEST(HttpCache, CachedRedirect) {
6184 MockHttpCache cache;
6186 ScopedMockTransaction kTestTransaction(kSimpleGET_Transaction);
6187 kTestTransaction.status = "HTTP/1.1 301 Moved Permanently";
6188 kTestTransaction.response_headers = "Location: http://www.bar.com/\n";
6190 MockHttpRequest request(kTestTransaction);
6191 TestCompletionCallback callback;
6193 // Write to the cache.
6195 scoped_ptr<HttpTransaction> trans;
6196 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6198 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6199 if (rv == ERR_IO_PENDING)
6200 rv = callback.WaitForResult();
6201 ASSERT_EQ(OK, rv);
6203 const HttpResponseInfo* info = trans->GetResponseInfo();
6204 ASSERT_TRUE(info);
6206 EXPECT_EQ(info->headers->response_code(), 301);
6208 std::string location;
6209 info->headers->EnumerateHeader(NULL, "Location", &location);
6210 EXPECT_EQ(location, "http://www.bar.com/");
6212 // Mark the transaction as completed so it is cached.
6213 trans->DoneReading();
6215 // Destroy transaction when going out of scope. We have not actually
6216 // read the response body -- want to test that it is still getting cached.
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 // Active entries in the cache are not retired synchronously. Make
6223 // sure the next run hits the MockHttpCache and open_count is
6224 // correct.
6225 base::MessageLoop::current()->RunUntilIdle();
6227 // Read from the cache.
6229 scoped_ptr<HttpTransaction> trans;
6230 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6232 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6233 if (rv == ERR_IO_PENDING)
6234 rv = callback.WaitForResult();
6235 ASSERT_EQ(OK, rv);
6237 const HttpResponseInfo* info = trans->GetResponseInfo();
6238 ASSERT_TRUE(info);
6240 EXPECT_EQ(info->headers->response_code(), 301);
6242 std::string location;
6243 info->headers->EnumerateHeader(NULL, "Location", &location);
6244 EXPECT_EQ(location, "http://www.bar.com/");
6246 // Mark the transaction as completed so it is cached.
6247 trans->DoneReading();
6249 // Destroy transaction when going out of scope. We have not actually
6250 // read the response body -- want to test that it is still getting cached.
6252 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6253 EXPECT_EQ(1, cache.disk_cache()->open_count());
6254 EXPECT_EQ(1, cache.disk_cache()->create_count());
6257 // Verify that no-cache resources are stored in cache, but are not fetched from
6258 // cache during normal loads.
6259 TEST(HttpCache, CacheControlNoCacheNormalLoad) {
6260 MockHttpCache cache;
6262 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6263 transaction.response_headers = "cache-control: no-cache\n";
6265 // Initial load.
6266 RunTransactionTest(cache.http_cache(), transaction);
6268 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6269 EXPECT_EQ(0, cache.disk_cache()->open_count());
6270 EXPECT_EQ(1, cache.disk_cache()->create_count());
6272 // Try loading again; it should result in a network fetch.
6273 RunTransactionTest(cache.http_cache(), transaction);
6275 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6276 EXPECT_EQ(1, cache.disk_cache()->open_count());
6277 EXPECT_EQ(1, cache.disk_cache()->create_count());
6279 disk_cache::Entry* entry;
6280 EXPECT_TRUE(cache.OpenBackendEntry(transaction.url, &entry));
6281 entry->Close();
6284 // Verify that no-cache resources are stored in cache and fetched from cache
6285 // when the LOAD_PREFERRING_CACHE flag is set.
6286 TEST(HttpCache, CacheControlNoCacheHistoryLoad) {
6287 MockHttpCache cache;
6289 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6290 transaction.response_headers = "cache-control: no-cache\n";
6292 // Initial load.
6293 RunTransactionTest(cache.http_cache(), transaction);
6295 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6296 EXPECT_EQ(0, cache.disk_cache()->open_count());
6297 EXPECT_EQ(1, cache.disk_cache()->create_count());
6299 // Try loading again with LOAD_PREFERRING_CACHE.
6300 transaction.load_flags = LOAD_PREFERRING_CACHE;
6301 RunTransactionTest(cache.http_cache(), transaction);
6303 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6304 EXPECT_EQ(1, cache.disk_cache()->open_count());
6305 EXPECT_EQ(1, cache.disk_cache()->create_count());
6307 disk_cache::Entry* entry;
6308 EXPECT_TRUE(cache.OpenBackendEntry(transaction.url, &entry));
6309 entry->Close();
6312 TEST(HttpCache, CacheControlNoStore) {
6313 MockHttpCache cache;
6315 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6316 transaction.response_headers = "cache-control: no-store\n";
6318 // initial load
6319 RunTransactionTest(cache.http_cache(), transaction);
6321 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6322 EXPECT_EQ(0, cache.disk_cache()->open_count());
6323 EXPECT_EQ(1, cache.disk_cache()->create_count());
6325 // try loading again; it should result in a network fetch
6326 RunTransactionTest(cache.http_cache(), transaction);
6328 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6329 EXPECT_EQ(0, cache.disk_cache()->open_count());
6330 EXPECT_EQ(2, cache.disk_cache()->create_count());
6332 disk_cache::Entry* entry;
6333 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
6336 TEST(HttpCache, CacheControlNoStore2) {
6337 // this test is similar to the above test, except that the initial response
6338 // is cachable, but when it is validated, no-store is received causing the
6339 // cached document to be deleted.
6340 MockHttpCache cache;
6342 ScopedMockTransaction transaction(kETagGET_Transaction);
6344 // initial load
6345 RunTransactionTest(cache.http_cache(), transaction);
6347 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6348 EXPECT_EQ(0, cache.disk_cache()->open_count());
6349 EXPECT_EQ(1, cache.disk_cache()->create_count());
6351 // try loading again; it should result in a network fetch
6352 transaction.load_flags = LOAD_VALIDATE_CACHE;
6353 transaction.response_headers = "cache-control: no-store\n";
6354 RunTransactionTest(cache.http_cache(), transaction);
6356 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6357 EXPECT_EQ(1, cache.disk_cache()->open_count());
6358 EXPECT_EQ(1, cache.disk_cache()->create_count());
6360 disk_cache::Entry* entry;
6361 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
6364 TEST(HttpCache, CacheControlNoStore3) {
6365 // this test is similar to the above test, except that the response is a 304
6366 // instead of a 200. this should never happen in practice, but it seems like
6367 // a good thing to verify that we still destroy the cache entry.
6368 MockHttpCache cache;
6370 ScopedMockTransaction transaction(kETagGET_Transaction);
6372 // initial load
6373 RunTransactionTest(cache.http_cache(), transaction);
6375 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6376 EXPECT_EQ(0, cache.disk_cache()->open_count());
6377 EXPECT_EQ(1, cache.disk_cache()->create_count());
6379 // try loading again; it should result in a network fetch
6380 transaction.load_flags = LOAD_VALIDATE_CACHE;
6381 transaction.response_headers = "cache-control: no-store\n";
6382 transaction.status = "HTTP/1.1 304 Not Modified";
6383 RunTransactionTest(cache.http_cache(), transaction);
6385 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6386 EXPECT_EQ(1, cache.disk_cache()->open_count());
6387 EXPECT_EQ(1, cache.disk_cache()->create_count());
6389 disk_cache::Entry* entry;
6390 EXPECT_FALSE(cache.OpenBackendEntry(transaction.url, &entry));
6393 // Ensure that we don't cache requests served over bad HTTPS.
6394 TEST(HttpCache, SimpleGET_SSLError) {
6395 MockHttpCache cache;
6397 MockTransaction transaction = kSimpleGET_Transaction;
6398 transaction.cert_status = CERT_STATUS_REVOKED;
6399 ScopedMockTransaction scoped_transaction(transaction);
6401 // write to the cache
6402 RunTransactionTest(cache.http_cache(), transaction);
6404 // Test that it was not cached.
6405 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
6407 MockHttpRequest request(transaction);
6408 TestCompletionCallback callback;
6410 scoped_ptr<HttpTransaction> trans;
6411 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6413 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6414 if (rv == ERR_IO_PENDING)
6415 rv = callback.WaitForResult();
6416 ASSERT_EQ(ERR_CACHE_MISS, rv);
6419 // Ensure that we don't crash by if left-behind transactions.
6420 TEST(HttpCache, OutlivedTransactions) {
6421 MockHttpCache* cache = new MockHttpCache;
6423 scoped_ptr<HttpTransaction> trans;
6424 EXPECT_EQ(OK, cache->CreateTransaction(&trans));
6426 delete cache;
6427 trans.reset();
6430 // Test that the disabled mode works.
6431 TEST(HttpCache, CacheDisabledMode) {
6432 MockHttpCache cache;
6434 // write to the cache
6435 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6437 // go into disabled mode
6438 cache.http_cache()->set_mode(HttpCache::DISABLE);
6440 // force this transaction to write to the cache again
6441 MockTransaction transaction(kSimpleGET_Transaction);
6443 RunTransactionTest(cache.http_cache(), transaction);
6445 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6446 EXPECT_EQ(0, cache.disk_cache()->open_count());
6447 EXPECT_EQ(1, cache.disk_cache()->create_count());
6450 // Other tests check that the response headers of the cached response
6451 // get updated on 304. Here we specifically check that the
6452 // HttpResponseHeaders::request_time and HttpResponseHeaders::response_time
6453 // fields also gets updated.
6454 // http://crbug.com/20594.
6455 TEST(HttpCache, UpdatesRequestResponseTimeOn304) {
6456 MockHttpCache cache;
6458 const char kUrl[] = "http://foobar";
6459 const char kData[] = "body";
6461 MockTransaction mock_network_response = { 0 };
6462 mock_network_response.url = kUrl;
6464 AddMockTransaction(&mock_network_response);
6466 // Request |kUrl|, causing |kNetResponse1| to be written to the cache.
6468 MockTransaction request = { 0 };
6469 request.url = kUrl;
6470 request.method = "GET";
6471 request.request_headers = "\r\n";
6472 request.data = kData;
6474 static const Response kNetResponse1 = {
6475 "HTTP/1.1 200 OK",
6476 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6477 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6478 kData
6481 kNetResponse1.AssignTo(&mock_network_response);
6483 RunTransactionTest(cache.http_cache(), request);
6485 // Request |kUrl| again, this time validating the cache and getting
6486 // a 304 back.
6488 request.load_flags = LOAD_VALIDATE_CACHE;
6490 static const Response kNetResponse2 = {
6491 "HTTP/1.1 304 Not Modified",
6492 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n",
6496 kNetResponse2.AssignTo(&mock_network_response);
6498 base::Time request_time = base::Time() + base::TimeDelta::FromHours(1234);
6499 base::Time response_time = base::Time() + base::TimeDelta::FromHours(1235);
6501 mock_network_response.request_time = request_time;
6502 mock_network_response.response_time = response_time;
6504 HttpResponseInfo response;
6505 RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response);
6507 // The request and response times should have been updated.
6508 EXPECT_EQ(request_time.ToInternalValue(),
6509 response.request_time.ToInternalValue());
6510 EXPECT_EQ(response_time.ToInternalValue(),
6511 response.response_time.ToInternalValue());
6513 std::string headers;
6514 response.headers->GetNormalizedHeaders(&headers);
6516 EXPECT_EQ("HTTP/1.1 200 OK\n"
6517 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6518 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6519 headers);
6521 RemoveMockTransaction(&mock_network_response);
6524 // Tests that we can write metadata to an entry.
6525 TEST(HttpCache, WriteMetadata_OK) {
6526 MockHttpCache cache;
6528 // Write to the cache
6529 HttpResponseInfo response;
6530 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
6531 &response);
6532 EXPECT_TRUE(response.metadata.get() == NULL);
6534 // Trivial call.
6535 cache.http_cache()->WriteMetadata(GURL("foo"), DEFAULT_PRIORITY, Time::Now(),
6536 NULL, 0);
6538 // Write meta data to the same entry.
6539 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50));
6540 memset(buf->data(), 0, buf->size());
6541 base::strlcpy(buf->data(), "Hi there", buf->size());
6542 cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
6543 DEFAULT_PRIORITY, response.response_time,
6544 buf.get(), buf->size());
6546 // Release the buffer before the operation takes place.
6547 buf = NULL;
6549 // Makes sure we finish pending operations.
6550 base::MessageLoop::current()->RunUntilIdle();
6552 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
6553 &response);
6554 ASSERT_TRUE(response.metadata.get() != NULL);
6555 EXPECT_EQ(50, response.metadata->size());
6556 EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
6558 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6559 EXPECT_EQ(2, cache.disk_cache()->open_count());
6560 EXPECT_EQ(1, cache.disk_cache()->create_count());
6563 // Tests that we only write metadata to an entry if the time stamp matches.
6564 TEST(HttpCache, WriteMetadata_Fail) {
6565 MockHttpCache cache;
6567 // Write to the cache
6568 HttpResponseInfo response;
6569 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
6570 &response);
6571 EXPECT_TRUE(response.metadata.get() == NULL);
6573 // Attempt to write meta data to the same entry.
6574 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50));
6575 memset(buf->data(), 0, buf->size());
6576 base::strlcpy(buf->data(), "Hi there", buf->size());
6577 base::Time expected_time = response.response_time -
6578 base::TimeDelta::FromMilliseconds(20);
6579 cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url),
6580 DEFAULT_PRIORITY, expected_time, buf.get(),
6581 buf->size());
6583 // Makes sure we finish pending operations.
6584 base::MessageLoop::current()->RunUntilIdle();
6586 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
6587 &response);
6588 EXPECT_TRUE(response.metadata.get() == NULL);
6590 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6591 EXPECT_EQ(2, cache.disk_cache()->open_count());
6592 EXPECT_EQ(1, cache.disk_cache()->create_count());
6595 // Tests that we can read metadata after validating the entry and with READ mode
6596 // transactions.
6597 TEST(HttpCache, ReadMetadata) {
6598 MockHttpCache cache;
6600 // Write to the cache
6601 HttpResponseInfo response;
6602 RunTransactionTestWithResponseInfo(cache.http_cache(),
6603 kTypicalGET_Transaction, &response);
6604 EXPECT_TRUE(response.metadata.get() == NULL);
6606 // Write meta data to the same entry.
6607 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50));
6608 memset(buf->data(), 0, buf->size());
6609 base::strlcpy(buf->data(), "Hi there", buf->size());
6610 cache.http_cache()->WriteMetadata(GURL(kTypicalGET_Transaction.url),
6611 DEFAULT_PRIORITY, response.response_time,
6612 buf.get(), buf->size());
6614 // Makes sure we finish pending operations.
6615 base::MessageLoop::current()->RunUntilIdle();
6617 // Start with a READ mode transaction.
6618 MockTransaction trans1(kTypicalGET_Transaction);
6619 trans1.load_flags = LOAD_ONLY_FROM_CACHE;
6621 RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response);
6622 ASSERT_TRUE(response.metadata.get() != NULL);
6623 EXPECT_EQ(50, response.metadata->size());
6624 EXPECT_EQ(0, strcmp(response.metadata->data(), "Hi there"));
6626 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6627 EXPECT_EQ(2, cache.disk_cache()->open_count());
6628 EXPECT_EQ(1, cache.disk_cache()->create_count());
6629 base::MessageLoop::current()->RunUntilIdle();
6631 // Now make sure that the entry is re-validated with the server.
6632 trans1.load_flags = LOAD_VALIDATE_CACHE;
6633 trans1.status = "HTTP/1.1 304 Not Modified";
6634 AddMockTransaction(&trans1);
6636 response.metadata = NULL;
6637 RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response);
6638 EXPECT_TRUE(response.metadata.get() != NULL);
6640 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6641 EXPECT_EQ(3, cache.disk_cache()->open_count());
6642 EXPECT_EQ(1, cache.disk_cache()->create_count());
6643 base::MessageLoop::current()->RunUntilIdle();
6644 RemoveMockTransaction(&trans1);
6646 // Now return 200 when validating the entry so the metadata will be lost.
6647 MockTransaction trans2(kTypicalGET_Transaction);
6648 trans2.load_flags = LOAD_VALIDATE_CACHE;
6649 RunTransactionTestWithResponseInfo(cache.http_cache(), trans2, &response);
6650 EXPECT_TRUE(response.metadata.get() == NULL);
6652 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6653 EXPECT_EQ(4, cache.disk_cache()->open_count());
6654 EXPECT_EQ(1, cache.disk_cache()->create_count());
6657 // Tests that we don't mark entries as truncated when a filter detects the end
6658 // of the stream.
6659 TEST(HttpCache, FilterCompletion) {
6660 MockHttpCache cache;
6661 TestCompletionCallback callback;
6664 scoped_ptr<HttpTransaction> trans;
6665 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6667 MockHttpRequest request(kSimpleGET_Transaction);
6668 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6669 EXPECT_EQ(OK, callback.GetResult(rv));
6671 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6672 rv = trans->Read(buf.get(), 256, callback.callback());
6673 EXPECT_GT(callback.GetResult(rv), 0);
6675 // Now make sure that the entry is preserved.
6676 trans->DoneReading();
6679 // Make sure that the ActiveEntry is gone.
6680 base::MessageLoop::current()->RunUntilIdle();
6682 // Read from the cache.
6683 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6685 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6686 EXPECT_EQ(1, cache.disk_cache()->open_count());
6687 EXPECT_EQ(1, cache.disk_cache()->create_count());
6690 // Tests that we don't mark entries as truncated and release the cache
6691 // entry when DoneReading() is called before any Read() calls, such as
6692 // for a redirect.
6693 TEST(HttpCache, DoneReading) {
6694 MockHttpCache cache;
6695 TestCompletionCallback callback;
6697 ScopedMockTransaction transaction(kSimpleGET_Transaction);
6698 transaction.data = "";
6700 scoped_ptr<HttpTransaction> trans;
6701 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6703 MockHttpRequest request(transaction);
6704 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6705 EXPECT_EQ(OK, callback.GetResult(rv));
6707 trans->DoneReading();
6708 // Leave the transaction around.
6710 // Make sure that the ActiveEntry is gone.
6711 base::MessageLoop::current()->RunUntilIdle();
6713 // Read from the cache. This should not deadlock.
6714 RunTransactionTest(cache.http_cache(), transaction);
6716 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6717 EXPECT_EQ(1, cache.disk_cache()->open_count());
6718 EXPECT_EQ(1, cache.disk_cache()->create_count());
6721 // Tests that we stop caching when told.
6722 TEST(HttpCache, StopCachingDeletesEntry) {
6723 MockHttpCache cache;
6724 TestCompletionCallback callback;
6725 MockHttpRequest request(kSimpleGET_Transaction);
6728 scoped_ptr<HttpTransaction> trans;
6729 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6731 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6732 EXPECT_EQ(OK, callback.GetResult(rv));
6734 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6735 rv = trans->Read(buf.get(), 10, callback.callback());
6736 EXPECT_EQ(10, callback.GetResult(rv));
6738 trans->StopCaching();
6740 // We should be able to keep reading.
6741 rv = trans->Read(buf.get(), 256, callback.callback());
6742 EXPECT_GT(callback.GetResult(rv), 0);
6743 rv = trans->Read(buf.get(), 256, callback.callback());
6744 EXPECT_EQ(0, callback.GetResult(rv));
6747 // Make sure that the ActiveEntry is gone.
6748 base::MessageLoop::current()->RunUntilIdle();
6750 // Verify that the entry is gone.
6751 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6753 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6754 EXPECT_EQ(0, cache.disk_cache()->open_count());
6755 EXPECT_EQ(2, cache.disk_cache()->create_count());
6758 // Tests that we stop caching when told, even if DoneReading is called
6759 // after StopCaching.
6760 TEST(HttpCache, StopCachingThenDoneReadingDeletesEntry) {
6761 MockHttpCache cache;
6762 TestCompletionCallback callback;
6763 MockHttpRequest request(kSimpleGET_Transaction);
6766 scoped_ptr<HttpTransaction> trans;
6767 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6769 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6770 EXPECT_EQ(OK, callback.GetResult(rv));
6772 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6773 rv = trans->Read(buf.get(), 10, callback.callback());
6774 EXPECT_EQ(10, callback.GetResult(rv));
6776 trans->StopCaching();
6778 // We should be able to keep reading.
6779 rv = trans->Read(buf.get(), 256, callback.callback());
6780 EXPECT_GT(callback.GetResult(rv), 0);
6781 rv = trans->Read(buf.get(), 256, callback.callback());
6782 EXPECT_EQ(0, callback.GetResult(rv));
6784 // We should be able to call DoneReading.
6785 trans->DoneReading();
6788 // Make sure that the ActiveEntry is gone.
6789 base::MessageLoop::current()->RunUntilIdle();
6791 // Verify that the entry is gone.
6792 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6794 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6795 EXPECT_EQ(0, cache.disk_cache()->open_count());
6796 EXPECT_EQ(2, cache.disk_cache()->create_count());
6799 // Tests that we stop caching when told, when using auth.
6800 TEST(HttpCache, StopCachingWithAuthDeletesEntry) {
6801 MockHttpCache cache;
6802 TestCompletionCallback callback;
6803 MockTransaction mock_transaction(kSimpleGET_Transaction);
6804 mock_transaction.status = "HTTP/1.1 401 Unauthorized";
6805 AddMockTransaction(&mock_transaction);
6806 MockHttpRequest request(mock_transaction);
6809 scoped_ptr<HttpTransaction> trans;
6810 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6812 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6813 EXPECT_EQ(OK, callback.GetResult(rv));
6815 trans->StopCaching();
6817 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6818 rv = trans->Read(buf.get(), 10, callback.callback());
6819 EXPECT_EQ(callback.GetResult(rv), 10);
6821 RemoveMockTransaction(&mock_transaction);
6823 // Make sure that the ActiveEntry is gone.
6824 base::MessageLoop::current()->RunUntilIdle();
6826 // Verify that the entry is gone.
6827 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6829 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6830 EXPECT_EQ(0, cache.disk_cache()->open_count());
6831 EXPECT_EQ(2, cache.disk_cache()->create_count());
6834 // Tests that when we are told to stop caching we don't throw away valid data.
6835 TEST(HttpCache, StopCachingSavesEntry) {
6836 MockHttpCache cache;
6837 TestCompletionCallback callback;
6838 MockHttpRequest request(kSimpleGET_Transaction);
6841 scoped_ptr<HttpTransaction> trans;
6842 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6844 // Force a response that can be resumed.
6845 MockTransaction mock_transaction(kSimpleGET_Transaction);
6846 AddMockTransaction(&mock_transaction);
6847 mock_transaction.response_headers = "Cache-Control: max-age=10000\n"
6848 "Content-Length: 42\n"
6849 "Etag: \"foo\"\n";
6851 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6852 EXPECT_EQ(OK, callback.GetResult(rv));
6854 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6855 rv = trans->Read(buf.get(), 10, callback.callback());
6856 EXPECT_EQ(callback.GetResult(rv), 10);
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_EQ(callback.GetResult(rv), 0);
6866 RemoveMockTransaction(&mock_transaction);
6869 // Verify that the entry is marked as incomplete.
6870 disk_cache::Entry* entry;
6871 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
6872 HttpResponseInfo response;
6873 bool truncated = false;
6874 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6875 EXPECT_TRUE(truncated);
6876 entry->Close();
6879 // Tests that we handle truncated enries when StopCaching is called.
6880 TEST(HttpCache, StopCachingTruncatedEntry) {
6881 MockHttpCache cache;
6882 TestCompletionCallback callback;
6883 MockHttpRequest request(kRangeGET_TransactionOK);
6884 request.extra_headers.Clear();
6885 request.extra_headers.AddHeaderFromString(EXTRA_HEADER_LINE);
6886 AddMockTransaction(&kRangeGET_TransactionOK);
6888 std::string raw_headers("HTTP/1.1 200 OK\n"
6889 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
6890 "ETag: \"foo\"\n"
6891 "Accept-Ranges: bytes\n"
6892 "Content-Length: 80\n");
6893 CreateTruncatedEntry(raw_headers, &cache);
6896 // Now make a regular request.
6897 scoped_ptr<HttpTransaction> trans;
6898 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6900 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6901 EXPECT_EQ(OK, callback.GetResult(rv));
6903 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6904 rv = trans->Read(buf.get(), 10, callback.callback());
6905 EXPECT_EQ(callback.GetResult(rv), 10);
6907 // This is actually going to do nothing.
6908 trans->StopCaching();
6910 // We should be able to keep reading.
6911 rv = trans->Read(buf.get(), 256, callback.callback());
6912 EXPECT_GT(callback.GetResult(rv), 0);
6913 rv = trans->Read(buf.get(), 256, callback.callback());
6914 EXPECT_GT(callback.GetResult(rv), 0);
6915 rv = trans->Read(buf.get(), 256, callback.callback());
6916 EXPECT_EQ(callback.GetResult(rv), 0);
6919 // Verify that the disk entry was updated.
6920 disk_cache::Entry* entry;
6921 ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry));
6922 EXPECT_EQ(80, entry->GetDataSize(1));
6923 bool truncated = true;
6924 HttpResponseInfo response;
6925 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6926 EXPECT_FALSE(truncated);
6927 entry->Close();
6929 RemoveMockTransaction(&kRangeGET_TransactionOK);
6932 // Tests that we detect truncated resources from the net when there is
6933 // a Content-Length header.
6934 TEST(HttpCache, TruncatedByContentLength) {
6935 MockHttpCache cache;
6936 TestCompletionCallback callback;
6938 MockTransaction transaction(kSimpleGET_Transaction);
6939 AddMockTransaction(&transaction);
6940 transaction.response_headers = "Cache-Control: max-age=10000\n"
6941 "Content-Length: 100\n";
6942 RunTransactionTest(cache.http_cache(), transaction);
6943 RemoveMockTransaction(&transaction);
6945 // Read from the cache.
6946 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
6948 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6949 EXPECT_EQ(0, cache.disk_cache()->open_count());
6950 EXPECT_EQ(2, cache.disk_cache()->create_count());
6953 // Tests that we actually flag entries as truncated when we detect an error
6954 // from the net.
6955 TEST(HttpCache, TruncatedByContentLength2) {
6956 MockHttpCache cache;
6957 TestCompletionCallback callback;
6959 MockTransaction transaction(kSimpleGET_Transaction);
6960 AddMockTransaction(&transaction);
6961 transaction.response_headers = "Cache-Control: max-age=10000\n"
6962 "Content-Length: 100\n"
6963 "Etag: \"foo\"\n";
6964 RunTransactionTest(cache.http_cache(), transaction);
6965 RemoveMockTransaction(&transaction);
6967 // Verify that the entry is marked as incomplete.
6968 disk_cache::Entry* entry;
6969 ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry));
6970 HttpResponseInfo response;
6971 bool truncated = false;
6972 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
6973 EXPECT_TRUE(truncated);
6974 entry->Close();
6977 // Make sure that calling SetPriority on a cache transaction passes on
6978 // its priority updates to its underlying network transaction.
6979 TEST(HttpCache, SetPriority) {
6980 MockHttpCache cache;
6982 scoped_ptr<HttpTransaction> trans;
6983 ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(IDLE, &trans));
6985 // Shouldn't crash, but doesn't do anything either.
6986 trans->SetPriority(LOW);
6988 EXPECT_FALSE(cache.network_layer()->last_transaction());
6989 EXPECT_EQ(DEFAULT_PRIORITY,
6990 cache.network_layer()->last_create_transaction_priority());
6992 HttpRequestInfo info;
6993 info.url = GURL(kSimpleGET_Transaction.url);
6994 TestCompletionCallback callback;
6995 EXPECT_EQ(ERR_IO_PENDING,
6996 trans->Start(&info, callback.callback(), BoundNetLog()));
6998 EXPECT_TRUE(cache.network_layer()->last_transaction());
6999 if (cache.network_layer()->last_transaction()) {
7000 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
7001 EXPECT_EQ(LOW, cache.network_layer()->last_transaction()->priority());
7004 trans->SetPriority(HIGHEST);
7006 if (cache.network_layer()->last_transaction()) {
7007 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
7008 EXPECT_EQ(HIGHEST, cache.network_layer()->last_transaction()->priority());
7011 EXPECT_EQ(OK, callback.WaitForResult());
7014 // Make sure that calling SetWebSocketHandshakeStreamCreateHelper on a cache
7015 // transaction passes on its argument to the underlying network transaction.
7016 TEST(HttpCache, SetWebSocketHandshakeStreamCreateHelper) {
7017 MockHttpCache cache;
7019 FakeWebSocketHandshakeStreamCreateHelper create_helper;
7020 scoped_ptr<HttpTransaction> trans;
7021 ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(IDLE, &trans));
7023 EXPECT_FALSE(cache.network_layer()->last_transaction());
7025 HttpRequestInfo info;
7026 info.url = GURL(kSimpleGET_Transaction.url);
7027 TestCompletionCallback callback;
7028 EXPECT_EQ(ERR_IO_PENDING,
7029 trans->Start(&info, callback.callback(), BoundNetLog()));
7031 ASSERT_TRUE(cache.network_layer()->last_transaction());
7032 EXPECT_FALSE(cache.network_layer()->last_transaction()->
7033 websocket_handshake_stream_create_helper());
7034 trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper);
7035 EXPECT_EQ(&create_helper,
7036 cache.network_layer()->last_transaction()->
7037 websocket_handshake_stream_create_helper());
7038 EXPECT_EQ(OK, callback.WaitForResult());
7041 // Make sure that a cache transaction passes on its priority to
7042 // newly-created network transactions.
7043 TEST(HttpCache, SetPriorityNewTransaction) {
7044 MockHttpCache cache;
7045 AddMockTransaction(&kRangeGET_TransactionOK);
7047 std::string raw_headers("HTTP/1.1 200 OK\n"
7048 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7049 "ETag: \"foo\"\n"
7050 "Accept-Ranges: bytes\n"
7051 "Content-Length: 80\n");
7052 CreateTruncatedEntry(raw_headers, &cache);
7054 // Now make a regular request.
7055 std::string headers;
7056 MockTransaction transaction(kRangeGET_TransactionOK);
7057 transaction.request_headers = EXTRA_HEADER;
7058 transaction.data = kFullRangeData;
7060 scoped_ptr<HttpTransaction> trans;
7061 ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(MEDIUM, &trans));
7062 EXPECT_EQ(DEFAULT_PRIORITY,
7063 cache.network_layer()->last_create_transaction_priority());
7065 MockHttpRequest info(transaction);
7066 TestCompletionCallback callback;
7067 EXPECT_EQ(ERR_IO_PENDING,
7068 trans->Start(&info, callback.callback(), BoundNetLog()));
7069 EXPECT_EQ(OK, callback.WaitForResult());
7071 EXPECT_EQ(MEDIUM, cache.network_layer()->last_create_transaction_priority());
7073 trans->SetPriority(HIGHEST);
7074 // Should trigger a new network transaction and pick up the new
7075 // priority.
7076 ReadAndVerifyTransaction(trans.get(), transaction);
7078 EXPECT_EQ(HIGHEST, cache.network_layer()->last_create_transaction_priority());
7080 RemoveMockTransaction(&kRangeGET_TransactionOK);
7083 int64 RunTransactionAndGetReceivedBytes(
7084 MockHttpCache& cache,
7085 const MockTransaction& trans_info) {
7086 int64 received_bytes = -1;
7087 RunTransactionTestBase(cache.http_cache(), trans_info,
7088 MockHttpRequest(trans_info), NULL, BoundNetLog(), NULL,
7089 &received_bytes);
7090 return received_bytes;
7093 int64 TransactionSize(const MockTransaction& transaction) {
7094 return strlen(transaction.status) + strlen(transaction.response_headers) +
7095 strlen(transaction.data);
7098 TEST(HttpCache, ReceivedBytesCacheMissAndThenHit) {
7099 MockHttpCache cache;
7101 MockTransaction transaction(kSimpleGET_Transaction);
7102 int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7103 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7105 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7106 EXPECT_EQ(0, received_bytes);
7109 TEST(HttpCache, ReceivedBytesConditionalRequest304) {
7110 MockHttpCache cache;
7112 ScopedMockTransaction transaction(kETagGET_Transaction);
7113 int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7114 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7116 transaction.load_flags = LOAD_VALIDATE_CACHE;
7117 transaction.handler = ETagGet_ConditionalRequest_Handler;
7118 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7119 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7122 TEST(HttpCache, ReceivedBytesConditionalRequest200) {
7123 MockHttpCache cache;
7125 MockTransaction transaction(kTypicalGET_Transaction);
7126 transaction.request_headers = "Foo: bar\r\n";
7127 transaction.response_headers =
7128 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
7129 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
7130 "Etag: \"foopy\"\n"
7131 "Cache-Control: max-age=0\n"
7132 "Vary: Foo\n";
7133 AddMockTransaction(&transaction);
7134 int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7135 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7137 RevalidationServer server;
7138 transaction.handler = server.Handler;
7139 transaction.request_headers = "Foo: none\r\n";
7140 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7141 EXPECT_EQ(TransactionSize(transaction), received_bytes);
7143 RemoveMockTransaction(&transaction);
7146 TEST(HttpCache, ReceivedBytesRange) {
7147 MockHttpCache cache;
7148 AddMockTransaction(&kRangeGET_TransactionOK);
7149 MockTransaction transaction(kRangeGET_TransactionOK);
7151 // Read bytes 40-49 from the network.
7152 int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7153 int64 range_response_size = TransactionSize(transaction);
7154 EXPECT_EQ(range_response_size, received_bytes);
7156 // Read bytes 40-49 from the cache.
7157 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7158 EXPECT_EQ(0, received_bytes);
7159 base::MessageLoop::current()->RunUntilIdle();
7161 // Read bytes 30-39 from the network.
7162 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
7163 transaction.data = "rg: 30-39 ";
7164 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7165 EXPECT_EQ(range_response_size, received_bytes);
7166 base::MessageLoop::current()->RunUntilIdle();
7168 // Read bytes 20-29 and 50-59 from the network, bytes 30-49 from the cache.
7169 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
7170 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
7171 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction);
7172 EXPECT_EQ(range_response_size * 2, received_bytes);
7174 RemoveMockTransaction(&kRangeGET_TransactionOK);
7177 class HttpCachePrefetchValidationTest : public ::testing::Test {
7178 protected:
7179 static const int kMaxAgeSecs = 100;
7180 static const int kRequireValidationSecs = kMaxAgeSecs + 1;
7182 HttpCachePrefetchValidationTest() : transaction_(kSimpleGET_Transaction) {
7183 DCHECK_LT(kMaxAgeSecs, prefetch_reuse_mins() * kNumSecondsPerMinute);
7185 clock_ = new base::SimpleTestClock();
7186 cache_.http_cache()->SetClockForTesting(make_scoped_ptr(clock_));
7187 cache_.network_layer()->SetClock(clock_);
7189 transaction_.response_headers = "Cache-Control: max-age=100\n";
7192 bool TransactionRequiredNetwork(int load_flags) {
7193 int pre_transaction_count = transaction_count();
7194 transaction_.load_flags = load_flags;
7195 RunTransactionTest(cache_.http_cache(), transaction_);
7196 return pre_transaction_count != transaction_count();
7199 void AdvanceTime(int seconds) {
7200 clock_->Advance(base::TimeDelta::FromSeconds(seconds));
7203 int prefetch_reuse_mins() { return HttpCache::kPrefetchReuseMins; }
7205 // How many times this test has sent requests to the (fake) origin
7206 // server. Every test case needs to make at least one request to initialise
7207 // the cache.
7208 int transaction_count() {
7209 return cache_.network_layer()->transaction_count();
7212 MockHttpCache cache_;
7213 ScopedMockTransaction transaction_;
7214 std::string response_headers_;
7215 base::SimpleTestClock* clock_;
7218 TEST_F(HttpCachePrefetchValidationTest, SkipValidationShortlyAfterPrefetch) {
7219 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7220 AdvanceTime(kRequireValidationSecs);
7221 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7224 TEST_F(HttpCachePrefetchValidationTest, ValidateLongAfterPrefetch) {
7225 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7226 AdvanceTime(prefetch_reuse_mins() * kNumSecondsPerMinute);
7227 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7230 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceOnly) {
7231 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7232 AdvanceTime(kRequireValidationSecs);
7233 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7234 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7237 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceReadOnly) {
7238 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7239 AdvanceTime(kRequireValidationSecs);
7240 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_ONLY_FROM_CACHE));
7241 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7244 TEST_F(HttpCachePrefetchValidationTest, BypassCacheOverwritesPrefetch) {
7245 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7246 AdvanceTime(kRequireValidationSecs);
7247 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_BYPASS_CACHE));
7248 AdvanceTime(kRequireValidationSecs);
7249 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7252 TEST_F(HttpCachePrefetchValidationTest,
7253 SkipValidationOnExistingEntryThatNeedsValidation) {
7254 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7255 AdvanceTime(kRequireValidationSecs);
7256 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7257 AdvanceTime(kRequireValidationSecs);
7258 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7259 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7262 TEST_F(HttpCachePrefetchValidationTest,
7263 SkipValidationOnExistingEntryThatDoesNotNeedValidation) {
7264 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7265 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
7266 AdvanceTime(kRequireValidationSecs);
7267 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7268 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
7271 TEST_F(HttpCachePrefetchValidationTest, PrefetchMultipleTimes) {
7272 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7273 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
7274 AdvanceTime(kRequireValidationSecs);
7275 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7278 TEST_F(HttpCachePrefetchValidationTest, ValidateOnDelayedSecondPrefetch) {
7279 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7280 AdvanceTime(kRequireValidationSecs);
7281 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
7282 AdvanceTime(kRequireValidationSecs);
7283 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
7286 static void CheckResourceFreshnessHeader(const HttpRequestInfo* request,
7287 std::string* response_status,
7288 std::string* response_headers,
7289 std::string* response_data) {
7290 std::string value;
7291 EXPECT_TRUE(request->extra_headers.GetHeader("Resource-Freshness", &value));
7292 EXPECT_EQ("max-age=3600,stale-while-revalidate=7200,age=10801", value);
7295 // Verify that the Resource-Freshness header is sent on a revalidation if the
7296 // stale-while-revalidate directive was on the response.
7297 TEST(HttpCache, ResourceFreshnessHeaderSent) {
7298 MockHttpCache cache;
7300 ScopedMockTransaction stale_while_revalidate_transaction(
7301 kSimpleGET_Transaction);
7302 stale_while_revalidate_transaction.response_headers =
7303 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7304 "Age: 10801\n"
7305 "Cache-Control: max-age=3600,stale-while-revalidate=7200\n";
7307 // Write to the cache.
7308 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
7310 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7312 // Send the request again and check that Resource-Freshness header is added.
7313 stale_while_revalidate_transaction.handler = CheckResourceFreshnessHeader;
7315 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
7317 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7320 static void CheckResourceFreshnessAbsent(const HttpRequestInfo* request,
7321 std::string* response_status,
7322 std::string* response_headers,
7323 std::string* response_data) {
7324 EXPECT_FALSE(request->extra_headers.HasHeader("Resource-Freshness"));
7327 // Verify that the Resource-Freshness header is not sent when
7328 // stale-while-revalidate is 0.
7329 TEST(HttpCache, ResourceFreshnessHeaderNotSent) {
7330 MockHttpCache cache;
7332 ScopedMockTransaction stale_while_revalidate_transaction(
7333 kSimpleGET_Transaction);
7334 stale_while_revalidate_transaction.response_headers =
7335 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7336 "Age: 10801\n"
7337 "Cache-Control: max-age=3600,stale-while-revalidate=0\n";
7339 // Write to the cache.
7340 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
7342 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7344 // Send the request again and check that Resource-Freshness header is absent.
7345 stale_while_revalidate_transaction.handler = CheckResourceFreshnessAbsent;
7347 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
7349 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7352 // Tests that we allow multiple simultaneous, non-overlapping transactions to
7353 // take place on a sparse entry.
7354 TEST(HttpCache, RangeGET_MultipleRequests) {
7355 MockHttpCache cache;
7357 // Create a transaction for bytes 0-9.
7358 MockHttpRequest request(kRangeGET_TransactionOK);
7359 MockTransaction transaction(kRangeGET_TransactionOK);
7360 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
7361 transaction.data = "rg: 00-09 ";
7362 AddMockTransaction(&transaction);
7364 TestCompletionCallback callback;
7365 scoped_ptr<HttpTransaction> trans;
7366 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
7367 EXPECT_EQ(OK, rv);
7368 ASSERT_TRUE(trans.get());
7370 // Start our transaction.
7371 trans->Start(&request, callback.callback(), BoundNetLog());
7373 // A second transaction on a different part of the file (the default
7374 // kRangeGET_TransactionOK requests 40-49) should not be blocked by
7375 // the already pending transaction.
7376 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
7378 // Let the first transaction complete.
7379 callback.WaitForResult();
7381 RemoveMockTransaction(&transaction);
7384 // Makes sure that a request stops using the cache when the response headers
7385 // with "Cache-Control: no-store" arrives. That means that another request for
7386 // the same URL can be processed before the response body of the original
7387 // request arrives.
7388 TEST(HttpCache, NoStoreResponseShouldNotBlockFollowingRequests) {
7389 MockHttpCache cache;
7390 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
7391 mock_transaction.response_headers = "Cache-Control: no-store\n";
7392 MockHttpRequest request(mock_transaction);
7394 scoped_ptr<Context> first(new Context);
7395 first->result = cache.CreateTransaction(&first->trans);
7396 ASSERT_EQ(OK, first->result);
7397 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
7398 first->result =
7399 first->trans->Start(&request, first->callback.callback(), BoundNetLog());
7400 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, first->trans->GetLoadState());
7402 base::MessageLoop::current()->RunUntilIdle();
7403 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
7404 ASSERT_TRUE(first->trans->GetResponseInfo());
7405 EXPECT_TRUE(first->trans->GetResponseInfo()->headers->HasHeaderValue(
7406 "Cache-Control", "no-store"));
7407 // Here we have read the response header but not read the response body yet.
7409 // Let us create the second (read) transaction.
7410 scoped_ptr<Context> second(new Context);
7411 second->result = cache.CreateTransaction(&second->trans);
7412 ASSERT_EQ(OK, second->result);
7413 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
7414 second->result = second->trans->Start(&request, second->callback.callback(),
7415 BoundNetLog());
7417 // Here the second transaction proceeds without reading the first body.
7418 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, second->trans->GetLoadState());
7419 base::MessageLoop::current()->RunUntilIdle();
7420 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
7421 ASSERT_TRUE(second->trans->GetResponseInfo());
7422 EXPECT_TRUE(second->trans->GetResponseInfo()->headers->HasHeaderValue(
7423 "Cache-Control", "no-store"));
7424 ReadAndVerifyTransaction(second->trans.get(), kSimpleGET_Transaction);
7427 // Tests that serving a response entirely from cache replays the previous
7428 // SSLInfo.
7429 TEST(HttpCache, CachePreservesSSLInfo) {
7430 static const uint16_t kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f;
7431 int status = 0;
7432 SSLConnectionStatusSetCipherSuite(kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
7433 &status);
7434 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2, &status);
7436 scoped_refptr<X509Certificate> cert =
7437 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
7439 MockHttpCache cache;
7441 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7442 transaction.cert = cert;
7443 transaction.ssl_connection_status = status;
7445 // Fetch the resource.
7446 HttpResponseInfo response_info;
7447 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
7448 &response_info);
7450 // The request should have hit the network and a cache entry created.
7451 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7452 EXPECT_EQ(0, cache.disk_cache()->open_count());
7453 EXPECT_EQ(1, cache.disk_cache()->create_count());
7455 // The expected SSL state was reported.
7456 EXPECT_EQ(transaction.ssl_connection_status,
7457 response_info.ssl_info.connection_status);
7458 EXPECT_TRUE(cert->Equals(response_info.ssl_info.cert.get()));
7460 // Fetch the resource again.
7461 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
7462 &response_info);
7464 // The request should have been reused without hitting the network.
7465 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7466 EXPECT_EQ(1, cache.disk_cache()->open_count());
7467 EXPECT_EQ(1, cache.disk_cache()->create_count());
7469 // The SSL state was preserved.
7470 EXPECT_EQ(status, response_info.ssl_info.connection_status);
7471 EXPECT_TRUE(cert->Equals(response_info.ssl_info.cert.get()));
7474 // Tests that SSLInfo gets updated when revalidating a cached response.
7475 TEST(HttpCache, RevalidationUpdatesSSLInfo) {
7476 static const uint16_t kTLS_RSA_WITH_RC4_128_MD5 = 0x0004;
7477 static const uint16_t kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f;
7479 int status1 = 0;
7480 SSLConnectionStatusSetCipherSuite(kTLS_RSA_WITH_RC4_128_MD5, &status1);
7481 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1, &status1);
7482 int status2 = 0;
7483 SSLConnectionStatusSetCipherSuite(kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
7484 &status2);
7485 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2, &status2);
7487 scoped_refptr<X509Certificate> cert1 =
7488 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
7489 scoped_refptr<X509Certificate> cert2 =
7490 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
7492 MockHttpCache cache;
7494 ScopedMockTransaction transaction(kTypicalGET_Transaction);
7495 transaction.cert = cert1;
7496 transaction.ssl_connection_status = status1;
7498 // Fetch the resource.
7499 HttpResponseInfo response_info;
7500 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
7501 &response_info);
7503 // The request should have hit the network and a cache entry created.
7504 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7505 EXPECT_EQ(0, cache.disk_cache()->open_count());
7506 EXPECT_EQ(1, cache.disk_cache()->create_count());
7507 EXPECT_FALSE(response_info.was_cached);
7509 // The expected SSL state was reported.
7510 EXPECT_EQ(status1, response_info.ssl_info.connection_status);
7511 EXPECT_TRUE(cert1->Equals(response_info.ssl_info.cert.get()));
7513 // The server deploys a more modern configuration but reports 304 on the
7514 // revalidation attempt.
7515 transaction.status = "HTTP/1.1 304 Not Modified";
7516 transaction.cert = cert2;
7517 transaction.ssl_connection_status = status2;
7519 // Fetch the resource again, forcing a revalidation.
7520 transaction.request_headers = "Cache-Control: max-age=0\r\n";
7521 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
7522 &response_info);
7524 // The request should have been successfully revalidated.
7525 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7526 EXPECT_EQ(1, cache.disk_cache()->open_count());
7527 EXPECT_EQ(1, cache.disk_cache()->create_count());
7528 EXPECT_TRUE(response_info.was_cached);
7530 // The new SSL state is reported.
7531 EXPECT_EQ(status2, response_info.ssl_info.connection_status);
7532 EXPECT_TRUE(cert2->Equals(response_info.ssl_info.cert.get()));
7535 } // namespace net