1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_cache.h"
6
7 #include <stdint.h>
8
9 #include <algorithm>
10 #include <memory>
11 #include <set>
12 #include <utility>
13 #include <vector>
14
15 #include "base/containers/cxx20_erase.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/format_macros.h"
18 #include "base/functional/bind.h"
19 #include "base/functional/callback_helpers.h"
20 #include "base/memory/ptr_util.h"
21 #include "base/memory/raw_ptr.h"
22 #include "base/run_loop.h"
23 #include "base/strings/strcat.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_util.h"
26 #include "base/strings/stringprintf.h"
27 #include "base/test/bind.h"
28 #include "base/test/metrics/histogram_tester.h"
29 #include "base/test/scoped_feature_list.h"
30 #include "base/test/simple_test_clock.h"
31 #include "base/time/time.h"
32 #include "base/trace_event/memory_allocator_dump.h"
33 #include "base/trace_event/memory_dump_request_args.h"
34 #include "base/trace_event/process_memory_dump.h"
35 #include "net/base/cache_type.h"
36 #include "net/base/completion_repeating_callback.h"
37 #include "net/base/elements_upload_data_stream.h"
38 #include "net/base/features.h"
39 #include "net/base/host_port_pair.h"
40 #include "net/base/ip_address.h"
41 #include "net/base/ip_endpoint.h"
42 #include "net/base/load_flags.h"
43 #include "net/base/load_timing_info.h"
44 #include "net/base/load_timing_info_test_util.h"
45 #include "net/base/net_errors.h"
46 #include "net/base/schemeful_site.h"
47 #include "net/base/tracing.h"
48 #include "net/base/upload_bytes_element_reader.h"
49 #include "net/cert/cert_status_flags.h"
50 #include "net/cert/x509_certificate.h"
51 #include "net/disk_cache/disk_cache.h"
52 #include "net/http/http_byte_range.h"
53 #include "net/http/http_cache_transaction.h"
54 #include "net/http/http_request_headers.h"
55 #include "net/http/http_request_info.h"
56 #include "net/http/http_response_headers.h"
57 #include "net/http/http_response_headers_test_util.h"
58 #include "net/http/http_response_info.h"
59 #include "net/http/http_transaction.h"
60 #include "net/http/http_transaction_test_util.h"
61 #include "net/http/http_util.h"
62 #include "net/http/mock_http_cache.h"
63 #include "net/log/net_log_event_type.h"
64 #include "net/log/net_log_source.h"
65 #include "net/log/net_log_with_source.h"
66 #include "net/log/test_net_log.h"
67 #include "net/log/test_net_log_util.h"
68 #include "net/socket/client_socket_handle.h"
69 #include "net/ssl/ssl_cert_request_info.h"
70 #include "net/ssl/ssl_connection_status_flags.h"
71 #include "net/test/cert_test_util.h"
72 #include "net/test/gtest_util.h"
73 #include "net/test/test_data_directory.h"
74 #include "net/test/test_with_task_environment.h"
75 #include "net/websockets/websocket_handshake_stream_base.h"
76 #include "testing/gmock/include/gmock/gmock.h"
77 #include "testing/gtest/include/gtest/gtest.h"
78 #include "third_party/abseil-cpp/absl/types/optional.h"
79 #include "url/origin.h"
80
81 using net::test::IsError;
82 using net::test::IsOk;
83 using testing::AllOf;
84 using testing::ByRef;
85 using testing::Contains;
86 using testing::ElementsAre;
87 using testing::Eq;
88 using testing::Field;
89 using testing::Gt;
90 using testing::IsEmpty;
91 using testing::NotNull;
92
93 using base::Time;
94
95 namespace net {
96
97 using CacheEntryStatus = HttpResponseInfo::CacheEntryStatus;
98
99 class WebSocketEndpointLockManager;
100
101 namespace {
102
103 constexpr auto ToSimpleString = test::HttpResponseHeadersToSimpleString;
104
105 // Tests the load timing values of a request that goes through a
106 // MockNetworkTransaction.
TestLoadTimingNetworkRequest(const LoadTimingInfo & load_timing_info)107 void TestLoadTimingNetworkRequest(const LoadTimingInfo& load_timing_info) {
108 EXPECT_FALSE(load_timing_info.socket_reused);
109 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
110
111 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
112 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
113
114 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
115 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
116 EXPECT_LE(load_timing_info.connect_timing.connect_end,
117 load_timing_info.send_start);
118
119 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
120
121 // Set by URLRequest / URLRequestHttpJob, at a higher level.
122 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
123 EXPECT_TRUE(load_timing_info.request_start.is_null());
124 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
125 }
126
127 // Tests the load timing values of a request that receives a cached response.
TestLoadTimingCachedResponse(const LoadTimingInfo & load_timing_info)128 void TestLoadTimingCachedResponse(const LoadTimingInfo& load_timing_info) {
129 EXPECT_FALSE(load_timing_info.socket_reused);
130 EXPECT_EQ(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
131
132 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
133 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
134
135 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
136
137 // Only the send start / end times should be sent, and they should have the
138 // same value.
139 EXPECT_FALSE(load_timing_info.send_start.is_null());
140 EXPECT_EQ(load_timing_info.send_start, load_timing_info.send_end);
141
142 // Set by URLRequest / URLRequestHttpJob, at a higher level.
143 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
144 EXPECT_TRUE(load_timing_info.request_start.is_null());
145 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
146 }
147
DeferCallback(bool * defer)148 void DeferCallback(bool* defer) {
149 *defer = true;
150 }
151
152 class DeleteCacheCompletionCallback : public TestCompletionCallbackBase {
153 public:
DeleteCacheCompletionCallback(std::unique_ptr<MockHttpCache> cache)154 explicit DeleteCacheCompletionCallback(std::unique_ptr<MockHttpCache> cache)
155 : cache_(std::move(cache)) {}
156
157 DeleteCacheCompletionCallback(const DeleteCacheCompletionCallback&) = delete;
158 DeleteCacheCompletionCallback& operator=(
159 const DeleteCacheCompletionCallback&) = delete;
160
callback()161 CompletionOnceCallback callback() {
162 return base::BindOnce(&DeleteCacheCompletionCallback::OnComplete,
163 base::Unretained(this));
164 }
165
166 private:
OnComplete(int result)167 void OnComplete(int result) {
168 cache_.reset();
169 SetResult(result);
170 }
171
172 std::unique_ptr<MockHttpCache> cache_;
173 };
174
175 //-----------------------------------------------------------------------------
176 // helpers
177
ReadAndVerifyTransaction(HttpTransaction * trans,const MockTransaction & trans_info)178 void ReadAndVerifyTransaction(HttpTransaction* trans,
179 const MockTransaction& trans_info) {
180 std::string content;
181 int rv = ReadTransaction(trans, &content);
182
183 EXPECT_THAT(rv, IsOk());
184 std::string expected(trans_info.data);
185 EXPECT_EQ(expected, content);
186 }
187
ReadRemainingAndVerifyTransaction(HttpTransaction * trans,const std::string & already_read,const MockTransaction & trans_info)188 void ReadRemainingAndVerifyTransaction(HttpTransaction* trans,
189 const std::string& already_read,
190 const MockTransaction& trans_info) {
191 std::string content;
192 int rv = ReadTransaction(trans, &content);
193 EXPECT_THAT(rv, IsOk());
194
195 std::string expected(trans_info.data);
196 EXPECT_EQ(expected, already_read + content);
197 }
198
RunTransactionTestBase(HttpCache * cache,const MockTransaction & trans_info,const MockHttpRequest & request,HttpResponseInfo * response_info,const NetLogWithSource & net_log,LoadTimingInfo * load_timing_info,int64_t * sent_bytes,int64_t * received_bytes,IPEndPoint * remote_endpoint)199 void RunTransactionTestBase(HttpCache* cache,
200 const MockTransaction& trans_info,
201 const MockHttpRequest& request,
202 HttpResponseInfo* response_info,
203 const NetLogWithSource& net_log,
204 LoadTimingInfo* load_timing_info,
205 int64_t* sent_bytes,
206 int64_t* received_bytes,
207 IPEndPoint* remote_endpoint) {
208 TestCompletionCallback callback;
209
210 // write to the cache
211
212 std::unique_ptr<HttpTransaction> trans;
213 int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &trans);
214 EXPECT_THAT(rv, IsOk());
215 ASSERT_TRUE(trans.get());
216
217 rv = trans->Start(&request, callback.callback(), net_log);
218 if (rv == ERR_IO_PENDING)
219 rv = callback.WaitForResult();
220 ASSERT_EQ(trans_info.start_return_code, rv);
221
222 if (OK != rv)
223 return;
224
225 const HttpResponseInfo* response = trans->GetResponseInfo();
226 ASSERT_TRUE(response);
227
228 if (response_info)
229 *response_info = *response;
230
231 if (load_timing_info) {
232 // If a fake network connection is used, need a NetLog to get a fake socket
233 // ID.
234 EXPECT_TRUE(net_log.net_log());
235 *load_timing_info = LoadTimingInfo();
236 trans->GetLoadTimingInfo(load_timing_info);
237 }
238
239 if (remote_endpoint)
240 ASSERT_TRUE(trans->GetRemoteEndpoint(remote_endpoint));
241
242 ReadAndVerifyTransaction(trans.get(), trans_info);
243
244 if (sent_bytes)
245 *sent_bytes = trans->GetTotalSentBytes();
246 if (received_bytes)
247 *received_bytes = trans->GetTotalReceivedBytes();
248 }
249
RunTransactionTestWithRequest(HttpCache * cache,const MockTransaction & trans_info,const MockHttpRequest & request,HttpResponseInfo * response_info)250 void RunTransactionTestWithRequest(HttpCache* cache,
251 const MockTransaction& trans_info,
252 const MockHttpRequest& request,
253 HttpResponseInfo* response_info) {
254 RunTransactionTestBase(cache, trans_info, request, response_info,
255 NetLogWithSource(), nullptr, nullptr, nullptr,
256 nullptr);
257 }
258
RunTransactionTestAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)259 void RunTransactionTestAndGetTiming(HttpCache* cache,
260 const MockTransaction& trans_info,
261 const NetLogWithSource& log,
262 LoadTimingInfo* load_timing_info) {
263 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
264 nullptr, log, load_timing_info, nullptr, nullptr,
265 nullptr);
266 }
267
RunTransactionTestAndGetTimingAndConnectedSocketAddress(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log,LoadTimingInfo * load_timing_info,IPEndPoint * remote_endpoint)268 void RunTransactionTestAndGetTimingAndConnectedSocketAddress(
269 HttpCache* cache,
270 const MockTransaction& trans_info,
271 const NetLogWithSource& log,
272 LoadTimingInfo* load_timing_info,
273 IPEndPoint* remote_endpoint) {
274 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
275 nullptr, log, load_timing_info, nullptr, nullptr,
276 remote_endpoint);
277 }
278
RunTransactionTest(HttpCache * cache,const MockTransaction & trans_info)279 void RunTransactionTest(HttpCache* cache, const MockTransaction& trans_info) {
280 RunTransactionTestAndGetTiming(cache, trans_info, NetLogWithSource(),
281 nullptr);
282 }
283
RunTransactionTestWithLog(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log)284 void RunTransactionTestWithLog(HttpCache* cache,
285 const MockTransaction& trans_info,
286 const NetLogWithSource& log) {
287 RunTransactionTestAndGetTiming(cache, trans_info, log, nullptr);
288 }
289
RunTransactionTestWithResponseInfo(HttpCache * cache,const MockTransaction & trans_info,HttpResponseInfo * response)290 void RunTransactionTestWithResponseInfo(HttpCache* cache,
291 const MockTransaction& trans_info,
292 HttpResponseInfo* response) {
293 RunTransactionTestWithRequest(cache, trans_info, MockHttpRequest(trans_info),
294 response);
295 }
296
RunTransactionTestWithResponseInfoAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,HttpResponseInfo * response,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)297 void RunTransactionTestWithResponseInfoAndGetTiming(
298 HttpCache* cache,
299 const MockTransaction& trans_info,
300 HttpResponseInfo* response,
301 const NetLogWithSource& log,
302 LoadTimingInfo* load_timing_info) {
303 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
304 response, log, load_timing_info, nullptr, nullptr,
305 nullptr);
306 }
307
RunTransactionTestWithResponse(HttpCache * cache,const MockTransaction & trans_info,std::string * response_headers)308 void RunTransactionTestWithResponse(HttpCache* cache,
309 const MockTransaction& trans_info,
310 std::string* response_headers) {
311 HttpResponseInfo response;
312 RunTransactionTestWithResponseInfo(cache, trans_info, &response);
313 *response_headers = ToSimpleString(response.headers);
314 }
315
RunTransactionTestWithResponseAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,std::string * response_headers,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)316 void RunTransactionTestWithResponseAndGetTiming(
317 HttpCache* cache,
318 const MockTransaction& trans_info,
319 std::string* response_headers,
320 const NetLogWithSource& log,
321 LoadTimingInfo* load_timing_info) {
322 HttpResponseInfo response;
323 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
324 &response, log, load_timing_info, nullptr, nullptr,
325 nullptr);
326 *response_headers = ToSimpleString(response.headers);
327 }
328
329 // This class provides a handler for kFastNoStoreGET_Transaction so that the
330 // no-store header can be included on demand.
331 class FastTransactionServer {
332 public:
FastTransactionServer()333 FastTransactionServer() {
334 no_store = false;
335 }
336
337 FastTransactionServer(const FastTransactionServer&) = delete;
338 FastTransactionServer& operator=(const FastTransactionServer&) = delete;
339
340 ~FastTransactionServer() = default;
341
set_no_store(bool value)342 void set_no_store(bool value) { no_store = value; }
343
FastNoStoreHandler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)344 static void FastNoStoreHandler(const HttpRequestInfo* request,
345 std::string* response_status,
346 std::string* response_headers,
347 std::string* response_data) {
348 if (no_store)
349 *response_headers = "Cache-Control: no-store\n";
350 }
351
352 private:
353 static bool no_store;
354 };
355 bool FastTransactionServer::no_store;
356
357 const MockTransaction kFastNoStoreGET_Transaction = {
358 "http://www.google.com/nostore",
359 "GET",
360 base::Time(),
361 "",
362 LOAD_VALIDATE_CACHE,
363 DefaultTransportInfo(),
364 "HTTP/1.1 200 OK",
365 "Cache-Control: max-age=10000\n",
366 base::Time(),
367 "<html><body>Google Blah Blah</body></html>",
368 {},
369 absl::nullopt,
370 absl::nullopt,
371 TEST_MODE_SYNC_NET_START,
372 base::BindRepeating(&FastTransactionServer::FastNoStoreHandler),
373 MockTransactionReadHandler(),
374 nullptr,
375 0,
376 0,
377 OK,
378 };
379
380 // This class provides a handler for kRangeGET_TransactionOK so that the range
381 // request can be served on demand.
382 class RangeTransactionServer {
383 public:
RangeTransactionServer()384 RangeTransactionServer() {
385 not_modified_ = false;
386 modified_ = false;
387 bad_200_ = false;
388 redirect_ = false;
389 length_ = 80;
390 }
391
392 RangeTransactionServer(const RangeTransactionServer&) = delete;
393 RangeTransactionServer& operator=(const RangeTransactionServer&) = delete;
394
~RangeTransactionServer()395 ~RangeTransactionServer() {
396 not_modified_ = false;
397 modified_ = false;
398 bad_200_ = false;
399 redirect_ = false;
400 length_ = 80;
401 }
402
403 // Returns only 416 or 304 when set.
set_not_modified(bool value)404 void set_not_modified(bool value) { not_modified_ = value; }
405
406 // Returns 206 when revalidating a range (instead of 304).
set_modified(bool value)407 void set_modified(bool value) { modified_ = value; }
408
409 // Returns 200 instead of 206 (a malformed response overall).
set_bad_200(bool value)410 void set_bad_200(bool value) { bad_200_ = value; }
411
412 // Sets how long the resource is. (Default is 80)
set_length(int64_t length)413 void set_length(int64_t length) { length_ = length; }
414
415 // Sets whether to return a 301 instead of normal return.
set_redirect(bool redirect)416 void set_redirect(bool redirect) { redirect_ = redirect; }
417
418 // Other than regular range related behavior (and the flags mentioned above),
419 // the server reacts to requests headers like so:
420 // X-Require-Mock-Auth -> return 401.
421 // X-Require-Mock-Auth-Alt -> return 401.
422 // X-Return-Default-Range -> assume 40-49 was requested.
423 // The -Alt variant doesn't cause the MockNetworkTransaction to
424 // report that it IsReadyToRestartForAuth().
425 static void RangeHandler(const HttpRequestInfo* request,
426 std::string* response_status,
427 std::string* response_headers,
428 std::string* response_data);
429
430 private:
431 static bool not_modified_;
432 static bool modified_;
433 static bool bad_200_;
434 static bool redirect_;
435 static int64_t length_;
436 };
437 bool RangeTransactionServer::not_modified_ = false;
438 bool RangeTransactionServer::modified_ = false;
439 bool RangeTransactionServer::bad_200_ = false;
440 bool RangeTransactionServer::redirect_ = false;
441 int64_t RangeTransactionServer::length_ = 80;
442
443 // A dummy extra header that must be preserved on a given request.
444
445 // EXTRA_HEADER_LINE doesn't include a line terminator because it
446 // will be passed to AddHeaderFromString() which doesn't accept them.
447 #define EXTRA_HEADER_LINE "Extra: header"
448
449 // EXTRA_HEADER contains a line terminator, as expected by
450 // AddHeadersFromString() (_not_ AddHeaderFromString()).
451 #define EXTRA_HEADER EXTRA_HEADER_LINE "\r\n"
452
453 static const char kExtraHeaderKey[] = "Extra";
454
455 // Static.
RangeHandler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)456 void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request,
457 std::string* response_status,
458 std::string* response_headers,
459 std::string* response_data) {
460 if (request->extra_headers.IsEmpty()) {
461 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
462 response_data->clear();
463 return;
464 }
465
466 // We want to make sure we don't delete extra headers.
467 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
468
469 bool require_auth =
470 request->extra_headers.HasHeader("X-Require-Mock-Auth") ||
471 request->extra_headers.HasHeader("X-Require-Mock-Auth-Alt");
472
473 if (require_auth && !request->extra_headers.HasHeader("Authorization")) {
474 response_status->assign("HTTP/1.1 401 Unauthorized");
475 response_data->assign("WWW-Authenticate: Foo\n");
476 return;
477 }
478
479 if (redirect_) {
480 response_status->assign("HTTP/1.1 301 Moved Permanently");
481 response_headers->assign("Location: /elsewhere\nContent-Length: 5");
482 response_data->assign("12345");
483 return;
484 }
485
486 if (not_modified_) {
487 response_status->assign("HTTP/1.1 304 Not Modified");
488 response_data->clear();
489 return;
490 }
491
492 std::vector<HttpByteRange> ranges;
493 std::string range_header;
494 if (!request->extra_headers.GetHeader(HttpRequestHeaders::kRange,
495 &range_header) ||
496 !HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ ||
497 ranges.size() != 1 ||
498 (modified_ && request->extra_headers.HasHeader("If-Range"))) {
499 // This is not a byte range request, or a failed If-Range. We return 200.
500 response_status->assign("HTTP/1.1 200 OK");
501 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT");
502 response_data->assign("Not a range");
503 return;
504 }
505
506 // We can handle this range request.
507 HttpByteRange byte_range = ranges[0];
508
509 if (request->extra_headers.HasHeader("X-Return-Default-Range")) {
510 byte_range.set_first_byte_position(40);
511 byte_range.set_last_byte_position(49);
512 }
513
514 if (byte_range.first_byte_position() >= length_) {
515 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
516 response_data->clear();
517 return;
518 }
519
520 EXPECT_TRUE(byte_range.ComputeBounds(length_));
521 int64_t start = byte_range.first_byte_position();
522 int64_t end = byte_range.last_byte_position();
523
524 EXPECT_LT(end, length_);
525
526 std::string content_range = base::StringPrintf("Content-Range: bytes %" PRId64
527 "-%" PRId64 "/%" PRId64 "\n",
528 start, end, length_);
529 response_headers->append(content_range);
530
531 if (!request->extra_headers.HasHeader("If-None-Match") || modified_) {
532 std::string data;
533 if (end == start) {
534 EXPECT_EQ(0, end % 10);
535 data = "r";
536 } else {
537 EXPECT_EQ(9, (end - start) % 10);
538 for (int64_t block_start = start; block_start < end; block_start += 10) {
539 base::StringAppendF(&data, "rg: %02" PRId64 "-%02" PRId64 " ",
540 block_start % 100, (block_start + 9) % 100);
541 }
542 }
543 *response_data = data;
544
545 if (end - start != 9) {
546 // We also have to fix content-length.
547 int64_t len = end - start + 1;
548 std::string content_length =
549 base::StringPrintf("Content-Length: %" PRId64 "\n", len);
550 response_headers->replace(response_headers->find("Content-Length:"),
551 content_length.size(), content_length);
552 }
553 } else {
554 response_status->assign("HTTP/1.1 304 Not Modified");
555 response_data->clear();
556 }
557 }
558
559 const MockTransaction kRangeGET_TransactionOK = {
560 "http://www.google.com/range",
561 "GET",
562 base::Time(),
563 "Range: bytes = 40-49\r\n" EXTRA_HEADER,
564 LOAD_NORMAL,
565 DefaultTransportInfo(),
566 "HTTP/1.1 206 Partial Content",
567 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
568 "ETag: \"foo\"\n"
569 "Accept-Ranges: bytes\n"
570 "Content-Length: 10\n",
571 base::Time(),
572 "rg: 40-49 ",
573 {},
574 absl::nullopt,
575 absl::nullopt,
576 TEST_MODE_NORMAL,
577 base::BindRepeating(&RangeTransactionServer::RangeHandler),
578 MockTransactionReadHandler(),
579 nullptr,
580 0,
581 0,
582 OK,
583 };
584
585 const char kFullRangeData[] =
586 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 "
587 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 ";
588
589 // Verifies the response headers (|response|) match a partial content
590 // response for the range starting at |start| and ending at |end|.
Verify206Response(const std::string & response,int start,int end)591 void Verify206Response(const std::string& response, int start, int end) {
592 auto headers = base::MakeRefCounted<HttpResponseHeaders>(
593 HttpUtil::AssembleRawHeaders(response));
594
595 ASSERT_EQ(206, headers->response_code());
596
597 int64_t range_start, range_end, object_size;
598 ASSERT_TRUE(
599 headers->GetContentRangeFor206(&range_start, &range_end, &object_size));
600 int64_t content_length = headers->GetContentLength();
601
602 int length = end - start + 1;
603 ASSERT_EQ(length, content_length);
604 ASSERT_EQ(start, range_start);
605 ASSERT_EQ(end, range_end);
606 }
607
608 // Creates a truncated entry that can be resumed using byte ranges.
CreateTruncatedEntry(std::string raw_headers,MockHttpCache * cache)609 void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) {
610 // Create a disk cache entry that stores an incomplete resource.
611 disk_cache::Entry* entry;
612 MockHttpRequest request(kRangeGET_TransactionOK);
613 ASSERT_TRUE(cache->CreateBackendEntry(request.CacheKey(), &entry, nullptr));
614
615 HttpResponseInfo response;
616 response.response_time = base::Time::Now();
617 response.request_time = base::Time::Now();
618 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
619 HttpUtil::AssembleRawHeaders(raw_headers));
620 // Set the last argument for this to be an incomplete request.
621 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
622
623 auto buf = base::MakeRefCounted<IOBufferWithSize>(100);
624 int len = static_cast<int>(base::strlcpy(buf->data(),
625 "rg: 00-09 rg: 10-19 ", 100));
626 TestCompletionCallback cb;
627 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
628 EXPECT_EQ(len, cb.GetResult(rv));
629 entry->Close();
630 }
631
632 // Verifies that there's an entry with this |key| with the truncated flag set to
633 // |flag_value|, and with an optional |data_size| (if not zero).
VerifyTruncatedFlag(MockHttpCache * cache,const std::string & key,bool flag_value,int data_size)634 void VerifyTruncatedFlag(MockHttpCache* cache,
635 const std::string& key,
636 bool flag_value,
637 int data_size) {
638 disk_cache::Entry* entry;
639 ASSERT_TRUE(cache->OpenBackendEntry(key, &entry));
640 disk_cache::ScopedEntryPtr closer(entry);
641
642 HttpResponseInfo response;
643 bool truncated = !flag_value;
644 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
645 EXPECT_EQ(flag_value, truncated);
646 if (data_size)
647 EXPECT_EQ(data_size, entry->GetDataSize(1));
648 }
649
650 // Helper to represent a network HTTP response.
651 struct Response {
652 // Set this response into |trans|.
AssignTonet::__anond56f448a0111::Response653 void AssignTo(MockTransaction* trans) const {
654 trans->status = status;
655 trans->response_headers = headers;
656 trans->data = body;
657 }
658
status_and_headersnet::__anond56f448a0111::Response659 std::string status_and_headers() const {
660 return std::string(status) + "\n" + std::string(headers);
661 }
662
663 const char* status;
664 const char* headers;
665 const char* body;
666 };
667
668 struct Context {
669 Context() = default;
670
671 int result = ERR_IO_PENDING;
672 TestCompletionCallback callback;
673 std::unique_ptr<HttpTransaction> trans;
674 };
675
676 class FakeWebSocketHandshakeStreamCreateHelper
677 : public WebSocketHandshakeStreamBase::CreateHelper {
678 public:
679 ~FakeWebSocketHandshakeStreamCreateHelper() override = default;
CreateBasicStream(std::unique_ptr<ClientSocketHandle> connect,bool using_proxy,WebSocketEndpointLockManager * websocket_endpoint_lock_manager)680 std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream(
681 std::unique_ptr<ClientSocketHandle> connect,
682 bool using_proxy,
683 WebSocketEndpointLockManager* websocket_endpoint_lock_manager) override {
684 return nullptr;
685 }
CreateHttp2Stream(base::WeakPtr<SpdySession> session,std::set<std::string> dns_aliases)686 std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream(
687 base::WeakPtr<SpdySession> session,
688 std::set<std::string> dns_aliases) override {
689 NOTREACHED();
690 return nullptr;
691 }
CreateHttp3Stream(std::unique_ptr<QuicChromiumClientSession::Handle> session,std::set<std::string> dns_aliases)692 std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp3Stream(
693 std::unique_ptr<QuicChromiumClientSession::Handle> session,
694 std::set<std::string> dns_aliases) override {
695 NOTREACHED();
696 return nullptr;
697 }
698 };
699
700 // Returns true if |entry| is not one of the log types paid attention to in this
701 // test. Note that HTTP_CACHE_WRITE_INFO and HTTP_CACHE_*_DATA are
702 // ignored.
ShouldIgnoreLogEntry(const NetLogEntry & entry)703 bool ShouldIgnoreLogEntry(const NetLogEntry& entry) {
704 switch (entry.type) {
705 case NetLogEventType::HTTP_CACHE_GET_BACKEND:
706 case NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY:
707 case NetLogEventType::HTTP_CACHE_OPEN_ENTRY:
708 case NetLogEventType::HTTP_CACHE_CREATE_ENTRY:
709 case NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY:
710 case NetLogEventType::HTTP_CACHE_DOOM_ENTRY:
711 case NetLogEventType::HTTP_CACHE_READ_INFO:
712 return false;
713 default:
714 return true;
715 }
716 }
717
718 // Gets the entries from |net_log| created by the cache layer and asserted on in
719 // these tests.
GetFilteredNetLogEntries(const RecordingNetLogObserver & net_log_observer)720 std::vector<NetLogEntry> GetFilteredNetLogEntries(
721 const RecordingNetLogObserver& net_log_observer) {
722 auto entries = net_log_observer.GetEntries();
723 base::EraseIf(entries, ShouldIgnoreLogEntry);
724 return entries;
725 }
726
LogContainsEventType(const RecordingNetLogObserver & net_log_observer,NetLogEventType expected)727 bool LogContainsEventType(const RecordingNetLogObserver& net_log_observer,
728 NetLogEventType expected) {
729 return !net_log_observer.GetEntriesWithType(expected).empty();
730 }
731
732 // Returns a TransportInfo distinct from the default for mock transactions,
733 // with the given port number.
TestTransportInfoWithPort(uint16_t port)734 TransportInfo TestTransportInfoWithPort(uint16_t port) {
735 TransportInfo result;
736 result.endpoint = IPEndPoint(IPAddress(42, 0, 1, 2), port);
737 return result;
738 }
739
740 // Returns a TransportInfo distinct from the default for mock transactions.
TestTransportInfo()741 TransportInfo TestTransportInfo() {
742 return TestTransportInfoWithPort(1337);
743 }
744
CachedTestTransportInfo()745 TransportInfo CachedTestTransportInfo() {
746 TransportInfo result = TestTransportInfo();
747 result.type = TransportType::kCached;
748 return result;
749 }
750
751 // Helper function, generating valid HTTP cache key from `url`.
752 // See also: HttpCache::GenerateCacheKey(..)
GenerateCacheKey(const std::string & url)753 std::string GenerateCacheKey(const std::string& url) {
754 return "1/0/" + url;
755 }
756
757 } // namespace
758
759 using HttpCacheTest = TestWithTaskEnvironment;
760
761 class HttpCacheIOCallbackTest : public HttpCacheTest {
762 public:
763 HttpCacheIOCallbackTest() = default;
764 ~HttpCacheIOCallbackTest() override = default;
765
766 // HttpCache::ActiveEntry is private, doing this allows tests to use it
767 using ActiveEntry = HttpCache::ActiveEntry;
768 using Transaction = HttpCache::Transaction;
769
770 // The below functions are forwarding calls to the HttpCache class.
OpenEntry(HttpCache * cache,const std::string & url,HttpCache::ActiveEntry ** entry,HttpCache::Transaction * trans)771 int OpenEntry(HttpCache* cache,
772 const std::string& url,
773 HttpCache::ActiveEntry** entry,
774 HttpCache::Transaction* trans) {
775 return cache->OpenEntry(GenerateCacheKey(url), entry, trans);
776 }
777
OpenOrCreateEntry(HttpCache * cache,const std::string & url,HttpCache::ActiveEntry ** entry,HttpCache::Transaction * trans)778 int OpenOrCreateEntry(HttpCache* cache,
779 const std::string& url,
780 HttpCache::ActiveEntry** entry,
781 HttpCache::Transaction* trans) {
782 return cache->OpenOrCreateEntry(GenerateCacheKey(url), entry, trans);
783 }
784
CreateEntry(HttpCache * cache,const std::string & url,HttpCache::ActiveEntry ** entry,HttpCache::Transaction * trans)785 int CreateEntry(HttpCache* cache,
786 const std::string& url,
787 HttpCache::ActiveEntry** entry,
788 HttpCache::Transaction* trans) {
789 return cache->CreateEntry(GenerateCacheKey(url), entry, trans);
790 }
791
DoomEntry(HttpCache * cache,const std::string & url,HttpCache::Transaction * trans)792 int DoomEntry(HttpCache* cache,
793 const std::string& url,
794 HttpCache::Transaction* trans) {
795 return cache->DoomEntry(GenerateCacheKey(url), trans);
796 }
797
DeactivateEntry(HttpCache * cache,ActiveEntry * entry)798 void DeactivateEntry(HttpCache* cache, ActiveEntry* entry) {
799 cache->DeactivateEntry(entry);
800 }
801 };
802
803 class HttpSplitCacheKeyTest : public HttpCacheTest {
804 public:
805 HttpSplitCacheKeyTest() = default;
806 ~HttpSplitCacheKeyTest() override = default;
807
ComputeCacheKey(const std::string & url_string)808 std::string ComputeCacheKey(const std::string& url_string) {
809 GURL url(url_string);
810 SchemefulSite site(url);
811 net::HttpRequestInfo request_info;
812 request_info.url = url;
813 request_info.method = "GET";
814 request_info.network_isolation_key = net::NetworkIsolationKey(site, site);
815 request_info.network_anonymization_key =
816 net::NetworkAnonymizationKey::CreateSameSite(site);
817 MockHttpCache cache;
818 return *cache.http_cache()->GenerateCacheKeyForRequest(&request_info);
819 }
820 };
821
822 //-----------------------------------------------------------------------------
823 // Tests.
824
TEST_F(HttpCacheTest,CreateThenDestroy)825 TEST_F(HttpCacheTest, CreateThenDestroy) {
826 MockHttpCache cache;
827
828 std::unique_ptr<HttpTransaction> trans;
829 EXPECT_THAT(cache.CreateTransaction(&trans), IsOk());
830 ASSERT_TRUE(trans.get());
831 }
832
TEST_F(HttpCacheTest,GetBackend)833 TEST_F(HttpCacheTest, GetBackend) {
834 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(0));
835
836 disk_cache::Backend* backend;
837 TestCompletionCallback cb;
838 // This will lazily initialize the backend.
839 int rv = cache.http_cache()->GetBackend(&backend, cb.callback());
840 EXPECT_THAT(cb.GetResult(rv), IsOk());
841 }
842
TEST_F(HttpCacheTest,SimpleGET)843 TEST_F(HttpCacheTest, SimpleGET) {
844 MockHttpCache cache;
845 LoadTimingInfo load_timing_info;
846
847 // Write to the cache.
848 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
849 NetLogWithSource::Make(NetLogSourceType::NONE),
850 &load_timing_info);
851
852 EXPECT_EQ(1, cache.network_layer()->transaction_count());
853 EXPECT_EQ(0, cache.disk_cache()->open_count());
854 EXPECT_EQ(1, cache.disk_cache()->create_count());
855 TestLoadTimingNetworkRequest(load_timing_info);
856 }
857
858 // This test verifies that the callback passed to SetConnectedCallback() is
859 // called once for simple GET calls that traverse the cache.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallback)860 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallback) {
861 MockHttpCache cache;
862
863 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
864 mock_transaction.transport_info = TestTransportInfo();
865 MockHttpRequest request(mock_transaction);
866
867 ConnectedHandler connected_handler;
868
869 std::unique_ptr<HttpTransaction> transaction;
870 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
871 ASSERT_THAT(transaction, NotNull());
872
873 transaction->SetConnectedCallback(connected_handler.Callback());
874
875 TestCompletionCallback callback;
876 ASSERT_THAT(
877 transaction->Start(&request, callback.callback(), NetLogWithSource()),
878 IsError(ERR_IO_PENDING));
879 EXPECT_THAT(callback.WaitForResult(), IsOk());
880
881 EXPECT_THAT(connected_handler.transports(), ElementsAre(TestTransportInfo()));
882 }
883
884 // This test verifies that when the callback passed to SetConnectedCallback()
885 // returns an error, the transaction fails with that error.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackReturnError)886 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackReturnError) {
887 MockHttpCache cache;
888 MockHttpRequest request(kSimpleGET_Transaction);
889 ConnectedHandler connected_handler;
890
891 std::unique_ptr<HttpTransaction> transaction;
892 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
893 ASSERT_THAT(transaction, NotNull());
894
895 // The exact error code does not matter. We only care that it is passed to
896 // the transaction's completion callback unmodified.
897 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
898 transaction->SetConnectedCallback(connected_handler.Callback());
899
900 TestCompletionCallback callback;
901 ASSERT_THAT(
902 transaction->Start(&request, callback.callback(), NetLogWithSource()),
903 IsError(ERR_IO_PENDING));
904 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));
905 }
906
907 // This test verifies that the callback passed to SetConnectedCallback() is
908 // called once for requests that hit the cache.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHit)909 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHit) {
910 MockHttpCache cache;
911
912 {
913 // Populate the cache.
914 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
915 mock_transaction.transport_info = TestTransportInfo();
916 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
917 }
918
919 // Establish a baseline.
920 EXPECT_EQ(1, cache.network_layer()->transaction_count());
921
922 // Load from the cache (only), observe the callback being called.
923
924 ConnectedHandler connected_handler;
925 MockHttpRequest request(kSimpleGET_Transaction);
926
927 std::unique_ptr<HttpTransaction> transaction;
928 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
929 ASSERT_THAT(transaction, NotNull());
930
931 transaction->SetConnectedCallback(connected_handler.Callback());
932
933 TestCompletionCallback callback;
934 ASSERT_THAT(
935 transaction->Start(&request, callback.callback(), NetLogWithSource()),
936 IsError(ERR_IO_PENDING));
937 EXPECT_THAT(callback.WaitForResult(), IsOk());
938
939 // Still only 1 transaction for the previous request. The connected callback
940 // was not called by a second network transaction.
941 EXPECT_EQ(1, cache.network_layer()->transaction_count());
942
943 EXPECT_THAT(connected_handler.transports(),
944 ElementsAre(CachedTestTransportInfo()));
945 }
946
947 // This test verifies that when the callback passed to SetConnectedCallback()
948 // is called for a request that hit the cache and returns an error, the cache
949 // entry is reusable.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnError)950 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHitReturnError) {
951 MockHttpCache cache;
952
953 {
954 // Populate the cache.
955 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
956 mock_transaction.transport_info = TestTransportInfo();
957 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
958 }
959
960 MockHttpRequest request(kSimpleGET_Transaction);
961
962 {
963 // Attempt to read from cache entry, but abort transaction due to a
964 // connected callback error.
965 ConnectedHandler connected_handler;
966 connected_handler.set_result(ERR_FAILED);
967
968 std::unique_ptr<HttpTransaction> transaction;
969 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
970 ASSERT_THAT(transaction, NotNull());
971
972 transaction->SetConnectedCallback(connected_handler.Callback());
973
974 TestCompletionCallback callback;
975 ASSERT_THAT(
976 transaction->Start(&request, callback.callback(), NetLogWithSource()),
977 IsError(ERR_IO_PENDING));
978 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));
979
980 // Used the cache entry only.
981 EXPECT_THAT(connected_handler.transports(),
982 ElementsAre(CachedTestTransportInfo()));
983 }
984
985 {
986 // Request the same resource once more, observe that it is read from cache.
987 ConnectedHandler connected_handler;
988
989 std::unique_ptr<HttpTransaction> transaction;
990 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
991 ASSERT_THAT(transaction, NotNull());
992
993 transaction->SetConnectedCallback(connected_handler.Callback());
994
995 TestCompletionCallback callback;
996 ASSERT_THAT(
997 transaction->Start(&request, callback.callback(), NetLogWithSource()),
998 IsError(ERR_IO_PENDING));
999 EXPECT_THAT(callback.WaitForResult(), IsOk());
1000
1001 // Used the cache entry only.
1002 EXPECT_THAT(connected_handler.transports(),
1003 ElementsAre(CachedTestTransportInfo()));
1004 }
1005 }
1006
1007 // This test verifies that when the callback passed to SetConnectedCallback()
1008 // returns `ERR_INCONSISTENT_IP_ADDRESS_SPACE`, the cache entry is invalidated.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnInconsistentIpError)1009 TEST_F(HttpCacheTest,
1010 SimpleGET_ConnectedCallbackOnCacheHitReturnInconsistentIpError) {
1011 MockHttpCache cache;
1012
1013 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1014 mock_transaction.transport_info = TestTransportInfo();
1015
1016 // Populate the cache.
1017 RunTransactionTest(cache.http_cache(), mock_transaction);
1018
1019 MockHttpRequest request(kSimpleGET_Transaction);
1020
1021 {
1022 // Attempt to read from cache entry, but abort transaction due to a
1023 // connected callback error.
1024 ConnectedHandler connected_handler;
1025 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
1026
1027 std::unique_ptr<HttpTransaction> transaction;
1028 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1029 ASSERT_THAT(transaction, NotNull());
1030
1031 transaction->SetConnectedCallback(connected_handler.Callback());
1032
1033 TestCompletionCallback callback;
1034 ASSERT_THAT(
1035 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1036 IsError(ERR_IO_PENDING));
1037 EXPECT_THAT(callback.WaitForResult(),
1038 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
1039
1040 // Used the cache entry only.
1041 EXPECT_THAT(connected_handler.transports(),
1042 ElementsAre(CachedTestTransportInfo()));
1043 }
1044
1045 {
1046 // Request the same resource once more, observe that it is not read from
1047 // cache.
1048 ConnectedHandler connected_handler;
1049
1050 std::unique_ptr<HttpTransaction> transaction;
1051 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1052 ASSERT_THAT(transaction, NotNull());
1053
1054 transaction->SetConnectedCallback(connected_handler.Callback());
1055
1056 TestCompletionCallback callback;
1057 ASSERT_THAT(
1058 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1059 IsError(ERR_IO_PENDING));
1060 EXPECT_THAT(callback.WaitForResult(), IsOk());
1061
1062 // Used the network only.
1063 EXPECT_THAT(connected_handler.transports(),
1064 ElementsAre(TestTransportInfo()));
1065 }
1066 }
1067
1068 // This test verifies that when the callback passed to SetConnectedCallback()
1069 // returns
1070 // `ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY`, the
1071 // cache entry is invalidated, and we'll retry the connection from the network.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnPrivateNetworkAccessBlockedError)1072 TEST_F(
1073 HttpCacheTest,
1074 SimpleGET_ConnectedCallbackOnCacheHitReturnPrivateNetworkAccessBlockedError) {
1075 MockHttpCache cache;
1076
1077 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1078 mock_transaction.transport_info = TestTransportInfo();
1079
1080 // Populate the cache.
1081 RunTransactionTest(cache.http_cache(), mock_transaction);
1082
1083 MockHttpRequest request(kSimpleGET_Transaction);
1084
1085 {
1086 // Attempt to read from cache entry, but abort transaction due to a
1087 // connected callback error.
1088 ConnectedHandler connected_handler;
1089 connected_handler.set_result(
1090 ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY);
1091
1092 std::unique_ptr<HttpTransaction> transaction;
1093 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1094 ASSERT_THAT(transaction, NotNull());
1095
1096 transaction->SetConnectedCallback(connected_handler.Callback());
1097
1098 TestCompletionCallback callback;
1099 ASSERT_THAT(
1100 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1101 IsError(ERR_IO_PENDING));
1102 EXPECT_THAT(
1103 callback.WaitForResult(),
1104 IsError(
1105 ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY));
1106
1107 // Used the cache entry only.
1108 EXPECT_THAT(connected_handler.transports(),
1109 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
1110 }
1111
1112 {
1113 // Request the same resource once more, observe that it is not read from
1114 // cache.
1115 ConnectedHandler connected_handler;
1116
1117 std::unique_ptr<HttpTransaction> transaction;
1118 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1119 ASSERT_THAT(transaction, NotNull());
1120
1121 transaction->SetConnectedCallback(connected_handler.Callback());
1122
1123 TestCompletionCallback callback;
1124 ASSERT_THAT(
1125 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1126 IsError(ERR_IO_PENDING));
1127 EXPECT_THAT(callback.WaitForResult(), IsOk());
1128
1129 // Used the network only.
1130 EXPECT_THAT(connected_handler.transports(),
1131 ElementsAre(TestTransportInfo()));
1132 }
1133 }
1134
1135 // This test verifies that the callback passed to SetConnectedCallback() is
1136 // called with the right transport type when the cached entry was originally
1137 // fetched via proxy.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitFromProxy)1138 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHitFromProxy) {
1139 MockHttpCache cache;
1140
1141 TransportInfo proxied_transport_info = TestTransportInfo();
1142 proxied_transport_info.type = TransportType::kProxied;
1143
1144 {
1145 // Populate the cache.
1146 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1147 mock_transaction.transport_info = proxied_transport_info;
1148 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1149 }
1150
1151 // Establish a baseline.
1152 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1153
1154 // Load from the cache (only), observe the callback being called.
1155
1156 ConnectedHandler connected_handler;
1157 MockHttpRequest request(kSimpleGET_Transaction);
1158
1159 std::unique_ptr<HttpTransaction> transaction;
1160 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1161 ASSERT_THAT(transaction, NotNull());
1162
1163 transaction->SetConnectedCallback(connected_handler.Callback());
1164
1165 TestCompletionCallback callback;
1166 ASSERT_THAT(
1167 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1168 IsError(ERR_IO_PENDING));
1169 EXPECT_THAT(callback.WaitForResult(), IsOk());
1170
1171 // Still only 1 transaction for the previous request. The connected callback
1172 // was not called by a second network transaction.
1173 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1174
1175 // The transport info mentions both the cache and the original proxy.
1176 TransportInfo expected_transport_info = TestTransportInfo();
1177 expected_transport_info.type = TransportType::kCachedFromProxy;
1178
1179 EXPECT_THAT(connected_handler.transports(),
1180 ElementsAre(expected_transport_info));
1181 }
1182
TEST_F(HttpCacheTest,SimpleGET_DelayedCacheLock)1183 TEST_F(HttpCacheTest, SimpleGET_DelayedCacheLock) {
1184 MockHttpCache cache;
1185 LoadTimingInfo load_timing_info;
1186
1187 // Configure the cache to delay the response for AddTransactionToEntry so it
1188 // gets sequenced behind any other tasks that get generated when starting the
1189 // transaction (i.e. network activity when run in parallel with the cache
1190 // lock).
1191 cache.http_cache()->DelayAddTransactionToEntryForTesting();
1192
1193 // Write to the cache.
1194 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
1195 NetLogWithSource::Make(NetLogSourceType::NONE),
1196 &load_timing_info);
1197
1198 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1199 EXPECT_EQ(0, cache.disk_cache()->open_count());
1200 EXPECT_EQ(1, cache.disk_cache()->create_count());
1201 TestLoadTimingNetworkRequest(load_timing_info);
1202 }
1203
1204 enum class SplitCacheTestCase {
1205 kSplitCacheDisabled,
1206 kSplitCacheNikFrameSiteEnabled,
1207 kSplitCacheNikCrossSiteFlagEnabled,
1208 kSplitCacheNikFrameSiteSharedOpaqueEnabled,
1209 };
1210
InitializeSplitCacheScopedFeatureList(base::test::ScopedFeatureList & scoped_feature_list,SplitCacheTestCase test_case)1211 void InitializeSplitCacheScopedFeatureList(
1212 base::test::ScopedFeatureList& scoped_feature_list,
1213 SplitCacheTestCase test_case) {
1214 std::vector<base::test::FeatureRef> enabled_features;
1215 std::vector<base::test::FeatureRef> disabled_features;
1216
1217 if (test_case == SplitCacheTestCase::kSplitCacheDisabled) {
1218 disabled_features.push_back(
1219 net::features::kSplitCacheByNetworkIsolationKey);
1220 } else {
1221 enabled_features.push_back(net::features::kSplitCacheByNetworkIsolationKey);
1222 }
1223
1224 if (test_case == SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled) {
1225 enabled_features.push_back(
1226 net::features::kEnableCrossSiteFlagNetworkIsolationKey);
1227 } else {
1228 disabled_features.push_back(
1229 net::features::kEnableCrossSiteFlagNetworkIsolationKey);
1230 }
1231
1232 if (test_case ==
1233 SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled) {
1234 enabled_features.push_back(
1235 net::features::kEnableFrameSiteSharedOpaqueNetworkIsolationKey);
1236 } else {
1237 disabled_features.push_back(
1238 net::features::kEnableFrameSiteSharedOpaqueNetworkIsolationKey);
1239 }
1240 scoped_feature_list.InitWithFeatures(enabled_features, disabled_features);
1241 }
1242
1243 class HttpCacheTest_SplitCacheFeature
1244 : public HttpCacheTest,
1245 public ::testing::WithParamInterface<SplitCacheTestCase> {
1246 public:
HttpCacheTest_SplitCacheFeature()1247 HttpCacheTest_SplitCacheFeature() {
1248 InitializeSplitCacheScopedFeatureList(feature_list_, GetParam());
1249 }
1250
IsSplitCacheEnabled() const1251 bool IsSplitCacheEnabled() const {
1252 return GetParam() != SplitCacheTestCase::kSplitCacheDisabled;
1253 }
1254
1255 private:
1256 base::test::ScopedFeatureList feature_list_;
1257 };
1258
TEST_P(HttpCacheTest_SplitCacheFeature,SimpleGETVerifyGoogleFontMetrics)1259 TEST_P(HttpCacheTest_SplitCacheFeature, SimpleGETVerifyGoogleFontMetrics) {
1260 SchemefulSite site_a(GURL("http://www.a.com"));
1261
1262 MockHttpCache cache;
1263
1264 MockTransaction transaction(kSimpleGET_Transaction);
1265 transaction.url = "http://themes.googleusercontent.com/static/fonts/roboto";
1266 AddMockTransaction(&transaction);
1267 MockHttpRequest request(transaction);
1268 request.network_isolation_key = NetworkIsolationKey(site_a, site_a);
1269 request.network_anonymization_key =
1270 net::NetworkAnonymizationKey::CreateSameSite(site_a);
1271
1272 // Attempt to populate the cache.
1273 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
1274 nullptr);
1275
1276 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
1277 nullptr);
1278 }
1279
1280 INSTANTIATE_TEST_SUITE_P(
1281 All,
1282 HttpCacheTest_SplitCacheFeature,
1283 testing::ValuesIn(
1284 {SplitCacheTestCase::kSplitCacheDisabled,
1285 SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled,
1286 SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled,
1287 SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled}),
__anond56f448a0202(const testing::TestParamInfo<SplitCacheTestCase>& info) 1288 [](const testing::TestParamInfo<SplitCacheTestCase>& info) {
1289 switch (info.param) {
1290 case (SplitCacheTestCase::kSplitCacheDisabled):
1291 return "SplitCacheDisabled";
1292 case (SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled):
1293 return "SplitCacheNikFrameSiteEnabled";
1294 case (SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled):
1295 return "SplitCacheNikCrossSiteFlagEnabled";
1296 case (SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled):
1297 return "SplitCacheNikFrameSiteSharedOpaqueEnabled";
1298 }
1299 });
1300
1301 class HttpCacheTest_SplitCacheFeatureEnabled
1302 : public HttpCacheTest_SplitCacheFeature {
1303 public:
HttpCacheTest_SplitCacheFeatureEnabled()1304 HttpCacheTest_SplitCacheFeatureEnabled() {
1305 CHECK(base::FeatureList::IsEnabled(
1306 net::features::kSplitCacheByNetworkIsolationKey));
1307 }
1308 };
1309
1310 INSTANTIATE_TEST_SUITE_P(
1311 All,
1312 HttpCacheTest_SplitCacheFeatureEnabled,
1313 testing::ValuesIn(
1314 {SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled,
1315 SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled,
1316 SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled}),
__anond56f448a0302(const testing::TestParamInfo<SplitCacheTestCase>& info) 1317 [](const testing::TestParamInfo<SplitCacheTestCase>& info) {
1318 switch (info.param) {
1319 case (SplitCacheTestCase::kSplitCacheDisabled):
1320 return "NotUsedForThisTestSuite";
1321 case (SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled):
1322 return "SplitCacheNikFrameSiteEnabled";
1323 case (SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled):
1324 return "SplitCacheNikCrossSiteFlagEnabled";
1325 case (SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled):
1326 return "SplitCacheNikFrameSiteSharedOpaqueEnabled";
1327 }
1328 });
1329
TEST_F(HttpCacheTest,SimpleGETNoDiskCache)1330 TEST_F(HttpCacheTest, SimpleGETNoDiskCache) {
1331 MockHttpCache cache;
1332
1333 cache.disk_cache()->set_fail_requests(true);
1334
1335 RecordingNetLogObserver net_log_observer;
1336 LoadTimingInfo load_timing_info;
1337
1338 // Read from the network, and don't use the cache.
1339 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
1340 NetLogWithSource::Make(NetLogSourceType::NONE),
1341 &load_timing_info);
1342
1343 // Check that the NetLog was filled as expected.
1344 // (We attempted to OpenOrCreate entries, but fail).
1345 auto entries = GetFilteredNetLogEntries(net_log_observer);
1346
1347 EXPECT_EQ(4u, entries.size());
1348 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1349 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1350 EXPECT_TRUE(
1351 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1352 EXPECT_TRUE(LogContainsBeginEvent(
1353 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1354 EXPECT_TRUE(LogContainsEndEvent(
1355 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1356
1357 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1358 EXPECT_EQ(0, cache.disk_cache()->open_count());
1359 EXPECT_EQ(0, cache.disk_cache()->create_count());
1360 TestLoadTimingNetworkRequest(load_timing_info);
1361 }
1362
TEST_F(HttpCacheTest,SimpleGETNoDiskCache2)1363 TEST_F(HttpCacheTest, SimpleGETNoDiskCache2) {
1364 // This will initialize a cache object with NULL backend.
1365 auto factory = std::make_unique<MockBlockingBackendFactory>();
1366 factory->set_fail(true);
1367 factory->FinishCreation(); // We'll complete synchronously.
1368 MockHttpCache cache(std::move(factory));
1369
1370 // Read from the network, and don't use the cache.
1371 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1372
1373 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1374 EXPECT_FALSE(cache.http_cache()->GetCurrentBackend());
1375 }
1376
1377 // Tests that IOBuffers are not referenced after IO completes.
TEST_F(HttpCacheTest,ReleaseBuffer)1378 TEST_F(HttpCacheTest, ReleaseBuffer) {
1379 MockHttpCache cache;
1380
1381 // Write to the cache.
1382 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1383
1384 MockHttpRequest request(kSimpleGET_Transaction);
1385 std::unique_ptr<HttpTransaction> trans;
1386 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
1387
1388 const int kBufferSize = 10;
1389 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
1390 ReleaseBufferCompletionCallback cb(buffer.get());
1391
1392 int rv = trans->Start(&request, cb.callback(), NetLogWithSource());
1393 EXPECT_THAT(cb.GetResult(rv), IsOk());
1394
1395 rv = trans->Read(buffer.get(), kBufferSize, cb.callback());
1396 EXPECT_EQ(kBufferSize, cb.GetResult(rv));
1397 }
1398
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures)1399 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures) {
1400 MockHttpCache cache;
1401
1402 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1403
1404 // Read from the network, and fail to write to the cache.
1405 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1406
1407 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1408 EXPECT_EQ(0, cache.disk_cache()->open_count());
1409 EXPECT_EQ(1, cache.disk_cache()->create_count());
1410
1411 // This one should see an empty cache again.
1412 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1413
1414 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1415 EXPECT_EQ(0, cache.disk_cache()->open_count());
1416 EXPECT_EQ(2, cache.disk_cache()->create_count());
1417 }
1418
1419 // Tests that disk failures after the transaction has started don't cause the
1420 // request to fail.
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures2)1421 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures2) {
1422 MockHttpCache cache;
1423
1424 MockHttpRequest request(kSimpleGET_Transaction);
1425
1426 auto c = std::make_unique<Context>();
1427 int rv = cache.CreateTransaction(&c->trans);
1428 ASSERT_THAT(rv, IsOk());
1429
1430 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
1431 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1432 rv = c->callback.WaitForResult();
1433
1434 // Start failing request now.
1435 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1436
1437 // We have to open the entry again to propagate the failure flag.
1438 disk_cache::Entry* en;
1439 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &en));
1440 en->Close();
1441
1442 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1443 c.reset();
1444
1445 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1446 EXPECT_EQ(1, cache.disk_cache()->open_count());
1447 EXPECT_EQ(1, cache.disk_cache()->create_count());
1448
1449 // This one should see an empty cache again.
1450 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1451
1452 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1453 EXPECT_EQ(1, cache.disk_cache()->open_count());
1454 EXPECT_EQ(2, cache.disk_cache()->create_count());
1455 }
1456
1457 // Tests that we handle failures to read from the cache.
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures3)1458 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures3) {
1459 MockHttpCache cache;
1460
1461 // Read from the network, and write to the cache.
1462 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1463
1464 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1465 EXPECT_EQ(0, cache.disk_cache()->open_count());
1466 EXPECT_EQ(1, cache.disk_cache()->create_count());
1467
1468 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1469
1470 MockHttpRequest request(kSimpleGET_Transaction);
1471
1472 // Now fail to read from the cache.
1473 auto c = std::make_unique<Context>();
1474 int rv = cache.CreateTransaction(&c->trans);
1475 ASSERT_THAT(rv, IsOk());
1476
1477 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
1478 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
1479
1480 // Now verify that the entry was removed from the cache.
1481 cache.disk_cache()->set_soft_failures_mask(0);
1482
1483 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1484 EXPECT_EQ(1, cache.disk_cache()->open_count());
1485 EXPECT_EQ(2, cache.disk_cache()->create_count());
1486
1487 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1488
1489 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1490 EXPECT_EQ(1, cache.disk_cache()->open_count());
1491 EXPECT_EQ(3, cache.disk_cache()->create_count());
1492 }
1493
TEST_F(HttpCacheTest,SimpleGET_LoadOnlyFromCache_Hit)1494 TEST_F(HttpCacheTest, SimpleGET_LoadOnlyFromCache_Hit) {
1495 MockHttpCache cache;
1496
1497 RecordingNetLogObserver net_log_observer;
1498 NetLogWithSource net_log_with_source =
1499 NetLogWithSource::Make(NetLogSourceType::NONE);
1500 LoadTimingInfo load_timing_info;
1501
1502 // Write to the cache.
1503 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
1504 net_log_with_source, &load_timing_info);
1505
1506 // Check that the NetLog was filled as expected.
1507 auto entries = GetFilteredNetLogEntries(net_log_observer);
1508
1509 EXPECT_EQ(6u, entries.size());
1510 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1511 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1512 EXPECT_TRUE(
1513 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1514 EXPECT_TRUE(LogContainsBeginEvent(
1515 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1516 EXPECT_TRUE(LogContainsEndEvent(
1517 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1518 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1519 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1520 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1521 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1522
1523 TestLoadTimingNetworkRequest(load_timing_info);
1524
1525 // Force this transaction to read from the cache.
1526 MockTransaction transaction(kSimpleGET_Transaction);
1527 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
1528
1529 net_log_observer.Clear();
1530
1531 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1532 net_log_with_source, &load_timing_info);
1533
1534 // Check that the NetLog was filled as expected.
1535 entries = GetFilteredNetLogEntries(net_log_observer);
1536
1537 EXPECT_EQ(8u, entries.size());
1538 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1539 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1540 EXPECT_TRUE(
1541 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1542 EXPECT_TRUE(LogContainsBeginEvent(
1543 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1544 EXPECT_TRUE(LogContainsEndEvent(
1545 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1546 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1547 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1548 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1549 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1550 EXPECT_TRUE(
1551 LogContainsBeginEvent(entries, 6, NetLogEventType::HTTP_CACHE_READ_INFO));
1552 EXPECT_TRUE(
1553 LogContainsEndEvent(entries, 7, NetLogEventType::HTTP_CACHE_READ_INFO));
1554
1555 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1556 EXPECT_EQ(1, cache.disk_cache()->open_count());
1557 EXPECT_EQ(1, cache.disk_cache()->create_count());
1558 TestLoadTimingCachedResponse(load_timing_info);
1559 }
1560
TEST_F(HttpCacheTest,SimpleGET_LoadOnlyFromCache_Miss)1561 TEST_F(HttpCacheTest, SimpleGET_LoadOnlyFromCache_Miss) {
1562 MockHttpCache cache;
1563
1564 // force this transaction to read from the cache
1565 MockTransaction transaction(kSimpleGET_Transaction);
1566 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
1567
1568 MockHttpRequest request(transaction);
1569 TestCompletionCallback callback;
1570
1571 std::unique_ptr<HttpTransaction> trans;
1572 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
1573
1574 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1575 if (rv == ERR_IO_PENDING)
1576 rv = callback.WaitForResult();
1577 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
1578
1579 trans.reset();
1580
1581 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1582 EXPECT_EQ(0, cache.disk_cache()->open_count());
1583 EXPECT_EQ(0, cache.disk_cache()->create_count());
1584 }
1585
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_Hit)1586 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_Hit) {
1587 MockHttpCache cache;
1588
1589 // write to the cache
1590 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1591
1592 // force this transaction to read from the cache if valid
1593 MockTransaction transaction(kSimpleGET_Transaction);
1594 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1595
1596 RunTransactionTest(cache.http_cache(), transaction);
1597
1598 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1599 EXPECT_EQ(1, cache.disk_cache()->open_count());
1600 EXPECT_EQ(1, cache.disk_cache()->create_count());
1601 }
1602
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_Miss)1603 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_Miss) {
1604 MockHttpCache cache;
1605
1606 // force this transaction to read from the cache if valid
1607 MockTransaction transaction(kSimpleGET_Transaction);
1608 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1609
1610 RunTransactionTest(cache.http_cache(), transaction);
1611
1612 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1613 EXPECT_EQ(0, cache.disk_cache()->open_count());
1614 EXPECT_EQ(1, cache.disk_cache()->create_count());
1615 }
1616
1617 // Tests LOAD_SKIP_CACHE_VALIDATION in the presence of vary headers.
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_VaryMatch)1618 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_VaryMatch) {
1619 MockHttpCache cache;
1620
1621 // Write to the cache.
1622 MockTransaction transaction(kSimpleGET_Transaction);
1623 transaction.request_headers = "Foo: bar\r\n";
1624 transaction.response_headers = "Cache-Control: max-age=10000\n"
1625 "Vary: Foo\n";
1626 AddMockTransaction(&transaction);
1627 RunTransactionTest(cache.http_cache(), transaction);
1628
1629 // Read from the cache.
1630 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1631 RunTransactionTest(cache.http_cache(), transaction);
1632
1633 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1634 EXPECT_EQ(1, cache.disk_cache()->open_count());
1635 EXPECT_EQ(1, cache.disk_cache()->create_count());
1636 RemoveMockTransaction(&transaction);
1637 }
1638
1639 // Tests LOAD_SKIP_CACHE_VALIDATION in the presence of vary headers.
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_VaryMismatch)1640 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_VaryMismatch) {
1641 MockHttpCache cache;
1642
1643 // Write to the cache.
1644 MockTransaction transaction(kSimpleGET_Transaction);
1645 transaction.request_headers = "Foo: bar\r\n";
1646 transaction.response_headers = "Cache-Control: max-age=10000\n"
1647 "Vary: Foo\n";
1648 AddMockTransaction(&transaction);
1649 RunTransactionTest(cache.http_cache(), transaction);
1650
1651 // Attempt to read from the cache... this is a vary mismatch that must reach
1652 // the network again.
1653 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1654 transaction.request_headers = "Foo: none\r\n";
1655 LoadTimingInfo load_timing_info;
1656 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1657 NetLogWithSource::Make(NetLogSourceType::NONE),
1658 &load_timing_info);
1659
1660 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1661 EXPECT_EQ(1, cache.disk_cache()->open_count());
1662 EXPECT_EQ(1, cache.disk_cache()->create_count());
1663 TestLoadTimingNetworkRequest(load_timing_info);
1664 RemoveMockTransaction(&transaction);
1665 }
1666
1667 // Tests that we honor Vary: * with LOAD_SKIP_CACHE_VALIDATION (crbug/778681)
TEST_F(HttpCacheTest,SimpleGET_LoadSkipCacheValidation_VaryStar)1668 TEST_F(HttpCacheTest, SimpleGET_LoadSkipCacheValidation_VaryStar) {
1669 MockHttpCache cache;
1670
1671 // Write to the cache.
1672 MockTransaction transaction(kSimpleGET_Transaction);
1673 transaction.response_headers =
1674 "Cache-Control: max-age=10000\n"
1675 "Vary: *\n";
1676 AddMockTransaction(&transaction);
1677 RunTransactionTest(cache.http_cache(), transaction);
1678
1679 // Attempt to read from the cache... we will still load it from network,
1680 // since Vary: * doesn't match.
1681 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1682 LoadTimingInfo load_timing_info;
1683 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1684 NetLogWithSource::Make(NetLogSourceType::NONE),
1685 &load_timing_info);
1686
1687 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1688 EXPECT_EQ(1, cache.disk_cache()->open_count());
1689 EXPECT_EQ(1, cache.disk_cache()->create_count());
1690 RemoveMockTransaction(&transaction);
1691 }
1692
1693 // Tests that was_cached was set properly on a failure, even if the cached
1694 // response wasn't returned.
TEST_F(HttpCacheTest,SimpleGET_CacheSignal_Failure)1695 TEST_F(HttpCacheTest, SimpleGET_CacheSignal_Failure) {
1696 for (bool use_memory_entry_data : {false, true}) {
1697 MockHttpCache cache;
1698 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
1699
1700 // Prime cache.
1701 MockTransaction transaction(kSimpleGET_Transaction);
1702 transaction.response_headers = "Cache-Control: no-cache\n";
1703
1704 AddMockTransaction(&transaction);
1705 RunTransactionTest(cache.http_cache(), transaction);
1706 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1707 EXPECT_EQ(1, cache.disk_cache()->create_count());
1708 EXPECT_EQ(0, cache.disk_cache()->open_count());
1709 RemoveMockTransaction(&transaction);
1710
1711 // Network failure with error; should fail but have was_cached set.
1712 transaction.start_return_code = ERR_FAILED;
1713 AddMockTransaction(&transaction);
1714
1715 MockHttpRequest request(transaction);
1716 TestCompletionCallback callback;
1717 std::unique_ptr<HttpTransaction> trans;
1718 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
1719 EXPECT_THAT(rv, IsOk());
1720 ASSERT_TRUE(trans.get());
1721 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1722 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
1723
1724 const HttpResponseInfo* response_info = trans->GetResponseInfo();
1725 ASSERT_TRUE(response_info);
1726 // If use_memory_entry_data is true, we will not bother opening the entry,
1727 // and just kick it out, so was_cached will end up false.
1728 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1729 if (use_memory_entry_data) {
1730 EXPECT_EQ(false, response_info->was_cached);
1731 EXPECT_EQ(2, cache.disk_cache()->create_count());
1732 EXPECT_EQ(0, cache.disk_cache()->open_count());
1733 } else {
1734 EXPECT_EQ(true, response_info->was_cached);
1735 EXPECT_EQ(1, cache.disk_cache()->create_count());
1736 EXPECT_EQ(1, cache.disk_cache()->open_count());
1737 }
1738
1739 RemoveMockTransaction(&transaction);
1740 }
1741 }
1742
1743 // Tests that if the transaction is destroyed right after setting the
1744 // cache_entry_status_ as CANT_CONDITIONALIZE, then RecordHistograms should not
1745 // hit a dcheck.
TEST_F(HttpCacheTest,RecordHistogramsCantConditionalize)1746 TEST_F(HttpCacheTest, RecordHistogramsCantConditionalize) {
1747 MockHttpCache cache;
1748 cache.disk_cache()->set_support_in_memory_entry_data(true);
1749
1750 {
1751 // Prime cache.
1752 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1753 transaction.response_headers = "Cache-Control: no-cache\n";
1754 RunTransactionTest(cache.http_cache(), transaction);
1755 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1756 EXPECT_EQ(1, cache.disk_cache()->create_count());
1757 EXPECT_EQ(0, cache.disk_cache()->open_count());
1758 }
1759
1760 {
1761 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1762 MockHttpRequest request(transaction);
1763 TestCompletionCallback callback;
1764 std::unique_ptr<HttpTransaction> trans;
1765 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
1766 EXPECT_THAT(rv, IsOk());
1767 ASSERT_TRUE(trans.get());
1768 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1769 // Now destroy the transaction so that RecordHistograms gets invoked.
1770 trans.reset();
1771 }
1772 }
1773
1774 // Confirm if we have an empty cache, a read is marked as network verified.
TEST_F(HttpCacheTest,SimpleGET_NetworkAccessed_Network)1775 TEST_F(HttpCacheTest, SimpleGET_NetworkAccessed_Network) {
1776 MockHttpCache cache;
1777
1778 // write to the cache
1779 HttpResponseInfo response_info;
1780 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
1781 &response_info);
1782
1783 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1784 EXPECT_EQ(0, cache.disk_cache()->open_count());
1785 EXPECT_EQ(1, cache.disk_cache()->create_count());
1786 EXPECT_TRUE(response_info.network_accessed);
1787 EXPECT_EQ(CacheEntryStatus::ENTRY_NOT_IN_CACHE,
1788 response_info.cache_entry_status);
1789 }
1790
1791 // Confirm if we have a fresh entry in cache, it isn't marked as
1792 // network verified.
TEST_F(HttpCacheTest,SimpleGET_NetworkAccessed_Cache)1793 TEST_F(HttpCacheTest, SimpleGET_NetworkAccessed_Cache) {
1794 MockHttpCache cache;
1795
1796 // Prime cache.
1797 MockTransaction transaction(kSimpleGET_Transaction);
1798
1799 RunTransactionTest(cache.http_cache(), transaction);
1800 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1801 EXPECT_EQ(1, cache.disk_cache()->create_count());
1802
1803 // Re-run transaction; make sure we don't mark the network as accessed.
1804 HttpResponseInfo response_info;
1805 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
1806 &response_info);
1807
1808 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1809 EXPECT_FALSE(response_info.network_accessed);
1810 EXPECT_EQ(CacheEntryStatus::ENTRY_USED, response_info.cache_entry_status);
1811 }
1812
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache)1813 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache) {
1814 MockHttpCache cache;
1815
1816 // Write to the cache.
1817 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1818
1819 // Force this transaction to write to the cache again.
1820 MockTransaction transaction(kSimpleGET_Transaction);
1821 transaction.load_flags |= LOAD_BYPASS_CACHE;
1822
1823 RecordingNetLogObserver net_log_observer;
1824 LoadTimingInfo load_timing_info;
1825
1826 // Write to the cache.
1827 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1828 NetLogWithSource::Make(NetLogSourceType::NONE),
1829 &load_timing_info);
1830
1831 // Check that the NetLog was filled as expected.
1832 auto entries = GetFilteredNetLogEntries(net_log_observer);
1833
1834 EXPECT_EQ(8u, entries.size());
1835 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1836 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1837 EXPECT_TRUE(
1838 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1839 EXPECT_TRUE(LogContainsBeginEvent(entries, 2,
1840 NetLogEventType::HTTP_CACHE_DOOM_ENTRY));
1841 EXPECT_TRUE(
1842 LogContainsEndEvent(entries, 3, NetLogEventType::HTTP_CACHE_DOOM_ENTRY));
1843 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1844 NetLogEventType::HTTP_CACHE_CREATE_ENTRY));
1845 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1846 NetLogEventType::HTTP_CACHE_CREATE_ENTRY));
1847 EXPECT_TRUE(LogContainsBeginEvent(entries, 6,
1848 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1849 EXPECT_TRUE(LogContainsEndEvent(entries, 7,
1850 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1851
1852 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1853 EXPECT_EQ(0, cache.disk_cache()->open_count());
1854 EXPECT_EQ(2, cache.disk_cache()->create_count());
1855 TestLoadTimingNetworkRequest(load_timing_info);
1856 }
1857
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache_Implicit)1858 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache_Implicit) {
1859 MockHttpCache cache;
1860
1861 // write to the cache
1862 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1863
1864 // force this transaction to write to the cache again
1865 MockTransaction transaction(kSimpleGET_Transaction);
1866 transaction.request_headers = "pragma: no-cache\r\n";
1867
1868 RunTransactionTest(cache.http_cache(), transaction);
1869
1870 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1871 EXPECT_EQ(0, cache.disk_cache()->open_count());
1872 EXPECT_EQ(2, cache.disk_cache()->create_count());
1873 }
1874
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache_Implicit2)1875 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache_Implicit2) {
1876 MockHttpCache cache;
1877
1878 // write to the cache
1879 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1880
1881 // force this transaction to write to the cache again
1882 MockTransaction transaction(kSimpleGET_Transaction);
1883 transaction.request_headers = "cache-control: no-cache\r\n";
1884
1885 RunTransactionTest(cache.http_cache(), transaction);
1886
1887 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1888 EXPECT_EQ(0, cache.disk_cache()->open_count());
1889 EXPECT_EQ(2, cache.disk_cache()->create_count());
1890 }
1891
TEST_F(HttpCacheTest,SimpleGET_LoadValidateCache)1892 TEST_F(HttpCacheTest, SimpleGET_LoadValidateCache) {
1893 MockHttpCache cache;
1894
1895 // Write to the cache.
1896 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1897
1898 // Read from the cache.
1899 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1900
1901 // Force this transaction to validate the cache.
1902 MockTransaction transaction(kSimpleGET_Transaction);
1903 transaction.load_flags |= LOAD_VALIDATE_CACHE;
1904
1905 HttpResponseInfo response_info;
1906 LoadTimingInfo load_timing_info;
1907 RunTransactionTestWithResponseInfoAndGetTiming(
1908 cache.http_cache(), transaction, &response_info,
1909 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
1910
1911 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1912 EXPECT_EQ(1, cache.disk_cache()->open_count());
1913 EXPECT_EQ(1, cache.disk_cache()->create_count());
1914 EXPECT_TRUE(response_info.network_accessed);
1915 TestLoadTimingNetworkRequest(load_timing_info);
1916 }
1917
TEST_F(HttpCacheTest,SimpleGET_LoadValidateCache_Implicit)1918 TEST_F(HttpCacheTest, SimpleGET_LoadValidateCache_Implicit) {
1919 MockHttpCache cache;
1920
1921 // write to the cache
1922 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1923
1924 // read from the cache
1925 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1926
1927 // force this transaction to validate the cache
1928 MockTransaction transaction(kSimpleGET_Transaction);
1929 transaction.request_headers = "cache-control: max-age=0\r\n";
1930
1931 RunTransactionTest(cache.http_cache(), transaction);
1932
1933 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1934 EXPECT_EQ(1, cache.disk_cache()->open_count());
1935 EXPECT_EQ(1, cache.disk_cache()->create_count());
1936 }
1937
1938 // Tests that |unused_since_prefetch| is updated accordingly (e.g. it is set to
1939 // true after a prefetch and set back to false when the prefetch is used).
TEST_F(HttpCacheTest,SimpleGET_UnusedSincePrefetch)1940 TEST_F(HttpCacheTest, SimpleGET_UnusedSincePrefetch) {
1941 MockHttpCache cache;
1942 HttpResponseInfo response_info;
1943
1944 // A normal load does not have |unused_since_prefetch| set.
1945 RunTransactionTestWithResponseInfoAndGetTiming(
1946 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1947 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1948 EXPECT_FALSE(response_info.unused_since_prefetch);
1949 EXPECT_FALSE(response_info.was_cached);
1950
1951 // The prefetch itself does not have |unused_since_prefetch| set.
1952 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
1953 prefetch_transaction.load_flags |= LOAD_PREFETCH;
1954 RunTransactionTestWithResponseInfoAndGetTiming(
1955 cache.http_cache(), prefetch_transaction, &response_info,
1956 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1957 EXPECT_FALSE(response_info.unused_since_prefetch);
1958 EXPECT_TRUE(response_info.was_cached);
1959
1960 // A duplicated prefetch has |unused_since_prefetch| set.
1961 RunTransactionTestWithResponseInfoAndGetTiming(
1962 cache.http_cache(), prefetch_transaction, &response_info,
1963 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1964 EXPECT_TRUE(response_info.unused_since_prefetch);
1965 EXPECT_TRUE(response_info.was_cached);
1966
1967 // |unused_since_prefetch| is still true after two prefetches in a row.
1968 RunTransactionTestWithResponseInfoAndGetTiming(
1969 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1970 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1971 EXPECT_TRUE(response_info.unused_since_prefetch);
1972 EXPECT_TRUE(response_info.was_cached);
1973
1974 // The resource has now been used, back to normal behavior.
1975 RunTransactionTestWithResponseInfoAndGetTiming(
1976 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1977 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1978 EXPECT_FALSE(response_info.unused_since_prefetch);
1979 EXPECT_TRUE(response_info.was_cached);
1980 }
1981
1982 // Tests that requests made with the LOAD_RESTRICTED_PREFETCH load flag result
1983 // in HttpResponseInfo entries with the |restricted_prefetch| flag set. Also
1984 // tests that responses with |restricted_prefetch| flag set can only be used by
1985 // requests that have the LOAD_CAN_USE_RESTRICTED_PREFETCH load flag.
TEST_F(HttpCacheTest,SimpleGET_RestrictedPrefetchIsRestrictedUntilReuse)1986 TEST_F(HttpCacheTest, SimpleGET_RestrictedPrefetchIsRestrictedUntilReuse) {
1987 MockHttpCache cache;
1988 HttpResponseInfo response_info;
1989
1990 // A normal load does not have |restricted_prefetch| set.
1991 RunTransactionTestWithResponseInfoAndGetTiming(
1992 cache.http_cache(), kTypicalGET_Transaction, &response_info,
1993 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1994 EXPECT_FALSE(response_info.restricted_prefetch);
1995 EXPECT_FALSE(response_info.was_cached);
1996 EXPECT_TRUE(response_info.network_accessed);
1997
1998 // A restricted prefetch is marked as |restricted_prefetch|.
1999 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
2000 prefetch_transaction.load_flags |= LOAD_PREFETCH;
2001 prefetch_transaction.load_flags |= LOAD_RESTRICTED_PREFETCH;
2002 RunTransactionTestWithResponseInfoAndGetTiming(
2003 cache.http_cache(), prefetch_transaction, &response_info,
2004 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2005 EXPECT_TRUE(response_info.restricted_prefetch);
2006 EXPECT_FALSE(response_info.was_cached);
2007 EXPECT_TRUE(response_info.network_accessed);
2008
2009 // Requests that are marked as able to reuse restricted prefetches can do so
2010 // correctly. Once it is reused, it is no longer considered as or marked
2011 // restricted.
2012 MockTransaction can_use_restricted_prefetch_transaction(
2013 kSimpleGET_Transaction);
2014 can_use_restricted_prefetch_transaction.load_flags |=
2015 LOAD_CAN_USE_RESTRICTED_PREFETCH;
2016 RunTransactionTestWithResponseInfoAndGetTiming(
2017 cache.http_cache(), can_use_restricted_prefetch_transaction,
2018 &response_info, NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2019 EXPECT_TRUE(response_info.restricted_prefetch);
2020 EXPECT_TRUE(response_info.was_cached);
2021 EXPECT_FALSE(response_info.network_accessed);
2022
2023 // Later reuse is still no longer marked restricted.
2024 RunTransactionTestWithResponseInfoAndGetTiming(
2025 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2026 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2027 EXPECT_FALSE(response_info.restricted_prefetch);
2028 EXPECT_TRUE(response_info.was_cached);
2029 EXPECT_FALSE(response_info.network_accessed);
2030 }
2031
TEST_F(HttpCacheTest,SimpleGET_RestrictedPrefetchReuseIsLimited)2032 TEST_F(HttpCacheTest, SimpleGET_RestrictedPrefetchReuseIsLimited) {
2033 MockHttpCache cache;
2034 HttpResponseInfo response_info;
2035
2036 // A restricted prefetch is marked as |restricted_prefetch|.
2037 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
2038 prefetch_transaction.load_flags |= LOAD_PREFETCH;
2039 prefetch_transaction.load_flags |= LOAD_RESTRICTED_PREFETCH;
2040 RunTransactionTestWithResponseInfoAndGetTiming(
2041 cache.http_cache(), prefetch_transaction, &response_info,
2042 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2043 EXPECT_TRUE(response_info.restricted_prefetch);
2044 EXPECT_FALSE(response_info.was_cached);
2045 EXPECT_TRUE(response_info.network_accessed);
2046
2047 // Requests that cannot reuse restricted prefetches fail to do so. The network
2048 // is accessed and the resulting response is not marked as
2049 // |restricted_prefetch|.
2050 RunTransactionTestWithResponseInfoAndGetTiming(
2051 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2052 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2053 EXPECT_FALSE(response_info.restricted_prefetch);
2054 EXPECT_FALSE(response_info.was_cached);
2055 EXPECT_TRUE(response_info.network_accessed);
2056
2057 // Future requests that are not marked as able to reuse restricted prefetches
2058 // can use the entry in the cache now, since it has been evicted in favor of
2059 // an unrestricted one.
2060 RunTransactionTestWithResponseInfoAndGetTiming(
2061 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2062 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2063 EXPECT_FALSE(response_info.restricted_prefetch);
2064 EXPECT_TRUE(response_info.was_cached);
2065 EXPECT_FALSE(response_info.network_accessed);
2066 }
2067
TEST_F(HttpCacheTest,SimpleGET_UnusedSincePrefetchWriteError)2068 TEST_F(HttpCacheTest, SimpleGET_UnusedSincePrefetchWriteError) {
2069 MockHttpCache cache;
2070 HttpResponseInfo response_info;
2071
2072 // Do a prefetch.
2073 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
2074 prefetch_transaction.load_flags |= LOAD_PREFETCH;
2075 RunTransactionTestWithResponseInfoAndGetTiming(
2076 cache.http_cache(), prefetch_transaction, &response_info,
2077 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2078 EXPECT_TRUE(response_info.unused_since_prefetch);
2079 EXPECT_FALSE(response_info.was_cached);
2080
2081 // Try to use it while injecting a failure on write.
2082 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_WRITE);
2083 RunTransactionTestWithResponseInfoAndGetTiming(
2084 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2085 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2086 }
2087
2088 // Make sure that if a prefetch entry is truncated, then an attempt to re-use it
2089 // gets aborted in connected handler that truncated bit is not lost.
TEST_F(HttpCacheTest,PrefetchTruncateCancelInConnectedCallback)2090 TEST_F(HttpCacheTest, PrefetchTruncateCancelInConnectedCallback) {
2091 MockHttpCache cache;
2092
2093 ScopedMockTransaction transaction(kSimpleGET_Transaction);
2094 transaction.response_headers =
2095 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2096 "Content-Length: 20\n"
2097 "Etag: \"foopy\"\n";
2098 transaction.data = "01234567890123456789";
2099 transaction.load_flags |= LOAD_PREFETCH | LOAD_CAN_USE_RESTRICTED_PREFETCH;
2100
2101 // Do a truncated read of a prefetch request.
2102 {
2103 MockHttpRequest request(transaction);
2104 Context c;
2105
2106 int rv = cache.CreateTransaction(&c.trans);
2107 ASSERT_THAT(rv, IsOk());
2108
2109 rv = c.callback.GetResult(
2110 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2111 ASSERT_THAT(rv, IsOk());
2112
2113 // Read less than the whole thing.
2114 scoped_refptr<IOBufferWithSize> buf =
2115 base::MakeRefCounted<IOBufferWithSize>(10);
2116 rv = c.callback.GetResult(
2117 c.trans->Read(buf.get(), buf->size(), c.callback.callback()));
2118 EXPECT_EQ(buf->size(), rv);
2119
2120 // Destroy the transaction.
2121 c.trans.reset();
2122 base::RunLoop().RunUntilIdle();
2123
2124 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2125 /*data_size=*/10);
2126 }
2127
2128 // Do a fetch that can use prefetch that aborts in connected handler.
2129 transaction.load_flags &= ~LOAD_PREFETCH;
2130 {
2131 MockHttpRequest request(transaction);
2132 Context c;
2133
2134 int rv = cache.CreateTransaction(&c.trans);
2135 ASSERT_THAT(rv, IsOk());
2136 c.trans->SetConnectedCallback(base::BindRepeating(
2137 [](const TransportInfo& info, CompletionOnceCallback callback) -> int {
2138 return net::ERR_ABORTED;
2139 }));
2140 rv = c.callback.GetResult(
2141 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2142 EXPECT_EQ(net::ERR_ABORTED, rv);
2143
2144 // Destroy the transaction.
2145 c.trans.reset();
2146 base::RunLoop().RunUntilIdle();
2147
2148 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2149 /*data_size=*/10);
2150 }
2151
2152 // Now try again without abort.
2153 {
2154 MockHttpRequest request(transaction);
2155 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
2156 /*response_info=*/nullptr);
2157 base::RunLoop().RunUntilIdle();
2158
2159 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/false,
2160 /*data_size=*/20);
2161 }
2162 }
2163
2164 // Make sure that if a stale-while-revalidate entry is truncated, then an
2165 // attempt to re-use it gets aborted in connected handler that truncated bit is
2166 // not lost.
TEST_F(HttpCacheTest,StaleWhiteRevalidateTruncateCancelInConnectedCallback)2167 TEST_F(HttpCacheTest, StaleWhiteRevalidateTruncateCancelInConnectedCallback) {
2168 MockHttpCache cache;
2169
2170 ScopedMockTransaction transaction(kSimpleGET_Transaction);
2171 transaction.response_headers =
2172 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2173 "Content-Length: 20\n"
2174 "Cache-Control: max-age=0, stale-while-revalidate=60\n"
2175 "Etag: \"foopy\"\n";
2176 transaction.data = "01234567890123456789";
2177 transaction.load_flags |= LOAD_SUPPORT_ASYNC_REVALIDATION;
2178
2179 // Do a truncated read of a stale-while-revalidate resource.
2180 {
2181 MockHttpRequest request(transaction);
2182 Context c;
2183
2184 int rv = cache.CreateTransaction(&c.trans);
2185 ASSERT_THAT(rv, IsOk());
2186
2187 rv = c.callback.GetResult(
2188 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2189 ASSERT_THAT(rv, IsOk());
2190
2191 // Read less than the whole thing.
2192 scoped_refptr<IOBufferWithSize> buf =
2193 base::MakeRefCounted<IOBufferWithSize>(10);
2194 rv = c.callback.GetResult(
2195 c.trans->Read(buf.get(), buf->size(), c.callback.callback()));
2196 EXPECT_EQ(buf->size(), rv);
2197
2198 // Destroy the transaction.
2199 c.trans.reset();
2200 base::RunLoop().RunUntilIdle();
2201
2202 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2203 /*data_size=*/10);
2204 }
2205
2206 // Do a fetch that uses that resource that aborts in connected handler.
2207 {
2208 MockHttpRequest request(transaction);
2209 Context c;
2210
2211 int rv = cache.CreateTransaction(&c.trans);
2212 ASSERT_THAT(rv, IsOk());
2213 c.trans->SetConnectedCallback(base::BindRepeating(
2214 [](const TransportInfo& info, CompletionOnceCallback callback) -> int {
2215 return net::ERR_ABORTED;
2216 }));
2217 rv = c.callback.GetResult(
2218 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2219 EXPECT_EQ(net::ERR_ABORTED, rv);
2220
2221 // Destroy the transaction.
2222 c.trans.reset();
2223 base::RunLoop().RunUntilIdle();
2224
2225 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2226 /*data_size=*/10);
2227 }
2228
2229 // Now try again without abort.
2230 {
2231 MockHttpRequest request(transaction);
2232 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
2233 /*response_info=*/nullptr);
2234 base::RunLoop().RunUntilIdle();
2235
2236 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/false,
2237 /*data_size=*/20);
2238 }
2239 }
2240
2241 static const auto kPreserveRequestHeaders =
2242 base::BindRepeating([](const net::HttpRequestInfo* request,
2243 std::string* response_status,
2244 std::string* response_headers,
__anond56f448a0602(const net::HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) 2245 std::string* response_data) {
2246 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
2247 });
2248
2249 // Tests that we don't remove extra headers for simple requests.
TEST_F(HttpCacheTest,SimpleGET_PreserveRequestHeaders)2250 TEST_F(HttpCacheTest, SimpleGET_PreserveRequestHeaders) {
2251 for (bool use_memory_entry_data : {false, true}) {
2252 MockHttpCache cache;
2253 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
2254
2255 MockTransaction transaction(kSimpleGET_Transaction);
2256 transaction.handler = kPreserveRequestHeaders;
2257 transaction.request_headers = EXTRA_HEADER;
2258 transaction.response_headers = "Cache-Control: max-age=0\n";
2259 AddMockTransaction(&transaction);
2260
2261 // Write, then revalidate the entry.
2262 RunTransactionTest(cache.http_cache(), transaction);
2263 RunTransactionTest(cache.http_cache(), transaction);
2264
2265 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2266
2267 // If the backend supports memory entry data, we can figure out that the
2268 // entry has caching-hostile headers w/o opening it.
2269 if (use_memory_entry_data) {
2270 EXPECT_EQ(0, cache.disk_cache()->open_count());
2271 EXPECT_EQ(2, cache.disk_cache()->create_count());
2272 } else {
2273 EXPECT_EQ(1, cache.disk_cache()->open_count());
2274 EXPECT_EQ(1, cache.disk_cache()->create_count());
2275 }
2276 RemoveMockTransaction(&transaction);
2277 }
2278 }
2279
2280 // Tests that we don't remove extra headers for conditionalized requests.
TEST_F(HttpCacheTest,ConditionalizedGET_PreserveRequestHeaders)2281 TEST_F(HttpCacheTest, ConditionalizedGET_PreserveRequestHeaders) {
2282 for (bool use_memory_entry_data : {false, true}) {
2283 MockHttpCache cache;
2284 // Unlike in SimpleGET_PreserveRequestHeaders, this entry can be
2285 // conditionalized, so memory hints don't affect behavior.
2286 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
2287
2288 // Write to the cache.
2289 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
2290
2291 MockTransaction transaction(kETagGET_Transaction);
2292 transaction.handler = kPreserveRequestHeaders;
2293 transaction.request_headers = "If-None-Match: \"foopy\"\r\n" EXTRA_HEADER;
2294 AddMockTransaction(&transaction);
2295
2296 RunTransactionTest(cache.http_cache(), transaction);
2297
2298 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2299 EXPECT_EQ(1, cache.disk_cache()->open_count());
2300 EXPECT_EQ(1, cache.disk_cache()->create_count());
2301 RemoveMockTransaction(&transaction);
2302 }
2303 }
2304
TEST_F(HttpCacheTest,SimpleGET_ManyReaders)2305 TEST_F(HttpCacheTest, SimpleGET_ManyReaders) {
2306 MockHttpCache cache;
2307
2308 MockHttpRequest request(kSimpleGET_Transaction);
2309
2310 std::vector<std::unique_ptr<Context>> context_list;
2311 const int kNumTransactions = 5;
2312
2313 for (int i = 0; i < kNumTransactions; ++i) {
2314 context_list.push_back(std::make_unique<Context>());
2315 auto& c = context_list[i];
2316
2317 c->result = cache.CreateTransaction(&c->trans);
2318 ASSERT_THAT(c->result, IsOk());
2319 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2320
2321 c->result =
2322 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2323 }
2324
2325 // All requests are waiting for the active entry.
2326 for (auto& context : context_list) {
2327 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
2328 }
2329
2330 // Allow all requests to move from the Create queue to the active entry.
2331 base::RunLoop().RunUntilIdle();
2332
2333 // All requests are added to writers.
2334 std::string cache_key = request.CacheKey();
2335 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
2336
2337 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2338 EXPECT_EQ(0, cache.disk_cache()->open_count());
2339 EXPECT_EQ(1, cache.disk_cache()->create_count());
2340
2341 // All requests are between Start and Read, i.e. idle.
2342 for (auto& context : context_list) {
2343 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
2344 }
2345
2346 for (int i = 0; i < kNumTransactions; ++i) {
2347 auto& c = context_list[i];
2348 if (c->result == ERR_IO_PENDING)
2349 c->result = c->callback.WaitForResult();
2350
2351 // After the 1st transaction has completed the response, all transactions
2352 // get added to readers.
2353 if (i > 0) {
2354 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
2355 EXPECT_EQ(kNumTransactions - i, cache.GetCountReaders(cache_key));
2356 }
2357
2358 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
2359 }
2360
2361 // We should not have had to re-open the disk entry
2362 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2363 EXPECT_EQ(0, cache.disk_cache()->open_count());
2364 EXPECT_EQ(1, cache.disk_cache()->create_count());
2365 }
2366
TEST_F(HttpCacheTest,RangeGET_FullAfterPartial)2367 TEST_F(HttpCacheTest, RangeGET_FullAfterPartial) {
2368 MockHttpCache cache;
2369
2370 // Request a prefix.
2371 {
2372 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2373 transaction_pre.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
2374 transaction_pre.data = "rg: 00-09 ";
2375 MockHttpRequest request_pre(transaction_pre);
2376
2377 HttpResponseInfo response_pre;
2378 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2379 request_pre, &response_pre);
2380 ASSERT_TRUE(response_pre.headers != nullptr);
2381 EXPECT_EQ(206, response_pre.headers->response_code());
2382 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2383 EXPECT_EQ(0, cache.disk_cache()->open_count());
2384 EXPECT_EQ(1, cache.disk_cache()->create_count());
2385 }
2386
2387 {
2388 // Now request the full thing, but set validation to fail. This would
2389 // previously fail in the middle of data and truncate it; current behavior
2390 // restarts it, somewhat wastefully but gets the data back.
2391 RangeTransactionServer handler;
2392 handler.set_modified(true);
2393
2394 ScopedMockTransaction transaction_all(kRangeGET_TransactionOK);
2395 transaction_all.request_headers = EXTRA_HEADER;
2396 transaction_all.data = "Not a range";
2397 MockHttpRequest request_all(transaction_all);
2398
2399 HttpResponseInfo response_all;
2400 RunTransactionTestWithRequest(cache.http_cache(), transaction_all,
2401 request_all, &response_all);
2402 ASSERT_TRUE(response_all.headers != nullptr);
2403 EXPECT_EQ(200, response_all.headers->response_code());
2404 // 1 from previous test, failed validation, and re-try.
2405 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2406 EXPECT_EQ(1, cache.disk_cache()->open_count());
2407 EXPECT_EQ(1, cache.disk_cache()->create_count());
2408 }
2409 }
2410
2411 // Tests that when a range request transaction becomes a writer for the first
2412 // range and then fails conditionalization for the next range and decides to
2413 // doom the entry, then there should not be a dcheck assertion hit.
TEST_F(HttpCacheTest,RangeGET_OverlappingRangesCouldntConditionalize)2414 TEST_F(HttpCacheTest, RangeGET_OverlappingRangesCouldntConditionalize) {
2415 MockHttpCache cache;
2416
2417 {
2418 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2419 transaction_pre.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2420 transaction_pre.data = "rg: 10-19 ";
2421 MockHttpRequest request_pre(transaction_pre);
2422
2423 HttpResponseInfo response_pre;
2424 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2425 request_pre, &response_pre);
2426 ASSERT_TRUE(response_pre.headers != nullptr);
2427 EXPECT_EQ(206, response_pre.headers->response_code());
2428 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2429 EXPECT_EQ(0, cache.disk_cache()->open_count());
2430 EXPECT_EQ(1, cache.disk_cache()->create_count());
2431 }
2432
2433 {
2434 // First range skips validation because the response is fresh while the
2435 // second range requires validation since that range is not present in the
2436 // cache and during validation it fails conditionalization.
2437 cache.FailConditionalizations();
2438 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2439 transaction_pre.request_headers = "Range: bytes = 10-29\r\n" EXTRA_HEADER;
2440
2441 // TODO(crbug.com/992521): Fix this scenario to not return the cached bytes
2442 // repeatedly.
2443 transaction_pre.data = "rg: 10-19 rg: 10-19 rg: 20-29 ";
2444 MockHttpRequest request_pre(transaction_pre);
2445 HttpResponseInfo response_pre;
2446 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2447 request_pre, &response_pre);
2448 ASSERT_TRUE(response_pre.headers != nullptr);
2449 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2450 EXPECT_EQ(1, cache.disk_cache()->open_count());
2451 EXPECT_EQ(2, cache.disk_cache()->create_count());
2452 }
2453 }
2454
TEST_F(HttpCacheTest,RangeGET_FullAfterPartialReuse)2455 TEST_F(HttpCacheTest, RangeGET_FullAfterPartialReuse) {
2456 MockHttpCache cache;
2457
2458 // Request a prefix.
2459 {
2460 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2461 transaction_pre.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
2462 transaction_pre.data = "rg: 00-09 ";
2463 MockHttpRequest request_pre(transaction_pre);
2464
2465 HttpResponseInfo response_pre;
2466 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2467 request_pre, &response_pre);
2468 ASSERT_TRUE(response_pre.headers != nullptr);
2469 EXPECT_EQ(206, response_pre.headers->response_code());
2470 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2471 EXPECT_EQ(0, cache.disk_cache()->open_count());
2472 EXPECT_EQ(1, cache.disk_cache()->create_count());
2473 }
2474
2475 {
2476 // Now request the full thing, revalidating successfully, so the full
2477 // file gets stored via a sparse-entry.
2478 ScopedMockTransaction transaction_all(kRangeGET_TransactionOK);
2479 transaction_all.request_headers = EXTRA_HEADER;
2480 transaction_all.data =
2481 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49"
2482 " rg: 50-59 rg: 60-69 rg: 70-79 ";
2483 MockHttpRequest request_all(transaction_all);
2484
2485 HttpResponseInfo response_all;
2486 RunTransactionTestWithRequest(cache.http_cache(), transaction_all,
2487 request_all, &response_all);
2488 ASSERT_TRUE(response_all.headers != nullptr);
2489 EXPECT_EQ(200, response_all.headers->response_code());
2490 // 1 from previous test, validation, and second chunk
2491 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2492 EXPECT_EQ(1, cache.disk_cache()->open_count());
2493 EXPECT_EQ(1, cache.disk_cache()->create_count());
2494 }
2495
2496 {
2497 // Grab it again, should not need re-validation.
2498 ScopedMockTransaction transaction_all2(kRangeGET_TransactionOK);
2499 transaction_all2.request_headers = EXTRA_HEADER;
2500 transaction_all2.data =
2501 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49"
2502 " rg: 50-59 rg: 60-69 rg: 70-79 ";
2503 MockHttpRequest request_all2(transaction_all2);
2504
2505 HttpResponseInfo response_all2;
2506 RunTransactionTestWithRequest(cache.http_cache(), transaction_all2,
2507 request_all2, &response_all2);
2508 ASSERT_TRUE(response_all2.headers != nullptr);
2509 EXPECT_EQ(200, response_all2.headers->response_code());
2510
2511 // Only one more cache open, no new network traffic.
2512 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2513 EXPECT_EQ(2, cache.disk_cache()->open_count());
2514 EXPECT_EQ(1, cache.disk_cache()->create_count());
2515 }
2516 }
2517
2518 // This test verifies that the ConnectedCallback passed to a cache transaction
2519 // is called once per subrange in the case of a range request with a partial
2520 // cache hit.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackCalledForEachRange)2521 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackCalledForEachRange) {
2522 MockHttpCache cache;
2523
2524 // Request an infix range and populate the cache with it.
2525 {
2526 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2527 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2528 mock_transaction.data = "rg: 20-29 ";
2529 mock_transaction.transport_info = TestTransportInfo();
2530
2531 RunTransactionTest(cache.http_cache(), mock_transaction);
2532 }
2533
2534 // Request a surrounding range and observe that the callback is called once
2535 // per subrange, as split up by cache hits.
2536 {
2537 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2538 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2539 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2540 mock_transaction.transport_info = TestTransportInfo();
2541 MockHttpRequest request(mock_transaction);
2542
2543 ConnectedHandler connected_handler;
2544
2545 std::unique_ptr<HttpTransaction> transaction;
2546 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2547 ASSERT_THAT(transaction, NotNull());
2548
2549 transaction->SetConnectedCallback(connected_handler.Callback());
2550
2551 TestCompletionCallback callback;
2552 ASSERT_THAT(
2553 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2554 IsError(ERR_IO_PENDING));
2555 EXPECT_THAT(callback.WaitForResult(), IsOk());
2556
2557 // 1 call for the first range's network transaction.
2558 EXPECT_THAT(connected_handler.transports(),
2559 ElementsAre(TestTransportInfo()));
2560
2561 // Switch the endpoint for the next network transaction to observe.
2562 // For ease, we just switch the port number.
2563 //
2564 // NOTE: This works because only the mock transaction struct's address is
2565 // registered with the mocking framework - the pointee data is consulted
2566 // each time it is read.
2567 mock_transaction.transport_info = TestTransportInfoWithPort(123);
2568
2569 ReadAndVerifyTransaction(transaction.get(), mock_transaction);
2570
2571 // A second call for the cached range, reported as coming from the original
2572 // endpoint it was cached from. A third call for the last range's network
2573 // transaction.
2574 EXPECT_THAT(connected_handler.transports(),
2575 ElementsAre(TestTransportInfo(), CachedTestTransportInfo(),
2576 TestTransportInfoWithPort(123)));
2577 }
2578 }
2579
2580 // This test verifies that when the ConnectedCallback passed to a cache range
2581 // transaction returns an `ERR_INCONSISTENT_IP_ADDRESS_SPACE` error during a
2582 // partial read from cache, then the cache entry is invalidated.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnInconsistentIpError)2583 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackReturnInconsistentIpError) {
2584 MockHttpCache cache;
2585
2586 // Request an infix range and populate the cache with it.
2587 {
2588 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2589 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2590 mock_transaction.data = "rg: 20-29 ";
2591 mock_transaction.transport_info = TestTransportInfo();
2592
2593 RunTransactionTest(cache.http_cache(), mock_transaction);
2594 }
2595
2596 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2597 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2598 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2599 mock_transaction.transport_info = TestTransportInfo();
2600 MockHttpRequest request(mock_transaction);
2601
2602 // Request a surrounding range. This *should* be read in three parts:
2603 //
2604 // 1. for the prefix: from the network
2605 // 2. for the cached infix: from the cache
2606 // 3. for the suffix: from the network
2607 //
2608 // The connected callback returns OK for 1), but fails during 2). As a result,
2609 // the transaction fails partway and 3) is never created. The cache entry is
2610 // invalidated as a result of the specific error code.
2611 {
2612 ConnectedHandler connected_handler;
2613
2614 std::unique_ptr<HttpTransaction> transaction;
2615 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2616 ASSERT_THAT(transaction, NotNull());
2617
2618 transaction->SetConnectedCallback(connected_handler.Callback());
2619
2620 TestCompletionCallback callback;
2621 ASSERT_THAT(
2622 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2623 IsError(ERR_IO_PENDING));
2624 EXPECT_THAT(callback.WaitForResult(), IsOk());
2625
2626 // 1 call for the first range's network transaction.
2627 EXPECT_THAT(connected_handler.transports(),
2628 ElementsAre(TestTransportInfo()));
2629
2630 // Set the callback to return an error the next time it is called.
2631 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
2632
2633 std::string content;
2634 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2635 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
2636
2637 // A second call that failed.
2638 EXPECT_THAT(connected_handler.transports(),
2639 ElementsAre(TestTransportInfo(), CachedTestTransportInfo()));
2640 }
2641
2642 // Request the same range again, observe that nothing is read from cache.
2643 {
2644 ConnectedHandler connected_handler;
2645
2646 std::unique_ptr<HttpTransaction> transaction;
2647 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2648 ASSERT_THAT(transaction, NotNull());
2649
2650 transaction->SetConnectedCallback(connected_handler.Callback());
2651
2652 TestCompletionCallback callback;
2653 ASSERT_THAT(
2654 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2655 IsError(ERR_IO_PENDING));
2656 EXPECT_THAT(callback.WaitForResult(), IsOk());
2657
2658 std::string content;
2659 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2660 EXPECT_EQ(content, mock_transaction.data);
2661
2662 // 1 call for the network transaction from which the whole response was
2663 // read. The first 20 bytes were cached by the previous two requests, but
2664 // the cache entry was doomed during the last transaction so they are not
2665 // used here.
2666 EXPECT_THAT(connected_handler.transports(),
2667 ElementsAre(TestTransportInfo()));
2668 }
2669 }
2670
2671 // This test verifies that when the ConnectedCallback passed to a cache range
2672 // transaction returns an `ERR_INCONSISTENT_IP_ADDRESS_SPACE` error during a
2673 // network transaction, then the cache entry is invalidated.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnInconsistentIpErrorForNetwork)2674 TEST_F(HttpCacheTest,
2675 RangeGET_ConnectedCallbackReturnInconsistentIpErrorForNetwork) {
2676 MockHttpCache cache;
2677
2678 // Request a prefix range and populate the cache with it.
2679 {
2680 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2681 mock_transaction.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2682 mock_transaction.data = "rg: 10-19 ";
2683 mock_transaction.transport_info = TestTransportInfo();
2684
2685 RunTransactionTest(cache.http_cache(), mock_transaction);
2686 }
2687
2688 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2689 mock_transaction.request_headers = "Range: bytes = 10-29\r\n" EXTRA_HEADER;
2690 mock_transaction.data = "rg: 10-19 rg: 20-29 ";
2691 mock_transaction.transport_info = TestTransportInfo();
2692 MockHttpRequest request(mock_transaction);
2693
2694 // Request a longer range. This *should* be read in two parts:
2695 //
2696 // 1. for the prefix: from the cache
2697 // 2. for the suffix: from the network
2698 {
2699 ConnectedHandler connected_handler;
2700
2701 std::unique_ptr<HttpTransaction> transaction;
2702 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2703 ASSERT_THAT(transaction, NotNull());
2704
2705 transaction->SetConnectedCallback(connected_handler.Callback());
2706
2707 TestCompletionCallback callback;
2708 ASSERT_THAT(
2709 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2710 IsError(ERR_IO_PENDING));
2711 EXPECT_THAT(callback.WaitForResult(), IsOk());
2712
2713 // 1 call for the first range's network transaction.
2714 EXPECT_THAT(connected_handler.transports(),
2715 ElementsAre(CachedTestTransportInfo()));
2716
2717 // Set the callback to return an error the next time it is called.
2718 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
2719
2720 std::string content;
2721 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2722 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
2723
2724 // A second call that failed.
2725 EXPECT_THAT(connected_handler.transports(),
2726 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
2727 }
2728
2729 // Request the same range again, observe that nothing is read from cache.
2730 {
2731 ConnectedHandler connected_handler;
2732
2733 std::unique_ptr<HttpTransaction> transaction;
2734 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2735 ASSERT_THAT(transaction, NotNull());
2736
2737 transaction->SetConnectedCallback(connected_handler.Callback());
2738
2739 TestCompletionCallback callback;
2740 ASSERT_THAT(
2741 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2742 IsError(ERR_IO_PENDING));
2743 EXPECT_THAT(callback.WaitForResult(), IsOk());
2744
2745 std::string content;
2746 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2747 EXPECT_EQ(content, mock_transaction.data);
2748
2749 // 1 call for the network transaction from which the whole response was
2750 // read. The first 20 bytes were cached by the previous two requests, but
2751 // the cache entry was doomed during the last transaction so they are not
2752 // used here.
2753 EXPECT_THAT(connected_handler.transports(),
2754 ElementsAre(TestTransportInfo()));
2755 }
2756 }
2757
2758 // This test verifies that when the ConnectedCallback passed to a cache
2759 // transaction returns an error for the second (or third) subrange transaction,
2760 // the overall cache transaction fails with that error. The cache entry is still
2761 // usable after that.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnErrorSecondTime)2762 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackReturnErrorSecondTime) {
2763 MockHttpCache cache;
2764
2765 // Request an infix range and populate the cache with it.
2766 {
2767 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2768 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2769 mock_transaction.data = "rg: 20-29 ";
2770 mock_transaction.transport_info = TestTransportInfo();
2771
2772 RunTransactionTest(cache.http_cache(), mock_transaction);
2773 }
2774
2775 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2776 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2777 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2778 mock_transaction.transport_info = TestTransportInfo();
2779 MockHttpRequest request(mock_transaction);
2780
2781 // Request a surrounding range. This *should* be read in three parts:
2782 //
2783 // 1. for the prefix: from the network
2784 // 2. for the cached infix: from the cache
2785 // 3. for the suffix: from the network
2786 //
2787 // The connected callback returns OK for 1), but fails during 2). As a result,
2788 // the transaction fails partway and 3) is never created. The prefix is still
2789 // cached, such that the cache entry ends up with both the prefix and infix.
2790 {
2791 ConnectedHandler connected_handler;
2792
2793 std::unique_ptr<HttpTransaction> transaction;
2794 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2795 ASSERT_THAT(transaction, NotNull());
2796
2797 transaction->SetConnectedCallback(connected_handler.Callback());
2798
2799 TestCompletionCallback callback;
2800 ASSERT_THAT(
2801 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2802 IsError(ERR_IO_PENDING));
2803 EXPECT_THAT(callback.WaitForResult(), IsOk());
2804
2805 // 1 call for the first range's network transaction.
2806 EXPECT_THAT(connected_handler.transports(),
2807 ElementsAre(TestTransportInfo()));
2808
2809 // Set the callback to return an error the next time it is called. The exact
2810 // error code is irrelevant, what matters is that it is reflected in the
2811 // overall status of the transaction.
2812 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
2813
2814 std::string content;
2815 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2816 IsError(ERR_NOT_IMPLEMENTED));
2817
2818 // A second call that failed.
2819 EXPECT_THAT(connected_handler.transports(),
2820 ElementsAre(TestTransportInfo(), CachedTestTransportInfo()));
2821 }
2822
2823 // Request the same range again, observe that the prefix and infix are both
2824 // read from cache. Only the suffix is fetched from the network.
2825 {
2826 ConnectedHandler connected_handler;
2827
2828 std::unique_ptr<HttpTransaction> transaction;
2829 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2830 ASSERT_THAT(transaction, NotNull());
2831
2832 transaction->SetConnectedCallback(connected_handler.Callback());
2833
2834 TestCompletionCallback callback;
2835 ASSERT_THAT(
2836 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2837 IsError(ERR_IO_PENDING));
2838 EXPECT_THAT(callback.WaitForResult(), IsOk());
2839
2840 // 1 call for the first range's cache transaction: the first 20 bytes were
2841 // cached by the previous two requests.
2842 EXPECT_THAT(connected_handler.transports(),
2843 ElementsAre(CachedTestTransportInfo()));
2844
2845 std::string content;
2846 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2847 EXPECT_EQ(content, mock_transaction.data);
2848
2849 // A second call from the network transaction for the last 10 bytes.
2850 EXPECT_THAT(connected_handler.transports(),
2851 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
2852 }
2853 }
2854
2855 // This test verifies that the ConnectedCallback passed to a cache transaction
2856 // is called once per subrange in the case of a range request with a partial
2857 // cache hit, even when a prefix of the range is cached.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackCalledForEachRangeWithPrefix)2858 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackCalledForEachRangeWithPrefix) {
2859 MockHttpCache cache;
2860
2861 // Request a prefix range and populate the cache with it.
2862 {
2863 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2864 mock_transaction.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2865 mock_transaction.data = "rg: 10-19 ";
2866 mock_transaction.transport_info = TestTransportInfo();
2867
2868 RunTransactionTest(cache.http_cache(), mock_transaction);
2869 }
2870
2871 // Request a surrounding range and observe that the callback is called once
2872 // per subrange, as split up by cache hits.
2873 {
2874 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2875 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2876 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2877 mock_transaction.transport_info = TestTransportInfoWithPort(123);
2878 MockHttpRequest request(mock_transaction);
2879
2880 ConnectedHandler connected_handler;
2881
2882 std::unique_ptr<HttpTransaction> transaction;
2883 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2884 ASSERT_THAT(transaction, NotNull());
2885
2886 transaction->SetConnectedCallback(connected_handler.Callback());
2887
2888 TestCompletionCallback callback;
2889 ASSERT_THAT(
2890 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2891 IsError(ERR_IO_PENDING));
2892 EXPECT_THAT(callback.WaitForResult(), IsOk());
2893
2894 // 1 call for the first range from the cache, reported as coming from the
2895 // endpoint which initially served the cached range.
2896 EXPECT_THAT(connected_handler.transports(),
2897 ElementsAre(CachedTestTransportInfo()));
2898
2899 ReadAndVerifyTransaction(transaction.get(), mock_transaction);
2900
2901 // A second call for the last range's network transaction.
2902 EXPECT_THAT(
2903 connected_handler.transports(),
2904 ElementsAre(CachedTestTransportInfo(), TestTransportInfoWithPort(123)));
2905 }
2906 }
2907
2908 // Tests that a range transaction is still usable even if it's unable to access
2909 // the cache.
TEST_F(HttpCacheTest,RangeGET_FailedCacheAccess)2910 TEST_F(HttpCacheTest, RangeGET_FailedCacheAccess) {
2911 MockHttpCache cache;
2912
2913 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
2914 MockHttpRequest request(transaction);
2915
2916 auto c = std::make_unique<Context>();
2917 c->result = cache.CreateTransaction(&c->trans);
2918 ASSERT_THAT(c->result, IsOk());
2919 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2920
2921 cache.disk_cache()->set_fail_requests(true);
2922
2923 c->result =
2924 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2925
2926 base::RunLoop().RunUntilIdle();
2927
2928 EXPECT_FALSE(cache.IsWriterPresent(kRangeGET_TransactionOK.url));
2929
2930 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2931 EXPECT_EQ(0, cache.disk_cache()->open_count());
2932 EXPECT_EQ(0, cache.disk_cache()->create_count());
2933
2934 c->result = c->callback.WaitForResult();
2935
2936 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
2937
2938 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2939 EXPECT_EQ(0, cache.disk_cache()->open_count());
2940 EXPECT_EQ(0, cache.disk_cache()->create_count());
2941 }
2942
2943 // Tests that we can have parallel validation on range requests.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatch)2944 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatch) {
2945 MockHttpCache cache;
2946
2947 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
2948 MockHttpRequest request(transaction);
2949
2950 std::vector<std::unique_ptr<Context>> context_list;
2951 const int kNumTransactions = 5;
2952
2953 for (int i = 0; i < kNumTransactions; ++i) {
2954 context_list.push_back(std::make_unique<Context>());
2955 auto& c = context_list[i];
2956
2957 c->result = cache.CreateTransaction(&c->trans);
2958 ASSERT_THAT(c->result, IsOk());
2959 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2960
2961 c->result =
2962 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2963 }
2964
2965 // All requests are waiting for the active entry.
2966 for (auto& context : context_list) {
2967 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
2968 }
2969
2970 // Allow all requests to move from the Create queue to the active entry.
2971 base::RunLoop().RunUntilIdle();
2972
2973 // First entry created is doomed due to 2nd transaction's validation leading
2974 // to restarting of the queued transactions.
2975 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
2976
2977 // TODO(shivanisha): The restarted transactions race for creating the entry
2978 // and thus instead of all 4 succeeding, 2 of them succeed. This is very
2979 // implementation specific and happens because the queued transactions get
2980 // restarted synchronously and get to the queue of creating the entry before
2981 // the transaction that is restarting them. Fix the test to make it less
2982 // vulnerable to any scheduling changes in the code.
2983 EXPECT_EQ(5, cache.network_layer()->transaction_count());
2984 EXPECT_EQ(0, cache.disk_cache()->open_count());
2985 EXPECT_EQ(3, cache.disk_cache()->create_count());
2986
2987 for (auto& context : context_list) {
2988 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
2989 }
2990
2991 for (int i = 0; i < kNumTransactions; ++i) {
2992 auto& c = context_list[i];
2993 if (c->result == ERR_IO_PENDING)
2994 c->result = c->callback.WaitForResult();
2995
2996 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
2997 }
2998
2999 EXPECT_EQ(5, cache.network_layer()->transaction_count());
3000 EXPECT_EQ(0, cache.disk_cache()->open_count());
3001 EXPECT_EQ(3, cache.disk_cache()->create_count());
3002 }
3003
3004 // Tests that if a transaction is dooming the entry and the entry was doomed by
3005 // another transaction that was not part of the entry and created a new entry,
3006 // the new entry should not be incorrectly doomed. (crbug.com/736993)
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatchDoomEntry)3007 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatchDoomEntry) {
3008 MockHttpCache cache;
3009
3010 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3011 MockHttpRequest request(transaction);
3012
3013 MockTransaction dooming_transaction(kRangeGET_TransactionOK);
3014 dooming_transaction.load_flags |= LOAD_BYPASS_CACHE;
3015 MockHttpRequest dooming_request(dooming_transaction);
3016
3017 std::vector<std::unique_ptr<Context>> context_list;
3018 const int kNumTransactions = 3;
3019
3020 scoped_refptr<MockDiskEntry> first_entry;
3021 scoped_refptr<MockDiskEntry> second_entry;
3022 for (int i = 0; i < kNumTransactions; ++i) {
3023 context_list.push_back(std::make_unique<Context>());
3024 auto& c = context_list[i];
3025
3026 c->result = cache.CreateTransaction(&c->trans);
3027 ASSERT_THAT(c->result, IsOk());
3028 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3029
3030 MockHttpRequest* this_request = &request;
3031
3032 if (i == 2)
3033 this_request = &dooming_request;
3034
3035 if (i == 1) {
3036 ASSERT_TRUE(first_entry);
3037 first_entry->SetDefer(MockDiskEntry::DEFER_READ);
3038 }
3039
3040 c->result = c->trans->Start(this_request, c->callback.callback(),
3041 NetLogWithSource());
3042
3043 // Continue the transactions. 2nd will pause at the cache reading state and
3044 // 3rd transaction will doom the entry.
3045 base::RunLoop().RunUntilIdle();
3046
3047 std::string cache_key = request.CacheKey();
3048 // Check status of the first and second entries after every transaction.
3049 switch (i) {
3050 case 0:
3051 first_entry = cache.disk_cache()->GetDiskEntryRef(cache_key);
3052 break;
3053 case 1:
3054 EXPECT_FALSE(first_entry->is_doomed());
3055 break;
3056 case 2:
3057 EXPECT_TRUE(first_entry->is_doomed());
3058 second_entry = cache.disk_cache()->GetDiskEntryRef(cache_key);
3059 EXPECT_FALSE(second_entry->is_doomed());
3060 break;
3061 }
3062 }
3063 // Resume cache read by 1st transaction which will lead to dooming the entry
3064 // as well since the entry cannot be validated. This double dooming should not
3065 // lead to an assertion.
3066 first_entry->ResumeDiskEntryOperation();
3067 base::RunLoop().RunUntilIdle();
3068
3069 // Since second_entry is already created, when 1st transaction goes on to
3070 // create an entry, it will get ERR_CACHE_RACE leading to dooming of
3071 // second_entry and creation of a third entry.
3072 EXPECT_TRUE(second_entry->is_doomed());
3073
3074 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3075 EXPECT_EQ(0, cache.disk_cache()->open_count());
3076 EXPECT_EQ(3, cache.disk_cache()->create_count());
3077
3078 for (auto& context : context_list) {
3079 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3080 }
3081
3082 for (auto& c : context_list) {
3083 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
3084 }
3085
3086 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3087 EXPECT_EQ(0, cache.disk_cache()->open_count());
3088 EXPECT_EQ(3, cache.disk_cache()->create_count());
3089 }
3090
3091 // Same as above but tests that the 2nd transaction does not do anything if
3092 // there is nothing to doom. (crbug.com/736993)
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatchDoomEntry1)3093 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatchDoomEntry1) {
3094 MockHttpCache cache;
3095
3096 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3097 MockHttpRequest request(transaction);
3098
3099 MockTransaction dooming_transaction(kRangeGET_TransactionOK);
3100 dooming_transaction.load_flags |= LOAD_BYPASS_CACHE;
3101 MockHttpRequest dooming_request(dooming_transaction);
3102
3103 std::vector<std::unique_ptr<Context>> context_list;
3104 const int kNumTransactions = 3;
3105
3106 scoped_refptr<MockDiskEntry> first_entry;
3107 for (int i = 0; i < kNumTransactions; ++i) {
3108 context_list.push_back(std::make_unique<Context>());
3109 auto& c = context_list[i];
3110
3111 c->result = cache.CreateTransaction(&c->trans);
3112 ASSERT_THAT(c->result, IsOk());
3113 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3114
3115 MockHttpRequest* this_request = &request;
3116
3117 if (i == 2) {
3118 this_request = &dooming_request;
3119 cache.disk_cache()->SetDefer(MockDiskEntry::DEFER_CREATE);
3120 }
3121
3122 if (i == 1) {
3123 ASSERT_TRUE(first_entry);
3124 first_entry->SetDefer(MockDiskEntry::DEFER_READ);
3125 }
3126
3127 c->result = c->trans->Start(this_request, c->callback.callback(),
3128 NetLogWithSource());
3129
3130 // Continue the transactions. 2nd will pause at the cache reading state and
3131 // 3rd transaction will doom the entry and pause before creating a new
3132 // entry.
3133 base::RunLoop().RunUntilIdle();
3134
3135 // Check status of the entry after every transaction.
3136 switch (i) {
3137 case 0:
3138 first_entry = cache.disk_cache()->GetDiskEntryRef(request.CacheKey());
3139 break;
3140 case 1:
3141 EXPECT_FALSE(first_entry->is_doomed());
3142 break;
3143 case 2:
3144 EXPECT_TRUE(first_entry->is_doomed());
3145 break;
3146 }
3147 }
3148 // Resume cache read by 2nd transaction which will lead to dooming the entry
3149 // as well since the entry cannot be validated. This double dooming should not
3150 // lead to an assertion.
3151 first_entry->ResumeDiskEntryOperation();
3152 base::RunLoop().RunUntilIdle();
3153
3154 // Resume creation of entry by 3rd transaction.
3155 cache.disk_cache()->ResumeCacheOperation();
3156 base::RunLoop().RunUntilIdle();
3157
3158 // Note that since 3rd transaction's entry is already created but its
3159 // callback is deferred, MockDiskCache's implementation returns
3160 // ERR_CACHE_CREATE_FAILURE when 2nd transaction tries to create an entry
3161 // during that time, leading to it switching over to pass-through mode.
3162 // Thus the number of entries is 2 below.
3163 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3164 EXPECT_EQ(0, cache.disk_cache()->open_count());
3165 EXPECT_EQ(2, cache.disk_cache()->create_count());
3166
3167 for (auto& context : context_list) {
3168 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3169 }
3170
3171 for (auto& c : context_list) {
3172 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
3173 }
3174
3175 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3176 EXPECT_EQ(0, cache.disk_cache()->open_count());
3177 EXPECT_EQ(2, cache.disk_cache()->create_count());
3178 }
3179
3180 // Tests parallel validation on range requests with non-overlapping ranges.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationDifferentRanges)3181 TEST_F(HttpCacheTest, RangeGET_ParallelValidationDifferentRanges) {
3182 MockHttpCache cache;
3183
3184 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3185
3186 std::vector<std::unique_ptr<Context>> context_list;
3187 const int kNumTransactions = 2;
3188
3189 for (int i = 0; i < kNumTransactions; ++i) {
3190 context_list.push_back(std::make_unique<Context>());
3191 }
3192
3193 // Let 1st transaction complete headers phase for ranges 40-49.
3194 std::string first_read;
3195 MockHttpRequest request1(transaction);
3196 {
3197 auto& c = context_list[0];
3198 c->result = cache.CreateTransaction(&c->trans);
3199 ASSERT_THAT(c->result, IsOk());
3200 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3201
3202 c->result =
3203 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3204 base::RunLoop().RunUntilIdle();
3205
3206 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3207 // true.
3208 const int kBufferSize = 5;
3209 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3210 ReleaseBufferCompletionCallback cb(buffer.get());
3211 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3212 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3213
3214 std::string data_read(buffer->data(), kBufferSize);
3215 first_read = data_read;
3216
3217 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3218 }
3219
3220 // 2nd transaction requests ranges 30-39.
3221 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
3222 MockHttpRequest request2(transaction);
3223 {
3224 auto& c = context_list[1];
3225 c->result = cache.CreateTransaction(&c->trans);
3226 ASSERT_THAT(c->result, IsOk());
3227 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3228
3229 c->result =
3230 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3231 base::RunLoop().RunUntilIdle();
3232
3233 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3234 }
3235
3236 std::string cache_key = request2.CacheKey();
3237 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3238 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3239
3240 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3241 EXPECT_EQ(0, cache.disk_cache()->open_count());
3242 EXPECT_EQ(1, cache.disk_cache()->create_count());
3243
3244 for (int i = 0; i < kNumTransactions; ++i) {
3245 auto& c = context_list[i];
3246 if (c->result == ERR_IO_PENDING)
3247 c->result = c->callback.WaitForResult();
3248
3249 if (i == 0) {
3250 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3251 transaction);
3252 continue;
3253 }
3254
3255 transaction.data = "rg: 30-39 ";
3256 ReadAndVerifyTransaction(c->trans.get(), transaction);
3257 }
3258
3259 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3260 EXPECT_EQ(0, cache.disk_cache()->open_count());
3261 EXPECT_EQ(1, cache.disk_cache()->create_count());
3262
3263 // Fetch from the cache to check that ranges 30-49 have been successfully
3264 // cached.
3265 {
3266 MockTransaction range_transaction(kRangeGET_TransactionOK);
3267 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3268 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3269 std::string headers;
3270 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3271 &headers);
3272 Verify206Response(headers, 30, 49);
3273 }
3274
3275 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3276 EXPECT_EQ(1, cache.disk_cache()->open_count());
3277 EXPECT_EQ(1, cache.disk_cache()->create_count());
3278
3279 context_list.clear();
3280 }
3281
3282 // Tests that a request does not create Writers when readers is not empty.
TEST_F(HttpCacheTest,RangeGET_DoNotCreateWritersWhenReaderExists)3283 TEST_F(HttpCacheTest, RangeGET_DoNotCreateWritersWhenReaderExists) {
3284 MockHttpCache cache;
3285
3286 // Save a request in the cache so that the next request can become a
3287 // reader.
3288 MockTransaction transaction(kRangeGET_Transaction);
3289 transaction.request_headers = EXTRA_HEADER;
3290 AddMockTransaction(&transaction);
3291 RunTransactionTest(cache.http_cache(), transaction);
3292
3293 // Let this request be a reader since it doesn't need validation as per its
3294 // load flag.
3295 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
3296 MockHttpRequest request(transaction);
3297 Context context;
3298 context.result = cache.CreateTransaction(&context.trans);
3299 ASSERT_THAT(context.result, IsOk());
3300 context.result = context.trans->Start(&request, context.callback.callback(),
3301 NetLogWithSource());
3302 base::RunLoop().RunUntilIdle();
3303 std::string cache_key = request.CacheKey();
3304 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
3305 RemoveMockTransaction(&transaction);
3306
3307 // A range request should now "not" create Writers while readers is still
3308 // non-empty.
3309 MockTransaction range_transaction(kRangeGET_Transaction);
3310 range_transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
3311 AddMockTransaction(&range_transaction);
3312 MockHttpRequest range_request(range_transaction);
3313 Context range_context;
3314 range_context.result = cache.CreateTransaction(&range_context.trans);
3315 ASSERT_THAT(range_context.result, IsOk());
3316 range_context.result = range_context.trans->Start(
3317 &range_request, range_context.callback.callback(), NetLogWithSource());
3318 base::RunLoop().RunUntilIdle();
3319
3320 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
3321 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
3322 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3323
3324 RemoveMockTransaction(&range_transaction);
3325 }
3326
3327 // Tests parallel validation on range requests can be successfully restarted
3328 // when there is a cache lock timeout.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCacheLockTimeout)3329 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCacheLockTimeout) {
3330 MockHttpCache cache;
3331
3332 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3333
3334 std::vector<std::unique_ptr<Context>> context_list;
3335 const int kNumTransactions = 2;
3336
3337 for (int i = 0; i < kNumTransactions; ++i) {
3338 context_list.push_back(std::make_unique<Context>());
3339 }
3340
3341 // Let 1st transaction complete headers phase for ranges 40-49.
3342 std::string first_read;
3343 MockHttpRequest request1(transaction);
3344 {
3345 auto& c = context_list[0];
3346 c->result = cache.CreateTransaction(&c->trans);
3347 ASSERT_THAT(c->result, IsOk());
3348 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3349
3350 c->result =
3351 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3352 base::RunLoop().RunUntilIdle();
3353
3354 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3355 // true.
3356 const int kBufferSize = 5;
3357 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3358 ReleaseBufferCompletionCallback cb(buffer.get());
3359 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3360 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3361
3362 std::string data_read(buffer->data(), kBufferSize);
3363 first_read = data_read;
3364
3365 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3366 }
3367
3368 // Cache lock timeout will lead to dooming the entry since the transaction may
3369 // have already written the headers.
3370 cache.SimulateCacheLockTimeoutAfterHeaders();
3371
3372 // 2nd transaction requests ranges 30-39.
3373 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
3374 MockHttpRequest request2(transaction);
3375 {
3376 auto& c = context_list[1];
3377 c->result = cache.CreateTransaction(&c->trans);
3378 ASSERT_THAT(c->result, IsOk());
3379 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3380
3381 c->result =
3382 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3383 base::RunLoop().RunUntilIdle();
3384
3385 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3386 }
3387
3388 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(request1.CacheKey()));
3389
3390 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3391 EXPECT_EQ(0, cache.disk_cache()->open_count());
3392 EXPECT_EQ(1, cache.disk_cache()->create_count());
3393
3394 for (int i = 0; i < kNumTransactions; ++i) {
3395 auto& c = context_list[i];
3396 if (c->result == ERR_IO_PENDING)
3397 c->result = c->callback.WaitForResult();
3398
3399 if (i == 0) {
3400 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3401 transaction);
3402 continue;
3403 }
3404
3405 transaction.data = "rg: 30-39 ";
3406 ReadAndVerifyTransaction(c->trans.get(), transaction);
3407 }
3408
3409 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3410 EXPECT_EQ(0, cache.disk_cache()->open_count());
3411 EXPECT_EQ(1, cache.disk_cache()->create_count());
3412 }
3413
3414 // Tests a full request and a simultaneous range request and the range request
3415 // dooms the entry created by the full request due to not being able to
3416 // conditionalize.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCouldntConditionalize)3417 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCouldntConditionalize) {
3418 MockHttpCache cache;
3419
3420 MockTransaction mock_transaction(kSimpleGET_Transaction);
3421 mock_transaction.url = kRangeGET_TransactionOK.url;
3422 ScopedMockTransaction transaction(mock_transaction);
3423
3424 // Remove the cache-control and other headers so that the response cannot be
3425 // conditionalized.
3426 transaction.response_headers = "";
3427
3428 std::vector<std::unique_ptr<Context>> context_list;
3429 const int kNumTransactions = 2;
3430
3431 for (int i = 0; i < kNumTransactions; ++i) {
3432 context_list.push_back(std::make_unique<Context>());
3433 }
3434
3435 // Let 1st transaction complete headers phase for no range and read some part
3436 // of the response and write in the cache.
3437 std::string first_read;
3438 MockHttpRequest request1(transaction);
3439 {
3440 request1.url = GURL(kRangeGET_TransactionOK.url);
3441 auto& c = context_list[0];
3442 c->result = cache.CreateTransaction(&c->trans);
3443 ASSERT_THAT(c->result, IsOk());
3444 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3445
3446 c->result =
3447 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3448 base::RunLoop().RunUntilIdle();
3449
3450 const int kBufferSize = 5;
3451 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3452 ReleaseBufferCompletionCallback cb(buffer.get());
3453 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3454 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3455
3456 std::string data_read(buffer->data(), kBufferSize);
3457 first_read = data_read;
3458
3459 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3460 }
3461
3462 // 2nd transaction requests a range.
3463 ScopedMockTransaction range_transaction(kRangeGET_TransactionOK);
3464 range_transaction.request_headers = "Range: bytes = 0-29\r\n" EXTRA_HEADER;
3465 MockHttpRequest request2(range_transaction);
3466 {
3467 auto& c = context_list[1];
3468 c->result = cache.CreateTransaction(&c->trans);
3469 ASSERT_THAT(c->result, IsOk());
3470 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3471
3472 c->result =
3473 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3474 base::RunLoop().RunUntilIdle();
3475
3476 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3477 }
3478
3479 // The second request would have doomed the 1st entry and created a new entry.
3480 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3481 EXPECT_EQ(0, cache.disk_cache()->open_count());
3482 EXPECT_EQ(2, cache.disk_cache()->create_count());
3483
3484 for (int i = 0; i < kNumTransactions; ++i) {
3485 auto& c = context_list[i];
3486 if (c->result == ERR_IO_PENDING)
3487 c->result = c->callback.WaitForResult();
3488
3489 if (i == 0) {
3490 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3491 transaction);
3492 continue;
3493 }
3494 range_transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 ";
3495 ReadAndVerifyTransaction(c->trans.get(), range_transaction);
3496 }
3497 context_list.clear();
3498 }
3499
3500 // Tests a 200 request and a simultaneous range request where conditionalization
3501 // is possible.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCouldConditionalize)3502 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCouldConditionalize) {
3503 MockHttpCache cache;
3504
3505 MockTransaction mock_transaction(kSimpleGET_Transaction);
3506 mock_transaction.url = kRangeGET_TransactionOK.url;
3507 mock_transaction.data = kFullRangeData;
3508 std::string response_headers_str = base::StrCat(
3509 {"ETag: StrongOne\n",
3510 "Content-Length:", base::NumberToString(strlen(kFullRangeData)), "\n"});
3511 mock_transaction.response_headers = response_headers_str.c_str();
3512
3513 ScopedMockTransaction transaction(mock_transaction);
3514
3515 std::vector<std::unique_ptr<Context>> context_list;
3516 const int kNumTransactions = 2;
3517
3518 for (int i = 0; i < kNumTransactions; ++i) {
3519 context_list.push_back(std::make_unique<Context>());
3520 }
3521
3522 // Let 1st transaction complete headers phase for no range and read some part
3523 // of the response and write in the cache.
3524 std::string first_read;
3525 MockHttpRequest request1(transaction);
3526 {
3527 request1.url = GURL(kRangeGET_TransactionOK.url);
3528 auto& c = context_list[0];
3529 c->result = cache.CreateTransaction(&c->trans);
3530 ASSERT_THAT(c->result, IsOk());
3531 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3532
3533 c->result =
3534 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3535 base::RunLoop().RunUntilIdle();
3536
3537 const int kBufferSize = 5;
3538 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3539 ReleaseBufferCompletionCallback cb(buffer.get());
3540 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3541 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3542
3543 std::string data_read(buffer->data(), kBufferSize);
3544 first_read = data_read;
3545
3546 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3547 }
3548
3549 // 2nd transaction requests a range.
3550 ScopedMockTransaction range_transaction(kRangeGET_TransactionOK);
3551 range_transaction.request_headers = "Range: bytes = 0-29\r\n" EXTRA_HEADER;
3552 MockHttpRequest request2(range_transaction);
3553 {
3554 auto& c = context_list[1];
3555 c->result = cache.CreateTransaction(&c->trans);
3556 ASSERT_THAT(c->result, IsOk());
3557 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3558
3559 c->result =
3560 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3561 base::RunLoop().RunUntilIdle();
3562
3563 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3564 }
3565
3566 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3567 EXPECT_EQ(0, cache.disk_cache()->open_count());
3568 EXPECT_EQ(1, cache.disk_cache()->create_count());
3569
3570 // Finish and verify the first request.
3571 auto& c0 = context_list[0];
3572 c0->result = c0->callback.WaitForResult();
3573 ReadRemainingAndVerifyTransaction(c0->trans.get(), first_read, transaction);
3574
3575 // And the second.
3576 auto& c1 = context_list[1];
3577 c1->result = c1->callback.WaitForResult();
3578
3579 range_transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 ";
3580 ReadAndVerifyTransaction(c1->trans.get(), range_transaction);
3581 context_list.clear();
3582 }
3583
3584 // Tests parallel validation on range requests with overlapping ranges.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationOverlappingRanges)3585 TEST_F(HttpCacheTest, RangeGET_ParallelValidationOverlappingRanges) {
3586 MockHttpCache cache;
3587
3588 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3589
3590 std::vector<std::unique_ptr<Context>> context_list;
3591 const int kNumTransactions = 2;
3592
3593 for (int i = 0; i < kNumTransactions; ++i) {
3594 context_list.push_back(std::make_unique<Context>());
3595 }
3596
3597 // Let 1st transaction complete headers phase for ranges 40-49.
3598 std::string first_read;
3599 MockHttpRequest request1(transaction);
3600 {
3601 auto& c = context_list[0];
3602 c->result = cache.CreateTransaction(&c->trans);
3603 ASSERT_THAT(c->result, IsOk());
3604 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3605
3606 c->result =
3607 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3608 base::RunLoop().RunUntilIdle();
3609
3610 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3611 // true.
3612 const int kBufferSize = 5;
3613 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3614 ReleaseBufferCompletionCallback cb(buffer.get());
3615 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3616 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3617
3618 std::string data_read(buffer->data(), kBufferSize);
3619 first_read = data_read;
3620
3621 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3622 }
3623
3624 // 2nd transaction requests ranges 30-49.
3625 transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3626 MockHttpRequest request2(transaction);
3627 {
3628 auto& c = context_list[1];
3629 c->result = cache.CreateTransaction(&c->trans);
3630 ASSERT_THAT(c->result, IsOk());
3631 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3632
3633 c->result =
3634 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3635 base::RunLoop().RunUntilIdle();
3636
3637 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3638 }
3639
3640 std::string cache_key = request1.CacheKey();
3641 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3642 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3643
3644 // Should have created another transaction for the uncached range.
3645 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3646 EXPECT_EQ(0, cache.disk_cache()->open_count());
3647 EXPECT_EQ(1, cache.disk_cache()->create_count());
3648
3649 for (int i = 0; i < kNumTransactions; ++i) {
3650 auto& c = context_list[i];
3651 if (c->result == ERR_IO_PENDING)
3652 c->result = c->callback.WaitForResult();
3653
3654 if (i == 0) {
3655 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3656 transaction);
3657 continue;
3658 }
3659
3660 transaction.data = "rg: 30-39 rg: 40-49 ";
3661 ReadAndVerifyTransaction(c->trans.get(), transaction);
3662 }
3663
3664 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3665 EXPECT_EQ(0, cache.disk_cache()->open_count());
3666 EXPECT_EQ(1, cache.disk_cache()->create_count());
3667
3668 // Fetch from the cache to check that ranges 30-49 have been successfully
3669 // cached.
3670 {
3671 MockTransaction range_transaction(kRangeGET_TransactionOK);
3672 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3673 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3674 std::string headers;
3675 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3676 &headers);
3677 Verify206Response(headers, 30, 49);
3678 }
3679
3680 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3681 EXPECT_EQ(0, cache.disk_cache()->open_count());
3682 EXPECT_EQ(1, cache.disk_cache()->create_count());
3683 }
3684
3685 // Tests parallel validation on range requests with overlapping ranges and the
3686 // impact of deleting the writer on transactions that have validated.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationRestartDoneHeaders)3687 TEST_F(HttpCacheTest, RangeGET_ParallelValidationRestartDoneHeaders) {
3688 MockHttpCache cache;
3689
3690 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3691
3692 std::vector<std::unique_ptr<Context>> context_list;
3693 const int kNumTransactions = 2;
3694
3695 for (int i = 0; i < kNumTransactions; ++i) {
3696 context_list.push_back(std::make_unique<Context>());
3697 }
3698
3699 // Let 1st transaction complete headers phase for ranges 40-59.
3700 std::string first_read;
3701 transaction.request_headers = "Range: bytes = 40-59\r\n" EXTRA_HEADER;
3702 MockHttpRequest request1(transaction);
3703 {
3704 auto& c = context_list[0];
3705 c->result = cache.CreateTransaction(&c->trans);
3706 ASSERT_THAT(c->result, IsOk());
3707 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3708
3709 c->result =
3710 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3711 base::RunLoop().RunUntilIdle();
3712
3713 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3714 // true.
3715 const int kBufferSize = 10;
3716 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3717 ReleaseBufferCompletionCallback cb(buffer.get());
3718 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3719 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3720
3721 std::string data_read(buffer->data(), kBufferSize);
3722 first_read = data_read;
3723
3724 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3725 }
3726
3727 // 2nd transaction requests ranges 30-59.
3728 transaction.request_headers = "Range: bytes = 30-59\r\n" EXTRA_HEADER;
3729 MockHttpRequest request2(transaction);
3730 {
3731 auto& c = context_list[1];
3732 c->result = cache.CreateTransaction(&c->trans);
3733 ASSERT_THAT(c->result, IsOk());
3734 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3735
3736 c->result =
3737 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3738 base::RunLoop().RunUntilIdle();
3739
3740 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3741 }
3742
3743 std::string cache_key = request1.CacheKey();
3744 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3745 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3746
3747 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3748 EXPECT_EQ(0, cache.disk_cache()->open_count());
3749 EXPECT_EQ(1, cache.disk_cache()->create_count());
3750
3751 // Delete the writer transaction.
3752 context_list[0].reset();
3753
3754 base::RunLoop().RunUntilIdle();
3755
3756 transaction.data = "rg: 30-39 rg: 40-49 rg: 50-59 ";
3757 ReadAndVerifyTransaction(context_list[1]->trans.get(), transaction);
3758
3759 // Create another network transaction since the 2nd transaction is restarted.
3760 // 30-39 will be read from network, 40-49 from the cache and 50-59 from the
3761 // network.
3762 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3763 EXPECT_EQ(0, cache.disk_cache()->open_count());
3764 EXPECT_EQ(1, cache.disk_cache()->create_count());
3765
3766 // Fetch from the cache to check that ranges 30-49 have been successfully
3767 // cached.
3768 {
3769 MockTransaction range_transaction(kRangeGET_TransactionOK);
3770 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3771 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3772 std::string headers;
3773 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3774 &headers);
3775 Verify206Response(headers, 30, 49);
3776 }
3777
3778 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3779 EXPECT_EQ(1, cache.disk_cache()->open_count());
3780 EXPECT_EQ(1, cache.disk_cache()->create_count());
3781 }
3782
3783 // A test of doing a range request to a cached 301 response
TEST_F(HttpCacheTest,RangeGET_CachedRedirect)3784 TEST_F(HttpCacheTest, RangeGET_CachedRedirect) {
3785 RangeTransactionServer handler;
3786 handler.set_redirect(true);
3787
3788 MockHttpCache cache;
3789 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3790 transaction.request_headers = "Range: bytes = 0-\r\n" EXTRA_HEADER;
3791 transaction.status = "HTTP/1.1 301 Moved Permanently";
3792 transaction.response_headers = "Location: /elsewhere\nContent-Length:5";
3793 transaction.data = "12345";
3794 MockHttpRequest request(transaction);
3795
3796 TestCompletionCallback callback;
3797
3798 // Write to the cache.
3799 {
3800 std::unique_ptr<HttpTransaction> trans;
3801 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3802
3803 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3804 if (rv == ERR_IO_PENDING)
3805 rv = callback.WaitForResult();
3806 ASSERT_THAT(rv, IsOk());
3807
3808 const HttpResponseInfo* info = trans->GetResponseInfo();
3809 ASSERT_TRUE(info);
3810
3811 EXPECT_EQ(info->headers->response_code(), 301);
3812
3813 std::string location;
3814 info->headers->EnumerateHeader(nullptr, "Location", &location);
3815 EXPECT_EQ(location, "/elsewhere");
3816
3817 ReadAndVerifyTransaction(trans.get(), transaction);
3818 }
3819 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3820 EXPECT_EQ(0, cache.disk_cache()->open_count());
3821 EXPECT_EQ(1, cache.disk_cache()->create_count());
3822
3823 // Active entries in the cache are not retired synchronously. Make
3824 // sure the next run hits the MockHttpCache and open_count is
3825 // correct.
3826 base::RunLoop().RunUntilIdle();
3827
3828 // Read from the cache.
3829 {
3830 std::unique_ptr<HttpTransaction> trans;
3831 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3832
3833 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3834 if (rv == ERR_IO_PENDING)
3835 rv = callback.WaitForResult();
3836 ASSERT_THAT(rv, IsOk());
3837
3838 const HttpResponseInfo* info = trans->GetResponseInfo();
3839 ASSERT_TRUE(info);
3840
3841 EXPECT_EQ(info->headers->response_code(), 301);
3842
3843 std::string location;
3844 info->headers->EnumerateHeader(nullptr, "Location", &location);
3845 EXPECT_EQ(location, "/elsewhere");
3846
3847 trans->DoneReading();
3848 }
3849 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3850 EXPECT_EQ(1, cache.disk_cache()->open_count());
3851 EXPECT_EQ(1, cache.disk_cache()->create_count());
3852
3853 // Now read the full body. This normally would not be done for a 301 by
3854 // higher layers, but e.g. a 500 could hit a further bug here.
3855 {
3856 std::unique_ptr<HttpTransaction> trans;
3857 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3858
3859 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3860 if (rv == ERR_IO_PENDING)
3861 rv = callback.WaitForResult();
3862 ASSERT_THAT(rv, IsOk());
3863
3864 const HttpResponseInfo* info = trans->GetResponseInfo();
3865 ASSERT_TRUE(info);
3866
3867 EXPECT_EQ(info->headers->response_code(), 301);
3868
3869 std::string location;
3870 info->headers->EnumerateHeader(nullptr, "Location", &location);
3871 EXPECT_EQ(location, "/elsewhere");
3872
3873 ReadAndVerifyTransaction(trans.get(), transaction);
3874 }
3875 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3876 // No extra open since it picks up a previous ActiveEntry.
3877 EXPECT_EQ(1, cache.disk_cache()->open_count());
3878 EXPECT_EQ(1, cache.disk_cache()->create_count());
3879 }
3880
3881 // A transaction that fails to validate an entry, while attempting to write
3882 // the response, should still get data to its consumer even if the attempt to
3883 // create a new entry fails.
TEST_F(HttpCacheTest,SimpleGET_ValidationFailureWithCreateFailure)3884 TEST_F(HttpCacheTest, SimpleGET_ValidationFailureWithCreateFailure) {
3885 MockHttpCache cache;
3886 MockHttpRequest request(kSimpleGET_Transaction);
3887 request.load_flags |= LOAD_VALIDATE_CACHE;
3888 std::vector<std::unique_ptr<Context>> context_list;
3889
3890 // Create and run the first, successful, transaction to prime the cache.
3891 context_list.push_back(std::make_unique<Context>());
3892 auto& c1 = context_list.back();
3893 c1->result = cache.CreateTransaction(&c1->trans);
3894 ASSERT_THAT(c1->result, IsOk());
3895 EXPECT_EQ(LOAD_STATE_IDLE, c1->trans->GetLoadState());
3896 c1->result =
3897 c1->trans->Start(&request, c1->callback.callback(), NetLogWithSource());
3898 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c1->trans->GetLoadState());
3899 base::RunLoop().RunUntilIdle();
3900
3901 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
3902 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3903 EXPECT_EQ(0, cache.disk_cache()->open_count());
3904 EXPECT_EQ(1, cache.disk_cache()->create_count());
3905
3906 // Create and start the second transaction, which will fail its validation
3907 // during the call to RunUntilIdle().
3908 context_list.push_back(std::make_unique<Context>());
3909 auto& c2 = context_list.back();
3910 c2->result = cache.CreateTransaction(&c2->trans);
3911 ASSERT_THAT(c2->result, IsOk());
3912 EXPECT_EQ(LOAD_STATE_IDLE, c2->trans->GetLoadState());
3913 c2->result =
3914 c2->trans->Start(&request, c2->callback.callback(), NetLogWithSource());
3915 // Expect idle at this point because we should be able to find and use the
3916 // Active Entry that c1 created instead of waiting on the cache to open the
3917 // entry.
3918 EXPECT_EQ(LOAD_STATE_IDLE, c2->trans->GetLoadState());
3919
3920 cache.disk_cache()->set_fail_requests(true);
3921 // The transaction, c2, should now attempt to validate the entry, fail when it
3922 // receives a 200 OK response, attempt to create a new entry, fail to create,
3923 // and then continue onward without an entry.
3924 base::RunLoop().RunUntilIdle();
3925
3926 // All requests depend on the writer, and the writer is between Start and
3927 // Read, i.e. idle.
3928 for (auto& context : context_list) {
3929 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3930 }
3931
3932 // Confirm that both transactions correctly Read() the data.
3933 for (auto& context : context_list) {
3934 if (context->result == ERR_IO_PENDING)
3935 context->result = context->callback.WaitForResult();
3936 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
3937 }
3938
3939 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3940 EXPECT_EQ(0, cache.disk_cache()->open_count());
3941 EXPECT_EQ(1, cache.disk_cache()->create_count());
3942 }
3943
3944 // Parallel validation results in 200.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationNoMatch)3945 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationNoMatch) {
3946 MockHttpCache cache;
3947 MockHttpRequest request(kSimpleGET_Transaction);
3948 request.load_flags |= LOAD_VALIDATE_CACHE;
3949 std::vector<std::unique_ptr<Context>> context_list;
3950 const int kNumTransactions = 5;
3951 for (int i = 0; i < kNumTransactions; ++i) {
3952 context_list.push_back(std::make_unique<Context>());
3953 auto& c = context_list[i];
3954 c->result = cache.CreateTransaction(&c->trans);
3955 ASSERT_THAT(c->result, IsOk());
3956 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3957 c->result =
3958 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
3959 }
3960
3961 // All requests are waiting for the active entry.
3962 for (auto& context : context_list) {
3963 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
3964 }
3965
3966 // Allow all requests to move from the Create queue to the active entry.
3967 base::RunLoop().RunUntilIdle();
3968
3969 // The first request should be a writer at this point, and the subsequent
3970 // requests should have passed the validation phase and created their own
3971 // entries since none of them matched the headers of the earlier one.
3972 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
3973
3974 EXPECT_EQ(5, cache.network_layer()->transaction_count());
3975 EXPECT_EQ(0, cache.disk_cache()->open_count());
3976 EXPECT_EQ(5, cache.disk_cache()->create_count());
3977
3978 // All requests depend on the writer, and the writer is between Start and
3979 // Read, i.e. idle.
3980 for (auto& context : context_list) {
3981 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3982 }
3983
3984 for (auto& context : context_list) {
3985 if (context->result == ERR_IO_PENDING)
3986 context->result = context->callback.WaitForResult();
3987 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
3988 }
3989
3990 EXPECT_EQ(5, cache.network_layer()->transaction_count());
3991 EXPECT_EQ(0, cache.disk_cache()->open_count());
3992 EXPECT_EQ(5, cache.disk_cache()->create_count());
3993 }
3994
TEST_F(HttpCacheTest,RangeGET_Enormous)3995 TEST_F(HttpCacheTest, RangeGET_Enormous) {
3996 // Test for how blockfile's limit on range namespace interacts with
3997 // HttpCache::Transaction.
3998 // See https://crbug.com/770694
3999 base::ScopedTempDir temp_dir;
4000 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
4001
4002 auto backend_factory = std::make_unique<HttpCache::DefaultBackend>(
4003 DISK_CACHE, CACHE_BACKEND_BLOCKFILE,
4004 /*file_operations_factory=*/nullptr, temp_dir.GetPath(), 1024 * 1024,
4005 false);
4006 MockHttpCache cache(std::move(backend_factory));
4007
4008 RangeTransactionServer handler;
4009 handler.set_length(2305843009213693962);
4010
4011 // Prime with a range it can store.
4012 {
4013 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4014 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
4015 transaction.data = "rg: 00-09 ";
4016 MockHttpRequest request(transaction);
4017
4018 HttpResponseInfo response;
4019 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4020 &response);
4021 ASSERT_TRUE(response.headers != nullptr);
4022 EXPECT_EQ(206, response.headers->response_code());
4023 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4024 }
4025
4026 // Try with a range it can't. Should still work.
4027 {
4028 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4029 transaction.request_headers =
4030 "Range: bytes = "
4031 "2305843009213693952-2305843009213693961\r\n" EXTRA_HEADER;
4032 transaction.data = "rg: 52-61 ";
4033 MockHttpRequest request(transaction);
4034
4035 HttpResponseInfo response;
4036 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4037 &response);
4038 ASSERT_TRUE(response.headers != nullptr);
4039 EXPECT_EQ(206, response.headers->response_code());
4040 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4041 }
4042
4043 // Can't actually cache it due to backend limitations. If the network
4044 // transaction count is 2, this test isn't covering what it needs to.
4045 {
4046 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4047 transaction.request_headers =
4048 "Range: bytes = "
4049 "2305843009213693952-2305843009213693961\r\n" EXTRA_HEADER;
4050 transaction.data = "rg: 52-61 ";
4051 MockHttpRequest request(transaction);
4052
4053 HttpResponseInfo response;
4054 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4055 &response);
4056 ASSERT_TRUE(response.headers != nullptr);
4057 EXPECT_EQ(206, response.headers->response_code());
4058 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4059 }
4060 }
4061
4062 // Parallel validation results in 200 for 1 transaction and validation matches
4063 // for subsequent transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationNoMatch1)4064 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationNoMatch1) {
4065 MockHttpCache cache;
4066 MockHttpRequest request(kSimpleGET_Transaction);
4067
4068 MockTransaction transaction(kSimpleGET_Transaction);
4069 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4070 MockHttpRequest validate_request(transaction);
4071 std::vector<std::unique_ptr<Context>> context_list;
4072 const int kNumTransactions = 5;
4073 for (int i = 0; i < kNumTransactions; ++i) {
4074 context_list.push_back(std::make_unique<Context>());
4075 auto& c = context_list[i];
4076 c->result = cache.CreateTransaction(&c->trans);
4077 ASSERT_THAT(c->result, IsOk());
4078 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
4079
4080 MockHttpRequest* this_request = &request;
4081 if (i == 1)
4082 this_request = &validate_request;
4083
4084 c->result = c->trans->Start(this_request, c->callback.callback(),
4085 NetLogWithSource());
4086 }
4087
4088 // All requests are waiting for the active entry.
4089 for (auto& context : context_list) {
4090 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
4091 }
4092
4093 // Allow all requests to move from the Create queue to the active entry.
4094 base::RunLoop().RunUntilIdle();
4095
4096 // The new entry will have all the transactions except the first one which
4097 // will continue in the doomed entry.
4098 EXPECT_EQ(kNumTransactions - 1,
4099 cache.GetCountWriterTransactions(validate_request.CacheKey()));
4100
4101 EXPECT_EQ(1, cache.disk_cache()->doomed_count());
4102
4103 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4104 EXPECT_EQ(0, cache.disk_cache()->open_count());
4105 EXPECT_EQ(2, cache.disk_cache()->create_count());
4106
4107 for (auto& context : context_list) {
4108 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
4109 }
4110
4111 for (auto& context : context_list) {
4112 if (context->result == ERR_IO_PENDING)
4113 context->result = context->callback.WaitForResult();
4114
4115 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4116 }
4117
4118 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4119 EXPECT_EQ(0, cache.disk_cache()->open_count());
4120 EXPECT_EQ(2, cache.disk_cache()->create_count());
4121 }
4122
4123 // Tests that a GET followed by a DELETE results in DELETE immediately starting
4124 // the headers phase and the entry is doomed.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationDelete)4125 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationDelete) {
4126 MockHttpCache cache;
4127
4128 MockHttpRequest request(kSimpleGET_Transaction);
4129 request.load_flags |= LOAD_VALIDATE_CACHE;
4130
4131 MockHttpRequest delete_request(kSimpleGET_Transaction);
4132 delete_request.method = "DELETE";
4133
4134 std::vector<std::unique_ptr<Context>> context_list;
4135 const int kNumTransactions = 2;
4136
4137 for (int i = 0; i < kNumTransactions; ++i) {
4138 context_list.push_back(std::make_unique<Context>());
4139 auto& c = context_list[i];
4140
4141 MockHttpRequest* this_request = &request;
4142 if (i == 1)
4143 this_request = &delete_request;
4144
4145 c->result = cache.CreateTransaction(&c->trans);
4146 ASSERT_THAT(c->result, IsOk());
4147 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
4148
4149 c->result = c->trans->Start(this_request, c->callback.callback(),
4150 NetLogWithSource());
4151 }
4152
4153 // All requests are waiting for the active entry.
4154 for (auto& context : context_list) {
4155 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
4156 }
4157
4158 // Allow all requests to move from the Create queue to the active entry.
4159 base::RunLoop().RunUntilIdle();
4160
4161 // The first request should be a writer at this point, and the subsequent
4162 // request should have passed the validation phase and doomed the existing
4163 // entry.
4164 EXPECT_TRUE(cache.disk_cache()->IsDiskEntryDoomed(request.CacheKey()));
4165
4166 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4167 EXPECT_EQ(0, cache.disk_cache()->open_count());
4168 EXPECT_EQ(1, cache.disk_cache()->create_count());
4169
4170 // All requests depend on the writer, and the writer is between Start and
4171 // Read, i.e. idle.
4172 for (auto& context : context_list) {
4173 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
4174 }
4175
4176 for (auto& context : context_list) {
4177 if (context->result == ERR_IO_PENDING)
4178 context->result = context->callback.WaitForResult();
4179 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4180 }
4181
4182 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4183 EXPECT_EQ(0, cache.disk_cache()->open_count());
4184 EXPECT_EQ(1, cache.disk_cache()->create_count());
4185 }
4186
4187 // Tests that a transaction which is in validated queue can be destroyed without
4188 // any impact to other transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelValidated)4189 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelValidated) {
4190 MockHttpCache cache;
4191
4192 MockHttpRequest request(kSimpleGET_Transaction);
4193
4194 MockTransaction transaction(kSimpleGET_Transaction);
4195 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4196 MockHttpRequest read_only_request(transaction);
4197
4198 std::vector<std::unique_ptr<Context>> context_list;
4199 const int kNumTransactions = 2;
4200
4201 for (int i = 0; i < kNumTransactions; ++i) {
4202 context_list.push_back(std::make_unique<Context>());
4203 auto& c = context_list[i];
4204
4205 c->result = cache.CreateTransaction(&c->trans);
4206 ASSERT_THAT(c->result, IsOk());
4207
4208 MockHttpRequest* current_request = i == 1 ? &read_only_request : &request;
4209
4210 c->result = c->trans->Start(current_request, c->callback.callback(),
4211 NetLogWithSource());
4212 }
4213
4214 // Allow all requests to move from the Create queue to the active entry.
4215 base::RunLoop().RunUntilIdle();
4216
4217 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4218 EXPECT_EQ(0, cache.disk_cache()->open_count());
4219 EXPECT_EQ(1, cache.disk_cache()->create_count());
4220
4221 std::string cache_key = request.CacheKey();
4222 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4223 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4224
4225 context_list[1].reset();
4226
4227 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4228
4229 // Complete the rest of the transactions.
4230 for (auto& context : context_list) {
4231 if (!context)
4232 continue;
4233 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4234 }
4235
4236 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4237 EXPECT_EQ(0, cache.disk_cache()->open_count());
4238 EXPECT_EQ(1, cache.disk_cache()->create_count());
4239 }
4240
4241 // Tests that an idle writer transaction can be deleted without impacting the
4242 // existing writers.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingCancelIdleTransaction)4243 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingCancelIdleTransaction) {
4244 MockHttpCache cache;
4245
4246 MockHttpRequest request(kSimpleGET_Transaction);
4247
4248 std::vector<std::unique_ptr<Context>> context_list;
4249 const int kNumTransactions = 2;
4250
4251 for (int i = 0; i < kNumTransactions; ++i) {
4252 context_list.push_back(std::make_unique<Context>());
4253 auto& c = context_list[i];
4254
4255 c->result = cache.CreateTransaction(&c->trans);
4256 ASSERT_THAT(c->result, IsOk());
4257
4258 c->result =
4259 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4260 }
4261
4262 // Allow all requests to move from the Create queue to the active entry.
4263 base::RunLoop().RunUntilIdle();
4264
4265 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4266 EXPECT_EQ(0, cache.disk_cache()->open_count());
4267 EXPECT_EQ(1, cache.disk_cache()->create_count());
4268
4269 // Both transactions would be added to writers.
4270 std::string cache_key = request.CacheKey();
4271 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
4272
4273 context_list[1].reset();
4274
4275 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
4276
4277 // Complete the rest of the transactions.
4278 for (auto& context : context_list) {
4279 if (!context)
4280 continue;
4281 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4282 }
4283
4284 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4285 EXPECT_EQ(0, cache.disk_cache()->open_count());
4286 EXPECT_EQ(1, cache.disk_cache()->create_count());
4287 }
4288
4289 // Tests that a transaction which is in validated queue can timeout and start
4290 // the headers phase again.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationValidatedTimeout)4291 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationValidatedTimeout) {
4292 MockHttpCache cache;
4293
4294 MockHttpRequest request(kSimpleGET_Transaction);
4295
4296 MockTransaction transaction(kSimpleGET_Transaction);
4297 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4298 MockHttpRequest read_only_request(transaction);
4299
4300 std::vector<std::unique_ptr<Context>> context_list;
4301 const int kNumTransactions = 2;
4302
4303 for (int i = 0; i < kNumTransactions; ++i) {
4304 context_list.push_back(std::make_unique<Context>());
4305 auto& c = context_list[i];
4306
4307 MockHttpRequest* this_request = &request;
4308 if (i == 1) {
4309 this_request = &read_only_request;
4310 cache.SimulateCacheLockTimeoutAfterHeaders();
4311 }
4312
4313 c->result = cache.CreateTransaction(&c->trans);
4314 ASSERT_THAT(c->result, IsOk());
4315
4316 c->result = c->trans->Start(this_request, c->callback.callback(),
4317 NetLogWithSource());
4318 }
4319
4320 // Allow all requests to move from the Create queue to the active entry.
4321 base::RunLoop().RunUntilIdle();
4322
4323 // The first request should be a writer at this point, and the subsequent
4324 // requests should have completed validation, timed out and restarted.
4325 // Since it is a read only request, it will error out.
4326
4327 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4328 EXPECT_EQ(0, cache.disk_cache()->open_count());
4329 EXPECT_EQ(1, cache.disk_cache()->create_count());
4330
4331 std::string cache_key = request.CacheKey();
4332 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
4333 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4334
4335 base::RunLoop().RunUntilIdle();
4336
4337 int rv = context_list[1]->callback.WaitForResult();
4338 EXPECT_EQ(ERR_CACHE_MISS, rv);
4339
4340 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4341 kSimpleGET_Transaction);
4342 }
4343
4344 // Tests that a transaction which is in readers can be destroyed without
4345 // any impact to other transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelReader)4346 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelReader) {
4347 MockHttpCache cache;
4348
4349 MockHttpRequest request(kSimpleGET_Transaction);
4350
4351 MockTransaction transaction(kSimpleGET_Transaction);
4352 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4353 MockHttpRequest validate_request(transaction);
4354
4355 int kNumTransactions = 4;
4356 std::vector<std::unique_ptr<Context>> context_list;
4357
4358 for (int i = 0; i < kNumTransactions; ++i) {
4359 context_list.push_back(std::make_unique<Context>());
4360 auto& c = context_list[i];
4361
4362 c->result = cache.CreateTransaction(&c->trans);
4363 ASSERT_THAT(c->result, IsOk());
4364
4365 MockHttpRequest* this_request = &request;
4366 if (i == 3) {
4367 this_request = &validate_request;
4368 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
4369 }
4370
4371 c->result = c->trans->Start(this_request, c->callback.callback(),
4372 NetLogWithSource());
4373 }
4374
4375 // Allow all requests to move from the Create queue to the active entry.
4376 base::RunLoop().RunUntilIdle();
4377
4378 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4379 EXPECT_EQ(0, cache.disk_cache()->open_count());
4380 EXPECT_EQ(1, cache.disk_cache()->create_count());
4381
4382 std::string cache_key = request.CacheKey();
4383
4384 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
4385 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4386
4387 // Complete the response body.
4388 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4389 kSimpleGET_Transaction);
4390
4391 // Rest of the transactions should move to readers.
4392 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
4393 EXPECT_EQ(kNumTransactions - 2, cache.GetCountReaders(cache_key));
4394 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4395 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4396
4397 // Add 2 new transactions.
4398 kNumTransactions = 6;
4399
4400 for (int i = 4; i < kNumTransactions; ++i) {
4401 context_list.push_back(std::make_unique<Context>());
4402 auto& c = context_list[i];
4403
4404 c->result = cache.CreateTransaction(&c->trans);
4405 ASSERT_THAT(c->result, IsOk());
4406
4407 c->result =
4408 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4409 }
4410
4411 EXPECT_EQ(2, cache.GetCountAddToEntryQueue(cache_key));
4412
4413 // Delete a reader.
4414 context_list[1].reset();
4415
4416 // Deleting the reader did not impact any other transaction.
4417 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
4418 EXPECT_EQ(2, cache.GetCountAddToEntryQueue(cache_key));
4419 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4420
4421 // Resume network start for headers_transaction. It will doom the entry as it
4422 // will be a 200 and will go to network for the response body.
4423 context_list[3]->trans->ResumeNetworkStart();
4424
4425 // The pending transactions will be added to a new entry as writers.
4426 base::RunLoop().RunUntilIdle();
4427
4428 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4429
4430 // Complete the rest of the transactions.
4431 for (int i = 2; i < kNumTransactions; ++i) {
4432 ReadAndVerifyTransaction(context_list[i]->trans.get(),
4433 kSimpleGET_Transaction);
4434 }
4435
4436 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4437 EXPECT_EQ(0, cache.disk_cache()->open_count());
4438 EXPECT_EQ(2, cache.disk_cache()->create_count());
4439 }
4440
4441 // Tests that when the only writer goes away, it immediately cleans up rather
4442 // than wait for the network request to finish. See https://crbug.com/804868.
TEST_F(HttpCacheTest,SimpleGET_HangingCacheWriteCleanup)4443 TEST_F(HttpCacheTest, SimpleGET_HangingCacheWriteCleanup) {
4444 MockHttpCache mock_cache;
4445 MockHttpRequest request(kSimpleGET_Transaction);
4446
4447 std::unique_ptr<HttpTransaction> transaction;
4448 mock_cache.CreateTransaction(&transaction);
4449 TestCompletionCallback callback;
4450 int result =
4451 transaction->Start(&request, callback.callback(), NetLogWithSource());
4452
4453 // Get the transaction ready to read.
4454 result = callback.GetResult(result);
4455
4456 // Read the first byte.
4457 auto buffer = base::MakeRefCounted<IOBufferWithSize>(1);
4458 ReleaseBufferCompletionCallback buffer_callback(buffer.get());
4459 result = transaction->Read(buffer.get(), 1, buffer_callback.callback());
4460 EXPECT_EQ(1, buffer_callback.GetResult(result));
4461
4462 // Read the second byte, but leave the cache write hanging.
4463 std::string cache_key = request.CacheKey();
4464 scoped_refptr<MockDiskEntry> entry =
4465 mock_cache.disk_cache()->GetDiskEntryRef(cache_key);
4466 entry->SetDefer(MockDiskEntry::DEFER_WRITE);
4467
4468 buffer = base::MakeRefCounted<IOBufferWithSize>(1);
4469 ReleaseBufferCompletionCallback buffer_callback2(buffer.get());
4470 result = transaction->Read(buffer.get(), 1, buffer_callback2.callback());
4471 EXPECT_EQ(ERR_IO_PENDING, result);
4472 base::RunLoop().RunUntilIdle();
4473 EXPECT_TRUE(mock_cache.IsWriterPresent(cache_key));
4474
4475 // At this point the next byte should have been read from the network but is
4476 // waiting to be written to the cache. Destroy the transaction and make sure
4477 // that everything has been cleaned up.
4478 transaction = nullptr;
4479 EXPECT_FALSE(mock_cache.IsWriterPresent(cache_key));
4480 EXPECT_FALSE(mock_cache.network_layer()->last_transaction());
4481 }
4482
4483 // Tests that a transaction writer can be destroyed mid-read.
4484 // A waiting for read transaction should be able to read the data that was
4485 // driven by the Read started by the cancelled writer.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingCancelWriter)4486 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingCancelWriter) {
4487 MockHttpCache cache;
4488
4489 MockHttpRequest request(kSimpleGET_Transaction);
4490
4491 MockTransaction transaction(kSimpleGET_Transaction);
4492 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4493 MockHttpRequest validate_request(transaction);
4494
4495 const int kNumTransactions = 3;
4496 std::vector<std::unique_ptr<Context>> context_list;
4497
4498 for (int i = 0; i < kNumTransactions; ++i) {
4499 context_list.push_back(std::make_unique<Context>());
4500 auto& c = context_list[i];
4501
4502 c->result = cache.CreateTransaction(&c->trans);
4503 ASSERT_THAT(c->result, IsOk());
4504
4505 MockHttpRequest* this_request = &request;
4506 if (i == 2) {
4507 this_request = &validate_request;
4508 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
4509 }
4510
4511 c->result = c->trans->Start(this_request, c->callback.callback(),
4512 NetLogWithSource());
4513 }
4514
4515 // Allow all requests to move from the Create queue to the active entry.
4516 base::RunLoop().RunUntilIdle();
4517
4518 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4519 EXPECT_EQ(0, cache.disk_cache()->open_count());
4520 EXPECT_EQ(1, cache.disk_cache()->create_count());
4521
4522 std::string cache_key = validate_request.CacheKey();
4523 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4524 EXPECT_EQ(2, cache.GetCountWriterTransactions(cache_key));
4525
4526 // Initiate Read from both writers and kill 1 of them mid-read.
4527 std::string first_read;
4528 for (int i = 0; i < 2; i++) {
4529 auto& c = context_list[i];
4530 const int kBufferSize = 5;
4531 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
4532 ReleaseBufferCompletionCallback cb(buffer.get());
4533 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
4534 EXPECT_EQ(ERR_IO_PENDING, c->result);
4535 // Deleting one writer at this point will not impact other transactions
4536 // since writers contain more transactions.
4537 if (i == 1) {
4538 context_list[0].reset();
4539 base::RunLoop().RunUntilIdle();
4540 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
4541 std::string data_read(buffer->data(), kBufferSize);
4542 first_read = data_read;
4543 }
4544 }
4545
4546 // Resume network start for headers_transaction. It will doom the existing
4547 // entry and create a new entry due to validation returning a 200.
4548 auto& c = context_list[2];
4549 c->trans->ResumeNetworkStart();
4550
4551 base::RunLoop().RunUntilIdle();
4552
4553 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4554
4555 // Complete the rest of the transactions.
4556 for (int i = 0; i < kNumTransactions; i++) {
4557 auto& context = context_list[i];
4558 if (!context)
4559 continue;
4560 if (i == 1)
4561 ReadRemainingAndVerifyTransaction(context->trans.get(), first_read,
4562 kSimpleGET_Transaction);
4563 else
4564 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4565 }
4566
4567 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4568 EXPECT_EQ(0, cache.disk_cache()->open_count());
4569 EXPECT_EQ(2, cache.disk_cache()->create_count());
4570 }
4571
4572 // Tests the case when network read failure happens. Idle and waiting
4573 // transactions should fail and headers transaction should be restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingNetworkReadFailed)4574 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingNetworkReadFailed) {
4575 MockHttpCache cache;
4576
4577 ScopedMockTransaction fail_transaction(kSimpleGET_Transaction);
4578 fail_transaction.read_return_code = ERR_INTERNET_DISCONNECTED;
4579 MockHttpRequest failing_request(fail_transaction);
4580
4581 MockHttpRequest request(kSimpleGET_Transaction);
4582
4583 MockTransaction transaction(kSimpleGET_Transaction);
4584 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4585 MockHttpRequest read_request(transaction);
4586
4587 const int kNumTransactions = 4;
4588 std::vector<std::unique_ptr<Context>> context_list;
4589
4590 for (int i = 0; i < kNumTransactions; ++i) {
4591 context_list.push_back(std::make_unique<Context>());
4592 auto& c = context_list[i];
4593
4594 c->result = cache.CreateTransaction(&c->trans);
4595 ASSERT_THAT(c->result, IsOk());
4596
4597 MockHttpRequest* this_request = &request;
4598 if (i == 0)
4599 this_request = &failing_request;
4600 if (i == 3)
4601 this_request = &read_request;
4602
4603 c->result = c->trans->Start(this_request, c->callback.callback(),
4604 NetLogWithSource());
4605 }
4606
4607 // Allow all requests to move from the Create queue to the active entry.
4608 base::RunLoop().RunUntilIdle();
4609
4610 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4611 EXPECT_EQ(0, cache.disk_cache()->open_count());
4612 EXPECT_EQ(1, cache.disk_cache()->create_count());
4613
4614 std::string cache_key = read_request.CacheKey();
4615 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4616 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4617
4618 // Initiate Read from two writers and let the first get a network failure.
4619 for (int i = 0; i < 2; i++) {
4620 auto& c = context_list[i];
4621 const int kBufferSize = 5;
4622 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
4623 c->result =
4624 c->trans->Read(buffer.get(), kBufferSize, c->callback.callback());
4625 EXPECT_EQ(ERR_IO_PENDING, c->result);
4626 }
4627
4628 base::RunLoop().RunUntilIdle();
4629 for (int i = 0; i < 2; i++) {
4630 auto& c = context_list[i];
4631 c->result = c->callback.WaitForResult();
4632 EXPECT_EQ(ERR_INTERNET_DISCONNECTED, c->result);
4633 }
4634
4635 // The entry should have been doomed and destroyed and the headers transaction
4636 // restarted. Since headers transaction is read-only it will error out.
4637 auto& read_only = context_list[3];
4638 read_only->result = read_only->callback.WaitForResult();
4639 EXPECT_EQ(ERR_CACHE_MISS, read_only->result);
4640
4641 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
4642
4643 // Invoke Read on the 3rd transaction and it should get the error code back.
4644 auto& c = context_list[2];
4645 const int kBufferSize = 5;
4646 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
4647 c->result = c->trans->Read(buffer.get(), kBufferSize, c->callback.callback());
4648 EXPECT_EQ(ERR_INTERNET_DISCONNECTED, c->result);
4649 }
4650
4651 // Tests the case when cache write failure happens. Idle and waiting
4652 // transactions should fail and headers transaction should be restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingCacheWriteFailed)4653 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingCacheWriteFailed) {
4654 MockHttpCache cache;
4655
4656 MockHttpRequest request(kSimpleGET_Transaction);
4657
4658 MockTransaction transaction(kSimpleGET_Transaction);
4659 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4660 MockHttpRequest read_request(transaction);
4661
4662 const int kNumTransactions = 4;
4663 std::vector<std::unique_ptr<Context>> context_list;
4664
4665 for (int i = 0; i < kNumTransactions; ++i) {
4666 context_list.push_back(std::make_unique<Context>());
4667 auto& c = context_list[i];
4668
4669 c->result = cache.CreateTransaction(&c->trans);
4670 ASSERT_THAT(c->result, IsOk());
4671
4672 MockHttpRequest* this_request = &request;
4673 if (i == 3)
4674 this_request = &read_request;
4675
4676 c->result = c->trans->Start(this_request, c->callback.callback(),
4677 NetLogWithSource());
4678 }
4679
4680 // Allow all requests to move from the Create queue to the active entry.
4681 base::RunLoop().RunUntilIdle();
4682
4683 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4684 EXPECT_EQ(0, cache.disk_cache()->open_count());
4685 EXPECT_EQ(1, cache.disk_cache()->create_count());
4686
4687 std::string cache_key = read_request.CacheKey();
4688 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4689 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4690
4691 // Initiate Read from two writers and let the first get a cache write failure.
4692 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
4693 // We have to open the entry again to propagate the failure flag.
4694 disk_cache::Entry* en;
4695 cache.OpenBackendEntry(cache_key, &en);
4696 en->Close();
4697 const int kBufferSize = 5;
4698 std::vector<scoped_refptr<IOBuffer>> buffer(
4699 3, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
4700 for (int i = 0; i < 2; i++) {
4701 auto& c = context_list[i];
4702 c->result =
4703 c->trans->Read(buffer[i].get(), kBufferSize, c->callback.callback());
4704 EXPECT_EQ(ERR_IO_PENDING, c->result);
4705 }
4706
4707 std::string first_read;
4708 base::RunLoop().RunUntilIdle();
4709 for (int i = 0; i < 2; i++) {
4710 auto& c = context_list[i];
4711 c->result = c->callback.WaitForResult();
4712 if (i == 0) {
4713 EXPECT_EQ(5, c->result);
4714 std::string data_read(buffer[i]->data(), kBufferSize);
4715 first_read = data_read;
4716 } else {
4717 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, c->result);
4718 }
4719 }
4720
4721 // The entry should have been doomed and destroyed and the headers transaction
4722 // restarted. Since headers transaction is read-only it will error out.
4723 auto& read_only = context_list[3];
4724 read_only->result = read_only->callback.WaitForResult();
4725 EXPECT_EQ(ERR_CACHE_MISS, read_only->result);
4726
4727 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
4728
4729 // Invoke Read on the 3rd transaction and it should get the error code back.
4730 auto& c = context_list[2];
4731 c->result =
4732 c->trans->Read(buffer[2].get(), kBufferSize, c->callback.callback());
4733 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, c->result);
4734
4735 // The first transaction should be able to continue to read from the network
4736 // without writing to the cache.
4737 auto& succ_read = context_list[0];
4738 ReadRemainingAndVerifyTransaction(succ_read->trans.get(), first_read,
4739 kSimpleGET_Transaction);
4740 }
4741
4742 // Tests that POST requests do not join existing transactions for parallel
4743 // writing to the cache. Note that two POSTs only map to the same entry if their
4744 // upload data identifier is same and that should happen for back-forward case
4745 // (LOAD_ONLY_FROM_CACHE). But this test tests without LOAD_ONLY_FROM_CACHE
4746 // because read-only transactions anyways do not join parallel writing.
4747 // TODO(shivanisha) Testing this because it is allowed by the code but looks
4748 // like the code should disallow two POSTs without LOAD_ONLY_FROM_CACHE with the
4749 // same upload data identifier to map to the same entry.
TEST_F(HttpCacheTest,SimplePOST_ParallelWritingDisallowed)4750 TEST_F(HttpCacheTest, SimplePOST_ParallelWritingDisallowed) {
4751 MockHttpCache cache;
4752
4753 MockTransaction transaction(kSimplePOST_Transaction);
4754
4755 const int64_t kUploadId = 1; // Just a dummy value.
4756
4757 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
4758 element_readers.push_back(
4759 std::make_unique<UploadBytesElementReader>("hello", 5));
4760 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
4761 kUploadId);
4762
4763 // Note that both transactions should have the same upload_data_stream
4764 // identifier to map to the same entry.
4765 transaction.load_flags = LOAD_SKIP_CACHE_VALIDATION;
4766 MockHttpRequest request(transaction);
4767 request.upload_data_stream = &upload_data_stream;
4768
4769 const int kNumTransactions = 2;
4770 std::vector<std::unique_ptr<Context>> context_list;
4771
4772 for (int i = 0; i < kNumTransactions; ++i) {
4773 context_list.push_back(std::make_unique<Context>());
4774 auto& c = context_list[i];
4775
4776 c->result = cache.CreateTransaction(&c->trans);
4777 ASSERT_THAT(c->result, IsOk());
4778
4779 c->result =
4780 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4781
4782 // Complete the headers phase request.
4783 base::RunLoop().RunUntilIdle();
4784 }
4785
4786 std::string cache_key = request.CacheKey();
4787 // Only the 1st transaction gets added to writers.
4788 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4789 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4790
4791 // Read the 1st transaction.
4792 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4793 kSimplePOST_Transaction);
4794
4795 // 2nd transaction should now become a reader.
4796 base::RunLoop().RunUntilIdle();
4797 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
4798 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4799 ReadAndVerifyTransaction(context_list[1]->trans.get(),
4800 kSimplePOST_Transaction);
4801
4802 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4803 EXPECT_EQ(0, cache.disk_cache()->open_count());
4804 EXPECT_EQ(1, cache.disk_cache()->create_count());
4805
4806 context_list.clear();
4807 }
4808
4809 // Tests the case when parallel writing succeeds. Tests both idle and waiting
4810 // transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingSuccess)4811 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingSuccess) {
4812 MockHttpCache cache;
4813
4814 MockHttpRequest request(kSimpleGET_Transaction);
4815
4816 MockTransaction transaction(kSimpleGET_Transaction);
4817 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4818 MockHttpRequest read_request(transaction);
4819
4820 const int kNumTransactions = 4;
4821 std::vector<std::unique_ptr<Context>> context_list;
4822
4823 for (int i = 0; i < kNumTransactions; ++i) {
4824 context_list.push_back(std::make_unique<Context>());
4825 auto& c = context_list[i];
4826
4827 c->result = cache.CreateTransaction(&c->trans);
4828 ASSERT_THAT(c->result, IsOk());
4829
4830 MockHttpRequest* this_request = &request;
4831 if (i == 3)
4832 this_request = &read_request;
4833
4834 c->result = c->trans->Start(this_request, c->callback.callback(),
4835 NetLogWithSource());
4836 }
4837
4838 // Allow all requests to move from the Create queue to the active entry.
4839 base::RunLoop().RunUntilIdle();
4840
4841 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4842 EXPECT_EQ(0, cache.disk_cache()->open_count());
4843 EXPECT_EQ(1, cache.disk_cache()->create_count());
4844
4845 std::string cache_key = request.CacheKey();
4846 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4847 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4848
4849 // Initiate Read from two writers.
4850 const int kBufferSize = 5;
4851 std::vector<scoped_refptr<IOBuffer>> buffer(
4852 3, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
4853 for (int i = 0; i < 2; i++) {
4854 auto& c = context_list[i];
4855 c->result =
4856 c->trans->Read(buffer[i].get(), kBufferSize, c->callback.callback());
4857 EXPECT_EQ(ERR_IO_PENDING, c->result);
4858 }
4859
4860 std::vector<std::string> first_read(2);
4861 base::RunLoop().RunUntilIdle();
4862 for (int i = 0; i < 2; i++) {
4863 auto& c = context_list[i];
4864 c->result = c->callback.WaitForResult();
4865 EXPECT_EQ(5, c->result);
4866 std::string data_read(buffer[i]->data(), kBufferSize);
4867 first_read[i] = data_read;
4868 }
4869 EXPECT_EQ(first_read[0], first_read[1]);
4870
4871 // The first transaction should be able to continue to read from the network
4872 // without writing to the cache.
4873 for (int i = 0; i < 2; i++) {
4874 auto& c = context_list[i];
4875 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read[i],
4876 kSimpleGET_Transaction);
4877 if (i == 0) {
4878 // Remaining transactions should now be readers.
4879 EXPECT_EQ(3, cache.GetCountReaders(cache_key));
4880 }
4881 }
4882
4883 // Verify the rest of the transactions.
4884 for (int i = 2; i < kNumTransactions; i++) {
4885 auto& c = context_list[i];
4886 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
4887 }
4888
4889 context_list.clear();
4890 }
4891
4892 // Tests the case when parallel writing involves things bigger than what cache
4893 // can store. In this case, the best we can do is re-fetch it.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingHuge)4894 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingHuge) {
4895 MockHttpCache cache;
4896 cache.disk_cache()->set_max_file_size(10);
4897
4898 MockTransaction transaction(kSimpleGET_Transaction);
4899 std::string response_headers = base::StrCat(
4900 {kSimpleGET_Transaction.response_headers, "Content-Length: ",
4901 base::NumberToString(strlen(kSimpleGET_Transaction.data)), "\n"});
4902 transaction.response_headers = response_headers.c_str();
4903 AddMockTransaction(&transaction);
4904 MockHttpRequest request(transaction);
4905
4906 const int kNumTransactions = 4;
4907 std::vector<std::unique_ptr<Context>> context_list;
4908
4909 for (int i = 0; i < kNumTransactions; ++i) {
4910 context_list.push_back(std::make_unique<Context>());
4911 auto& c = context_list[i];
4912
4913 c->result = cache.CreateTransaction(&c->trans);
4914 ASSERT_THAT(c->result, IsOk());
4915
4916 MockHttpRequest* this_request = &request;
4917 c->result = c->trans->Start(this_request, c->callback.callback(),
4918 NetLogWithSource());
4919 }
4920
4921 // Start them up.
4922 base::RunLoop().RunUntilIdle();
4923
4924 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4925 EXPECT_EQ(0, cache.disk_cache()->open_count());
4926 EXPECT_EQ(1, cache.disk_cache()->create_count());
4927
4928 std::string cache_key = request.CacheKey();
4929 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4930 EXPECT_EQ(kNumTransactions - 1, cache.GetCountDoneHeadersQueue(cache_key));
4931
4932 // Initiate Read from first transaction.
4933 const int kBufferSize = 5;
4934 std::vector<scoped_refptr<IOBuffer>> buffer(
4935 kNumTransactions, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
4936 auto& c = context_list[0];
4937 c->result =
4938 c->trans->Read(buffer[0].get(), kBufferSize, c->callback.callback());
4939 EXPECT_EQ(ERR_IO_PENDING, c->result);
4940
4941 // ... and complete it.
4942 std::vector<std::string> first_read(kNumTransactions);
4943 base::RunLoop().RunUntilIdle();
4944 c->result = c->callback.WaitForResult();
4945 EXPECT_EQ(kBufferSize, c->result);
4946 std::string data_read(buffer[0]->data(), kBufferSize);
4947 first_read[0] = data_read;
4948 EXPECT_EQ("<html", first_read[0]);
4949
4950 // Complete all of them.
4951 for (int i = 0; i < kNumTransactions; i++) {
4952 ReadRemainingAndVerifyTransaction(context_list[i]->trans.get(),
4953 first_read[i], kSimpleGET_Transaction);
4954 }
4955
4956 // Sadly all of them have to hit the network
4957 EXPECT_EQ(kNumTransactions, cache.network_layer()->transaction_count());
4958
4959 context_list.clear();
4960 RemoveMockTransaction(&transaction);
4961 }
4962
4963 // Tests that network transaction's info is saved correctly when a writer
4964 // transaction that created the network transaction becomes a reader. Also
4965 // verifies that the network bytes are only attributed to the transaction that
4966 // created the network transaction.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingVerifyNetworkBytes)4967 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingVerifyNetworkBytes) {
4968 MockHttpCache cache;
4969
4970 MockHttpRequest request(kSimpleGET_Transaction);
4971
4972 const int kNumTransactions = 2;
4973 std::vector<std::unique_ptr<Context>> context_list;
4974
4975 for (int i = 0; i < kNumTransactions; ++i) {
4976 context_list.push_back(std::make_unique<Context>());
4977 auto& c = context_list[i];
4978
4979 c->result = cache.CreateTransaction(&c->trans);
4980 ASSERT_THAT(c->result, IsOk());
4981
4982 c->result =
4983 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4984 }
4985
4986 // Allow all requests to move from the Create queue to the active entry.
4987 base::RunLoop().RunUntilIdle();
4988
4989 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4990 EXPECT_EQ(0, cache.disk_cache()->open_count());
4991 EXPECT_EQ(1, cache.disk_cache()->create_count());
4992
4993 std::string cache_key = request.CacheKey();
4994 EXPECT_EQ(2, cache.GetCountWriterTransactions(cache_key));
4995 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4996
4997 // Get the network bytes read by the first transaction.
4998 int total_received_bytes = context_list[0]->trans->GetTotalReceivedBytes();
4999 EXPECT_GT(total_received_bytes, 0);
5000
5001 // Complete Read by the 2nd transaction so that the 1st transaction that
5002 // created the network transaction is now a reader.
5003 ReadAndVerifyTransaction(context_list[1]->trans.get(),
5004 kSimpleGET_Transaction);
5005
5006 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
5007
5008 // Verify that the network bytes read are not attributed to the 2nd
5009 // transaction but to the 1st.
5010 EXPECT_EQ(0, context_list[1]->trans->GetTotalReceivedBytes());
5011
5012 EXPECT_GE(total_received_bytes,
5013 context_list[0]->trans->GetTotalReceivedBytes());
5014
5015 ReadAndVerifyTransaction(context_list[0]->trans.get(),
5016 kSimpleGET_Transaction);
5017 }
5018
5019 // Tests than extra Read from the consumer should not hang/crash the browser.
TEST_F(HttpCacheTest,SimpleGET_ExtraRead)5020 TEST_F(HttpCacheTest, SimpleGET_ExtraRead) {
5021 MockHttpCache cache;
5022 MockHttpRequest request(kSimpleGET_Transaction);
5023 Context c;
5024
5025 c.result = cache.CreateTransaction(&c.trans);
5026 ASSERT_THAT(c.result, IsOk());
5027
5028 c.result =
5029 c.trans->Start(&request, c.callback.callback(), NetLogWithSource());
5030
5031 base::RunLoop().RunUntilIdle();
5032
5033 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5034 EXPECT_EQ(0, cache.disk_cache()->open_count());
5035 EXPECT_EQ(1, cache.disk_cache()->create_count());
5036
5037 std::string cache_key = request.CacheKey();
5038 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
5039 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
5040
5041 ReadAndVerifyTransaction(c.trans.get(), kSimpleGET_Transaction);
5042
5043 // Perform an extra Read.
5044 const int kBufferSize = 10;
5045 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
5046 c.result = c.trans->Read(buffer.get(), kBufferSize, c.callback.callback());
5047 EXPECT_EQ(0, c.result);
5048 }
5049
5050 // Tests when a writer is destroyed mid-read, all the other writer transactions
5051 // can continue writing to the entry.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelWriter)5052 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelWriter) {
5053 MockHttpCache cache;
5054
5055 ScopedMockTransaction transaction(kSimpleGET_Transaction);
5056 transaction.response_headers =
5057 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
5058 "Content-Length: 22\n"
5059 "Etag: \"foopy\"\n";
5060 MockHttpRequest request(transaction);
5061
5062 const int kNumTransactions = 3;
5063 std::vector<std::unique_ptr<Context>> context_list;
5064
5065 for (int i = 0; i < kNumTransactions; ++i) {
5066 context_list.push_back(std::make_unique<Context>());
5067 auto& c = context_list[i];
5068
5069 c->result = cache.CreateTransaction(&c->trans);
5070 ASSERT_THAT(c->result, IsOk());
5071
5072 c->result =
5073 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5074 }
5075
5076 // Allow all requests to move from the Create queue to the active entry.
5077 base::RunLoop().RunUntilIdle();
5078
5079 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5080 EXPECT_EQ(0, cache.disk_cache()->open_count());
5081 EXPECT_EQ(1, cache.disk_cache()->create_count());
5082
5083 std::string cache_key = request.CacheKey();
5084 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
5085
5086 // Let first transaction read some bytes.
5087 {
5088 auto& c = context_list[0];
5089 const int kBufferSize = 5;
5090 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
5091 ReleaseBufferCompletionCallback cb(buffer.get());
5092 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
5093 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
5094 }
5095
5096 // Deleting the active transaction at this point will not impact the other
5097 // transactions since there are other transactions in writers.
5098 context_list[0].reset();
5099
5100 base::RunLoop().RunUntilIdle();
5101
5102 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5103 EXPECT_EQ(0, cache.disk_cache()->open_count());
5104 EXPECT_EQ(1, cache.disk_cache()->create_count());
5105
5106 // Complete the rest of the transactions.
5107 for (auto& context : context_list) {
5108 if (!context)
5109 continue;
5110 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
5111 }
5112 }
5113
5114 // Tests that when StopCaching is invoked on a writer, dependent transactions
5115 // are restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationStopCaching)5116 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationStopCaching) {
5117 MockHttpCache cache;
5118
5119 MockHttpRequest request(kSimpleGET_Transaction);
5120
5121 MockTransaction transaction(kSimpleGET_Transaction);
5122 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
5123 MockHttpRequest read_only_request(transaction);
5124
5125 const int kNumTransactions = 2;
5126 std::vector<std::unique_ptr<Context>> context_list;
5127
5128 for (int i = 0; i < kNumTransactions; ++i) {
5129 context_list.push_back(std::make_unique<Context>());
5130 auto& c = context_list[i];
5131
5132 c->result = cache.CreateTransaction(&c->trans);
5133 ASSERT_THAT(c->result, IsOk());
5134
5135 MockHttpRequest* this_request = &request;
5136 if (i == 1) {
5137 this_request = &read_only_request;
5138 }
5139
5140 c->result = c->trans->Start(this_request, c->callback.callback(),
5141 NetLogWithSource());
5142 }
5143
5144 // Allow all requests to move from the Create queue to the active entry.
5145 base::RunLoop().RunUntilIdle();
5146
5147 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5148 EXPECT_EQ(0, cache.disk_cache()->open_count());
5149 EXPECT_EQ(1, cache.disk_cache()->create_count());
5150
5151 std::string cache_key = request.CacheKey();
5152 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
5153 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
5154
5155 // Invoking StopCaching on the writer will lead to dooming the entry and
5156 // restarting the validated transactions. Since it is a read-only transaction
5157 // it will error out.
5158 context_list[0]->trans->StopCaching();
5159
5160 base::RunLoop().RunUntilIdle();
5161
5162 int rv = context_list[1]->callback.WaitForResult();
5163 EXPECT_EQ(ERR_CACHE_MISS, rv);
5164
5165 ReadAndVerifyTransaction(context_list[0]->trans.get(),
5166 kSimpleGET_Transaction);
5167 }
5168
5169 // Tests that when StopCaching is invoked on a writer transaction, it is a
5170 // no-op if there are other writer transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritersStopCachingNoOp)5171 TEST_F(HttpCacheTest, SimpleGET_ParallelWritersStopCachingNoOp) {
5172 MockHttpCache cache;
5173
5174 MockHttpRequest request(kSimpleGET_Transaction);
5175
5176 MockTransaction transaction(kSimpleGET_Transaction);
5177 transaction.load_flags |= LOAD_VALIDATE_CACHE;
5178 MockHttpRequest validate_request(transaction);
5179
5180 const int kNumTransactions = 3;
5181 std::vector<std::unique_ptr<Context>> context_list;
5182
5183 for (int i = 0; i < kNumTransactions; ++i) {
5184 context_list.push_back(std::make_unique<Context>());
5185 auto& c = context_list[i];
5186
5187 c->result = cache.CreateTransaction(&c->trans);
5188 ASSERT_THAT(c->result, IsOk());
5189
5190 MockHttpRequest* this_request = &request;
5191 if (i == 2) {
5192 this_request = &validate_request;
5193 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
5194 }
5195
5196 c->result = c->trans->Start(this_request, c->callback.callback(),
5197 NetLogWithSource());
5198 }
5199
5200 // Allow all requests to move from the Create queue to the active entry.
5201 base::RunLoop().RunUntilIdle();
5202
5203 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5204 EXPECT_EQ(0, cache.disk_cache()->open_count());
5205 EXPECT_EQ(1, cache.disk_cache()->create_count());
5206
5207 std::string cache_key = request.CacheKey();
5208 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
5209 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
5210
5211 // Invoking StopCaching on the writer will be a no-op since there are multiple
5212 // transaction in writers.
5213 context_list[0]->trans->StopCaching();
5214
5215 // Resume network start for headers_transaction.
5216 auto& c = context_list[2];
5217 c->trans->ResumeNetworkStart();
5218 base::RunLoop().RunUntilIdle();
5219 // After validation old entry will be doomed and headers_transaction will be
5220 // added to the new entry.
5221 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
5222
5223 // Complete the rest of the transactions.
5224 for (auto& context : context_list) {
5225 if (!context)
5226 continue;
5227 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
5228 }
5229
5230 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5231 EXPECT_EQ(0, cache.disk_cache()->open_count());
5232 EXPECT_EQ(2, cache.disk_cache()->create_count());
5233 }
5234
5235 // Tests that a transaction is currently in headers phase and is destroyed
5236 // leading to destroying the entry.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelHeaders)5237 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelHeaders) {
5238 MockHttpCache cache;
5239
5240 MockHttpRequest request(kSimpleGET_Transaction);
5241
5242 const int kNumTransactions = 2;
5243 std::vector<std::unique_ptr<Context>> context_list;
5244
5245 for (int i = 0; i < kNumTransactions; ++i) {
5246 context_list.push_back(std::make_unique<Context>());
5247 auto& c = context_list[i];
5248
5249 c->result = cache.CreateTransaction(&c->trans);
5250 ASSERT_THAT(c->result, IsOk());
5251
5252 if (i == 0)
5253 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
5254
5255 c->result =
5256 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5257 }
5258
5259 base::RunLoop().RunUntilIdle();
5260
5261 std::string cache_key = request.CacheKey();
5262 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
5263 EXPECT_EQ(1, cache.GetCountAddToEntryQueue(cache_key));
5264
5265 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5266 EXPECT_EQ(0, cache.disk_cache()->open_count());
5267 EXPECT_EQ(1, cache.disk_cache()->create_count());
5268
5269 // Delete the headers transaction.
5270 context_list[0].reset();
5271
5272 base::RunLoop().RunUntilIdle();
5273
5274 // Complete the rest of the transactions.
5275 for (auto& context : context_list) {
5276 if (!context)
5277 continue;
5278 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
5279 }
5280
5281 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5282 EXPECT_EQ(0, cache.disk_cache()->open_count());
5283 EXPECT_EQ(2, cache.disk_cache()->create_count());
5284 }
5285
5286 // Similar to the above test, except here cache write fails and the
5287 // validated transactions should be restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritersFailWrite)5288 TEST_F(HttpCacheTest, SimpleGET_ParallelWritersFailWrite) {
5289 MockHttpCache cache;
5290
5291 MockHttpRequest request(kSimpleGET_Transaction);
5292
5293 const int kNumTransactions = 5;
5294 std::vector<std::unique_ptr<Context>> context_list;
5295
5296 for (int i = 0; i < kNumTransactions; ++i) {
5297 context_list.push_back(std::make_unique<Context>());
5298 auto& c = context_list[i];
5299
5300 c->result = cache.CreateTransaction(&c->trans);
5301 ASSERT_THAT(c->result, IsOk());
5302 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
5303
5304 c->result =
5305 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5306 }
5307
5308 // All requests are waiting for the active entry.
5309 for (auto& context : context_list) {
5310 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
5311 }
5312
5313 // Allow all requests to move from the Create queue to the active entry.
5314 base::RunLoop().RunUntilIdle();
5315
5316 // All transactions become writers.
5317 std::string cache_key = request.CacheKey();
5318 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
5319
5320 // All requests depend on the writer, and the writer is between Start and
5321 // Read, i.e. idle.
5322 for (auto& context : context_list) {
5323 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
5324 }
5325
5326 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5327 EXPECT_EQ(0, cache.disk_cache()->open_count());
5328 EXPECT_EQ(1, cache.disk_cache()->create_count());
5329
5330 // Fail the request.
5331 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
5332 // We have to open the entry again to propagate the failure flag.
5333 disk_cache::Entry* en;
5334 cache.OpenBackendEntry(cache_key, &en);
5335 en->Close();
5336
5337 for (int i = 0; i < kNumTransactions; ++i) {
5338 auto& c = context_list[i];
5339 if (c->result == ERR_IO_PENDING)
5340 c->result = c->callback.WaitForResult();
5341 if (i == 1) {
5342 // The earlier entry must be destroyed and its disk entry doomed.
5343 EXPECT_TRUE(cache.disk_cache()->IsDiskEntryDoomed(cache_key));
5344 }
5345
5346 if (i == 0) {
5347 // Consumer gets the response even if cache write failed.
5348 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5349 } else {
5350 // Read should lead to a failure being returned.
5351 const int kBufferSize = 5;
5352 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
5353 ReleaseBufferCompletionCallback cb(buffer.get());
5354 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
5355 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, cb.GetResult(c->result));
5356 }
5357 }
5358 }
5359
5360 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4769.
5361 // If cancelling a request is racing with another request for the same resource
5362 // finishing, we have to make sure that we remove both transactions from the
5363 // entry.
TEST_F(HttpCacheTest,SimpleGET_RacingReaders)5364 TEST_F(HttpCacheTest, SimpleGET_RacingReaders) {
5365 MockHttpCache cache;
5366
5367 MockHttpRequest request(kSimpleGET_Transaction);
5368 MockHttpRequest reader_request(kSimpleGET_Transaction);
5369 reader_request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
5370
5371 std::vector<std::unique_ptr<Context>> context_list;
5372 const int kNumTransactions = 5;
5373
5374 for (int i = 0; i < kNumTransactions; ++i) {
5375 context_list.push_back(std::make_unique<Context>());
5376 Context* c = context_list[i].get();
5377
5378 c->result = cache.CreateTransaction(&c->trans);
5379 ASSERT_THAT(c->result, IsOk());
5380
5381 MockHttpRequest* this_request = &request;
5382 if (i == 1 || i == 2)
5383 this_request = &reader_request;
5384
5385 c->result = c->trans->Start(this_request, c->callback.callback(),
5386 NetLogWithSource());
5387 }
5388
5389 // Allow all requests to move from the Create queue to the active entry.
5390 base::RunLoop().RunUntilIdle();
5391
5392 // The first request should be a writer at this point, and the subsequent
5393 // requests should be pending.
5394
5395 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5396 EXPECT_EQ(0, cache.disk_cache()->open_count());
5397 EXPECT_EQ(1, cache.disk_cache()->create_count());
5398
5399 Context* c = context_list[0].get();
5400 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5401 c->result = c->callback.WaitForResult();
5402 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5403
5404 // Now all transactions should be waiting for read to be invoked. Two readers
5405 // are because of the load flags and remaining two transactions were converted
5406 // to readers after skipping validation. Note that the remaining two went on
5407 // to process the headers in parallel with readers present on the entry.
5408 EXPECT_EQ(LOAD_STATE_IDLE, context_list[2]->trans->GetLoadState());
5409 EXPECT_EQ(LOAD_STATE_IDLE, context_list[3]->trans->GetLoadState());
5410
5411 c = context_list[1].get();
5412 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5413 c->result = c->callback.WaitForResult();
5414 if (c->result == OK)
5415 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5416
5417 // At this point we have one reader, two pending transactions and a task on
5418 // the queue to move to the next transaction. Now we cancel the request that
5419 // is the current reader, and expect the queued task to be able to start the
5420 // next request.
5421
5422 c = context_list[2].get();
5423 c->trans.reset();
5424
5425 for (int i = 3; i < kNumTransactions; ++i) {
5426 c = context_list[i].get();
5427 if (c->result == ERR_IO_PENDING)
5428 c->result = c->callback.WaitForResult();
5429 if (c->result == OK)
5430 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5431 }
5432
5433 // We should not have had to re-open the disk entry.
5434
5435 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5436 EXPECT_EQ(0, cache.disk_cache()->open_count());
5437 EXPECT_EQ(1, cache.disk_cache()->create_count());
5438 }
5439
5440 // Tests that we can doom an entry with pending transactions and delete one of
5441 // the pending transactions before the first one completes.
5442 // See http://code.google.com/p/chromium/issues/detail?id=25588
TEST_F(HttpCacheTest,SimpleGET_DoomWithPending)5443 TEST_F(HttpCacheTest, SimpleGET_DoomWithPending) {
5444 // We need simultaneous doomed / not_doomed entries so let's use a real cache.
5445 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
5446
5447 MockHttpRequest request(kSimpleGET_Transaction);
5448 MockHttpRequest writer_request(kSimpleGET_Transaction);
5449 writer_request.load_flags = LOAD_BYPASS_CACHE;
5450
5451 std::vector<std::unique_ptr<Context>> context_list;
5452 const int kNumTransactions = 4;
5453
5454 for (int i = 0; i < kNumTransactions; ++i) {
5455 context_list.push_back(std::make_unique<Context>());
5456 Context* c = context_list[i].get();
5457
5458 c->result = cache.CreateTransaction(&c->trans);
5459 ASSERT_THAT(c->result, IsOk());
5460
5461 MockHttpRequest* this_request = &request;
5462 if (i == 3)
5463 this_request = &writer_request;
5464
5465 c->result = c->trans->Start(this_request, c->callback.callback(),
5466 NetLogWithSource());
5467 }
5468
5469 base::RunLoop().RunUntilIdle();
5470
5471 // The first request should be a writer at this point, and the two subsequent
5472 // requests should be pending. The last request doomed the first entry.
5473
5474 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5475
5476 // Cancel the second transaction. Note that this and the 3rd transactions
5477 // would have completed their headers phase and would be waiting in the
5478 // done_headers_queue when the 2nd transaction is cancelled.
5479 context_list[1].reset();
5480
5481 for (int i = 0; i < kNumTransactions; ++i) {
5482 if (i == 1)
5483 continue;
5484 Context* c = context_list[i].get();
5485 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5486 c->result = c->callback.WaitForResult();
5487 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5488 }
5489 }
5490
TEST_F(HttpCacheTest,DoomDoesNotSetHints)5491 TEST_F(HttpCacheTest, DoomDoesNotSetHints) {
5492 // Test that a doomed writer doesn't set in-memory index hints.
5493 MockHttpCache cache;
5494 cache.disk_cache()->set_support_in_memory_entry_data(true);
5495
5496 // Request 1 is a normal one to a no-cache/no-etag resource, to potentially
5497 // set a "this is unvalidatable" hint in the cache. We also need it to
5498 // actually write out to the doomed entry after request 2 does its thing,
5499 // so its transaction is paused.
5500 MockTransaction no_cache_transaction(kSimpleGET_Transaction);
5501 no_cache_transaction.response_headers = "Cache-Control: no-cache\n";
5502 AddMockTransaction(&no_cache_transaction);
5503 MockHttpRequest request1(no_cache_transaction);
5504
5505 Context c1;
5506 c1.result = cache.CreateTransaction(&c1.trans);
5507 ASSERT_THAT(c1.result, IsOk());
5508 c1.trans->SetBeforeNetworkStartCallback(
5509 base::BindOnce([](bool* defer) { *defer = true; }));
5510 c1.result =
5511 c1.trans->Start(&request1, c1.callback.callback(), NetLogWithSource());
5512 ASSERT_THAT(c1.result, IsError(ERR_IO_PENDING));
5513
5514 // It starts, copies over headers info, but doesn't get to proceed.
5515 base::RunLoop().RunUntilIdle();
5516 RemoveMockTransaction(&no_cache_transaction);
5517
5518 // Request 2 sets LOAD_BYPASS_CACHE to force the first one to be doomed ---
5519 // it'll want to be a writer.
5520 MockHttpRequest request2(kSimpleGET_Transaction);
5521 request2.load_flags = LOAD_BYPASS_CACHE;
5522
5523 Context c2;
5524 c2.result = cache.CreateTransaction(&c2.trans);
5525 ASSERT_THAT(c2.result, IsOk());
5526 c2.result =
5527 c2.trans->Start(&request2, c2.callback.callback(), NetLogWithSource());
5528 ASSERT_THAT(c2.result, IsError(ERR_IO_PENDING));
5529
5530 // Run Request2, then let the first one wrap up.
5531 base::RunLoop().RunUntilIdle();
5532 c2.callback.WaitForResult();
5533 ReadAndVerifyTransaction(c2.trans.get(), kSimpleGET_Transaction);
5534
5535 c1.trans->ResumeNetworkStart();
5536 c1.callback.WaitForResult();
5537 ReadAndVerifyTransaction(c1.trans.get(), no_cache_transaction);
5538
5539 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5540 EXPECT_EQ(0, cache.disk_cache()->open_count());
5541 EXPECT_EQ(2, cache.disk_cache()->create_count());
5542
5543 // Request 3 tries to read from cache, and it should successfully do so. It's
5544 // run after the previous two transactions finish so it doesn't try to
5545 // cooperate with them, and is entirely driven by the state of the cache.
5546 MockHttpRequest request3(kSimpleGET_Transaction);
5547 Context context3;
5548 context3.result = cache.CreateTransaction(&context3.trans);
5549 ASSERT_THAT(context3.result, IsOk());
5550 context3.result = context3.trans->Start(
5551 &request3, context3.callback.callback(), NetLogWithSource());
5552 base::RunLoop().RunUntilIdle();
5553 ASSERT_THAT(context3.result, IsError(ERR_IO_PENDING));
5554 context3.result = context3.callback.WaitForResult();
5555 ReadAndVerifyTransaction(context3.trans.get(), kSimpleGET_Transaction);
5556
5557 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5558 EXPECT_EQ(1, cache.disk_cache()->open_count());
5559 EXPECT_EQ(2, cache.disk_cache()->create_count());
5560 }
5561
5562 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4731.
5563 // We may attempt to delete an entry synchronously with the act of adding a new
5564 // transaction to said entry.
TEST_F(HttpCacheTest,FastNoStoreGET_DoneWithPending)5565 TEST_F(HttpCacheTest, FastNoStoreGET_DoneWithPending) {
5566 MockHttpCache cache;
5567
5568 // The headers will be served right from the call to Start() the request.
5569 MockHttpRequest request(kFastNoStoreGET_Transaction);
5570 FastTransactionServer request_handler;
5571 AddMockTransaction(&kFastNoStoreGET_Transaction);
5572
5573 std::vector<std::unique_ptr<Context>> context_list;
5574 const int kNumTransactions = 3;
5575
5576 for (int i = 0; i < kNumTransactions; ++i) {
5577 context_list.push_back(std::make_unique<Context>());
5578 Context* c = context_list[i].get();
5579
5580 c->result = cache.CreateTransaction(&c->trans);
5581 ASSERT_THAT(c->result, IsOk());
5582
5583 c->result =
5584 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5585 }
5586
5587 // Allow all requests to move from the Create queue to the active entry.
5588 base::RunLoop().RunUntilIdle();
5589
5590 // The first request should be a writer at this point, and the subsequent
5591 // requests should have completed validation. Since the validation does not
5592 // result in a match, a new entry would be created.
5593
5594 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5595 EXPECT_EQ(0, cache.disk_cache()->open_count());
5596 EXPECT_EQ(3, cache.disk_cache()->create_count());
5597
5598 // Now, make sure that the second request asks for the entry not to be stored.
5599 request_handler.set_no_store(true);
5600
5601 for (int i = 0; i < kNumTransactions; ++i) {
5602 Context* c = context_list[i].get();
5603 if (c->result == ERR_IO_PENDING)
5604 c->result = c->callback.WaitForResult();
5605 ReadAndVerifyTransaction(c->trans.get(), kFastNoStoreGET_Transaction);
5606 context_list[i].reset();
5607 }
5608
5609 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5610 EXPECT_EQ(0, cache.disk_cache()->open_count());
5611 EXPECT_EQ(3, cache.disk_cache()->create_count());
5612
5613 RemoveMockTransaction(&kFastNoStoreGET_Transaction);
5614 }
5615
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_CancelFirst)5616 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_CancelFirst) {
5617 MockHttpCache cache;
5618
5619 MockHttpRequest request(kSimpleGET_Transaction);
5620
5621 std::vector<std::unique_ptr<Context>> context_list;
5622 const int kNumTransactions = 2;
5623
5624 for (int i = 0; i < kNumTransactions; ++i) {
5625 context_list.push_back(std::make_unique<Context>());
5626 Context* c = context_list[i].get();
5627
5628 c->result = cache.CreateTransaction(&c->trans);
5629 ASSERT_THAT(c->result, IsOk());
5630
5631 c->result =
5632 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5633 }
5634
5635 // Allow all requests to move from the Create queue to the active entry.
5636 // All would have been added to writers.
5637 base::RunLoop().RunUntilIdle();
5638 std::string cache_key =
5639 *cache.http_cache()->GenerateCacheKeyForRequest(&request);
5640 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
5641
5642 // The second transaction skipped validation, thus only one network
5643 // transaction is created.
5644 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5645 EXPECT_EQ(0, cache.disk_cache()->open_count());
5646 EXPECT_EQ(1, cache.disk_cache()->create_count());
5647
5648 for (int i = 0; i < kNumTransactions; ++i) {
5649 Context* c = context_list[i].get();
5650 if (c->result == ERR_IO_PENDING)
5651 c->result = c->callback.WaitForResult();
5652 // Destroy only the first transaction.
5653 // This should not impact the other writer transaction and the network
5654 // transaction will continue to be used by that transaction.
5655 if (i == 0) {
5656 context_list[i].reset();
5657 }
5658 }
5659
5660 // Complete the rest of the transactions.
5661 for (int i = 1; i < kNumTransactions; ++i) {
5662 Context* c = context_list[i].get();
5663 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5664 }
5665
5666 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5667 EXPECT_EQ(0, cache.disk_cache()->open_count());
5668 EXPECT_EQ(1, cache.disk_cache()->create_count());
5669 }
5670
5671 // Tests that we can cancel requests that are queued waiting to open the disk
5672 // cache entry.
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_CancelCreate)5673 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_CancelCreate) {
5674 MockHttpCache cache;
5675
5676 MockHttpRequest request(kSimpleGET_Transaction);
5677
5678 std::vector<std::unique_ptr<Context>> context_list;
5679 const int kNumTransactions = 5;
5680
5681 for (int i = 0; i < kNumTransactions; i++) {
5682 context_list.push_back(std::make_unique<Context>());
5683 Context* c = context_list[i].get();
5684
5685 c->result = cache.CreateTransaction(&c->trans);
5686 ASSERT_THAT(c->result, IsOk());
5687
5688 c->result =
5689 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5690 }
5691
5692 // The first request should be creating the disk cache entry and the others
5693 // should be pending.
5694
5695 EXPECT_EQ(0, cache.network_layer()->transaction_count());
5696 EXPECT_EQ(0, cache.disk_cache()->open_count());
5697 EXPECT_EQ(1, cache.disk_cache()->create_count());
5698
5699 // Cancel a request from the pending queue.
5700 context_list[3].reset();
5701
5702 // Cancel the request that is creating the entry. This will force the pending
5703 // operations to restart.
5704 context_list[0].reset();
5705
5706 // Complete the rest of the transactions.
5707 for (int i = 1; i < kNumTransactions; i++) {
5708 Context* c = context_list[i].get();
5709 if (c) {
5710 c->result = c->callback.GetResult(c->result);
5711 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5712 }
5713 }
5714
5715 // We should have had to re-create the disk entry.
5716
5717 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5718 EXPECT_EQ(0, cache.disk_cache()->open_count());
5719 EXPECT_EQ(2, cache.disk_cache()->create_count());
5720 }
5721
5722 // Tests that we can cancel a single request to open a disk cache entry.
TEST_F(HttpCacheTest,SimpleGET_CancelCreate)5723 TEST_F(HttpCacheTest, SimpleGET_CancelCreate) {
5724 MockHttpCache cache;
5725
5726 MockHttpRequest request(kSimpleGET_Transaction);
5727
5728 auto c = std::make_unique<Context>();
5729
5730 c->result = cache.CreateTransaction(&c->trans);
5731 ASSERT_THAT(c->result, IsOk());
5732
5733 c->result =
5734 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5735 EXPECT_THAT(c->result, IsError(ERR_IO_PENDING));
5736
5737 // Release the reference that the mock disk cache keeps for this entry, so
5738 // that we test that the http cache handles the cancellation correctly.
5739 cache.disk_cache()->ReleaseAll();
5740 c.reset();
5741
5742 base::RunLoop().RunUntilIdle();
5743 EXPECT_EQ(1, cache.disk_cache()->create_count());
5744 }
5745
5746 // Tests that we delete/create entries even if multiple requests are queued.
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_BypassCache)5747 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_BypassCache) {
5748 MockHttpCache cache;
5749
5750 MockHttpRequest request(kSimpleGET_Transaction);
5751 request.load_flags = LOAD_BYPASS_CACHE;
5752
5753 std::vector<std::unique_ptr<Context>> context_list;
5754 const int kNumTransactions = 5;
5755
5756 for (int i = 0; i < kNumTransactions; i++) {
5757 context_list.push_back(std::make_unique<Context>());
5758 Context* c = context_list[i].get();
5759
5760 c->result = cache.CreateTransaction(&c->trans);
5761 ASSERT_THAT(c->result, IsOk());
5762
5763 c->result =
5764 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5765 }
5766
5767 // The first request should be deleting the disk cache entry and the others
5768 // should be pending.
5769
5770 EXPECT_EQ(0, cache.network_layer()->transaction_count());
5771 EXPECT_EQ(0, cache.disk_cache()->open_count());
5772 EXPECT_EQ(0, cache.disk_cache()->create_count());
5773
5774 // Complete the transactions.
5775 for (int i = 0; i < kNumTransactions; i++) {
5776 Context* c = context_list[i].get();
5777 c->result = c->callback.GetResult(c->result);
5778 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5779 }
5780
5781 // We should have had to re-create the disk entry multiple times.
5782
5783 EXPECT_EQ(5, cache.network_layer()->transaction_count());
5784 EXPECT_EQ(0, cache.disk_cache()->open_count());
5785 EXPECT_EQ(5, cache.disk_cache()->create_count());
5786 }
5787
5788 // Tests that a (simulated) timeout allows transactions waiting on the cache
5789 // lock to continue.
TEST_F(HttpCacheTest,SimpleGET_WriterTimeout)5790 TEST_F(HttpCacheTest, SimpleGET_WriterTimeout) {
5791 MockHttpCache cache;
5792 cache.SimulateCacheLockTimeout();
5793
5794 MockHttpRequest request(kSimpleGET_Transaction);
5795 Context c1, c2;
5796 ASSERT_THAT(cache.CreateTransaction(&c1.trans), IsOk());
5797 ASSERT_EQ(ERR_IO_PENDING, c1.trans->Start(&request, c1.callback.callback(),
5798 NetLogWithSource()));
5799 ASSERT_THAT(cache.CreateTransaction(&c2.trans), IsOk());
5800 ASSERT_EQ(ERR_IO_PENDING, c2.trans->Start(&request, c2.callback.callback(),
5801 NetLogWithSource()));
5802
5803 // The second request is queued after the first one.
5804
5805 c2.callback.WaitForResult();
5806 ReadAndVerifyTransaction(c2.trans.get(), kSimpleGET_Transaction);
5807
5808 // Complete the first transaction.
5809 c1.callback.WaitForResult();
5810 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
5811 }
5812
5813 // Tests that a (simulated) timeout allows transactions waiting on the cache
5814 // lock to continue but read only transactions to error out.
TEST_F(HttpCacheTest,SimpleGET_WriterTimeoutReadOnlyError)5815 TEST_F(HttpCacheTest, SimpleGET_WriterTimeoutReadOnlyError) {
5816 MockHttpCache cache;
5817
5818 // Simulate timeout.
5819 cache.SimulateCacheLockTimeout();
5820
5821 MockHttpRequest request(kSimpleGET_Transaction);
5822 Context c1, c2;
5823 ASSERT_THAT(cache.CreateTransaction(&c1.trans), IsOk());
5824 ASSERT_EQ(ERR_IO_PENDING, c1.trans->Start(&request, c1.callback.callback(),
5825 NetLogWithSource()));
5826
5827 request.load_flags = LOAD_ONLY_FROM_CACHE;
5828 ASSERT_THAT(cache.CreateTransaction(&c2.trans), IsOk());
5829 ASSERT_EQ(ERR_IO_PENDING, c2.trans->Start(&request, c2.callback.callback(),
5830 NetLogWithSource()));
5831
5832 // The second request is queued after the first one.
5833 int res = c2.callback.WaitForResult();
5834 ASSERT_EQ(ERR_CACHE_MISS, res);
5835
5836 // Complete the first transaction.
5837 c1.callback.WaitForResult();
5838 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
5839 }
5840
TEST_F(HttpCacheTest,SimpleGET_AbandonedCacheRead)5841 TEST_F(HttpCacheTest, SimpleGET_AbandonedCacheRead) {
5842 MockHttpCache cache;
5843
5844 // write to the cache
5845 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5846
5847 MockHttpRequest request(kSimpleGET_Transaction);
5848 TestCompletionCallback callback;
5849
5850 std::unique_ptr<HttpTransaction> trans;
5851 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
5852 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5853 if (rv == ERR_IO_PENDING)
5854 rv = callback.WaitForResult();
5855 ASSERT_THAT(rv, IsOk());
5856
5857 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
5858 rv = trans->Read(buf.get(), 256, callback.callback());
5859 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5860
5861 // Test that destroying the transaction while it is reading from the cache
5862 // works properly.
5863 trans.reset();
5864
5865 // Make sure we pump any pending events, which should include a call to
5866 // HttpCache::Transaction::OnCacheReadCompleted.
5867 base::RunLoop().RunUntilIdle();
5868 }
5869
5870 // Tests that we can delete the HttpCache and deal with queued transactions
5871 // ("waiting for the backend" as opposed to Active or Doomed entries).
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_DeleteCache)5872 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_DeleteCache) {
5873 auto cache = std::make_unique<MockHttpCache>(
5874 std::make_unique<MockBackendNoCbFactory>());
5875
5876 MockHttpRequest request(kSimpleGET_Transaction);
5877
5878 std::vector<std::unique_ptr<Context>> context_list;
5879 const int kNumTransactions = 5;
5880
5881 for (int i = 0; i < kNumTransactions; i++) {
5882 context_list.push_back(std::make_unique<Context>());
5883 Context* c = context_list[i].get();
5884
5885 c->result = cache->CreateTransaction(&c->trans);
5886 ASSERT_THAT(c->result, IsOk());
5887
5888 c->result =
5889 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5890 }
5891
5892 // The first request should be creating the disk cache entry and the others
5893 // should be pending.
5894
5895 EXPECT_EQ(0, cache->network_layer()->transaction_count());
5896 EXPECT_EQ(0, cache->disk_cache()->open_count());
5897 EXPECT_EQ(0, cache->disk_cache()->create_count());
5898
5899 cache.reset();
5900 }
5901
5902 // Tests that we queue requests when initializing the backend.
TEST_F(HttpCacheTest,SimpleGET_WaitForBackend)5903 TEST_F(HttpCacheTest, SimpleGET_WaitForBackend) {
5904 auto factory = std::make_unique<MockBlockingBackendFactory>();
5905 MockBlockingBackendFactory* factory_ptr = factory.get();
5906 MockHttpCache cache(std::move(factory));
5907
5908 MockHttpRequest request0(kSimpleGET_Transaction);
5909 MockHttpRequest request1(kTypicalGET_Transaction);
5910 MockHttpRequest request2(kETagGET_Transaction);
5911
5912 std::vector<std::unique_ptr<Context>> context_list;
5913 const int kNumTransactions = 3;
5914
5915 for (int i = 0; i < kNumTransactions; i++) {
5916 context_list.push_back(std::make_unique<Context>());
5917 Context* c = context_list[i].get();
5918
5919 c->result = cache.CreateTransaction(&c->trans);
5920 ASSERT_THAT(c->result, IsOk());
5921 }
5922
5923 context_list[0]->result = context_list[0]->trans->Start(
5924 &request0, context_list[0]->callback.callback(), NetLogWithSource());
5925 context_list[1]->result = context_list[1]->trans->Start(
5926 &request1, context_list[1]->callback.callback(), NetLogWithSource());
5927 context_list[2]->result = context_list[2]->trans->Start(
5928 &request2, context_list[2]->callback.callback(), NetLogWithSource());
5929
5930 // Just to make sure that everything is still pending.
5931 base::RunLoop().RunUntilIdle();
5932
5933 // The first request should be creating the disk cache.
5934 EXPECT_FALSE(context_list[0]->callback.have_result());
5935
5936 factory_ptr->FinishCreation();
5937
5938 base::RunLoop().RunUntilIdle();
5939 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5940 EXPECT_EQ(3, cache.disk_cache()->create_count());
5941
5942 for (int i = 0; i < kNumTransactions; ++i) {
5943 EXPECT_TRUE(context_list[i]->callback.have_result());
5944 context_list[i].reset();
5945 }
5946 }
5947
5948 // Tests that we can cancel requests that are queued waiting for the backend
5949 // to be initialized.
TEST_F(HttpCacheTest,SimpleGET_WaitForBackend_CancelCreate)5950 TEST_F(HttpCacheTest, SimpleGET_WaitForBackend_CancelCreate) {
5951 auto factory = std::make_unique<MockBlockingBackendFactory>();
5952 MockBlockingBackendFactory* factory_ptr = factory.get();
5953 MockHttpCache cache(std::move(factory));
5954
5955 MockHttpRequest request0(kSimpleGET_Transaction);
5956 MockHttpRequest request1(kTypicalGET_Transaction);
5957 MockHttpRequest request2(kETagGET_Transaction);
5958
5959 std::vector<std::unique_ptr<Context>> context_list;
5960 const int kNumTransactions = 3;
5961
5962 for (int i = 0; i < kNumTransactions; i++) {
5963 context_list.push_back(std::make_unique<Context>());
5964 Context* c = context_list[i].get();
5965
5966 c->result = cache.CreateTransaction(&c->trans);
5967 ASSERT_THAT(c->result, IsOk());
5968 }
5969
5970 context_list[0]->result = context_list[0]->trans->Start(
5971 &request0, context_list[0]->callback.callback(), NetLogWithSource());
5972 context_list[1]->result = context_list[1]->trans->Start(
5973 &request1, context_list[1]->callback.callback(), NetLogWithSource());
5974 context_list[2]->result = context_list[2]->trans->Start(
5975 &request2, context_list[2]->callback.callback(), NetLogWithSource());
5976
5977 // Just to make sure that everything is still pending.
5978 base::RunLoop().RunUntilIdle();
5979
5980 // The first request should be creating the disk cache.
5981 EXPECT_FALSE(context_list[0]->callback.have_result());
5982
5983 // Cancel a request from the pending queue.
5984 context_list[1].reset();
5985
5986 // Cancel the request that is creating the entry.
5987 context_list[0].reset();
5988
5989 // Complete the last transaction.
5990 factory_ptr->FinishCreation();
5991
5992 context_list[2]->result =
5993 context_list[2]->callback.GetResult(context_list[2]->result);
5994 ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction);
5995
5996 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5997 EXPECT_EQ(1, cache.disk_cache()->create_count());
5998 }
5999
6000 // Tests that we can delete the HttpCache while creating the backend.
TEST_F(HttpCacheTest,DeleteCacheWaitingForBackend)6001 TEST_F(HttpCacheTest, DeleteCacheWaitingForBackend) {
6002 auto factory = std::make_unique<MockBlockingBackendFactory>();
6003 MockBlockingBackendFactory* factory_ptr = factory.get();
6004 auto cache = std::make_unique<MockHttpCache>(std::move(factory));
6005
6006 MockHttpRequest request(kSimpleGET_Transaction);
6007
6008 auto c = std::make_unique<Context>();
6009 c->result = cache->CreateTransaction(&c->trans);
6010 ASSERT_THAT(c->result, IsOk());
6011
6012 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
6013
6014 // Just to make sure that everything is still pending.
6015 base::RunLoop().RunUntilIdle();
6016
6017 // The request should be creating the disk cache.
6018 EXPECT_FALSE(c->callback.have_result());
6019
6020 // Manually arrange for completion to happen after ~HttpCache.
6021 // This can't be done via FinishCreation() since that's in `factory`, and
6022 // that's owned by `cache`.
6023 disk_cache::BackendResultCallback callback = factory_ptr->ReleaseCallback();
6024
6025 cache.reset();
6026 base::RunLoop().RunUntilIdle();
6027
6028 // Simulate the backend completion callback running now the HttpCache is gone.
6029 std::move(callback).Run(disk_cache::BackendResult::MakeError(ERR_ABORTED));
6030 }
6031
6032 // Tests that we can delete the cache while creating the backend, from within
6033 // one of the callbacks.
TEST_F(HttpCacheTest,DeleteCacheWaitingForBackend2)6034 TEST_F(HttpCacheTest, DeleteCacheWaitingForBackend2) {
6035 auto factory = std::make_unique<MockBlockingBackendFactory>();
6036 MockBlockingBackendFactory* factory_ptr = factory.get();
6037 auto cache = std::make_unique<MockHttpCache>(std::move(factory));
6038 auto* cache_ptr = cache.get();
6039
6040 DeleteCacheCompletionCallback cb(std::move(cache));
6041 disk_cache::Backend* backend;
6042 int rv = cache_ptr->http_cache()->GetBackend(&backend, cb.callback());
6043 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6044
6045 // Now let's queue a regular transaction
6046 MockHttpRequest request(kSimpleGET_Transaction);
6047
6048 auto c = std::make_unique<Context>();
6049 c->result = cache_ptr->CreateTransaction(&c->trans);
6050 ASSERT_THAT(c->result, IsOk());
6051
6052 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
6053
6054 // And another direct backend request.
6055 TestCompletionCallback cb2;
6056 rv = cache_ptr->http_cache()->GetBackend(&backend, cb2.callback());
6057 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6058
6059 // Just to make sure that everything is still pending.
6060 base::RunLoop().RunUntilIdle();
6061
6062 // The request should be queued.
6063 EXPECT_FALSE(c->callback.have_result());
6064
6065 // Generate the callback.
6066 factory_ptr->FinishCreation();
6067 rv = cb.WaitForResult();
6068
6069 // The cache should be gone by now.
6070 base::RunLoop().RunUntilIdle();
6071 EXPECT_THAT(c->callback.GetResult(c->result), IsOk());
6072 EXPECT_FALSE(cb2.have_result());
6073 }
6074
TEST_F(HttpCacheTest,TypicalGET_ConditionalRequest)6075 TEST_F(HttpCacheTest, TypicalGET_ConditionalRequest) {
6076 MockHttpCache cache;
6077
6078 // write to the cache
6079 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
6080
6081 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6082 EXPECT_EQ(0, cache.disk_cache()->open_count());
6083 EXPECT_EQ(1, cache.disk_cache()->create_count());
6084
6085 // Get the same URL again, but this time we expect it to result
6086 // in a conditional request.
6087 LoadTimingInfo load_timing_info;
6088 RunTransactionTestAndGetTiming(cache.http_cache(), kTypicalGET_Transaction,
6089 NetLogWithSource::Make(NetLogSourceType::NONE),
6090 &load_timing_info);
6091
6092 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6093 EXPECT_EQ(1, cache.disk_cache()->open_count());
6094 EXPECT_EQ(1, cache.disk_cache()->create_count());
6095 TestLoadTimingNetworkRequest(load_timing_info);
6096 }
6097
6098 static const auto kETagGetConditionalRequestHandler =
6099 base::BindRepeating([](const HttpRequestInfo* request,
6100 std::string* response_status,
6101 std::string* response_headers,
__anond56f448a0802(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) 6102 std::string* response_data) {
6103 EXPECT_TRUE(
6104 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6105 response_status->assign("HTTP/1.1 304 Not Modified");
6106 response_headers->assign(kETagGET_Transaction.response_headers);
6107 response_data->clear();
6108 });
6109
TEST_F(HttpCacheTest,ETagGET_ConditionalRequest_304)6110 TEST_F(HttpCacheTest, ETagGET_ConditionalRequest_304) {
6111 MockHttpCache cache;
6112
6113 ScopedMockTransaction transaction(kETagGET_Transaction);
6114
6115 // write to the cache
6116 RunTransactionTest(cache.http_cache(), transaction);
6117
6118 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6119 EXPECT_EQ(0, cache.disk_cache()->open_count());
6120 EXPECT_EQ(1, cache.disk_cache()->create_count());
6121
6122 // Get the same URL again, but this time we expect it to result
6123 // in a conditional request.
6124 transaction.load_flags = LOAD_VALIDATE_CACHE;
6125 transaction.handler = kETagGetConditionalRequestHandler;
6126 LoadTimingInfo load_timing_info;
6127 IPEndPoint remote_endpoint;
6128 RunTransactionTestAndGetTimingAndConnectedSocketAddress(
6129 cache.http_cache(), transaction,
6130 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info,
6131 &remote_endpoint);
6132
6133 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6134 EXPECT_EQ(1, cache.disk_cache()->open_count());
6135 EXPECT_EQ(1, cache.disk_cache()->create_count());
6136 TestLoadTimingNetworkRequest(load_timing_info);
6137
6138 EXPECT_FALSE(remote_endpoint.address().empty());
6139 }
6140
6141 class RevalidationServer {
6142 public:
6143 RevalidationServer() = default;
6144
EtagUsed()6145 bool EtagUsed() { return etag_used_; }
LastModifiedUsed()6146 bool LastModifiedUsed() { return last_modified_used_; }
6147
GetHandlerCallback()6148 MockTransactionHandler GetHandlerCallback() {
6149 return base::BindLambdaForTesting([this](const HttpRequestInfo* request,
6150 std::string* response_status,
6151 std::string* response_headers,
6152 std::string* response_data) {
6153 if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch)) {
6154 etag_used_ = true;
6155 }
6156
6157 if (request->extra_headers.HasHeader(
6158 HttpRequestHeaders::kIfModifiedSince)) {
6159 last_modified_used_ = true;
6160 }
6161
6162 if (etag_used_ || last_modified_used_) {
6163 response_status->assign("HTTP/1.1 304 Not Modified");
6164 response_headers->assign(kTypicalGET_Transaction.response_headers);
6165 response_data->clear();
6166 } else {
6167 response_status->assign(kTypicalGET_Transaction.status);
6168 response_headers->assign(kTypicalGET_Transaction.response_headers);
6169 response_data->assign(kTypicalGET_Transaction.data);
6170 }
6171 });
6172 }
6173
6174 private:
6175 bool etag_used_ = false;
6176 bool last_modified_used_ = false;
6177 };
6178
6179 // Tests revalidation after a vary match.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch)6180 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch) {
6181 MockHttpCache cache;
6182
6183 // Write to the cache.
6184 MockTransaction transaction(kTypicalGET_Transaction);
6185 transaction.request_headers = "Foo: bar\r\n";
6186 transaction.response_headers =
6187 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6188 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6189 "Etag: \"foopy\"\n"
6190 "Cache-Control: max-age=0\n"
6191 "Vary: Foo\n";
6192 AddMockTransaction(&transaction);
6193 RunTransactionTest(cache.http_cache(), transaction);
6194
6195 // Read from the cache.
6196 RevalidationServer server;
6197 transaction.handler = server.GetHandlerCallback();
6198 LoadTimingInfo load_timing_info;
6199 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6200 NetLogWithSource::Make(NetLogSourceType::NONE),
6201 &load_timing_info);
6202
6203 EXPECT_TRUE(server.EtagUsed());
6204 EXPECT_TRUE(server.LastModifiedUsed());
6205 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6206 EXPECT_EQ(1, cache.disk_cache()->open_count());
6207 EXPECT_EQ(1, cache.disk_cache()->create_count());
6208 TestLoadTimingNetworkRequest(load_timing_info);
6209 RemoveMockTransaction(&transaction);
6210 }
6211
6212 // Tests revalidation after a vary mismatch if etag is present.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch)6213 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch) {
6214 MockHttpCache cache;
6215
6216 // Write to the cache.
6217 MockTransaction transaction(kTypicalGET_Transaction);
6218 transaction.request_headers = "Foo: bar\r\n";
6219 transaction.response_headers =
6220 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6221 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6222 "Etag: \"foopy\"\n"
6223 "Cache-Control: max-age=0\n"
6224 "Vary: Foo\n";
6225 AddMockTransaction(&transaction);
6226 RunTransactionTest(cache.http_cache(), transaction);
6227
6228 // Read from the cache and revalidate the entry.
6229 RevalidationServer server;
6230 transaction.handler = server.GetHandlerCallback();
6231 transaction.request_headers = "Foo: none\r\n";
6232 LoadTimingInfo load_timing_info;
6233 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6234 NetLogWithSource::Make(NetLogSourceType::NONE),
6235 &load_timing_info);
6236
6237 EXPECT_TRUE(server.EtagUsed());
6238 EXPECT_FALSE(server.LastModifiedUsed());
6239 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6240 EXPECT_EQ(1, cache.disk_cache()->open_count());
6241 EXPECT_EQ(1, cache.disk_cache()->create_count());
6242 TestLoadTimingNetworkRequest(load_timing_info);
6243 RemoveMockTransaction(&transaction);
6244 }
6245
6246 // Tests revalidation after a vary mismatch due to vary: * if etag is present.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatchStar)6247 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatchStar) {
6248 MockHttpCache cache;
6249
6250 // Write to the cache.
6251 MockTransaction transaction(kTypicalGET_Transaction);
6252 transaction.response_headers =
6253 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6254 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6255 "Etag: \"foopy\"\n"
6256 "Cache-Control: max-age=0\n"
6257 "Vary: *\n";
6258 AddMockTransaction(&transaction);
6259 RunTransactionTest(cache.http_cache(), transaction);
6260
6261 // Read from the cache and revalidate the entry.
6262 RevalidationServer server;
6263 transaction.handler = server.GetHandlerCallback();
6264 LoadTimingInfo load_timing_info;
6265 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6266 NetLogWithSource::Make(NetLogSourceType::NONE),
6267 &load_timing_info);
6268
6269 EXPECT_TRUE(server.EtagUsed());
6270 EXPECT_FALSE(server.LastModifiedUsed());
6271 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6272 EXPECT_EQ(1, cache.disk_cache()->open_count());
6273 EXPECT_EQ(1, cache.disk_cache()->create_count());
6274 TestLoadTimingNetworkRequest(load_timing_info);
6275 RemoveMockTransaction(&transaction);
6276 }
6277
6278 // Tests lack of revalidation after a vary mismatch and no etag.
TEST_F(HttpCacheTest,GET_DontValidateCache_VaryMismatch)6279 TEST_F(HttpCacheTest, GET_DontValidateCache_VaryMismatch) {
6280 MockHttpCache cache;
6281
6282 // Write to the cache.
6283 MockTransaction transaction(kTypicalGET_Transaction);
6284 transaction.request_headers = "Foo: bar\r\n";
6285 transaction.response_headers =
6286 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6287 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6288 "Cache-Control: max-age=0\n"
6289 "Vary: Foo\n";
6290 AddMockTransaction(&transaction);
6291 RunTransactionTest(cache.http_cache(), transaction);
6292
6293 // Read from the cache and don't revalidate the entry.
6294 RevalidationServer server;
6295 transaction.handler = server.GetHandlerCallback();
6296 transaction.request_headers = "Foo: none\r\n";
6297 LoadTimingInfo load_timing_info;
6298 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6299 NetLogWithSource::Make(NetLogSourceType::NONE),
6300 &load_timing_info);
6301
6302 EXPECT_FALSE(server.EtagUsed());
6303 EXPECT_FALSE(server.LastModifiedUsed());
6304 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6305 EXPECT_EQ(1, cache.disk_cache()->open_count());
6306 EXPECT_EQ(1, cache.disk_cache()->create_count());
6307 TestLoadTimingNetworkRequest(load_timing_info);
6308 RemoveMockTransaction(&transaction);
6309 }
6310
6311 // Tests that a new vary header provided when revalidating an entry is saved.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch_UpdateVary)6312 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch_UpdateVary) {
6313 MockHttpCache cache;
6314
6315 // Write to the cache.
6316 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6317 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
6318 transaction.response_headers =
6319 "Etag: \"foopy\"\n"
6320 "Cache-Control: max-age=0\n"
6321 "Vary: Foo\n";
6322 RunTransactionTest(cache.http_cache(), transaction);
6323
6324 // Validate the entry and change the vary field in the response.
6325 transaction.request_headers = "Foo: bar\r\n Name: none\r\n";
6326 transaction.status = "HTTP/1.1 304 Not Modified";
6327 transaction.response_headers =
6328 "Etag: \"foopy\"\n"
6329 "Cache-Control: max-age=3600\n"
6330 "Vary: Name\n";
6331 RunTransactionTest(cache.http_cache(), transaction);
6332
6333 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6334 EXPECT_EQ(1, cache.disk_cache()->open_count());
6335 EXPECT_EQ(1, cache.disk_cache()->create_count());
6336
6337 // Make sure that the ActiveEntry is gone.
6338 base::RunLoop().RunUntilIdle();
6339
6340 // Generate a vary mismatch.
6341 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
6342 RunTransactionTest(cache.http_cache(), transaction);
6343
6344 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6345 EXPECT_EQ(2, cache.disk_cache()->open_count());
6346 EXPECT_EQ(1, cache.disk_cache()->create_count());
6347 }
6348
6349 // Tests that new request headers causing a vary mismatch are paired with the
6350 // new response when the server says the old response can be used.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch_UpdateRequestHeader)6351 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch_UpdateRequestHeader) {
6352 MockHttpCache cache;
6353
6354 // Write to the cache.
6355 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6356 transaction.request_headers = "Foo: bar\r\n";
6357 transaction.response_headers =
6358 "Etag: \"foopy\"\n"
6359 "Cache-Control: max-age=3600\n"
6360 "Vary: Foo\n";
6361 RunTransactionTest(cache.http_cache(), transaction);
6362
6363 // Vary-mismatch validation receives 304.
6364 transaction.request_headers = "Foo: none\r\n";
6365 transaction.status = "HTTP/1.1 304 Not Modified";
6366 RunTransactionTest(cache.http_cache(), transaction);
6367
6368 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6369 EXPECT_EQ(1, cache.disk_cache()->open_count());
6370 EXPECT_EQ(1, cache.disk_cache()->create_count());
6371
6372 // Make sure that the ActiveEntry is gone.
6373 base::RunLoop().RunUntilIdle();
6374
6375 // Generate a vary mismatch.
6376 transaction.request_headers = "Foo: bar\r\n";
6377 RunTransactionTest(cache.http_cache(), transaction);
6378
6379 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6380 EXPECT_EQ(2, cache.disk_cache()->open_count());
6381 EXPECT_EQ(1, cache.disk_cache()->create_count());
6382 }
6383
6384 // Tests that a 304 without vary headers doesn't delete the previously stored
6385 // vary data after a vary match revalidation.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch_DontDeleteVary)6386 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch_DontDeleteVary) {
6387 MockHttpCache cache;
6388
6389 // Write to the cache.
6390 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6391 transaction.request_headers = "Foo: bar\r\n";
6392 transaction.response_headers =
6393 "Etag: \"foopy\"\n"
6394 "Cache-Control: max-age=0\n"
6395 "Vary: Foo\n";
6396 RunTransactionTest(cache.http_cache(), transaction);
6397
6398 // Validate the entry and remove the vary field in the response.
6399 transaction.status = "HTTP/1.1 304 Not Modified";
6400 transaction.response_headers =
6401 "Etag: \"foopy\"\n"
6402 "Cache-Control: max-age=3600\n";
6403 RunTransactionTest(cache.http_cache(), transaction);
6404
6405 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6406 EXPECT_EQ(1, cache.disk_cache()->open_count());
6407 EXPECT_EQ(1, cache.disk_cache()->create_count());
6408
6409 // Make sure that the ActiveEntry is gone.
6410 base::RunLoop().RunUntilIdle();
6411
6412 // Generate a vary mismatch.
6413 transaction.request_headers = "Foo: none\r\n";
6414 RunTransactionTest(cache.http_cache(), transaction);
6415
6416 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6417 EXPECT_EQ(2, cache.disk_cache()->open_count());
6418 EXPECT_EQ(1, cache.disk_cache()->create_count());
6419 }
6420
6421 // Tests that a 304 without vary headers doesn't delete the previously stored
6422 // vary data after a vary mismatch.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch_DontDeleteVary)6423 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch_DontDeleteVary) {
6424 MockHttpCache cache;
6425
6426 // Write to the cache.
6427 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6428 transaction.request_headers = "Foo: bar\r\n";
6429 transaction.response_headers =
6430 "Etag: \"foopy\"\n"
6431 "Cache-Control: max-age=3600\n"
6432 "Vary: Foo\n";
6433 RunTransactionTest(cache.http_cache(), transaction);
6434
6435 // Vary-mismatch validation receives 304 and no vary header.
6436 transaction.request_headers = "Foo: none\r\n";
6437 transaction.status = "HTTP/1.1 304 Not Modified";
6438 transaction.response_headers =
6439 "Etag: \"foopy\"\n"
6440 "Cache-Control: max-age=3600\n";
6441 RunTransactionTest(cache.http_cache(), transaction);
6442
6443 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6444 EXPECT_EQ(1, cache.disk_cache()->open_count());
6445 EXPECT_EQ(1, cache.disk_cache()->create_count());
6446
6447 // Make sure that the ActiveEntry is gone.
6448 base::RunLoop().RunUntilIdle();
6449
6450 // Generate a vary mismatch.
6451 transaction.request_headers = "Foo: bar\r\n";
6452 RunTransactionTest(cache.http_cache(), transaction);
6453
6454 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6455 EXPECT_EQ(2, cache.disk_cache()->open_count());
6456 EXPECT_EQ(1, cache.disk_cache()->create_count());
6457 }
6458
ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)6459 static void ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo* request,
6460 std::string* response_status,
6461 std::string* response_headers,
6462 std::string* response_data) {
6463 EXPECT_FALSE(
6464 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6465 }
6466
TEST_F(HttpCacheTest,ETagGET_Http10)6467 TEST_F(HttpCacheTest, ETagGET_Http10) {
6468 MockHttpCache cache;
6469
6470 ScopedMockTransaction transaction(kETagGET_Transaction);
6471 transaction.status = "HTTP/1.0 200 OK";
6472
6473 // Write to the cache.
6474 RunTransactionTest(cache.http_cache(), transaction);
6475
6476 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6477 EXPECT_EQ(0, cache.disk_cache()->open_count());
6478 EXPECT_EQ(1, cache.disk_cache()->create_count());
6479
6480 // Get the same URL again, without generating a conditional request.
6481 transaction.load_flags = LOAD_VALIDATE_CACHE;
6482 transaction.handler =
6483 base::BindRepeating(&ETagGet_UnconditionalRequest_Handler);
6484 RunTransactionTest(cache.http_cache(), transaction);
6485
6486 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6487 EXPECT_EQ(1, cache.disk_cache()->open_count());
6488 EXPECT_EQ(1, cache.disk_cache()->create_count());
6489 }
6490
TEST_F(HttpCacheTest,ETagGET_Http10_Range)6491 TEST_F(HttpCacheTest, ETagGET_Http10_Range) {
6492 MockHttpCache cache;
6493
6494 ScopedMockTransaction transaction(kETagGET_Transaction);
6495 transaction.status = "HTTP/1.0 200 OK";
6496
6497 // Write to the cache.
6498 RunTransactionTest(cache.http_cache(), transaction);
6499
6500 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6501 EXPECT_EQ(0, cache.disk_cache()->open_count());
6502 EXPECT_EQ(1, cache.disk_cache()->create_count());
6503
6504 // Get the same URL again, but use a byte range request.
6505 transaction.load_flags = LOAD_VALIDATE_CACHE;
6506 transaction.handler =
6507 base::BindRepeating(&ETagGet_UnconditionalRequest_Handler);
6508 transaction.request_headers = "Range: bytes = 5-\r\n";
6509 RunTransactionTest(cache.http_cache(), transaction);
6510
6511 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6512 EXPECT_EQ(1, cache.disk_cache()->open_count());
6513 EXPECT_EQ(2, cache.disk_cache()->create_count());
6514 }
6515
ETagGet_ConditionalRequest_NoStore_Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)6516 static void ETagGet_ConditionalRequest_NoStore_Handler(
6517 const HttpRequestInfo* request,
6518 std::string* response_status,
6519 std::string* response_headers,
6520 std::string* response_data) {
6521 EXPECT_TRUE(
6522 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6523 response_status->assign("HTTP/1.1 304 Not Modified");
6524 response_headers->assign("Cache-Control: no-store\n");
6525 response_data->clear();
6526 }
6527
TEST_F(HttpCacheTest,ETagGET_ConditionalRequest_304_NoStore)6528 TEST_F(HttpCacheTest, ETagGET_ConditionalRequest_304_NoStore) {
6529 MockHttpCache cache;
6530
6531 ScopedMockTransaction transaction(kETagGET_Transaction);
6532
6533 // Write to the cache.
6534 RunTransactionTest(cache.http_cache(), transaction);
6535
6536 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6537 EXPECT_EQ(0, cache.disk_cache()->open_count());
6538 EXPECT_EQ(1, cache.disk_cache()->create_count());
6539
6540 // Get the same URL again, but this time we expect it to result
6541 // in a conditional request.
6542 transaction.load_flags = LOAD_VALIDATE_CACHE;
6543 transaction.handler =
6544 base::BindRepeating(&ETagGet_ConditionalRequest_NoStore_Handler);
6545 RunTransactionTest(cache.http_cache(), transaction);
6546
6547 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6548 EXPECT_EQ(1, cache.disk_cache()->open_count());
6549 EXPECT_EQ(1, cache.disk_cache()->create_count());
6550
6551 ScopedMockTransaction transaction2(kETagGET_Transaction);
6552
6553 // Write to the cache again. This should create a new entry.
6554 RunTransactionTest(cache.http_cache(), transaction2);
6555
6556 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6557 EXPECT_EQ(1, cache.disk_cache()->open_count());
6558 EXPECT_EQ(2, cache.disk_cache()->create_count());
6559 }
6560
6561 // Helper that does 4 requests using HttpCache:
6562 //
6563 // (1) loads |kUrl| -- expects |net_response_1| to be returned.
6564 // (2) loads |kUrl| from cache only -- expects |net_response_1| to be returned.
6565 // (3) loads |kUrl| using |extra_request_headers| -- expects |net_response_2| to
6566 // be returned.
6567 // (4) loads |kUrl| from cache only -- expects |cached_response_2| to be
6568 // returned.
6569 // The entry will be created once and will be opened for the 3 subsequent
6570 // requests.
ConditionalizedRequestUpdatesCacheHelper(const Response & net_response_1,const Response & net_response_2,const Response & cached_response_2,const char * extra_request_headers)6571 static void ConditionalizedRequestUpdatesCacheHelper(
6572 const Response& net_response_1,
6573 const Response& net_response_2,
6574 const Response& cached_response_2,
6575 const char* extra_request_headers) {
6576 MockHttpCache cache;
6577
6578 // The URL we will be requesting.
6579 const char kUrl[] = "http://foobar.com/main.css";
6580
6581 // Junk network response.
6582 static const Response kUnexpectedResponse = {
6583 "HTTP/1.1 500 Unexpected",
6584 "Server: unexpected_header",
6585 "unexpected body"
6586 };
6587
6588 // We will control the network layer's responses for |kUrl| using
6589 // |mock_network_response|.
6590 MockTransaction mock_network_response = {nullptr};
6591 mock_network_response.url = kUrl;
6592 AddMockTransaction(&mock_network_response);
6593
6594 // Request |kUrl| for the first time. It should hit the network and
6595 // receive |kNetResponse1|, which it saves into the HTTP cache.
6596
6597 MockTransaction request = {nullptr};
6598 request.url = kUrl;
6599 request.method = "GET";
6600 request.request_headers = "";
6601
6602 net_response_1.AssignTo(&mock_network_response); // Network mock.
6603 net_response_1.AssignTo(&request); // Expected result.
6604
6605 std::string response_headers;
6606 RunTransactionTestWithResponse(
6607 cache.http_cache(), request, &response_headers);
6608
6609 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
6610 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6611 EXPECT_EQ(0, cache.disk_cache()->open_count());
6612 EXPECT_EQ(1, cache.disk_cache()->create_count());
6613
6614 // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP
6615 // cache, so we don't hit the network.
6616
6617 request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
6618
6619 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
6620 net_response_1.AssignTo(&request); // Expected result.
6621
6622 RunTransactionTestWithResponse(
6623 cache.http_cache(), request, &response_headers);
6624
6625 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
6626 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6627 EXPECT_EQ(1, cache.disk_cache()->open_count());
6628 EXPECT_EQ(1, cache.disk_cache()->create_count());
6629
6630 // Request |kUrl| yet again, but this time give the request an
6631 // "If-Modified-Since" header. This will cause the request to re-hit the
6632 // network. However now the network response is going to be
6633 // different -- this simulates a change made to the CSS file.
6634
6635 request.request_headers = extra_request_headers;
6636 request.load_flags = LOAD_NORMAL;
6637
6638 net_response_2.AssignTo(&mock_network_response); // Network mock.
6639 net_response_2.AssignTo(&request); // Expected result.
6640
6641 RunTransactionTestWithResponse(
6642 cache.http_cache(), request, &response_headers);
6643
6644 EXPECT_EQ(net_response_2.status_and_headers(), response_headers);
6645 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6646 EXPECT_EQ(1, cache.disk_cache()->open_count());
6647 EXPECT_EQ(1, cache.disk_cache()->create_count());
6648
6649 // Finally, request |kUrl| again. This request should be serviced from
6650 // the cache. Moreover, the value in the cache should be |kNetResponse2|
6651 // and NOT |kNetResponse1|. The previous step should have replaced the
6652 // value in the cache with the modified response.
6653
6654 request.request_headers = "";
6655 request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
6656
6657 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
6658 cached_response_2.AssignTo(&request); // Expected result.
6659
6660 RunTransactionTestWithResponse(
6661 cache.http_cache(), request, &response_headers);
6662
6663 EXPECT_EQ(cached_response_2.status_and_headers(), response_headers);
6664 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6665 EXPECT_EQ(2, cache.disk_cache()->open_count());
6666 EXPECT_EQ(1, cache.disk_cache()->create_count());
6667
6668 RemoveMockTransaction(&mock_network_response);
6669 }
6670
6671 // Check that when an "if-modified-since" header is attached
6672 // to the request, the result still updates the cached entry.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache1)6673 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache1) {
6674 // First network response for |kUrl|.
6675 static const Response kNetResponse1 = {
6676 "HTTP/1.1 200 OK",
6677 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6678 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6679 "body1"
6680 };
6681
6682 // Second network response for |kUrl|.
6683 static const Response kNetResponse2 = {
6684 "HTTP/1.1 200 OK",
6685 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6686 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6687 "body2"
6688 };
6689
6690 const char extra_headers[] =
6691 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6692
6693 ConditionalizedRequestUpdatesCacheHelper(
6694 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
6695 }
6696
6697 // Check that when an "if-none-match" header is attached
6698 // to the request, the result updates the cached entry.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache2)6699 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache2) {
6700 // First network response for |kUrl|.
6701 static const Response kNetResponse1 = {
6702 "HTTP/1.1 200 OK",
6703 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6704 "Etag: \"ETAG1\"\n"
6705 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
6706 "body1"
6707 };
6708
6709 // Second network response for |kUrl|.
6710 static const Response kNetResponse2 = {
6711 "HTTP/1.1 200 OK",
6712 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6713 "Etag: \"ETAG2\"\n"
6714 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
6715 "body2"
6716 };
6717
6718 const char extra_headers[] = "If-None-Match: \"ETAG1\"\r\n";
6719
6720 ConditionalizedRequestUpdatesCacheHelper(
6721 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
6722 }
6723
6724 // Check that when an "if-modified-since" header is attached
6725 // to a request, the 304 (not modified result) result updates the cached
6726 // headers, and the 304 response is returned rather than the cached response.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache3)6727 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache3) {
6728 // First network response for |kUrl|.
6729 static const Response kNetResponse1 = {
6730 "HTTP/1.1 200 OK",
6731 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6732 "Server: server1\n"
6733 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6734 "body1"
6735 };
6736
6737 // Second network response for |kUrl|.
6738 static const Response kNetResponse2 = {
6739 "HTTP/1.1 304 Not Modified",
6740 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6741 "Server: server2\n"
6742 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6743 ""
6744 };
6745
6746 static const Response kCachedResponse2 = {
6747 "HTTP/1.1 200 OK",
6748 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6749 "Server: server2\n"
6750 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6751 "body1"
6752 };
6753
6754 const char extra_headers[] =
6755 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6756
6757 ConditionalizedRequestUpdatesCacheHelper(
6758 kNetResponse1, kNetResponse2, kCachedResponse2, extra_headers);
6759 }
6760
6761 // Test that when doing an externally conditionalized if-modified-since
6762 // and there is no corresponding cache entry, a new cache entry is NOT
6763 // created (304 response).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache4)6764 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache4) {
6765 MockHttpCache cache;
6766
6767 const char kUrl[] = "http://foobar.com/main.css";
6768
6769 static const Response kNetResponse = {
6770 "HTTP/1.1 304 Not Modified",
6771 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6772 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6773 ""
6774 };
6775
6776 const char kExtraRequestHeaders[] =
6777 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6778
6779 // We will control the network layer's responses for |kUrl| using
6780 // |mock_network_response|.
6781 MockTransaction mock_network_response = {nullptr};
6782 mock_network_response.url = kUrl;
6783 AddMockTransaction(&mock_network_response);
6784
6785 MockTransaction request = {nullptr};
6786 request.url = kUrl;
6787 request.method = "GET";
6788 request.request_headers = kExtraRequestHeaders;
6789
6790 kNetResponse.AssignTo(&mock_network_response); // Network mock.
6791 kNetResponse.AssignTo(&request); // Expected result.
6792
6793 std::string response_headers;
6794 RunTransactionTestWithResponse(
6795 cache.http_cache(), request, &response_headers);
6796
6797 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
6798 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6799 EXPECT_EQ(0, cache.disk_cache()->open_count());
6800 EXPECT_EQ(0, cache.disk_cache()->create_count());
6801
6802 RemoveMockTransaction(&mock_network_response);
6803 }
6804
6805 // Test that when doing an externally conditionalized if-modified-since
6806 // and there is no corresponding cache entry, a new cache entry is NOT
6807 // created (200 response).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache5)6808 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache5) {
6809 MockHttpCache cache;
6810
6811 const char kUrl[] = "http://foobar.com/main.css";
6812
6813 static const Response kNetResponse = {
6814 "HTTP/1.1 200 OK",
6815 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6816 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6817 "foobar!!!"
6818 };
6819
6820 const char kExtraRequestHeaders[] =
6821 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6822
6823 // We will control the network layer's responses for |kUrl| using
6824 // |mock_network_response|.
6825 MockTransaction mock_network_response = {nullptr};
6826 mock_network_response.url = kUrl;
6827 AddMockTransaction(&mock_network_response);
6828
6829 MockTransaction request = {nullptr};
6830 request.url = kUrl;
6831 request.method = "GET";
6832 request.request_headers = kExtraRequestHeaders;
6833
6834 kNetResponse.AssignTo(&mock_network_response); // Network mock.
6835 kNetResponse.AssignTo(&request); // Expected result.
6836
6837 std::string response_headers;
6838 RunTransactionTestWithResponse(
6839 cache.http_cache(), request, &response_headers);
6840
6841 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
6842 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6843 EXPECT_EQ(0, cache.disk_cache()->open_count());
6844 EXPECT_EQ(0, cache.disk_cache()->create_count());
6845
6846 RemoveMockTransaction(&mock_network_response);
6847 }
6848
6849 // Test that when doing an externally conditionalized if-modified-since
6850 // if the date does not match the cache entry's last-modified date,
6851 // then we do NOT use the response (304) to update the cache.
6852 // (the if-modified-since date is 2 days AFTER the cache's modification date).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache6)6853 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache6) {
6854 static const Response kNetResponse1 = {
6855 "HTTP/1.1 200 OK",
6856 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6857 "Server: server1\n"
6858 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6859 "body1"
6860 };
6861
6862 // Second network response for |kUrl|.
6863 static const Response kNetResponse2 = {
6864 "HTTP/1.1 304 Not Modified",
6865 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6866 "Server: server2\n"
6867 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6868 ""
6869 };
6870
6871 // This is two days in the future from the original response's last-modified
6872 // date!
6873 const char kExtraRequestHeaders[] =
6874 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n";
6875
6876 ConditionalizedRequestUpdatesCacheHelper(
6877 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
6878 }
6879
6880 // Test that when doing an externally conditionalized if-none-match
6881 // if the etag does not match the cache entry's etag, then we do not use the
6882 // response (304) to update the cache.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache7)6883 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache7) {
6884 static const Response kNetResponse1 = {
6885 "HTTP/1.1 200 OK",
6886 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6887 "Etag: \"Foo1\"\n"
6888 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6889 "body1"
6890 };
6891
6892 // Second network response for |kUrl|.
6893 static const Response kNetResponse2 = {
6894 "HTTP/1.1 304 Not Modified",
6895 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6896 "Etag: \"Foo2\"\n"
6897 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6898 ""
6899 };
6900
6901 // Different etag from original response.
6902 const char kExtraRequestHeaders[] = "If-None-Match: \"Foo2\"\r\n";
6903
6904 ConditionalizedRequestUpdatesCacheHelper(
6905 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
6906 }
6907
6908 // Test that doing an externally conditionalized request with both if-none-match
6909 // and if-modified-since updates the cache.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache8)6910 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache8) {
6911 static const Response kNetResponse1 = {
6912 "HTTP/1.1 200 OK",
6913 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6914 "Etag: \"Foo1\"\n"
6915 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6916 "body1"
6917 };
6918
6919 // Second network response for |kUrl|.
6920 static const Response kNetResponse2 = {
6921 "HTTP/1.1 200 OK",
6922 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6923 "Etag: \"Foo2\"\n"
6924 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6925 "body2"
6926 };
6927
6928 const char kExtraRequestHeaders[] =
6929 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
6930 "If-None-Match: \"Foo1\"\r\n";
6931
6932 ConditionalizedRequestUpdatesCacheHelper(
6933 kNetResponse1, kNetResponse2, kNetResponse2, kExtraRequestHeaders);
6934 }
6935
6936 // Test that doing an externally conditionalized request with both if-none-match
6937 // and if-modified-since does not update the cache with only one match.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache9)6938 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache9) {
6939 static const Response kNetResponse1 = {
6940 "HTTP/1.1 200 OK",
6941 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6942 "Etag: \"Foo1\"\n"
6943 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6944 "body1"
6945 };
6946
6947 // Second network response for |kUrl|.
6948 static const Response kNetResponse2 = {
6949 "HTTP/1.1 200 OK",
6950 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6951 "Etag: \"Foo2\"\n"
6952 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6953 "body2"
6954 };
6955
6956 // The etag doesn't match what we have stored.
6957 const char kExtraRequestHeaders[] =
6958 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
6959 "If-None-Match: \"Foo2\"\r\n";
6960
6961 ConditionalizedRequestUpdatesCacheHelper(
6962 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
6963 }
6964
6965 // Test that doing an externally conditionalized request with both if-none-match
6966 // and if-modified-since does not update the cache with only one match.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache10)6967 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache10) {
6968 static const Response kNetResponse1 = {
6969 "HTTP/1.1 200 OK",
6970 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6971 "Etag: \"Foo1\"\n"
6972 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6973 "body1"
6974 };
6975
6976 // Second network response for |kUrl|.
6977 static const Response kNetResponse2 = {
6978 "HTTP/1.1 200 OK",
6979 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6980 "Etag: \"Foo2\"\n"
6981 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6982 "body2"
6983 };
6984
6985 // The modification date doesn't match what we have stored.
6986 const char kExtraRequestHeaders[] =
6987 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n"
6988 "If-None-Match: \"Foo1\"\r\n";
6989
6990 ConditionalizedRequestUpdatesCacheHelper(
6991 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
6992 }
6993
TEST_F(HttpCacheTest,UrlContainingHash)6994 TEST_F(HttpCacheTest, UrlContainingHash) {
6995 MockHttpCache cache;
6996
6997 // Do a typical GET request -- should write an entry into our cache.
6998 MockTransaction trans(kTypicalGET_Transaction);
6999 RunTransactionTest(cache.http_cache(), trans);
7000
7001 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7002 EXPECT_EQ(0, cache.disk_cache()->open_count());
7003 EXPECT_EQ(1, cache.disk_cache()->create_count());
7004
7005 // Request the same URL, but this time with a reference section (hash).
7006 // Since the cache key strips the hash sections, this should be a cache hit.
7007 std::string url_with_hash = std::string(trans.url) + "#multiple#hashes";
7008 trans.url = url_with_hash.c_str();
7009 trans.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7010
7011 RunTransactionTest(cache.http_cache(), trans);
7012
7013 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7014 EXPECT_EQ(1, cache.disk_cache()->open_count());
7015 EXPECT_EQ(1, cache.disk_cache()->create_count());
7016 }
7017
7018 // Tests that we skip the cache for POST requests that do not have an upload
7019 // identifier.
TEST_F(HttpCacheTest,SimplePOST_SkipsCache)7020 TEST_F(HttpCacheTest, SimplePOST_SkipsCache) {
7021 MockHttpCache cache;
7022
7023 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
7024
7025 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7026 EXPECT_EQ(0, cache.disk_cache()->open_count());
7027 EXPECT_EQ(0, cache.disk_cache()->create_count());
7028 }
7029
7030 // Tests POST handling with a disabled cache (no DCHECK).
TEST_F(HttpCacheTest,SimplePOST_DisabledCache)7031 TEST_F(HttpCacheTest, SimplePOST_DisabledCache) {
7032 MockHttpCache cache;
7033 cache.http_cache()->set_mode(HttpCache::Mode::DISABLE);
7034
7035 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
7036
7037 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7038 EXPECT_EQ(0, cache.disk_cache()->open_count());
7039 EXPECT_EQ(0, cache.disk_cache()->create_count());
7040 }
7041
TEST_F(HttpCacheTest,SimplePOST_LoadOnlyFromCache_Miss)7042 TEST_F(HttpCacheTest, SimplePOST_LoadOnlyFromCache_Miss) {
7043 MockHttpCache cache;
7044
7045 MockTransaction transaction(kSimplePOST_Transaction);
7046 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7047
7048 MockHttpRequest request(transaction);
7049 TestCompletionCallback callback;
7050
7051 std::unique_ptr<HttpTransaction> trans;
7052 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
7053 ASSERT_TRUE(trans.get());
7054
7055 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
7056 ASSERT_THAT(callback.GetResult(rv), IsError(ERR_CACHE_MISS));
7057
7058 trans.reset();
7059
7060 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7061 EXPECT_EQ(0, cache.disk_cache()->open_count());
7062 EXPECT_EQ(0, cache.disk_cache()->create_count());
7063 }
7064
TEST_F(HttpCacheTest,SimplePOST_LoadOnlyFromCache_Hit)7065 TEST_F(HttpCacheTest, SimplePOST_LoadOnlyFromCache_Hit) {
7066 MockHttpCache cache;
7067
7068 // Test that we hit the cache for POST requests.
7069
7070 MockTransaction transaction(kSimplePOST_Transaction);
7071
7072 const int64_t kUploadId = 1; // Just a dummy value.
7073
7074 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7075 element_readers.push_back(
7076 std::make_unique<UploadBytesElementReader>("hello", 5));
7077 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
7078 kUploadId);
7079 MockHttpRequest request(transaction);
7080 request.upload_data_stream = &upload_data_stream;
7081
7082 // Populate the cache.
7083 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7084 nullptr);
7085
7086 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7087 EXPECT_EQ(0, cache.disk_cache()->open_count());
7088 EXPECT_EQ(1, cache.disk_cache()->create_count());
7089
7090 // Load from cache.
7091 request.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7092 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7093 nullptr);
7094
7095 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7096 EXPECT_EQ(1, cache.disk_cache()->open_count());
7097 EXPECT_EQ(1, cache.disk_cache()->create_count());
7098 }
7099
7100 // Test that we don't hit the cache for POST requests if there is a byte range.
TEST_F(HttpCacheTest,SimplePOST_WithRanges)7101 TEST_F(HttpCacheTest, SimplePOST_WithRanges) {
7102 MockHttpCache cache;
7103
7104 MockTransaction transaction(kSimplePOST_Transaction);
7105 transaction.request_headers = "Range: bytes = 0-4\r\n";
7106
7107 const int64_t kUploadId = 1; // Just a dummy value.
7108
7109 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7110 element_readers.push_back(
7111 std::make_unique<UploadBytesElementReader>("hello", 5));
7112 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
7113 kUploadId);
7114
7115 MockHttpRequest request(transaction);
7116 request.upload_data_stream = &upload_data_stream;
7117
7118 // Attempt to populate the cache.
7119 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7120 nullptr);
7121
7122 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7123 EXPECT_EQ(0, cache.disk_cache()->open_count());
7124 EXPECT_EQ(0, cache.disk_cache()->create_count());
7125 }
7126
7127 // Tests that a POST is cached separately from a GET.
TEST_F(HttpCacheTest,SimplePOST_SeparateCache)7128 TEST_F(HttpCacheTest, SimplePOST_SeparateCache) {
7129 MockHttpCache cache;
7130
7131 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7132 element_readers.push_back(
7133 std::make_unique<UploadBytesElementReader>("hello", 5));
7134 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7135
7136 MockTransaction transaction(kSimplePOST_Transaction);
7137 MockHttpRequest req1(transaction);
7138 req1.upload_data_stream = &upload_data_stream;
7139
7140 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7141
7142 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7143 EXPECT_EQ(0, cache.disk_cache()->open_count());
7144 EXPECT_EQ(1, cache.disk_cache()->create_count());
7145
7146 transaction.method = "GET";
7147 MockHttpRequest req2(transaction);
7148
7149 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7150
7151 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7152 EXPECT_EQ(0, cache.disk_cache()->open_count());
7153 EXPECT_EQ(2, cache.disk_cache()->create_count());
7154 }
7155
7156 // Tests that a successful POST invalidates a previously cached GET.
TEST_F(HttpCacheTest,SimplePOST_Invalidate_205)7157 TEST_F(HttpCacheTest, SimplePOST_Invalidate_205) {
7158 MockHttpCache cache;
7159
7160 MockTransaction transaction(kSimpleGET_Transaction);
7161 AddMockTransaction(&transaction);
7162 MockHttpRequest req1(transaction);
7163
7164 // Attempt to populate the cache.
7165 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7166
7167 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7168 EXPECT_EQ(0, cache.disk_cache()->open_count());
7169 EXPECT_EQ(1, cache.disk_cache()->create_count());
7170
7171 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7172 element_readers.push_back(
7173 std::make_unique<UploadBytesElementReader>("hello", 5));
7174 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7175
7176 transaction.method = "POST";
7177 transaction.status = "HTTP/1.1 205 No Content";
7178 MockHttpRequest req2(transaction);
7179 req2.upload_data_stream = &upload_data_stream;
7180
7181 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7182
7183 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7184 EXPECT_EQ(0, cache.disk_cache()->open_count());
7185 EXPECT_EQ(2, cache.disk_cache()->create_count());
7186
7187 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7188
7189 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7190 EXPECT_EQ(0, cache.disk_cache()->open_count());
7191 EXPECT_EQ(3, cache.disk_cache()->create_count());
7192 RemoveMockTransaction(&transaction);
7193 }
7194
7195 // Tests that a successful POST invalidates a previously cached GET,
7196 // with cache split by top-frame origin.
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SimplePOST_Invalidate_205_SplitCache)7197 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
7198 SimplePOST_Invalidate_205_SplitCache) {
7199 SchemefulSite site_a(GURL("http://a.com"));
7200 SchemefulSite site_b(GURL("http://b.com"));
7201
7202 MockHttpCache cache;
7203
7204 MockTransaction transaction(kSimpleGET_Transaction);
7205 AddMockTransaction(&transaction);
7206 MockHttpRequest req1(transaction);
7207 req1.network_isolation_key = NetworkIsolationKey(site_a, site_a);
7208 req1.network_anonymization_key =
7209 net::NetworkAnonymizationKey::CreateSameSite(site_a);
7210
7211 // Attempt to populate the cache.
7212 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7213
7214 // Same for a different origin.
7215 MockHttpRequest req1b(transaction);
7216 req1b.network_isolation_key = NetworkIsolationKey(site_b, site_b);
7217 req1b.network_anonymization_key =
7218 net::NetworkAnonymizationKey::CreateSameSite(site_b);
7219 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1b,
7220 nullptr);
7221
7222 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7223 EXPECT_EQ(0, cache.disk_cache()->open_count());
7224 EXPECT_EQ(2, cache.disk_cache()->create_count());
7225
7226 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7227 element_readers.push_back(
7228 std::make_unique<UploadBytesElementReader>("hello", 5));
7229 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7230
7231 transaction.method = "POST";
7232 transaction.status = "HTTP/1.1 205 No Content";
7233 MockHttpRequest req2(transaction);
7234 req2.upload_data_stream = &upload_data_stream;
7235 req2.network_isolation_key = NetworkIsolationKey(site_a, site_a);
7236 req2.network_anonymization_key =
7237 net::NetworkAnonymizationKey::CreateSameSite(site_a);
7238
7239 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7240
7241 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7242 EXPECT_EQ(0, cache.disk_cache()->open_count());
7243 EXPECT_EQ(3, cache.disk_cache()->create_count());
7244
7245 // req1b should still be cached, since it has a different top-level frame
7246 // origin.
7247 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1b,
7248 nullptr);
7249 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7250 EXPECT_EQ(1, cache.disk_cache()->open_count());
7251 EXPECT_EQ(3, cache.disk_cache()->create_count());
7252
7253 // req1 should not be cached after the POST.
7254 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7255 EXPECT_EQ(4, cache.network_layer()->transaction_count());
7256 EXPECT_EQ(1, cache.disk_cache()->open_count());
7257 EXPECT_EQ(4, cache.disk_cache()->create_count());
7258
7259 RemoveMockTransaction(&transaction);
7260 }
7261
7262 // Tests that a successful POST invalidates a previously cached GET, even when
7263 // there is no upload identifier.
TEST_F(HttpCacheTest,SimplePOST_NoUploadId_Invalidate_205)7264 TEST_F(HttpCacheTest, SimplePOST_NoUploadId_Invalidate_205) {
7265 MockHttpCache cache;
7266
7267 MockTransaction transaction(kSimpleGET_Transaction);
7268 AddMockTransaction(&transaction);
7269 MockHttpRequest req1(transaction);
7270
7271 // Attempt to populate the cache.
7272 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7273
7274 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7275 EXPECT_EQ(0, cache.disk_cache()->open_count());
7276 EXPECT_EQ(1, cache.disk_cache()->create_count());
7277
7278 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7279 element_readers.push_back(
7280 std::make_unique<UploadBytesElementReader>("hello", 5));
7281 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7282
7283 transaction.method = "POST";
7284 transaction.status = "HTTP/1.1 205 No Content";
7285 MockHttpRequest req2(transaction);
7286 req2.upload_data_stream = &upload_data_stream;
7287
7288 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7289
7290 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7291 EXPECT_EQ(0, cache.disk_cache()->open_count());
7292 EXPECT_EQ(1, cache.disk_cache()->create_count());
7293
7294 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7295
7296 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7297 EXPECT_EQ(0, cache.disk_cache()->open_count());
7298 EXPECT_EQ(2, cache.disk_cache()->create_count());
7299 RemoveMockTransaction(&transaction);
7300 }
7301
7302 // Tests that processing a POST before creating the backend doesn't crash.
TEST_F(HttpCacheTest,SimplePOST_NoUploadId_NoBackend)7303 TEST_F(HttpCacheTest, SimplePOST_NoUploadId_NoBackend) {
7304 // This will initialize a cache object with NULL backend.
7305 auto factory = std::make_unique<MockBlockingBackendFactory>();
7306 factory->set_fail(true);
7307 factory->FinishCreation();
7308 MockHttpCache cache(std::move(factory));
7309
7310 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7311 element_readers.push_back(
7312 std::make_unique<UploadBytesElementReader>("hello", 5));
7313 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7314
7315 MockTransaction transaction(kSimplePOST_Transaction);
7316 AddMockTransaction(&transaction);
7317 MockHttpRequest req(transaction);
7318 req.upload_data_stream = &upload_data_stream;
7319
7320 RunTransactionTestWithRequest(cache.http_cache(), transaction, req, nullptr);
7321
7322 RemoveMockTransaction(&transaction);
7323 }
7324
7325 // Tests that we don't invalidate entries as a result of a failed POST.
TEST_F(HttpCacheTest,SimplePOST_DontInvalidate_100)7326 TEST_F(HttpCacheTest, SimplePOST_DontInvalidate_100) {
7327 MockHttpCache cache;
7328
7329 MockTransaction transaction(kSimpleGET_Transaction);
7330 AddMockTransaction(&transaction);
7331 MockHttpRequest req1(transaction);
7332
7333 // Attempt to populate the cache.
7334 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7335
7336 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7337 EXPECT_EQ(0, cache.disk_cache()->open_count());
7338 EXPECT_EQ(1, cache.disk_cache()->create_count());
7339
7340 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7341 element_readers.push_back(
7342 std::make_unique<UploadBytesElementReader>("hello", 5));
7343 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7344
7345 transaction.method = "POST";
7346 transaction.status = "HTTP/1.1 100 Continue";
7347 MockHttpRequest req2(transaction);
7348 req2.upload_data_stream = &upload_data_stream;
7349
7350 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7351
7352 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7353 EXPECT_EQ(0, cache.disk_cache()->open_count());
7354 EXPECT_EQ(2, cache.disk_cache()->create_count());
7355
7356 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7357
7358 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7359 EXPECT_EQ(1, cache.disk_cache()->open_count());
7360 EXPECT_EQ(2, cache.disk_cache()->create_count());
7361 RemoveMockTransaction(&transaction);
7362 }
7363
7364 // Tests that a HEAD request is not cached by itself.
TEST_F(HttpCacheTest,SimpleHEAD_LoadOnlyFromCache_Miss)7365 TEST_F(HttpCacheTest, SimpleHEAD_LoadOnlyFromCache_Miss) {
7366 MockHttpCache cache;
7367 MockTransaction transaction(kSimplePOST_Transaction);
7368 AddMockTransaction(&transaction);
7369 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7370 transaction.method = "HEAD";
7371
7372 MockHttpRequest request(transaction);
7373 TestCompletionCallback callback;
7374
7375 std::unique_ptr<HttpTransaction> trans;
7376 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
7377 ASSERT_TRUE(trans.get());
7378
7379 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
7380 ASSERT_THAT(callback.GetResult(rv), IsError(ERR_CACHE_MISS));
7381
7382 trans.reset();
7383
7384 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7385 EXPECT_EQ(0, cache.disk_cache()->open_count());
7386 EXPECT_EQ(0, cache.disk_cache()->create_count());
7387 RemoveMockTransaction(&transaction);
7388 }
7389
7390 // Tests that a HEAD request is served from a cached GET.
TEST_F(HttpCacheTest,SimpleHEAD_LoadOnlyFromCache_Hit)7391 TEST_F(HttpCacheTest, SimpleHEAD_LoadOnlyFromCache_Hit) {
7392 MockHttpCache cache;
7393 MockTransaction transaction(kSimpleGET_Transaction);
7394 AddMockTransaction(&transaction);
7395
7396 // Populate the cache.
7397 RunTransactionTest(cache.http_cache(), transaction);
7398
7399 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7400 EXPECT_EQ(0, cache.disk_cache()->open_count());
7401 EXPECT_EQ(1, cache.disk_cache()->create_count());
7402
7403 // Load from cache.
7404 transaction.method = "HEAD";
7405 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7406 transaction.data = "";
7407 RunTransactionTest(cache.http_cache(), transaction);
7408
7409 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7410 EXPECT_EQ(1, cache.disk_cache()->open_count());
7411 EXPECT_EQ(1, cache.disk_cache()->create_count());
7412 RemoveMockTransaction(&transaction);
7413 }
7414
7415 // Tests that a read-only request served from the cache preserves CL.
TEST_F(HttpCacheTest,SimpleHEAD_ContentLengthOnHit_Read)7416 TEST_F(HttpCacheTest, SimpleHEAD_ContentLengthOnHit_Read) {
7417 MockHttpCache cache;
7418 MockTransaction transaction(kSimpleGET_Transaction);
7419 AddMockTransaction(&transaction);
7420 transaction.response_headers = "Content-Length: 42\n";
7421
7422 // Populate the cache.
7423 RunTransactionTest(cache.http_cache(), transaction);
7424
7425 // Load from cache.
7426 transaction.method = "HEAD";
7427 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7428 transaction.data = "";
7429 std::string headers;
7430
7431 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7432
7433 EXPECT_EQ("HTTP/1.1 200 OK\nContent-Length: 42\n", headers);
7434 RemoveMockTransaction(&transaction);
7435 }
7436
7437 // Tests that a read-write request served from the cache preserves CL.
TEST_F(HttpCacheTest,ETagHEAD_ContentLengthOnHit_ReadWrite)7438 TEST_F(HttpCacheTest, ETagHEAD_ContentLengthOnHit_ReadWrite) {
7439 MockHttpCache cache;
7440 MockTransaction transaction(kETagGET_Transaction);
7441 AddMockTransaction(&transaction);
7442 std::string server_headers(kETagGET_Transaction.response_headers);
7443 server_headers.append("Content-Length: 42\n");
7444 transaction.response_headers = server_headers.data();
7445
7446 // Populate the cache.
7447 RunTransactionTest(cache.http_cache(), transaction);
7448
7449 // Load from cache.
7450 transaction.method = "HEAD";
7451 transaction.data = "";
7452 std::string headers;
7453
7454 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7455
7456 EXPECT_NE(std::string::npos, headers.find("Content-Length: 42\n"));
7457 RemoveMockTransaction(&transaction);
7458 }
7459
7460 // Tests that a HEAD request that includes byte ranges bypasses the cache.
TEST_F(HttpCacheTest,SimpleHEAD_WithRanges)7461 TEST_F(HttpCacheTest, SimpleHEAD_WithRanges) {
7462 MockHttpCache cache;
7463 MockTransaction transaction(kSimpleGET_Transaction);
7464 AddMockTransaction(&transaction);
7465
7466 // Populate the cache.
7467 RunTransactionTest(cache.http_cache(), transaction);
7468
7469 // Load from cache.
7470 transaction.method = "HEAD";
7471 transaction.request_headers = "Range: bytes = 0-4\r\n";
7472 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7473 transaction.start_return_code = ERR_CACHE_MISS;
7474 RunTransactionTest(cache.http_cache(), transaction);
7475
7476 EXPECT_EQ(0, cache.disk_cache()->open_count());
7477 EXPECT_EQ(1, cache.disk_cache()->create_count());
7478 RemoveMockTransaction(&transaction);
7479 }
7480
7481 // Tests that a HEAD request can be served from a partially cached resource.
TEST_F(HttpCacheTest,SimpleHEAD_WithCachedRanges)7482 TEST_F(HttpCacheTest, SimpleHEAD_WithCachedRanges) {
7483 MockHttpCache cache;
7484 AddMockTransaction(&kRangeGET_TransactionOK);
7485
7486 // Write to the cache (40-49).
7487 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
7488 RemoveMockTransaction(&kRangeGET_TransactionOK);
7489
7490 MockTransaction transaction(kSimpleGET_Transaction);
7491
7492 transaction.url = kRangeGET_TransactionOK.url;
7493 transaction.method = "HEAD";
7494 transaction.data = "";
7495 AddMockTransaction(&transaction);
7496 std::string headers;
7497
7498 // Load from cache.
7499 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7500
7501 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7502 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
7503 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
7504 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7505 EXPECT_EQ(1, cache.disk_cache()->open_count());
7506 EXPECT_EQ(1, cache.disk_cache()->create_count());
7507 RemoveMockTransaction(&transaction);
7508 }
7509
7510 // Tests that a HEAD request can be served from a truncated resource.
TEST_F(HttpCacheTest,SimpleHEAD_WithTruncatedEntry)7511 TEST_F(HttpCacheTest, SimpleHEAD_WithTruncatedEntry) {
7512 MockHttpCache cache;
7513 AddMockTransaction(&kRangeGET_TransactionOK);
7514
7515 std::string raw_headers("HTTP/1.1 200 OK\n"
7516 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7517 "ETag: \"foo\"\n"
7518 "Accept-Ranges: bytes\n"
7519 "Content-Length: 80\n");
7520 CreateTruncatedEntry(raw_headers, &cache);
7521 RemoveMockTransaction(&kRangeGET_TransactionOK);
7522
7523 MockTransaction transaction(kSimpleGET_Transaction);
7524
7525 transaction.url = kRangeGET_TransactionOK.url;
7526 transaction.method = "HEAD";
7527 transaction.data = "";
7528 AddMockTransaction(&transaction);
7529 std::string headers;
7530
7531 // Load from cache.
7532 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7533
7534 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7535 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
7536 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
7537 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7538 EXPECT_EQ(1, cache.disk_cache()->open_count());
7539 EXPECT_EQ(1, cache.disk_cache()->create_count());
7540 RemoveMockTransaction(&transaction);
7541 }
7542
7543 // Tests that a HEAD request updates the cached response.
TEST_F(HttpCacheTest,TypicalHEAD_UpdatesResponse)7544 TEST_F(HttpCacheTest, TypicalHEAD_UpdatesResponse) {
7545 MockHttpCache cache;
7546 MockTransaction transaction(kTypicalGET_Transaction);
7547 AddMockTransaction(&transaction);
7548
7549 // Populate the cache.
7550 RunTransactionTest(cache.http_cache(), transaction);
7551
7552 // Update the cache.
7553 transaction.method = "HEAD";
7554 transaction.response_headers = "Foo: bar\n";
7555 transaction.data = "";
7556 transaction.status = "HTTP/1.1 304 Not Modified\n";
7557 std::string headers;
7558 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7559 RemoveMockTransaction(&transaction);
7560
7561 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7562 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7563
7564 MockTransaction transaction2(kTypicalGET_Transaction);
7565 AddMockTransaction(&transaction2);
7566
7567 // Make sure we are done with the previous transaction.
7568 base::RunLoop().RunUntilIdle();
7569
7570 // Load from the cache.
7571 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7572 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
7573
7574 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
7575 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7576 EXPECT_EQ(2, cache.disk_cache()->open_count());
7577 EXPECT_EQ(1, cache.disk_cache()->create_count());
7578 RemoveMockTransaction(&transaction2);
7579 }
7580
7581 // Tests that an externally conditionalized HEAD request updates the cache.
TEST_F(HttpCacheTest,TypicalHEAD_ConditionalizedRequestUpdatesResponse)7582 TEST_F(HttpCacheTest, TypicalHEAD_ConditionalizedRequestUpdatesResponse) {
7583 MockHttpCache cache;
7584 MockTransaction transaction(kTypicalGET_Transaction);
7585 AddMockTransaction(&transaction);
7586
7587 // Populate the cache.
7588 RunTransactionTest(cache.http_cache(), transaction);
7589
7590 // Update the cache.
7591 transaction.method = "HEAD";
7592 transaction.request_headers =
7593 "If-Modified-Since: Wed, 28 Nov 2007 00:40:09 GMT\r\n";
7594 transaction.response_headers = "Foo: bar\n";
7595 transaction.data = "";
7596 transaction.status = "HTTP/1.1 304 Not Modified\n";
7597 std::string headers;
7598 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7599 RemoveMockTransaction(&transaction);
7600
7601 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 304 Not Modified\n"));
7602 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7603
7604 MockTransaction transaction2(kTypicalGET_Transaction);
7605 AddMockTransaction(&transaction2);
7606
7607 // Make sure we are done with the previous transaction.
7608 base::RunLoop().RunUntilIdle();
7609
7610 // Load from the cache.
7611 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7612 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
7613
7614 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
7615 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7616 EXPECT_EQ(2, cache.disk_cache()->open_count());
7617 EXPECT_EQ(1, cache.disk_cache()->create_count());
7618 RemoveMockTransaction(&transaction2);
7619 }
7620
7621 // Tests that a HEAD request invalidates an old cached entry.
TEST_F(HttpCacheTest,SimpleHEAD_InvalidatesEntry)7622 TEST_F(HttpCacheTest, SimpleHEAD_InvalidatesEntry) {
7623 MockHttpCache cache;
7624 MockTransaction transaction(kTypicalGET_Transaction);
7625 AddMockTransaction(&transaction);
7626
7627 // Populate the cache.
7628 RunTransactionTest(cache.http_cache(), transaction);
7629
7630 // Update the cache.
7631 transaction.method = "HEAD";
7632 transaction.data = "";
7633 RunTransactionTest(cache.http_cache(), transaction);
7634 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7635
7636 // Load from the cache.
7637 transaction.method = "GET";
7638 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7639 transaction.start_return_code = ERR_CACHE_MISS;
7640 RunTransactionTest(cache.http_cache(), transaction);
7641
7642 RemoveMockTransaction(&transaction);
7643 }
7644
7645 // Tests that we do not cache the response of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Miss)7646 TEST_F(HttpCacheTest, SimplePUT_Miss) {
7647 MockHttpCache cache;
7648
7649 MockTransaction transaction(kSimplePOST_Transaction);
7650 transaction.method = "PUT";
7651
7652 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7653 element_readers.push_back(
7654 std::make_unique<UploadBytesElementReader>("hello", 5));
7655 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7656
7657 MockHttpRequest request(transaction);
7658 request.upload_data_stream = &upload_data_stream;
7659
7660 // Attempt to populate the cache.
7661 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7662 nullptr);
7663
7664 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7665 EXPECT_EQ(0, cache.disk_cache()->open_count());
7666 EXPECT_EQ(0, cache.disk_cache()->create_count());
7667 }
7668
7669 // Tests that we invalidate entries as a result of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Invalidate)7670 TEST_F(HttpCacheTest, SimplePUT_Invalidate) {
7671 MockHttpCache cache;
7672
7673 MockTransaction transaction(kSimpleGET_Transaction);
7674 MockHttpRequest req1(transaction);
7675
7676 // Attempt to populate the cache.
7677 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7678
7679 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7680 EXPECT_EQ(0, cache.disk_cache()->open_count());
7681 EXPECT_EQ(1, cache.disk_cache()->create_count());
7682
7683 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7684 element_readers.push_back(
7685 std::make_unique<UploadBytesElementReader>("hello", 5));
7686 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7687
7688 transaction.method = "PUT";
7689 MockHttpRequest req2(transaction);
7690 req2.upload_data_stream = &upload_data_stream;
7691
7692 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7693
7694 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7695 EXPECT_EQ(1, cache.disk_cache()->open_count());
7696 EXPECT_EQ(1, cache.disk_cache()->create_count());
7697
7698 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7699
7700 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7701 EXPECT_EQ(1, cache.disk_cache()->open_count());
7702 EXPECT_EQ(2, cache.disk_cache()->create_count());
7703 }
7704
7705 // Tests that we invalidate entries as a result of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Invalidate_305)7706 TEST_F(HttpCacheTest, SimplePUT_Invalidate_305) {
7707 MockHttpCache cache;
7708
7709 MockTransaction transaction(kSimpleGET_Transaction);
7710 AddMockTransaction(&transaction);
7711 MockHttpRequest req1(transaction);
7712
7713 // Attempt to populate the cache.
7714 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7715
7716 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7717 EXPECT_EQ(0, cache.disk_cache()->open_count());
7718 EXPECT_EQ(1, cache.disk_cache()->create_count());
7719
7720 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7721 element_readers.push_back(
7722 std::make_unique<UploadBytesElementReader>("hello", 5));
7723 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7724
7725 transaction.method = "PUT";
7726 transaction.status = "HTTP/1.1 305 Use Proxy";
7727 MockHttpRequest req2(transaction);
7728 req2.upload_data_stream = &upload_data_stream;
7729
7730 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7731
7732 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7733 EXPECT_EQ(1, cache.disk_cache()->open_count());
7734 EXPECT_EQ(1, cache.disk_cache()->create_count());
7735
7736 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7737
7738 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7739 EXPECT_EQ(1, cache.disk_cache()->open_count());
7740 EXPECT_EQ(2, cache.disk_cache()->create_count());
7741 RemoveMockTransaction(&transaction);
7742 }
7743
7744 // Tests that we don't invalidate entries as a result of a failed PUT.
TEST_F(HttpCacheTest,SimplePUT_DontInvalidate_404)7745 TEST_F(HttpCacheTest, SimplePUT_DontInvalidate_404) {
7746 MockHttpCache cache;
7747
7748 MockTransaction transaction(kSimpleGET_Transaction);
7749 AddMockTransaction(&transaction);
7750 MockHttpRequest req1(transaction);
7751
7752 // Attempt to populate the cache.
7753 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7754
7755 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7756 EXPECT_EQ(0, cache.disk_cache()->open_count());
7757 EXPECT_EQ(1, cache.disk_cache()->create_count());
7758
7759 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7760 element_readers.push_back(
7761 std::make_unique<UploadBytesElementReader>("hello", 5));
7762 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7763
7764 transaction.method = "PUT";
7765 transaction.status = "HTTP/1.1 404 Not Found";
7766 MockHttpRequest req2(transaction);
7767 req2.upload_data_stream = &upload_data_stream;
7768
7769 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7770
7771 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7772 EXPECT_EQ(1, cache.disk_cache()->open_count());
7773 EXPECT_EQ(1, cache.disk_cache()->create_count());
7774
7775 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7776
7777 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7778 EXPECT_EQ(2, cache.disk_cache()->open_count());
7779 EXPECT_EQ(1, cache.disk_cache()->create_count());
7780 RemoveMockTransaction(&transaction);
7781 }
7782
7783 // Tests that we do not cache the response of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Miss)7784 TEST_F(HttpCacheTest, SimpleDELETE_Miss) {
7785 MockHttpCache cache;
7786
7787 MockTransaction transaction(kSimplePOST_Transaction);
7788 transaction.method = "DELETE";
7789
7790 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7791 element_readers.push_back(
7792 std::make_unique<UploadBytesElementReader>("hello", 5));
7793 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7794
7795 MockHttpRequest request(transaction);
7796 request.upload_data_stream = &upload_data_stream;
7797
7798 // Attempt to populate the cache.
7799 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7800 nullptr);
7801
7802 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7803 EXPECT_EQ(0, cache.disk_cache()->open_count());
7804 EXPECT_EQ(0, cache.disk_cache()->create_count());
7805 }
7806
7807 // Tests that we invalidate entries as a result of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Invalidate)7808 TEST_F(HttpCacheTest, SimpleDELETE_Invalidate) {
7809 MockHttpCache cache;
7810
7811 MockTransaction transaction(kSimpleGET_Transaction);
7812 MockHttpRequest req1(transaction);
7813
7814 // Attempt to populate the cache.
7815 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7816
7817 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7818 EXPECT_EQ(0, cache.disk_cache()->open_count());
7819 EXPECT_EQ(1, cache.disk_cache()->create_count());
7820
7821 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7822 element_readers.push_back(
7823 std::make_unique<UploadBytesElementReader>("hello", 5));
7824 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7825
7826 transaction.method = "DELETE";
7827 MockHttpRequest req2(transaction);
7828 req2.upload_data_stream = &upload_data_stream;
7829
7830 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7831
7832 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7833 EXPECT_EQ(1, cache.disk_cache()->open_count());
7834 EXPECT_EQ(1, cache.disk_cache()->create_count());
7835
7836 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7837
7838 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7839 EXPECT_EQ(1, cache.disk_cache()->open_count());
7840 EXPECT_EQ(2, cache.disk_cache()->create_count());
7841 }
7842
7843 // Tests that we invalidate entries as a result of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Invalidate_301)7844 TEST_F(HttpCacheTest, SimpleDELETE_Invalidate_301) {
7845 MockHttpCache cache;
7846
7847 MockTransaction transaction(kSimpleGET_Transaction);
7848 AddMockTransaction(&transaction);
7849
7850 // Attempt to populate the cache.
7851 RunTransactionTest(cache.http_cache(), transaction);
7852
7853 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7854 EXPECT_EQ(0, cache.disk_cache()->open_count());
7855 EXPECT_EQ(1, cache.disk_cache()->create_count());
7856
7857 transaction.method = "DELETE";
7858 transaction.status = "HTTP/1.1 301 Moved Permanently ";
7859
7860 RunTransactionTest(cache.http_cache(), transaction);
7861
7862 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7863 EXPECT_EQ(1, cache.disk_cache()->open_count());
7864 EXPECT_EQ(1, cache.disk_cache()->create_count());
7865
7866 transaction.method = "GET";
7867 RunTransactionTest(cache.http_cache(), transaction);
7868
7869 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7870 EXPECT_EQ(1, cache.disk_cache()->open_count());
7871 EXPECT_EQ(2, cache.disk_cache()->create_count());
7872 RemoveMockTransaction(&transaction);
7873 }
7874
7875 // Tests that we don't invalidate entries as a result of a failed DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_DontInvalidate_416)7876 TEST_F(HttpCacheTest, SimpleDELETE_DontInvalidate_416) {
7877 MockHttpCache cache;
7878
7879 MockTransaction transaction(kSimpleGET_Transaction);
7880 AddMockTransaction(&transaction);
7881
7882 // Attempt to populate the cache.
7883 RunTransactionTest(cache.http_cache(), transaction);
7884
7885 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7886 EXPECT_EQ(0, cache.disk_cache()->open_count());
7887 EXPECT_EQ(1, cache.disk_cache()->create_count());
7888
7889 transaction.method = "DELETE";
7890 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
7891
7892 RunTransactionTest(cache.http_cache(), transaction);
7893
7894 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7895 EXPECT_EQ(1, cache.disk_cache()->open_count());
7896 EXPECT_EQ(1, cache.disk_cache()->create_count());
7897
7898 transaction.method = "GET";
7899 transaction.status = "HTTP/1.1 200 OK";
7900 RunTransactionTest(cache.http_cache(), transaction);
7901
7902 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7903 EXPECT_EQ(2, cache.disk_cache()->open_count());
7904 EXPECT_EQ(1, cache.disk_cache()->create_count());
7905 RemoveMockTransaction(&transaction);
7906 }
7907
7908 // Tests that we invalidate entries as a result of a PATCH.
TEST_F(HttpCacheTest,SimplePATCH_Invalidate)7909 TEST_F(HttpCacheTest, SimplePATCH_Invalidate) {
7910 MockHttpCache cache;
7911
7912 MockTransaction transaction(kSimpleGET_Transaction);
7913 MockHttpRequest req1(transaction);
7914
7915 // Attempt to populate the cache.
7916 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7917
7918 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7919 EXPECT_EQ(0, cache.disk_cache()->open_count());
7920 EXPECT_EQ(1, cache.disk_cache()->create_count());
7921
7922 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7923 element_readers.push_back(
7924 std::make_unique<UploadBytesElementReader>("hello", 5));
7925 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7926
7927 transaction.method = "PATCH";
7928 MockHttpRequest req2(transaction);
7929 req2.upload_data_stream = &upload_data_stream;
7930
7931 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7932
7933 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7934 EXPECT_EQ(1, cache.disk_cache()->open_count());
7935 EXPECT_EQ(1, cache.disk_cache()->create_count());
7936
7937 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7938
7939 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7940 EXPECT_EQ(1, cache.disk_cache()->open_count());
7941 EXPECT_EQ(2, cache.disk_cache()->create_count());
7942 }
7943
7944 // Tests that we invalidate entries as a result of a PATCH.
TEST_F(HttpCacheTest,SimplePATCH_Invalidate_301)7945 TEST_F(HttpCacheTest, SimplePATCH_Invalidate_301) {
7946 MockHttpCache cache;
7947
7948 MockTransaction transaction(kSimpleGET_Transaction);
7949 AddMockTransaction(&transaction);
7950
7951 // Attempt to populate the cache.
7952 RunTransactionTest(cache.http_cache(), transaction);
7953
7954 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7955 EXPECT_EQ(0, cache.disk_cache()->open_count());
7956 EXPECT_EQ(1, cache.disk_cache()->create_count());
7957
7958 transaction.method = "PATCH";
7959 transaction.status = "HTTP/1.1 301 Moved Permanently ";
7960
7961 RunTransactionTest(cache.http_cache(), transaction);
7962
7963 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7964 EXPECT_EQ(1, cache.disk_cache()->open_count());
7965 EXPECT_EQ(1, cache.disk_cache()->create_count());
7966
7967 transaction.method = "GET";
7968 RunTransactionTest(cache.http_cache(), transaction);
7969
7970 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7971 EXPECT_EQ(1, cache.disk_cache()->open_count());
7972 EXPECT_EQ(2, cache.disk_cache()->create_count());
7973 RemoveMockTransaction(&transaction);
7974 }
7975
7976 // Tests that we don't invalidate entries as a result of a failed PATCH.
TEST_F(HttpCacheTest,SimplePATCH_DontInvalidate_416)7977 TEST_F(HttpCacheTest, SimplePATCH_DontInvalidate_416) {
7978 MockHttpCache cache;
7979
7980 MockTransaction transaction(kSimpleGET_Transaction);
7981 AddMockTransaction(&transaction);
7982
7983 // Attempt to populate the cache.
7984 RunTransactionTest(cache.http_cache(), transaction);
7985
7986 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7987 EXPECT_EQ(0, cache.disk_cache()->open_count());
7988 EXPECT_EQ(1, cache.disk_cache()->create_count());
7989
7990 transaction.method = "PATCH";
7991 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
7992
7993 RunTransactionTest(cache.http_cache(), transaction);
7994
7995 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7996 EXPECT_EQ(1, cache.disk_cache()->open_count());
7997 EXPECT_EQ(1, cache.disk_cache()->create_count());
7998
7999 transaction.method = "GET";
8000 transaction.status = "HTTP/1.1 200 OK";
8001 RunTransactionTest(cache.http_cache(), transaction);
8002
8003 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8004 EXPECT_EQ(2, cache.disk_cache()->open_count());
8005 EXPECT_EQ(1, cache.disk_cache()->create_count());
8006 RemoveMockTransaction(&transaction);
8007 }
8008
8009 // Tests that we don't invalidate entries after a failed network transaction.
TEST_F(HttpCacheTest,SimpleGET_DontInvalidateOnFailure)8010 TEST_F(HttpCacheTest, SimpleGET_DontInvalidateOnFailure) {
8011 MockHttpCache cache;
8012
8013 // Populate the cache.
8014 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
8015 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8016
8017 // Fail the network request.
8018 MockTransaction transaction(kSimpleGET_Transaction);
8019 transaction.start_return_code = ERR_FAILED;
8020 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8021
8022 AddMockTransaction(&transaction);
8023 RunTransactionTest(cache.http_cache(), transaction);
8024 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8025 RemoveMockTransaction(&transaction);
8026
8027 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
8028 transaction.start_return_code = OK;
8029 AddMockTransaction(&transaction);
8030 RunTransactionTest(cache.http_cache(), transaction);
8031
8032 // Make sure the transaction didn't reach the network.
8033 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8034 RemoveMockTransaction(&transaction);
8035 }
8036
TEST_F(HttpCacheTest,RangeGET_SkipsCache)8037 TEST_F(HttpCacheTest, RangeGET_SkipsCache) {
8038 MockHttpCache cache;
8039
8040 // Test that we skip the cache for range GET requests. Eventually, we will
8041 // want to cache these, but we'll still have cases where skipping the cache
8042 // makes sense, so we want to make sure that it works properly.
8043
8044 RunTransactionTest(cache.http_cache(), kRangeGET_Transaction);
8045
8046 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8047 EXPECT_EQ(0, cache.disk_cache()->open_count());
8048 EXPECT_EQ(0, cache.disk_cache()->create_count());
8049
8050 MockTransaction transaction(kSimpleGET_Transaction);
8051 transaction.request_headers = "If-None-Match: foo\r\n";
8052 RunTransactionTest(cache.http_cache(), transaction);
8053
8054 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8055 EXPECT_EQ(0, cache.disk_cache()->open_count());
8056 EXPECT_EQ(0, cache.disk_cache()->create_count());
8057
8058 transaction.request_headers =
8059 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n";
8060 RunTransactionTest(cache.http_cache(), transaction);
8061
8062 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8063 EXPECT_EQ(0, cache.disk_cache()->open_count());
8064 EXPECT_EQ(0, cache.disk_cache()->create_count());
8065 }
8066
8067 // Test that we skip the cache for range requests that include a validation
8068 // header.
TEST_F(HttpCacheTest,RangeGET_SkipsCache2)8069 TEST_F(HttpCacheTest, RangeGET_SkipsCache2) {
8070 MockHttpCache cache;
8071
8072 MockTransaction transaction(kRangeGET_Transaction);
8073 transaction.request_headers = "If-None-Match: foo\r\n"
8074 EXTRA_HEADER
8075 "Range: bytes = 40-49\r\n";
8076 RunTransactionTest(cache.http_cache(), transaction);
8077
8078 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8079 EXPECT_EQ(0, cache.disk_cache()->open_count());
8080 EXPECT_EQ(0, cache.disk_cache()->create_count());
8081
8082 transaction.request_headers =
8083 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n"
8084 EXTRA_HEADER
8085 "Range: bytes = 40-49\r\n";
8086 RunTransactionTest(cache.http_cache(), transaction);
8087
8088 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8089 EXPECT_EQ(0, cache.disk_cache()->open_count());
8090 EXPECT_EQ(0, cache.disk_cache()->create_count());
8091
8092 transaction.request_headers = "If-Range: bla\r\n"
8093 EXTRA_HEADER
8094 "Range: bytes = 40-49\r\n";
8095 RunTransactionTest(cache.http_cache(), transaction);
8096
8097 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8098 EXPECT_EQ(0, cache.disk_cache()->open_count());
8099 EXPECT_EQ(0, cache.disk_cache()->create_count());
8100 }
8101
TEST_F(HttpCacheTest,SimpleGET_DoesntLogHeaders)8102 TEST_F(HttpCacheTest, SimpleGET_DoesntLogHeaders) {
8103 MockHttpCache cache;
8104
8105 RecordingNetLogObserver net_log_observer;
8106 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction,
8107 NetLogWithSource::Make(NetLogSourceType::NONE));
8108
8109 EXPECT_FALSE(LogContainsEventType(
8110 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8111 }
8112
TEST_F(HttpCacheTest,RangeGET_LogsHeaders)8113 TEST_F(HttpCacheTest, RangeGET_LogsHeaders) {
8114 MockHttpCache cache;
8115
8116 RecordingNetLogObserver net_log_observer;
8117 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_Transaction,
8118 NetLogWithSource::Make(NetLogSourceType::NONE));
8119
8120 EXPECT_TRUE(LogContainsEventType(
8121 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8122 }
8123
TEST_F(HttpCacheTest,ExternalValidation_LogsHeaders)8124 TEST_F(HttpCacheTest, ExternalValidation_LogsHeaders) {
8125 MockHttpCache cache;
8126
8127 RecordingNetLogObserver net_log_observer;
8128 MockTransaction transaction(kSimpleGET_Transaction);
8129 transaction.request_headers = "If-None-Match: foo\r\n" EXTRA_HEADER;
8130 RunTransactionTestWithLog(cache.http_cache(), transaction,
8131 NetLogWithSource::Make(NetLogSourceType::NONE));
8132
8133 EXPECT_TRUE(LogContainsEventType(
8134 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8135 }
8136
TEST_F(HttpCacheTest,SpecialHeaders_LogsHeaders)8137 TEST_F(HttpCacheTest, SpecialHeaders_LogsHeaders) {
8138 MockHttpCache cache;
8139
8140 RecordingNetLogObserver net_log_observer;
8141 MockTransaction transaction(kSimpleGET_Transaction);
8142 transaction.request_headers = "cache-control: no-cache\r\n" EXTRA_HEADER;
8143 RunTransactionTestWithLog(cache.http_cache(), transaction,
8144 NetLogWithSource::Make(NetLogSourceType::NONE));
8145
8146 EXPECT_TRUE(LogContainsEventType(
8147 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8148 }
8149
8150 // Tests that receiving 206 for a regular request is handled correctly.
TEST_F(HttpCacheTest,GET_Crazy206)8151 TEST_F(HttpCacheTest, GET_Crazy206) {
8152 MockHttpCache cache;
8153
8154 // Write to the cache.
8155 MockTransaction transaction(kRangeGET_TransactionOK);
8156 AddMockTransaction(&transaction);
8157 transaction.request_headers = EXTRA_HEADER;
8158 transaction.handler = MockTransactionHandler();
8159 RunTransactionTest(cache.http_cache(), transaction);
8160
8161 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8162 EXPECT_EQ(0, cache.disk_cache()->open_count());
8163 EXPECT_EQ(1, cache.disk_cache()->create_count());
8164
8165 // This should read again from the net.
8166 RunTransactionTest(cache.http_cache(), transaction);
8167
8168 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8169 EXPECT_EQ(0, cache.disk_cache()->open_count());
8170 EXPECT_EQ(2, cache.disk_cache()->create_count());
8171 RemoveMockTransaction(&transaction);
8172 }
8173
8174 // Tests that receiving 416 for a regular request is handled correctly.
TEST_F(HttpCacheTest,GET_Crazy416)8175 TEST_F(HttpCacheTest, GET_Crazy416) {
8176 MockHttpCache cache;
8177
8178 // Write to the cache.
8179 MockTransaction transaction(kSimpleGET_Transaction);
8180 AddMockTransaction(&transaction);
8181 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
8182 RunTransactionTest(cache.http_cache(), transaction);
8183
8184 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8185 EXPECT_EQ(0, cache.disk_cache()->open_count());
8186 EXPECT_EQ(1, cache.disk_cache()->create_count());
8187
8188 RemoveMockTransaction(&transaction);
8189 }
8190
8191 // Tests that we don't store partial responses that can't be validated.
TEST_F(HttpCacheTest,RangeGET_NoStrongValidators)8192 TEST_F(HttpCacheTest, RangeGET_NoStrongValidators) {
8193 MockHttpCache cache;
8194 std::string headers;
8195
8196 // Attempt to write to the cache (40-49).
8197 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8198 transaction.response_headers = "Content-Length: 10\n"
8199 "Cache-Control: max-age=3600\n"
8200 "ETag: w/\"foo\"\n";
8201 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8202
8203 Verify206Response(headers, 40, 49);
8204 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8205 EXPECT_EQ(0, cache.disk_cache()->open_count());
8206 EXPECT_EQ(1, cache.disk_cache()->create_count());
8207
8208 // Now verify that there's no cached data.
8209 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8210 &headers);
8211
8212 Verify206Response(headers, 40, 49);
8213 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8214 EXPECT_EQ(0, cache.disk_cache()->open_count());
8215 EXPECT_EQ(2, cache.disk_cache()->create_count());
8216 }
8217
8218 // Tests failures to conditionalize byte range requests.
TEST_F(HttpCacheTest,RangeGET_NoConditionalization)8219 TEST_F(HttpCacheTest, RangeGET_NoConditionalization) {
8220 MockHttpCache cache;
8221 cache.FailConditionalizations();
8222 std::string headers;
8223
8224 // Write to the cache (40-49).
8225 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8226 transaction.response_headers = "Content-Length: 10\n"
8227 "ETag: \"foo\"\n";
8228 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8229
8230 Verify206Response(headers, 40, 49);
8231 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8232 EXPECT_EQ(0, cache.disk_cache()->open_count());
8233 EXPECT_EQ(1, cache.disk_cache()->create_count());
8234
8235 // Now verify that the cached data is not used.
8236 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8237 &headers);
8238
8239 Verify206Response(headers, 40, 49);
8240 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8241 EXPECT_EQ(1, cache.disk_cache()->open_count());
8242 EXPECT_EQ(2, cache.disk_cache()->create_count());
8243 }
8244
8245 // Tests that restarting a partial request when the cached data cannot be
8246 // revalidated logs an event.
TEST_F(HttpCacheTest,RangeGET_NoValidation_LogsRestart)8247 TEST_F(HttpCacheTest, RangeGET_NoValidation_LogsRestart) {
8248 MockHttpCache cache;
8249 cache.FailConditionalizations();
8250
8251 // Write to the cache (40-49).
8252 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8253 transaction.response_headers = "Content-Length: 10\n"
8254 "ETag: \"foo\"\n";
8255 RunTransactionTest(cache.http_cache(), transaction);
8256
8257 // Now verify that the cached data is not used.
8258 RecordingNetLogObserver net_log_observer;
8259 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_TransactionOK,
8260 NetLogWithSource::Make(NetLogSourceType::NONE));
8261
8262 EXPECT_TRUE(LogContainsEventType(
8263 net_log_observer, NetLogEventType::HTTP_CACHE_RESTART_PARTIAL_REQUEST));
8264 }
8265
8266 // Tests that a failure to conditionalize a regular request (no range) with a
8267 // sparse entry results in a full response.
TEST_F(HttpCacheTest,GET_NoConditionalization)8268 TEST_F(HttpCacheTest, GET_NoConditionalization) {
8269 for (bool use_memory_entry_data : {false, true}) {
8270 MockHttpCache cache;
8271 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
8272 cache.FailConditionalizations();
8273 std::string headers;
8274
8275 // Write to the cache (40-49).
8276 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8277 transaction.response_headers =
8278 "Content-Length: 10\n"
8279 "ETag: \"foo\"\n";
8280 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8281
8282 Verify206Response(headers, 40, 49);
8283 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8284 EXPECT_EQ(0, cache.disk_cache()->open_count());
8285 EXPECT_EQ(1, cache.disk_cache()->create_count());
8286
8287 // Now verify that the cached data is not used.
8288 // Don't ask for a range. The cache will attempt to use the cached data but
8289 // should discard it as it cannot be validated. A regular request should go
8290 // to the server and a new entry should be created.
8291 transaction.request_headers = EXTRA_HEADER;
8292 transaction.data = "Not a range";
8293 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8294
8295 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
8296 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8297 EXPECT_EQ(1, cache.disk_cache()->open_count());
8298 EXPECT_EQ(2, cache.disk_cache()->create_count());
8299
8300 // The last response was saved.
8301 RunTransactionTest(cache.http_cache(), transaction);
8302 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8303 if (use_memory_entry_data) {
8304 // The cache entry isn't really useful, since when
8305 // &RangeTransactionServer::RangeHandler gets a non-range request,
8306 // (the network transaction #2) it returns headers without ETag,
8307 // Last-Modified or caching headers, with a Date in 2007 (so no heuristic
8308 // freshness), so it's both expired and not conditionalizable --- so in
8309 // this branch we avoid opening it.
8310 EXPECT_EQ(1, cache.disk_cache()->open_count());
8311 EXPECT_EQ(3, cache.disk_cache()->create_count());
8312 } else {
8313 EXPECT_EQ(2, cache.disk_cache()->open_count());
8314 EXPECT_EQ(2, cache.disk_cache()->create_count());
8315 }
8316 }
8317 }
8318
8319 // Verifies that conditionalization failures when asking for a range that would
8320 // require the cache to modify the range to ask, result in a network request
8321 // that matches the user's one.
TEST_F(HttpCacheTest,RangeGET_NoConditionalization2)8322 TEST_F(HttpCacheTest, RangeGET_NoConditionalization2) {
8323 MockHttpCache cache;
8324 cache.FailConditionalizations();
8325 std::string headers;
8326
8327 // Write to the cache (40-49).
8328 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8329 transaction.response_headers = "Content-Length: 10\n"
8330 "ETag: \"foo\"\n";
8331 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8332
8333 Verify206Response(headers, 40, 49);
8334 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8335 EXPECT_EQ(0, cache.disk_cache()->open_count());
8336 EXPECT_EQ(1, cache.disk_cache()->create_count());
8337
8338 // Now verify that the cached data is not used.
8339 // Ask for a range that extends before and after the cached data so that the
8340 // cache would normally mix data from three sources. After deleting the entry,
8341 // the response will come from a single network request.
8342 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8343 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8344 transaction.response_headers = kRangeGET_TransactionOK.response_headers;
8345 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8346
8347 Verify206Response(headers, 20, 59);
8348 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8349 EXPECT_EQ(1, cache.disk_cache()->open_count());
8350 EXPECT_EQ(2, cache.disk_cache()->create_count());
8351
8352 // The last response was saved.
8353 RunTransactionTest(cache.http_cache(), transaction);
8354 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8355 EXPECT_EQ(2, cache.disk_cache()->open_count());
8356 EXPECT_EQ(2, cache.disk_cache()->create_count());
8357 }
8358
8359 // Tests that we cache partial responses that lack content-length.
TEST_F(HttpCacheTest,RangeGET_NoContentLength)8360 TEST_F(HttpCacheTest, RangeGET_NoContentLength) {
8361 MockHttpCache cache;
8362 std::string headers;
8363
8364 // Attempt to write to the cache (40-49).
8365 MockTransaction transaction(kRangeGET_TransactionOK);
8366 AddMockTransaction(&transaction);
8367 transaction.response_headers = "ETag: \"foo\"\n"
8368 "Accept-Ranges: bytes\n"
8369 "Content-Range: bytes 40-49/80\n";
8370 transaction.handler = MockTransactionHandler();
8371 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8372
8373 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8374 EXPECT_EQ(0, cache.disk_cache()->open_count());
8375 EXPECT_EQ(1, cache.disk_cache()->create_count());
8376
8377 // Now verify that there's no cached data.
8378 transaction.handler =
8379 base::BindRepeating(&RangeTransactionServer::RangeHandler);
8380 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8381 &headers);
8382
8383 Verify206Response(headers, 40, 49);
8384 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8385 EXPECT_EQ(1, cache.disk_cache()->open_count());
8386 EXPECT_EQ(1, cache.disk_cache()->create_count());
8387
8388 RemoveMockTransaction(&transaction);
8389 }
8390
8391 // Tests that we can cache range requests and fetch random blocks from the
8392 // cache and the network.
TEST_F(HttpCacheTest,RangeGET_OK)8393 TEST_F(HttpCacheTest, RangeGET_OK) {
8394 MockHttpCache cache;
8395 AddMockTransaction(&kRangeGET_TransactionOK);
8396 std::string headers;
8397
8398 // Write to the cache (40-49).
8399 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8400 &headers);
8401
8402 Verify206Response(headers, 40, 49);
8403 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8404 EXPECT_EQ(0, cache.disk_cache()->open_count());
8405 EXPECT_EQ(1, cache.disk_cache()->create_count());
8406
8407 // Read from the cache (40-49).
8408 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8409 &headers);
8410
8411 Verify206Response(headers, 40, 49);
8412 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8413 EXPECT_EQ(1, cache.disk_cache()->open_count());
8414 EXPECT_EQ(1, cache.disk_cache()->create_count());
8415
8416 // Make sure we are done with the previous transaction.
8417 base::RunLoop().RunUntilIdle();
8418
8419 // Write to the cache (30-39).
8420 MockTransaction transaction(kRangeGET_TransactionOK);
8421 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
8422 transaction.data = "rg: 30-39 ";
8423 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8424
8425 Verify206Response(headers, 30, 39);
8426 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8427 EXPECT_EQ(2, cache.disk_cache()->open_count());
8428 EXPECT_EQ(1, cache.disk_cache()->create_count());
8429
8430 // Make sure we are done with the previous transaction.
8431 base::RunLoop().RunUntilIdle();
8432
8433 // Write and read from the cache (20-59).
8434 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8435 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8436 LoadTimingInfo load_timing_info;
8437 RunTransactionTestWithResponseAndGetTiming(
8438 cache.http_cache(), transaction, &headers,
8439 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
8440
8441 Verify206Response(headers, 20, 59);
8442 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8443 EXPECT_EQ(3, cache.disk_cache()->open_count());
8444 EXPECT_EQ(1, cache.disk_cache()->create_count());
8445 TestLoadTimingNetworkRequest(load_timing_info);
8446
8447 RemoveMockTransaction(&kRangeGET_TransactionOK);
8448 }
8449
TEST_F(HttpCacheTest,RangeGET_CacheReadError)8450 TEST_F(HttpCacheTest, RangeGET_CacheReadError) {
8451 // Tests recovery on cache read error on range request.
8452 MockHttpCache cache;
8453 AddMockTransaction(&kRangeGET_TransactionOK);
8454 std::string headers;
8455
8456 // Write to the cache (40-49).
8457 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8458 &headers);
8459
8460 Verify206Response(headers, 40, 49);
8461 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8462 EXPECT_EQ(0, cache.disk_cache()->open_count());
8463 EXPECT_EQ(1, cache.disk_cache()->create_count());
8464
8465 cache.disk_cache()->set_soft_failures_one_instance(MockDiskEntry::FAIL_ALL);
8466
8467 // Try to read from the cache (40-49), which will fail quickly enough to
8468 // restart, due to the failure injected above. This should still be a range
8469 // request. (https://crbug.com/891212)
8470 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8471 &headers);
8472
8473 Verify206Response(headers, 40, 49);
8474 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8475 EXPECT_EQ(1, cache.disk_cache()->open_count());
8476 EXPECT_EQ(2, cache.disk_cache()->create_count());
8477
8478 RemoveMockTransaction(&kRangeGET_TransactionOK);
8479 }
8480
8481 // Tests that range requests with no-store get correct content-length
8482 // (https://crbug.com/700197).
TEST_F(HttpCacheTest,RangeGET_NoStore)8483 TEST_F(HttpCacheTest, RangeGET_NoStore) {
8484 MockHttpCache cache;
8485
8486 MockTransaction transaction(kRangeGET_TransactionOK);
8487 std::string response_headers = base::StrCat(
8488 {kRangeGET_TransactionOK.response_headers, "Cache-Control: no-store\n"});
8489 transaction.response_headers = response_headers.c_str();
8490 AddMockTransaction(&transaction);
8491
8492 std::string headers;
8493 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8494
8495 Verify206Response(headers, 40, 49);
8496 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8497 EXPECT_EQ(0, cache.disk_cache()->open_count());
8498 EXPECT_EQ(1, cache.disk_cache()->create_count());
8499
8500 RemoveMockTransaction(&transaction);
8501 }
8502
8503 // Tests a 304 setting no-store on existing 206 entry.
TEST_F(HttpCacheTest,RangeGET_NoStore304)8504 TEST_F(HttpCacheTest, RangeGET_NoStore304) {
8505 MockHttpCache cache;
8506
8507 MockTransaction transaction(kRangeGET_TransactionOK);
8508 std::string response_headers = base::StrCat(
8509 {kRangeGET_TransactionOK.response_headers, "Cache-Control: max-age=0\n"});
8510 transaction.response_headers = response_headers.c_str();
8511 AddMockTransaction(&transaction);
8512
8513 std::string headers;
8514 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8515
8516 Verify206Response(headers, 40, 49);
8517 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8518 EXPECT_EQ(0, cache.disk_cache()->open_count());
8519 EXPECT_EQ(1, cache.disk_cache()->create_count());
8520
8521 response_headers = base::StrCat(
8522 {kRangeGET_TransactionOK.response_headers, "Cache-Control: no-store\n"});
8523 transaction.response_headers = response_headers.c_str();
8524 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8525 Verify206Response(headers, 40, 49);
8526
8527 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8528 EXPECT_EQ(1, cache.disk_cache()->open_count());
8529 EXPECT_EQ(1, cache.disk_cache()->create_count());
8530
8531 // Fetch again, this one should be from newly created cache entry, due to
8532 // earlier no-store.
8533 transaction.response_headers = kRangeGET_TransactionOK.response_headers;
8534 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8535 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8536 EXPECT_EQ(1, cache.disk_cache()->open_count());
8537 EXPECT_EQ(2, cache.disk_cache()->create_count());
8538 Verify206Response(headers, 40, 49);
8539
8540 RemoveMockTransaction(&transaction);
8541 }
8542
8543 // Tests that we can cache range requests and fetch random blocks from the
8544 // cache and the network, with synchronous responses.
TEST_F(HttpCacheTest,RangeGET_SyncOK)8545 TEST_F(HttpCacheTest, RangeGET_SyncOK) {
8546 MockHttpCache cache;
8547
8548 MockTransaction transaction(kRangeGET_TransactionOK);
8549 transaction.test_mode = TEST_MODE_SYNC_ALL;
8550 AddMockTransaction(&transaction);
8551
8552 // Write to the cache (40-49).
8553 std::string headers;
8554 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8555
8556 Verify206Response(headers, 40, 49);
8557 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8558 EXPECT_EQ(0, cache.disk_cache()->open_count());
8559 EXPECT_EQ(1, cache.disk_cache()->create_count());
8560
8561 // Read from the cache (40-49).
8562 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8563
8564 Verify206Response(headers, 40, 49);
8565 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8566 EXPECT_EQ(0, cache.disk_cache()->open_count());
8567 EXPECT_EQ(1, cache.disk_cache()->create_count());
8568
8569 // Make sure we are done with the previous transaction.
8570 base::RunLoop().RunUntilIdle();
8571
8572 // Write to the cache (30-39).
8573 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
8574 transaction.data = "rg: 30-39 ";
8575 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8576
8577 Verify206Response(headers, 30, 39);
8578 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8579 EXPECT_EQ(1, cache.disk_cache()->open_count());
8580 EXPECT_EQ(1, cache.disk_cache()->create_count());
8581
8582 // Make sure we are done with the previous transaction.
8583 base::RunLoop().RunUntilIdle();
8584
8585 // Write and read from the cache (20-59).
8586 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8587 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8588 LoadTimingInfo load_timing_info;
8589 RunTransactionTestWithResponseAndGetTiming(
8590 cache.http_cache(), transaction, &headers,
8591 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
8592
8593 Verify206Response(headers, 20, 59);
8594 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8595 EXPECT_EQ(2, cache.disk_cache()->open_count());
8596 EXPECT_EQ(1, cache.disk_cache()->create_count());
8597 TestLoadTimingNetworkRequest(load_timing_info);
8598
8599 RemoveMockTransaction(&transaction);
8600 }
8601
8602 // Tests that if the previous transaction is cancelled while busy (doing sparse
8603 // IO), a new transaction (that reuses that same ActiveEntry) waits until the
8604 // entry is ready again.
TEST_F(HttpCacheTest,Sparse_WaitForEntry)8605 TEST_F(HttpCacheTest, Sparse_WaitForEntry) {
8606 MockHttpCache cache;
8607
8608 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8609
8610 // Create a sparse entry.
8611 RunTransactionTest(cache.http_cache(), transaction);
8612
8613 // Simulate a previous transaction being cancelled.
8614 disk_cache::Entry* entry;
8615 MockHttpRequest request(transaction);
8616 std::string cache_key =
8617 *cache.http_cache()->GenerateCacheKeyForRequest(&request);
8618 ASSERT_TRUE(cache.OpenBackendEntry(cache_key, &entry));
8619 entry->CancelSparseIO();
8620
8621 // Test with a range request.
8622 RunTransactionTest(cache.http_cache(), transaction);
8623
8624 // Now test with a regular request.
8625 entry->CancelSparseIO();
8626 transaction.request_headers = EXTRA_HEADER;
8627 transaction.data = kFullRangeData;
8628 RunTransactionTest(cache.http_cache(), transaction);
8629
8630 entry->Close();
8631 }
8632
8633 // Tests that we don't revalidate an entry unless we are required to do so.
TEST_F(HttpCacheTest,RangeGET_Revalidate1)8634 TEST_F(HttpCacheTest, RangeGET_Revalidate1) {
8635 MockHttpCache cache;
8636 std::string headers;
8637
8638 // Write to the cache (40-49).
8639 MockTransaction transaction(kRangeGET_TransactionOK);
8640 transaction.response_headers =
8641 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
8642 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n" // Should never expire.
8643 "ETag: \"foo\"\n"
8644 "Accept-Ranges: bytes\n"
8645 "Content-Length: 10\n";
8646 AddMockTransaction(&transaction);
8647 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8648
8649 Verify206Response(headers, 40, 49);
8650 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8651 EXPECT_EQ(0, cache.disk_cache()->open_count());
8652 EXPECT_EQ(1, cache.disk_cache()->create_count());
8653
8654 // Read from the cache (40-49).
8655 NetLogWithSource net_log_with_source =
8656 NetLogWithSource::Make(NetLogSourceType::NONE);
8657 LoadTimingInfo load_timing_info;
8658 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
8659 &headers, net_log_with_source,
8660 &load_timing_info);
8661
8662 Verify206Response(headers, 40, 49);
8663 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8664 EXPECT_EQ(1, cache.disk_cache()->open_count());
8665 EXPECT_EQ(1, cache.disk_cache()->create_count());
8666 TestLoadTimingCachedResponse(load_timing_info);
8667
8668 // Read again forcing the revalidation.
8669 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8670 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
8671 &headers, net_log_with_source,
8672 &load_timing_info);
8673
8674 Verify206Response(headers, 40, 49);
8675 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8676 EXPECT_EQ(1, cache.disk_cache()->open_count());
8677 EXPECT_EQ(1, cache.disk_cache()->create_count());
8678 TestLoadTimingNetworkRequest(load_timing_info);
8679
8680 RemoveMockTransaction(&transaction);
8681 }
8682
8683 // Checks that we revalidate an entry when the headers say so.
TEST_F(HttpCacheTest,RangeGET_Revalidate2)8684 TEST_F(HttpCacheTest, RangeGET_Revalidate2) {
8685 MockHttpCache cache;
8686 std::string headers;
8687
8688 // Write to the cache (40-49).
8689 MockTransaction transaction(kRangeGET_TransactionOK);
8690 transaction.response_headers =
8691 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
8692 "Expires: Sat, 18 Apr 2009 01:10:43 GMT\n" // Expired.
8693 "ETag: \"foo\"\n"
8694 "Accept-Ranges: bytes\n"
8695 "Content-Length: 10\n";
8696 AddMockTransaction(&transaction);
8697 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8698
8699 Verify206Response(headers, 40, 49);
8700 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8701 EXPECT_EQ(0, cache.disk_cache()->open_count());
8702 EXPECT_EQ(1, cache.disk_cache()->create_count());
8703
8704 // Read from the cache (40-49).
8705 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8706 Verify206Response(headers, 40, 49);
8707
8708 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8709 EXPECT_EQ(1, cache.disk_cache()->open_count());
8710 EXPECT_EQ(1, cache.disk_cache()->create_count());
8711
8712 RemoveMockTransaction(&transaction);
8713 }
8714
8715 // Tests that we deal with 304s for range requests.
TEST_F(HttpCacheTest,RangeGET_304)8716 TEST_F(HttpCacheTest, RangeGET_304) {
8717 MockHttpCache cache;
8718 AddMockTransaction(&kRangeGET_TransactionOK);
8719 std::string headers;
8720
8721 // Write to the cache (40-49).
8722 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8723 &headers);
8724
8725 Verify206Response(headers, 40, 49);
8726 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8727 EXPECT_EQ(0, cache.disk_cache()->open_count());
8728 EXPECT_EQ(1, cache.disk_cache()->create_count());
8729
8730 // Read from the cache (40-49).
8731 RangeTransactionServer handler;
8732 handler.set_not_modified(true);
8733 MockTransaction transaction(kRangeGET_TransactionOK);
8734 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8735 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8736
8737 Verify206Response(headers, 40, 49);
8738 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8739 EXPECT_EQ(1, cache.disk_cache()->open_count());
8740 EXPECT_EQ(1, cache.disk_cache()->create_count());
8741
8742 RemoveMockTransaction(&kRangeGET_TransactionOK);
8743 }
8744
8745 // Tests that we deal with 206s when revalidating range requests.
TEST_F(HttpCacheTest,RangeGET_ModifiedResult)8746 TEST_F(HttpCacheTest, RangeGET_ModifiedResult) {
8747 MockHttpCache cache;
8748 AddMockTransaction(&kRangeGET_TransactionOK);
8749 std::string headers;
8750
8751 // Write to the cache (40-49).
8752 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8753 &headers);
8754
8755 Verify206Response(headers, 40, 49);
8756 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8757 EXPECT_EQ(0, cache.disk_cache()->open_count());
8758 EXPECT_EQ(1, cache.disk_cache()->create_count());
8759
8760 // Attempt to read from the cache (40-49).
8761 RangeTransactionServer handler;
8762 handler.set_modified(true);
8763 MockTransaction transaction(kRangeGET_TransactionOK);
8764 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8765 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8766
8767 Verify206Response(headers, 40, 49);
8768 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8769 EXPECT_EQ(1, cache.disk_cache()->open_count());
8770 EXPECT_EQ(1, cache.disk_cache()->create_count());
8771
8772 // And the entry should be gone.
8773 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
8774 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8775 EXPECT_EQ(1, cache.disk_cache()->open_count());
8776 EXPECT_EQ(2, cache.disk_cache()->create_count());
8777
8778 RemoveMockTransaction(&kRangeGET_TransactionOK);
8779 }
8780
8781 // Tests that when a server returns 206 with a sub-range of the requested range,
8782 // and there is nothing stored in the cache, the returned response is passed to
8783 // the caller as is. In this context, a subrange means a response that starts
8784 // with the same byte that was requested, but that is not the whole range that
8785 // was requested.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSubrangeRange_NoCachedContent)8786 TEST_F(HttpCacheTest, RangeGET_206ReturnsSubrangeRange_NoCachedContent) {
8787 MockHttpCache cache;
8788 std::string headers;
8789
8790 // Request a large range (40-59). The server sends 40-49.
8791 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8792 transaction.request_headers = "Range: bytes = 40-59\r\n" EXTRA_HEADER;
8793 transaction.response_headers =
8794 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8795 "ETag: \"foo\"\n"
8796 "Accept-Ranges: bytes\n"
8797 "Content-Length: 10\n"
8798 "Content-Range: bytes 40-49/80\n";
8799 transaction.handler = MockTransactionHandler();
8800 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8801
8802 Verify206Response(headers, 40, 49);
8803 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8804 EXPECT_EQ(0, cache.disk_cache()->open_count());
8805 EXPECT_EQ(1, cache.disk_cache()->create_count());
8806 }
8807
8808 // Tests that when a server returns 206 with a sub-range of the requested range,
8809 // and there was an entry stored in the cache, the cache gets out of the way.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSubrangeRange_CachedContent)8810 TEST_F(HttpCacheTest, RangeGET_206ReturnsSubrangeRange_CachedContent) {
8811 MockHttpCache cache;
8812 std::string headers;
8813
8814 // Write to the cache (70-79).
8815 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8816 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8817 transaction.data = "rg: 70-79 ";
8818 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8819 Verify206Response(headers, 70, 79);
8820
8821 // Request a large range (40-79). The cache will ask the server for 40-59.
8822 // The server returns 40-49. The cache should consider the server confused and
8823 // abort caching, restarting the request without caching.
8824 transaction.request_headers = "Range: bytes = 40-79\r\n" EXTRA_HEADER;
8825 transaction.response_headers =
8826 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8827 "ETag: \"foo\"\n"
8828 "Accept-Ranges: bytes\n"
8829 "Content-Length: 10\n"
8830 "Content-Range: bytes 40-49/80\n";
8831 transaction.handler = MockTransactionHandler();
8832 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8833
8834 // Two new network requests were issued, one from the cache and another after
8835 // deleting the entry.
8836 Verify206Response(headers, 40, 49);
8837 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8838 EXPECT_EQ(1, cache.disk_cache()->open_count());
8839 EXPECT_EQ(1, cache.disk_cache()->create_count());
8840
8841 // The entry was deleted.
8842 RunTransactionTest(cache.http_cache(), transaction);
8843 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8844 EXPECT_EQ(1, cache.disk_cache()->open_count());
8845 EXPECT_EQ(2, cache.disk_cache()->create_count());
8846 }
8847
8848 // Tests that when a server returns 206 with a sub-range of the requested range,
8849 // and there was an entry stored in the cache, the cache gets out of the way,
8850 // when the caller is not using ranges.
TEST_F(HttpCacheTest,GET_206ReturnsSubrangeRange_CachedContent)8851 TEST_F(HttpCacheTest, GET_206ReturnsSubrangeRange_CachedContent) {
8852 MockHttpCache cache;
8853 std::string headers;
8854
8855 // Write to the cache (70-79).
8856 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8857 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8858 transaction.data = "rg: 70-79 ";
8859 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8860 Verify206Response(headers, 70, 79);
8861
8862 // Don't ask for a range. The cache will ask the server for 0-69.
8863 // The server returns 40-49. The cache should consider the server confused and
8864 // abort caching, restarting the request.
8865 // The second network request should not be a byte range request so the server
8866 // should return 200 + "Not a range"
8867 transaction.request_headers = "X-Return-Default-Range:\r\n" EXTRA_HEADER;
8868 transaction.data = "Not a range";
8869 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8870
8871 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
8872 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8873 EXPECT_EQ(1, cache.disk_cache()->open_count());
8874 EXPECT_EQ(1, cache.disk_cache()->create_count());
8875
8876 // The entry was deleted.
8877 RunTransactionTest(cache.http_cache(), transaction);
8878 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8879 EXPECT_EQ(1, cache.disk_cache()->open_count());
8880 EXPECT_EQ(2, cache.disk_cache()->create_count());
8881 }
8882
8883 // Tests that when a server returns 206 with a random range and there is
8884 // nothing stored in the cache, the returned response is passed to the caller
8885 // as is. In this context, a WrongRange means that the returned range may or may
8886 // not have any relationship with the requested range (may or may not be
8887 // contained). The important part is that the first byte doesn't match the first
8888 // requested byte.
TEST_F(HttpCacheTest,RangeGET_206ReturnsWrongRange_NoCachedContent)8889 TEST_F(HttpCacheTest, RangeGET_206ReturnsWrongRange_NoCachedContent) {
8890 MockHttpCache cache;
8891 std::string headers;
8892
8893 // Request a large range (30-59). The server sends (40-49).
8894 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8895 transaction.request_headers = "Range: bytes = 30-59\r\n" EXTRA_HEADER;
8896 transaction.response_headers =
8897 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8898 "ETag: \"foo\"\n"
8899 "Accept-Ranges: bytes\n"
8900 "Content-Length: 10\n"
8901 "Content-Range: bytes 40-49/80\n";
8902 transaction.handler = MockTransactionHandler();
8903 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8904
8905 Verify206Response(headers, 40, 49);
8906 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8907 EXPECT_EQ(0, cache.disk_cache()->open_count());
8908 EXPECT_EQ(1, cache.disk_cache()->create_count());
8909
8910 // The entry was deleted.
8911 RunTransactionTest(cache.http_cache(), transaction);
8912 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8913 EXPECT_EQ(0, cache.disk_cache()->open_count());
8914 EXPECT_EQ(2, cache.disk_cache()->create_count());
8915 }
8916
8917 // Tests that when a server returns 206 with a random range and there is
8918 // an entry stored in the cache, the cache gets out of the way.
TEST_F(HttpCacheTest,RangeGET_206ReturnsWrongRange_CachedContent)8919 TEST_F(HttpCacheTest, RangeGET_206ReturnsWrongRange_CachedContent) {
8920 MockHttpCache cache;
8921 std::string headers;
8922
8923 // Write to the cache (70-79).
8924 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8925 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8926 transaction.data = "rg: 70-79 ";
8927 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8928 Verify206Response(headers, 70, 79);
8929
8930 // Request a large range (30-79). The cache will ask the server for 30-69.
8931 // The server returns 40-49. The cache should consider the server confused and
8932 // abort caching, returning the weird range to the caller.
8933 transaction.request_headers = "Range: bytes = 30-79\r\n" EXTRA_HEADER;
8934 transaction.response_headers =
8935 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8936 "ETag: \"foo\"\n"
8937 "Accept-Ranges: bytes\n"
8938 "Content-Length: 10\n"
8939 "Content-Range: bytes 40-49/80\n";
8940 transaction.handler = MockTransactionHandler();
8941 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8942
8943 Verify206Response(headers, 40, 49);
8944 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8945 EXPECT_EQ(1, cache.disk_cache()->open_count());
8946 EXPECT_EQ(1, cache.disk_cache()->create_count());
8947
8948 // The entry was deleted.
8949 RunTransactionTest(cache.http_cache(), transaction);
8950 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8951 EXPECT_EQ(1, cache.disk_cache()->open_count());
8952 EXPECT_EQ(2, cache.disk_cache()->create_count());
8953 }
8954
8955 // Tests that when a caller asks for a range beyond EOF, with an empty cache,
8956 // the response matches the one provided by the server.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSmallerFile_NoCachedContent)8957 TEST_F(HttpCacheTest, RangeGET_206ReturnsSmallerFile_NoCachedContent) {
8958 MockHttpCache cache;
8959 std::string headers;
8960
8961 // Request a large range (70-99). The server sends 70-79.
8962 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8963 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
8964 transaction.data = "rg: 70-79 ";
8965 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8966
8967 Verify206Response(headers, 70, 79);
8968 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8969 EXPECT_EQ(0, cache.disk_cache()->open_count());
8970 EXPECT_EQ(1, cache.disk_cache()->create_count());
8971
8972 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
8973 EXPECT_EQ(1, cache.disk_cache()->open_count());
8974 }
8975
8976 // Tests that when a caller asks for a range beyond EOF, with a cached entry,
8977 // the cache automatically fixes the request.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSmallerFile_CachedContent)8978 TEST_F(HttpCacheTest, RangeGET_206ReturnsSmallerFile_CachedContent) {
8979 MockHttpCache cache;
8980 std::string headers;
8981
8982 // Write to the cache (40-49).
8983 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8984 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8985
8986 // Request a large range (70-99). The server sends 70-79.
8987 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
8988 transaction.data = "rg: 70-79 ";
8989 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8990
8991 Verify206Response(headers, 70, 79);
8992 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8993 EXPECT_EQ(1, cache.disk_cache()->open_count());
8994 EXPECT_EQ(1, cache.disk_cache()->create_count());
8995
8996 // The entry was not deleted (the range was automatically fixed).
8997 RunTransactionTest(cache.http_cache(), transaction);
8998 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8999 EXPECT_EQ(2, cache.disk_cache()->open_count());
9000 EXPECT_EQ(1, cache.disk_cache()->create_count());
9001 }
9002
9003 // Tests that when a caller asks for a not-satisfiable range, the server's
9004 // response is forwarded to the caller.
TEST_F(HttpCacheTest,RangeGET_416_NoCachedContent)9005 TEST_F(HttpCacheTest, RangeGET_416_NoCachedContent) {
9006 MockHttpCache cache;
9007 std::string headers;
9008
9009 // Request a range beyond EOF (80-99).
9010 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9011 transaction.request_headers = "Range: bytes = 80-99\r\n" EXTRA_HEADER;
9012 transaction.data = "";
9013 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
9014 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9015
9016 EXPECT_EQ(0U, headers.find(transaction.status));
9017 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9018 EXPECT_EQ(0, cache.disk_cache()->open_count());
9019 EXPECT_EQ(1, cache.disk_cache()->create_count());
9020
9021 // The entry was deleted.
9022 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9023 EXPECT_EQ(2, cache.disk_cache()->create_count());
9024 }
9025
9026 // Tests that we cache 301s for range requests.
TEST_F(HttpCacheTest,RangeGET_301)9027 TEST_F(HttpCacheTest, RangeGET_301) {
9028 MockHttpCache cache;
9029 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9030 transaction.status = "HTTP/1.1 301 Moved Permanently";
9031 transaction.response_headers = "Location: http://www.bar.com/\n";
9032 transaction.data = "";
9033 transaction.handler = MockTransactionHandler();
9034
9035 // Write to the cache.
9036 RunTransactionTest(cache.http_cache(), transaction);
9037 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9038 EXPECT_EQ(0, cache.disk_cache()->open_count());
9039 EXPECT_EQ(1, cache.disk_cache()->create_count());
9040
9041 // Read from the cache.
9042 RunTransactionTest(cache.http_cache(), transaction);
9043 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9044 EXPECT_EQ(1, cache.disk_cache()->open_count());
9045 EXPECT_EQ(1, cache.disk_cache()->create_count());
9046 }
9047
9048 // Tests that we can cache range requests when the start or end is unknown.
9049 // We start with one suffix request, followed by a request from a given point.
TEST_F(HttpCacheTest,UnknownRangeGET_1)9050 TEST_F(HttpCacheTest, UnknownRangeGET_1) {
9051 MockHttpCache cache;
9052 AddMockTransaction(&kRangeGET_TransactionOK);
9053 std::string headers;
9054
9055 // Write to the cache (70-79).
9056 MockTransaction transaction(kRangeGET_TransactionOK);
9057 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
9058 transaction.data = "rg: 70-79 ";
9059 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9060
9061 Verify206Response(headers, 70, 79);
9062 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9063 EXPECT_EQ(0, cache.disk_cache()->open_count());
9064 EXPECT_EQ(1, cache.disk_cache()->create_count());
9065
9066 // Make sure we are done with the previous transaction.
9067 base::RunLoop().RunUntilIdle();
9068
9069 // Write and read from the cache (60-79).
9070 transaction.request_headers = "Range: bytes = 60-\r\n" EXTRA_HEADER;
9071 transaction.data = "rg: 60-69 rg: 70-79 ";
9072 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9073
9074 Verify206Response(headers, 60, 79);
9075 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9076 EXPECT_EQ(1, cache.disk_cache()->open_count());
9077 EXPECT_EQ(1, cache.disk_cache()->create_count());
9078
9079 RemoveMockTransaction(&kRangeGET_TransactionOK);
9080 }
9081
9082 // Tests that we can cache range requests when the start or end is unknown.
9083 // We start with one request from a given point, followed by a suffix request.
9084 // We'll also verify that synchronous cache responses work as intended.
TEST_F(HttpCacheTest,UnknownRangeGET_2)9085 TEST_F(HttpCacheTest, UnknownRangeGET_2) {
9086 MockHttpCache cache;
9087 std::string headers;
9088
9089 MockTransaction transaction(kRangeGET_TransactionOK);
9090 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9091 TEST_MODE_SYNC_CACHE_READ |
9092 TEST_MODE_SYNC_CACHE_WRITE;
9093 AddMockTransaction(&transaction);
9094
9095 // Write to the cache (70-79).
9096 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
9097 transaction.data = "rg: 70-79 ";
9098 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9099
9100 Verify206Response(headers, 70, 79);
9101 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9102 EXPECT_EQ(0, cache.disk_cache()->open_count());
9103 EXPECT_EQ(1, cache.disk_cache()->create_count());
9104
9105 // Make sure we are done with the previous transaction.
9106 base::RunLoop().RunUntilIdle();
9107
9108 // Write and read from the cache (60-79).
9109 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
9110 transaction.data = "rg: 60-69 rg: 70-79 ";
9111 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9112
9113 Verify206Response(headers, 60, 79);
9114 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9115 EXPECT_EQ(1, cache.disk_cache()->open_count());
9116 EXPECT_EQ(1, cache.disk_cache()->create_count());
9117
9118 RemoveMockTransaction(&transaction);
9119 }
9120
9121 // Similar to UnknownRangeGET_2, except that the resource size is empty.
9122 // Regression test for crbug.com/813061, and probably https://crbug.com/1375128
TEST_F(HttpCacheTest,UnknownRangeGET_3)9123 TEST_F(HttpCacheTest, UnknownRangeGET_3) {
9124 MockHttpCache cache;
9125 std::string headers;
9126
9127 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9128 transaction.response_headers =
9129 "Cache-Control: max-age=10000\n"
9130 "Content-Length: 0\n",
9131 transaction.data = "";
9132 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9133 TEST_MODE_SYNC_CACHE_READ |
9134 TEST_MODE_SYNC_CACHE_WRITE;
9135
9136 // Write the empty resource to the cache.
9137 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9138
9139 EXPECT_EQ(
9140 "HTTP/1.1 200 OK\nCache-Control: max-age=10000\nContent-Length: 0\n",
9141 headers);
9142 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9143 EXPECT_EQ(0, cache.disk_cache()->open_count());
9144 EXPECT_EQ(1, cache.disk_cache()->create_count());
9145
9146 // Make sure we are done with the previous transaction.
9147 base::RunLoop().RunUntilIdle();
9148
9149 // Write and read from the cache. This used to trigger a DCHECK
9150 // (or loop infinitely with it off).
9151 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
9152 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9153
9154 EXPECT_EQ(
9155 "HTTP/1.1 200 OK\nCache-Control: max-age=10000\nContent-Length: 0\n",
9156 headers);
9157 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9158 EXPECT_EQ(1, cache.disk_cache()->open_count());
9159 EXPECT_EQ(1, cache.disk_cache()->create_count());
9160 }
9161
9162 // Testcase for https://crbug.com/1433305, validation of range request to a
9163 // cache 302, which is notably bodiless.
TEST_F(HttpCacheTest,UnknownRangeGET_302)9164 TEST_F(HttpCacheTest, UnknownRangeGET_302) {
9165 MockHttpCache cache;
9166 std::string headers;
9167
9168 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9169 transaction.status = "HTTP/1.1 302 Found";
9170 transaction.response_headers =
9171 "Cache-Control: max-age=0\n"
9172 "Content-Length: 0\n"
9173 "Location: https://example.org/\n",
9174
9175 transaction.data = "";
9176 transaction.request_headers = "Range: bytes = 0-\r\n" EXTRA_HEADER;
9177 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9178 TEST_MODE_SYNC_CACHE_READ |
9179 TEST_MODE_SYNC_CACHE_WRITE;
9180
9181 // Write the empty resource to the cache.
9182 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9183
9184 EXPECT_EQ(
9185 "HTTP/1.1 302 Found\n"
9186 "Cache-Control: max-age=0\n"
9187 "Content-Length: 0\n"
9188 "Location: https://example.org/\n",
9189 headers);
9190 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9191 EXPECT_EQ(0, cache.disk_cache()->open_count());
9192 EXPECT_EQ(1, cache.disk_cache()->create_count());
9193
9194 // Make sure we are done with the previous transaction.
9195 base::RunLoop().RunUntilIdle();
9196
9197 // Try to read from the cache. This should send a network request to
9198 // validate it, and get a different redirect.
9199 transaction.response_headers =
9200 "Cache-Control: max-age=0\n"
9201 "Content-Length: 0\n"
9202 "Location: https://example.com/\n",
9203 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9204
9205 EXPECT_EQ(
9206 "HTTP/1.1 302 Found\n"
9207 "Cache-Control: max-age=0\n"
9208 "Content-Length: 0\n"
9209 "Location: https://example.com/\n",
9210 headers);
9211 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9212 EXPECT_EQ(1, cache.disk_cache()->open_count());
9213 // A new entry is created since this one isn't conditionalizable.
9214 EXPECT_EQ(2, cache.disk_cache()->create_count());
9215 }
9216
9217 // Testcase for https://crbug.com/1433305, validation of range request to a
9218 // cache 302, which is notably bodiless, where the 302 is replaced with an
9219 // actual body.
TEST_F(HttpCacheTest,UnknownRangeGET_302_Replaced)9220 TEST_F(HttpCacheTest, UnknownRangeGET_302_Replaced) {
9221 MockHttpCache cache;
9222 std::string headers;
9223
9224 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9225 transaction.status = "HTTP/1.1 302 Found";
9226 transaction.response_headers =
9227 "Cache-Control: max-age=0\n"
9228 "Content-Length: 0\n"
9229 "Location: https://example.org/\n",
9230
9231 transaction.data = "";
9232 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9233 TEST_MODE_SYNC_CACHE_READ |
9234 TEST_MODE_SYNC_CACHE_WRITE;
9235
9236 // Write the empty resource to the cache.
9237 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9238
9239 EXPECT_EQ(
9240 "HTTP/1.1 302 Found\n"
9241 "Cache-Control: max-age=0\n"
9242 "Content-Length: 0\n"
9243 "Location: https://example.org/\n",
9244 headers);
9245 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9246 EXPECT_EQ(0, cache.disk_cache()->open_count());
9247 EXPECT_EQ(1, cache.disk_cache()->create_count());
9248
9249 // Make sure we are done with the previous transaction.
9250 base::RunLoop().RunUntilIdle();
9251
9252 // Try to read from the cache. This should send a network request to
9253 // validate it, and get a different response.
9254 transaction.handler =
9255 base::BindRepeating(&RangeTransactionServer::RangeHandler);
9256 transaction.request_headers = "Range: bytes = -30\r\n" EXTRA_HEADER;
9257 // Tail 30 bytes out of 80
9258 transaction.data = "rg: 50-59 rg: 60-69 rg: 70-79 ";
9259 transaction.status = "HTTP/1.1 206 Partial Content";
9260 transaction.response_headers = "Content-Length: 10\n";
9261 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9262
9263 EXPECT_EQ(
9264 "HTTP/1.1 206 Partial Content\n"
9265 "Content-Range: bytes 50-79/80\n"
9266 "Content-Length: 30\n",
9267 headers);
9268 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9269 EXPECT_EQ(1, cache.disk_cache()->open_count());
9270 // A new entry is created since this one isn't conditionalizable.
9271 EXPECT_EQ(2, cache.disk_cache()->create_count());
9272 }
9273
9274 // Tests that receiving Not Modified when asking for an open range doesn't mess
9275 // up things.
TEST_F(HttpCacheTest,UnknownRangeGET_304)9276 TEST_F(HttpCacheTest, UnknownRangeGET_304) {
9277 MockHttpCache cache;
9278 std::string headers;
9279
9280 MockTransaction transaction(kRangeGET_TransactionOK);
9281 AddMockTransaction(&transaction);
9282
9283 RangeTransactionServer handler;
9284 handler.set_not_modified(true);
9285
9286 // Ask for the end of the file, without knowing the length.
9287 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
9288 transaction.data = "";
9289 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9290
9291 // We just bypass the cache.
9292 EXPECT_EQ(0U, headers.find("HTTP/1.1 304 Not Modified\n"));
9293 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9294 EXPECT_EQ(0, cache.disk_cache()->open_count());
9295 EXPECT_EQ(1, cache.disk_cache()->create_count());
9296
9297 RunTransactionTest(cache.http_cache(), transaction);
9298 EXPECT_EQ(2, cache.disk_cache()->create_count());
9299
9300 RemoveMockTransaction(&transaction);
9301 }
9302
9303 // Tests that we can handle non-range requests when we have cached a range.
TEST_F(HttpCacheTest,GET_Previous206)9304 TEST_F(HttpCacheTest, GET_Previous206) {
9305 MockHttpCache cache;
9306 AddMockTransaction(&kRangeGET_TransactionOK);
9307 std::string headers;
9308 NetLogWithSource net_log_with_source =
9309 NetLogWithSource::Make(NetLogSourceType::NONE);
9310 LoadTimingInfo load_timing_info;
9311
9312 // Write to the cache (40-49).
9313 RunTransactionTestWithResponseAndGetTiming(
9314 cache.http_cache(), kRangeGET_TransactionOK, &headers,
9315 net_log_with_source, &load_timing_info);
9316
9317 Verify206Response(headers, 40, 49);
9318 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9319 EXPECT_EQ(0, cache.disk_cache()->open_count());
9320 EXPECT_EQ(1, cache.disk_cache()->create_count());
9321 TestLoadTimingNetworkRequest(load_timing_info);
9322
9323 // Write and read from the cache (0-79), when not asked for a range.
9324 MockTransaction transaction(kRangeGET_TransactionOK);
9325 transaction.request_headers = EXTRA_HEADER;
9326 transaction.data = kFullRangeData;
9327 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9328 &headers, net_log_with_source,
9329 &load_timing_info);
9330
9331 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9332 EXPECT_EQ(3, cache.network_layer()->transaction_count());
9333 EXPECT_EQ(1, cache.disk_cache()->open_count());
9334 EXPECT_EQ(1, cache.disk_cache()->create_count());
9335 TestLoadTimingNetworkRequest(load_timing_info);
9336
9337 RemoveMockTransaction(&kRangeGET_TransactionOK);
9338 }
9339
9340 // Tests that we can handle non-range requests when we have cached the first
9341 // part of the object and the server replies with 304 (Not Modified).
TEST_F(HttpCacheTest,GET_Previous206_NotModified)9342 TEST_F(HttpCacheTest, GET_Previous206_NotModified) {
9343 MockHttpCache cache;
9344
9345 MockTransaction transaction(kRangeGET_TransactionOK);
9346 AddMockTransaction(&transaction);
9347 std::string headers;
9348 NetLogWithSource net_log_with_source =
9349 NetLogWithSource::Make(NetLogSourceType::NONE);
9350
9351 LoadTimingInfo load_timing_info;
9352
9353 // Write to the cache (0-9).
9354 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
9355 transaction.data = "rg: 00-09 ";
9356 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9357 &headers, net_log_with_source,
9358 &load_timing_info);
9359 Verify206Response(headers, 0, 9);
9360 TestLoadTimingNetworkRequest(load_timing_info);
9361
9362 // Write to the cache (70-79).
9363 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
9364 transaction.data = "rg: 70-79 ";
9365 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9366 &headers, net_log_with_source,
9367 &load_timing_info);
9368 Verify206Response(headers, 70, 79);
9369
9370 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9371 EXPECT_EQ(1, cache.disk_cache()->open_count());
9372 EXPECT_EQ(1, cache.disk_cache()->create_count());
9373 TestLoadTimingNetworkRequest(load_timing_info);
9374
9375 // Read from the cache (0-9), write and read from cache (10 - 79).
9376 transaction.load_flags |= LOAD_VALIDATE_CACHE;
9377 transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER;
9378 transaction.data = kFullRangeData;
9379 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9380 &headers, net_log_with_source,
9381 &load_timing_info);
9382
9383 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9384 EXPECT_EQ(4, cache.network_layer()->transaction_count());
9385 EXPECT_EQ(2, cache.disk_cache()->open_count());
9386 EXPECT_EQ(1, cache.disk_cache()->create_count());
9387 TestLoadTimingNetworkRequest(load_timing_info);
9388
9389 RemoveMockTransaction(&transaction);
9390 }
9391
9392 // Tests that we can handle a regular request to a sparse entry, that results in
9393 // new content provided by the server (206).
TEST_F(HttpCacheTest,GET_Previous206_NewContent)9394 TEST_F(HttpCacheTest, GET_Previous206_NewContent) {
9395 MockHttpCache cache;
9396 AddMockTransaction(&kRangeGET_TransactionOK);
9397 std::string headers;
9398
9399 // Write to the cache (0-9).
9400 MockTransaction transaction(kRangeGET_TransactionOK);
9401 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
9402 transaction.data = "rg: 00-09 ";
9403 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9404
9405 Verify206Response(headers, 0, 9);
9406 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9407 EXPECT_EQ(0, cache.disk_cache()->open_count());
9408 EXPECT_EQ(1, cache.disk_cache()->create_count());
9409
9410 // Now we'll issue a request without any range that should result first in a
9411 // 206 (when revalidating), and then in a weird standard answer: the test
9412 // server will not modify the response so we'll get the default range... a
9413 // real server will answer with 200.
9414 MockTransaction transaction2(kRangeGET_TransactionOK);
9415 transaction2.request_headers = EXTRA_HEADER;
9416 transaction2.load_flags |= LOAD_VALIDATE_CACHE;
9417 transaction2.data = "Not a range";
9418 RangeTransactionServer handler;
9419 handler.set_modified(true);
9420 LoadTimingInfo load_timing_info;
9421 RunTransactionTestWithResponseAndGetTiming(
9422 cache.http_cache(), transaction2, &headers,
9423 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
9424
9425 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9426 EXPECT_EQ(3, cache.network_layer()->transaction_count());
9427 EXPECT_EQ(1, cache.disk_cache()->open_count());
9428 EXPECT_EQ(1, cache.disk_cache()->create_count());
9429 TestLoadTimingNetworkRequest(load_timing_info);
9430
9431 // Verify that the previous request deleted the entry.
9432 RunTransactionTest(cache.http_cache(), transaction);
9433 EXPECT_EQ(2, cache.disk_cache()->create_count());
9434
9435 RemoveMockTransaction(&transaction);
9436 }
9437
9438 // Tests that we can handle cached 206 responses that are not sparse.
TEST_F(HttpCacheTest,GET_Previous206_NotSparse)9439 TEST_F(HttpCacheTest, GET_Previous206_NotSparse) {
9440 MockHttpCache cache;
9441
9442 MockHttpRequest request(kSimpleGET_Transaction);
9443 // Create a disk cache entry that stores 206 headers while not being sparse.
9444 disk_cache::Entry* entry;
9445 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9446
9447 std::string raw_headers(kRangeGET_TransactionOK.status);
9448 raw_headers.append("\n");
9449 raw_headers.append(kRangeGET_TransactionOK.response_headers);
9450
9451 HttpResponseInfo response;
9452 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9453 HttpUtil::AssembleRawHeaders(raw_headers));
9454 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9455
9456 auto buf(base::MakeRefCounted<IOBufferWithSize>(500));
9457 int len = static_cast<int>(base::strlcpy(buf->data(),
9458 kRangeGET_TransactionOK.data, 500));
9459 TestCompletionCallback cb;
9460 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9461 EXPECT_EQ(len, cb.GetResult(rv));
9462 entry->Close();
9463
9464 // Now see that we don't use the stored entry.
9465 std::string headers;
9466 LoadTimingInfo load_timing_info;
9467 RunTransactionTestWithResponseAndGetTiming(
9468 cache.http_cache(), kSimpleGET_Transaction, &headers,
9469 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
9470
9471 // We are expecting a 200.
9472 std::string expected_headers(kSimpleGET_Transaction.status);
9473 expected_headers.append("\n");
9474 expected_headers.append(kSimpleGET_Transaction.response_headers);
9475 EXPECT_EQ(expected_headers, headers);
9476 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9477 EXPECT_EQ(1, cache.disk_cache()->open_count());
9478 EXPECT_EQ(2, cache.disk_cache()->create_count());
9479 TestLoadTimingNetworkRequest(load_timing_info);
9480 }
9481
9482 // Tests that we can handle cached 206 responses that are not sparse. This time
9483 // we issue a range request and expect to receive a range.
TEST_F(HttpCacheTest,RangeGET_Previous206_NotSparse_2)9484 TEST_F(HttpCacheTest, RangeGET_Previous206_NotSparse_2) {
9485 MockHttpCache cache;
9486 AddMockTransaction(&kRangeGET_TransactionOK);
9487
9488 // Create a disk cache entry that stores 206 headers while not being sparse.
9489 MockHttpRequest request(kRangeGET_TransactionOK);
9490 disk_cache::Entry* entry;
9491 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9492
9493 std::string raw_headers(kRangeGET_TransactionOK.status);
9494 raw_headers.append("\n");
9495 raw_headers.append(kRangeGET_TransactionOK.response_headers);
9496
9497 HttpResponseInfo response;
9498 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9499 HttpUtil::AssembleRawHeaders(raw_headers));
9500 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9501
9502 auto buf = base::MakeRefCounted<IOBufferWithSize>(500);
9503 int len = static_cast<int>(base::strlcpy(buf->data(),
9504 kRangeGET_TransactionOK.data, 500));
9505 TestCompletionCallback cb;
9506 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9507 EXPECT_EQ(len, cb.GetResult(rv));
9508 entry->Close();
9509
9510 // Now see that we don't use the stored entry.
9511 std::string headers;
9512 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9513 &headers);
9514
9515 // We are expecting a 206.
9516 Verify206Response(headers, 40, 49);
9517 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9518 EXPECT_EQ(1, cache.disk_cache()->open_count());
9519 EXPECT_EQ(2, cache.disk_cache()->create_count());
9520
9521 RemoveMockTransaction(&kRangeGET_TransactionOK);
9522 }
9523
9524 // Tests that we can handle cached 206 responses that can't be validated.
TEST_F(HttpCacheTest,GET_Previous206_NotValidation)9525 TEST_F(HttpCacheTest, GET_Previous206_NotValidation) {
9526 MockHttpCache cache;
9527
9528 MockHttpRequest request(kSimpleGET_Transaction);
9529 // Create a disk cache entry that stores 206 headers.
9530 disk_cache::Entry* entry;
9531 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9532
9533 // Make sure that the headers cannot be validated with the server.
9534 std::string raw_headers(kRangeGET_TransactionOK.status);
9535 raw_headers.append("\n");
9536 raw_headers.append("Content-Length: 80\n");
9537
9538 HttpResponseInfo response;
9539 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9540 HttpUtil::AssembleRawHeaders(raw_headers));
9541 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9542
9543 auto buf = base::MakeRefCounted<IOBufferWithSize>(500);
9544 int len = static_cast<int>(base::strlcpy(buf->data(),
9545 kRangeGET_TransactionOK.data, 500));
9546 TestCompletionCallback cb;
9547 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9548 EXPECT_EQ(len, cb.GetResult(rv));
9549 entry->Close();
9550
9551 // Now see that we don't use the stored entry.
9552 std::string headers;
9553 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction,
9554 &headers);
9555
9556 // We are expecting a 200.
9557 std::string expected_headers(kSimpleGET_Transaction.status);
9558 expected_headers.append("\n");
9559 expected_headers.append(kSimpleGET_Transaction.response_headers);
9560 EXPECT_EQ(expected_headers, headers);
9561 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9562 EXPECT_EQ(1, cache.disk_cache()->open_count());
9563 EXPECT_EQ(2, cache.disk_cache()->create_count());
9564 }
9565
9566 // Tests that we can handle range requests with cached 200 responses.
TEST_F(HttpCacheTest,RangeGET_Previous200)9567 TEST_F(HttpCacheTest, RangeGET_Previous200) {
9568 MockHttpCache cache;
9569
9570 // Store the whole thing with status 200.
9571 MockTransaction transaction(kTypicalGET_Transaction);
9572 transaction.url = kRangeGET_TransactionOK.url;
9573 transaction.data = kFullRangeData;
9574 AddMockTransaction(&transaction);
9575 RunTransactionTest(cache.http_cache(), transaction);
9576 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9577 EXPECT_EQ(0, cache.disk_cache()->open_count());
9578 EXPECT_EQ(1, cache.disk_cache()->create_count());
9579
9580 RemoveMockTransaction(&transaction);
9581 AddMockTransaction(&kRangeGET_TransactionOK);
9582
9583 // Now see that we use the stored entry.
9584 std::string headers;
9585 MockTransaction transaction2(kRangeGET_TransactionOK);
9586 RangeTransactionServer handler;
9587 handler.set_not_modified(true);
9588 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9589
9590 // We are expecting a 206.
9591 Verify206Response(headers, 40, 49);
9592 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9593 EXPECT_EQ(1, cache.disk_cache()->open_count());
9594 EXPECT_EQ(1, cache.disk_cache()->create_count());
9595
9596 // The last transaction has finished so make sure the entry is deactivated.
9597 base::RunLoop().RunUntilIdle();
9598
9599 // Make a request for an invalid range.
9600 MockTransaction transaction3(kRangeGET_TransactionOK);
9601 transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER;
9602 transaction3.data = transaction.data;
9603 transaction3.load_flags = LOAD_SKIP_CACHE_VALIDATION;
9604 RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers);
9605 EXPECT_EQ(2, cache.disk_cache()->open_count());
9606 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 "));
9607 EXPECT_EQ(std::string::npos, headers.find("Content-Range:"));
9608 EXPECT_EQ(std::string::npos, headers.find("Content-Length: 80"));
9609
9610 // Make sure the entry is deactivated.
9611 base::RunLoop().RunUntilIdle();
9612
9613 // Even though the request was invalid, we should have the entry.
9614 RunTransactionTest(cache.http_cache(), transaction2);
9615 EXPECT_EQ(3, cache.disk_cache()->open_count());
9616
9617 // Make sure the entry is deactivated.
9618 base::RunLoop().RunUntilIdle();
9619
9620 // Now we should receive a range from the server and drop the stored entry.
9621 handler.set_not_modified(false);
9622 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
9623 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9624 Verify206Response(headers, 40, 49);
9625 EXPECT_EQ(4, cache.network_layer()->transaction_count());
9626 EXPECT_EQ(4, cache.disk_cache()->open_count());
9627 EXPECT_EQ(1, cache.disk_cache()->create_count());
9628
9629 RunTransactionTest(cache.http_cache(), transaction2);
9630 EXPECT_EQ(2, cache.disk_cache()->create_count());
9631
9632 RemoveMockTransaction(&kRangeGET_TransactionOK);
9633 }
9634
9635 // Tests that we can handle a 200 response when dealing with sparse entries.
TEST_F(HttpCacheTest,RangeRequestResultsIn200)9636 TEST_F(HttpCacheTest, RangeRequestResultsIn200) {
9637 MockHttpCache cache;
9638 AddMockTransaction(&kRangeGET_TransactionOK);
9639 std::string headers;
9640
9641 // Write to the cache (70-79).
9642 MockTransaction transaction(kRangeGET_TransactionOK);
9643 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
9644 transaction.data = "rg: 70-79 ";
9645 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9646
9647 Verify206Response(headers, 70, 79);
9648 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9649 EXPECT_EQ(0, cache.disk_cache()->open_count());
9650 EXPECT_EQ(1, cache.disk_cache()->create_count());
9651
9652 // Now we'll issue a request that results in a plain 200 response, but to
9653 // the to the same URL that we used to store sparse data, and making sure
9654 // that we ask for a range.
9655 RemoveMockTransaction(&kRangeGET_TransactionOK);
9656 MockTransaction transaction2(kSimpleGET_Transaction);
9657 transaction2.url = kRangeGET_TransactionOK.url;
9658 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
9659 AddMockTransaction(&transaction2);
9660
9661 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9662
9663 std::string expected_headers(kSimpleGET_Transaction.status);
9664 expected_headers.append("\n");
9665 expected_headers.append(kSimpleGET_Transaction.response_headers);
9666 EXPECT_EQ(expected_headers, headers);
9667 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9668 EXPECT_EQ(1, cache.disk_cache()->open_count());
9669 EXPECT_EQ(1, cache.disk_cache()->create_count());
9670
9671 RemoveMockTransaction(&transaction2);
9672 }
9673
9674 // Tests that a range request that falls outside of the size that we know about
9675 // only deletes the entry if the resource has indeed changed.
TEST_F(HttpCacheTest,RangeGET_MoreThanCurrentSize)9676 TEST_F(HttpCacheTest, RangeGET_MoreThanCurrentSize) {
9677 MockHttpCache cache;
9678 AddMockTransaction(&kRangeGET_TransactionOK);
9679 std::string headers;
9680
9681 // Write to the cache (40-49).
9682 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9683 &headers);
9684
9685 Verify206Response(headers, 40, 49);
9686 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9687 EXPECT_EQ(0, cache.disk_cache()->open_count());
9688 EXPECT_EQ(1, cache.disk_cache()->create_count());
9689
9690 // A weird request should not delete this entry. Ask for bytes 120-.
9691 MockTransaction transaction(kRangeGET_TransactionOK);
9692 transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER;
9693 transaction.data = "";
9694 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9695
9696 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
9697 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9698 EXPECT_EQ(1, cache.disk_cache()->open_count());
9699 EXPECT_EQ(1, cache.disk_cache()->create_count());
9700
9701 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9702 EXPECT_EQ(2, cache.disk_cache()->open_count());
9703 EXPECT_EQ(1, cache.disk_cache()->create_count());
9704
9705 RemoveMockTransaction(&kRangeGET_TransactionOK);
9706 }
9707
9708 // Tests that we don't delete a sparse entry when we cancel a request.
TEST_F(HttpCacheTest,RangeGET_Cancel)9709 TEST_F(HttpCacheTest, RangeGET_Cancel) {
9710 MockHttpCache cache;
9711 AddMockTransaction(&kRangeGET_TransactionOK);
9712
9713 MockHttpRequest request(kRangeGET_TransactionOK);
9714
9715 auto c = std::make_unique<Context>();
9716 int rv = cache.CreateTransaction(&c->trans);
9717 ASSERT_THAT(rv, IsOk());
9718
9719 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9720 if (rv == ERR_IO_PENDING)
9721 rv = c->callback.WaitForResult();
9722
9723 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9724 EXPECT_EQ(0, cache.disk_cache()->open_count());
9725 EXPECT_EQ(1, cache.disk_cache()->create_count());
9726
9727 // Make sure that the entry has some data stored.
9728 scoped_refptr<IOBufferWithSize> buf =
9729 base::MakeRefCounted<IOBufferWithSize>(10);
9730 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9731 if (rv == ERR_IO_PENDING)
9732 rv = c->callback.WaitForResult();
9733 EXPECT_EQ(buf->size(), rv);
9734
9735 // Destroy the transaction.
9736 c.reset();
9737
9738 // Verify that the entry has not been deleted.
9739 disk_cache::Entry* entry;
9740 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9741 entry->Close();
9742 RemoveMockTransaction(&kRangeGET_TransactionOK);
9743 }
9744
9745 // Tests that we don't mark an entry as truncated if it is partial and not
9746 // already truncated.
TEST_F(HttpCacheTest,RangeGET_CancelWhileReading)9747 TEST_F(HttpCacheTest, RangeGET_CancelWhileReading) {
9748 MockHttpCache cache;
9749 AddMockTransaction(&kRangeGET_TransactionOK);
9750
9751 MockHttpRequest request(kRangeGET_TransactionOK);
9752
9753 auto context = std::make_unique<Context>();
9754 int rv = cache.CreateTransaction(&context->trans);
9755 ASSERT_THAT(rv, IsOk());
9756
9757 rv = context->trans->Start(&request, context->callback.callback(),
9758 NetLogWithSource());
9759 if (rv == ERR_IO_PENDING)
9760 rv = context->callback.WaitForResult();
9761
9762 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9763 EXPECT_EQ(0, cache.disk_cache()->open_count());
9764 EXPECT_EQ(1, cache.disk_cache()->create_count());
9765
9766 // Start Read.
9767 scoped_refptr<IOBufferWithSize> buf =
9768 base::MakeRefCounted<IOBufferWithSize>(5);
9769 rv = context->trans->Read(buf.get(), buf->size(),
9770 context->callback.callback());
9771 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9772
9773 // Destroy the transaction.
9774 context.reset();
9775
9776 // Complete Read.
9777 base::RunLoop().RunUntilIdle();
9778
9779 // Verify that the entry has not been marked as truncated.
9780 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 0);
9781 RemoveMockTransaction(&kRangeGET_TransactionOK);
9782 }
9783
9784 // Tests that we don't delete a sparse entry when we start a new request after
9785 // cancelling the previous one.
TEST_F(HttpCacheTest,RangeGET_Cancel2)9786 TEST_F(HttpCacheTest, RangeGET_Cancel2) {
9787 MockHttpCache cache;
9788 AddMockTransaction(&kRangeGET_TransactionOK);
9789
9790 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9791 MockHttpRequest request(kRangeGET_TransactionOK);
9792 request.load_flags |= LOAD_VALIDATE_CACHE;
9793
9794 auto c = std::make_unique<Context>();
9795 int rv = cache.CreateTransaction(&c->trans);
9796 ASSERT_THAT(rv, IsOk());
9797
9798 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9799 if (rv == ERR_IO_PENDING)
9800 rv = c->callback.WaitForResult();
9801
9802 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9803 EXPECT_EQ(1, cache.disk_cache()->open_count());
9804 EXPECT_EQ(1, cache.disk_cache()->create_count());
9805
9806 // Make sure that we revalidate the entry and read from the cache (a single
9807 // read will return while waiting for the network).
9808 scoped_refptr<IOBufferWithSize> buf =
9809 base::MakeRefCounted<IOBufferWithSize>(5);
9810 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9811 EXPECT_EQ(5, c->callback.GetResult(rv));
9812 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9813 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9814
9815 // Destroy the transaction before completing the read.
9816 c.reset();
9817
9818 // We have the read and the delete (OnProcessPendingQueue) waiting on the
9819 // message loop. This means that a new transaction will just reuse the same
9820 // active entry (no open or create).
9821
9822 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9823
9824 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9825 EXPECT_EQ(1, cache.disk_cache()->open_count());
9826 EXPECT_EQ(1, cache.disk_cache()->create_count());
9827 RemoveMockTransaction(&kRangeGET_TransactionOK);
9828 }
9829
9830 // A slight variation of the previous test, this time we cancel two requests in
9831 // a row, making sure that the second is waiting for the entry to be ready.
TEST_F(HttpCacheTest,RangeGET_Cancel3)9832 TEST_F(HttpCacheTest, RangeGET_Cancel3) {
9833 MockHttpCache cache;
9834 AddMockTransaction(&kRangeGET_TransactionOK);
9835
9836 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9837 MockHttpRequest request(kRangeGET_TransactionOK);
9838 request.load_flags |= LOAD_VALIDATE_CACHE;
9839
9840 auto c = std::make_unique<Context>();
9841 int rv = cache.CreateTransaction(&c->trans);
9842 ASSERT_THAT(rv, IsOk());
9843
9844 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9845 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9846 rv = c->callback.WaitForResult();
9847
9848 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9849 EXPECT_EQ(1, cache.disk_cache()->open_count());
9850 EXPECT_EQ(1, cache.disk_cache()->create_count());
9851
9852 // Make sure that we revalidate the entry and read from the cache (a single
9853 // read will return while waiting for the network).
9854 scoped_refptr<IOBufferWithSize> buf =
9855 base::MakeRefCounted<IOBufferWithSize>(5);
9856 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9857 EXPECT_EQ(5, c->callback.GetResult(rv));
9858 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9859 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9860
9861 // Destroy the previous transaction before completing the read.
9862 c.reset();
9863
9864 // We have the read and the delete (OnProcessPendingQueue) waiting on the
9865 // message loop. This means that a new transaction will just reuse the same
9866 // active entry (no open or create).
9867
9868 c = std::make_unique<Context>();
9869 rv = cache.CreateTransaction(&c->trans);
9870 ASSERT_THAT(rv, IsOk());
9871
9872 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9873 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9874
9875 MockDiskEntry::IgnoreCallbacks(true);
9876 base::RunLoop().RunUntilIdle();
9877 MockDiskEntry::IgnoreCallbacks(false);
9878
9879 // The new transaction is waiting for the query range callback.
9880 c.reset();
9881
9882 // And we should not crash when the callback is delivered.
9883 base::RunLoop().RunUntilIdle();
9884
9885 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9886 EXPECT_EQ(1, cache.disk_cache()->open_count());
9887 EXPECT_EQ(1, cache.disk_cache()->create_count());
9888 RemoveMockTransaction(&kRangeGET_TransactionOK);
9889 }
9890
9891 // Tests that an invalid range response results in no cached entry.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse1)9892 TEST_F(HttpCacheTest, RangeGET_InvalidResponse1) {
9893 MockHttpCache cache;
9894 std::string headers;
9895
9896 MockTransaction transaction(kRangeGET_TransactionOK);
9897 transaction.handler = MockTransactionHandler();
9898 transaction.response_headers = "Content-Range: bytes 40-49/45\n"
9899 "Content-Length: 10\n";
9900 AddMockTransaction(&transaction);
9901 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9902
9903 std::string expected(transaction.status);
9904 expected.append("\n");
9905 expected.append(transaction.response_headers);
9906 EXPECT_EQ(expected, headers);
9907
9908 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9909 EXPECT_EQ(0, cache.disk_cache()->open_count());
9910 EXPECT_EQ(1, cache.disk_cache()->create_count());
9911
9912 // Verify that we don't have a cached entry.
9913 disk_cache::Entry* entry;
9914 MockHttpRequest request(transaction);
9915 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9916
9917 RemoveMockTransaction(&kRangeGET_TransactionOK);
9918 }
9919
9920 // Tests that we reject a range that doesn't match the content-length.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse2)9921 TEST_F(HttpCacheTest, RangeGET_InvalidResponse2) {
9922 MockHttpCache cache;
9923 std::string headers;
9924
9925 MockTransaction transaction(kRangeGET_TransactionOK);
9926 transaction.handler = MockTransactionHandler();
9927 transaction.response_headers = "Content-Range: bytes 40-49/80\n"
9928 "Content-Length: 20\n";
9929 AddMockTransaction(&transaction);
9930 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9931
9932 std::string expected(transaction.status);
9933 expected.append("\n");
9934 expected.append(transaction.response_headers);
9935 EXPECT_EQ(expected, headers);
9936
9937 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9938 EXPECT_EQ(0, cache.disk_cache()->open_count());
9939 EXPECT_EQ(1, cache.disk_cache()->create_count());
9940
9941 // Verify that we don't have a cached entry.
9942 disk_cache::Entry* entry;
9943 MockHttpRequest request(transaction);
9944 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9945
9946 RemoveMockTransaction(&kRangeGET_TransactionOK);
9947 }
9948
9949 // Tests that if a server tells us conflicting information about a resource we
9950 // drop the entry.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse3)9951 TEST_F(HttpCacheTest, RangeGET_InvalidResponse3) {
9952 MockHttpCache cache;
9953 std::string headers;
9954
9955 MockTransaction transaction(kRangeGET_TransactionOK);
9956 transaction.handler = MockTransactionHandler();
9957 transaction.request_headers = "Range: bytes = 50-59\r\n" EXTRA_HEADER;
9958 std::string response_headers(transaction.response_headers);
9959 response_headers.append("Content-Range: bytes 50-59/160\n");
9960 transaction.response_headers = response_headers.c_str();
9961 AddMockTransaction(&transaction);
9962 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9963
9964 Verify206Response(headers, 50, 59);
9965 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9966 EXPECT_EQ(0, cache.disk_cache()->open_count());
9967 EXPECT_EQ(1, cache.disk_cache()->create_count());
9968
9969 RemoveMockTransaction(&transaction);
9970 AddMockTransaction(&kRangeGET_TransactionOK);
9971
9972 // This transaction will report a resource size of 80 bytes, and we think it's
9973 // 160 so we should ignore the response.
9974 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9975 &headers);
9976
9977 Verify206Response(headers, 40, 49);
9978 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9979 EXPECT_EQ(1, cache.disk_cache()->open_count());
9980 EXPECT_EQ(1, cache.disk_cache()->create_count());
9981
9982 // Verify that the entry is gone.
9983 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9984 EXPECT_EQ(1, cache.disk_cache()->open_count());
9985 EXPECT_EQ(2, cache.disk_cache()->create_count());
9986 RemoveMockTransaction(&kRangeGET_TransactionOK);
9987 }
9988
9989 // Tests that we handle large range values properly.
TEST_F(HttpCacheTest,RangeGET_LargeValues)9990 TEST_F(HttpCacheTest, RangeGET_LargeValues) {
9991 // We need a real sparse cache for this test.
9992 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
9993 std::string headers;
9994
9995 MockTransaction transaction(kRangeGET_TransactionOK);
9996 transaction.handler = MockTransactionHandler();
9997 transaction.request_headers = "Range: bytes = 4294967288-4294967297\r\n"
9998 EXTRA_HEADER;
9999 transaction.response_headers =
10000 "ETag: \"foo\"\n"
10001 "Content-Range: bytes 4294967288-4294967297/4294967299\n"
10002 "Content-Length: 10\n";
10003 AddMockTransaction(&transaction);
10004 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10005
10006 std::string expected(transaction.status);
10007 expected.append("\n");
10008 expected.append(transaction.response_headers);
10009 EXPECT_EQ(expected, headers);
10010
10011 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10012
10013 // Verify that we have a cached entry.
10014 disk_cache::Entry* en;
10015 MockHttpRequest request(transaction);
10016 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &en));
10017 en->Close();
10018
10019 RemoveMockTransaction(&kRangeGET_TransactionOK);
10020 }
10021
10022 // Tests that we don't crash with a range request if the disk cache was not
10023 // initialized properly.
TEST_F(HttpCacheTest,RangeGET_NoDiskCache)10024 TEST_F(HttpCacheTest, RangeGET_NoDiskCache) {
10025 auto factory = std::make_unique<MockBlockingBackendFactory>();
10026 factory->set_fail(true);
10027 factory->FinishCreation(); // We'll complete synchronously.
10028 MockHttpCache cache(std::move(factory));
10029
10030 AddMockTransaction(&kRangeGET_TransactionOK);
10031
10032 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
10033 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10034
10035 RemoveMockTransaction(&kRangeGET_TransactionOK);
10036 }
10037
10038 // Tests that we handle byte range requests that skip the cache.
TEST_F(HttpCacheTest,RangeHEAD)10039 TEST_F(HttpCacheTest, RangeHEAD) {
10040 MockHttpCache cache;
10041 AddMockTransaction(&kRangeGET_TransactionOK);
10042
10043 MockTransaction transaction(kRangeGET_TransactionOK);
10044 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
10045 transaction.method = "HEAD";
10046 transaction.data = "rg: 70-79 ";
10047
10048 std::string headers;
10049 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10050
10051 Verify206Response(headers, 70, 79);
10052 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10053 EXPECT_EQ(0, cache.disk_cache()->open_count());
10054 EXPECT_EQ(0, cache.disk_cache()->create_count());
10055
10056 RemoveMockTransaction(&kRangeGET_TransactionOK);
10057 }
10058
10059 // Tests that we don't crash when after reading from the cache we issue a
10060 // request for the next range and the server gives us a 200 synchronously.
TEST_F(HttpCacheTest,RangeGET_FastFlakyServer)10061 TEST_F(HttpCacheTest, RangeGET_FastFlakyServer) {
10062 MockHttpCache cache;
10063
10064 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10065 transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER;
10066 transaction.test_mode = TEST_MODE_SYNC_NET_START;
10067 transaction.load_flags |= LOAD_VALIDATE_CACHE;
10068
10069 // Write to the cache.
10070 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
10071
10072 // And now read from the cache and the network.
10073 RangeTransactionServer handler;
10074 handler.set_bad_200(true);
10075 transaction.data = "Not a range";
10076 RecordingNetLogObserver net_log_observer;
10077 RunTransactionTestWithLog(cache.http_cache(), transaction,
10078 NetLogWithSource::Make(NetLogSourceType::NONE));
10079
10080 EXPECT_EQ(3, cache.network_layer()->transaction_count());
10081 EXPECT_EQ(1, cache.disk_cache()->open_count());
10082 EXPECT_EQ(1, cache.disk_cache()->create_count());
10083 EXPECT_TRUE(LogContainsEventType(
10084 net_log_observer, NetLogEventType::HTTP_CACHE_RE_SEND_PARTIAL_REQUEST));
10085 }
10086
10087 // Tests that when the server gives us less data than expected, we don't keep
10088 // asking for more data.
TEST_F(HttpCacheTest,RangeGET_FastFlakyServer2)10089 TEST_F(HttpCacheTest, RangeGET_FastFlakyServer2) {
10090 MockHttpCache cache;
10091
10092 // First, check with an empty cache (WRITE mode).
10093 MockTransaction transaction(kRangeGET_TransactionOK);
10094 transaction.request_headers = "Range: bytes = 40-49\r\n" EXTRA_HEADER;
10095 transaction.data = "rg: 40-"; // Less than expected.
10096 transaction.handler = MockTransactionHandler();
10097 std::string headers(transaction.response_headers);
10098 headers.append("Content-Range: bytes 40-49/80\n");
10099 transaction.response_headers = headers.c_str();
10100
10101 AddMockTransaction(&transaction);
10102
10103 // Write to the cache.
10104 RunTransactionTest(cache.http_cache(), transaction);
10105
10106 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10107 EXPECT_EQ(0, cache.disk_cache()->open_count());
10108 EXPECT_EQ(1, cache.disk_cache()->create_count());
10109
10110 // Now verify that even in READ_WRITE mode, we forward the bad response to
10111 // the caller.
10112 transaction.request_headers = "Range: bytes = 60-69\r\n" EXTRA_HEADER;
10113 transaction.data = "rg: 60-"; // Less than expected.
10114 headers = kRangeGET_TransactionOK.response_headers;
10115 headers.append("Content-Range: bytes 60-69/80\n");
10116 transaction.response_headers = headers.c_str();
10117
10118 RunTransactionTest(cache.http_cache(), transaction);
10119
10120 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10121 EXPECT_EQ(1, cache.disk_cache()->open_count());
10122 EXPECT_EQ(1, cache.disk_cache()->create_count());
10123
10124 RemoveMockTransaction(&transaction);
10125 }
10126
TEST_F(HttpCacheTest,RangeGET_OK_LoadOnlyFromCache)10127 TEST_F(HttpCacheTest, RangeGET_OK_LoadOnlyFromCache) {
10128 MockHttpCache cache;
10129 AddMockTransaction(&kRangeGET_TransactionOK);
10130
10131 // Write to the cache (40-49).
10132 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
10133 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10134 EXPECT_EQ(0, cache.disk_cache()->open_count());
10135 EXPECT_EQ(1, cache.disk_cache()->create_count());
10136
10137 // Force this transaction to read from the cache.
10138 MockTransaction transaction(kRangeGET_TransactionOK);
10139 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
10140
10141 MockHttpRequest request(transaction);
10142 TestCompletionCallback callback;
10143
10144 std::unique_ptr<HttpTransaction> trans;
10145 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
10146 EXPECT_THAT(rv, IsOk());
10147 ASSERT_TRUE(trans.get());
10148
10149 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
10150 if (rv == ERR_IO_PENDING)
10151 rv = callback.WaitForResult();
10152 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
10153
10154 trans.reset();
10155
10156 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10157 EXPECT_EQ(1, cache.disk_cache()->open_count());
10158 EXPECT_EQ(1, cache.disk_cache()->create_count());
10159
10160 RemoveMockTransaction(&kRangeGET_TransactionOK);
10161 }
10162
10163 // Tests the handling of the "truncation" flag.
TEST_F(HttpCacheTest,WriteResponseInfo_Truncated)10164 TEST_F(HttpCacheTest, WriteResponseInfo_Truncated) {
10165 MockHttpCache cache;
10166 disk_cache::Entry* entry;
10167 ASSERT_TRUE(cache.CreateBackendEntry(
10168 GenerateCacheKey("http://www.google.com"), &entry, nullptr));
10169
10170 HttpResponseInfo response;
10171 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
10172 HttpUtil::AssembleRawHeaders("HTTP/1.1 200 OK"));
10173
10174 // Set the last argument for this to be an incomplete request.
10175 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
10176 bool truncated = false;
10177 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
10178 EXPECT_TRUE(truncated);
10179
10180 // And now test the opposite case.
10181 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
10182 truncated = true;
10183 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
10184 EXPECT_FALSE(truncated);
10185 entry->Close();
10186 }
10187
10188 // Tests basic pickling/unpickling of HttpResponseInfo.
TEST_F(HttpCacheTest,PersistHttpResponseInfo)10189 TEST_F(HttpCacheTest, PersistHttpResponseInfo) {
10190 const IPEndPoint expected_endpoint = IPEndPoint(IPAddress(1, 2, 3, 4), 80);
10191 // Set some fields (add more if needed.)
10192 HttpResponseInfo response1;
10193 response1.was_cached = false;
10194 response1.remote_endpoint = expected_endpoint;
10195 response1.headers =
10196 base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
10197
10198 // Pickle.
10199 base::Pickle pickle;
10200 response1.Persist(&pickle, false, false);
10201
10202 // Unpickle.
10203 HttpResponseInfo response2;
10204 bool response_truncated;
10205 EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated));
10206 EXPECT_FALSE(response_truncated);
10207
10208 // Verify fields.
10209 EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag.
10210 EXPECT_EQ(expected_endpoint, response2.remote_endpoint);
10211 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
10212 }
10213
10214 // Tests that we delete an entry when the request is cancelled before starting
10215 // to read from the network.
TEST_F(HttpCacheTest,DoomOnDestruction)10216 TEST_F(HttpCacheTest, DoomOnDestruction) {
10217 MockHttpCache cache;
10218
10219 MockHttpRequest request(kSimpleGET_Transaction);
10220
10221 auto c = std::make_unique<Context>();
10222 int rv = cache.CreateTransaction(&c->trans);
10223 ASSERT_THAT(rv, IsOk());
10224
10225 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10226 if (rv == ERR_IO_PENDING)
10227 c->result = c->callback.WaitForResult();
10228
10229 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10230 EXPECT_EQ(0, cache.disk_cache()->open_count());
10231 EXPECT_EQ(1, cache.disk_cache()->create_count());
10232
10233 // Destroy the transaction. We only have the headers so we should delete this
10234 // entry.
10235 c.reset();
10236
10237 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10238
10239 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10240 EXPECT_EQ(0, cache.disk_cache()->open_count());
10241 EXPECT_EQ(2, cache.disk_cache()->create_count());
10242 }
10243
10244 // Tests that we delete an entry when the request is cancelled if the response
10245 // does not have content-length and strong validators.
TEST_F(HttpCacheTest,DoomOnDestruction2)10246 TEST_F(HttpCacheTest, DoomOnDestruction2) {
10247 MockHttpCache cache;
10248
10249 MockHttpRequest request(kSimpleGET_Transaction);
10250
10251 auto c = std::make_unique<Context>();
10252 int rv = cache.CreateTransaction(&c->trans);
10253 ASSERT_THAT(rv, IsOk());
10254
10255 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10256 if (rv == ERR_IO_PENDING)
10257 rv = c->callback.WaitForResult();
10258
10259 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10260 EXPECT_EQ(0, cache.disk_cache()->open_count());
10261 EXPECT_EQ(1, cache.disk_cache()->create_count());
10262
10263 // Make sure that the entry has some data stored.
10264 scoped_refptr<IOBufferWithSize> buf =
10265 base::MakeRefCounted<IOBufferWithSize>(10);
10266 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10267 if (rv == ERR_IO_PENDING)
10268 rv = c->callback.WaitForResult();
10269 EXPECT_EQ(buf->size(), rv);
10270
10271 // Destroy the transaction.
10272 c.reset();
10273
10274 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10275
10276 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10277 EXPECT_EQ(0, cache.disk_cache()->open_count());
10278 EXPECT_EQ(2, cache.disk_cache()->create_count());
10279 }
10280
10281 // Tests that we delete an entry when the request is cancelled if the response
10282 // has an "Accept-Ranges: none" header.
TEST_F(HttpCacheTest,DoomOnDestruction3)10283 TEST_F(HttpCacheTest, DoomOnDestruction3) {
10284 MockHttpCache cache;
10285
10286 MockTransaction transaction(kSimpleGET_Transaction);
10287 transaction.response_headers =
10288 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10289 "Content-Length: 22\n"
10290 "Accept-Ranges: none\n"
10291 "Etag: \"foopy\"\n";
10292 AddMockTransaction(&transaction);
10293 MockHttpRequest request(transaction);
10294
10295 auto c = std::make_unique<Context>();
10296 int rv = cache.CreateTransaction(&c->trans);
10297 ASSERT_THAT(rv, IsOk());
10298
10299 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10300 if (rv == ERR_IO_PENDING)
10301 rv = c->callback.WaitForResult();
10302
10303 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10304 EXPECT_EQ(0, cache.disk_cache()->open_count());
10305 EXPECT_EQ(1, cache.disk_cache()->create_count());
10306
10307 // Make sure that the entry has some data stored.
10308 scoped_refptr<IOBufferWithSize> buf =
10309 base::MakeRefCounted<IOBufferWithSize>(10);
10310 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10311 if (rv == ERR_IO_PENDING)
10312 rv = c->callback.WaitForResult();
10313 EXPECT_EQ(buf->size(), rv);
10314
10315 // Destroy the transaction.
10316 c.reset();
10317
10318 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10319
10320 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10321 EXPECT_EQ(0, cache.disk_cache()->open_count());
10322 EXPECT_EQ(2, cache.disk_cache()->create_count());
10323
10324 RemoveMockTransaction(&transaction);
10325 }
10326
10327 // Tests that we mark an entry as incomplete when the request is cancelled.
TEST_F(HttpCacheTest,SetTruncatedFlag)10328 TEST_F(HttpCacheTest, SetTruncatedFlag) {
10329 MockHttpCache cache;
10330
10331 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10332 transaction.response_headers =
10333 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10334 "Content-Length: 22\n"
10335 "Etag: \"foopy\"\n";
10336 MockHttpRequest request(transaction);
10337
10338 auto c = std::make_unique<Context>();
10339
10340 int rv = cache.CreateTransaction(&c->trans);
10341 ASSERT_THAT(rv, IsOk());
10342
10343 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10344 if (rv == ERR_IO_PENDING)
10345 rv = c->callback.WaitForResult();
10346
10347 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10348 EXPECT_EQ(0, cache.disk_cache()->open_count());
10349 EXPECT_EQ(1, cache.disk_cache()->create_count());
10350
10351 // Make sure that the entry has some data stored.
10352 scoped_refptr<IOBufferWithSize> buf =
10353 base::MakeRefCounted<IOBufferWithSize>(10);
10354 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10355 if (rv == ERR_IO_PENDING)
10356 rv = c->callback.WaitForResult();
10357 EXPECT_EQ(buf->size(), rv);
10358
10359 // We want to cancel the request when the transaction is busy.
10360 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10361 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10362 EXPECT_FALSE(c->callback.have_result());
10363
10364 // Destroy the transaction.
10365 c->trans.reset();
10366
10367 // Make sure that we don't invoke the callback. We may have an issue if the
10368 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
10369 // could end up with the transaction being deleted twice if we send any
10370 // notification from the transaction destructor (see http://crbug.com/31723).
10371 EXPECT_FALSE(c->callback.have_result());
10372
10373 base::RunLoop().RunUntilIdle();
10374 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 0);
10375 }
10376
10377 // Tests that we do not mark an entry as truncated when the request is
10378 // cancelled.
TEST_F(HttpCacheTest,DontSetTruncatedFlagForGarbledResponseCode)10379 TEST_F(HttpCacheTest, DontSetTruncatedFlagForGarbledResponseCode) {
10380 MockHttpCache cache;
10381
10382 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10383 transaction.response_headers =
10384 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10385 "Content-Length: 22\n"
10386 "Etag: \"foopy\"\n";
10387 transaction.status = "HTTP/1.1 2";
10388 MockHttpRequest request(transaction);
10389
10390 auto c = std::make_unique<Context>();
10391
10392 int rv = cache.CreateTransaction(&c->trans);
10393 ASSERT_THAT(rv, IsOk());
10394
10395 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10396 if (rv == ERR_IO_PENDING)
10397 rv = c->callback.WaitForResult();
10398
10399 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10400 EXPECT_EQ(0, cache.disk_cache()->open_count());
10401 EXPECT_EQ(1, cache.disk_cache()->create_count());
10402
10403 // Make sure that the entry has some data stored.
10404 scoped_refptr<IOBufferWithSize> buf =
10405 base::MakeRefCounted<IOBufferWithSize>(10);
10406 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10407 if (rv == ERR_IO_PENDING)
10408 rv = c->callback.WaitForResult();
10409 EXPECT_EQ(buf->size(), rv);
10410
10411 // We want to cancel the request when the transaction is busy.
10412 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10413 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10414 EXPECT_FALSE(c->callback.have_result());
10415
10416 MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL);
10417
10418 // Destroy the transaction.
10419 c->trans.reset();
10420 MockHttpCache::SetTestMode(0);
10421
10422 // Make sure that we don't invoke the callback. We may have an issue if the
10423 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
10424 // could end up with the transaction being deleted twice if we send any
10425 // notification from the transaction destructor (see http://crbug.com/31723).
10426 EXPECT_FALSE(c->callback.have_result());
10427
10428 // Verify that the entry is deleted as well, since the response status is
10429 // garbled. Note that the entry will be deleted after the pending Read is
10430 // complete.
10431 base::RunLoop().RunUntilIdle();
10432 disk_cache::Entry* entry;
10433 ASSERT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10434 }
10435
10436 // Tests that we don't mark an entry as truncated when we read everything.
TEST_F(HttpCacheTest,DontSetTruncatedFlag)10437 TEST_F(HttpCacheTest, DontSetTruncatedFlag) {
10438 MockHttpCache cache;
10439
10440 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10441 transaction.response_headers =
10442 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10443 "Content-Length: 22\n"
10444 "Etag: \"foopy\"\n";
10445 MockHttpRequest request(transaction);
10446
10447 auto c = std::make_unique<Context>();
10448 int rv = cache.CreateTransaction(&c->trans);
10449 ASSERT_THAT(rv, IsOk());
10450
10451 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10452 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10453
10454 // Read everything.
10455 scoped_refptr<IOBufferWithSize> buf =
10456 base::MakeRefCounted<IOBufferWithSize>(22);
10457 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10458 EXPECT_EQ(buf->size(), c->callback.GetResult(rv));
10459
10460 // Destroy the transaction.
10461 c->trans.reset();
10462
10463 // Verify that the entry is not marked as truncated.
10464 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 0);
10465 }
10466
10467 // Tests that sparse entries don't set the truncate flag.
TEST_F(HttpCacheTest,RangeGET_DontTruncate)10468 TEST_F(HttpCacheTest, RangeGET_DontTruncate) {
10469 MockHttpCache cache;
10470
10471 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10472 transaction.request_headers = "Range: bytes = 0-19\r\n" EXTRA_HEADER;
10473
10474 auto request = std::make_unique<MockHttpRequest>(transaction);
10475 std::unique_ptr<HttpTransaction> trans;
10476
10477 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
10478 EXPECT_THAT(rv, IsOk());
10479
10480 TestCompletionCallback cb;
10481 rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
10482 EXPECT_EQ(0, cb.GetResult(rv));
10483
10484 auto buf = base::MakeRefCounted<IOBufferWithSize>(10);
10485 rv = trans->Read(buf.get(), 10, cb.callback());
10486 EXPECT_EQ(10, cb.GetResult(rv));
10487
10488 // Should not trigger any DCHECK.
10489 trans.reset();
10490 VerifyTruncatedFlag(&cache, request->CacheKey(), false, 0);
10491 }
10492
10493 // Tests that sparse entries don't set the truncate flag (when the byte range
10494 // starts after 0).
TEST_F(HttpCacheTest,RangeGET_DontTruncate2)10495 TEST_F(HttpCacheTest, RangeGET_DontTruncate2) {
10496 MockHttpCache cache;
10497
10498 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10499 transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
10500
10501 auto request = std::make_unique<MockHttpRequest>(transaction);
10502 std::unique_ptr<HttpTransaction> trans;
10503
10504 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
10505 EXPECT_THAT(rv, IsOk());
10506
10507 TestCompletionCallback cb;
10508 rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
10509 EXPECT_EQ(0, cb.GetResult(rv));
10510
10511 auto buf = base::MakeRefCounted<IOBufferWithSize>(10);
10512 rv = trans->Read(buf.get(), 10, cb.callback());
10513 EXPECT_EQ(10, cb.GetResult(rv));
10514
10515 // Should not trigger any DCHECK.
10516 trans.reset();
10517 VerifyTruncatedFlag(&cache, request->CacheKey(), false, 0);
10518 }
10519
10520 // Tests that we can continue with a request that was interrupted.
TEST_F(HttpCacheTest,GET_IncompleteResource)10521 TEST_F(HttpCacheTest, GET_IncompleteResource) {
10522 MockHttpCache cache;
10523 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10524
10525 std::string raw_headers("HTTP/1.1 200 OK\n"
10526 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10527 "ETag: \"foo\"\n"
10528 "Accept-Ranges: bytes\n"
10529 "Content-Length: 80\n");
10530 CreateTruncatedEntry(raw_headers, &cache);
10531
10532 // Now make a regular request.
10533 std::string headers;
10534 transaction.request_headers = EXTRA_HEADER;
10535 transaction.data = kFullRangeData;
10536 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10537
10538 // We update the headers with the ones received while revalidating.
10539 std::string expected_headers(
10540 "HTTP/1.1 200 OK\n"
10541 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10542 "Accept-Ranges: bytes\n"
10543 "ETag: \"foo\"\n"
10544 "Content-Length: 80\n");
10545
10546 EXPECT_EQ(expected_headers, headers);
10547 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10548 EXPECT_EQ(1, cache.disk_cache()->open_count());
10549 EXPECT_EQ(1, cache.disk_cache()->create_count());
10550
10551 // Verify that the disk entry was updated.
10552 MockHttpRequest request(transaction);
10553 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 80);
10554 }
10555
10556 // Tests the handling of no-store when revalidating a truncated entry.
TEST_F(HttpCacheTest,GET_IncompleteResource_NoStore)10557 TEST_F(HttpCacheTest, GET_IncompleteResource_NoStore) {
10558 MockHttpCache cache;
10559 AddMockTransaction(&kRangeGET_TransactionOK);
10560
10561 std::string raw_headers("HTTP/1.1 200 OK\n"
10562 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10563 "ETag: \"foo\"\n"
10564 "Accept-Ranges: bytes\n"
10565 "Content-Length: 80\n");
10566 CreateTruncatedEntry(raw_headers, &cache);
10567 RemoveMockTransaction(&kRangeGET_TransactionOK);
10568
10569 // Now make a regular request.
10570 MockTransaction transaction(kRangeGET_TransactionOK);
10571 transaction.request_headers = EXTRA_HEADER;
10572 std::string response_headers(transaction.response_headers);
10573 response_headers += ("Cache-Control: no-store\n");
10574 transaction.response_headers = response_headers.c_str();
10575 transaction.data = kFullRangeData;
10576 AddMockTransaction(&transaction);
10577
10578 std::string headers;
10579 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10580
10581 // We update the headers with the ones received while revalidating.
10582 std::string expected_headers(
10583 "HTTP/1.1 200 OK\n"
10584 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10585 "Accept-Ranges: bytes\n"
10586 "Cache-Control: no-store\n"
10587 "ETag: \"foo\"\n"
10588 "Content-Length: 80\n");
10589
10590 EXPECT_EQ(expected_headers, headers);
10591 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10592 EXPECT_EQ(1, cache.disk_cache()->open_count());
10593 EXPECT_EQ(1, cache.disk_cache()->create_count());
10594
10595 // Verify that the disk entry was deleted.
10596 disk_cache::Entry* entry;
10597 MockHttpRequest request(transaction);
10598 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10599 RemoveMockTransaction(&transaction);
10600 }
10601
10602 // Tests cancelling a request after the server sent no-store.
TEST_F(HttpCacheTest,GET_IncompleteResource_Cancel)10603 TEST_F(HttpCacheTest, GET_IncompleteResource_Cancel) {
10604 MockHttpCache cache;
10605 AddMockTransaction(&kRangeGET_TransactionOK);
10606
10607 std::string raw_headers("HTTP/1.1 200 OK\n"
10608 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10609 "ETag: \"foo\"\n"
10610 "Accept-Ranges: bytes\n"
10611 "Content-Length: 80\n");
10612 CreateTruncatedEntry(raw_headers, &cache);
10613 RemoveMockTransaction(&kRangeGET_TransactionOK);
10614
10615 // Now make a regular request.
10616 MockTransaction transaction(kRangeGET_TransactionOK);
10617 transaction.request_headers = EXTRA_HEADER;
10618 std::string response_headers(transaction.response_headers);
10619 response_headers += ("Cache-Control: no-store\n");
10620 transaction.response_headers = response_headers.c_str();
10621 transaction.data = kFullRangeData;
10622 AddMockTransaction(&transaction);
10623
10624 MockHttpRequest request(transaction);
10625 auto c = std::make_unique<Context>();
10626
10627 int rv = cache.CreateTransaction(&c->trans);
10628 ASSERT_THAT(rv, IsOk());
10629
10630 // Queue another request to this transaction. We have to start this request
10631 // before the first one gets the response from the server and dooms the entry,
10632 // otherwise it will just create a new entry without being queued to the first
10633 // request.
10634 auto pending = std::make_unique<Context>();
10635 ASSERT_THAT(cache.CreateTransaction(&pending->trans), IsOk());
10636
10637 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10638 EXPECT_EQ(ERR_IO_PENDING,
10639 pending->trans->Start(&request, pending->callback.callback(),
10640 NetLogWithSource()));
10641 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10642
10643 // Make sure that the entry has some data stored.
10644 scoped_refptr<IOBufferWithSize> buf =
10645 base::MakeRefCounted<IOBufferWithSize>(5);
10646 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10647 EXPECT_EQ(5, c->callback.GetResult(rv));
10648
10649 // Since |pending| is currently validating the already written headers
10650 // it will be restarted as well.
10651 c.reset();
10652 pending.reset();
10653
10654 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10655 EXPECT_EQ(1, cache.disk_cache()->open_count());
10656 EXPECT_EQ(1, cache.disk_cache()->create_count());
10657
10658 base::RunLoop().RunUntilIdle();
10659 RemoveMockTransaction(&transaction);
10660 }
10661
10662 // Tests that we delete truncated entries if the server changes its mind midway.
TEST_F(HttpCacheTest,GET_IncompleteResource2)10663 TEST_F(HttpCacheTest, GET_IncompleteResource2) {
10664 MockHttpCache cache;
10665 AddMockTransaction(&kRangeGET_TransactionOK);
10666
10667 // Content-length will be intentionally bad.
10668 std::string raw_headers("HTTP/1.1 200 OK\n"
10669 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10670 "ETag: \"foo\"\n"
10671 "Accept-Ranges: bytes\n"
10672 "Content-Length: 50\n");
10673 CreateTruncatedEntry(raw_headers, &cache);
10674
10675 // Now make a regular request. We expect the code to fail the validation and
10676 // retry the request without using byte ranges.
10677 std::string headers;
10678 MockTransaction transaction(kRangeGET_TransactionOK);
10679 transaction.request_headers = EXTRA_HEADER;
10680 transaction.data = "Not a range";
10681 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10682
10683 // The server will return 200 instead of a byte range.
10684 std::string expected_headers(
10685 "HTTP/1.1 200 OK\n"
10686 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
10687
10688 EXPECT_EQ(expected_headers, headers);
10689 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10690 EXPECT_EQ(1, cache.disk_cache()->open_count());
10691 EXPECT_EQ(1, cache.disk_cache()->create_count());
10692
10693 // Verify that the disk entry was deleted.
10694 disk_cache::Entry* entry;
10695 MockHttpRequest request(transaction);
10696 ASSERT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10697 RemoveMockTransaction(&kRangeGET_TransactionOK);
10698 }
10699
10700 // Tests that we always validate a truncated request.
TEST_F(HttpCacheTest,GET_IncompleteResource3)10701 TEST_F(HttpCacheTest, GET_IncompleteResource3) {
10702 MockHttpCache cache;
10703 AddMockTransaction(&kRangeGET_TransactionOK);
10704
10705 // This should not require validation for 10 hours.
10706 std::string raw_headers("HTTP/1.1 200 OK\n"
10707 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10708 "ETag: \"foo\"\n"
10709 "Cache-Control: max-age= 36000\n"
10710 "Accept-Ranges: bytes\n"
10711 "Content-Length: 80\n");
10712 CreateTruncatedEntry(raw_headers, &cache);
10713
10714 // Now make a regular request.
10715 std::string headers;
10716 MockTransaction transaction(kRangeGET_TransactionOK);
10717 transaction.request_headers = EXTRA_HEADER;
10718 transaction.data = kFullRangeData;
10719
10720 auto c = std::make_unique<Context>();
10721 int rv = cache.CreateTransaction(&c->trans);
10722 ASSERT_THAT(rv, IsOk());
10723
10724 MockHttpRequest request(transaction);
10725 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10726 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10727
10728 // We should have checked with the server before finishing Start().
10729 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10730 EXPECT_EQ(1, cache.disk_cache()->open_count());
10731 EXPECT_EQ(1, cache.disk_cache()->create_count());
10732
10733 RemoveMockTransaction(&kRangeGET_TransactionOK);
10734 }
10735
10736 // Tests that we handle 401s for truncated resources.
TEST_F(HttpCacheTest,GET_IncompleteResourceWithAuth)10737 TEST_F(HttpCacheTest, GET_IncompleteResourceWithAuth) {
10738 MockHttpCache cache;
10739 AddMockTransaction(&kRangeGET_TransactionOK);
10740
10741 std::string raw_headers("HTTP/1.1 200 OK\n"
10742 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10743 "ETag: \"foo\"\n"
10744 "Accept-Ranges: bytes\n"
10745 "Content-Length: 80\n");
10746 CreateTruncatedEntry(raw_headers, &cache);
10747
10748 // Now make a regular request.
10749 MockTransaction transaction(kRangeGET_TransactionOK);
10750 transaction.request_headers = "X-Require-Mock-Auth: dummy\r\n"
10751 EXTRA_HEADER;
10752 transaction.data = kFullRangeData;
10753 RangeTransactionServer handler;
10754
10755 auto c = std::make_unique<Context>();
10756 int rv = cache.CreateTransaction(&c->trans);
10757 ASSERT_THAT(rv, IsOk());
10758
10759 MockHttpRequest request(transaction);
10760 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10761 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10762
10763 const HttpResponseInfo* response = c->trans->GetResponseInfo();
10764 ASSERT_TRUE(response);
10765 ASSERT_EQ(401, response->headers->response_code());
10766 rv = c->trans->RestartWithAuth(AuthCredentials(), c->callback.callback());
10767 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10768 response = c->trans->GetResponseInfo();
10769 ASSERT_TRUE(response);
10770 ASSERT_EQ(200, response->headers->response_code());
10771
10772 ReadAndVerifyTransaction(c->trans.get(), transaction);
10773 c.reset(); // The destructor could delete the entry.
10774 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10775
10776 // Verify that the entry was deleted.
10777 disk_cache::Entry* entry;
10778 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10779 entry->Close();
10780
10781 RemoveMockTransaction(&kRangeGET_TransactionOK);
10782 }
10783
10784 // Test that the transaction won't retry failed partial requests
10785 // after it starts reading data. http://crbug.com/474835
TEST_F(HttpCacheTest,TransactionRetryLimit)10786 TEST_F(HttpCacheTest, TransactionRetryLimit) {
10787 MockHttpCache cache;
10788
10789 // Cache 0-9, so that we have data to read before failing.
10790 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10791 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
10792 transaction.data = "rg: 00-09 ";
10793
10794 // Write to the cache.
10795 RunTransactionTest(cache.http_cache(), transaction);
10796 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10797
10798 // And now read from the cache and the network. 10-19 will get a
10799 // 401, but will have already returned 0-9.
10800 // We do not set X-Require-Mock-Auth because that causes the mock
10801 // network transaction to become IsReadyToRestartForAuth().
10802 transaction.request_headers =
10803 "Range: bytes = 0-79\r\n"
10804 "X-Require-Mock-Auth-Alt: dummy\r\n" EXTRA_HEADER;
10805
10806 auto c = std::make_unique<Context>();
10807 int rv = cache.CreateTransaction(&c->trans);
10808 ASSERT_THAT(rv, IsOk());
10809
10810 MockHttpRequest request(transaction);
10811
10812 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10813 if (rv == ERR_IO_PENDING)
10814 rv = c->callback.WaitForResult();
10815 std::string content;
10816 rv = ReadTransaction(c->trans.get(), &content);
10817 EXPECT_THAT(rv, IsError(ERR_CACHE_AUTH_FAILURE_AFTER_READ));
10818 }
10819
10820 // Tests that we cache a 200 response to the validation request.
TEST_F(HttpCacheTest,GET_IncompleteResource4)10821 TEST_F(HttpCacheTest, GET_IncompleteResource4) {
10822 MockHttpCache cache;
10823 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10824
10825 std::string raw_headers("HTTP/1.1 200 OK\n"
10826 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10827 "ETag: \"foo\"\n"
10828 "Accept-Ranges: bytes\n"
10829 "Content-Length: 80\n");
10830 CreateTruncatedEntry(raw_headers, &cache);
10831
10832 // Now make a regular request.
10833 std::string headers;
10834 transaction.request_headers = EXTRA_HEADER;
10835 transaction.data = "Not a range";
10836 RangeTransactionServer handler;
10837 handler.set_bad_200(true);
10838 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10839
10840 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10841 EXPECT_EQ(1, cache.disk_cache()->open_count());
10842 EXPECT_EQ(1, cache.disk_cache()->create_count());
10843
10844 // Verify that the disk entry was updated.
10845 MockHttpRequest request(transaction);
10846 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 11);
10847 }
10848
10849 // Tests that when we cancel a request that was interrupted, we mark it again
10850 // as truncated.
TEST_F(HttpCacheTest,GET_CancelIncompleteResource)10851 TEST_F(HttpCacheTest, GET_CancelIncompleteResource) {
10852 MockHttpCache cache;
10853 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10854
10855 std::string raw_headers("HTTP/1.1 200 OK\n"
10856 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10857 "ETag: \"foo\"\n"
10858 "Accept-Ranges: bytes\n"
10859 "Content-Length: 80\n");
10860 CreateTruncatedEntry(raw_headers, &cache);
10861
10862 // Now make a regular request.
10863 transaction.request_headers = EXTRA_HEADER;
10864
10865 MockHttpRequest request(transaction);
10866 auto c = std::make_unique<Context>();
10867 int rv = cache.CreateTransaction(&c->trans);
10868 ASSERT_THAT(rv, IsOk());
10869
10870 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10871 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10872
10873 // Read 20 bytes from the cache, and 10 from the net.
10874 auto buf = base::MakeRefCounted<IOBufferWithSize>(100);
10875 rv = c->trans->Read(buf.get(), 20, c->callback.callback());
10876 EXPECT_EQ(20, c->callback.GetResult(rv));
10877 rv = c->trans->Read(buf.get(), 10, c->callback.callback());
10878 EXPECT_EQ(10, c->callback.GetResult(rv));
10879
10880 // At this point, we are already reading so canceling the request should leave
10881 // a truncated one.
10882 c.reset();
10883
10884 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10885 EXPECT_EQ(1, cache.disk_cache()->open_count());
10886 EXPECT_EQ(1, cache.disk_cache()->create_count());
10887
10888 // Verify that the disk entry was updated: now we have 30 bytes.
10889 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 30);
10890 }
10891
10892 // Tests that we can handle range requests when we have a truncated entry.
TEST_F(HttpCacheTest,RangeGET_IncompleteResource)10893 TEST_F(HttpCacheTest, RangeGET_IncompleteResource) {
10894 MockHttpCache cache;
10895 AddMockTransaction(&kRangeGET_TransactionOK);
10896
10897 // Content-length will be intentionally bogus.
10898 std::string raw_headers("HTTP/1.1 200 OK\n"
10899 "Last-Modified: something\n"
10900 "ETag: \"foo\"\n"
10901 "Accept-Ranges: bytes\n"
10902 "Content-Length: 10\n");
10903 CreateTruncatedEntry(raw_headers, &cache);
10904
10905 // Now make a range request.
10906 std::string headers;
10907 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
10908 &headers);
10909
10910 Verify206Response(headers, 40, 49);
10911 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10912 EXPECT_EQ(1, cache.disk_cache()->open_count());
10913 EXPECT_EQ(2, cache.disk_cache()->create_count());
10914
10915 RemoveMockTransaction(&kRangeGET_TransactionOK);
10916 }
10917
TEST_F(HttpCacheTest,SyncRead)10918 TEST_F(HttpCacheTest, SyncRead) {
10919 MockHttpCache cache;
10920
10921 // This test ensures that a read that completes synchronously does not cause
10922 // any problems.
10923
10924 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10925 transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START |
10926 TEST_MODE_SYNC_CACHE_READ |
10927 TEST_MODE_SYNC_CACHE_WRITE);
10928
10929 MockHttpRequest r1(transaction),
10930 r2(transaction),
10931 r3(transaction);
10932
10933 TestTransactionConsumer c1(DEFAULT_PRIORITY, cache.http_cache()),
10934 c2(DEFAULT_PRIORITY, cache.http_cache()),
10935 c3(DEFAULT_PRIORITY, cache.http_cache());
10936
10937 c1.Start(&r1, NetLogWithSource());
10938
10939 r2.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
10940 c2.Start(&r2, NetLogWithSource());
10941
10942 r3.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
10943 c3.Start(&r3, NetLogWithSource());
10944
10945 base::RunLoop().Run();
10946
10947 EXPECT_TRUE(c1.is_done());
10948 EXPECT_TRUE(c2.is_done());
10949 EXPECT_TRUE(c3.is_done());
10950
10951 EXPECT_THAT(c1.error(), IsOk());
10952 EXPECT_THAT(c2.error(), IsOk());
10953 EXPECT_THAT(c3.error(), IsOk());
10954 }
10955
TEST_F(HttpCacheTest,ValidationResultsIn200)10956 TEST_F(HttpCacheTest, ValidationResultsIn200) {
10957 MockHttpCache cache;
10958
10959 // This test ensures that a conditional request, which results in a 200
10960 // instead of a 304, properly truncates the existing response data.
10961
10962 // write to the cache
10963 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
10964
10965 // force this transaction to validate the cache
10966 MockTransaction transaction(kETagGET_Transaction);
10967 transaction.load_flags |= LOAD_VALIDATE_CACHE;
10968 RunTransactionTest(cache.http_cache(), transaction);
10969
10970 // read from the cache
10971 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
10972 }
10973
TEST_F(HttpCacheTest,CachedRedirect)10974 TEST_F(HttpCacheTest, CachedRedirect) {
10975 MockHttpCache cache;
10976
10977 ScopedMockTransaction kTestTransaction(kSimpleGET_Transaction);
10978 kTestTransaction.status = "HTTP/1.1 301 Moved Permanently";
10979 kTestTransaction.response_headers = "Location: http://www.bar.com/\n";
10980
10981 MockHttpRequest request(kTestTransaction);
10982 TestCompletionCallback callback;
10983
10984 // Write to the cache.
10985 {
10986 std::unique_ptr<HttpTransaction> trans;
10987 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
10988
10989 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
10990 if (rv == ERR_IO_PENDING)
10991 rv = callback.WaitForResult();
10992 ASSERT_THAT(rv, IsOk());
10993
10994 const HttpResponseInfo* info = trans->GetResponseInfo();
10995 ASSERT_TRUE(info);
10996
10997 EXPECT_EQ(info->headers->response_code(), 301);
10998
10999 std::string location;
11000 info->headers->EnumerateHeader(nullptr, "Location", &location);
11001 EXPECT_EQ(location, "http://www.bar.com/");
11002
11003 // Mark the transaction as completed so it is cached.
11004 trans->DoneReading();
11005
11006 // Destroy transaction when going out of scope. We have not actually
11007 // read the response body -- want to test that it is still getting cached.
11008 }
11009 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11010 EXPECT_EQ(0, cache.disk_cache()->open_count());
11011 EXPECT_EQ(1, cache.disk_cache()->create_count());
11012
11013 // Active entries in the cache are not retired synchronously. Make
11014 // sure the next run hits the MockHttpCache and open_count is
11015 // correct.
11016 base::RunLoop().RunUntilIdle();
11017
11018 // Read from the cache.
11019 {
11020 std::unique_ptr<HttpTransaction> trans;
11021 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11022
11023 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11024 if (rv == ERR_IO_PENDING)
11025 rv = callback.WaitForResult();
11026 ASSERT_THAT(rv, IsOk());
11027
11028 const HttpResponseInfo* info = trans->GetResponseInfo();
11029 ASSERT_TRUE(info);
11030
11031 EXPECT_EQ(info->headers->response_code(), 301);
11032
11033 std::string location;
11034 info->headers->EnumerateHeader(nullptr, "Location", &location);
11035 EXPECT_EQ(location, "http://www.bar.com/");
11036
11037 // Mark the transaction as completed so it is cached.
11038 trans->DoneReading();
11039
11040 // Destroy transaction when going out of scope. We have not actually
11041 // read the response body -- want to test that it is still getting cached.
11042 }
11043 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11044 EXPECT_EQ(1, cache.disk_cache()->open_count());
11045 EXPECT_EQ(1, cache.disk_cache()->create_count());
11046 }
11047
11048 // Verify that no-cache resources are stored in cache, but are not fetched from
11049 // cache during normal loads.
TEST_F(HttpCacheTest,CacheControlNoCacheNormalLoad)11050 TEST_F(HttpCacheTest, CacheControlNoCacheNormalLoad) {
11051 for (bool use_memory_entry_data : {false, true}) {
11052 MockHttpCache cache;
11053 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
11054
11055 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11056 transaction.response_headers = "cache-control: no-cache\n";
11057
11058 // Initial load.
11059 RunTransactionTest(cache.http_cache(), transaction);
11060
11061 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11062 EXPECT_EQ(0, cache.disk_cache()->open_count());
11063 EXPECT_EQ(1, cache.disk_cache()->create_count());
11064
11065 // Try loading again; it should result in a network fetch.
11066 RunTransactionTest(cache.http_cache(), transaction);
11067
11068 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11069 if (use_memory_entry_data) {
11070 EXPECT_EQ(0, cache.disk_cache()->open_count());
11071 EXPECT_EQ(2, cache.disk_cache()->create_count());
11072 } else {
11073 EXPECT_EQ(1, cache.disk_cache()->open_count());
11074 EXPECT_EQ(1, cache.disk_cache()->create_count());
11075 }
11076
11077 disk_cache::Entry* entry;
11078 MockHttpRequest request(transaction);
11079 EXPECT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11080 entry->Close();
11081 }
11082 }
11083
11084 // Verify that no-cache resources are stored in cache and fetched from cache
11085 // when the LOAD_SKIP_CACHE_VALIDATION flag is set.
TEST_F(HttpCacheTest,CacheControlNoCacheHistoryLoad)11086 TEST_F(HttpCacheTest, CacheControlNoCacheHistoryLoad) {
11087 MockHttpCache cache;
11088
11089 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11090 transaction.response_headers = "cache-control: no-cache\n";
11091
11092 // Initial load.
11093 RunTransactionTest(cache.http_cache(), transaction);
11094
11095 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11096 EXPECT_EQ(0, cache.disk_cache()->open_count());
11097 EXPECT_EQ(1, cache.disk_cache()->create_count());
11098
11099 // Try loading again with LOAD_SKIP_CACHE_VALIDATION.
11100 transaction.load_flags = LOAD_SKIP_CACHE_VALIDATION;
11101 RunTransactionTest(cache.http_cache(), transaction);
11102
11103 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11104 EXPECT_EQ(1, cache.disk_cache()->open_count());
11105 EXPECT_EQ(1, cache.disk_cache()->create_count());
11106
11107 disk_cache::Entry* entry;
11108 MockHttpRequest request(transaction);
11109 EXPECT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11110 entry->Close();
11111 }
11112
TEST_F(HttpCacheTest,CacheControlNoStore)11113 TEST_F(HttpCacheTest, CacheControlNoStore) {
11114 MockHttpCache cache;
11115
11116 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11117 transaction.response_headers = "cache-control: no-store\n";
11118
11119 // initial load
11120 RunTransactionTest(cache.http_cache(), transaction);
11121
11122 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11123 EXPECT_EQ(0, cache.disk_cache()->open_count());
11124 EXPECT_EQ(1, cache.disk_cache()->create_count());
11125
11126 // try loading again; it should result in a network fetch
11127 RunTransactionTest(cache.http_cache(), transaction);
11128
11129 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11130 EXPECT_EQ(0, cache.disk_cache()->open_count());
11131 EXPECT_EQ(2, cache.disk_cache()->create_count());
11132
11133 disk_cache::Entry* entry;
11134 MockHttpRequest request(transaction);
11135 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11136 }
11137
TEST_F(HttpCacheTest,CacheControlNoStore2)11138 TEST_F(HttpCacheTest, CacheControlNoStore2) {
11139 // this test is similar to the above test, except that the initial response
11140 // is cachable, but when it is validated, no-store is received causing the
11141 // cached document to be deleted.
11142 MockHttpCache cache;
11143
11144 ScopedMockTransaction transaction(kETagGET_Transaction);
11145
11146 // initial load
11147 RunTransactionTest(cache.http_cache(), transaction);
11148
11149 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11150 EXPECT_EQ(0, cache.disk_cache()->open_count());
11151 EXPECT_EQ(1, cache.disk_cache()->create_count());
11152
11153 // try loading again; it should result in a network fetch
11154 transaction.load_flags = LOAD_VALIDATE_CACHE;
11155 transaction.response_headers = "cache-control: no-store\n";
11156 RunTransactionTest(cache.http_cache(), transaction);
11157
11158 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11159 EXPECT_EQ(1, cache.disk_cache()->open_count());
11160 EXPECT_EQ(1, cache.disk_cache()->create_count());
11161
11162 disk_cache::Entry* entry;
11163 MockHttpRequest request(transaction);
11164 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11165 }
11166
TEST_F(HttpCacheTest,CacheControlNoStore3)11167 TEST_F(HttpCacheTest, CacheControlNoStore3) {
11168 // this test is similar to the above test, except that the response is a 304
11169 // instead of a 200. this should never happen in practice, but it seems like
11170 // a good thing to verify that we still destroy the cache entry.
11171 MockHttpCache cache;
11172
11173 ScopedMockTransaction transaction(kETagGET_Transaction);
11174
11175 // initial load
11176 RunTransactionTest(cache.http_cache(), transaction);
11177
11178 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11179 EXPECT_EQ(0, cache.disk_cache()->open_count());
11180 EXPECT_EQ(1, cache.disk_cache()->create_count());
11181
11182 // try loading again; it should result in a network fetch
11183 transaction.load_flags = LOAD_VALIDATE_CACHE;
11184 transaction.response_headers = "cache-control: no-store\n";
11185 transaction.status = "HTTP/1.1 304 Not Modified";
11186 RunTransactionTest(cache.http_cache(), transaction);
11187
11188 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11189 EXPECT_EQ(1, cache.disk_cache()->open_count());
11190 EXPECT_EQ(1, cache.disk_cache()->create_count());
11191
11192 disk_cache::Entry* entry;
11193 MockHttpRequest request(transaction);
11194 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11195 }
11196
11197 // Ensure that we don't cache requests served over bad HTTPS.
TEST_F(HttpCacheTest,SimpleGET_SSLError)11198 TEST_F(HttpCacheTest, SimpleGET_SSLError) {
11199 MockHttpCache cache;
11200
11201 MockTransaction transaction = kSimpleGET_Transaction;
11202 transaction.cert_status = CERT_STATUS_REVOKED;
11203 ScopedMockTransaction scoped_transaction(transaction);
11204
11205 // write to the cache
11206 RunTransactionTest(cache.http_cache(), transaction);
11207
11208 // Test that it was not cached.
11209 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
11210
11211 MockHttpRequest request(transaction);
11212 TestCompletionCallback callback;
11213
11214 std::unique_ptr<HttpTransaction> trans;
11215 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11216
11217 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11218 if (rv == ERR_IO_PENDING)
11219 rv = callback.WaitForResult();
11220 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
11221 }
11222
11223 // Ensure that we don't crash by if left-behind transactions.
TEST_F(HttpCacheTest,OutlivedTransactions)11224 TEST_F(HttpCacheTest, OutlivedTransactions) {
11225 auto cache = std::make_unique<MockHttpCache>();
11226
11227 std::unique_ptr<HttpTransaction> trans;
11228 EXPECT_THAT(cache->CreateTransaction(&trans), IsOk());
11229
11230 cache.reset();
11231 trans.reset();
11232 }
11233
11234 // Test that the disabled mode works.
TEST_F(HttpCacheTest,CacheDisabledMode)11235 TEST_F(HttpCacheTest, CacheDisabledMode) {
11236 MockHttpCache cache;
11237
11238 // write to the cache
11239 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11240
11241 // go into disabled mode
11242 cache.http_cache()->set_mode(HttpCache::DISABLE);
11243
11244 // force this transaction to write to the cache again
11245 MockTransaction transaction(kSimpleGET_Transaction);
11246
11247 RunTransactionTest(cache.http_cache(), transaction);
11248
11249 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11250 EXPECT_EQ(0, cache.disk_cache()->open_count());
11251 EXPECT_EQ(1, cache.disk_cache()->create_count());
11252 }
11253
11254 // Other tests check that the response headers of the cached response
11255 // get updated on 304. Here we specifically check that the
11256 // HttpResponseHeaders::request_time and HttpResponseHeaders::response_time
11257 // fields also gets updated.
11258 // http://crbug.com/20594.
TEST_F(HttpCacheTest,UpdatesRequestResponseTimeOn304)11259 TEST_F(HttpCacheTest, UpdatesRequestResponseTimeOn304) {
11260 MockHttpCache cache;
11261
11262 const char kUrl[] = "http://foobar";
11263 const char kData[] = "body";
11264
11265 MockTransaction mock_network_response = {nullptr};
11266 mock_network_response.url = kUrl;
11267
11268 AddMockTransaction(&mock_network_response);
11269
11270 // Request |kUrl|, causing |kNetResponse1| to be written to the cache.
11271
11272 MockTransaction request = {nullptr};
11273 request.url = kUrl;
11274 request.method = "GET";
11275 request.request_headers = "\r\n";
11276 request.data = kData;
11277
11278 static const Response kNetResponse1 = {
11279 "HTTP/1.1 200 OK",
11280 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
11281 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
11282 kData
11283 };
11284
11285 kNetResponse1.AssignTo(&mock_network_response);
11286
11287 RunTransactionTest(cache.http_cache(), request);
11288
11289 // Request |kUrl| again, this time validating the cache and getting
11290 // a 304 back.
11291
11292 request.load_flags = LOAD_VALIDATE_CACHE;
11293
11294 static const Response kNetResponse2 = {
11295 "HTTP/1.1 304 Not Modified",
11296 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n",
11297 ""
11298 };
11299
11300 kNetResponse2.AssignTo(&mock_network_response);
11301
11302 base::Time request_time = base::Time() + base::Hours(1234);
11303 base::Time response_time = base::Time() + base::Hours(1235);
11304
11305 mock_network_response.request_time = request_time;
11306 mock_network_response.response_time = response_time;
11307
11308 HttpResponseInfo response;
11309 RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response);
11310
11311 // The request and response times should have been updated.
11312 EXPECT_EQ(request_time.ToInternalValue(),
11313 response.request_time.ToInternalValue());
11314 EXPECT_EQ(response_time.ToInternalValue(),
11315 response.response_time.ToInternalValue());
11316
11317 EXPECT_EQ("HTTP/1.1 200 OK\n"
11318 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
11319 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
11320 ToSimpleString(response.headers));
11321
11322 RemoveMockTransaction(&mock_network_response);
11323 }
11324
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCacheWithNetworkIsolationKey)11325 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
11326 SplitCacheWithNetworkIsolationKey) {
11327 MockHttpCache cache;
11328 HttpResponseInfo response;
11329
11330 SchemefulSite site_a(GURL("http://a.com"));
11331 SchemefulSite site_b(GURL("http://b.com"));
11332 SchemefulSite site_data(GURL("data:text/html,<body>Hello World</body>"));
11333
11334 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11335 // Request with a.com as the top frame and subframe origins. This should
11336 // result in a cache miss.
11337 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11338 trans_info.network_anonymization_key =
11339 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11340 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11341 trans_info, &response);
11342 EXPECT_FALSE(response.was_cached);
11343
11344 // The second request should result in a cache hit.
11345 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11346 trans_info, &response);
11347 EXPECT_TRUE(response.was_cached);
11348
11349 // Now request with b.com as the subframe origin. It should result in a cache
11350 // miss.
11351 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_b);
11352 trans_info.network_anonymization_key =
11353 net::NetworkAnonymizationKey::CreateCrossSite(site_a);
11354 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11355 trans_info, &response);
11356 EXPECT_FALSE(response.was_cached);
11357
11358 // The second request should result in a cache hit.
11359 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11360 trans_info, &response);
11361 EXPECT_TRUE(response.was_cached);
11362
11363 // Another request with a.com as the top frame and subframe origin should
11364 // still result in a cache hit.
11365 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11366 trans_info.network_anonymization_key =
11367 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11368 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11369 trans_info, &response);
11370 EXPECT_TRUE(response.was_cached);
11371
11372 // Now make a request with an opaque subframe site. It shouldn't cause
11373 // anything to be added to the cache when the NIK makes use of the frame site.
11374 // Note that we will use `site_b` as the top-level site so that this resource
11375 // won't be in the cache at first regardless of the NIK partitioning scheme.
11376 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_data);
11377 trans_info.network_anonymization_key =
11378 net::NetworkAnonymizationKey::CreateCrossSite(site_b);
11379 switch (GetParam()) {
11380 case SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled:
11381 EXPECT_EQ(absl::nullopt,
11382 trans_info.network_isolation_key.ToCacheKeyString());
11383 break;
11384 case SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled:
11385 EXPECT_EQ("http://b.com _1",
11386 trans_info.network_isolation_key.ToCacheKeyString().value());
11387 break;
11388 case SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled:
11389 EXPECT_EQ("http://b.com _opaque",
11390 trans_info.network_isolation_key.ToCacheKeyString().value());
11391 break;
11392 case SplitCacheTestCase::kSplitCacheDisabled:
11393 NOTREACHED_NORETURN();
11394 }
11395
11396 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11397 trans_info, &response);
11398 EXPECT_FALSE(response.was_cached);
11399
11400 // On the second request, expect a cache miss if the NIK uses the frame site.
11401 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11402 trans_info, &response);
11403 switch (GetParam()) {
11404 case SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled:
11405 EXPECT_FALSE(response.was_cached);
11406 break;
11407 case SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled:
11408 case SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled:
11409 EXPECT_TRUE(response.was_cached);
11410 break;
11411 case SplitCacheTestCase::kSplitCacheDisabled:
11412 NOTREACHED_NORETURN();
11413 }
11414
11415 // Verify that a post transaction with a data stream uses a separate key.
11416 const int64_t kUploadId = 1; // Just a dummy value.
11417
11418 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11419 element_readers.push_back(
11420 std::make_unique<UploadBytesElementReader>("hello", 5));
11421 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
11422 kUploadId);
11423
11424 MockHttpRequest post_info = MockHttpRequest(kSimplePOST_Transaction);
11425 post_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11426 post_info.network_anonymization_key =
11427 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11428 post_info.upload_data_stream = &upload_data_stream;
11429
11430 RunTransactionTestWithRequest(cache.http_cache(), kSimplePOST_Transaction,
11431 post_info, &response);
11432 EXPECT_FALSE(response.was_cached);
11433 }
11434
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyCSS)11435 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyCSS) {
11436 base::HistogramTester histograms;
11437 MockHttpCache cache;
11438 HttpResponseInfo response;
11439
11440 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11441 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11442 SchemefulSite site_a(origin_a);
11443 SchemefulSite site_b(origin_b);
11444
11445 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11446 transaction.response_headers = "Content-Type: text/css\n";
11447
11448 MockHttpRequest trans_info = MockHttpRequest(transaction);
11449
11450 // Requesting with the same top-frame site should not count as third-party
11451 // but should still be recorded as CSS
11452 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11453 trans_info.network_anonymization_key =
11454 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11455 trans_info.possibly_top_frame_origin = origin_a;
11456
11457 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11458 &response);
11459
11460 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11461 histograms.ExpectTotalCount("HttpCache.Pattern.CSS", 1);
11462 histograms.ExpectTotalCount("HttpCache.Pattern.CSSThirdParty", 0);
11463
11464 // Requesting with a different top-frame site should count as third-party
11465 // and recorded as CSS
11466 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11467 trans_info.network_anonymization_key =
11468 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11469 trans_info.possibly_top_frame_origin = origin_b;
11470
11471 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11472 &response);
11473 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11474 histograms.ExpectTotalCount("HttpCache.Pattern.CSS", 2);
11475 histograms.ExpectTotalCount("HttpCache.Pattern.CSSThirdParty", 1);
11476 }
11477
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyJavaScript)11478 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyJavaScript) {
11479 base::HistogramTester histograms;
11480 MockHttpCache cache;
11481 HttpResponseInfo response;
11482
11483 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11484 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11485 SchemefulSite site_a(origin_a);
11486 SchemefulSite site_b(origin_b);
11487
11488 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11489 transaction.response_headers = "Content-Type: application/javascript\n";
11490
11491 MockHttpRequest trans_info = MockHttpRequest(transaction);
11492
11493 // Requesting with the same top-frame site should not count as third-party
11494 // but should still be recorded as JavaScript
11495 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11496 trans_info.network_anonymization_key =
11497 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11498 trans_info.possibly_top_frame_origin = origin_a;
11499
11500 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11501 &response);
11502
11503 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11504 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScript", 1);
11505 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScriptThirdParty", 0);
11506
11507 // Requesting with a different top-frame site should count as third-party
11508 // and recorded as JavaScript
11509 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11510 trans_info.network_anonymization_key =
11511 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11512 trans_info.possibly_top_frame_origin = origin_b;
11513
11514 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11515 &response);
11516 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11517 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScript", 2);
11518 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScriptThirdParty", 1);
11519 }
11520
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyFont)11521 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyFont) {
11522 base::HistogramTester histograms;
11523 MockHttpCache cache;
11524 HttpResponseInfo response;
11525
11526 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11527 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11528 SchemefulSite site_a(origin_a);
11529 SchemefulSite site_b(origin_b);
11530
11531 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11532 transaction.response_headers = "Content-Type: font/otf\n";
11533
11534 MockHttpRequest trans_info = MockHttpRequest(transaction);
11535
11536 // Requesting with the same top-frame site should not count as third-party
11537 // but should still be recorded as a font
11538 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11539 trans_info.network_anonymization_key =
11540 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11541 trans_info.possibly_top_frame_origin = origin_a;
11542
11543 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11544 &response);
11545
11546 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11547 histograms.ExpectTotalCount("HttpCache.Pattern.Font", 1);
11548 histograms.ExpectTotalCount("HttpCache.Pattern.FontThirdParty", 0);
11549
11550 // Requesting with a different top-frame site should count as third-party
11551 // and recorded as a font
11552 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11553 trans_info.network_anonymization_key =
11554 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11555 trans_info.possibly_top_frame_origin = origin_b;
11556
11557 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11558 &response);
11559 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11560 histograms.ExpectTotalCount("HttpCache.Pattern.Font", 2);
11561 histograms.ExpectTotalCount("HttpCache.Pattern.FontThirdParty", 1);
11562 }
11563
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCache)11564 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled, SplitCache) {
11565 MockHttpCache cache;
11566 HttpResponseInfo response;
11567
11568 SchemefulSite site_a(GURL("http://a.com"));
11569 SchemefulSite site_b(GURL("http://b.com"));
11570 SchemefulSite site_data(GURL("data:text/html,<body>Hello World</body>"));
11571
11572 // A request without a top frame origin shouldn't result in anything being
11573 // added to the cache.
11574 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11575 trans_info.network_isolation_key = net::NetworkIsolationKey();
11576 trans_info.network_anonymization_key = net::NetworkAnonymizationKey();
11577 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11578 trans_info, &response);
11579 EXPECT_FALSE(response.was_cached);
11580
11581 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11582 trans_info, &response);
11583 EXPECT_FALSE(response.was_cached);
11584
11585 // Now request with a.com as the top frame origin. This should initially
11586 // result in a cache miss since the cached resource has a different top frame
11587 // origin.
11588 net::NetworkIsolationKey key_a(site_a, site_a);
11589 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11590 trans_info.network_isolation_key = key_a;
11591 trans_info.network_anonymization_key = nak_a;
11592 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11593 trans_info, &response);
11594 EXPECT_FALSE(response.was_cached);
11595
11596 // The second request should result in a cache hit.
11597 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11598 trans_info, &response);
11599 EXPECT_TRUE(response.was_cached);
11600
11601 // If the same resource with the same NIK is for a subframe document resource,
11602 // it should not be a cache hit.
11603 MockHttpRequest subframe_document_trans_info = trans_info;
11604 subframe_document_trans_info.is_subframe_document_resource = true;
11605 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11606 subframe_document_trans_info, &response);
11607 EXPECT_FALSE(response.was_cached);
11608
11609 // Same request again should be a cache hit.
11610 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11611 subframe_document_trans_info, &response);
11612 EXPECT_TRUE(response.was_cached);
11613
11614 // Now request with b.com as the top frame origin. It should be a cache miss.
11615 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11616 trans_info.network_anonymization_key =
11617 NetworkAnonymizationKey::CreateSameSite(site_b);
11618 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11619 trans_info, &response);
11620 EXPECT_FALSE(response.was_cached);
11621
11622 // The second request should be a cache hit.
11623 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11624 trans_info, &response);
11625 EXPECT_TRUE(response.was_cached);
11626
11627 // Another request for a.com should still result in a cache hit.
11628 trans_info.network_isolation_key = key_a;
11629 trans_info.network_anonymization_key = nak_a;
11630 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11631 trans_info, &response);
11632 EXPECT_TRUE(response.was_cached);
11633
11634 // Now make a request with an opaque top frame origin. It shouldn't result in
11635 // a cache hit.
11636 trans_info.network_isolation_key = NetworkIsolationKey(site_data, site_data);
11637 trans_info.network_anonymization_key =
11638 NetworkAnonymizationKey::CreateSameSite(site_data);
11639 EXPECT_EQ(absl::nullopt, trans_info.network_isolation_key.ToCacheKeyString());
11640 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11641 trans_info, &response);
11642 EXPECT_FALSE(response.was_cached);
11643
11644 // On the second request, it still shouldn't result in a cache hit.
11645 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11646 trans_info, &response);
11647 EXPECT_FALSE(response.was_cached);
11648
11649 // Verify that a post transaction with a data stream uses a separate key.
11650 const int64_t kUploadId = 1; // Just a dummy value.
11651
11652 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11653 element_readers.push_back(
11654 std::make_unique<UploadBytesElementReader>("hello", 5));
11655 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
11656 kUploadId);
11657
11658 MockHttpRequest post_info = MockHttpRequest(kSimplePOST_Transaction);
11659 post_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11660 post_info.network_anonymization_key =
11661 NetworkAnonymizationKey::CreateSameSite(site_a);
11662 post_info.upload_data_stream = &upload_data_stream;
11663
11664 RunTransactionTestWithRequest(cache.http_cache(), kSimplePOST_Transaction,
11665 post_info, &response);
11666 EXPECT_FALSE(response.was_cached);
11667 }
11668
TEST_F(HttpCacheTest,SplitCacheEnabledByDefault)11669 TEST_F(HttpCacheTest, SplitCacheEnabledByDefault) {
11670 HttpCache::ClearGlobalsForTesting();
11671 HttpCache::SplitCacheFeatureEnableByDefault();
11672 EXPECT_TRUE(HttpCache::IsSplitCacheEnabled());
11673
11674 MockHttpCache cache;
11675 HttpResponseInfo response;
11676
11677 SchemefulSite site_a(GURL("http://a.com"));
11678 SchemefulSite site_b(GURL("http://b.com"));
11679 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11680 net::NetworkIsolationKey key_a(site_a, site_a);
11681 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11682 trans_info.network_isolation_key = key_a;
11683 trans_info.network_anonymization_key = nak_a;
11684 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11685 trans_info, &response);
11686 EXPECT_FALSE(response.was_cached);
11687
11688 // Subsequent requests with the same NIK and different NIK will be a cache hit
11689 // and miss respectively.
11690 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11691 trans_info, &response);
11692 EXPECT_TRUE(response.was_cached);
11693
11694 net::NetworkIsolationKey key_b(site_b, site_b);
11695 auto nak_b = net::NetworkAnonymizationKey::CreateSameSite(site_b);
11696 trans_info.network_isolation_key = key_b;
11697 trans_info.network_anonymization_key = nak_b;
11698 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11699 trans_info, &response);
11700 EXPECT_FALSE(response.was_cached);
11701 }
11702
TEST_F(HttpCacheTest,SplitCacheEnabledByDefaultButOverridden)11703 TEST_F(HttpCacheTest, SplitCacheEnabledByDefaultButOverridden) {
11704 HttpCache::ClearGlobalsForTesting();
11705 base::test::ScopedFeatureList feature_list;
11706 feature_list.InitAndDisableFeature(
11707 net::features::kSplitCacheByNetworkIsolationKey);
11708
11709 // Enabling it here should have no effect as it is already overridden.
11710 HttpCache::SplitCacheFeatureEnableByDefault();
11711 EXPECT_FALSE(HttpCache::IsSplitCacheEnabled());
11712 }
11713
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCacheUsesRegistrableDomain)11714 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
11715 SplitCacheUsesRegistrableDomain) {
11716 MockHttpCache cache;
11717 HttpResponseInfo response;
11718 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11719
11720 SchemefulSite site_a(GURL("http://a.foo.com"));
11721 SchemefulSite site_b(GURL("http://b.foo.com"));
11722
11723 net::NetworkIsolationKey key_a(site_a, site_a);
11724 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11725 trans_info.network_isolation_key = key_a;
11726 trans_info.network_anonymization_key = nak_a;
11727 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11728 trans_info, &response);
11729 EXPECT_FALSE(response.was_cached);
11730
11731 // The second request with a different origin but the same registrable domain
11732 // should be a cache hit.
11733 net::NetworkIsolationKey key_b(site_b, site_b);
11734 auto nak_b = net::NetworkAnonymizationKey::CreateSameSite(site_b);
11735 trans_info.network_isolation_key = key_b;
11736 trans_info.network_anonymization_key = nak_b;
11737 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11738 trans_info, &response);
11739 EXPECT_TRUE(response.was_cached);
11740
11741 // Request with a different registrable domain. It should be a cache miss.
11742 SchemefulSite new_site_a(GURL("http://a.bar.com"));
11743 net::NetworkIsolationKey new_key_a(new_site_a, new_site_a);
11744 auto new_nak_a = net::NetworkAnonymizationKey::CreateSameSite(new_site_a);
11745 trans_info.network_isolation_key = new_key_a;
11746 trans_info.network_anonymization_key = new_nak_a;
11747 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11748 trans_info, &response);
11749 EXPECT_FALSE(response.was_cached);
11750 }
11751
TEST_F(HttpCacheTest,NonSplitCache)11752 TEST_F(HttpCacheTest, NonSplitCache) {
11753 base::test::ScopedFeatureList feature_list;
11754 feature_list.InitAndDisableFeature(
11755 net::features::kSplitCacheByNetworkIsolationKey);
11756
11757 MockHttpCache cache;
11758 HttpResponseInfo response;
11759
11760 // A request without a top frame is added to the cache normally.
11761 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11762 trans_info.network_isolation_key = NetworkIsolationKey();
11763 trans_info.network_anonymization_key = NetworkAnonymizationKey();
11764 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11765 trans_info, &response);
11766 EXPECT_FALSE(response.was_cached);
11767
11768 // The second request should result in a cache hit.
11769 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11770 trans_info, &response);
11771 EXPECT_TRUE(response.was_cached);
11772
11773 // Now request with a.com as the top frame origin. The same cached object
11774 // should be used.
11775 const SchemefulSite kSiteA(GURL("http://a.com/"));
11776 trans_info.network_isolation_key = NetworkIsolationKey(kSiteA, kSiteA);
11777 trans_info.network_anonymization_key =
11778 NetworkAnonymizationKey::CreateSameSite(kSiteA);
11779 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11780 trans_info, &response);
11781 EXPECT_TRUE(response.was_cached);
11782 }
11783
TEST_F(HttpCacheTest,SkipVaryCheck)11784 TEST_F(HttpCacheTest, SkipVaryCheck) {
11785 MockHttpCache cache;
11786
11787 // Write a simple vary transaction to the cache.
11788 HttpResponseInfo response;
11789 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11790 transaction.request_headers = "accept-encoding: gzip\r\n";
11791 transaction.response_headers =
11792 "Vary: accept-encoding\n"
11793 "Cache-Control: max-age=10000\n";
11794 RunTransactionTest(cache.http_cache(), transaction);
11795
11796 // Change the request headers so that the request doesn't match due to vary.
11797 // The request should fail.
11798 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11799 transaction.request_headers = "accept-encoding: foo\r\n";
11800 transaction.start_return_code = ERR_CACHE_MISS;
11801 RunTransactionTest(cache.http_cache(), transaction);
11802
11803 // Change the load flags to ignore vary checks, the request should now hit.
11804 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_VARY_CHECK;
11805 transaction.start_return_code = OK;
11806 RunTransactionTest(cache.http_cache(), transaction);
11807 }
11808
TEST_F(HttpCacheTest,SkipVaryCheckStar)11809 TEST_F(HttpCacheTest, SkipVaryCheckStar) {
11810 MockHttpCache cache;
11811
11812 // Write a simple vary:* transaction to the cache.
11813 HttpResponseInfo response;
11814 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11815 transaction.request_headers = "accept-encoding: gzip\r\n";
11816 transaction.response_headers =
11817 "Vary: *\n"
11818 "Cache-Control: max-age=10000\n";
11819 RunTransactionTest(cache.http_cache(), transaction);
11820
11821 // The request shouldn't match even with the same request headers due to the
11822 // Vary: *. The request should fail.
11823 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11824 transaction.start_return_code = ERR_CACHE_MISS;
11825 RunTransactionTest(cache.http_cache(), transaction);
11826
11827 // Change the load flags to ignore vary checks, the request should now hit.
11828 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_VARY_CHECK;
11829 transaction.start_return_code = OK;
11830 RunTransactionTest(cache.http_cache(), transaction);
11831 }
11832
11833 // Tests that we only return valid entries with LOAD_ONLY_FROM_CACHE
11834 // transactions unless LOAD_SKIP_CACHE_VALIDATION is set.
TEST_F(HttpCacheTest,ValidLoadOnlyFromCache)11835 TEST_F(HttpCacheTest, ValidLoadOnlyFromCache) {
11836 MockHttpCache cache;
11837 base::SimpleTestClock clock;
11838 cache.http_cache()->SetClockForTesting(&clock);
11839 cache.network_layer()->SetClock(&clock);
11840
11841 // Write a resource that will expire in 100 seconds.
11842 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11843 transaction.response_headers = "Cache-Control: max-age=100\n";
11844 RunTransactionTest(cache.http_cache(), transaction);
11845
11846 // Move forward in time such that the cached response is no longer valid.
11847 clock.Advance(base::Seconds(101));
11848
11849 // Skipping cache validation should still return a response.
11850 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
11851 RunTransactionTest(cache.http_cache(), transaction);
11852
11853 // If the cache entry is checked for validitiy, it should fail.
11854 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11855 transaction.start_return_code = ERR_CACHE_MISS;
11856 RunTransactionTest(cache.http_cache(), transaction);
11857 }
11858
TEST_F(HttpCacheTest,InvalidLoadFlagCombination)11859 TEST_F(HttpCacheTest, InvalidLoadFlagCombination) {
11860 MockHttpCache cache;
11861
11862 // Put the resource in the cache.
11863 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11864
11865 // Now try to fetch it again, but with a flag combination disallowing both
11866 // cache and network access.
11867 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11868 // DevTools relies on this combination of flags for "disable cache" mode
11869 // when a resource is only supposed to be loaded from cache.
11870 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_BYPASS_CACHE;
11871 transaction.start_return_code = ERR_CACHE_MISS;
11872 RunTransactionTest(cache.http_cache(), transaction);
11873 }
11874
11875 // Tests that we don't mark entries as truncated when a filter detects the end
11876 // of the stream.
TEST_F(HttpCacheTest,FilterCompletion)11877 TEST_F(HttpCacheTest, FilterCompletion) {
11878 MockHttpCache cache;
11879 TestCompletionCallback callback;
11880
11881 {
11882 MockHttpRequest request(kSimpleGET_Transaction);
11883 std::unique_ptr<HttpTransaction> trans;
11884 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11885
11886 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11887 EXPECT_THAT(callback.GetResult(rv), IsOk());
11888
11889 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
11890 rv = trans->Read(buf.get(), 256, callback.callback());
11891 EXPECT_GT(callback.GetResult(rv), 0);
11892
11893 // Now make sure that the entry is preserved.
11894 trans->DoneReading();
11895 }
11896
11897 // Make sure that the ActiveEntry is gone.
11898 base::RunLoop().RunUntilIdle();
11899
11900 // Read from the cache.
11901 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11902
11903 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11904 EXPECT_EQ(1, cache.disk_cache()->open_count());
11905 EXPECT_EQ(1, cache.disk_cache()->create_count());
11906 }
11907
11908 // Tests that we don't mark entries as truncated and release the cache
11909 // entry when DoneReading() is called before any Read() calls, such as
11910 // for a redirect.
TEST_F(HttpCacheTest,DoneReading)11911 TEST_F(HttpCacheTest, DoneReading) {
11912 MockHttpCache cache;
11913 TestCompletionCallback callback;
11914
11915 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11916 transaction.data = "";
11917 MockHttpRequest request(transaction);
11918
11919 std::unique_ptr<HttpTransaction> trans;
11920 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11921
11922 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11923 EXPECT_THAT(callback.GetResult(rv), IsOk());
11924
11925 trans->DoneReading();
11926 // Leave the transaction around.
11927
11928 // Make sure that the ActiveEntry is gone.
11929 base::RunLoop().RunUntilIdle();
11930
11931 // Read from the cache. This should not deadlock.
11932 RunTransactionTest(cache.http_cache(), transaction);
11933
11934 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11935 EXPECT_EQ(1, cache.disk_cache()->open_count());
11936 EXPECT_EQ(1, cache.disk_cache()->create_count());
11937 }
11938
11939 // Tests that we stop caching when told.
TEST_F(HttpCacheTest,StopCachingDeletesEntry)11940 TEST_F(HttpCacheTest, StopCachingDeletesEntry) {
11941 MockHttpCache cache;
11942 TestCompletionCallback callback;
11943 MockHttpRequest request(kSimpleGET_Transaction);
11944
11945 {
11946 std::unique_ptr<HttpTransaction> trans;
11947 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11948
11949 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11950 EXPECT_THAT(callback.GetResult(rv), IsOk());
11951
11952 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
11953 rv = trans->Read(buf.get(), 10, callback.callback());
11954 EXPECT_EQ(10, callback.GetResult(rv));
11955
11956 trans->StopCaching();
11957
11958 // We should be able to keep reading.
11959 rv = trans->Read(buf.get(), 256, callback.callback());
11960 EXPECT_GT(callback.GetResult(rv), 0);
11961 rv = trans->Read(buf.get(), 256, callback.callback());
11962 EXPECT_EQ(0, callback.GetResult(rv));
11963 }
11964
11965 // Make sure that the ActiveEntry is gone.
11966 base::RunLoop().RunUntilIdle();
11967
11968 // Verify that the entry is gone.
11969 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11970
11971 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11972 EXPECT_EQ(0, cache.disk_cache()->open_count());
11973 EXPECT_EQ(2, cache.disk_cache()->create_count());
11974 }
11975
11976 // Tests that we stop caching when told, even if DoneReading is called
11977 // after StopCaching.
TEST_F(HttpCacheTest,StopCachingThenDoneReadingDeletesEntry)11978 TEST_F(HttpCacheTest, StopCachingThenDoneReadingDeletesEntry) {
11979 MockHttpCache cache;
11980 TestCompletionCallback callback;
11981 MockHttpRequest request(kSimpleGET_Transaction);
11982
11983 {
11984 std::unique_ptr<HttpTransaction> trans;
11985 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11986
11987 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11988 EXPECT_THAT(callback.GetResult(rv), IsOk());
11989
11990 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
11991 rv = trans->Read(buf.get(), 10, callback.callback());
11992 EXPECT_EQ(10, callback.GetResult(rv));
11993
11994 trans->StopCaching();
11995
11996 // We should be able to keep reading.
11997 rv = trans->Read(buf.get(), 256, callback.callback());
11998 EXPECT_GT(callback.GetResult(rv), 0);
11999 rv = trans->Read(buf.get(), 256, callback.callback());
12000 EXPECT_EQ(0, callback.GetResult(rv));
12001
12002 // We should be able to call DoneReading.
12003 trans->DoneReading();
12004 }
12005
12006 // Make sure that the ActiveEntry is gone.
12007 base::RunLoop().RunUntilIdle();
12008
12009 // Verify that the entry is gone.
12010 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
12011
12012 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12013 EXPECT_EQ(0, cache.disk_cache()->open_count());
12014 EXPECT_EQ(2, cache.disk_cache()->create_count());
12015 }
12016
12017 // Tests that we stop caching when told, when using auth.
TEST_F(HttpCacheTest,StopCachingWithAuthDeletesEntry)12018 TEST_F(HttpCacheTest, StopCachingWithAuthDeletesEntry) {
12019 MockHttpCache cache;
12020 TestCompletionCallback callback;
12021 MockTransaction mock_transaction(kSimpleGET_Transaction);
12022 mock_transaction.status = "HTTP/1.1 401 Unauthorized";
12023 AddMockTransaction(&mock_transaction);
12024 MockHttpRequest request(mock_transaction);
12025
12026 {
12027 std::unique_ptr<HttpTransaction> trans;
12028 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
12029
12030 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12031 EXPECT_THAT(callback.GetResult(rv), IsOk());
12032
12033 trans->StopCaching();
12034 }
12035 RemoveMockTransaction(&mock_transaction);
12036
12037 // Make sure that the ActiveEntry is gone.
12038 base::RunLoop().RunUntilIdle();
12039
12040 // Verify that the entry is gone.
12041 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
12042
12043 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12044 EXPECT_EQ(0, cache.disk_cache()->open_count());
12045 EXPECT_EQ(2, cache.disk_cache()->create_count());
12046 }
12047
12048 // Tests that when we are told to stop caching we don't throw away valid data.
TEST_F(HttpCacheTest,StopCachingSavesEntry)12049 TEST_F(HttpCacheTest, StopCachingSavesEntry) {
12050 MockHttpCache cache;
12051 TestCompletionCallback callback;
12052 MockHttpRequest request(kSimpleGET_Transaction);
12053
12054 {
12055 std::unique_ptr<HttpTransaction> trans;
12056 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
12057
12058 // Force a response that can be resumed.
12059 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
12060 AddMockTransaction(&mock_transaction);
12061 mock_transaction.response_headers = "Cache-Control: max-age=10000\n"
12062 "Content-Length: 42\n"
12063 "Etag: \"foo\"\n";
12064
12065 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12066 EXPECT_THAT(callback.GetResult(rv), IsOk());
12067
12068 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
12069 rv = trans->Read(buf.get(), 10, callback.callback());
12070 EXPECT_EQ(callback.GetResult(rv), 10);
12071
12072 trans->StopCaching();
12073
12074 // We should be able to keep reading.
12075 rv = trans->Read(buf.get(), 256, callback.callback());
12076 EXPECT_GT(callback.GetResult(rv), 0);
12077 rv = trans->Read(buf.get(), 256, callback.callback());
12078 EXPECT_EQ(callback.GetResult(rv), 0);
12079 }
12080
12081 // Verify that the entry is marked as incomplete.
12082 // VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0);
12083 // Verify that the entry is doomed.
12084 cache.disk_cache()->IsDiskEntryDoomed(request.CacheKey());
12085 }
12086
12087 // Tests that we handle truncated enries when StopCaching is called.
TEST_F(HttpCacheTest,StopCachingTruncatedEntry)12088 TEST_F(HttpCacheTest, StopCachingTruncatedEntry) {
12089 MockHttpCache cache;
12090 TestCompletionCallback callback;
12091 MockHttpRequest request(kRangeGET_TransactionOK);
12092 request.extra_headers.Clear();
12093 request.extra_headers.AddHeaderFromString(EXTRA_HEADER_LINE);
12094 AddMockTransaction(&kRangeGET_TransactionOK);
12095
12096 std::string raw_headers("HTTP/1.1 200 OK\n"
12097 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12098 "ETag: \"foo\"\n"
12099 "Accept-Ranges: bytes\n"
12100 "Content-Length: 80\n");
12101 CreateTruncatedEntry(raw_headers, &cache);
12102
12103 {
12104 // Now make a regular request.
12105 std::unique_ptr<HttpTransaction> trans;
12106 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
12107
12108 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12109 EXPECT_THAT(callback.GetResult(rv), IsOk());
12110
12111 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
12112 rv = trans->Read(buf.get(), 10, callback.callback());
12113 EXPECT_EQ(callback.GetResult(rv), 10);
12114
12115 // This is actually going to do nothing.
12116 trans->StopCaching();
12117
12118 // We should be able to keep reading.
12119 rv = trans->Read(buf.get(), 256, callback.callback());
12120 EXPECT_GT(callback.GetResult(rv), 0);
12121 rv = trans->Read(buf.get(), 256, callback.callback());
12122 EXPECT_GT(callback.GetResult(rv), 0);
12123 rv = trans->Read(buf.get(), 256, callback.callback());
12124 EXPECT_EQ(callback.GetResult(rv), 0);
12125 }
12126
12127 // Verify that the disk entry was updated.
12128 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 80);
12129 RemoveMockTransaction(&kRangeGET_TransactionOK);
12130 }
12131
12132 namespace {
12133
12134 enum class TransactionPhase {
12135 BEFORE_FIRST_READ,
12136 AFTER_FIRST_READ,
12137 AFTER_NETWORK_READ
12138 };
12139
12140 using CacheInitializer = void (*)(MockHttpCache*);
12141 using HugeCacheTestConfiguration =
12142 std::pair<TransactionPhase, CacheInitializer>;
12143
12144 class HttpCacheHugeResourceTest
12145 : public ::testing::TestWithParam<HugeCacheTestConfiguration>,
12146 public WithTaskEnvironment {
12147 public:
12148 static std::list<HugeCacheTestConfiguration> GetTestModes();
12149 static std::list<HugeCacheTestConfiguration> kTestModes;
12150
12151 // CacheInitializer callbacks. These are used to initialize the cache
12152 // depending on the test run configuration.
12153
12154 // Initializes a cache containing a truncated entry containing the first 20
12155 // bytes of the reponse body.
12156 static void SetupTruncatedCacheEntry(MockHttpCache* cache);
12157
12158 // Initializes a cache containing a sparse entry. The first 10 bytes are
12159 // present in the cache.
12160 static void SetupPrefixSparseCacheEntry(MockHttpCache* cache);
12161
12162 // Initializes a cache containing a sparse entry. The 10 bytes at offset
12163 // 99990 are present in the cache.
12164 static void SetupInfixSparseCacheEntry(MockHttpCache* cache);
12165
12166 protected:
12167 static void LargeResourceTransactionHandler(
12168 const net::HttpRequestInfo* request,
12169 std::string* response_status,
12170 std::string* response_headers,
12171 std::string* response_data);
12172 static int LargeBufferReader(int64_t content_length,
12173 int64_t offset,
12174 net::IOBuffer* buf,
12175 int buf_len);
12176
12177 static void SetFlagOnBeforeNetworkStart(bool* started, bool* /* defer */);
12178
12179 // Size of resource to be tested.
12180 static const int64_t kTotalSize = 5000LL * 1000 * 1000;
12181 };
12182
12183 const int64_t HttpCacheHugeResourceTest::kTotalSize;
12184
12185 // static
LargeResourceTransactionHandler(const net::HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)12186 void HttpCacheHugeResourceTest::LargeResourceTransactionHandler(
12187 const net::HttpRequestInfo* request,
12188 std::string* response_status,
12189 std::string* response_headers,
12190 std::string* response_data) {
12191 std::string if_range;
12192 if (!request->extra_headers.GetHeader(net::HttpRequestHeaders::kIfRange,
12193 &if_range)) {
12194 // If there were no range headers in the request, we are going to just
12195 // return the entire response body.
12196 *response_status = "HTTP/1.1 200 Success";
12197 *response_headers = base::StringPrintf("Content-Length: %" PRId64
12198 "\n"
12199 "ETag: \"foo\"\n"
12200 "Accept-Ranges: bytes\n",
12201 kTotalSize);
12202 return;
12203 }
12204
12205 // From this point on, we should be processing a valid byte-range request.
12206 EXPECT_EQ("\"foo\"", if_range);
12207
12208 std::string range_header;
12209 EXPECT_TRUE(request->extra_headers.GetHeader(net::HttpRequestHeaders::kRange,
12210 &range_header));
12211 std::vector<net::HttpByteRange> ranges;
12212
12213 EXPECT_TRUE(net::HttpUtil::ParseRangeHeader(range_header, &ranges));
12214 ASSERT_EQ(1u, ranges.size());
12215
12216 net::HttpByteRange range = ranges[0];
12217 EXPECT_TRUE(range.HasFirstBytePosition());
12218 int64_t last_byte_position =
12219 range.HasLastBytePosition() ? range.last_byte_position() : kTotalSize - 1;
12220
12221 *response_status = "HTTP/1.1 206 Partial";
12222 *response_headers = base::StringPrintf(
12223 "Content-Range: bytes %" PRId64 "-%" PRId64 "/%" PRId64
12224 "\n"
12225 "Content-Length: %" PRId64 "\n",
12226 range.first_byte_position(), last_byte_position, kTotalSize,
12227 last_byte_position - range.first_byte_position() + 1);
12228 }
12229
12230 // static
LargeBufferReader(int64_t content_length,int64_t offset,net::IOBuffer * buf,int buf_len)12231 int HttpCacheHugeResourceTest::LargeBufferReader(int64_t content_length,
12232 int64_t offset,
12233 net::IOBuffer* buf,
12234 int buf_len) {
12235 // This test involves reading multiple gigabytes of data. To make it run in a
12236 // reasonable amount of time, we are going to skip filling the buffer with
12237 // data. Instead the test relies on verifying that the count of bytes expected
12238 // at the end is correct.
12239 EXPECT_LT(0, content_length);
12240 EXPECT_LE(offset, content_length);
12241 int num = std::min(static_cast<int64_t>(buf_len), content_length - offset);
12242 return num;
12243 }
12244
12245 // static
SetFlagOnBeforeNetworkStart(bool * started,bool *)12246 void HttpCacheHugeResourceTest::SetFlagOnBeforeNetworkStart(bool* started,
12247 bool* /* defer */) {
12248 *started = true;
12249 }
12250
12251 // static
SetupTruncatedCacheEntry(MockHttpCache * cache)12252 void HttpCacheHugeResourceTest::SetupTruncatedCacheEntry(MockHttpCache* cache) {
12253 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
12254 std::string cached_headers = base::StringPrintf(
12255 "HTTP/1.1 200 OK\n"
12256 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12257 "ETag: \"foo\"\n"
12258 "Accept-Ranges: bytes\n"
12259 "Content-Length: %" PRId64 "\n",
12260 kTotalSize);
12261 CreateTruncatedEntry(cached_headers, cache);
12262 }
12263
12264 // static
SetupPrefixSparseCacheEntry(MockHttpCache * cache)12265 void HttpCacheHugeResourceTest::SetupPrefixSparseCacheEntry(
12266 MockHttpCache* cache) {
12267 MockTransaction transaction(kRangeGET_TransactionOK);
12268 transaction.handler = MockTransactionHandler();
12269 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
12270 transaction.response_headers =
12271 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12272 "ETag: \"foo\"\n"
12273 "Accept-Ranges: bytes\n"
12274 "Content-Range: bytes 0-9/5000000000\n"
12275 "Content-Length: 10\n";
12276 AddMockTransaction(&transaction);
12277 std::string headers;
12278 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
12279 RemoveMockTransaction(&transaction);
12280 }
12281
12282 // static
SetupInfixSparseCacheEntry(MockHttpCache * cache)12283 void HttpCacheHugeResourceTest::SetupInfixSparseCacheEntry(
12284 MockHttpCache* cache) {
12285 MockTransaction transaction(kRangeGET_TransactionOK);
12286 transaction.handler = MockTransactionHandler();
12287 transaction.request_headers = "Range: bytes = 99990-99999\r\n" EXTRA_HEADER;
12288 transaction.response_headers =
12289 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12290 "ETag: \"foo\"\n"
12291 "Accept-Ranges: bytes\n"
12292 "Content-Range: bytes 99990-99999/5000000000\n"
12293 "Content-Length: 10\n";
12294 AddMockTransaction(&transaction);
12295 std::string headers;
12296 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
12297 RemoveMockTransaction(&transaction);
12298 }
12299
12300 // static
12301 std::list<HugeCacheTestConfiguration>
GetTestModes()12302 HttpCacheHugeResourceTest::GetTestModes() {
12303 std::list<HugeCacheTestConfiguration> test_modes;
12304 const TransactionPhase kTransactionPhases[] = {
12305 TransactionPhase::BEFORE_FIRST_READ, TransactionPhase::AFTER_FIRST_READ,
12306 TransactionPhase::AFTER_NETWORK_READ};
12307 const CacheInitializer kInitializers[] = {&SetupTruncatedCacheEntry,
12308 &SetupPrefixSparseCacheEntry,
12309 &SetupInfixSparseCacheEntry};
12310
12311 for (const auto phase : kTransactionPhases)
12312 for (const auto initializer : kInitializers)
12313 test_modes.emplace_back(phase, initializer);
12314
12315 return test_modes;
12316 }
12317
12318 // static
12319 std::list<HugeCacheTestConfiguration> HttpCacheHugeResourceTest::kTestModes =
12320 HttpCacheHugeResourceTest::GetTestModes();
12321
12322 INSTANTIATE_TEST_SUITE_P(
12323 _,
12324 HttpCacheHugeResourceTest,
12325 ::testing::ValuesIn(HttpCacheHugeResourceTest::kTestModes));
12326
12327 } // namespace
12328
12329 // Test what happens when StopCaching() is called while reading a huge resource
12330 // fetched via GET. Various combinations of cache state and when StopCaching()
12331 // is called is controlled by the parameter passed into the test via the
12332 // INSTANTIATE_TEST_SUITE_P invocation above.
TEST_P(HttpCacheHugeResourceTest,StopCachingFollowedByReadForHugeTruncatedResource)12333 TEST_P(HttpCacheHugeResourceTest,
12334 StopCachingFollowedByReadForHugeTruncatedResource) {
12335 // This test is going to be repeated for all combinations of TransactionPhase
12336 // and CacheInitializers returned by GetTestModes().
12337 const TransactionPhase stop_caching_phase = GetParam().first;
12338 const CacheInitializer cache_initializer = GetParam().second;
12339
12340 MockHttpCache cache;
12341 (*cache_initializer)(&cache);
12342
12343 MockTransaction transaction(kSimpleGET_Transaction);
12344 transaction.url = kRangeGET_TransactionOK.url;
12345 transaction.handler = base::BindRepeating(&LargeResourceTransactionHandler);
12346 transaction.read_handler = base::BindRepeating(&LargeBufferReader);
12347 ScopedMockTransaction scoped_transaction(transaction);
12348
12349 MockHttpRequest request(transaction);
12350 net::TestCompletionCallback callback;
12351 std::unique_ptr<net::HttpTransaction> http_transaction;
12352 int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY,
12353 &http_transaction);
12354 ASSERT_EQ(net::OK, rv);
12355 ASSERT_TRUE(http_transaction.get());
12356
12357 bool network_transaction_started = false;
12358 if (stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
12359 http_transaction->SetBeforeNetworkStartCallback(base::BindOnce(
12360 &SetFlagOnBeforeNetworkStart, &network_transaction_started));
12361 }
12362
12363 rv = http_transaction->Start(&request, callback.callback(),
12364 NetLogWithSource());
12365 rv = callback.GetResult(rv);
12366 ASSERT_EQ(net::OK, rv);
12367
12368 if (stop_caching_phase == TransactionPhase::BEFORE_FIRST_READ)
12369 http_transaction->StopCaching();
12370
12371 int64_t total_bytes_received = 0;
12372
12373 EXPECT_EQ(kTotalSize,
12374 http_transaction->GetResponseInfo()->headers->GetContentLength());
12375 do {
12376 // This test simulates reading gigabytes of data. Buffer size is set to 10MB
12377 // to reduce the number of reads and speed up the test.
12378 const int kBufferSize = 1024 * 1024 * 10;
12379 scoped_refptr<net::IOBuffer> buf =
12380 base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
12381 rv = http_transaction->Read(buf.get(), kBufferSize, callback.callback());
12382 rv = callback.GetResult(rv);
12383
12384 if (stop_caching_phase == TransactionPhase::AFTER_FIRST_READ &&
12385 total_bytes_received == 0) {
12386 http_transaction->StopCaching();
12387 }
12388
12389 if (rv > 0)
12390 total_bytes_received += rv;
12391
12392 if (network_transaction_started &&
12393 stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
12394 http_transaction->StopCaching();
12395 network_transaction_started = false;
12396 }
12397 } while (rv > 0);
12398
12399 // The only verification we are going to do is that the received resource has
12400 // the correct size. This is sufficient to verify that the state machine
12401 // didn't terminate abruptly due to the StopCaching() call.
12402 EXPECT_EQ(kTotalSize, total_bytes_received);
12403 }
12404
12405 // Tests that we detect truncated resources from the net when there is
12406 // a Content-Length header.
TEST_F(HttpCacheTest,TruncatedByContentLength)12407 TEST_F(HttpCacheTest, TruncatedByContentLength) {
12408 MockHttpCache cache;
12409 TestCompletionCallback callback;
12410
12411 MockTransaction transaction(kSimpleGET_Transaction);
12412 AddMockTransaction(&transaction);
12413 transaction.response_headers = "Cache-Control: max-age=10000\n"
12414 "Content-Length: 100\n";
12415 RunTransactionTest(cache.http_cache(), transaction);
12416 RemoveMockTransaction(&transaction);
12417
12418 // Read from the cache.
12419 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
12420
12421 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12422 EXPECT_EQ(0, cache.disk_cache()->open_count());
12423 EXPECT_EQ(2, cache.disk_cache()->create_count());
12424 }
12425
12426 // Tests that we actually flag entries as truncated when we detect an error
12427 // from the net.
TEST_F(HttpCacheTest,TruncatedByContentLength2)12428 TEST_F(HttpCacheTest, TruncatedByContentLength2) {
12429 MockHttpCache cache;
12430 TestCompletionCallback callback;
12431
12432 MockTransaction transaction(kSimpleGET_Transaction);
12433 AddMockTransaction(&transaction);
12434 transaction.response_headers = "Cache-Control: max-age=10000\n"
12435 "Content-Length: 100\n"
12436 "Etag: \"foo\"\n";
12437 RunTransactionTest(cache.http_cache(), transaction);
12438 RemoveMockTransaction(&transaction);
12439
12440 // Verify that the entry is marked as incomplete.
12441 MockHttpRequest request(transaction);
12442 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 0);
12443 }
12444
12445 // Make sure that calling SetPriority on a cache transaction passes on
12446 // its priority updates to its underlying network transaction.
TEST_F(HttpCacheTest,SetPriority)12447 TEST_F(HttpCacheTest, SetPriority) {
12448 MockHttpCache cache;
12449
12450 HttpRequestInfo info;
12451 std::unique_ptr<HttpTransaction> trans;
12452 ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk());
12453
12454 // Shouldn't crash, but doesn't do anything either.
12455 trans->SetPriority(LOW);
12456
12457 EXPECT_FALSE(cache.network_layer()->last_transaction());
12458 EXPECT_EQ(DEFAULT_PRIORITY,
12459 cache.network_layer()->last_create_transaction_priority());
12460
12461 info.url = GURL(kSimpleGET_Transaction.url);
12462 TestCompletionCallback callback;
12463 EXPECT_EQ(ERR_IO_PENDING,
12464 trans->Start(&info, callback.callback(), NetLogWithSource()));
12465
12466 EXPECT_TRUE(cache.network_layer()->last_transaction());
12467 if (cache.network_layer()->last_transaction()) {
12468 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
12469 EXPECT_EQ(LOW, cache.network_layer()->last_transaction()->priority());
12470 }
12471
12472 trans->SetPriority(HIGHEST);
12473
12474 if (cache.network_layer()->last_transaction()) {
12475 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
12476 EXPECT_EQ(HIGHEST, cache.network_layer()->last_transaction()->priority());
12477 }
12478
12479 EXPECT_THAT(callback.WaitForResult(), IsOk());
12480 }
12481
12482 // Make sure that calling SetWebSocketHandshakeStreamCreateHelper on a cache
12483 // transaction passes on its argument to the underlying network transaction.
TEST_F(HttpCacheTest,SetWebSocketHandshakeStreamCreateHelper)12484 TEST_F(HttpCacheTest, SetWebSocketHandshakeStreamCreateHelper) {
12485 MockHttpCache cache;
12486 HttpRequestInfo info;
12487
12488 FakeWebSocketHandshakeStreamCreateHelper create_helper;
12489 std::unique_ptr<HttpTransaction> trans;
12490 ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk());
12491
12492 EXPECT_FALSE(cache.network_layer()->last_transaction());
12493
12494 info.url = GURL(kSimpleGET_Transaction.url);
12495 TestCompletionCallback callback;
12496 EXPECT_EQ(ERR_IO_PENDING,
12497 trans->Start(&info, callback.callback(), NetLogWithSource()));
12498
12499 ASSERT_TRUE(cache.network_layer()->last_transaction());
12500 EXPECT_FALSE(cache.network_layer()->last_transaction()->
12501 websocket_handshake_stream_create_helper());
12502 trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper);
12503 EXPECT_EQ(&create_helper,
12504 cache.network_layer()->last_transaction()->
12505 websocket_handshake_stream_create_helper());
12506 EXPECT_THAT(callback.WaitForResult(), IsOk());
12507 }
12508
12509 // Make sure that a cache transaction passes on its priority to
12510 // newly-created network transactions.
TEST_F(HttpCacheTest,SetPriorityNewTransaction)12511 TEST_F(HttpCacheTest, SetPriorityNewTransaction) {
12512 MockHttpCache cache;
12513 AddMockTransaction(&kRangeGET_TransactionOK);
12514
12515 std::string raw_headers("HTTP/1.1 200 OK\n"
12516 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12517 "ETag: \"foo\"\n"
12518 "Accept-Ranges: bytes\n"
12519 "Content-Length: 80\n");
12520 CreateTruncatedEntry(raw_headers, &cache);
12521
12522 // Now make a regular request.
12523 std::string headers;
12524 MockTransaction transaction(kRangeGET_TransactionOK);
12525 transaction.request_headers = EXTRA_HEADER;
12526 transaction.data = kFullRangeData;
12527
12528 std::unique_ptr<HttpTransaction> trans;
12529 ASSERT_THAT(cache.http_cache()->CreateTransaction(MEDIUM, &trans), IsOk());
12530 EXPECT_EQ(DEFAULT_PRIORITY,
12531 cache.network_layer()->last_create_transaction_priority());
12532
12533 MockHttpRequest info(transaction);
12534 TestCompletionCallback callback;
12535 EXPECT_EQ(ERR_IO_PENDING,
12536 trans->Start(&info, callback.callback(), NetLogWithSource()));
12537 EXPECT_THAT(callback.WaitForResult(), IsOk());
12538
12539 EXPECT_EQ(MEDIUM, cache.network_layer()->last_create_transaction_priority());
12540
12541 trans->SetPriority(HIGHEST);
12542 // Should trigger a new network transaction and pick up the new
12543 // priority.
12544 ReadAndVerifyTransaction(trans.get(), transaction);
12545
12546 EXPECT_EQ(HIGHEST, cache.network_layer()->last_create_transaction_priority());
12547
12548 RemoveMockTransaction(&kRangeGET_TransactionOK);
12549 }
12550
12551 namespace {
12552
RunTransactionAndGetNetworkBytes(MockHttpCache * cache,const MockTransaction & trans_info,int64_t * sent_bytes,int64_t * received_bytes)12553 void RunTransactionAndGetNetworkBytes(MockHttpCache* cache,
12554 const MockTransaction& trans_info,
12555 int64_t* sent_bytes,
12556 int64_t* received_bytes) {
12557 RunTransactionTestBase(
12558 cache->http_cache(), trans_info, MockHttpRequest(trans_info), nullptr,
12559 NetLogWithSource(), nullptr, sent_bytes, received_bytes, nullptr);
12560 }
12561
12562 } // namespace
12563
TEST_F(HttpCacheTest,NetworkBytesCacheMissAndThenHit)12564 TEST_F(HttpCacheTest, NetworkBytesCacheMissAndThenHit) {
12565 MockHttpCache cache;
12566
12567 MockTransaction transaction(kSimpleGET_Transaction);
12568 int64_t sent, received;
12569 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12570 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12571 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12572
12573 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12574 EXPECT_EQ(0, sent);
12575 EXPECT_EQ(0, received);
12576 }
12577
TEST_F(HttpCacheTest,NetworkBytesConditionalRequest304)12578 TEST_F(HttpCacheTest, NetworkBytesConditionalRequest304) {
12579 MockHttpCache cache;
12580
12581 ScopedMockTransaction transaction(kETagGET_Transaction);
12582 int64_t sent, received;
12583 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12584 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12585 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12586
12587 transaction.load_flags = LOAD_VALIDATE_CACHE;
12588 transaction.handler = kETagGetConditionalRequestHandler;
12589 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12590 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12591 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12592 }
12593
TEST_F(HttpCacheTest,NetworkBytesConditionalRequest200)12594 TEST_F(HttpCacheTest, NetworkBytesConditionalRequest200) {
12595 MockHttpCache cache;
12596
12597 MockTransaction transaction(kTypicalGET_Transaction);
12598 transaction.request_headers = "Foo: bar\r\n";
12599 transaction.response_headers =
12600 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
12601 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
12602 "Etag: \"foopy\"\n"
12603 "Cache-Control: max-age=0\n"
12604 "Vary: Foo\n";
12605 AddMockTransaction(&transaction);
12606 int64_t sent, received;
12607 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12608 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12609 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12610
12611 RevalidationServer server;
12612 transaction.handler = server.GetHandlerCallback();
12613
12614 transaction.request_headers = "Foo: none\r\n";
12615 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12616 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12617 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12618
12619 RemoveMockTransaction(&transaction);
12620 }
12621
TEST_F(HttpCacheTest,NetworkBytesRange)12622 TEST_F(HttpCacheTest, NetworkBytesRange) {
12623 MockHttpCache cache;
12624 AddMockTransaction(&kRangeGET_TransactionOK);
12625 MockTransaction transaction(kRangeGET_TransactionOK);
12626
12627 // Read bytes 40-49 from the network.
12628 int64_t sent, received;
12629 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12630 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12631 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12632
12633 // Read bytes 40-49 from the cache.
12634 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12635 EXPECT_EQ(0, sent);
12636 EXPECT_EQ(0, received);
12637 base::RunLoop().RunUntilIdle();
12638
12639 // Read bytes 30-39 from the network.
12640 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
12641 transaction.data = "rg: 30-39 ";
12642 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12643 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12644 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12645 base::RunLoop().RunUntilIdle();
12646
12647 // Read bytes 20-29 and 50-59 from the network, bytes 30-49 from the cache.
12648 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
12649 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
12650 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12651 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes * 2, sent);
12652 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes * 2, received);
12653
12654 RemoveMockTransaction(&kRangeGET_TransactionOK);
12655 }
12656
12657 class HttpCachePrefetchValidationTest : public TestWithTaskEnvironment {
12658 protected:
12659 static const int kNumSecondsPerMinute = 60;
12660 static const int kMaxAgeSecs = 100;
12661 static const int kRequireValidationSecs = kMaxAgeSecs + 1;
12662
HttpCachePrefetchValidationTest()12663 HttpCachePrefetchValidationTest() : transaction_(kSimpleGET_Transaction) {
12664 DCHECK_LT(kMaxAgeSecs, prefetch_reuse_mins() * kNumSecondsPerMinute);
12665
12666 cache_.http_cache()->SetClockForTesting(&clock_);
12667 cache_.network_layer()->SetClock(&clock_);
12668
12669 transaction_.response_headers = "Cache-Control: max-age=100\n";
12670 }
12671
TransactionRequiredNetwork(int load_flags)12672 bool TransactionRequiredNetwork(int load_flags) {
12673 int pre_transaction_count = transaction_count();
12674 transaction_.load_flags = load_flags;
12675 RunTransactionTest(cache_.http_cache(), transaction_);
12676 return pre_transaction_count != transaction_count();
12677 }
12678
AdvanceTime(int seconds)12679 void AdvanceTime(int seconds) { clock_.Advance(base::Seconds(seconds)); }
12680
prefetch_reuse_mins()12681 int prefetch_reuse_mins() { return HttpCache::kPrefetchReuseMins; }
12682
12683 // How many times this test has sent requests to the (fake) origin
12684 // server. Every test case needs to make at least one request to initialise
12685 // the cache.
transaction_count()12686 int transaction_count() {
12687 return cache_.network_layer()->transaction_count();
12688 }
12689
12690 MockHttpCache cache_;
12691 ScopedMockTransaction transaction_;
12692 std::string response_headers_;
12693 base::SimpleTestClock clock_;
12694 };
12695
TEST_F(HttpCachePrefetchValidationTest,SkipValidationShortlyAfterPrefetch)12696 TEST_F(HttpCachePrefetchValidationTest, SkipValidationShortlyAfterPrefetch) {
12697 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12698 AdvanceTime(kRequireValidationSecs);
12699 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12700 }
12701
TEST_F(HttpCachePrefetchValidationTest,ValidateLongAfterPrefetch)12702 TEST_F(HttpCachePrefetchValidationTest, ValidateLongAfterPrefetch) {
12703 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12704 AdvanceTime(prefetch_reuse_mins() * kNumSecondsPerMinute);
12705 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12706 }
12707
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnceOnly)12708 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceOnly) {
12709 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12710 AdvanceTime(kRequireValidationSecs);
12711 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12712 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12713 }
12714
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnceReadOnly)12715 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceReadOnly) {
12716 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12717 AdvanceTime(kRequireValidationSecs);
12718 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_ONLY_FROM_CACHE |
12719 LOAD_SKIP_CACHE_VALIDATION));
12720 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12721 }
12722
TEST_F(HttpCachePrefetchValidationTest,BypassCacheOverwritesPrefetch)12723 TEST_F(HttpCachePrefetchValidationTest, BypassCacheOverwritesPrefetch) {
12724 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12725 AdvanceTime(kRequireValidationSecs);
12726 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_BYPASS_CACHE));
12727 AdvanceTime(kRequireValidationSecs);
12728 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12729 }
12730
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnExistingEntryThatNeedsValidation)12731 TEST_F(HttpCachePrefetchValidationTest,
12732 SkipValidationOnExistingEntryThatNeedsValidation) {
12733 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12734 AdvanceTime(kRequireValidationSecs);
12735 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12736 AdvanceTime(kRequireValidationSecs);
12737 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12738 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12739 }
12740
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnExistingEntryThatDoesNotNeedValidation)12741 TEST_F(HttpCachePrefetchValidationTest,
12742 SkipValidationOnExistingEntryThatDoesNotNeedValidation) {
12743 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12744 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
12745 AdvanceTime(kRequireValidationSecs);
12746 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12747 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12748 }
12749
TEST_F(HttpCachePrefetchValidationTest,PrefetchMultipleTimes)12750 TEST_F(HttpCachePrefetchValidationTest, PrefetchMultipleTimes) {
12751 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12752 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
12753 AdvanceTime(kRequireValidationSecs);
12754 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12755 }
12756
TEST_F(HttpCachePrefetchValidationTest,ValidateOnDelayedSecondPrefetch)12757 TEST_F(HttpCachePrefetchValidationTest, ValidateOnDelayedSecondPrefetch) {
12758 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12759 AdvanceTime(kRequireValidationSecs);
12760 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12761 AdvanceTime(kRequireValidationSecs);
12762 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12763 }
12764
TEST_F(HttpCacheTest,StaleContentNotUsedWhenLoadFlagNotSet)12765 TEST_F(HttpCacheTest, StaleContentNotUsedWhenLoadFlagNotSet) {
12766 MockHttpCache cache;
12767
12768 ScopedMockTransaction stale_while_revalidate_transaction(
12769 kSimpleGET_Transaction);
12770
12771 stale_while_revalidate_transaction.response_headers =
12772 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12773 "Age: 10801\n"
12774 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12775
12776 // Write to the cache.
12777 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12778
12779 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12780
12781 // Send the request again and check that it is sent to the network again.
12782 HttpResponseInfo response_info;
12783 RunTransactionTestWithResponseInfo(
12784 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12785
12786 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12787 EXPECT_FALSE(response_info.async_revalidation_requested);
12788 }
12789
TEST_F(HttpCacheTest,StaleContentUsedWhenLoadFlagSetAndUsableThenTimesout)12790 TEST_F(HttpCacheTest, StaleContentUsedWhenLoadFlagSetAndUsableThenTimesout) {
12791 MockHttpCache cache;
12792 base::SimpleTestClock clock;
12793 cache.http_cache()->SetClockForTesting(&clock);
12794 cache.network_layer()->SetClock(&clock);
12795 clock.Advance(base::Seconds(10));
12796
12797 ScopedMockTransaction stale_while_revalidate_transaction(
12798 kSimpleGET_Transaction);
12799 stale_while_revalidate_transaction.load_flags |=
12800 LOAD_SUPPORT_ASYNC_REVALIDATION;
12801 stale_while_revalidate_transaction.response_headers =
12802 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12803 "Age: 10801\n"
12804 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12805
12806 // Write to the cache.
12807 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12808
12809 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12810
12811 // Send the request again and check that it is not sent to the network again.
12812 HttpResponseInfo response_info;
12813 RunTransactionTestWithResponseInfo(
12814 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12815
12816 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12817 EXPECT_TRUE(response_info.async_revalidation_requested);
12818 EXPECT_FALSE(response_info.stale_revalidate_timeout.is_null());
12819
12820 // Move forward in time such that the stale response is no longer valid.
12821 clock.SetNow(response_info.stale_revalidate_timeout);
12822 clock.Advance(base::Seconds(1));
12823
12824 RunTransactionTestWithResponseInfo(
12825 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12826
12827 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12828 EXPECT_FALSE(response_info.async_revalidation_requested);
12829 }
12830
TEST_F(HttpCacheTest,StaleContentUsedWhenLoadFlagSetAndUsable)12831 TEST_F(HttpCacheTest, StaleContentUsedWhenLoadFlagSetAndUsable) {
12832 MockHttpCache cache;
12833 base::SimpleTestClock clock;
12834 cache.http_cache()->SetClockForTesting(&clock);
12835 cache.network_layer()->SetClock(&clock);
12836 clock.Advance(base::Seconds(10));
12837
12838 ScopedMockTransaction stale_while_revalidate_transaction(
12839 kSimpleGET_Transaction);
12840 stale_while_revalidate_transaction.load_flags |=
12841 LOAD_SUPPORT_ASYNC_REVALIDATION;
12842 stale_while_revalidate_transaction.response_headers =
12843 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12844 "Age: 10801\n"
12845 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12846
12847 // Write to the cache.
12848 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12849
12850 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12851
12852 // Send the request again and check that it is not sent to the network again.
12853 HttpResponseInfo response_info;
12854 RunTransactionTestWithResponseInfo(
12855 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12856
12857 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12858 EXPECT_TRUE(response_info.async_revalidation_requested);
12859 EXPECT_FALSE(response_info.stale_revalidate_timeout.is_null());
12860 base::Time revalidation_timeout = response_info.stale_revalidate_timeout;
12861 clock.Advance(base::Seconds(1));
12862 EXPECT_TRUE(clock.Now() < revalidation_timeout);
12863
12864 // Fetch the resource again inside the revalidation timeout window.
12865 RunTransactionTestWithResponseInfo(
12866 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12867
12868 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12869 EXPECT_TRUE(response_info.async_revalidation_requested);
12870 EXPECT_FALSE(response_info.stale_revalidate_timeout.is_null());
12871 // Expect that the original revalidation timeout hasn't changed.
12872 EXPECT_TRUE(revalidation_timeout == response_info.stale_revalidate_timeout);
12873
12874 // mask of async revalidation flag.
12875 stale_while_revalidate_transaction.load_flags &=
12876 ~LOAD_SUPPORT_ASYNC_REVALIDATION;
12877 stale_while_revalidate_transaction.status = "HTTP/1.1 304 Not Modified";
12878 // Write 304 to the cache.
12879 RunTransactionTestWithResponseInfo(
12880 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12881
12882 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12883 EXPECT_FALSE(response_info.async_revalidation_requested);
12884 EXPECT_TRUE(response_info.stale_revalidate_timeout.is_null());
12885 }
12886
TEST_F(HttpCacheTest,StaleContentNotUsedWhenUnusable)12887 TEST_F(HttpCacheTest, StaleContentNotUsedWhenUnusable) {
12888 MockHttpCache cache;
12889
12890 ScopedMockTransaction stale_while_revalidate_transaction(
12891 kSimpleGET_Transaction);
12892 stale_while_revalidate_transaction.load_flags |=
12893 LOAD_SUPPORT_ASYNC_REVALIDATION;
12894 stale_while_revalidate_transaction.response_headers =
12895 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12896 "Age: 10801\n"
12897 "Cache-Control: max-age=0,stale-while-revalidate=1800\n";
12898
12899 // Write to the cache.
12900 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12901
12902 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12903
12904 // Send the request again and check that it is sent to the network again.
12905 HttpResponseInfo response_info;
12906 RunTransactionTestWithResponseInfo(
12907 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12908
12909 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12910 EXPECT_FALSE(response_info.async_revalidation_requested);
12911 }
12912
TEST_F(HttpCacheTest,StaleContentWriteError)12913 TEST_F(HttpCacheTest, StaleContentWriteError) {
12914 MockHttpCache cache;
12915 base::SimpleTestClock clock;
12916 cache.http_cache()->SetClockForTesting(&clock);
12917 cache.network_layer()->SetClock(&clock);
12918 clock.Advance(base::Seconds(10));
12919
12920 ScopedMockTransaction stale_while_revalidate_transaction(
12921 kSimpleGET_Transaction);
12922 stale_while_revalidate_transaction.load_flags |=
12923 LOAD_SUPPORT_ASYNC_REVALIDATION;
12924 stale_while_revalidate_transaction.response_headers =
12925 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12926 "Age: 10801\n"
12927 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12928
12929 // Write to the cache.
12930 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12931
12932 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12933
12934 // Send the request again but inject a write fault. Should still work
12935 // (and not dereference any null pointers).
12936 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_WRITE);
12937 HttpResponseInfo response_info;
12938 RunTransactionTestWithResponseInfo(
12939 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12940
12941 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12942 }
12943
12944 // Tests that we allow multiple simultaneous, non-overlapping transactions to
12945 // take place on a sparse entry.
TEST_F(HttpCacheTest,RangeGET_MultipleRequests)12946 TEST_F(HttpCacheTest, RangeGET_MultipleRequests) {
12947 MockHttpCache cache;
12948
12949 // Create a transaction for bytes 0-9.
12950 MockHttpRequest request(kRangeGET_TransactionOK);
12951 MockTransaction transaction(kRangeGET_TransactionOK);
12952 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
12953 transaction.data = "rg: 00-09 ";
12954 AddMockTransaction(&transaction);
12955
12956 TestCompletionCallback callback;
12957 std::unique_ptr<HttpTransaction> trans;
12958 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
12959 EXPECT_THAT(rv, IsOk());
12960 ASSERT_TRUE(trans.get());
12961
12962 // Start our transaction.
12963 trans->Start(&request, callback.callback(), NetLogWithSource());
12964
12965 // A second transaction on a different part of the file (the default
12966 // kRangeGET_TransactionOK requests 40-49) should not be blocked by
12967 // the already pending transaction.
12968 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
12969
12970 // Let the first transaction complete.
12971 callback.WaitForResult();
12972
12973 RemoveMockTransaction(&transaction);
12974 }
12975
12976 // Verify that a range request can be satisfied from a completely cached
12977 // resource with the LOAD_ONLY_FROM_CACHE flag set. Currently it's not
12978 // implemented so it returns ERR_CACHE_MISS. See also
12979 // HttpCacheTest.RangeGET_OK_LoadOnlyFromCache.
12980 // TODO(ricea): Update this test if it is implemented in future.
TEST_F(HttpCacheTest,RangeGET_Previous200_LoadOnlyFromCache)12981 TEST_F(HttpCacheTest, RangeGET_Previous200_LoadOnlyFromCache) {
12982 MockHttpCache cache;
12983
12984 // Store the whole thing with status 200.
12985 MockTransaction transaction(kETagGET_Transaction);
12986 transaction.url = kRangeGET_TransactionOK.url;
12987 transaction.data = kFullRangeData;
12988 AddMockTransaction(&transaction);
12989 RunTransactionTest(cache.http_cache(), transaction);
12990 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12991 EXPECT_EQ(0, cache.disk_cache()->open_count());
12992 EXPECT_EQ(1, cache.disk_cache()->create_count());
12993
12994 RemoveMockTransaction(&transaction);
12995 AddMockTransaction(&kRangeGET_TransactionOK);
12996
12997 // Now see that we use the stored entry.
12998 MockTransaction transaction2(kRangeGET_TransactionOK);
12999 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE;
13000 MockHttpRequest request(transaction2);
13001 TestCompletionCallback callback;
13002
13003 std::unique_ptr<HttpTransaction> trans;
13004 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
13005 EXPECT_THAT(rv, IsOk());
13006 ASSERT_TRUE(trans);
13007
13008 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
13009 if (rv == ERR_IO_PENDING) {
13010 rv = callback.WaitForResult();
13011 }
13012 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
13013
13014 EXPECT_EQ(1, cache.network_layer()->transaction_count());
13015 EXPECT_EQ(1, cache.disk_cache()->open_count());
13016 EXPECT_EQ(1, cache.disk_cache()->create_count());
13017 }
13018
13019 // Makes sure that a request stops using the cache when the response headers
13020 // with "Cache-Control: no-store" arrives. That means that another request for
13021 // the same URL can be processed before the response body of the original
13022 // request arrives.
TEST_F(HttpCacheTest,NoStoreResponseShouldNotBlockFollowingRequests)13023 TEST_F(HttpCacheTest, NoStoreResponseShouldNotBlockFollowingRequests) {
13024 MockHttpCache cache;
13025 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
13026 mock_transaction.response_headers = "Cache-Control: no-store\n";
13027 MockHttpRequest request(mock_transaction);
13028
13029 auto first = std::make_unique<Context>();
13030 first->result = cache.CreateTransaction(&first->trans);
13031 ASSERT_THAT(first->result, IsOk());
13032 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
13033 first->result = first->trans->Start(&request, first->callback.callback(),
13034 NetLogWithSource());
13035 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, first->trans->GetLoadState());
13036
13037 base::RunLoop().RunUntilIdle();
13038 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
13039 ASSERT_TRUE(first->trans->GetResponseInfo());
13040 EXPECT_TRUE(first->trans->GetResponseInfo()->headers->HasHeaderValue(
13041 "Cache-Control", "no-store"));
13042 // Here we have read the response header but not read the response body yet.
13043
13044 // Let us create the second (read) transaction.
13045 auto second = std::make_unique<Context>();
13046 second->result = cache.CreateTransaction(&second->trans);
13047 ASSERT_THAT(second->result, IsOk());
13048 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
13049 second->result = second->trans->Start(&request, second->callback.callback(),
13050 NetLogWithSource());
13051
13052 // Here the second transaction proceeds without reading the first body.
13053 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, second->trans->GetLoadState());
13054 base::RunLoop().RunUntilIdle();
13055 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
13056 ASSERT_TRUE(second->trans->GetResponseInfo());
13057 EXPECT_TRUE(second->trans->GetResponseInfo()->headers->HasHeaderValue(
13058 "Cache-Control", "no-store"));
13059 ReadAndVerifyTransaction(second->trans.get(), kSimpleGET_Transaction);
13060 }
13061
13062 // Tests that serving a response entirely from cache replays the previous
13063 // SSLInfo.
TEST_F(HttpCacheTest,CachePreservesSSLInfo)13064 TEST_F(HttpCacheTest, CachePreservesSSLInfo) {
13065 static const uint16_t kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f;
13066 int status = 0;
13067 SSLConnectionStatusSetCipherSuite(kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
13068 &status);
13069 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2, &status);
13070
13071 scoped_refptr<X509Certificate> cert =
13072 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13073
13074 MockHttpCache cache;
13075
13076 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13077 transaction.cert = cert;
13078 transaction.ssl_connection_status = status;
13079
13080 // Fetch the resource.
13081 HttpResponseInfo response_info;
13082 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13083 &response_info);
13084
13085 // The request should have hit the network and a cache entry created.
13086 EXPECT_EQ(1, cache.network_layer()->transaction_count());
13087 EXPECT_EQ(0, cache.disk_cache()->open_count());
13088 EXPECT_EQ(1, cache.disk_cache()->create_count());
13089
13090 // The expected SSL state was reported.
13091 EXPECT_EQ(transaction.ssl_connection_status,
13092 response_info.ssl_info.connection_status);
13093 EXPECT_TRUE(cert->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13094
13095 // Fetch the resource again.
13096 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13097 &response_info);
13098
13099 // The request should have been reused without hitting the network.
13100 EXPECT_EQ(1, cache.network_layer()->transaction_count());
13101 EXPECT_EQ(1, cache.disk_cache()->open_count());
13102 EXPECT_EQ(1, cache.disk_cache()->create_count());
13103
13104 // The SSL state was preserved.
13105 EXPECT_EQ(status, response_info.ssl_info.connection_status);
13106 EXPECT_TRUE(cert->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13107 }
13108
13109 // Tests that SSLInfo gets updated when revalidating a cached response.
TEST_F(HttpCacheTest,RevalidationUpdatesSSLInfo)13110 TEST_F(HttpCacheTest, RevalidationUpdatesSSLInfo) {
13111 static const uint16_t kTLS_RSA_WITH_RC4_128_MD5 = 0x0004;
13112 static const uint16_t kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f;
13113
13114 int status1 = 0;
13115 SSLConnectionStatusSetCipherSuite(kTLS_RSA_WITH_RC4_128_MD5, &status1);
13116 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1, &status1);
13117 int status2 = 0;
13118 SSLConnectionStatusSetCipherSuite(kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
13119 &status2);
13120 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2, &status2);
13121
13122 scoped_refptr<X509Certificate> cert1 =
13123 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
13124 scoped_refptr<X509Certificate> cert2 =
13125 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13126
13127 MockHttpCache cache;
13128
13129 ScopedMockTransaction transaction(kTypicalGET_Transaction);
13130 transaction.cert = cert1;
13131 transaction.ssl_connection_status = status1;
13132
13133 // Fetch the resource.
13134 HttpResponseInfo response_info;
13135 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13136 &response_info);
13137
13138 // The request should have hit the network and a cache entry created.
13139 EXPECT_EQ(1, cache.network_layer()->transaction_count());
13140 EXPECT_EQ(0, cache.disk_cache()->open_count());
13141 EXPECT_EQ(1, cache.disk_cache()->create_count());
13142 EXPECT_FALSE(response_info.was_cached);
13143
13144 // The expected SSL state was reported.
13145 EXPECT_EQ(status1, response_info.ssl_info.connection_status);
13146 EXPECT_TRUE(cert1->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13147
13148 // The server deploys a more modern configuration but reports 304 on the
13149 // revalidation attempt.
13150 transaction.status = "HTTP/1.1 304 Not Modified";
13151 transaction.cert = cert2;
13152 transaction.ssl_connection_status = status2;
13153
13154 // Fetch the resource again, forcing a revalidation.
13155 transaction.request_headers = "Cache-Control: max-age=0\r\n";
13156 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13157 &response_info);
13158
13159 // The request should have been successfully revalidated.
13160 EXPECT_EQ(2, cache.network_layer()->transaction_count());
13161 EXPECT_EQ(1, cache.disk_cache()->open_count());
13162 EXPECT_EQ(1, cache.disk_cache()->create_count());
13163 EXPECT_TRUE(response_info.was_cached);
13164
13165 // The new SSL state is reported.
13166 EXPECT_EQ(status2, response_info.ssl_info.connection_status);
13167 EXPECT_TRUE(cert2->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13168 }
13169
TEST_F(HttpCacheTest,CacheEntryStatusOther)13170 TEST_F(HttpCacheTest, CacheEntryStatusOther) {
13171 MockHttpCache cache;
13172
13173 HttpResponseInfo response_info;
13174 RunTransactionTestWithResponseInfo(cache.http_cache(), kRangeGET_Transaction,
13175 &response_info);
13176
13177 EXPECT_FALSE(response_info.was_cached);
13178 EXPECT_TRUE(response_info.network_accessed);
13179 EXPECT_EQ(CacheEntryStatus::ENTRY_OTHER, response_info.cache_entry_status);
13180 }
13181
TEST_F(HttpCacheTest,CacheEntryStatusNotInCache)13182 TEST_F(HttpCacheTest, CacheEntryStatusNotInCache) {
13183 MockHttpCache cache;
13184
13185 HttpResponseInfo response_info;
13186 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
13187 &response_info);
13188
13189 EXPECT_FALSE(response_info.was_cached);
13190 EXPECT_TRUE(response_info.network_accessed);
13191 EXPECT_EQ(CacheEntryStatus::ENTRY_NOT_IN_CACHE,
13192 response_info.cache_entry_status);
13193 }
13194
TEST_F(HttpCacheTest,CacheEntryStatusUsed)13195 TEST_F(HttpCacheTest, CacheEntryStatusUsed) {
13196 MockHttpCache cache;
13197 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
13198
13199 HttpResponseInfo response_info;
13200 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
13201 &response_info);
13202
13203 EXPECT_TRUE(response_info.was_cached);
13204 EXPECT_FALSE(response_info.network_accessed);
13205 EXPECT_EQ(CacheEntryStatus::ENTRY_USED, response_info.cache_entry_status);
13206 }
13207
TEST_F(HttpCacheTest,CacheEntryStatusValidated)13208 TEST_F(HttpCacheTest, CacheEntryStatusValidated) {
13209 MockHttpCache cache;
13210 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
13211
13212 ScopedMockTransaction still_valid(kETagGET_Transaction);
13213 still_valid.load_flags = LOAD_VALIDATE_CACHE; // Force a validation.
13214 still_valid.handler = kETagGetConditionalRequestHandler;
13215
13216 HttpResponseInfo response_info;
13217 RunTransactionTestWithResponseInfo(cache.http_cache(), still_valid,
13218 &response_info);
13219
13220 EXPECT_TRUE(response_info.was_cached);
13221 EXPECT_TRUE(response_info.network_accessed);
13222 EXPECT_EQ(CacheEntryStatus::ENTRY_VALIDATED,
13223 response_info.cache_entry_status);
13224 }
13225
TEST_F(HttpCacheTest,CacheEntryStatusUpdated)13226 TEST_F(HttpCacheTest, CacheEntryStatusUpdated) {
13227 MockHttpCache cache;
13228 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
13229
13230 ScopedMockTransaction update(kETagGET_Transaction);
13231 update.load_flags = LOAD_VALIDATE_CACHE; // Force a validation.
13232
13233 HttpResponseInfo response_info;
13234 RunTransactionTestWithResponseInfo(cache.http_cache(), update,
13235 &response_info);
13236
13237 EXPECT_FALSE(response_info.was_cached);
13238 EXPECT_TRUE(response_info.network_accessed);
13239 EXPECT_EQ(CacheEntryStatus::ENTRY_UPDATED, response_info.cache_entry_status);
13240 }
13241
TEST_F(HttpCacheTest,CacheEntryStatusCantConditionalize)13242 TEST_F(HttpCacheTest, CacheEntryStatusCantConditionalize) {
13243 MockHttpCache cache;
13244 cache.FailConditionalizations();
13245 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
13246
13247 HttpResponseInfo response_info;
13248 RunTransactionTestWithResponseInfo(cache.http_cache(),
13249 kTypicalGET_Transaction, &response_info);
13250
13251 EXPECT_FALSE(response_info.was_cached);
13252 EXPECT_TRUE(response_info.network_accessed);
13253 EXPECT_EQ(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE,
13254 response_info.cache_entry_status);
13255 }
13256
TEST_F(HttpSplitCacheKeyTest,GetResourceURLFromHttpCacheKey)13257 TEST_F(HttpSplitCacheKeyTest, GetResourceURLFromHttpCacheKey) {
13258 base::test::ScopedFeatureList feature_list;
13259 feature_list.InitAndEnableFeature(
13260 net::features::kSplitCacheByNetworkIsolationKey);
13261 MockHttpCache cache;
13262 std::string urls[] = {"http://www.a.com/", "https://b.com/example.html",
13263 "http://example.com/Some Path/Some Leaf?some query"};
13264
13265 for (const std::string& url : urls) {
13266 std::string key = ComputeCacheKey(url);
13267 EXPECT_EQ(GURL(url).spec(), HttpCache::GetResourceURLFromHttpCacheKey(key));
13268 }
13269 }
13270
TEST_F(HttpCacheTest,GetResourceURLFromHttpCacheKey)13271 TEST_F(HttpCacheTest, GetResourceURLFromHttpCacheKey) {
13272 const struct {
13273 std::string input;
13274 std::string output;
13275 } kTestCase[] = {
13276 // Valid input:
13277 {"0/0/https://a.com/", "https://a.com/"},
13278 {"0/0/https://a.com/path", "https://a.com/path"},
13279 {"0/0/https://a.com/?query", "https://a.com/?query"},
13280 {"0/0/https://a.com/#fragment", "https://a.com/#fragment"},
13281 {"0/0/_dk_s_ https://a.com/", "https://a.com/"},
13282 {"0/0/_dk_https://a.com https://b.com https://c.com/", "https://c.com/"},
13283 {"0/0/_dk_shttps://a.com https://b.com https://c.com/", "https://c.com/"},
13284
13285 // Invalid input, producing garbage, without crashing.
13286 {"", ""},
13287 {"0/a.com", "0/a.com"},
13288 {"https://a.com/", "a.com/"},
13289 {"0/https://a.com/", "/a.com/"},
13290 };
13291
13292 for (const auto& test : kTestCase) {
13293 EXPECT_EQ(test.output,
13294 HttpCache::GetResourceURLFromHttpCacheKey(test.input));
13295 }
13296 }
13297
13298 class TestCompletionCallbackForHttpCache : public TestCompletionCallbackBase {
13299 public:
13300 TestCompletionCallbackForHttpCache() = default;
13301 ~TestCompletionCallbackForHttpCache() override = default;
13302
callback()13303 CompletionRepeatingCallback callback() {
13304 return base::BindRepeating(&TestCompletionCallbackForHttpCache::SetResult,
13305 base::Unretained(this));
13306 }
13307
results()13308 const std::vector<int>& results() { return results_; }
13309
13310 private:
13311 std::vector<int> results_;
13312
13313 protected:
SetResult(int result)13314 void SetResult(int result) override {
13315 results_.push_back(result);
13316 DidSetResult();
13317 }
13318 };
13319
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByOpen)13320 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByOpen) {
13321 MockHttpCache cache;
13322 TestCompletionCallbackForHttpCache cb;
13323 std::unique_ptr<Transaction> transaction =
13324 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13325
13326 transaction->SetIOCallBackForTest(cb.callback());
13327 transaction->SetCacheIOCallBackForTest(cb.callback());
13328
13329 // Create the backend here as our direct calls to DoomEntry and OpenEntry
13330 // below require that it exists.
13331 cache.backend();
13332
13333 // Need a mock transaction in order to use some of MockHttpCache's
13334 // functions.
13335 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13336
13337 ActiveEntry* entry1 = nullptr;
13338
13339 cache.disk_cache()->set_force_fail_callback_later(true);
13340
13341 // Queue up our operations.
13342 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13343 ASSERT_EQ(rv, ERR_IO_PENDING);
13344 cache.disk_cache()->set_force_fail_callback_later(false);
13345 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13346 transaction.get());
13347 ASSERT_EQ(rv, ERR_IO_PENDING);
13348
13349 // Wait for all the results to arrive.
13350 cb.GetResult(rv);
13351 ASSERT_EQ(cb.results().size(), 2u);
13352
13353 // Verify that DoomEntry failed correctly.
13354 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13355 // Verify that OpenEntry fails with the same code.
13356 ASSERT_EQ(cb.results()[1], ERR_CACHE_DOOM_FAILURE);
13357 ASSERT_EQ(entry1, nullptr);
13358 }
13359
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByCreate)13360 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByCreate) {
13361 MockHttpCache cache;
13362 TestCompletionCallbackForHttpCache cb;
13363 std::unique_ptr<Transaction> transaction =
13364 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13365
13366 transaction->SetIOCallBackForTest(cb.callback());
13367 transaction->SetCacheIOCallBackForTest(cb.callback());
13368
13369 // Create the backend here as our direct calls to DoomEntry and CreateEntry
13370 // below require that it exists.
13371 cache.backend();
13372
13373 // Need a mock transaction in order to use some of MockHttpCache's
13374 // functions.
13375 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13376
13377 ActiveEntry* entry1 = nullptr;
13378
13379 cache.disk_cache()->set_force_fail_callback_later(true);
13380
13381 // Queue up our operations.
13382 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13383 ASSERT_EQ(rv, ERR_IO_PENDING);
13384 cache.disk_cache()->set_force_fail_callback_later(false);
13385 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13386 transaction.get());
13387 ASSERT_EQ(rv, ERR_IO_PENDING);
13388
13389 // Wait for all the results to arrive.
13390 cb.GetResult(rv);
13391 ASSERT_EQ(cb.results().size(), 2u);
13392
13393 // Verify that DoomEntry failed correctly.
13394 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13395 // Verify that CreateEntry requests a restart (CACHE_RACE).
13396 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13397 ASSERT_EQ(entry1, nullptr);
13398 }
13399
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByDoom)13400 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByDoom) {
13401 MockHttpCache cache;
13402 TestCompletionCallbackForHttpCache cb;
13403 std::unique_ptr<Transaction> transaction =
13404 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13405
13406 transaction->SetIOCallBackForTest(cb.callback());
13407 transaction->SetCacheIOCallBackForTest(cb.callback());
13408
13409 // Create the backend here as our direct calls to DoomEntry below require that
13410 // it exists.
13411 cache.backend();
13412
13413 // Need a mock transaction in order to use some of MockHttpCache's
13414 // functions.
13415 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13416
13417 cache.disk_cache()->set_force_fail_callback_later(true);
13418
13419 // Queue up our operations.
13420 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13421 ASSERT_EQ(rv, ERR_IO_PENDING);
13422 cache.disk_cache()->set_force_fail_callback_later(false);
13423 rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13424 ASSERT_EQ(rv, ERR_IO_PENDING);
13425
13426 // Wait for all the results to arrive.
13427 cb.GetResult(rv);
13428 ASSERT_EQ(cb.results().size(), 2u);
13429
13430 // Verify that DoomEntry failed correctly.
13431 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13432 // Verify that the second DoomEntry requests a restart (CACHE_RACE).
13433 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13434 }
13435
TEST_F(HttpCacheIOCallbackTest,FailedOpenFollowedByCreate)13436 TEST_F(HttpCacheIOCallbackTest, FailedOpenFollowedByCreate) {
13437 MockHttpCache cache;
13438 TestCompletionCallbackForHttpCache cb;
13439 std::unique_ptr<Transaction> transaction =
13440 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13441
13442 transaction->SetIOCallBackForTest(cb.callback());
13443 transaction->SetCacheIOCallBackForTest(cb.callback());
13444
13445 // Create the backend here as our direct calls to OpenEntry and CreateEntry
13446 // below require that it exists.
13447 cache.backend();
13448
13449 // Need a mock transaction in order to use some of MockHttpCache's
13450 // functions.
13451 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13452
13453 ActiveEntry* entry1 = nullptr;
13454 ActiveEntry* entry2 = nullptr;
13455
13456 cache.disk_cache()->set_force_fail_callback_later(true);
13457
13458 // Queue up our operations.
13459 int rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13460 transaction.get());
13461 ASSERT_EQ(rv, ERR_IO_PENDING);
13462 cache.disk_cache()->set_force_fail_callback_later(false);
13463 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13464 transaction.get());
13465 ASSERT_EQ(rv, ERR_IO_PENDING);
13466
13467 // Wait for all the results to arrive.
13468 cb.GetResult(rv);
13469 ASSERT_EQ(cb.results().size(), 2u);
13470
13471 // Verify that OpenEntry failed correctly.
13472 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_FAILURE);
13473 ASSERT_EQ(entry1, nullptr);
13474 // Verify that the CreateEntry requests a restart (CACHE_RACE).
13475 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13476 ASSERT_EQ(entry2, nullptr);
13477 }
13478
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByOpen)13479 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByOpen) {
13480 MockHttpCache cache;
13481 TestCompletionCallbackForHttpCache cb;
13482 std::unique_ptr<Transaction> transaction =
13483 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13484
13485 transaction->SetIOCallBackForTest(cb.callback());
13486 transaction->SetCacheIOCallBackForTest(cb.callback());
13487
13488 // Create the backend here as our direct calls to CreateEntry and OpenEntry
13489 // below require that it exists.
13490 cache.backend();
13491
13492 // Need a mock transaction in order to use some of MockHttpCache's
13493 // functions.
13494 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13495
13496 ActiveEntry* entry1 = nullptr;
13497 ActiveEntry* entry2 = nullptr;
13498
13499 cache.disk_cache()->set_force_fail_callback_later(true);
13500
13501 // Queue up our operations.
13502 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13503 transaction.get());
13504 ASSERT_EQ(rv, ERR_IO_PENDING);
13505 cache.disk_cache()->set_force_fail_callback_later(false);
13506 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry2,
13507 transaction.get());
13508 ASSERT_EQ(rv, ERR_IO_PENDING);
13509
13510 // Wait for all the results to arrive.
13511 cb.GetResult(rv);
13512 ASSERT_EQ(cb.results().size(), 2u);
13513
13514 // Verify that CreateEntry failed correctly.
13515 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13516 ASSERT_EQ(entry1, nullptr);
13517 // Verify that the OpenEntry requests a restart (CACHE_RACE).
13518 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13519 ASSERT_EQ(entry2, nullptr);
13520 }
13521
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByCreate)13522 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByCreate) {
13523 MockHttpCache cache;
13524 TestCompletionCallbackForHttpCache cb;
13525 std::unique_ptr<Transaction> transaction =
13526 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13527
13528 transaction->SetIOCallBackForTest(cb.callback());
13529 transaction->SetCacheIOCallBackForTest(cb.callback());
13530
13531 // Create the backend here as our direct calls to CreateEntry below require
13532 // that it exists.
13533 cache.backend();
13534
13535 // Need a mock transaction in order to use some of MockHttpCache's
13536 // functions.
13537 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13538
13539 ActiveEntry* entry1 = nullptr;
13540 ActiveEntry* entry2 = nullptr;
13541
13542 cache.disk_cache()->set_force_fail_callback_later(true);
13543
13544 // Queue up our operations.
13545 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13546 transaction.get());
13547 ASSERT_EQ(rv, ERR_IO_PENDING);
13548 cache.disk_cache()->set_force_fail_callback_later(false);
13549 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13550 transaction.get());
13551 ASSERT_EQ(rv, ERR_IO_PENDING);
13552
13553 // Wait for all the results to arrive.
13554 cb.GetResult(rv);
13555 ASSERT_EQ(cb.results().size(), 2u);
13556
13557 // Verify the CreateEntry(s) failed.
13558 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13559 ASSERT_EQ(entry1, nullptr);
13560 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13561 ASSERT_EQ(entry2, nullptr);
13562 }
13563
TEST_F(HttpCacheIOCallbackTest,CreateFollowedByCreate)13564 TEST_F(HttpCacheIOCallbackTest, CreateFollowedByCreate) {
13565 MockHttpCache cache;
13566 TestCompletionCallbackForHttpCache cb;
13567 std::unique_ptr<Transaction> transaction =
13568 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13569
13570 transaction->SetIOCallBackForTest(cb.callback());
13571 transaction->SetCacheIOCallBackForTest(cb.callback());
13572
13573 // Create the backend here as our direct calls to CreateEntry below require
13574 // that it exists.
13575 cache.backend();
13576
13577 // Need a mock transaction in order to use some of MockHttpCache's
13578 // functions.
13579 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13580
13581 ActiveEntry* entry1 = nullptr;
13582 ActiveEntry* entry2 = nullptr;
13583
13584 // Queue up our operations.
13585 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13586 transaction.get());
13587 ASSERT_EQ(rv, ERR_IO_PENDING);
13588 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13589 transaction.get());
13590 ASSERT_EQ(rv, ERR_IO_PENDING);
13591
13592 // Wait for all the results to arrive.
13593 cb.GetResult(rv);
13594 ASSERT_EQ(cb.results().size(), 2u);
13595
13596 // Verify that the first CreateEntry succeeded.
13597 ASSERT_EQ(cb.results()[0], OK);
13598 ASSERT_NE(entry1, nullptr);
13599 // Verify that the second CreateEntry failed.
13600 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13601 ASSERT_EQ(entry2, nullptr);
13602 }
13603
TEST_F(HttpCacheIOCallbackTest,OperationFollowedByDoom)13604 TEST_F(HttpCacheIOCallbackTest, OperationFollowedByDoom) {
13605 MockHttpCache cache;
13606 TestCompletionCallbackForHttpCache cb;
13607 std::unique_ptr<Transaction> transaction =
13608 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13609
13610 transaction->SetIOCallBackForTest(cb.callback());
13611 transaction->SetCacheIOCallBackForTest(cb.callback());
13612
13613 // Create the backend here as our direct calls to CreateEntry and DoomEntry
13614 // below require that it exists.
13615 cache.backend();
13616
13617 // Need a mock transaction in order to use some of MockHttpCache's
13618 // functions.
13619 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13620
13621 ActiveEntry* entry1 = nullptr;
13622
13623 // Queue up our operations.
13624 // For this test all we need is some operation followed by a doom, a create
13625 // fulfills that requirement.
13626 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13627 transaction.get());
13628 ASSERT_EQ(rv, ERR_IO_PENDING);
13629 rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13630 ASSERT_EQ(rv, ERR_IO_PENDING);
13631
13632 // Wait for all the results to arrive.
13633 cb.GetResult(rv);
13634 ASSERT_EQ(cb.results().size(), 2u);
13635
13636 // Verify that the CreateEntry succeeded.
13637 ASSERT_EQ(cb.results()[0], OK);
13638 // Verify that the DoomEntry requests a restart (CACHE_RACE).
13639 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13640 }
13641
TEST_F(HttpCacheIOCallbackTest,CreateFollowedByOpenOrCreate)13642 TEST_F(HttpCacheIOCallbackTest, CreateFollowedByOpenOrCreate) {
13643 MockHttpCache cache;
13644 TestCompletionCallbackForHttpCache cb;
13645 std::unique_ptr<Transaction> transaction =
13646 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13647
13648 transaction->SetIOCallBackForTest(cb.callback());
13649 transaction->SetCacheIOCallBackForTest(cb.callback());
13650
13651 // Create the backend here as our direct calls to CreateEntry and
13652 // OpenOrCreateEntry below require that it exists.
13653 cache.backend();
13654
13655 // Need a mock transaction in order to use some of MockHttpCache's
13656 // functions.
13657 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13658
13659 ActiveEntry* entry1 = nullptr;
13660 ActiveEntry* entry2 = nullptr;
13661
13662 // Queue up our operations.
13663 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13664 transaction.get());
13665 ASSERT_EQ(rv, ERR_IO_PENDING);
13666 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13667 transaction.get());
13668 ASSERT_EQ(rv, ERR_IO_PENDING);
13669
13670 // Wait for all the results to arrive.
13671 cb.GetResult(rv);
13672 ASSERT_EQ(cb.results().size(), 2u);
13673
13674 // Verify that the CreateEntry succeeded.
13675 ASSERT_EQ(cb.results()[0], OK);
13676 ASSERT_NE(entry1, nullptr);
13677 // Verify that OpenOrCreateEntry succeeded.
13678 ASSERT_EQ(cb.results()[1], OK);
13679 ASSERT_NE(entry2, nullptr);
13680 ASSERT_EQ(entry1->disk_entry, entry2->disk_entry);
13681 }
13682
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByOpenOrCreate)13683 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByOpenOrCreate) {
13684 MockHttpCache cache;
13685 TestCompletionCallbackForHttpCache cb;
13686 std::unique_ptr<Transaction> transaction =
13687 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13688
13689 transaction->SetIOCallBackForTest(cb.callback());
13690 transaction->SetCacheIOCallBackForTest(cb.callback());
13691
13692 // Create the backend here as our direct calls to CreateEntry and
13693 // OpenOrCreateEntry below require that it exists.
13694 cache.backend();
13695
13696 // Need a mock transaction in order to use some of MockHttpCache's
13697 // functions.
13698 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13699
13700 ActiveEntry* entry1 = nullptr;
13701 ActiveEntry* entry2 = nullptr;
13702
13703 cache.disk_cache()->set_force_fail_callback_later(true);
13704
13705 // Queue up our operations.
13706 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13707 transaction.get());
13708 ASSERT_EQ(rv, ERR_IO_PENDING);
13709 cache.disk_cache()->set_force_fail_callback_later(false);
13710 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13711 transaction.get());
13712 ASSERT_EQ(rv, ERR_IO_PENDING);
13713
13714 // Wait for all the results to arrive.
13715 cb.GetResult(rv);
13716 ASSERT_EQ(cb.results().size(), 2u);
13717
13718 // Verify that CreateEntry failed correctly.
13719 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13720 ASSERT_EQ(entry1, nullptr);
13721 // Verify that the OpenOrCreateEntry requests a restart (CACHE_RACE).
13722 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13723 ASSERT_EQ(entry2, nullptr);
13724 }
13725
TEST_F(HttpCacheIOCallbackTest,OpenFollowedByOpenOrCreate)13726 TEST_F(HttpCacheIOCallbackTest, OpenFollowedByOpenOrCreate) {
13727 MockHttpCache cache;
13728 TestCompletionCallbackForHttpCache cb;
13729 std::unique_ptr<Transaction> transaction =
13730 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13731
13732 transaction->SetIOCallBackForTest(cb.callback());
13733 transaction->SetCacheIOCallBackForTest(cb.callback());
13734
13735 // Create the backend here as our direct calls to OpenEntry and
13736 // OpenOrCreateEntry below require that it exists.
13737 cache.backend();
13738
13739 // Need a mock transaction in order to use some of MockHttpCache's
13740 // functions.
13741 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13742
13743 ActiveEntry* entry0 = nullptr;
13744 ActiveEntry* entry1 = nullptr;
13745 ActiveEntry* entry2 = nullptr;
13746
13747 // First need to create and entry so we can open it.
13748 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry0,
13749 transaction.get());
13750 ASSERT_EQ(rv, ERR_IO_PENDING);
13751 cb.GetResult(rv);
13752 ASSERT_EQ(cb.results().size(), static_cast<size_t>(1));
13753 ASSERT_EQ(cb.results()[0], OK);
13754 ASSERT_NE(entry0, nullptr);
13755 // Manually DeactivateEntry() because OpenEntry() fails if there is an
13756 // existing active entry.
13757 DeactivateEntry(cache.http_cache(), entry0);
13758
13759 // Queue up our operations.
13760 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13761 transaction.get());
13762 ASSERT_EQ(rv, ERR_IO_PENDING);
13763 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13764 transaction.get());
13765 ASSERT_EQ(rv, ERR_IO_PENDING);
13766
13767 // Wait for all the results to arrive.
13768 cb.GetResult(rv);
13769 ASSERT_EQ(cb.results().size(), 3u);
13770
13771 // Verify that the OpenEntry succeeded.
13772 ASSERT_EQ(cb.results()[1], OK);
13773 ASSERT_NE(entry1, nullptr);
13774 // Verify that OpenOrCreateEntry succeeded.
13775 ASSERT_EQ(cb.results()[2], OK);
13776 ASSERT_NE(entry2, nullptr);
13777 ASSERT_EQ(entry1->disk_entry, entry2->disk_entry);
13778 }
13779
TEST_F(HttpCacheIOCallbackTest,FailedOpenFollowedByOpenOrCreate)13780 TEST_F(HttpCacheIOCallbackTest, FailedOpenFollowedByOpenOrCreate) {
13781 MockHttpCache cache;
13782 TestCompletionCallbackForHttpCache cb;
13783 std::unique_ptr<Transaction> transaction =
13784 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13785
13786 transaction->SetIOCallBackForTest(cb.callback());
13787 transaction->SetCacheIOCallBackForTest(cb.callback());
13788
13789 // Create the backend here as our direct calls to OpenEntry and
13790 // OpenOrCreateEntry below require that it exists.
13791 cache.backend();
13792
13793 // Need a mock transaction in order to use some of MockHttpCache's
13794 // functions.
13795 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13796
13797 ActiveEntry* entry1 = nullptr;
13798 ActiveEntry* entry2 = nullptr;
13799
13800 cache.disk_cache()->set_force_fail_callback_later(true);
13801
13802 // Queue up our operations.
13803 int rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13804 transaction.get());
13805 ASSERT_EQ(rv, ERR_IO_PENDING);
13806 cache.disk_cache()->set_force_fail_callback_later(false);
13807 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13808 transaction.get());
13809 ASSERT_EQ(rv, ERR_IO_PENDING);
13810
13811 // Wait for all the results to arrive.
13812 cb.GetResult(rv);
13813 ASSERT_EQ(cb.results().size(), 2u);
13814
13815 // Verify that OpenEntry failed correctly.
13816 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_FAILURE);
13817 ASSERT_EQ(entry1, nullptr);
13818 // Verify that the OpenOrCreateEntry requests a restart (CACHE_RACE).
13819 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13820 ASSERT_EQ(entry2, nullptr);
13821 }
13822
TEST_F(HttpCacheIOCallbackTest,OpenOrCreateFollowedByCreate)13823 TEST_F(HttpCacheIOCallbackTest, OpenOrCreateFollowedByCreate) {
13824 MockHttpCache cache;
13825 TestCompletionCallbackForHttpCache cb;
13826 std::unique_ptr<Transaction> transaction =
13827 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13828
13829 transaction->SetIOCallBackForTest(cb.callback());
13830 transaction->SetCacheIOCallBackForTest(cb.callback());
13831
13832 // Create the backend here as our direct calls to OpenOrCreateEntry and
13833 // CreateEntry below require that it exists.
13834 cache.backend();
13835
13836 // Need a mock transaction in order to use some of MockHttpCache's
13837 // functions.
13838 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13839
13840 ActiveEntry* entry1 = nullptr;
13841 ActiveEntry* entry2 = nullptr;
13842
13843 // Queue up our operations.
13844 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13845 transaction.get());
13846 ASSERT_EQ(rv, ERR_IO_PENDING);
13847 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13848 transaction.get());
13849 ASSERT_EQ(rv, ERR_IO_PENDING);
13850
13851 // Wait for all the results to arrive.
13852 cb.GetResult(rv);
13853 ASSERT_EQ(cb.results().size(), 2u);
13854
13855 // Verify that the OpenOrCreateEntry succeeded.
13856 ASSERT_EQ(cb.results()[0], OK);
13857 ASSERT_NE(entry1, nullptr);
13858 // Verify that CreateEntry failed.
13859 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13860 ASSERT_EQ(entry2, nullptr);
13861 }
13862
TEST_F(HttpCacheIOCallbackTest,OpenOrCreateFollowedByOpenOrCreate)13863 TEST_F(HttpCacheIOCallbackTest, OpenOrCreateFollowedByOpenOrCreate) {
13864 MockHttpCache cache;
13865 TestCompletionCallbackForHttpCache cb;
13866 std::unique_ptr<Transaction> transaction =
13867 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13868
13869 transaction->SetIOCallBackForTest(cb.callback());
13870 transaction->SetCacheIOCallBackForTest(cb.callback());
13871
13872 // Create the backend here as our direct calls to OpenOrCreateEntry below
13873 // require that it exists.
13874 cache.backend();
13875
13876 // Need a mock transaction in order to use some of MockHttpCache's
13877 // functions.
13878 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13879
13880 ActiveEntry* entry1 = nullptr;
13881 ActiveEntry* entry2 = nullptr;
13882
13883 // Queue up our operations.
13884 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13885 transaction.get());
13886 ASSERT_EQ(rv, ERR_IO_PENDING);
13887 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13888 transaction.get());
13889 ASSERT_EQ(rv, ERR_IO_PENDING);
13890
13891 // Wait for all the results to arrive.
13892 cb.GetResult(rv);
13893 ASSERT_EQ(cb.results().size(), 2u);
13894
13895 // Verify that the OpenOrCreateEntry succeeded.
13896 ASSERT_EQ(cb.results()[0], OK);
13897 ASSERT_NE(entry1, nullptr);
13898 // Verify that the other succeeded.
13899 ASSERT_EQ(cb.results()[1], OK);
13900 ASSERT_NE(entry2, nullptr);
13901 }
13902
TEST_F(HttpCacheIOCallbackTest,FailedOpenOrCreateFollowedByOpenOrCreate)13903 TEST_F(HttpCacheIOCallbackTest, FailedOpenOrCreateFollowedByOpenOrCreate) {
13904 MockHttpCache cache;
13905 TestCompletionCallbackForHttpCache cb;
13906 std::unique_ptr<Transaction> transaction =
13907 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13908
13909 transaction->SetIOCallBackForTest(cb.callback());
13910 transaction->SetCacheIOCallBackForTest(cb.callback());
13911
13912 // Create the backend here as our direct calls to OpenOrCreateEntry below
13913 // require that it exists.
13914 cache.backend();
13915
13916 // Need a mock transaction in order to use some of MockHttpCache's
13917 // functions.
13918 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13919
13920 ActiveEntry* entry1 = nullptr;
13921 ActiveEntry* entry2 = nullptr;
13922
13923 cache.disk_cache()->set_force_fail_callback_later(true);
13924
13925 // Queue up our operations.
13926 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13927 transaction.get());
13928 ASSERT_EQ(rv, ERR_IO_PENDING);
13929 cache.disk_cache()->set_force_fail_callback_later(false);
13930 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13931 transaction.get());
13932 ASSERT_EQ(rv, ERR_IO_PENDING);
13933
13934 // Wait for all the results to arrive.
13935 cb.GetResult(rv);
13936 ASSERT_EQ(cb.results().size(), 2u);
13937
13938 // Verify that the OpenOrCreateEntry failed.
13939 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_OR_CREATE_FAILURE);
13940 ASSERT_EQ(entry1, nullptr);
13941 // Verify that the other failed.
13942 ASSERT_EQ(cb.results()[1], ERR_CACHE_OPEN_OR_CREATE_FAILURE);
13943 ASSERT_EQ(entry2, nullptr);
13944 }
13945
TEST_F(HttpCacheTest,DnsAliasesNoRevalidation)13946 TEST_F(HttpCacheTest, DnsAliasesNoRevalidation) {
13947 MockHttpCache cache;
13948 HttpResponseInfo response;
13949 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13950 transaction.dns_aliases = {"alias1", "alias2"};
13951
13952 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13953 &response);
13954 EXPECT_FALSE(response.was_cached);
13955 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
13956
13957 // The second request result in a cache hit and the response used without
13958 // revalidation. Set the transaction alias list to empty to verify that the
13959 // cached aliases are being used.
13960 transaction.dns_aliases = {};
13961 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13962 &response);
13963 EXPECT_TRUE(response.was_cached);
13964 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
13965 }
13966
TEST_F(HttpCacheTest,NoDnsAliasesNoRevalidation)13967 TEST_F(HttpCacheTest, NoDnsAliasesNoRevalidation) {
13968 MockHttpCache cache;
13969 HttpResponseInfo response;
13970 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13971 transaction.dns_aliases = {};
13972
13973 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13974 &response);
13975 EXPECT_FALSE(response.was_cached);
13976 EXPECT_TRUE(response.dns_aliases.empty());
13977
13978 // The second request should result in a cache hit and the response used
13979 // without revalidation. Set the transaction alias list to nonempty to verify
13980 // that the cached aliases are being used.
13981 transaction.dns_aliases = {"alias"};
13982 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13983 &response);
13984 EXPECT_TRUE(response.was_cached);
13985 EXPECT_TRUE(response.dns_aliases.empty());
13986 }
13987
TEST_F(HttpCacheTest,DnsAliasesRevalidation)13988 TEST_F(HttpCacheTest, DnsAliasesRevalidation) {
13989 MockHttpCache cache;
13990 HttpResponseInfo response;
13991 ScopedMockTransaction transaction(kTypicalGET_Transaction);
13992 transaction.response_headers =
13993 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
13994 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
13995 "Cache-Control: max-age=0\n";
13996 transaction.dns_aliases = {"alias1", "alias2"};
13997
13998 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13999 &response);
14000 EXPECT_FALSE(response.was_cached);
14001 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
14002
14003 // On the second request, the cache should be revalidated. Change the aliases
14004 // to be sure that the new aliases are being used, and have the response be
14005 // cached for next time.
14006 transaction.response_headers = "Cache-Control: max-age=10000\n";
14007 transaction.dns_aliases = {"alias3", "alias4"};
14008 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14009 &response);
14010 EXPECT_FALSE(response.was_cached);
14011 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias3", "alias4"));
14012
14013 transaction.dns_aliases = {"alias5", "alias6"};
14014 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14015 &response);
14016 EXPECT_TRUE(response.was_cached);
14017 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias3", "alias4"));
14018 }
14019
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldBypass_NoId)14020 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldBypass_NoId) {
14021 MockHttpCache cache;
14022 HttpResponseInfo response;
14023 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14024
14025 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14026 &response);
14027 EXPECT_FALSE(response.was_cached);
14028
14029 transaction.fps_cache_filter = {5};
14030 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14031 &response);
14032 EXPECT_FALSE(response.was_cached);
14033 }
14034
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldBypass_IdTooSmall)14035 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldBypass_IdTooSmall) {
14036 MockHttpCache cache;
14037 HttpResponseInfo response;
14038 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14039 const int64_t kBrowserRunId = 4;
14040 transaction.browser_run_id = {kBrowserRunId};
14041 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14042 &response);
14043 EXPECT_FALSE(response.was_cached);
14044 EXPECT_TRUE(response.browser_run_id.has_value());
14045 EXPECT_EQ(kBrowserRunId, response.browser_run_id.value());
14046
14047 transaction.fps_cache_filter = {5};
14048 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14049 &response);
14050 EXPECT_FALSE(response.was_cached);
14051 }
14052
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldNotBypass)14053 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldNotBypass) {
14054 MockHttpCache cache;
14055 HttpResponseInfo response;
14056 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14057 const int64_t kBrowserRunId = 5;
14058 transaction.browser_run_id = {kBrowserRunId};
14059 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14060 &response);
14061 EXPECT_FALSE(response.was_cached);
14062 EXPECT_TRUE(response.browser_run_id.has_value());
14063 EXPECT_EQ(kBrowserRunId, response.browser_run_id.value());
14064
14065 transaction.fps_cache_filter = {5};
14066 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14067 &response);
14068 EXPECT_TRUE(response.was_cached);
14069 }
14070
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldNotBypass_NoFilter)14071 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldNotBypass_NoFilter) {
14072 MockHttpCache cache;
14073 HttpResponseInfo response;
14074 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14075
14076 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14077 &response);
14078 EXPECT_FALSE(response.was_cached);
14079
14080 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14081 &response);
14082 EXPECT_TRUE(response.was_cached);
14083 }
14084
TEST_F(HttpCacheTest,SecurityHeadersAreCopiedToConditionalizedResponse)14085 TEST_F(HttpCacheTest, SecurityHeadersAreCopiedToConditionalizedResponse) {
14086 MockHttpCache cache;
14087 HttpResponseInfo response;
14088 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14089
14090 static const Response kNetResponse1 = {
14091 "HTTP/1.1 200 OK",
14092 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
14093 "Server: server1\n"
14094 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n"
14095 "Cross-Origin-Resource-Policy: cross-origin\n",
14096 "body1"};
14097
14098 static const Response kNetResponse2 = {
14099 "HTTP/1.1 304 Not Modified",
14100 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
14101 "Server: server2\n"
14102 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
14103 ""};
14104
14105 kNetResponse1.AssignTo(&transaction);
14106 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14107 &response);
14108
14109 // On the second request, the cache is revalidated.
14110 const char kExtraRequestHeaders[] =
14111 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
14112 transaction.request_headers = kExtraRequestHeaders;
14113 kNetResponse2.AssignTo(&transaction);
14114 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14115 &response);
14116
14117 // Verify that the CORP header was carried over to the response.
14118 std::string response_corp_header;
14119 response.headers->GetNormalizedHeader("Cross-Origin-Resource-Policy",
14120 &response_corp_header);
14121
14122 EXPECT_EQ(304, response.headers->response_code());
14123 EXPECT_EQ("cross-origin", response_corp_header);
14124 }
14125
14126 } // namespace net
14127