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/metrics/histogram_tester.h"
28 #include "base/test/scoped_feature_list.h"
29 #include "base/test/simple_test_clock.h"
30 #include "base/time/time.h"
31 #include "base/trace_event/memory_dump_request_args.h"
32 #include "base/trace_event/process_memory_dump.h"
33 #include "net/base/cache_type.h"
34 #include "net/base/completion_repeating_callback.h"
35 #include "net/base/elements_upload_data_stream.h"
36 #include "net/base/features.h"
37 #include "net/base/host_port_pair.h"
38 #include "net/base/ip_address.h"
39 #include "net/base/ip_endpoint.h"
40 #include "net/base/load_flags.h"
41 #include "net/base/load_timing_info.h"
42 #include "net/base/load_timing_info_test_util.h"
43 #include "net/base/net_errors.h"
44 #include "net/base/schemeful_site.h"
45 #include "net/base/tracing.h"
46 #include "net/base/upload_bytes_element_reader.h"
47 #include "net/cert/cert_status_flags.h"
48 #include "net/cert/x509_certificate.h"
49 #include "net/disk_cache/disk_cache.h"
50 #include "net/http/http_byte_range.h"
51 #include "net/http/http_cache_transaction.h"
52 #include "net/http/http_request_headers.h"
53 #include "net/http/http_request_info.h"
54 #include "net/http/http_response_headers.h"
55 #include "net/http/http_response_info.h"
56 #include "net/http/http_transaction.h"
57 #include "net/http/http_transaction_test_util.h"
58 #include "net/http/http_util.h"
59 #include "net/http/mock_http_cache.h"
60 #include "net/log/net_log_event_type.h"
61 #include "net/log/net_log_source.h"
62 #include "net/log/net_log_with_source.h"
63 #include "net/log/test_net_log.h"
64 #include "net/log/test_net_log_util.h"
65 #include "net/socket/client_socket_handle.h"
66 #include "net/ssl/ssl_cert_request_info.h"
67 #include "net/ssl/ssl_connection_status_flags.h"
68 #include "net/test/cert_test_util.h"
69 #include "net/test/gtest_util.h"
70 #include "net/test/test_data_directory.h"
71 #include "net/test/test_with_task_environment.h"
72 #include "net/websockets/websocket_handshake_stream_base.h"
73 #include "testing/gmock/include/gmock/gmock.h"
74 #include "testing/gtest/include/gtest/gtest.h"
75 #include "third_party/abseil-cpp/absl/types/optional.h"
76 #include "url/origin.h"
77
78 using net::test::IsError;
79 using net::test::IsOk;
80 using testing::AllOf;
81 using testing::ByRef;
82 using testing::Contains;
83 using testing::ElementsAre;
84 using testing::Eq;
85 using testing::Field;
86 using testing::Gt;
87 using testing::IsEmpty;
88 using testing::NotNull;
89
90 using base::Time;
91
92 namespace net {
93
94 using CacheEntryStatus = HttpResponseInfo::CacheEntryStatus;
95
96 class WebSocketEndpointLockManager;
97
98 namespace {
99
100 // Returns a simple text serialization of the given
101 // |HttpResponseHeaders|. This is used by tests to verify that an
102 // |HttpResponseHeaders| matches an expectation string.
103 //
104 // * One line per header, written as:
105 // HEADER_NAME: HEADER_VALUE\n
106 // * The original case of header names is preserved.
107 // * Whitespace around head names/values is stripped.
108 // * Repeated headers are not aggregated.
109 // * Headers are listed in their original order.
110 // TODO(tfarina): this is a duplicate function from
111 // http_response_headers_unittest.cc:ToSimpleString(). Figure out how to merge
112 // them. crbug.com/488593
ToSimpleString(const scoped_refptr<HttpResponseHeaders> & parsed)113 std::string ToSimpleString(const scoped_refptr<HttpResponseHeaders>& parsed) {
114 std::string result = parsed->GetStatusLine() + "\n";
115
116 size_t iter = 0;
117 std::string name;
118 std::string value;
119 while (parsed->EnumerateHeaderLines(&iter, &name, &value)) {
120 std::string new_line = name + ": " + value + "\n";
121
122 result += new_line;
123 }
124
125 return result;
126 }
127
128 // Tests the load timing values of a request that goes through a
129 // MockNetworkTransaction.
TestLoadTimingNetworkRequest(const LoadTimingInfo & load_timing_info)130 void TestLoadTimingNetworkRequest(const LoadTimingInfo& load_timing_info) {
131 EXPECT_FALSE(load_timing_info.socket_reused);
132 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
133
134 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
135 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
136
137 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
138 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
139 EXPECT_LE(load_timing_info.connect_timing.connect_end,
140 load_timing_info.send_start);
141
142 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
143
144 // Set by URLRequest / URLRequestHttpJob, at a higher level.
145 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
146 EXPECT_TRUE(load_timing_info.request_start.is_null());
147 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
148 }
149
150 // Tests the load timing values of a request that receives a cached response.
TestLoadTimingCachedResponse(const LoadTimingInfo & load_timing_info)151 void TestLoadTimingCachedResponse(const LoadTimingInfo& load_timing_info) {
152 EXPECT_FALSE(load_timing_info.socket_reused);
153 EXPECT_EQ(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
154
155 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
156 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
157
158 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
159
160 // Only the send start / end times should be sent, and they should have the
161 // same value.
162 EXPECT_FALSE(load_timing_info.send_start.is_null());
163 EXPECT_EQ(load_timing_info.send_start, load_timing_info.send_end);
164
165 // Set by URLRequest / URLRequestHttpJob, at a higher level.
166 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
167 EXPECT_TRUE(load_timing_info.request_start.is_null());
168 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
169 }
170
DeferCallback(bool * defer)171 void DeferCallback(bool* defer) {
172 *defer = true;
173 }
174
175 class DeleteCacheCompletionCallback : public TestCompletionCallbackBase {
176 public:
DeleteCacheCompletionCallback(std::unique_ptr<MockHttpCache> cache)177 explicit DeleteCacheCompletionCallback(std::unique_ptr<MockHttpCache> cache)
178 : cache_(std::move(cache)) {}
179
180 DeleteCacheCompletionCallback(const DeleteCacheCompletionCallback&) = delete;
181 DeleteCacheCompletionCallback& operator=(
182 const DeleteCacheCompletionCallback&) = delete;
183
callback()184 CompletionOnceCallback callback() {
185 return base::BindOnce(&DeleteCacheCompletionCallback::OnComplete,
186 base::Unretained(this));
187 }
188
189 private:
OnComplete(int result)190 void OnComplete(int result) {
191 cache_.reset();
192 SetResult(result);
193 }
194
195 std::unique_ptr<MockHttpCache> cache_;
196 };
197
198 //-----------------------------------------------------------------------------
199 // helpers
200
ReadAndVerifyTransaction(HttpTransaction * trans,const MockTransaction & trans_info)201 void ReadAndVerifyTransaction(HttpTransaction* trans,
202 const MockTransaction& trans_info) {
203 std::string content;
204 int rv = ReadTransaction(trans, &content);
205
206 EXPECT_THAT(rv, IsOk());
207 std::string expected(trans_info.data);
208 EXPECT_EQ(expected, content);
209 }
210
ReadRemainingAndVerifyTransaction(HttpTransaction * trans,const std::string & already_read,const MockTransaction & trans_info)211 void ReadRemainingAndVerifyTransaction(HttpTransaction* trans,
212 const std::string& already_read,
213 const MockTransaction& trans_info) {
214 std::string content;
215 int rv = ReadTransaction(trans, &content);
216 EXPECT_THAT(rv, IsOk());
217
218 std::string expected(trans_info.data);
219 EXPECT_EQ(expected, already_read + content);
220 }
221
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)222 void RunTransactionTestBase(HttpCache* cache,
223 const MockTransaction& trans_info,
224 const MockHttpRequest& request,
225 HttpResponseInfo* response_info,
226 const NetLogWithSource& net_log,
227 LoadTimingInfo* load_timing_info,
228 int64_t* sent_bytes,
229 int64_t* received_bytes,
230 IPEndPoint* remote_endpoint) {
231 TestCompletionCallback callback;
232
233 // write to the cache
234
235 std::unique_ptr<HttpTransaction> trans;
236 int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &trans);
237 EXPECT_THAT(rv, IsOk());
238 ASSERT_TRUE(trans.get());
239
240 rv = trans->Start(&request, callback.callback(), net_log);
241 if (rv == ERR_IO_PENDING)
242 rv = callback.WaitForResult();
243 ASSERT_EQ(trans_info.start_return_code, rv);
244
245 if (OK != rv)
246 return;
247
248 const HttpResponseInfo* response = trans->GetResponseInfo();
249 ASSERT_TRUE(response);
250
251 if (response_info)
252 *response_info = *response;
253
254 if (load_timing_info) {
255 // If a fake network connection is used, need a NetLog to get a fake socket
256 // ID.
257 EXPECT_TRUE(net_log.net_log());
258 *load_timing_info = LoadTimingInfo();
259 trans->GetLoadTimingInfo(load_timing_info);
260 }
261
262 if (remote_endpoint)
263 ASSERT_TRUE(trans->GetRemoteEndpoint(remote_endpoint));
264
265 ReadAndVerifyTransaction(trans.get(), trans_info);
266
267 if (sent_bytes)
268 *sent_bytes = trans->GetTotalSentBytes();
269 if (received_bytes)
270 *received_bytes = trans->GetTotalReceivedBytes();
271 }
272
RunTransactionTestWithRequest(HttpCache * cache,const MockTransaction & trans_info,const MockHttpRequest & request,HttpResponseInfo * response_info)273 void RunTransactionTestWithRequest(HttpCache* cache,
274 const MockTransaction& trans_info,
275 const MockHttpRequest& request,
276 HttpResponseInfo* response_info) {
277 RunTransactionTestBase(cache, trans_info, request, response_info,
278 NetLogWithSource(), nullptr, nullptr, nullptr,
279 nullptr);
280 }
281
RunTransactionTestAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)282 void RunTransactionTestAndGetTiming(HttpCache* cache,
283 const MockTransaction& trans_info,
284 const NetLogWithSource& log,
285 LoadTimingInfo* load_timing_info) {
286 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
287 nullptr, log, load_timing_info, nullptr, nullptr,
288 nullptr);
289 }
290
RunTransactionTestAndGetTimingAndConnectedSocketAddress(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log,LoadTimingInfo * load_timing_info,IPEndPoint * remote_endpoint)291 void RunTransactionTestAndGetTimingAndConnectedSocketAddress(
292 HttpCache* cache,
293 const MockTransaction& trans_info,
294 const NetLogWithSource& log,
295 LoadTimingInfo* load_timing_info,
296 IPEndPoint* remote_endpoint) {
297 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
298 nullptr, log, load_timing_info, nullptr, nullptr,
299 remote_endpoint);
300 }
301
RunTransactionTest(HttpCache * cache,const MockTransaction & trans_info)302 void RunTransactionTest(HttpCache* cache, const MockTransaction& trans_info) {
303 RunTransactionTestAndGetTiming(cache, trans_info, NetLogWithSource(),
304 nullptr);
305 }
306
RunTransactionTestWithLog(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log)307 void RunTransactionTestWithLog(HttpCache* cache,
308 const MockTransaction& trans_info,
309 const NetLogWithSource& log) {
310 RunTransactionTestAndGetTiming(cache, trans_info, log, nullptr);
311 }
312
RunTransactionTestWithResponseInfo(HttpCache * cache,const MockTransaction & trans_info,HttpResponseInfo * response)313 void RunTransactionTestWithResponseInfo(HttpCache* cache,
314 const MockTransaction& trans_info,
315 HttpResponseInfo* response) {
316 RunTransactionTestWithRequest(cache, trans_info, MockHttpRequest(trans_info),
317 response);
318 }
319
RunTransactionTestWithResponseInfoAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,HttpResponseInfo * response,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)320 void RunTransactionTestWithResponseInfoAndGetTiming(
321 HttpCache* cache,
322 const MockTransaction& trans_info,
323 HttpResponseInfo* response,
324 const NetLogWithSource& log,
325 LoadTimingInfo* load_timing_info) {
326 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
327 response, log, load_timing_info, nullptr, nullptr,
328 nullptr);
329 }
330
RunTransactionTestWithResponse(HttpCache * cache,const MockTransaction & trans_info,std::string * response_headers)331 void RunTransactionTestWithResponse(HttpCache* cache,
332 const MockTransaction& trans_info,
333 std::string* response_headers) {
334 HttpResponseInfo response;
335 RunTransactionTestWithResponseInfo(cache, trans_info, &response);
336 *response_headers = ToSimpleString(response.headers);
337 }
338
RunTransactionTestWithResponseAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,std::string * response_headers,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)339 void RunTransactionTestWithResponseAndGetTiming(
340 HttpCache* cache,
341 const MockTransaction& trans_info,
342 std::string* response_headers,
343 const NetLogWithSource& log,
344 LoadTimingInfo* load_timing_info) {
345 HttpResponseInfo response;
346 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
347 &response, log, load_timing_info, nullptr, nullptr,
348 nullptr);
349 *response_headers = ToSimpleString(response.headers);
350 }
351
352 // This class provides a handler for kFastNoStoreGET_Transaction so that the
353 // no-store header can be included on demand.
354 class FastTransactionServer {
355 public:
FastTransactionServer()356 FastTransactionServer() {
357 no_store = false;
358 }
359
360 FastTransactionServer(const FastTransactionServer&) = delete;
361 FastTransactionServer& operator=(const FastTransactionServer&) = delete;
362
363 ~FastTransactionServer() = default;
364
set_no_store(bool value)365 void set_no_store(bool value) { no_store = value; }
366
FastNoStoreHandler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)367 static void FastNoStoreHandler(const HttpRequestInfo* request,
368 std::string* response_status,
369 std::string* response_headers,
370 std::string* response_data) {
371 if (no_store)
372 *response_headers = "Cache-Control: no-store\n";
373 }
374
375 private:
376 static bool no_store;
377 };
378 bool FastTransactionServer::no_store;
379
380 const MockTransaction kFastNoStoreGET_Transaction = {
381 "http://www.google.com/nostore",
382 "GET",
383 base::Time(),
384 "",
385 LOAD_VALIDATE_CACHE,
386 DefaultTransportInfo(),
387 "HTTP/1.1 200 OK",
388 "Cache-Control: max-age=10000\n",
389 base::Time(),
390 "<html><body>Google Blah Blah</body></html>",
391 {},
392 absl::nullopt,
393 absl::nullopt,
394 TEST_MODE_SYNC_NET_START,
395 &FastTransactionServer::FastNoStoreHandler,
396 nullptr,
397 nullptr,
398 0,
399 0,
400 OK,
401 };
402
403 // This class provides a handler for kRangeGET_TransactionOK so that the range
404 // request can be served on demand.
405 class RangeTransactionServer {
406 public:
RangeTransactionServer()407 RangeTransactionServer() {
408 not_modified_ = false;
409 modified_ = false;
410 bad_200_ = false;
411 redirect_ = false;
412 length_ = 80;
413 }
414
415 RangeTransactionServer(const RangeTransactionServer&) = delete;
416 RangeTransactionServer& operator=(const RangeTransactionServer&) = delete;
417
~RangeTransactionServer()418 ~RangeTransactionServer() {
419 not_modified_ = false;
420 modified_ = false;
421 bad_200_ = false;
422 redirect_ = false;
423 length_ = 80;
424 }
425
426 // Returns only 416 or 304 when set.
set_not_modified(bool value)427 void set_not_modified(bool value) { not_modified_ = value; }
428
429 // Returns 206 when revalidating a range (instead of 304).
set_modified(bool value)430 void set_modified(bool value) { modified_ = value; }
431
432 // Returns 200 instead of 206 (a malformed response overall).
set_bad_200(bool value)433 void set_bad_200(bool value) { bad_200_ = value; }
434
435 // Sets how long the resource is. (Default is 80)
set_length(int64_t length)436 void set_length(int64_t length) { length_ = length; }
437
438 // Sets whether to return a 301 instead of normal return.
set_redirect(bool redirect)439 void set_redirect(bool redirect) { redirect_ = redirect; }
440
441 // Other than regular range related behavior (and the flags mentioned above),
442 // the server reacts to requests headers like so:
443 // X-Require-Mock-Auth -> return 401.
444 // X-Require-Mock-Auth-Alt -> return 401.
445 // X-Return-Default-Range -> assume 40-49 was requested.
446 // The -Alt variant doesn't cause the MockNetworkTransaction to
447 // report that it IsReadyToRestartForAuth().
448 static void RangeHandler(const HttpRequestInfo* request,
449 std::string* response_status,
450 std::string* response_headers,
451 std::string* response_data);
452
453 private:
454 static bool not_modified_;
455 static bool modified_;
456 static bool bad_200_;
457 static bool redirect_;
458 static int64_t length_;
459 };
460 bool RangeTransactionServer::not_modified_ = false;
461 bool RangeTransactionServer::modified_ = false;
462 bool RangeTransactionServer::bad_200_ = false;
463 bool RangeTransactionServer::redirect_ = false;
464 int64_t RangeTransactionServer::length_ = 80;
465
466 // A dummy extra header that must be preserved on a given request.
467
468 // EXTRA_HEADER_LINE doesn't include a line terminator because it
469 // will be passed to AddHeaderFromString() which doesn't accept them.
470 #define EXTRA_HEADER_LINE "Extra: header"
471
472 // EXTRA_HEADER contains a line terminator, as expected by
473 // AddHeadersFromString() (_not_ AddHeaderFromString()).
474 #define EXTRA_HEADER EXTRA_HEADER_LINE "\r\n"
475
476 static const char kExtraHeaderKey[] = "Extra";
477
478 // Static.
RangeHandler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)479 void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request,
480 std::string* response_status,
481 std::string* response_headers,
482 std::string* response_data) {
483 if (request->extra_headers.IsEmpty()) {
484 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
485 response_data->clear();
486 return;
487 }
488
489 // We want to make sure we don't delete extra headers.
490 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
491
492 bool require_auth =
493 request->extra_headers.HasHeader("X-Require-Mock-Auth") ||
494 request->extra_headers.HasHeader("X-Require-Mock-Auth-Alt");
495
496 if (require_auth && !request->extra_headers.HasHeader("Authorization")) {
497 response_status->assign("HTTP/1.1 401 Unauthorized");
498 response_data->assign("WWW-Authenticate: Foo\n");
499 return;
500 }
501
502 if (redirect_) {
503 response_status->assign("HTTP/1.1 301 Moved Permanently");
504 response_headers->assign("Location: /elsewhere\nContent-Length: 5");
505 response_data->assign("12345");
506 return;
507 }
508
509 if (not_modified_) {
510 response_status->assign("HTTP/1.1 304 Not Modified");
511 response_data->clear();
512 return;
513 }
514
515 std::vector<HttpByteRange> ranges;
516 std::string range_header;
517 if (!request->extra_headers.GetHeader(HttpRequestHeaders::kRange,
518 &range_header) ||
519 !HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ ||
520 ranges.size() != 1 ||
521 (modified_ && request->extra_headers.HasHeader("If-Range"))) {
522 // This is not a byte range request, or a failed If-Range. We return 200.
523 response_status->assign("HTTP/1.1 200 OK");
524 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT");
525 response_data->assign("Not a range");
526 return;
527 }
528
529 // We can handle this range request.
530 HttpByteRange byte_range = ranges[0];
531
532 if (request->extra_headers.HasHeader("X-Return-Default-Range")) {
533 byte_range.set_first_byte_position(40);
534 byte_range.set_last_byte_position(49);
535 }
536
537 if (byte_range.first_byte_position() >= length_) {
538 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
539 response_data->clear();
540 return;
541 }
542
543 EXPECT_TRUE(byte_range.ComputeBounds(length_));
544 int64_t start = byte_range.first_byte_position();
545 int64_t end = byte_range.last_byte_position();
546
547 EXPECT_LT(end, length_);
548
549 std::string content_range = base::StringPrintf("Content-Range: bytes %" PRId64
550 "-%" PRId64 "/%" PRId64 "\n",
551 start, end, length_);
552 response_headers->append(content_range);
553
554 if (!request->extra_headers.HasHeader("If-None-Match") || modified_) {
555 std::string data;
556 if (end == start) {
557 EXPECT_EQ(0, end % 10);
558 data = "r";
559 } else {
560 EXPECT_EQ(9, (end - start) % 10);
561 for (int64_t block_start = start; block_start < end; block_start += 10) {
562 base::StringAppendF(&data, "rg: %02" PRId64 "-%02" PRId64 " ",
563 block_start % 100, (block_start + 9) % 100);
564 }
565 }
566 *response_data = data;
567
568 if (end - start != 9) {
569 // We also have to fix content-length.
570 int64_t len = end - start + 1;
571 std::string content_length =
572 base::StringPrintf("Content-Length: %" PRId64 "\n", len);
573 response_headers->replace(response_headers->find("Content-Length:"),
574 content_length.size(), content_length);
575 }
576 } else {
577 response_status->assign("HTTP/1.1 304 Not Modified");
578 response_data->clear();
579 }
580 }
581
582 const MockTransaction kRangeGET_TransactionOK = {
583 "http://www.google.com/range",
584 "GET",
585 base::Time(),
586 "Range: bytes = 40-49\r\n" EXTRA_HEADER,
587 LOAD_NORMAL,
588 DefaultTransportInfo(),
589 "HTTP/1.1 206 Partial Content",
590 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
591 "ETag: \"foo\"\n"
592 "Accept-Ranges: bytes\n"
593 "Content-Length: 10\n",
594 base::Time(),
595 "rg: 40-49 ",
596 {},
597 absl::nullopt,
598 absl::nullopt,
599 TEST_MODE_NORMAL,
600 &RangeTransactionServer::RangeHandler,
601 nullptr,
602 nullptr,
603 0,
604 0,
605 OK,
606 };
607
608 const char kFullRangeData[] =
609 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 "
610 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 ";
611
612 // Verifies the response headers (|response|) match a partial content
613 // response for the range starting at |start| and ending at |end|.
Verify206Response(const std::string & response,int start,int end)614 void Verify206Response(const std::string& response, int start, int end) {
615 auto headers = base::MakeRefCounted<HttpResponseHeaders>(
616 HttpUtil::AssembleRawHeaders(response));
617
618 ASSERT_EQ(206, headers->response_code());
619
620 int64_t range_start, range_end, object_size;
621 ASSERT_TRUE(
622 headers->GetContentRangeFor206(&range_start, &range_end, &object_size));
623 int64_t content_length = headers->GetContentLength();
624
625 int length = end - start + 1;
626 ASSERT_EQ(length, content_length);
627 ASSERT_EQ(start, range_start);
628 ASSERT_EQ(end, range_end);
629 }
630
631 // Creates a truncated entry that can be resumed using byte ranges.
CreateTruncatedEntry(std::string raw_headers,MockHttpCache * cache)632 void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) {
633 // Create a disk cache entry that stores an incomplete resource.
634 disk_cache::Entry* entry;
635 MockHttpRequest request(kRangeGET_TransactionOK);
636 ASSERT_TRUE(cache->CreateBackendEntry(request.CacheKey(), &entry, nullptr));
637
638 HttpResponseInfo response;
639 response.response_time = base::Time::Now();
640 response.request_time = base::Time::Now();
641 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
642 HttpUtil::AssembleRawHeaders(raw_headers));
643 // Set the last argument for this to be an incomplete request.
644 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
645
646 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(100);
647 int len = static_cast<int>(base::strlcpy(buf->data(),
648 "rg: 00-09 rg: 10-19 ", 100));
649 TestCompletionCallback cb;
650 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
651 EXPECT_EQ(len, cb.GetResult(rv));
652 entry->Close();
653 }
654
655 // Verifies that there's an entry with this |key| with the truncated flag set to
656 // |flag_value|, and with an optional |data_size| (if not zero).
VerifyTruncatedFlag(MockHttpCache * cache,const std::string & key,bool flag_value,int data_size)657 void VerifyTruncatedFlag(MockHttpCache* cache,
658 const std::string& key,
659 bool flag_value,
660 int data_size) {
661 disk_cache::Entry* entry;
662 ASSERT_TRUE(cache->OpenBackendEntry(key, &entry));
663 disk_cache::ScopedEntryPtr closer(entry);
664
665 HttpResponseInfo response;
666 bool truncated = !flag_value;
667 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
668 EXPECT_EQ(flag_value, truncated);
669 if (data_size)
670 EXPECT_EQ(data_size, entry->GetDataSize(1));
671 }
672
673 // Helper to represent a network HTTP response.
674 struct Response {
675 // Set this response into |trans|.
AssignTonet::__anonc87d1e5b0111::Response676 void AssignTo(MockTransaction* trans) const {
677 trans->status = status;
678 trans->response_headers = headers;
679 trans->data = body;
680 }
681
status_and_headersnet::__anonc87d1e5b0111::Response682 std::string status_and_headers() const {
683 return std::string(status) + "\n" + std::string(headers);
684 }
685
686 const char* status;
687 const char* headers;
688 const char* body;
689 };
690
691 struct Context {
692 Context() = default;
693
694 int result = ERR_IO_PENDING;
695 TestCompletionCallback callback;
696 std::unique_ptr<HttpTransaction> trans;
697 };
698
699 class FakeWebSocketHandshakeStreamCreateHelper
700 : public WebSocketHandshakeStreamBase::CreateHelper {
701 public:
702 ~FakeWebSocketHandshakeStreamCreateHelper() override = default;
CreateBasicStream(std::unique_ptr<ClientSocketHandle> connect,bool using_proxy,WebSocketEndpointLockManager * websocket_endpoint_lock_manager)703 std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream(
704 std::unique_ptr<ClientSocketHandle> connect,
705 bool using_proxy,
706 WebSocketEndpointLockManager* websocket_endpoint_lock_manager) override {
707 return nullptr;
708 }
CreateHttp2Stream(base::WeakPtr<SpdySession> session,std::set<std::string> dns_aliases)709 std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream(
710 base::WeakPtr<SpdySession> session,
711 std::set<std::string> dns_aliases) override {
712 NOTREACHED();
713 return nullptr;
714 }
CreateHttp3Stream(std::unique_ptr<QuicChromiumClientSession::Handle> session,std::set<std::string> dns_aliases)715 std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp3Stream(
716 std::unique_ptr<QuicChromiumClientSession::Handle> session,
717 std::set<std::string> dns_aliases) override {
718 NOTREACHED();
719 return nullptr;
720 }
721 };
722
723 // Returns true if |entry| is not one of the log types paid attention to in this
724 // test. Note that HTTP_CACHE_WRITE_INFO and HTTP_CACHE_*_DATA are
725 // ignored.
ShouldIgnoreLogEntry(const NetLogEntry & entry)726 bool ShouldIgnoreLogEntry(const NetLogEntry& entry) {
727 switch (entry.type) {
728 case NetLogEventType::HTTP_CACHE_GET_BACKEND:
729 case NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY:
730 case NetLogEventType::HTTP_CACHE_OPEN_ENTRY:
731 case NetLogEventType::HTTP_CACHE_CREATE_ENTRY:
732 case NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY:
733 case NetLogEventType::HTTP_CACHE_DOOM_ENTRY:
734 case NetLogEventType::HTTP_CACHE_READ_INFO:
735 return false;
736 default:
737 return true;
738 }
739 }
740
741 // Gets the entries from |net_log| created by the cache layer and asserted on in
742 // these tests.
GetFilteredNetLogEntries(const RecordingNetLogObserver & net_log_observer)743 std::vector<NetLogEntry> GetFilteredNetLogEntries(
744 const RecordingNetLogObserver& net_log_observer) {
745 auto entries = net_log_observer.GetEntries();
746 base::EraseIf(entries, ShouldIgnoreLogEntry);
747 return entries;
748 }
749
LogContainsEventType(const RecordingNetLogObserver & net_log_observer,NetLogEventType expected)750 bool LogContainsEventType(const RecordingNetLogObserver& net_log_observer,
751 NetLogEventType expected) {
752 return !net_log_observer.GetEntriesWithType(expected).empty();
753 }
754
755 // Returns a TransportInfo distinct from the default for mock transactions,
756 // with the given port number.
TestTransportInfoWithPort(uint16_t port)757 TransportInfo TestTransportInfoWithPort(uint16_t port) {
758 TransportInfo result;
759 result.endpoint = IPEndPoint(IPAddress(42, 0, 1, 2), port);
760 return result;
761 }
762
763 // Returns a TransportInfo distinct from the default for mock transactions.
TestTransportInfo()764 TransportInfo TestTransportInfo() {
765 return TestTransportInfoWithPort(1337);
766 }
767
CachedTestTransportInfo()768 TransportInfo CachedTestTransportInfo() {
769 TransportInfo result = TestTransportInfo();
770 result.type = TransportType::kCached;
771 return result;
772 }
773
774 // Helper function, generating valid HTTP cache key from `url`.
775 // See also: HttpCache::GenerateCacheKey(..)
GenerateCacheKey(const std::string & url)776 std::string GenerateCacheKey(const std::string& url) {
777 return "1/0/" + url;
778 }
779
780 } // namespace
781
782 using HttpCacheTest = TestWithTaskEnvironment;
783 class HttpCacheIOCallbackTest : public HttpCacheTest {
784 public:
785 HttpCacheIOCallbackTest() = default;
786 ~HttpCacheIOCallbackTest() override = default;
787
788 // HttpCache::ActiveEntry is private, doing this allows tests to use it
789 using ActiveEntry = HttpCache::ActiveEntry;
790 using Transaction = HttpCache::Transaction;
791
792 // The below functions are forwarding calls to the HttpCache class.
OpenEntry(HttpCache * cache,const std::string & url,HttpCache::ActiveEntry ** entry,HttpCache::Transaction * trans)793 int OpenEntry(HttpCache* cache,
794 const std::string& url,
795 HttpCache::ActiveEntry** entry,
796 HttpCache::Transaction* trans) {
797 return cache->OpenEntry(GenerateCacheKey(url), entry, trans);
798 }
799
OpenOrCreateEntry(HttpCache * cache,const std::string & url,HttpCache::ActiveEntry ** entry,HttpCache::Transaction * trans)800 int OpenOrCreateEntry(HttpCache* cache,
801 const std::string& url,
802 HttpCache::ActiveEntry** entry,
803 HttpCache::Transaction* trans) {
804 return cache->OpenOrCreateEntry(GenerateCacheKey(url), entry, trans);
805 }
806
CreateEntry(HttpCache * cache,const std::string & url,HttpCache::ActiveEntry ** entry,HttpCache::Transaction * trans)807 int CreateEntry(HttpCache* cache,
808 const std::string& url,
809 HttpCache::ActiveEntry** entry,
810 HttpCache::Transaction* trans) {
811 return cache->CreateEntry(GenerateCacheKey(url), entry, trans);
812 }
813
DoomEntry(HttpCache * cache,const std::string & url,HttpCache::Transaction * trans)814 int DoomEntry(HttpCache* cache,
815 const std::string& url,
816 HttpCache::Transaction* trans) {
817 return cache->DoomEntry(GenerateCacheKey(url), trans);
818 }
819
DeactivateEntry(HttpCache * cache,ActiveEntry * entry)820 void DeactivateEntry(HttpCache* cache, ActiveEntry* entry) {
821 cache->DeactivateEntry(entry);
822 }
823 };
824
825 class HttpSplitCacheKeyTest : public HttpCacheTest {
826 public:
827 HttpSplitCacheKeyTest() = default;
828 ~HttpSplitCacheKeyTest() override = default;
829
ComputeCacheKey(const std::string & url_string)830 std::string ComputeCacheKey(const std::string& url_string) {
831 GURL url(url_string);
832 SchemefulSite site(url);
833 net::HttpRequestInfo request_info;
834 request_info.url = url;
835 request_info.method = "GET";
836 request_info.network_isolation_key = net::NetworkIsolationKey(site, site);
837 request_info.network_anonymization_key =
838 net::NetworkAnonymizationKey::CreateSameSite(site);
839 MockHttpCache cache;
840 return *cache.http_cache()->GenerateCacheKeyForRequest(&request_info);
841 }
842 };
843
844 //-----------------------------------------------------------------------------
845 // Tests.
846
TEST_F(HttpCacheTest,CreateThenDestroy)847 TEST_F(HttpCacheTest, CreateThenDestroy) {
848 MockHttpCache cache;
849
850 std::unique_ptr<HttpTransaction> trans;
851 EXPECT_THAT(cache.CreateTransaction(&trans), IsOk());
852 ASSERT_TRUE(trans.get());
853 }
854
TEST_F(HttpCacheTest,GetBackend)855 TEST_F(HttpCacheTest, GetBackend) {
856 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(0));
857
858 disk_cache::Backend* backend;
859 TestCompletionCallback cb;
860 // This will lazily initialize the backend.
861 int rv = cache.http_cache()->GetBackend(&backend, cb.callback());
862 EXPECT_THAT(cb.GetResult(rv), IsOk());
863 }
864
TEST_F(HttpCacheTest,SimpleGET)865 TEST_F(HttpCacheTest, SimpleGET) {
866 MockHttpCache cache;
867 LoadTimingInfo load_timing_info;
868
869 // Write to the cache.
870 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
871 NetLogWithSource::Make(NetLogSourceType::NONE),
872 &load_timing_info);
873
874 EXPECT_EQ(1, cache.network_layer()->transaction_count());
875 EXPECT_EQ(0, cache.disk_cache()->open_count());
876 EXPECT_EQ(1, cache.disk_cache()->create_count());
877 TestLoadTimingNetworkRequest(load_timing_info);
878 }
879
880 // This test verifies that the callback passed to SetConnectedCallback() is
881 // called once for simple GET calls that traverse the cache.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallback)882 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallback) {
883 MockHttpCache cache;
884
885 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
886 mock_transaction.transport_info = TestTransportInfo();
887 MockHttpRequest request(mock_transaction);
888
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 transaction->SetConnectedCallback(connected_handler.Callback());
896
897 TestCompletionCallback callback;
898 ASSERT_THAT(
899 transaction->Start(&request, callback.callback(), NetLogWithSource()),
900 IsError(ERR_IO_PENDING));
901 EXPECT_THAT(callback.WaitForResult(), IsOk());
902
903 EXPECT_THAT(connected_handler.transports(), ElementsAre(TestTransportInfo()));
904 }
905
906 // This test verifies that when the callback passed to SetConnectedCallback()
907 // returns an error, the transaction fails with that error.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackReturnError)908 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackReturnError) {
909 MockHttpCache cache;
910 MockHttpRequest request(kSimpleGET_Transaction);
911 ConnectedHandler connected_handler;
912
913 std::unique_ptr<HttpTransaction> transaction;
914 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
915 ASSERT_THAT(transaction, NotNull());
916
917 // The exact error code does not matter. We only care that it is passed to
918 // the transaction's completion callback unmodified.
919 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
920 transaction->SetConnectedCallback(connected_handler.Callback());
921
922 TestCompletionCallback callback;
923 ASSERT_THAT(
924 transaction->Start(&request, callback.callback(), NetLogWithSource()),
925 IsError(ERR_IO_PENDING));
926 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));
927 }
928
929 // This test verifies that the callback passed to SetConnectedCallback() is
930 // called once for requests that hit the cache.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHit)931 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHit) {
932 MockHttpCache cache;
933
934 {
935 // Populate the cache.
936 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
937 mock_transaction.transport_info = TestTransportInfo();
938 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
939 }
940
941 // Establish a baseline.
942 EXPECT_EQ(1, cache.network_layer()->transaction_count());
943
944 // Load from the cache (only), observe the callback being called.
945
946 ConnectedHandler connected_handler;
947 MockHttpRequest request(kSimpleGET_Transaction);
948
949 std::unique_ptr<HttpTransaction> transaction;
950 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
951 ASSERT_THAT(transaction, NotNull());
952
953 transaction->SetConnectedCallback(connected_handler.Callback());
954
955 TestCompletionCallback callback;
956 ASSERT_THAT(
957 transaction->Start(&request, callback.callback(), NetLogWithSource()),
958 IsError(ERR_IO_PENDING));
959 EXPECT_THAT(callback.WaitForResult(), IsOk());
960
961 // Still only 1 transaction for the previous request. The connected callback
962 // was not called by a second network transaction.
963 EXPECT_EQ(1, cache.network_layer()->transaction_count());
964
965 EXPECT_THAT(connected_handler.transports(),
966 ElementsAre(CachedTestTransportInfo()));
967 }
968
969 // This test verifies that when the callback passed to SetConnectedCallback()
970 // is called for a request that hit the cache and returns an error, the cache
971 // entry is reusable.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnError)972 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHitReturnError) {
973 MockHttpCache cache;
974
975 {
976 // Populate the cache.
977 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
978 mock_transaction.transport_info = TestTransportInfo();
979 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
980 }
981
982 MockHttpRequest request(kSimpleGET_Transaction);
983
984 {
985 // Attempt to read from cache entry, but abort transaction due to a
986 // connected callback error.
987 ConnectedHandler connected_handler;
988 connected_handler.set_result(ERR_FAILED);
989
990 std::unique_ptr<HttpTransaction> transaction;
991 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
992 ASSERT_THAT(transaction, NotNull());
993
994 transaction->SetConnectedCallback(connected_handler.Callback());
995
996 TestCompletionCallback callback;
997 ASSERT_THAT(
998 transaction->Start(&request, callback.callback(), NetLogWithSource()),
999 IsError(ERR_IO_PENDING));
1000 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));
1001
1002 // Used the cache entry only.
1003 EXPECT_THAT(connected_handler.transports(),
1004 ElementsAre(CachedTestTransportInfo()));
1005 }
1006
1007 {
1008 // Request the same resource once more, observe that it is read from cache.
1009 ConnectedHandler connected_handler;
1010
1011 std::unique_ptr<HttpTransaction> transaction;
1012 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1013 ASSERT_THAT(transaction, NotNull());
1014
1015 transaction->SetConnectedCallback(connected_handler.Callback());
1016
1017 TestCompletionCallback callback;
1018 ASSERT_THAT(
1019 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1020 IsError(ERR_IO_PENDING));
1021 EXPECT_THAT(callback.WaitForResult(), IsOk());
1022
1023 // Used the cache entry only.
1024 EXPECT_THAT(connected_handler.transports(),
1025 ElementsAre(CachedTestTransportInfo()));
1026 }
1027 }
1028
1029 // This test verifies that when the callback passed to SetConnectedCallback()
1030 // returns `ERR_INCONSISTENT_IP_ADDRESS_SPACE`, the cache entry is invalidated.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnInconsistentIpError)1031 TEST_F(HttpCacheTest,
1032 SimpleGET_ConnectedCallbackOnCacheHitReturnInconsistentIpError) {
1033 MockHttpCache cache;
1034
1035 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1036 mock_transaction.transport_info = TestTransportInfo();
1037
1038 // Populate the cache.
1039 RunTransactionTest(cache.http_cache(), mock_transaction);
1040
1041 MockHttpRequest request(kSimpleGET_Transaction);
1042
1043 {
1044 // Attempt to read from cache entry, but abort transaction due to a
1045 // connected callback error.
1046 ConnectedHandler connected_handler;
1047 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
1048
1049 std::unique_ptr<HttpTransaction> transaction;
1050 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1051 ASSERT_THAT(transaction, NotNull());
1052
1053 transaction->SetConnectedCallback(connected_handler.Callback());
1054
1055 TestCompletionCallback callback;
1056 ASSERT_THAT(
1057 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1058 IsError(ERR_IO_PENDING));
1059 EXPECT_THAT(callback.WaitForResult(),
1060 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
1061
1062 // Used the cache entry only.
1063 EXPECT_THAT(connected_handler.transports(),
1064 ElementsAre(CachedTestTransportInfo()));
1065 }
1066
1067 {
1068 // Request the same resource once more, observe that it is not read from
1069 // cache.
1070 ConnectedHandler connected_handler;
1071
1072 std::unique_ptr<HttpTransaction> transaction;
1073 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1074 ASSERT_THAT(transaction, NotNull());
1075
1076 transaction->SetConnectedCallback(connected_handler.Callback());
1077
1078 TestCompletionCallback callback;
1079 ASSERT_THAT(
1080 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1081 IsError(ERR_IO_PENDING));
1082 EXPECT_THAT(callback.WaitForResult(), IsOk());
1083
1084 // Used the network only.
1085 EXPECT_THAT(connected_handler.transports(),
1086 ElementsAre(TestTransportInfo()));
1087 }
1088 }
1089
1090 // This test verifies that when the callback passed to SetConnectedCallback()
1091 // returns
1092 // `ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_LOCAL_NETWORK_ACCESS_POLICY`, the
1093 // cache entry is invalidated, and we'll retry the connection from the network.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnLocalNetworkAccessBlockedError)1094 TEST_F(
1095 HttpCacheTest,
1096 SimpleGET_ConnectedCallbackOnCacheHitReturnLocalNetworkAccessBlockedError) {
1097 MockHttpCache cache;
1098
1099 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1100 mock_transaction.transport_info = TestTransportInfo();
1101
1102 // Populate the cache.
1103 RunTransactionTest(cache.http_cache(), mock_transaction);
1104
1105 MockHttpRequest request(kSimpleGET_Transaction);
1106
1107 {
1108 // Attempt to read from cache entry, but abort transaction due to a
1109 // connected callback error.
1110 ConnectedHandler connected_handler;
1111 connected_handler.set_result(
1112 ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_LOCAL_NETWORK_ACCESS_POLICY);
1113
1114 std::unique_ptr<HttpTransaction> transaction;
1115 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1116 ASSERT_THAT(transaction, NotNull());
1117
1118 transaction->SetConnectedCallback(connected_handler.Callback());
1119
1120 TestCompletionCallback callback;
1121 ASSERT_THAT(
1122 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1123 IsError(ERR_IO_PENDING));
1124 EXPECT_THAT(
1125 callback.WaitForResult(),
1126 IsError(
1127 ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_LOCAL_NETWORK_ACCESS_POLICY));
1128
1129 // Used the cache entry only.
1130 EXPECT_THAT(connected_handler.transports(),
1131 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
1132 }
1133
1134 {
1135 // Request the same resource once more, observe that it is not read from
1136 // cache.
1137 ConnectedHandler connected_handler;
1138
1139 std::unique_ptr<HttpTransaction> transaction;
1140 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1141 ASSERT_THAT(transaction, NotNull());
1142
1143 transaction->SetConnectedCallback(connected_handler.Callback());
1144
1145 TestCompletionCallback callback;
1146 ASSERT_THAT(
1147 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1148 IsError(ERR_IO_PENDING));
1149 EXPECT_THAT(callback.WaitForResult(), IsOk());
1150
1151 // Used the network only.
1152 EXPECT_THAT(connected_handler.transports(),
1153 ElementsAre(TestTransportInfo()));
1154 }
1155 }
1156
1157 // This test verifies that the callback passed to SetConnectedCallback() is
1158 // called with the right transport type when the cached entry was originally
1159 // fetched via proxy.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitFromProxy)1160 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHitFromProxy) {
1161 MockHttpCache cache;
1162
1163 TransportInfo proxied_transport_info = TestTransportInfo();
1164 proxied_transport_info.type = TransportType::kProxied;
1165
1166 {
1167 // Populate the cache.
1168 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1169 mock_transaction.transport_info = proxied_transport_info;
1170 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1171 }
1172
1173 // Establish a baseline.
1174 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1175
1176 // Load from the cache (only), observe the callback being called.
1177
1178 ConnectedHandler connected_handler;
1179 MockHttpRequest request(kSimpleGET_Transaction);
1180
1181 std::unique_ptr<HttpTransaction> transaction;
1182 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1183 ASSERT_THAT(transaction, NotNull());
1184
1185 transaction->SetConnectedCallback(connected_handler.Callback());
1186
1187 TestCompletionCallback callback;
1188 ASSERT_THAT(
1189 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1190 IsError(ERR_IO_PENDING));
1191 EXPECT_THAT(callback.WaitForResult(), IsOk());
1192
1193 // Still only 1 transaction for the previous request. The connected callback
1194 // was not called by a second network transaction.
1195 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1196
1197 // The transport info mentions both the cache and the original proxy.
1198 TransportInfo expected_transport_info = TestTransportInfo();
1199 expected_transport_info.type = TransportType::kCachedFromProxy;
1200
1201 EXPECT_THAT(connected_handler.transports(),
1202 ElementsAre(expected_transport_info));
1203 }
1204
1205 enum class SplitCacheTestCase {
1206 kSplitCacheDisabled,
1207 kSplitCacheNikFrameSiteEnabled,
1208 kSplitCacheNikCrossSiteFlagEnabled,
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 scoped_feature_list.InitWithFeatures(enabled_features, disabled_features);
1232 }
1233
1234 class HttpCacheTest_SplitCacheFeature
1235 : public HttpCacheTest,
1236 public ::testing::WithParamInterface<SplitCacheTestCase> {
1237 public:
HttpCacheTest_SplitCacheFeature()1238 HttpCacheTest_SplitCacheFeature() {
1239 InitializeSplitCacheScopedFeatureList(feature_list_, GetParam());
1240 }
1241
IsSplitCacheEnabled() const1242 bool IsSplitCacheEnabled() const {
1243 return GetParam() != SplitCacheTestCase::kSplitCacheDisabled;
1244 }
1245
IsNikFrameSiteEnabled() const1246 bool IsNikFrameSiteEnabled() const {
1247 return GetParam() == SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled;
1248 }
1249
1250 private:
1251 base::test::ScopedFeatureList feature_list_;
1252 };
1253
TEST_P(HttpCacheTest_SplitCacheFeature,SimpleGETVerifyGoogleFontMetrics)1254 TEST_P(HttpCacheTest_SplitCacheFeature, SimpleGETVerifyGoogleFontMetrics) {
1255 base::HistogramTester histograms;
1256 const std::string histogram_name = "WebFont.HttpCacheStatus_roboto";
1257
1258 SchemefulSite site_a(GURL("http://www.a.com"));
1259
1260 MockHttpCache cache;
1261
1262 MockTransaction transaction(kSimpleGET_Transaction);
1263 transaction.url = "http://themes.googleusercontent.com/static/fonts/roboto";
1264 AddMockTransaction(&transaction);
1265 MockHttpRequest request(transaction);
1266 request.network_isolation_key = NetworkIsolationKey(site_a, site_a);
1267 request.network_anonymization_key =
1268 net::NetworkAnonymizationKey::CreateSameSite(site_a);
1269
1270 // Attempt to populate the cache.
1271 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
1272 nullptr);
1273
1274 histograms.ExpectUniqueSample(
1275 histogram_name, static_cast<int>(CacheEntryStatus::ENTRY_NOT_IN_CACHE),
1276 1);
1277
1278 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
1279 nullptr);
1280
1281 histograms.ExpectBucketCount(
1282 histogram_name, static_cast<int>(CacheEntryStatus::ENTRY_USED), 1);
1283 }
1284
1285 INSTANTIATE_TEST_SUITE_P(
1286 All,
1287 HttpCacheTest_SplitCacheFeature,
1288 testing::ValuesIn({SplitCacheTestCase::kSplitCacheDisabled,
1289 SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled,
1290 SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled}),
__anonc87d1e5b0202(const testing::TestParamInfo<SplitCacheTestCase>& info) 1291 [](const testing::TestParamInfo<SplitCacheTestCase>& info) {
1292 switch (info.param) {
1293 case (SplitCacheTestCase::kSplitCacheDisabled):
1294 return "SplitCacheDisabled";
1295 case (SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled):
1296 return "SplitCacheNikFrameSiteEnabled";
1297 case (SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled):
1298 return "SplitCacheNikCrossSiteFlagEnabled";
1299 }
1300 });
1301
1302 class HttpCacheTest_SplitCacheFeatureEnabled
1303 : public HttpCacheTest_SplitCacheFeature {
1304 public:
HttpCacheTest_SplitCacheFeatureEnabled()1305 HttpCacheTest_SplitCacheFeatureEnabled() {
1306 CHECK(base::FeatureList::IsEnabled(
1307 net::features::kSplitCacheByNetworkIsolationKey));
1308 }
1309 };
1310
1311 INSTANTIATE_TEST_SUITE_P(
1312 All,
1313 HttpCacheTest_SplitCacheFeatureEnabled,
1314 testing::ValuesIn({SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled,
1315 SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled}),
__anonc87d1e5b0302(const testing::TestParamInfo<SplitCacheTestCase>& info) 1316 [](const testing::TestParamInfo<SplitCacheTestCase>& info) {
1317 switch (info.param) {
1318 case (SplitCacheTestCase::kSplitCacheDisabled):
1319 return "NotUsedForThisTestSuite";
1320 case (SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled):
1321 return "SplitCacheNikFrameSiteEnabled";
1322 case (SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled):
1323 return "SplitCacheNikCrossSiteFlagEnabled";
1324 }
1325 });
1326
TEST_F(HttpCacheTest,SimpleGETNoDiskCache)1327 TEST_F(HttpCacheTest, SimpleGETNoDiskCache) {
1328 MockHttpCache cache;
1329
1330 cache.disk_cache()->set_fail_requests(true);
1331
1332 RecordingNetLogObserver net_log_observer;
1333 LoadTimingInfo load_timing_info;
1334
1335 // Read from the network, and don't use the cache.
1336 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
1337 NetLogWithSource::Make(NetLogSourceType::NONE),
1338 &load_timing_info);
1339
1340 // Check that the NetLog was filled as expected.
1341 // (We attempted to OpenOrCreate entries, but fail).
1342 auto entries = GetFilteredNetLogEntries(net_log_observer);
1343
1344 EXPECT_EQ(4u, entries.size());
1345 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1346 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1347 EXPECT_TRUE(
1348 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1349 EXPECT_TRUE(LogContainsBeginEvent(
1350 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1351 EXPECT_TRUE(LogContainsEndEvent(
1352 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1353
1354 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1355 EXPECT_EQ(0, cache.disk_cache()->open_count());
1356 EXPECT_EQ(0, cache.disk_cache()->create_count());
1357 TestLoadTimingNetworkRequest(load_timing_info);
1358 }
1359
TEST_F(HttpCacheTest,SimpleGETNoDiskCache2)1360 TEST_F(HttpCacheTest, SimpleGETNoDiskCache2) {
1361 // This will initialize a cache object with NULL backend.
1362 auto factory = std::make_unique<MockBlockingBackendFactory>();
1363 factory->set_fail(true);
1364 factory->FinishCreation(); // We'll complete synchronously.
1365 MockHttpCache cache(std::move(factory));
1366
1367 // Read from the network, and don't use the cache.
1368 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1369
1370 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1371 EXPECT_FALSE(cache.http_cache()->GetCurrentBackend());
1372 }
1373
1374 // Tests that IOBuffers are not referenced after IO completes.
TEST_F(HttpCacheTest,ReleaseBuffer)1375 TEST_F(HttpCacheTest, ReleaseBuffer) {
1376 MockHttpCache cache;
1377
1378 // Write to the cache.
1379 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1380
1381 MockHttpRequest request(kSimpleGET_Transaction);
1382 std::unique_ptr<HttpTransaction> trans;
1383 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
1384
1385 const int kBufferSize = 10;
1386 scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(kBufferSize);
1387 ReleaseBufferCompletionCallback cb(buffer.get());
1388
1389 int rv = trans->Start(&request, cb.callback(), NetLogWithSource());
1390 EXPECT_THAT(cb.GetResult(rv), IsOk());
1391
1392 rv = trans->Read(buffer.get(), kBufferSize, cb.callback());
1393 EXPECT_EQ(kBufferSize, cb.GetResult(rv));
1394 }
1395
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures)1396 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures) {
1397 MockHttpCache cache;
1398
1399 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1400
1401 // Read from the network, and fail to write to the cache.
1402 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1403
1404 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1405 EXPECT_EQ(0, cache.disk_cache()->open_count());
1406 EXPECT_EQ(1, cache.disk_cache()->create_count());
1407
1408 // This one should see an empty cache again.
1409 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1410
1411 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1412 EXPECT_EQ(0, cache.disk_cache()->open_count());
1413 EXPECT_EQ(2, cache.disk_cache()->create_count());
1414 }
1415
1416 // Tests that disk failures after the transaction has started don't cause the
1417 // request to fail.
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures2)1418 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures2) {
1419 MockHttpCache cache;
1420
1421 MockHttpRequest request(kSimpleGET_Transaction);
1422
1423 auto c = std::make_unique<Context>();
1424 int rv = cache.CreateTransaction(&c->trans);
1425 ASSERT_THAT(rv, IsOk());
1426
1427 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
1428 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1429 rv = c->callback.WaitForResult();
1430
1431 // Start failing request now.
1432 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1433
1434 // We have to open the entry again to propagate the failure flag.
1435 disk_cache::Entry* en;
1436 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &en));
1437 en->Close();
1438
1439 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1440 c.reset();
1441
1442 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1443 EXPECT_EQ(1, cache.disk_cache()->open_count());
1444 EXPECT_EQ(1, cache.disk_cache()->create_count());
1445
1446 // This one should see an empty cache again.
1447 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1448
1449 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1450 EXPECT_EQ(1, cache.disk_cache()->open_count());
1451 EXPECT_EQ(2, cache.disk_cache()->create_count());
1452 }
1453
1454 // Tests that we handle failures to read from the cache.
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures3)1455 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures3) {
1456 MockHttpCache cache;
1457
1458 // Read from the network, and write to the cache.
1459 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1460
1461 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1462 EXPECT_EQ(0, cache.disk_cache()->open_count());
1463 EXPECT_EQ(1, cache.disk_cache()->create_count());
1464
1465 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1466
1467 MockHttpRequest request(kSimpleGET_Transaction);
1468
1469 // Now fail to read from the cache.
1470 auto c = std::make_unique<Context>();
1471 int rv = cache.CreateTransaction(&c->trans);
1472 ASSERT_THAT(rv, IsOk());
1473
1474 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
1475 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
1476
1477 // Now verify that the entry was removed from the cache.
1478 cache.disk_cache()->set_soft_failures_mask(0);
1479
1480 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1481 EXPECT_EQ(1, cache.disk_cache()->open_count());
1482 EXPECT_EQ(2, cache.disk_cache()->create_count());
1483
1484 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1485
1486 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1487 EXPECT_EQ(1, cache.disk_cache()->open_count());
1488 EXPECT_EQ(3, cache.disk_cache()->create_count());
1489 }
1490
TEST_F(HttpCacheTest,SimpleGET_LoadOnlyFromCache_Hit)1491 TEST_F(HttpCacheTest, SimpleGET_LoadOnlyFromCache_Hit) {
1492 MockHttpCache cache;
1493
1494 RecordingNetLogObserver net_log_observer;
1495 NetLogWithSource net_log_with_source =
1496 NetLogWithSource::Make(NetLogSourceType::NONE);
1497 LoadTimingInfo load_timing_info;
1498
1499 // Write to the cache.
1500 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
1501 net_log_with_source, &load_timing_info);
1502
1503 // Check that the NetLog was filled as expected.
1504 auto entries = GetFilteredNetLogEntries(net_log_observer);
1505
1506 EXPECT_EQ(6u, entries.size());
1507 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1508 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1509 EXPECT_TRUE(
1510 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1511 EXPECT_TRUE(LogContainsBeginEvent(
1512 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1513 EXPECT_TRUE(LogContainsEndEvent(
1514 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1515 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1516 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1517 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1518 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1519
1520 TestLoadTimingNetworkRequest(load_timing_info);
1521
1522 // Force this transaction to read from the cache.
1523 MockTransaction transaction(kSimpleGET_Transaction);
1524 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
1525
1526 net_log_observer.Clear();
1527
1528 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1529 net_log_with_source, &load_timing_info);
1530
1531 // Check that the NetLog was filled as expected.
1532 entries = GetFilteredNetLogEntries(net_log_observer);
1533
1534 EXPECT_EQ(8u, entries.size());
1535 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1536 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1537 EXPECT_TRUE(
1538 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1539 EXPECT_TRUE(LogContainsBeginEvent(
1540 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1541 EXPECT_TRUE(LogContainsEndEvent(
1542 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1543 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1544 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1545 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1546 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1547 EXPECT_TRUE(
1548 LogContainsBeginEvent(entries, 6, NetLogEventType::HTTP_CACHE_READ_INFO));
1549 EXPECT_TRUE(
1550 LogContainsEndEvent(entries, 7, NetLogEventType::HTTP_CACHE_READ_INFO));
1551
1552 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1553 EXPECT_EQ(1, cache.disk_cache()->open_count());
1554 EXPECT_EQ(1, cache.disk_cache()->create_count());
1555 TestLoadTimingCachedResponse(load_timing_info);
1556 }
1557
TEST_F(HttpCacheTest,SimpleGET_LoadOnlyFromCache_Miss)1558 TEST_F(HttpCacheTest, SimpleGET_LoadOnlyFromCache_Miss) {
1559 MockHttpCache cache;
1560
1561 // force this transaction to read from the cache
1562 MockTransaction transaction(kSimpleGET_Transaction);
1563 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
1564
1565 MockHttpRequest request(transaction);
1566 TestCompletionCallback callback;
1567
1568 std::unique_ptr<HttpTransaction> trans;
1569 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
1570
1571 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1572 if (rv == ERR_IO_PENDING)
1573 rv = callback.WaitForResult();
1574 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
1575
1576 trans.reset();
1577
1578 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1579 EXPECT_EQ(0, cache.disk_cache()->open_count());
1580 EXPECT_EQ(0, cache.disk_cache()->create_count());
1581 }
1582
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_Hit)1583 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_Hit) {
1584 MockHttpCache cache;
1585
1586 // write to the cache
1587 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1588
1589 // force this transaction to read from the cache if valid
1590 MockTransaction transaction(kSimpleGET_Transaction);
1591 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1592
1593 RunTransactionTest(cache.http_cache(), transaction);
1594
1595 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1596 EXPECT_EQ(1, cache.disk_cache()->open_count());
1597 EXPECT_EQ(1, cache.disk_cache()->create_count());
1598 }
1599
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_Miss)1600 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_Miss) {
1601 MockHttpCache cache;
1602
1603 // force this transaction to read from the cache if valid
1604 MockTransaction transaction(kSimpleGET_Transaction);
1605 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1606
1607 RunTransactionTest(cache.http_cache(), transaction);
1608
1609 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1610 EXPECT_EQ(0, cache.disk_cache()->open_count());
1611 EXPECT_EQ(1, cache.disk_cache()->create_count());
1612 }
1613
1614 // Tests LOAD_SKIP_CACHE_VALIDATION in the presence of vary headers.
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_VaryMatch)1615 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_VaryMatch) {
1616 MockHttpCache cache;
1617
1618 // Write to the cache.
1619 MockTransaction transaction(kSimpleGET_Transaction);
1620 transaction.request_headers = "Foo: bar\r\n";
1621 transaction.response_headers = "Cache-Control: max-age=10000\n"
1622 "Vary: Foo\n";
1623 AddMockTransaction(&transaction);
1624 RunTransactionTest(cache.http_cache(), transaction);
1625
1626 // Read from the cache.
1627 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1628 RunTransactionTest(cache.http_cache(), transaction);
1629
1630 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1631 EXPECT_EQ(1, cache.disk_cache()->open_count());
1632 EXPECT_EQ(1, cache.disk_cache()->create_count());
1633 RemoveMockTransaction(&transaction);
1634 }
1635
1636 // Tests LOAD_SKIP_CACHE_VALIDATION in the presence of vary headers.
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_VaryMismatch)1637 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_VaryMismatch) {
1638 MockHttpCache cache;
1639
1640 // Write to the cache.
1641 MockTransaction transaction(kSimpleGET_Transaction);
1642 transaction.request_headers = "Foo: bar\r\n";
1643 transaction.response_headers = "Cache-Control: max-age=10000\n"
1644 "Vary: Foo\n";
1645 AddMockTransaction(&transaction);
1646 RunTransactionTest(cache.http_cache(), transaction);
1647
1648 // Attempt to read from the cache... this is a vary mismatch that must reach
1649 // the network again.
1650 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1651 transaction.request_headers = "Foo: none\r\n";
1652 LoadTimingInfo load_timing_info;
1653 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1654 NetLogWithSource::Make(NetLogSourceType::NONE),
1655 &load_timing_info);
1656
1657 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1658 EXPECT_EQ(1, cache.disk_cache()->open_count());
1659 EXPECT_EQ(1, cache.disk_cache()->create_count());
1660 TestLoadTimingNetworkRequest(load_timing_info);
1661 RemoveMockTransaction(&transaction);
1662 }
1663
1664 // Tests that we honor Vary: * with LOAD_SKIP_CACHE_VALIDATION (crbug/778681)
TEST_F(HttpCacheTest,SimpleGET_LoadSkipCacheValidation_VaryStar)1665 TEST_F(HttpCacheTest, SimpleGET_LoadSkipCacheValidation_VaryStar) {
1666 MockHttpCache cache;
1667
1668 // Write to the cache.
1669 MockTransaction transaction(kSimpleGET_Transaction);
1670 transaction.response_headers =
1671 "Cache-Control: max-age=10000\n"
1672 "Vary: *\n";
1673 AddMockTransaction(&transaction);
1674 RunTransactionTest(cache.http_cache(), transaction);
1675
1676 // Attempt to read from the cache... we will still load it from network,
1677 // since Vary: * doesn't match.
1678 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1679 LoadTimingInfo load_timing_info;
1680 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1681 NetLogWithSource::Make(NetLogSourceType::NONE),
1682 &load_timing_info);
1683
1684 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1685 EXPECT_EQ(1, cache.disk_cache()->open_count());
1686 EXPECT_EQ(1, cache.disk_cache()->create_count());
1687 RemoveMockTransaction(&transaction);
1688 }
1689
1690 // Tests that was_cached was set properly on a failure, even if the cached
1691 // response wasn't returned.
TEST_F(HttpCacheTest,SimpleGET_CacheSignal_Failure)1692 TEST_F(HttpCacheTest, SimpleGET_CacheSignal_Failure) {
1693 for (bool use_memory_entry_data : {false, true}) {
1694 MockHttpCache cache;
1695 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
1696
1697 // Prime cache.
1698 MockTransaction transaction(kSimpleGET_Transaction);
1699 transaction.response_headers = "Cache-Control: no-cache\n";
1700
1701 AddMockTransaction(&transaction);
1702 RunTransactionTest(cache.http_cache(), transaction);
1703 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1704 EXPECT_EQ(1, cache.disk_cache()->create_count());
1705 EXPECT_EQ(0, cache.disk_cache()->open_count());
1706 RemoveMockTransaction(&transaction);
1707
1708 // Network failure with error; should fail but have was_cached set.
1709 transaction.start_return_code = ERR_FAILED;
1710 AddMockTransaction(&transaction);
1711
1712 MockHttpRequest request(transaction);
1713 TestCompletionCallback callback;
1714 std::unique_ptr<HttpTransaction> trans;
1715 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
1716 EXPECT_THAT(rv, IsOk());
1717 ASSERT_TRUE(trans.get());
1718 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1719 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
1720
1721 const HttpResponseInfo* response_info = trans->GetResponseInfo();
1722 ASSERT_TRUE(response_info);
1723 // If use_memory_entry_data is true, we will not bother opening the entry,
1724 // and just kick it out, so was_cached will end up false.
1725 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1726 if (use_memory_entry_data) {
1727 EXPECT_EQ(false, response_info->was_cached);
1728 EXPECT_EQ(2, cache.disk_cache()->create_count());
1729 EXPECT_EQ(0, cache.disk_cache()->open_count());
1730 } else {
1731 EXPECT_EQ(true, response_info->was_cached);
1732 EXPECT_EQ(1, cache.disk_cache()->create_count());
1733 EXPECT_EQ(1, cache.disk_cache()->open_count());
1734 }
1735
1736 RemoveMockTransaction(&transaction);
1737 }
1738 }
1739
1740 // Tests that if the transaction is destroyed right after setting the
1741 // cache_entry_status_ as CANT_CONDITIONALIZE, then RecordHistograms should not
1742 // hit a dcheck.
TEST_F(HttpCacheTest,RecordHistogramsCantConditionalize)1743 TEST_F(HttpCacheTest, RecordHistogramsCantConditionalize) {
1744 MockHttpCache cache;
1745 cache.disk_cache()->set_support_in_memory_entry_data(true);
1746
1747 {
1748 // Prime cache.
1749 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1750 transaction.response_headers = "Cache-Control: no-cache\n";
1751 RunTransactionTest(cache.http_cache(), transaction);
1752 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1753 EXPECT_EQ(1, cache.disk_cache()->create_count());
1754 EXPECT_EQ(0, cache.disk_cache()->open_count());
1755 }
1756
1757 {
1758 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1759 MockHttpRequest request(transaction);
1760 TestCompletionCallback callback;
1761 std::unique_ptr<HttpTransaction> trans;
1762 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
1763 EXPECT_THAT(rv, IsOk());
1764 ASSERT_TRUE(trans.get());
1765 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1766 // Now destroy the transaction so that RecordHistograms gets invoked.
1767 trans.reset();
1768 }
1769 }
1770
1771 // Confirm if we have an empty cache, a read is marked as network verified.
TEST_F(HttpCacheTest,SimpleGET_NetworkAccessed_Network)1772 TEST_F(HttpCacheTest, SimpleGET_NetworkAccessed_Network) {
1773 MockHttpCache cache;
1774
1775 // write to the cache
1776 HttpResponseInfo response_info;
1777 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
1778 &response_info);
1779
1780 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1781 EXPECT_EQ(0, cache.disk_cache()->open_count());
1782 EXPECT_EQ(1, cache.disk_cache()->create_count());
1783 EXPECT_TRUE(response_info.network_accessed);
1784 EXPECT_EQ(CacheEntryStatus::ENTRY_NOT_IN_CACHE,
1785 response_info.cache_entry_status);
1786 }
1787
1788 // Confirm if we have a fresh entry in cache, it isn't marked as
1789 // network verified.
TEST_F(HttpCacheTest,SimpleGET_NetworkAccessed_Cache)1790 TEST_F(HttpCacheTest, SimpleGET_NetworkAccessed_Cache) {
1791 MockHttpCache cache;
1792
1793 // Prime cache.
1794 MockTransaction transaction(kSimpleGET_Transaction);
1795
1796 RunTransactionTest(cache.http_cache(), transaction);
1797 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1798 EXPECT_EQ(1, cache.disk_cache()->create_count());
1799
1800 // Re-run transaction; make sure we don't mark the network as accessed.
1801 HttpResponseInfo response_info;
1802 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
1803 &response_info);
1804
1805 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1806 EXPECT_FALSE(response_info.network_accessed);
1807 EXPECT_EQ(CacheEntryStatus::ENTRY_USED, response_info.cache_entry_status);
1808 }
1809
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache)1810 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache) {
1811 MockHttpCache cache;
1812
1813 // Write to the cache.
1814 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1815
1816 // Force this transaction to write to the cache again.
1817 MockTransaction transaction(kSimpleGET_Transaction);
1818 transaction.load_flags |= LOAD_BYPASS_CACHE;
1819
1820 RecordingNetLogObserver net_log_observer;
1821 LoadTimingInfo load_timing_info;
1822
1823 // Write to the cache.
1824 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1825 NetLogWithSource::Make(NetLogSourceType::NONE),
1826 &load_timing_info);
1827
1828 // Check that the NetLog was filled as expected.
1829 auto entries = GetFilteredNetLogEntries(net_log_observer);
1830
1831 EXPECT_EQ(8u, entries.size());
1832 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1833 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1834 EXPECT_TRUE(
1835 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1836 EXPECT_TRUE(LogContainsBeginEvent(entries, 2,
1837 NetLogEventType::HTTP_CACHE_DOOM_ENTRY));
1838 EXPECT_TRUE(
1839 LogContainsEndEvent(entries, 3, NetLogEventType::HTTP_CACHE_DOOM_ENTRY));
1840 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1841 NetLogEventType::HTTP_CACHE_CREATE_ENTRY));
1842 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1843 NetLogEventType::HTTP_CACHE_CREATE_ENTRY));
1844 EXPECT_TRUE(LogContainsBeginEvent(entries, 6,
1845 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1846 EXPECT_TRUE(LogContainsEndEvent(entries, 7,
1847 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1848
1849 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1850 EXPECT_EQ(0, cache.disk_cache()->open_count());
1851 EXPECT_EQ(2, cache.disk_cache()->create_count());
1852 TestLoadTimingNetworkRequest(load_timing_info);
1853 }
1854
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache_Implicit)1855 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache_Implicit) {
1856 MockHttpCache cache;
1857
1858 // write to the cache
1859 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1860
1861 // force this transaction to write to the cache again
1862 MockTransaction transaction(kSimpleGET_Transaction);
1863 transaction.request_headers = "pragma: no-cache\r\n";
1864
1865 RunTransactionTest(cache.http_cache(), transaction);
1866
1867 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1868 EXPECT_EQ(0, cache.disk_cache()->open_count());
1869 EXPECT_EQ(2, cache.disk_cache()->create_count());
1870 }
1871
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache_Implicit2)1872 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache_Implicit2) {
1873 MockHttpCache cache;
1874
1875 // write to the cache
1876 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1877
1878 // force this transaction to write to the cache again
1879 MockTransaction transaction(kSimpleGET_Transaction);
1880 transaction.request_headers = "cache-control: no-cache\r\n";
1881
1882 RunTransactionTest(cache.http_cache(), transaction);
1883
1884 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1885 EXPECT_EQ(0, cache.disk_cache()->open_count());
1886 EXPECT_EQ(2, cache.disk_cache()->create_count());
1887 }
1888
TEST_F(HttpCacheTest,SimpleGET_LoadValidateCache)1889 TEST_F(HttpCacheTest, SimpleGET_LoadValidateCache) {
1890 MockHttpCache cache;
1891
1892 // Write to the cache.
1893 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1894
1895 // Read from the cache.
1896 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1897
1898 // Force this transaction to validate the cache.
1899 MockTransaction transaction(kSimpleGET_Transaction);
1900 transaction.load_flags |= LOAD_VALIDATE_CACHE;
1901
1902 HttpResponseInfo response_info;
1903 LoadTimingInfo load_timing_info;
1904 RunTransactionTestWithResponseInfoAndGetTiming(
1905 cache.http_cache(), transaction, &response_info,
1906 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
1907
1908 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1909 EXPECT_EQ(1, cache.disk_cache()->open_count());
1910 EXPECT_EQ(1, cache.disk_cache()->create_count());
1911 EXPECT_TRUE(response_info.network_accessed);
1912 TestLoadTimingNetworkRequest(load_timing_info);
1913 }
1914
TEST_F(HttpCacheTest,SimpleGET_LoadValidateCache_Implicit)1915 TEST_F(HttpCacheTest, SimpleGET_LoadValidateCache_Implicit) {
1916 MockHttpCache cache;
1917
1918 // write to the cache
1919 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1920
1921 // read from the cache
1922 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1923
1924 // force this transaction to validate the cache
1925 MockTransaction transaction(kSimpleGET_Transaction);
1926 transaction.request_headers = "cache-control: max-age=0\r\n";
1927
1928 RunTransactionTest(cache.http_cache(), transaction);
1929
1930 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1931 EXPECT_EQ(1, cache.disk_cache()->open_count());
1932 EXPECT_EQ(1, cache.disk_cache()->create_count());
1933 }
1934
1935 // Tests that |unused_since_prefetch| is updated accordingly (e.g. it is set to
1936 // true after a prefetch and set back to false when the prefetch is used).
TEST_F(HttpCacheTest,SimpleGET_UnusedSincePrefetch)1937 TEST_F(HttpCacheTest, SimpleGET_UnusedSincePrefetch) {
1938 MockHttpCache cache;
1939 HttpResponseInfo response_info;
1940
1941 // A normal load does not have |unused_since_prefetch| set.
1942 RunTransactionTestWithResponseInfoAndGetTiming(
1943 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1944 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1945 EXPECT_FALSE(response_info.unused_since_prefetch);
1946 EXPECT_FALSE(response_info.was_cached);
1947
1948 // The prefetch itself does not have |unused_since_prefetch| set.
1949 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
1950 prefetch_transaction.load_flags |= LOAD_PREFETCH;
1951 RunTransactionTestWithResponseInfoAndGetTiming(
1952 cache.http_cache(), prefetch_transaction, &response_info,
1953 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1954 EXPECT_FALSE(response_info.unused_since_prefetch);
1955 EXPECT_TRUE(response_info.was_cached);
1956
1957 // A duplicated prefetch has |unused_since_prefetch| set.
1958 RunTransactionTestWithResponseInfoAndGetTiming(
1959 cache.http_cache(), prefetch_transaction, &response_info,
1960 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1961 EXPECT_TRUE(response_info.unused_since_prefetch);
1962 EXPECT_TRUE(response_info.was_cached);
1963
1964 // |unused_since_prefetch| is still true after two prefetches in a row.
1965 RunTransactionTestWithResponseInfoAndGetTiming(
1966 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1967 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1968 EXPECT_TRUE(response_info.unused_since_prefetch);
1969 EXPECT_TRUE(response_info.was_cached);
1970
1971 // The resource has now been used, back to normal behavior.
1972 RunTransactionTestWithResponseInfoAndGetTiming(
1973 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1974 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1975 EXPECT_FALSE(response_info.unused_since_prefetch);
1976 EXPECT_TRUE(response_info.was_cached);
1977 }
1978
1979 // Tests that requests made with the LOAD_RESTRICTED_PREFETCH load flag result
1980 // in HttpResponseInfo entries with the |restricted_prefetch| flag set. Also
1981 // tests that responses with |restricted_prefetch| flag set can only be used by
1982 // requests that have the LOAD_CAN_USE_RESTRICTED_PREFETCH load flag.
TEST_F(HttpCacheTest,SimpleGET_RestrictedPrefetchIsRestrictedUntilReuse)1983 TEST_F(HttpCacheTest, SimpleGET_RestrictedPrefetchIsRestrictedUntilReuse) {
1984 MockHttpCache cache;
1985 HttpResponseInfo response_info;
1986
1987 // A normal load does not have |restricted_prefetch| set.
1988 RunTransactionTestWithResponseInfoAndGetTiming(
1989 cache.http_cache(), kTypicalGET_Transaction, &response_info,
1990 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1991 EXPECT_FALSE(response_info.restricted_prefetch);
1992 EXPECT_FALSE(response_info.was_cached);
1993 EXPECT_TRUE(response_info.network_accessed);
1994
1995 // A restricted prefetch is marked as |restricted_prefetch|.
1996 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
1997 prefetch_transaction.load_flags |= LOAD_PREFETCH;
1998 prefetch_transaction.load_flags |= LOAD_RESTRICTED_PREFETCH;
1999 RunTransactionTestWithResponseInfoAndGetTiming(
2000 cache.http_cache(), prefetch_transaction, &response_info,
2001 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2002 EXPECT_TRUE(response_info.restricted_prefetch);
2003 EXPECT_FALSE(response_info.was_cached);
2004 EXPECT_TRUE(response_info.network_accessed);
2005
2006 // Requests that are marked as able to reuse restricted prefetches can do so
2007 // correctly. Once it is reused, it is no longer considered as or marked
2008 // restricted.
2009 MockTransaction can_use_restricted_prefetch_transaction(
2010 kSimpleGET_Transaction);
2011 can_use_restricted_prefetch_transaction.load_flags |=
2012 LOAD_CAN_USE_RESTRICTED_PREFETCH;
2013 RunTransactionTestWithResponseInfoAndGetTiming(
2014 cache.http_cache(), can_use_restricted_prefetch_transaction,
2015 &response_info, NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2016 EXPECT_TRUE(response_info.restricted_prefetch);
2017 EXPECT_TRUE(response_info.was_cached);
2018 EXPECT_FALSE(response_info.network_accessed);
2019
2020 // Later reuse is still no longer marked restricted.
2021 RunTransactionTestWithResponseInfoAndGetTiming(
2022 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2023 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2024 EXPECT_FALSE(response_info.restricted_prefetch);
2025 EXPECT_TRUE(response_info.was_cached);
2026 EXPECT_FALSE(response_info.network_accessed);
2027 }
2028
TEST_F(HttpCacheTest,SimpleGET_RestrictedPrefetchReuseIsLimited)2029 TEST_F(HttpCacheTest, SimpleGET_RestrictedPrefetchReuseIsLimited) {
2030 MockHttpCache cache;
2031 HttpResponseInfo response_info;
2032
2033 // A restricted prefetch is marked as |restricted_prefetch|.
2034 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
2035 prefetch_transaction.load_flags |= LOAD_PREFETCH;
2036 prefetch_transaction.load_flags |= LOAD_RESTRICTED_PREFETCH;
2037 RunTransactionTestWithResponseInfoAndGetTiming(
2038 cache.http_cache(), prefetch_transaction, &response_info,
2039 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2040 EXPECT_TRUE(response_info.restricted_prefetch);
2041 EXPECT_FALSE(response_info.was_cached);
2042 EXPECT_TRUE(response_info.network_accessed);
2043
2044 // Requests that cannot reuse restricted prefetches fail to do so. The network
2045 // is accessed and the resulting response is not marked as
2046 // |restricted_prefetch|.
2047 RunTransactionTestWithResponseInfoAndGetTiming(
2048 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2049 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2050 EXPECT_FALSE(response_info.restricted_prefetch);
2051 EXPECT_FALSE(response_info.was_cached);
2052 EXPECT_TRUE(response_info.network_accessed);
2053
2054 // Future requests that are not marked as able to reuse restricted prefetches
2055 // can use the entry in the cache now, since it has been evicted in favor of
2056 // an unrestricted one.
2057 RunTransactionTestWithResponseInfoAndGetTiming(
2058 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2059 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2060 EXPECT_FALSE(response_info.restricted_prefetch);
2061 EXPECT_TRUE(response_info.was_cached);
2062 EXPECT_FALSE(response_info.network_accessed);
2063 }
2064
TEST_F(HttpCacheTest,SimpleGET_UnusedSincePrefetchWriteError)2065 TEST_F(HttpCacheTest, SimpleGET_UnusedSincePrefetchWriteError) {
2066 MockHttpCache cache;
2067 HttpResponseInfo response_info;
2068
2069 // Do a prefetch.
2070 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
2071 prefetch_transaction.load_flags |= LOAD_PREFETCH;
2072 RunTransactionTestWithResponseInfoAndGetTiming(
2073 cache.http_cache(), prefetch_transaction, &response_info,
2074 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2075 EXPECT_TRUE(response_info.unused_since_prefetch);
2076 EXPECT_FALSE(response_info.was_cached);
2077
2078 // Try to use it while injecting a failure on write.
2079 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_WRITE);
2080 RunTransactionTestWithResponseInfoAndGetTiming(
2081 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2082 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2083 }
2084
2085 // Make sure that if a prefetch entry is truncated, then an attempt to re-use it
2086 // gets aborted in connected handler that truncated bit is not lost.
TEST_F(HttpCacheTest,PrefetchTruncateCancelInConnectedCallback)2087 TEST_F(HttpCacheTest, PrefetchTruncateCancelInConnectedCallback) {
2088 MockHttpCache cache;
2089
2090 ScopedMockTransaction transaction(kSimpleGET_Transaction);
2091 transaction.response_headers =
2092 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2093 "Content-Length: 20\n"
2094 "Etag: \"foopy\"\n";
2095 transaction.data = "01234567890123456789";
2096 transaction.load_flags |= LOAD_PREFETCH | LOAD_CAN_USE_RESTRICTED_PREFETCH;
2097
2098 // Do a truncated read of a prefetch request.
2099 {
2100 MockHttpRequest request(transaction);
2101 Context c;
2102
2103 int rv = cache.CreateTransaction(&c.trans);
2104 ASSERT_THAT(rv, IsOk());
2105
2106 rv = c.callback.GetResult(
2107 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2108 ASSERT_THAT(rv, IsOk());
2109
2110 // Read less than the whole thing.
2111 scoped_refptr<IOBufferWithSize> buf =
2112 base::MakeRefCounted<IOBufferWithSize>(10);
2113 rv = c.callback.GetResult(
2114 c.trans->Read(buf.get(), buf->size(), c.callback.callback()));
2115 EXPECT_EQ(buf->size(), rv);
2116
2117 // Destroy the transaction.
2118 c.trans.reset();
2119 base::RunLoop().RunUntilIdle();
2120
2121 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2122 /*data_size=*/10);
2123 }
2124
2125 // Do a fetch that can use prefetch that aborts in connected handler.
2126 transaction.load_flags &= ~LOAD_PREFETCH;
2127 {
2128 MockHttpRequest request(transaction);
2129 Context c;
2130
2131 int rv = cache.CreateTransaction(&c.trans);
2132 ASSERT_THAT(rv, IsOk());
2133 c.trans->SetConnectedCallback(base::BindRepeating(
2134 [](const TransportInfo& info, CompletionOnceCallback callback) -> int {
2135 return net::ERR_ABORTED;
2136 }));
2137 rv = c.callback.GetResult(
2138 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2139 EXPECT_EQ(net::ERR_ABORTED, rv);
2140
2141 // Destroy the transaction.
2142 c.trans.reset();
2143 base::RunLoop().RunUntilIdle();
2144
2145 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2146 /*data_size=*/10);
2147 }
2148
2149 // Now try again without abort.
2150 {
2151 MockHttpRequest request(transaction);
2152 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
2153 /*response_info=*/nullptr);
2154 base::RunLoop().RunUntilIdle();
2155
2156 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/false,
2157 /*data_size=*/20);
2158 }
2159 }
2160
2161 // Make sure that if a stale-while-revalidate entry is truncated, then an
2162 // attempt to re-use it gets aborted in connected handler that truncated bit is
2163 // not lost.
TEST_F(HttpCacheTest,StaleWhiteRevalidateTruncateCancelInConnectedCallback)2164 TEST_F(HttpCacheTest, StaleWhiteRevalidateTruncateCancelInConnectedCallback) {
2165 MockHttpCache cache;
2166
2167 ScopedMockTransaction transaction(kSimpleGET_Transaction);
2168 transaction.response_headers =
2169 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2170 "Content-Length: 20\n"
2171 "Cache-Control: max-age=0, stale-while-revalidate=60\n"
2172 "Etag: \"foopy\"\n";
2173 transaction.data = "01234567890123456789";
2174 transaction.load_flags |= LOAD_SUPPORT_ASYNC_REVALIDATION;
2175
2176 // Do a truncated read of a stale-while-revalidate resource.
2177 {
2178 MockHttpRequest request(transaction);
2179 Context c;
2180
2181 int rv = cache.CreateTransaction(&c.trans);
2182 ASSERT_THAT(rv, IsOk());
2183
2184 rv = c.callback.GetResult(
2185 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2186 ASSERT_THAT(rv, IsOk());
2187
2188 // Read less than the whole thing.
2189 scoped_refptr<IOBufferWithSize> buf =
2190 base::MakeRefCounted<IOBufferWithSize>(10);
2191 rv = c.callback.GetResult(
2192 c.trans->Read(buf.get(), buf->size(), c.callback.callback()));
2193 EXPECT_EQ(buf->size(), rv);
2194
2195 // Destroy the transaction.
2196 c.trans.reset();
2197 base::RunLoop().RunUntilIdle();
2198
2199 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2200 /*data_size=*/10);
2201 }
2202
2203 // Do a fetch that uses that resource that aborts in connected handler.
2204 {
2205 MockHttpRequest request(transaction);
2206 Context c;
2207
2208 int rv = cache.CreateTransaction(&c.trans);
2209 ASSERT_THAT(rv, IsOk());
2210 c.trans->SetConnectedCallback(base::BindRepeating(
2211 [](const TransportInfo& info, CompletionOnceCallback callback) -> int {
2212 return net::ERR_ABORTED;
2213 }));
2214 rv = c.callback.GetResult(
2215 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2216 EXPECT_EQ(net::ERR_ABORTED, rv);
2217
2218 // Destroy the transaction.
2219 c.trans.reset();
2220 base::RunLoop().RunUntilIdle();
2221
2222 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2223 /*data_size=*/10);
2224 }
2225
2226 // Now try again without abort.
2227 {
2228 MockHttpRequest request(transaction);
2229 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
2230 /*response_info=*/nullptr);
2231 base::RunLoop().RunUntilIdle();
2232
2233 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/false,
2234 /*data_size=*/20);
2235 }
2236 }
2237
PreserveRequestHeaders_Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)2238 static void PreserveRequestHeaders_Handler(const HttpRequestInfo* request,
2239 std::string* response_status,
2240 std::string* response_headers,
2241 std::string* response_data) {
2242 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
2243 }
2244
2245 // Tests that we don't remove extra headers for simple requests.
TEST_F(HttpCacheTest,SimpleGET_PreserveRequestHeaders)2246 TEST_F(HttpCacheTest, SimpleGET_PreserveRequestHeaders) {
2247 for (bool use_memory_entry_data : {false, true}) {
2248 MockHttpCache cache;
2249 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
2250
2251 MockTransaction transaction(kSimpleGET_Transaction);
2252 transaction.handler = PreserveRequestHeaders_Handler;
2253 transaction.request_headers = EXTRA_HEADER;
2254 transaction.response_headers = "Cache-Control: max-age=0\n";
2255 AddMockTransaction(&transaction);
2256
2257 // Write, then revalidate the entry.
2258 RunTransactionTest(cache.http_cache(), transaction);
2259 RunTransactionTest(cache.http_cache(), transaction);
2260
2261 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2262
2263 // If the backend supports memory entry data, we can figure out that the
2264 // entry has caching-hostile headers w/o opening it.
2265 if (use_memory_entry_data) {
2266 EXPECT_EQ(0, cache.disk_cache()->open_count());
2267 EXPECT_EQ(2, cache.disk_cache()->create_count());
2268 } else {
2269 EXPECT_EQ(1, cache.disk_cache()->open_count());
2270 EXPECT_EQ(1, cache.disk_cache()->create_count());
2271 }
2272 RemoveMockTransaction(&transaction);
2273 }
2274 }
2275
2276 // Tests that we don't remove extra headers for conditionalized requests.
TEST_F(HttpCacheTest,ConditionalizedGET_PreserveRequestHeaders)2277 TEST_F(HttpCacheTest, ConditionalizedGET_PreserveRequestHeaders) {
2278 for (bool use_memory_entry_data : {false, true}) {
2279 MockHttpCache cache;
2280 // Unlike in SimpleGET_PreserveRequestHeaders, this entry can be
2281 // conditionalized, so memory hints don't affect behavior.
2282 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
2283
2284 // Write to the cache.
2285 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
2286
2287 MockTransaction transaction(kETagGET_Transaction);
2288 transaction.handler = PreserveRequestHeaders_Handler;
2289 transaction.request_headers = "If-None-Match: \"foopy\"\r\n" EXTRA_HEADER;
2290 AddMockTransaction(&transaction);
2291
2292 RunTransactionTest(cache.http_cache(), transaction);
2293
2294 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2295 EXPECT_EQ(1, cache.disk_cache()->open_count());
2296 EXPECT_EQ(1, cache.disk_cache()->create_count());
2297 RemoveMockTransaction(&transaction);
2298 }
2299 }
2300
TEST_F(HttpCacheTest,SimpleGET_ManyReaders)2301 TEST_F(HttpCacheTest, SimpleGET_ManyReaders) {
2302 MockHttpCache cache;
2303
2304 MockHttpRequest request(kSimpleGET_Transaction);
2305
2306 std::vector<std::unique_ptr<Context>> context_list;
2307 const int kNumTransactions = 5;
2308
2309 for (int i = 0; i < kNumTransactions; ++i) {
2310 context_list.push_back(std::make_unique<Context>());
2311 auto& c = context_list[i];
2312
2313 c->result = cache.CreateTransaction(&c->trans);
2314 ASSERT_THAT(c->result, IsOk());
2315 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2316
2317 c->result =
2318 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2319 }
2320
2321 // All requests are waiting for the active entry.
2322 for (auto& context : context_list) {
2323 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
2324 }
2325
2326 // Allow all requests to move from the Create queue to the active entry.
2327 base::RunLoop().RunUntilIdle();
2328
2329 // All requests are added to writers.
2330 std::string cache_key = request.CacheKey();
2331 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
2332
2333 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2334 EXPECT_EQ(0, cache.disk_cache()->open_count());
2335 EXPECT_EQ(1, cache.disk_cache()->create_count());
2336
2337 // All requests are between Start and Read, i.e. idle.
2338 for (auto& context : context_list) {
2339 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
2340 }
2341
2342 for (int i = 0; i < kNumTransactions; ++i) {
2343 auto& c = context_list[i];
2344 if (c->result == ERR_IO_PENDING)
2345 c->result = c->callback.WaitForResult();
2346
2347 // After the 1st transaction has completed the response, all transactions
2348 // get added to readers.
2349 if (i > 0) {
2350 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
2351 EXPECT_EQ(kNumTransactions - i, cache.GetCountReaders(cache_key));
2352 }
2353
2354 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
2355 }
2356
2357 // We should not have had to re-open the disk entry
2358 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2359 EXPECT_EQ(0, cache.disk_cache()->open_count());
2360 EXPECT_EQ(1, cache.disk_cache()->create_count());
2361 }
2362
TEST_F(HttpCacheTest,RangeGET_FullAfterPartial)2363 TEST_F(HttpCacheTest, RangeGET_FullAfterPartial) {
2364 MockHttpCache cache;
2365
2366 // Request a prefix.
2367 {
2368 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2369 transaction_pre.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
2370 transaction_pre.data = "rg: 00-09 ";
2371 MockHttpRequest request_pre(transaction_pre);
2372
2373 HttpResponseInfo response_pre;
2374 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2375 request_pre, &response_pre);
2376 ASSERT_TRUE(response_pre.headers != nullptr);
2377 EXPECT_EQ(206, response_pre.headers->response_code());
2378 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2379 EXPECT_EQ(0, cache.disk_cache()->open_count());
2380 EXPECT_EQ(1, cache.disk_cache()->create_count());
2381 }
2382
2383 {
2384 // Now request the full thing, but set validation to fail. This would
2385 // previously fail in the middle of data and truncate it; current behavior
2386 // restarts it, somewhat wastefully but gets the data back.
2387 RangeTransactionServer handler;
2388 handler.set_modified(true);
2389
2390 ScopedMockTransaction transaction_all(kRangeGET_TransactionOK);
2391 transaction_all.request_headers = EXTRA_HEADER;
2392 transaction_all.data = "Not a range";
2393 MockHttpRequest request_all(transaction_all);
2394
2395 HttpResponseInfo response_all;
2396 RunTransactionTestWithRequest(cache.http_cache(), transaction_all,
2397 request_all, &response_all);
2398 ASSERT_TRUE(response_all.headers != nullptr);
2399 EXPECT_EQ(200, response_all.headers->response_code());
2400 // 1 from previous test, failed validation, and re-try.
2401 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2402 EXPECT_EQ(1, cache.disk_cache()->open_count());
2403 EXPECT_EQ(1, cache.disk_cache()->create_count());
2404 }
2405 }
2406
2407 // Tests that when a range request transaction becomes a writer for the first
2408 // range and then fails conditionalization for the next range and decides to
2409 // doom the entry, then there should not be a dcheck assertion hit.
TEST_F(HttpCacheTest,RangeGET_OverlappingRangesCouldntConditionalize)2410 TEST_F(HttpCacheTest, RangeGET_OverlappingRangesCouldntConditionalize) {
2411 MockHttpCache cache;
2412
2413 {
2414 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2415 transaction_pre.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2416 transaction_pre.data = "rg: 10-19 ";
2417 MockHttpRequest request_pre(transaction_pre);
2418
2419 HttpResponseInfo response_pre;
2420 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2421 request_pre, &response_pre);
2422 ASSERT_TRUE(response_pre.headers != nullptr);
2423 EXPECT_EQ(206, response_pre.headers->response_code());
2424 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2425 EXPECT_EQ(0, cache.disk_cache()->open_count());
2426 EXPECT_EQ(1, cache.disk_cache()->create_count());
2427 }
2428
2429 {
2430 // First range skips validation because the response is fresh while the
2431 // second range requires validation since that range is not present in the
2432 // cache and during validation it fails conditionalization.
2433 cache.FailConditionalizations();
2434 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2435 transaction_pre.request_headers = "Range: bytes = 10-29\r\n" EXTRA_HEADER;
2436
2437 // TODO(crbug.com/992521): Fix this scenario to not return the cached bytes
2438 // repeatedly.
2439 transaction_pre.data = "rg: 10-19 rg: 10-19 rg: 20-29 ";
2440 MockHttpRequest request_pre(transaction_pre);
2441 HttpResponseInfo response_pre;
2442 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2443 request_pre, &response_pre);
2444 ASSERT_TRUE(response_pre.headers != nullptr);
2445 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2446 EXPECT_EQ(1, cache.disk_cache()->open_count());
2447 EXPECT_EQ(2, cache.disk_cache()->create_count());
2448 }
2449 }
2450
TEST_F(HttpCacheTest,RangeGET_FullAfterPartialReuse)2451 TEST_F(HttpCacheTest, RangeGET_FullAfterPartialReuse) {
2452 MockHttpCache cache;
2453
2454 // Request a prefix.
2455 {
2456 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2457 transaction_pre.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
2458 transaction_pre.data = "rg: 00-09 ";
2459 MockHttpRequest request_pre(transaction_pre);
2460
2461 HttpResponseInfo response_pre;
2462 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2463 request_pre, &response_pre);
2464 ASSERT_TRUE(response_pre.headers != nullptr);
2465 EXPECT_EQ(206, response_pre.headers->response_code());
2466 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2467 EXPECT_EQ(0, cache.disk_cache()->open_count());
2468 EXPECT_EQ(1, cache.disk_cache()->create_count());
2469 }
2470
2471 {
2472 // Now request the full thing, revalidating successfully, so the full
2473 // file gets stored via a sparse-entry.
2474 ScopedMockTransaction transaction_all(kRangeGET_TransactionOK);
2475 transaction_all.request_headers = EXTRA_HEADER;
2476 transaction_all.data =
2477 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49"
2478 " rg: 50-59 rg: 60-69 rg: 70-79 ";
2479 MockHttpRequest request_all(transaction_all);
2480
2481 HttpResponseInfo response_all;
2482 RunTransactionTestWithRequest(cache.http_cache(), transaction_all,
2483 request_all, &response_all);
2484 ASSERT_TRUE(response_all.headers != nullptr);
2485 EXPECT_EQ(200, response_all.headers->response_code());
2486 // 1 from previous test, validation, and second chunk
2487 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2488 EXPECT_EQ(1, cache.disk_cache()->open_count());
2489 EXPECT_EQ(1, cache.disk_cache()->create_count());
2490 }
2491
2492 {
2493 // Grab it again, should not need re-validation.
2494 ScopedMockTransaction transaction_all2(kRangeGET_TransactionOK);
2495 transaction_all2.request_headers = EXTRA_HEADER;
2496 transaction_all2.data =
2497 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49"
2498 " rg: 50-59 rg: 60-69 rg: 70-79 ";
2499 MockHttpRequest request_all2(transaction_all2);
2500
2501 HttpResponseInfo response_all2;
2502 RunTransactionTestWithRequest(cache.http_cache(), transaction_all2,
2503 request_all2, &response_all2);
2504 ASSERT_TRUE(response_all2.headers != nullptr);
2505 EXPECT_EQ(200, response_all2.headers->response_code());
2506
2507 // Only one more cache open, no new network traffic.
2508 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2509 EXPECT_EQ(2, cache.disk_cache()->open_count());
2510 EXPECT_EQ(1, cache.disk_cache()->create_count());
2511 }
2512 }
2513
2514 // This test verifies that the ConnectedCallback passed to a cache transaction
2515 // is called once per subrange in the case of a range request with a partial
2516 // cache hit.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackCalledForEachRange)2517 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackCalledForEachRange) {
2518 MockHttpCache cache;
2519
2520 // Request an infix range and populate the cache with it.
2521 {
2522 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2523 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2524 mock_transaction.data = "rg: 20-29 ";
2525 mock_transaction.transport_info = TestTransportInfo();
2526
2527 RunTransactionTest(cache.http_cache(), mock_transaction);
2528 }
2529
2530 // Request a surrounding range and observe that the callback is called once
2531 // per subrange, as split up by cache hits.
2532 {
2533 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2534 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2535 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2536 mock_transaction.transport_info = TestTransportInfo();
2537 MockHttpRequest request(mock_transaction);
2538
2539 ConnectedHandler connected_handler;
2540
2541 std::unique_ptr<HttpTransaction> transaction;
2542 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2543 ASSERT_THAT(transaction, NotNull());
2544
2545 transaction->SetConnectedCallback(connected_handler.Callback());
2546
2547 TestCompletionCallback callback;
2548 ASSERT_THAT(
2549 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2550 IsError(ERR_IO_PENDING));
2551 EXPECT_THAT(callback.WaitForResult(), IsOk());
2552
2553 // 1 call for the first range's network transaction.
2554 EXPECT_THAT(connected_handler.transports(),
2555 ElementsAre(TestTransportInfo()));
2556
2557 // Switch the endpoint for the next network transaction to observe.
2558 // For ease, we just switch the port number.
2559 //
2560 // NOTE: This works because only the mock transaction struct's address is
2561 // registered with the mocking framework - the pointee data is consulted
2562 // each time it is read.
2563 mock_transaction.transport_info = TestTransportInfoWithPort(123);
2564
2565 ReadAndVerifyTransaction(transaction.get(), mock_transaction);
2566
2567 // A second call for the cached range, reported as coming from the original
2568 // endpoint it was cached from. A third call for the last range's network
2569 // transaction.
2570 EXPECT_THAT(connected_handler.transports(),
2571 ElementsAre(TestTransportInfo(), CachedTestTransportInfo(),
2572 TestTransportInfoWithPort(123)));
2573 }
2574 }
2575
2576 // This test verifies that when the ConnectedCallback passed to a cache range
2577 // transaction returns an `ERR_INCONSISTENT_IP_ADDRESS_SPACE` error during a
2578 // partial read from cache, then the cache entry is invalidated.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnInconsistentIpError)2579 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackReturnInconsistentIpError) {
2580 MockHttpCache cache;
2581
2582 // Request an infix range and populate the cache with it.
2583 {
2584 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2585 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2586 mock_transaction.data = "rg: 20-29 ";
2587 mock_transaction.transport_info = TestTransportInfo();
2588
2589 RunTransactionTest(cache.http_cache(), mock_transaction);
2590 }
2591
2592 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2593 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2594 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2595 mock_transaction.transport_info = TestTransportInfo();
2596 MockHttpRequest request(mock_transaction);
2597
2598 // Request a surrounding range. This *should* be read in three parts:
2599 //
2600 // 1. for the prefix: from the network
2601 // 2. for the cached infix: from the cache
2602 // 3. for the suffix: from the network
2603 //
2604 // The connected callback returns OK for 1), but fails during 2). As a result,
2605 // the transaction fails partway and 3) is never created. The cache entry is
2606 // invalidated as a result of the specific error code.
2607 {
2608 ConnectedHandler connected_handler;
2609
2610 std::unique_ptr<HttpTransaction> transaction;
2611 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2612 ASSERT_THAT(transaction, NotNull());
2613
2614 transaction->SetConnectedCallback(connected_handler.Callback());
2615
2616 TestCompletionCallback callback;
2617 ASSERT_THAT(
2618 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2619 IsError(ERR_IO_PENDING));
2620 EXPECT_THAT(callback.WaitForResult(), IsOk());
2621
2622 // 1 call for the first range's network transaction.
2623 EXPECT_THAT(connected_handler.transports(),
2624 ElementsAre(TestTransportInfo()));
2625
2626 // Set the callback to return an error the next time it is called.
2627 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
2628
2629 std::string content;
2630 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2631 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
2632
2633 // A second call that failed.
2634 EXPECT_THAT(connected_handler.transports(),
2635 ElementsAre(TestTransportInfo(), CachedTestTransportInfo()));
2636 }
2637
2638 // Request the same range again, observe that nothing is read from cache.
2639 {
2640 ConnectedHandler connected_handler;
2641
2642 std::unique_ptr<HttpTransaction> transaction;
2643 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2644 ASSERT_THAT(transaction, NotNull());
2645
2646 transaction->SetConnectedCallback(connected_handler.Callback());
2647
2648 TestCompletionCallback callback;
2649 ASSERT_THAT(
2650 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2651 IsError(ERR_IO_PENDING));
2652 EXPECT_THAT(callback.WaitForResult(), IsOk());
2653
2654 std::string content;
2655 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2656 EXPECT_EQ(content, mock_transaction.data);
2657
2658 // 1 call for the network transaction from which the whole response was
2659 // read. The first 20 bytes were cached by the previous two requests, but
2660 // the cache entry was doomed during the last transaction so they are not
2661 // used here.
2662 EXPECT_THAT(connected_handler.transports(),
2663 ElementsAre(TestTransportInfo()));
2664 }
2665 }
2666
2667 // This test verifies that when the ConnectedCallback passed to a cache range
2668 // transaction returns an `ERR_INCONSISTENT_IP_ADDRESS_SPACE` error during a
2669 // network transaction, then the cache entry is invalidated.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnInconsistentIpErrorForNetwork)2670 TEST_F(HttpCacheTest,
2671 RangeGET_ConnectedCallbackReturnInconsistentIpErrorForNetwork) {
2672 MockHttpCache cache;
2673
2674 // Request a prefix range and populate the cache with it.
2675 {
2676 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2677 mock_transaction.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2678 mock_transaction.data = "rg: 10-19 ";
2679 mock_transaction.transport_info = TestTransportInfo();
2680
2681 RunTransactionTest(cache.http_cache(), mock_transaction);
2682 }
2683
2684 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2685 mock_transaction.request_headers = "Range: bytes = 10-29\r\n" EXTRA_HEADER;
2686 mock_transaction.data = "rg: 10-19 rg: 20-29 ";
2687 mock_transaction.transport_info = TestTransportInfo();
2688 MockHttpRequest request(mock_transaction);
2689
2690 // Request a longer range. This *should* be read in two parts:
2691 //
2692 // 1. for the prefix: from the cache
2693 // 2. for the suffix: from the network
2694 {
2695 ConnectedHandler connected_handler;
2696
2697 std::unique_ptr<HttpTransaction> transaction;
2698 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2699 ASSERT_THAT(transaction, NotNull());
2700
2701 transaction->SetConnectedCallback(connected_handler.Callback());
2702
2703 TestCompletionCallback callback;
2704 ASSERT_THAT(
2705 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2706 IsError(ERR_IO_PENDING));
2707 EXPECT_THAT(callback.WaitForResult(), IsOk());
2708
2709 // 1 call for the first range's network transaction.
2710 EXPECT_THAT(connected_handler.transports(),
2711 ElementsAre(CachedTestTransportInfo()));
2712
2713 // Set the callback to return an error the next time it is called.
2714 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
2715
2716 std::string content;
2717 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2718 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
2719
2720 // A second call that failed.
2721 EXPECT_THAT(connected_handler.transports(),
2722 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
2723 }
2724
2725 // Request the same range again, observe that nothing is read from cache.
2726 {
2727 ConnectedHandler connected_handler;
2728
2729 std::unique_ptr<HttpTransaction> transaction;
2730 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2731 ASSERT_THAT(transaction, NotNull());
2732
2733 transaction->SetConnectedCallback(connected_handler.Callback());
2734
2735 TestCompletionCallback callback;
2736 ASSERT_THAT(
2737 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2738 IsError(ERR_IO_PENDING));
2739 EXPECT_THAT(callback.WaitForResult(), IsOk());
2740
2741 std::string content;
2742 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2743 EXPECT_EQ(content, mock_transaction.data);
2744
2745 // 1 call for the network transaction from which the whole response was
2746 // read. The first 20 bytes were cached by the previous two requests, but
2747 // the cache entry was doomed during the last transaction so they are not
2748 // used here.
2749 EXPECT_THAT(connected_handler.transports(),
2750 ElementsAre(TestTransportInfo()));
2751 }
2752 }
2753
2754 // This test verifies that when the ConnectedCallback passed to a cache
2755 // transaction returns an error for the second (or third) subrange transaction,
2756 // the overall cache transaction fails with that error. The cache entry is still
2757 // usable after that.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnErrorSecondTime)2758 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackReturnErrorSecondTime) {
2759 MockHttpCache cache;
2760
2761 // Request an infix range and populate the cache with it.
2762 {
2763 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2764 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2765 mock_transaction.data = "rg: 20-29 ";
2766 mock_transaction.transport_info = TestTransportInfo();
2767
2768 RunTransactionTest(cache.http_cache(), mock_transaction);
2769 }
2770
2771 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2772 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2773 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2774 mock_transaction.transport_info = TestTransportInfo();
2775 MockHttpRequest request(mock_transaction);
2776
2777 // Request a surrounding range. This *should* be read in three parts:
2778 //
2779 // 1. for the prefix: from the network
2780 // 2. for the cached infix: from the cache
2781 // 3. for the suffix: from the network
2782 //
2783 // The connected callback returns OK for 1), but fails during 2). As a result,
2784 // the transaction fails partway and 3) is never created. The prefix is still
2785 // cached, such that the cache entry ends up with both the prefix and infix.
2786 {
2787 ConnectedHandler connected_handler;
2788
2789 std::unique_ptr<HttpTransaction> transaction;
2790 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2791 ASSERT_THAT(transaction, NotNull());
2792
2793 transaction->SetConnectedCallback(connected_handler.Callback());
2794
2795 TestCompletionCallback callback;
2796 ASSERT_THAT(
2797 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2798 IsError(ERR_IO_PENDING));
2799 EXPECT_THAT(callback.WaitForResult(), IsOk());
2800
2801 // 1 call for the first range's network transaction.
2802 EXPECT_THAT(connected_handler.transports(),
2803 ElementsAre(TestTransportInfo()));
2804
2805 // Set the callback to return an error the next time it is called. The exact
2806 // error code is irrelevant, what matters is that it is reflected in the
2807 // overall status of the transaction.
2808 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
2809
2810 std::string content;
2811 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2812 IsError(ERR_NOT_IMPLEMENTED));
2813
2814 // A second call that failed.
2815 EXPECT_THAT(connected_handler.transports(),
2816 ElementsAre(TestTransportInfo(), CachedTestTransportInfo()));
2817 }
2818
2819 // Request the same range again, observe that the prefix and infix are both
2820 // read from cache. Only the suffix is fetched from the network.
2821 {
2822 ConnectedHandler connected_handler;
2823
2824 std::unique_ptr<HttpTransaction> transaction;
2825 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2826 ASSERT_THAT(transaction, NotNull());
2827
2828 transaction->SetConnectedCallback(connected_handler.Callback());
2829
2830 TestCompletionCallback callback;
2831 ASSERT_THAT(
2832 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2833 IsError(ERR_IO_PENDING));
2834 EXPECT_THAT(callback.WaitForResult(), IsOk());
2835
2836 // 1 call for the first range's cache transaction: the first 20 bytes were
2837 // cached by the previous two requests.
2838 EXPECT_THAT(connected_handler.transports(),
2839 ElementsAre(CachedTestTransportInfo()));
2840
2841 std::string content;
2842 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2843 EXPECT_EQ(content, mock_transaction.data);
2844
2845 // A second call from the network transaction for the last 10 bytes.
2846 EXPECT_THAT(connected_handler.transports(),
2847 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
2848 }
2849 }
2850
2851 // This test verifies that the ConnectedCallback passed to a cache transaction
2852 // is called once per subrange in the case of a range request with a partial
2853 // cache hit, even when a prefix of the range is cached.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackCalledForEachRangeWithPrefix)2854 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackCalledForEachRangeWithPrefix) {
2855 MockHttpCache cache;
2856
2857 // Request a prefix range and populate the cache with it.
2858 {
2859 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2860 mock_transaction.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2861 mock_transaction.data = "rg: 10-19 ";
2862 mock_transaction.transport_info = TestTransportInfo();
2863
2864 RunTransactionTest(cache.http_cache(), mock_transaction);
2865 }
2866
2867 // Request a surrounding range and observe that the callback is called once
2868 // per subrange, as split up by cache hits.
2869 {
2870 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2871 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2872 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2873 mock_transaction.transport_info = TestTransportInfoWithPort(123);
2874 MockHttpRequest request(mock_transaction);
2875
2876 ConnectedHandler connected_handler;
2877
2878 std::unique_ptr<HttpTransaction> transaction;
2879 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2880 ASSERT_THAT(transaction, NotNull());
2881
2882 transaction->SetConnectedCallback(connected_handler.Callback());
2883
2884 TestCompletionCallback callback;
2885 ASSERT_THAT(
2886 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2887 IsError(ERR_IO_PENDING));
2888 EXPECT_THAT(callback.WaitForResult(), IsOk());
2889
2890 // 1 call for the first range from the cache, reported as coming from the
2891 // endpoint which initially served the cached range.
2892 EXPECT_THAT(connected_handler.transports(),
2893 ElementsAre(CachedTestTransportInfo()));
2894
2895 ReadAndVerifyTransaction(transaction.get(), mock_transaction);
2896
2897 // A second call for the last range's network transaction.
2898 EXPECT_THAT(
2899 connected_handler.transports(),
2900 ElementsAre(CachedTestTransportInfo(), TestTransportInfoWithPort(123)));
2901 }
2902 }
2903
2904 // Tests that a range transaction is still usable even if it's unable to access
2905 // the cache.
TEST_F(HttpCacheTest,RangeGET_FailedCacheAccess)2906 TEST_F(HttpCacheTest, RangeGET_FailedCacheAccess) {
2907 MockHttpCache cache;
2908
2909 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
2910 MockHttpRequest request(transaction);
2911
2912 auto c = std::make_unique<Context>();
2913 c->result = cache.CreateTransaction(&c->trans);
2914 ASSERT_THAT(c->result, IsOk());
2915 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2916
2917 cache.disk_cache()->set_fail_requests(true);
2918
2919 c->result =
2920 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2921
2922 base::RunLoop().RunUntilIdle();
2923
2924 EXPECT_FALSE(cache.IsWriterPresent(kRangeGET_TransactionOK.url));
2925
2926 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2927 EXPECT_EQ(0, cache.disk_cache()->open_count());
2928 EXPECT_EQ(0, cache.disk_cache()->create_count());
2929
2930 c->result = c->callback.WaitForResult();
2931
2932 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
2933
2934 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2935 EXPECT_EQ(0, cache.disk_cache()->open_count());
2936 EXPECT_EQ(0, cache.disk_cache()->create_count());
2937 }
2938
2939 // Tests that we can have parallel validation on range requests.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatch)2940 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatch) {
2941 MockHttpCache cache;
2942
2943 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
2944 MockHttpRequest request(transaction);
2945
2946 std::vector<std::unique_ptr<Context>> context_list;
2947 const int kNumTransactions = 5;
2948
2949 for (int i = 0; i < kNumTransactions; ++i) {
2950 context_list.push_back(std::make_unique<Context>());
2951 auto& c = context_list[i];
2952
2953 c->result = cache.CreateTransaction(&c->trans);
2954 ASSERT_THAT(c->result, IsOk());
2955 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2956
2957 c->result =
2958 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2959 }
2960
2961 // All requests are waiting for the active entry.
2962 for (auto& context : context_list) {
2963 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
2964 }
2965
2966 // Allow all requests to move from the Create queue to the active entry.
2967 base::RunLoop().RunUntilIdle();
2968
2969 // First entry created is doomed due to 2nd transaction's validation leading
2970 // to restarting of the queued transactions.
2971 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
2972
2973 // TODO(shivanisha): The restarted transactions race for creating the entry
2974 // and thus instead of all 4 succeeding, 2 of them succeed. This is very
2975 // implementation specific and happens because the queued transactions get
2976 // restarted synchronously and get to the queue of creating the entry before
2977 // the transaction that is restarting them. Fix the test to make it less
2978 // vulnerable to any scheduling changes in the code.
2979 EXPECT_EQ(5, cache.network_layer()->transaction_count());
2980 EXPECT_EQ(0, cache.disk_cache()->open_count());
2981 EXPECT_EQ(3, cache.disk_cache()->create_count());
2982
2983 for (auto& context : context_list) {
2984 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
2985 }
2986
2987 for (int i = 0; i < kNumTransactions; ++i) {
2988 auto& c = context_list[i];
2989 if (c->result == ERR_IO_PENDING)
2990 c->result = c->callback.WaitForResult();
2991
2992 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
2993 }
2994
2995 EXPECT_EQ(5, cache.network_layer()->transaction_count());
2996 EXPECT_EQ(0, cache.disk_cache()->open_count());
2997 EXPECT_EQ(3, cache.disk_cache()->create_count());
2998 }
2999
3000 // Tests that if a transaction is dooming the entry and the entry was doomed by
3001 // another transaction that was not part of the entry and created a new entry,
3002 // the new entry should not be incorrectly doomed. (crbug.com/736993)
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatchDoomEntry)3003 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatchDoomEntry) {
3004 MockHttpCache cache;
3005
3006 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3007 MockHttpRequest request(transaction);
3008
3009 MockTransaction dooming_transaction(kRangeGET_TransactionOK);
3010 dooming_transaction.load_flags |= LOAD_BYPASS_CACHE;
3011 MockHttpRequest dooming_request(dooming_transaction);
3012
3013 std::vector<std::unique_ptr<Context>> context_list;
3014 const int kNumTransactions = 3;
3015
3016 scoped_refptr<MockDiskEntry> first_entry;
3017 scoped_refptr<MockDiskEntry> second_entry;
3018 for (int i = 0; i < kNumTransactions; ++i) {
3019 context_list.push_back(std::make_unique<Context>());
3020 auto& c = context_list[i];
3021
3022 c->result = cache.CreateTransaction(&c->trans);
3023 ASSERT_THAT(c->result, IsOk());
3024 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3025
3026 MockHttpRequest* this_request = &request;
3027
3028 if (i == 2)
3029 this_request = &dooming_request;
3030
3031 if (i == 1) {
3032 ASSERT_TRUE(first_entry);
3033 first_entry->SetDefer(MockDiskEntry::DEFER_READ);
3034 }
3035
3036 c->result = c->trans->Start(this_request, c->callback.callback(),
3037 NetLogWithSource());
3038
3039 // Continue the transactions. 2nd will pause at the cache reading state and
3040 // 3rd transaction will doom the entry.
3041 base::RunLoop().RunUntilIdle();
3042
3043 std::string cache_key = request.CacheKey();
3044 // Check status of the first and second entries after every transaction.
3045 switch (i) {
3046 case 0:
3047 first_entry = cache.disk_cache()->GetDiskEntryRef(cache_key);
3048 break;
3049 case 1:
3050 EXPECT_FALSE(first_entry->is_doomed());
3051 break;
3052 case 2:
3053 EXPECT_TRUE(first_entry->is_doomed());
3054 second_entry = cache.disk_cache()->GetDiskEntryRef(cache_key);
3055 EXPECT_FALSE(second_entry->is_doomed());
3056 break;
3057 }
3058 }
3059 // Resume cache read by 1st transaction which will lead to dooming the entry
3060 // as well since the entry cannot be validated. This double dooming should not
3061 // lead to an assertion.
3062 first_entry->ResumeDiskEntryOperation();
3063 base::RunLoop().RunUntilIdle();
3064
3065 // Since second_entry is already created, when 1st transaction goes on to
3066 // create an entry, it will get ERR_CACHE_RACE leading to dooming of
3067 // second_entry and creation of a third entry.
3068 EXPECT_TRUE(second_entry->is_doomed());
3069
3070 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3071 EXPECT_EQ(0, cache.disk_cache()->open_count());
3072 EXPECT_EQ(3, cache.disk_cache()->create_count());
3073
3074 for (auto& context : context_list) {
3075 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3076 }
3077
3078 for (auto& c : context_list) {
3079 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
3080 }
3081
3082 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3083 EXPECT_EQ(0, cache.disk_cache()->open_count());
3084 EXPECT_EQ(3, cache.disk_cache()->create_count());
3085 }
3086
3087 // Same as above but tests that the 2nd transaction does not do anything if
3088 // there is nothing to doom. (crbug.com/736993)
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatchDoomEntry1)3089 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatchDoomEntry1) {
3090 MockHttpCache cache;
3091
3092 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3093 MockHttpRequest request(transaction);
3094
3095 MockTransaction dooming_transaction(kRangeGET_TransactionOK);
3096 dooming_transaction.load_flags |= LOAD_BYPASS_CACHE;
3097 MockHttpRequest dooming_request(dooming_transaction);
3098
3099 std::vector<std::unique_ptr<Context>> context_list;
3100 const int kNumTransactions = 3;
3101
3102 scoped_refptr<MockDiskEntry> first_entry;
3103 for (int i = 0; i < kNumTransactions; ++i) {
3104 context_list.push_back(std::make_unique<Context>());
3105 auto& c = context_list[i];
3106
3107 c->result = cache.CreateTransaction(&c->trans);
3108 ASSERT_THAT(c->result, IsOk());
3109 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3110
3111 MockHttpRequest* this_request = &request;
3112
3113 if (i == 2) {
3114 this_request = &dooming_request;
3115 cache.disk_cache()->SetDefer(MockDiskEntry::DEFER_CREATE);
3116 }
3117
3118 if (i == 1) {
3119 ASSERT_TRUE(first_entry);
3120 first_entry->SetDefer(MockDiskEntry::DEFER_READ);
3121 }
3122
3123 c->result = c->trans->Start(this_request, c->callback.callback(),
3124 NetLogWithSource());
3125
3126 // Continue the transactions. 2nd will pause at the cache reading state and
3127 // 3rd transaction will doom the entry and pause before creating a new
3128 // entry.
3129 base::RunLoop().RunUntilIdle();
3130
3131 // Check status of the entry after every transaction.
3132 switch (i) {
3133 case 0:
3134 first_entry = cache.disk_cache()->GetDiskEntryRef(request.CacheKey());
3135 break;
3136 case 1:
3137 EXPECT_FALSE(first_entry->is_doomed());
3138 break;
3139 case 2:
3140 EXPECT_TRUE(first_entry->is_doomed());
3141 break;
3142 }
3143 }
3144 // Resume cache read by 2nd transaction which will lead to dooming the entry
3145 // as well since the entry cannot be validated. This double dooming should not
3146 // lead to an assertion.
3147 first_entry->ResumeDiskEntryOperation();
3148 base::RunLoop().RunUntilIdle();
3149
3150 // Resume creation of entry by 3rd transaction.
3151 cache.disk_cache()->ResumeCacheOperation();
3152 base::RunLoop().RunUntilIdle();
3153
3154 // Note that since 3rd transaction's entry is already created but its
3155 // callback is deferred, MockDiskCache's implementation returns
3156 // ERR_CACHE_CREATE_FAILURE when 2nd transaction tries to create an entry
3157 // during that time, leading to it switching over to pass-through mode.
3158 // Thus the number of entries is 2 below.
3159 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3160 EXPECT_EQ(0, cache.disk_cache()->open_count());
3161 EXPECT_EQ(2, cache.disk_cache()->create_count());
3162
3163 for (auto& context : context_list) {
3164 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3165 }
3166
3167 for (auto& c : context_list) {
3168 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
3169 }
3170
3171 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3172 EXPECT_EQ(0, cache.disk_cache()->open_count());
3173 EXPECT_EQ(2, cache.disk_cache()->create_count());
3174 }
3175
3176 // Tests parallel validation on range requests with non-overlapping ranges.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationDifferentRanges)3177 TEST_F(HttpCacheTest, RangeGET_ParallelValidationDifferentRanges) {
3178 MockHttpCache cache;
3179
3180 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3181
3182 std::vector<std::unique_ptr<Context>> context_list;
3183 const int kNumTransactions = 2;
3184
3185 for (int i = 0; i < kNumTransactions; ++i) {
3186 context_list.push_back(std::make_unique<Context>());
3187 }
3188
3189 // Let 1st transaction complete headers phase for ranges 40-49.
3190 std::string first_read;
3191 MockHttpRequest request1(transaction);
3192 {
3193 auto& c = context_list[0];
3194 c->result = cache.CreateTransaction(&c->trans);
3195 ASSERT_THAT(c->result, IsOk());
3196 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3197
3198 c->result =
3199 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3200 base::RunLoop().RunUntilIdle();
3201
3202 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3203 // true.
3204 const int kBufferSize = 5;
3205 scoped_refptr<IOBuffer> buffer =
3206 base::MakeRefCounted<IOBuffer>(kBufferSize);
3207 ReleaseBufferCompletionCallback cb(buffer.get());
3208 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3209 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3210
3211 std::string data_read(buffer->data(), kBufferSize);
3212 first_read = data_read;
3213
3214 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3215 }
3216
3217 // 2nd transaction requests ranges 30-39.
3218 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
3219 MockHttpRequest request2(transaction);
3220 {
3221 auto& c = context_list[1];
3222 c->result = cache.CreateTransaction(&c->trans);
3223 ASSERT_THAT(c->result, IsOk());
3224 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3225
3226 c->result =
3227 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3228 base::RunLoop().RunUntilIdle();
3229
3230 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3231 }
3232
3233 std::string cache_key = request2.CacheKey();
3234 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3235 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3236
3237 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3238 EXPECT_EQ(0, cache.disk_cache()->open_count());
3239 EXPECT_EQ(1, cache.disk_cache()->create_count());
3240
3241 for (int i = 0; i < kNumTransactions; ++i) {
3242 auto& c = context_list[i];
3243 if (c->result == ERR_IO_PENDING)
3244 c->result = c->callback.WaitForResult();
3245
3246 if (i == 0) {
3247 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3248 transaction);
3249 continue;
3250 }
3251
3252 transaction.data = "rg: 30-39 ";
3253 ReadAndVerifyTransaction(c->trans.get(), transaction);
3254 }
3255
3256 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3257 EXPECT_EQ(0, cache.disk_cache()->open_count());
3258 EXPECT_EQ(1, cache.disk_cache()->create_count());
3259
3260 // Fetch from the cache to check that ranges 30-49 have been successfully
3261 // cached.
3262 {
3263 MockTransaction range_transaction(kRangeGET_TransactionOK);
3264 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3265 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3266 std::string headers;
3267 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3268 &headers);
3269 Verify206Response(headers, 30, 49);
3270 }
3271
3272 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3273 EXPECT_EQ(1, cache.disk_cache()->open_count());
3274 EXPECT_EQ(1, cache.disk_cache()->create_count());
3275
3276 context_list.clear();
3277 }
3278
3279 // Tests that a request does not create Writers when readers is not empty.
TEST_F(HttpCacheTest,RangeGET_DoNotCreateWritersWhenReaderExists)3280 TEST_F(HttpCacheTest, RangeGET_DoNotCreateWritersWhenReaderExists) {
3281 MockHttpCache cache;
3282
3283 // Save a request in the cache so that the next request can become a
3284 // reader.
3285 MockTransaction transaction(kRangeGET_Transaction);
3286 transaction.request_headers = EXTRA_HEADER;
3287 AddMockTransaction(&transaction);
3288 RunTransactionTest(cache.http_cache(), transaction);
3289
3290 // Let this request be a reader since it doesn't need validation as per its
3291 // load flag.
3292 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
3293 MockHttpRequest request(transaction);
3294 Context context;
3295 context.result = cache.CreateTransaction(&context.trans);
3296 ASSERT_THAT(context.result, IsOk());
3297 context.result = context.trans->Start(&request, context.callback.callback(),
3298 NetLogWithSource());
3299 base::RunLoop().RunUntilIdle();
3300 std::string cache_key = request.CacheKey();
3301 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
3302 RemoveMockTransaction(&transaction);
3303
3304 // A range request should now "not" create Writers while readers is still
3305 // non-empty.
3306 MockTransaction range_transaction(kRangeGET_Transaction);
3307 range_transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
3308 AddMockTransaction(&range_transaction);
3309 MockHttpRequest range_request(range_transaction);
3310 Context range_context;
3311 range_context.result = cache.CreateTransaction(&range_context.trans);
3312 ASSERT_THAT(range_context.result, IsOk());
3313 range_context.result = range_context.trans->Start(
3314 &range_request, range_context.callback.callback(), NetLogWithSource());
3315 base::RunLoop().RunUntilIdle();
3316
3317 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
3318 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
3319 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3320
3321 RemoveMockTransaction(&range_transaction);
3322 }
3323
3324 // Tests parallel validation on range requests can be successfully restarted
3325 // when there is a cache lock timeout.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCacheLockTimeout)3326 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCacheLockTimeout) {
3327 MockHttpCache cache;
3328
3329 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3330
3331 std::vector<std::unique_ptr<Context>> context_list;
3332 const int kNumTransactions = 2;
3333
3334 for (int i = 0; i < kNumTransactions; ++i) {
3335 context_list.push_back(std::make_unique<Context>());
3336 }
3337
3338 // Let 1st transaction complete headers phase for ranges 40-49.
3339 std::string first_read;
3340 MockHttpRequest request1(transaction);
3341 {
3342 auto& c = context_list[0];
3343 c->result = cache.CreateTransaction(&c->trans);
3344 ASSERT_THAT(c->result, IsOk());
3345 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3346
3347 c->result =
3348 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3349 base::RunLoop().RunUntilIdle();
3350
3351 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3352 // true.
3353 const int kBufferSize = 5;
3354 scoped_refptr<IOBuffer> buffer =
3355 base::MakeRefCounted<IOBuffer>(kBufferSize);
3356 ReleaseBufferCompletionCallback cb(buffer.get());
3357 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3358 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3359
3360 std::string data_read(buffer->data(), kBufferSize);
3361 first_read = data_read;
3362
3363 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3364 }
3365
3366 // Cache lock timeout will lead to dooming the entry since the transaction may
3367 // have already written the headers.
3368 cache.SimulateCacheLockTimeoutAfterHeaders();
3369
3370 // 2nd transaction requests ranges 30-39.
3371 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
3372 MockHttpRequest request2(transaction);
3373 {
3374 auto& c = context_list[1];
3375 c->result = cache.CreateTransaction(&c->trans);
3376 ASSERT_THAT(c->result, IsOk());
3377 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3378
3379 c->result =
3380 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3381 base::RunLoop().RunUntilIdle();
3382
3383 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3384 }
3385
3386 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(request1.CacheKey()));
3387
3388 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3389 EXPECT_EQ(0, cache.disk_cache()->open_count());
3390 EXPECT_EQ(1, cache.disk_cache()->create_count());
3391
3392 for (int i = 0; i < kNumTransactions; ++i) {
3393 auto& c = context_list[i];
3394 if (c->result == ERR_IO_PENDING)
3395 c->result = c->callback.WaitForResult();
3396
3397 if (i == 0) {
3398 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3399 transaction);
3400 continue;
3401 }
3402
3403 transaction.data = "rg: 30-39 ";
3404 ReadAndVerifyTransaction(c->trans.get(), transaction);
3405 }
3406
3407 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3408 EXPECT_EQ(0, cache.disk_cache()->open_count());
3409 EXPECT_EQ(1, cache.disk_cache()->create_count());
3410 }
3411
3412 // Tests a full request and a simultaneous range request and the range request
3413 // dooms the entry created by the full request due to not being able to
3414 // conditionalize.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCouldntConditionalize)3415 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCouldntConditionalize) {
3416 MockHttpCache cache;
3417
3418 MockTransaction mock_transaction(kSimpleGET_Transaction);
3419 mock_transaction.url = kRangeGET_TransactionOK.url;
3420 ScopedMockTransaction transaction(mock_transaction);
3421
3422 // Remove the cache-control and other headers so that the response cannot be
3423 // conditionalized.
3424 transaction.response_headers = "";
3425
3426 std::vector<std::unique_ptr<Context>> context_list;
3427 const int kNumTransactions = 2;
3428
3429 for (int i = 0; i < kNumTransactions; ++i) {
3430 context_list.push_back(std::make_unique<Context>());
3431 }
3432
3433 // Let 1st transaction complete headers phase for no range and read some part
3434 // of the response and write in the cache.
3435 std::string first_read;
3436 MockHttpRequest request1(transaction);
3437 {
3438 request1.url = GURL(kRangeGET_TransactionOK.url);
3439 auto& c = context_list[0];
3440 c->result = cache.CreateTransaction(&c->trans);
3441 ASSERT_THAT(c->result, IsOk());
3442 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3443
3444 c->result =
3445 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3446 base::RunLoop().RunUntilIdle();
3447
3448 const int kBufferSize = 5;
3449 scoped_refptr<IOBuffer> buffer =
3450 base::MakeRefCounted<IOBuffer>(kBufferSize);
3451 ReleaseBufferCompletionCallback cb(buffer.get());
3452 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3453 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3454
3455 std::string data_read(buffer->data(), kBufferSize);
3456 first_read = data_read;
3457
3458 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3459 }
3460
3461 // 2nd transaction requests a range.
3462 ScopedMockTransaction range_transaction(kRangeGET_TransactionOK);
3463 range_transaction.request_headers = "Range: bytes = 0-29\r\n" EXTRA_HEADER;
3464 MockHttpRequest request2(range_transaction);
3465 {
3466 auto& c = context_list[1];
3467 c->result = cache.CreateTransaction(&c->trans);
3468 ASSERT_THAT(c->result, IsOk());
3469 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3470
3471 c->result =
3472 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3473 base::RunLoop().RunUntilIdle();
3474
3475 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3476 }
3477
3478 // The second request would have doomed the 1st entry and created a new entry.
3479 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3480 EXPECT_EQ(0, cache.disk_cache()->open_count());
3481 EXPECT_EQ(2, cache.disk_cache()->create_count());
3482
3483 for (int i = 0; i < kNumTransactions; ++i) {
3484 auto& c = context_list[i];
3485 if (c->result == ERR_IO_PENDING)
3486 c->result = c->callback.WaitForResult();
3487
3488 if (i == 0) {
3489 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3490 transaction);
3491 continue;
3492 }
3493 range_transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 ";
3494 ReadAndVerifyTransaction(c->trans.get(), range_transaction);
3495 }
3496 context_list.clear();
3497 }
3498
3499 // Tests a 200 request and a simultaneous range request where conditionalization
3500 // is possible.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCouldConditionalize)3501 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCouldConditionalize) {
3502 MockHttpCache cache;
3503
3504 MockTransaction mock_transaction(kSimpleGET_Transaction);
3505 mock_transaction.url = kRangeGET_TransactionOK.url;
3506 mock_transaction.data = kFullRangeData;
3507 std::string response_headers_str = base::StrCat(
3508 {"ETag: StrongOne\n",
3509 "Content-Length:", base::NumberToString(strlen(kFullRangeData)), "\n"});
3510 mock_transaction.response_headers = response_headers_str.c_str();
3511
3512 ScopedMockTransaction transaction(mock_transaction);
3513
3514 std::vector<std::unique_ptr<Context>> context_list;
3515 const int kNumTransactions = 2;
3516
3517 for (int i = 0; i < kNumTransactions; ++i) {
3518 context_list.push_back(std::make_unique<Context>());
3519 }
3520
3521 // Let 1st transaction complete headers phase for no range and read some part
3522 // of the response and write in the cache.
3523 std::string first_read;
3524 MockHttpRequest request1(transaction);
3525 {
3526 request1.url = GURL(kRangeGET_TransactionOK.url);
3527 auto& c = context_list[0];
3528 c->result = cache.CreateTransaction(&c->trans);
3529 ASSERT_THAT(c->result, IsOk());
3530 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3531
3532 c->result =
3533 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3534 base::RunLoop().RunUntilIdle();
3535
3536 const int kBufferSize = 5;
3537 scoped_refptr<IOBuffer> buffer =
3538 base::MakeRefCounted<IOBuffer>(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 scoped_refptr<IOBuffer> buffer =
3614 base::MakeRefCounted<IOBuffer>(kBufferSize);
3615 ReleaseBufferCompletionCallback cb(buffer.get());
3616 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3617 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3618
3619 std::string data_read(buffer->data(), kBufferSize);
3620 first_read = data_read;
3621
3622 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3623 }
3624
3625 // 2nd transaction requests ranges 30-49.
3626 transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3627 MockHttpRequest request2(transaction);
3628 {
3629 auto& c = context_list[1];
3630 c->result = cache.CreateTransaction(&c->trans);
3631 ASSERT_THAT(c->result, IsOk());
3632 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3633
3634 c->result =
3635 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3636 base::RunLoop().RunUntilIdle();
3637
3638 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3639 }
3640
3641 std::string cache_key = request1.CacheKey();
3642 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3643 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3644
3645 // Should have created another transaction for the uncached range.
3646 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3647 EXPECT_EQ(0, cache.disk_cache()->open_count());
3648 EXPECT_EQ(1, cache.disk_cache()->create_count());
3649
3650 for (int i = 0; i < kNumTransactions; ++i) {
3651 auto& c = context_list[i];
3652 if (c->result == ERR_IO_PENDING)
3653 c->result = c->callback.WaitForResult();
3654
3655 if (i == 0) {
3656 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3657 transaction);
3658 continue;
3659 }
3660
3661 transaction.data = "rg: 30-39 rg: 40-49 ";
3662 ReadAndVerifyTransaction(c->trans.get(), transaction);
3663 }
3664
3665 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3666 EXPECT_EQ(0, cache.disk_cache()->open_count());
3667 EXPECT_EQ(1, cache.disk_cache()->create_count());
3668
3669 // Fetch from the cache to check that ranges 30-49 have been successfully
3670 // cached.
3671 {
3672 MockTransaction range_transaction(kRangeGET_TransactionOK);
3673 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3674 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3675 std::string headers;
3676 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3677 &headers);
3678 Verify206Response(headers, 30, 49);
3679 }
3680
3681 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3682 EXPECT_EQ(0, cache.disk_cache()->open_count());
3683 EXPECT_EQ(1, cache.disk_cache()->create_count());
3684 }
3685
3686 // Tests parallel validation on range requests with overlapping ranges and the
3687 // impact of deleting the writer on transactions that have validated.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationRestartDoneHeaders)3688 TEST_F(HttpCacheTest, RangeGET_ParallelValidationRestartDoneHeaders) {
3689 MockHttpCache cache;
3690
3691 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3692
3693 std::vector<std::unique_ptr<Context>> context_list;
3694 const int kNumTransactions = 2;
3695
3696 for (int i = 0; i < kNumTransactions; ++i) {
3697 context_list.push_back(std::make_unique<Context>());
3698 }
3699
3700 // Let 1st transaction complete headers phase for ranges 40-59.
3701 std::string first_read;
3702 transaction.request_headers = "Range: bytes = 40-59\r\n" EXTRA_HEADER;
3703 MockHttpRequest request1(transaction);
3704 {
3705 auto& c = context_list[0];
3706 c->result = cache.CreateTransaction(&c->trans);
3707 ASSERT_THAT(c->result, IsOk());
3708 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3709
3710 c->result =
3711 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3712 base::RunLoop().RunUntilIdle();
3713
3714 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3715 // true.
3716 const int kBufferSize = 10;
3717 scoped_refptr<IOBuffer> buffer =
3718 base::MakeRefCounted<IOBuffer>(kBufferSize);
3719 ReleaseBufferCompletionCallback cb(buffer.get());
3720 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3721 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3722
3723 std::string data_read(buffer->data(), kBufferSize);
3724 first_read = data_read;
3725
3726 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3727 }
3728
3729 // 2nd transaction requests ranges 30-59.
3730 transaction.request_headers = "Range: bytes = 30-59\r\n" EXTRA_HEADER;
3731 MockHttpRequest request2(transaction);
3732 {
3733 auto& c = context_list[1];
3734 c->result = cache.CreateTransaction(&c->trans);
3735 ASSERT_THAT(c->result, IsOk());
3736 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3737
3738 c->result =
3739 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3740 base::RunLoop().RunUntilIdle();
3741
3742 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3743 }
3744
3745 std::string cache_key = request1.CacheKey();
3746 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3747 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3748
3749 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3750 EXPECT_EQ(0, cache.disk_cache()->open_count());
3751 EXPECT_EQ(1, cache.disk_cache()->create_count());
3752
3753 // Delete the writer transaction.
3754 context_list[0].reset();
3755
3756 base::RunLoop().RunUntilIdle();
3757
3758 transaction.data = "rg: 30-39 rg: 40-49 rg: 50-59 ";
3759 ReadAndVerifyTransaction(context_list[1]->trans.get(), transaction);
3760
3761 // Create another network transaction since the 2nd transaction is restarted.
3762 // 30-39 will be read from network, 40-49 from the cache and 50-59 from the
3763 // network.
3764 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3765 EXPECT_EQ(0, cache.disk_cache()->open_count());
3766 EXPECT_EQ(1, cache.disk_cache()->create_count());
3767
3768 // Fetch from the cache to check that ranges 30-49 have been successfully
3769 // cached.
3770 {
3771 MockTransaction range_transaction(kRangeGET_TransactionOK);
3772 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3773 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3774 std::string headers;
3775 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3776 &headers);
3777 Verify206Response(headers, 30, 49);
3778 }
3779
3780 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3781 EXPECT_EQ(1, cache.disk_cache()->open_count());
3782 EXPECT_EQ(1, cache.disk_cache()->create_count());
3783 }
3784
3785 // A test of doing a range request to a cached 301 response
TEST_F(HttpCacheTest,RangeGET_CachedRedirect)3786 TEST_F(HttpCacheTest, RangeGET_CachedRedirect) {
3787 RangeTransactionServer handler;
3788 handler.set_redirect(true);
3789
3790 MockHttpCache cache;
3791 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3792 transaction.request_headers = "Range: bytes = 0-\r\n" EXTRA_HEADER;
3793 transaction.status = "HTTP/1.1 301 Moved Permanently";
3794 transaction.response_headers = "Location: /elsewhere\nContent-Length:5";
3795 transaction.data = "12345";
3796 MockHttpRequest request(transaction);
3797
3798 TestCompletionCallback callback;
3799
3800 // Write to the cache.
3801 {
3802 std::unique_ptr<HttpTransaction> trans;
3803 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3804
3805 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3806 if (rv == ERR_IO_PENDING)
3807 rv = callback.WaitForResult();
3808 ASSERT_THAT(rv, IsOk());
3809
3810 const HttpResponseInfo* info = trans->GetResponseInfo();
3811 ASSERT_TRUE(info);
3812
3813 EXPECT_EQ(info->headers->response_code(), 301);
3814
3815 std::string location;
3816 info->headers->EnumerateHeader(nullptr, "Location", &location);
3817 EXPECT_EQ(location, "/elsewhere");
3818
3819 ReadAndVerifyTransaction(trans.get(), transaction);
3820 }
3821 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3822 EXPECT_EQ(0, cache.disk_cache()->open_count());
3823 EXPECT_EQ(1, cache.disk_cache()->create_count());
3824
3825 // Active entries in the cache are not retired synchronously. Make
3826 // sure the next run hits the MockHttpCache and open_count is
3827 // correct.
3828 base::RunLoop().RunUntilIdle();
3829
3830 // Read from the cache.
3831 {
3832 std::unique_ptr<HttpTransaction> trans;
3833 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3834
3835 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3836 if (rv == ERR_IO_PENDING)
3837 rv = callback.WaitForResult();
3838 ASSERT_THAT(rv, IsOk());
3839
3840 const HttpResponseInfo* info = trans->GetResponseInfo();
3841 ASSERT_TRUE(info);
3842
3843 EXPECT_EQ(info->headers->response_code(), 301);
3844
3845 std::string location;
3846 info->headers->EnumerateHeader(nullptr, "Location", &location);
3847 EXPECT_EQ(location, "/elsewhere");
3848
3849 trans->DoneReading();
3850 }
3851 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3852 EXPECT_EQ(1, cache.disk_cache()->open_count());
3853 EXPECT_EQ(1, cache.disk_cache()->create_count());
3854
3855 // Now read the full body. This normally would not be done for a 301 by
3856 // higher layers, but e.g. a 500 could hit a further bug here.
3857 {
3858 std::unique_ptr<HttpTransaction> trans;
3859 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3860
3861 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3862 if (rv == ERR_IO_PENDING)
3863 rv = callback.WaitForResult();
3864 ASSERT_THAT(rv, IsOk());
3865
3866 const HttpResponseInfo* info = trans->GetResponseInfo();
3867 ASSERT_TRUE(info);
3868
3869 EXPECT_EQ(info->headers->response_code(), 301);
3870
3871 std::string location;
3872 info->headers->EnumerateHeader(nullptr, "Location", &location);
3873 EXPECT_EQ(location, "/elsewhere");
3874
3875 ReadAndVerifyTransaction(trans.get(), transaction);
3876 }
3877 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3878 // No extra open since it picks up a previous ActiveEntry.
3879 EXPECT_EQ(1, cache.disk_cache()->open_count());
3880 EXPECT_EQ(1, cache.disk_cache()->create_count());
3881 }
3882
3883 // A transaction that fails to validate an entry, while attempting to write
3884 // the response, should still get data to its consumer even if the attempt to
3885 // create a new entry fails.
TEST_F(HttpCacheTest,SimpleGET_ValidationFailureWithCreateFailure)3886 TEST_F(HttpCacheTest, SimpleGET_ValidationFailureWithCreateFailure) {
3887 MockHttpCache cache;
3888 MockHttpRequest request(kSimpleGET_Transaction);
3889 request.load_flags |= LOAD_VALIDATE_CACHE;
3890 std::vector<std::unique_ptr<Context>> context_list;
3891
3892 // Create and run the first, successful, transaction to prime the cache.
3893 context_list.push_back(std::make_unique<Context>());
3894 auto& c1 = context_list.back();
3895 c1->result = cache.CreateTransaction(&c1->trans);
3896 ASSERT_THAT(c1->result, IsOk());
3897 EXPECT_EQ(LOAD_STATE_IDLE, c1->trans->GetLoadState());
3898 c1->result =
3899 c1->trans->Start(&request, c1->callback.callback(), NetLogWithSource());
3900 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c1->trans->GetLoadState());
3901 base::RunLoop().RunUntilIdle();
3902
3903 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
3904 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3905 EXPECT_EQ(0, cache.disk_cache()->open_count());
3906 EXPECT_EQ(1, cache.disk_cache()->create_count());
3907
3908 // Create and start the second transaction, which will fail its validation
3909 // during the call to RunUntilIdle().
3910 context_list.push_back(std::make_unique<Context>());
3911 auto& c2 = context_list.back();
3912 c2->result = cache.CreateTransaction(&c2->trans);
3913 ASSERT_THAT(c2->result, IsOk());
3914 EXPECT_EQ(LOAD_STATE_IDLE, c2->trans->GetLoadState());
3915 c2->result =
3916 c2->trans->Start(&request, c2->callback.callback(), NetLogWithSource());
3917 // Expect idle at this point because we should be able to find and use the
3918 // Active Entry that c1 created instead of waiting on the cache to open the
3919 // entry.
3920 EXPECT_EQ(LOAD_STATE_IDLE, c2->trans->GetLoadState());
3921
3922 cache.disk_cache()->set_fail_requests(true);
3923 // The transaction, c2, should now attempt to validate the entry, fail when it
3924 // receives a 200 OK response, attempt to create a new entry, fail to create,
3925 // and then continue onward without an entry.
3926 base::RunLoop().RunUntilIdle();
3927
3928 // All requests depend on the writer, and the writer is between Start and
3929 // Read, i.e. idle.
3930 for (auto& context : context_list) {
3931 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3932 }
3933
3934 // Confirm that both transactions correctly Read() the data.
3935 for (auto& context : context_list) {
3936 if (context->result == ERR_IO_PENDING)
3937 context->result = context->callback.WaitForResult();
3938 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
3939 }
3940
3941 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3942 EXPECT_EQ(0, cache.disk_cache()->open_count());
3943 EXPECT_EQ(1, cache.disk_cache()->create_count());
3944 }
3945
3946 // Parallel validation results in 200.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationNoMatch)3947 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationNoMatch) {
3948 MockHttpCache cache;
3949 MockHttpRequest request(kSimpleGET_Transaction);
3950 request.load_flags |= LOAD_VALIDATE_CACHE;
3951 std::vector<std::unique_ptr<Context>> context_list;
3952 const int kNumTransactions = 5;
3953 for (int i = 0; i < kNumTransactions; ++i) {
3954 context_list.push_back(std::make_unique<Context>());
3955 auto& c = context_list[i];
3956 c->result = cache.CreateTransaction(&c->trans);
3957 ASSERT_THAT(c->result, IsOk());
3958 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3959 c->result =
3960 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
3961 }
3962
3963 // All requests are waiting for the active entry.
3964 for (auto& context : context_list) {
3965 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
3966 }
3967
3968 // Allow all requests to move from the Create queue to the active entry.
3969 base::RunLoop().RunUntilIdle();
3970
3971 // The first request should be a writer at this point, and the subsequent
3972 // requests should have passed the validation phase and created their own
3973 // entries since none of them matched the headers of the earlier one.
3974 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
3975
3976 EXPECT_EQ(5, cache.network_layer()->transaction_count());
3977 EXPECT_EQ(0, cache.disk_cache()->open_count());
3978 EXPECT_EQ(5, cache.disk_cache()->create_count());
3979
3980 // All requests depend on the writer, and the writer is between Start and
3981 // Read, i.e. idle.
3982 for (auto& context : context_list) {
3983 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3984 }
3985
3986 for (auto& context : context_list) {
3987 if (context->result == ERR_IO_PENDING)
3988 context->result = context->callback.WaitForResult();
3989 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
3990 }
3991
3992 EXPECT_EQ(5, cache.network_layer()->transaction_count());
3993 EXPECT_EQ(0, cache.disk_cache()->open_count());
3994 EXPECT_EQ(5, cache.disk_cache()->create_count());
3995 }
3996
TEST_F(HttpCacheTest,RangeGET_Enormous)3997 TEST_F(HttpCacheTest, RangeGET_Enormous) {
3998 // Test for how blockfile's limit on range namespace interacts with
3999 // HttpCache::Transaction.
4000 // See https://crbug.com/770694
4001 base::ScopedTempDir temp_dir;
4002 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
4003
4004 auto backend_factory = std::make_unique<HttpCache::DefaultBackend>(
4005 DISK_CACHE, CACHE_BACKEND_BLOCKFILE,
4006 /*file_operations_factory=*/nullptr, temp_dir.GetPath(), 1024 * 1024,
4007 false);
4008 MockHttpCache cache(std::move(backend_factory));
4009
4010 RangeTransactionServer handler;
4011 handler.set_length(2305843009213693962);
4012
4013 // Prime with a range it can store.
4014 {
4015 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4016 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
4017 transaction.data = "rg: 00-09 ";
4018 MockHttpRequest request(transaction);
4019
4020 HttpResponseInfo response;
4021 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4022 &response);
4023 ASSERT_TRUE(response.headers != nullptr);
4024 EXPECT_EQ(206, response.headers->response_code());
4025 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4026 }
4027
4028 // Try with a range it can't. Should still work.
4029 {
4030 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4031 transaction.request_headers =
4032 "Range: bytes = "
4033 "2305843009213693952-2305843009213693961\r\n" EXTRA_HEADER;
4034 transaction.data = "rg: 52-61 ";
4035 MockHttpRequest request(transaction);
4036
4037 HttpResponseInfo response;
4038 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4039 &response);
4040 ASSERT_TRUE(response.headers != nullptr);
4041 EXPECT_EQ(206, response.headers->response_code());
4042 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4043 }
4044
4045 // Can't actually cache it due to backend limitations. If the network
4046 // transaction count is 2, this test isn't covering what it needs to.
4047 {
4048 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4049 transaction.request_headers =
4050 "Range: bytes = "
4051 "2305843009213693952-2305843009213693961\r\n" EXTRA_HEADER;
4052 transaction.data = "rg: 52-61 ";
4053 MockHttpRequest request(transaction);
4054
4055 HttpResponseInfo response;
4056 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4057 &response);
4058 ASSERT_TRUE(response.headers != nullptr);
4059 EXPECT_EQ(206, response.headers->response_code());
4060 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4061 }
4062 }
4063
4064 // Parallel validation results in 200 for 1 transaction and validation matches
4065 // for subsequent transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationNoMatch1)4066 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationNoMatch1) {
4067 MockHttpCache cache;
4068 MockHttpRequest request(kSimpleGET_Transaction);
4069
4070 MockTransaction transaction(kSimpleGET_Transaction);
4071 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4072 MockHttpRequest validate_request(transaction);
4073 std::vector<std::unique_ptr<Context>> context_list;
4074 const int kNumTransactions = 5;
4075 for (int i = 0; i < kNumTransactions; ++i) {
4076 context_list.push_back(std::make_unique<Context>());
4077 auto& c = context_list[i];
4078 c->result = cache.CreateTransaction(&c->trans);
4079 ASSERT_THAT(c->result, IsOk());
4080 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
4081
4082 MockHttpRequest* this_request = &request;
4083 if (i == 1)
4084 this_request = &validate_request;
4085
4086 c->result = c->trans->Start(this_request, c->callback.callback(),
4087 NetLogWithSource());
4088 }
4089
4090 // All requests are waiting for the active entry.
4091 for (auto& context : context_list) {
4092 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
4093 }
4094
4095 // Allow all requests to move from the Create queue to the active entry.
4096 base::RunLoop().RunUntilIdle();
4097
4098 // The new entry will have all the transactions except the first one which
4099 // will continue in the doomed entry.
4100 EXPECT_EQ(kNumTransactions - 1,
4101 cache.GetCountWriterTransactions(validate_request.CacheKey()));
4102
4103 EXPECT_EQ(1, cache.disk_cache()->doomed_count());
4104
4105 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4106 EXPECT_EQ(0, cache.disk_cache()->open_count());
4107 EXPECT_EQ(2, cache.disk_cache()->create_count());
4108
4109 for (auto& context : context_list) {
4110 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
4111 }
4112
4113 for (auto& context : context_list) {
4114 if (context->result == ERR_IO_PENDING)
4115 context->result = context->callback.WaitForResult();
4116
4117 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4118 }
4119
4120 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4121 EXPECT_EQ(0, cache.disk_cache()->open_count());
4122 EXPECT_EQ(2, cache.disk_cache()->create_count());
4123 }
4124
4125 // Tests that a GET followed by a DELETE results in DELETE immediately starting
4126 // the headers phase and the entry is doomed.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationDelete)4127 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationDelete) {
4128 MockHttpCache cache;
4129
4130 MockHttpRequest request(kSimpleGET_Transaction);
4131 request.load_flags |= LOAD_VALIDATE_CACHE;
4132
4133 MockHttpRequest delete_request(kSimpleGET_Transaction);
4134 delete_request.method = "DELETE";
4135
4136 std::vector<std::unique_ptr<Context>> context_list;
4137 const int kNumTransactions = 2;
4138
4139 for (int i = 0; i < kNumTransactions; ++i) {
4140 context_list.push_back(std::make_unique<Context>());
4141 auto& c = context_list[i];
4142
4143 MockHttpRequest* this_request = &request;
4144 if (i == 1)
4145 this_request = &delete_request;
4146
4147 c->result = cache.CreateTransaction(&c->trans);
4148 ASSERT_THAT(c->result, IsOk());
4149 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
4150
4151 c->result = c->trans->Start(this_request, c->callback.callback(),
4152 NetLogWithSource());
4153 }
4154
4155 // All requests are waiting for the active entry.
4156 for (auto& context : context_list) {
4157 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
4158 }
4159
4160 // Allow all requests to move from the Create queue to the active entry.
4161 base::RunLoop().RunUntilIdle();
4162
4163 // The first request should be a writer at this point, and the subsequent
4164 // request should have passed the validation phase and doomed the existing
4165 // entry.
4166 EXPECT_TRUE(cache.disk_cache()->IsDiskEntryDoomed(request.CacheKey()));
4167
4168 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4169 EXPECT_EQ(0, cache.disk_cache()->open_count());
4170 EXPECT_EQ(1, cache.disk_cache()->create_count());
4171
4172 // All requests depend on the writer, and the writer is between Start and
4173 // Read, i.e. idle.
4174 for (auto& context : context_list) {
4175 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
4176 }
4177
4178 for (auto& context : context_list) {
4179 if (context->result == ERR_IO_PENDING)
4180 context->result = context->callback.WaitForResult();
4181 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4182 }
4183
4184 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4185 EXPECT_EQ(0, cache.disk_cache()->open_count());
4186 EXPECT_EQ(1, cache.disk_cache()->create_count());
4187 }
4188
4189 // Tests that a transaction which is in validated queue can be destroyed without
4190 // any impact to other transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelValidated)4191 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelValidated) {
4192 MockHttpCache cache;
4193
4194 MockHttpRequest request(kSimpleGET_Transaction);
4195
4196 MockTransaction transaction(kSimpleGET_Transaction);
4197 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4198 MockHttpRequest read_only_request(transaction);
4199
4200 std::vector<std::unique_ptr<Context>> context_list;
4201 const int kNumTransactions = 2;
4202
4203 for (int i = 0; i < kNumTransactions; ++i) {
4204 context_list.push_back(std::make_unique<Context>());
4205 auto& c = context_list[i];
4206
4207 c->result = cache.CreateTransaction(&c->trans);
4208 ASSERT_THAT(c->result, IsOk());
4209
4210 MockHttpRequest* current_request = i == 1 ? &read_only_request : &request;
4211
4212 c->result = c->trans->Start(current_request, c->callback.callback(),
4213 NetLogWithSource());
4214 }
4215
4216 // Allow all requests to move from the Create queue to the active entry.
4217 base::RunLoop().RunUntilIdle();
4218
4219 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4220 EXPECT_EQ(0, cache.disk_cache()->open_count());
4221 EXPECT_EQ(1, cache.disk_cache()->create_count());
4222
4223 std::string cache_key = request.CacheKey();
4224 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4225 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4226
4227 context_list[1].reset();
4228
4229 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4230
4231 // Complete the rest of the transactions.
4232 for (auto& context : context_list) {
4233 if (!context)
4234 continue;
4235 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4236 }
4237
4238 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4239 EXPECT_EQ(0, cache.disk_cache()->open_count());
4240 EXPECT_EQ(1, cache.disk_cache()->create_count());
4241 }
4242
4243 // Tests that an idle writer transaction can be deleted without impacting the
4244 // existing writers.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingCancelIdleTransaction)4245 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingCancelIdleTransaction) {
4246 MockHttpCache cache;
4247
4248 MockHttpRequest request(kSimpleGET_Transaction);
4249
4250 std::vector<std::unique_ptr<Context>> context_list;
4251 const int kNumTransactions = 2;
4252
4253 for (int i = 0; i < kNumTransactions; ++i) {
4254 context_list.push_back(std::make_unique<Context>());
4255 auto& c = context_list[i];
4256
4257 c->result = cache.CreateTransaction(&c->trans);
4258 ASSERT_THAT(c->result, IsOk());
4259
4260 c->result =
4261 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4262 }
4263
4264 // Allow all requests to move from the Create queue to the active entry.
4265 base::RunLoop().RunUntilIdle();
4266
4267 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4268 EXPECT_EQ(0, cache.disk_cache()->open_count());
4269 EXPECT_EQ(1, cache.disk_cache()->create_count());
4270
4271 // Both transactions would be added to writers.
4272 std::string cache_key = request.CacheKey();
4273 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
4274
4275 context_list[1].reset();
4276
4277 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
4278
4279 // Complete the rest of the transactions.
4280 for (auto& context : context_list) {
4281 if (!context)
4282 continue;
4283 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4284 }
4285
4286 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4287 EXPECT_EQ(0, cache.disk_cache()->open_count());
4288 EXPECT_EQ(1, cache.disk_cache()->create_count());
4289 }
4290
4291 // Tests that a transaction which is in validated queue can timeout and start
4292 // the headers phase again.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationValidatedTimeout)4293 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationValidatedTimeout) {
4294 MockHttpCache cache;
4295
4296 MockHttpRequest request(kSimpleGET_Transaction);
4297
4298 MockTransaction transaction(kSimpleGET_Transaction);
4299 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4300 MockHttpRequest read_only_request(transaction);
4301
4302 std::vector<std::unique_ptr<Context>> context_list;
4303 const int kNumTransactions = 2;
4304
4305 for (int i = 0; i < kNumTransactions; ++i) {
4306 context_list.push_back(std::make_unique<Context>());
4307 auto& c = context_list[i];
4308
4309 MockHttpRequest* this_request = &request;
4310 if (i == 1) {
4311 this_request = &read_only_request;
4312 cache.SimulateCacheLockTimeoutAfterHeaders();
4313 }
4314
4315 c->result = cache.CreateTransaction(&c->trans);
4316 ASSERT_THAT(c->result, IsOk());
4317
4318 c->result = c->trans->Start(this_request, c->callback.callback(),
4319 NetLogWithSource());
4320 }
4321
4322 // Allow all requests to move from the Create queue to the active entry.
4323 base::RunLoop().RunUntilIdle();
4324
4325 // The first request should be a writer at this point, and the subsequent
4326 // requests should have completed validation, timed out and restarted.
4327 // Since it is a read only request, it will error out.
4328
4329 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4330 EXPECT_EQ(0, cache.disk_cache()->open_count());
4331 EXPECT_EQ(1, cache.disk_cache()->create_count());
4332
4333 std::string cache_key = request.CacheKey();
4334 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
4335 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4336
4337 base::RunLoop().RunUntilIdle();
4338
4339 int rv = context_list[1]->callback.WaitForResult();
4340 EXPECT_EQ(ERR_CACHE_MISS, rv);
4341
4342 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4343 kSimpleGET_Transaction);
4344 }
4345
4346 // Tests that a transaction which is in readers can be destroyed without
4347 // any impact to other transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelReader)4348 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelReader) {
4349 MockHttpCache cache;
4350
4351 MockHttpRequest request(kSimpleGET_Transaction);
4352
4353 MockTransaction transaction(kSimpleGET_Transaction);
4354 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4355 MockHttpRequest validate_request(transaction);
4356
4357 int kNumTransactions = 4;
4358 std::vector<std::unique_ptr<Context>> context_list;
4359
4360 for (int i = 0; i < kNumTransactions; ++i) {
4361 context_list.push_back(std::make_unique<Context>());
4362 auto& c = context_list[i];
4363
4364 c->result = cache.CreateTransaction(&c->trans);
4365 ASSERT_THAT(c->result, IsOk());
4366
4367 MockHttpRequest* this_request = &request;
4368 if (i == 3) {
4369 this_request = &validate_request;
4370 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
4371 }
4372
4373 c->result = c->trans->Start(this_request, c->callback.callback(),
4374 NetLogWithSource());
4375 }
4376
4377 // Allow all requests to move from the Create queue to the active entry.
4378 base::RunLoop().RunUntilIdle();
4379
4380 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4381 EXPECT_EQ(0, cache.disk_cache()->open_count());
4382 EXPECT_EQ(1, cache.disk_cache()->create_count());
4383
4384 std::string cache_key = request.CacheKey();
4385
4386 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
4387 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4388
4389 // Complete the response body.
4390 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4391 kSimpleGET_Transaction);
4392
4393 // Rest of the transactions should move to readers.
4394 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
4395 EXPECT_EQ(kNumTransactions - 2, cache.GetCountReaders(cache_key));
4396 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4397 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4398
4399 // Add 2 new transactions.
4400 kNumTransactions = 6;
4401
4402 for (int i = 4; i < kNumTransactions; ++i) {
4403 context_list.push_back(std::make_unique<Context>());
4404 auto& c = context_list[i];
4405
4406 c->result = cache.CreateTransaction(&c->trans);
4407 ASSERT_THAT(c->result, IsOk());
4408
4409 c->result =
4410 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4411 }
4412
4413 EXPECT_EQ(2, cache.GetCountAddToEntryQueue(cache_key));
4414
4415 // Delete a reader.
4416 context_list[1].reset();
4417
4418 // Deleting the reader did not impact any other transaction.
4419 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
4420 EXPECT_EQ(2, cache.GetCountAddToEntryQueue(cache_key));
4421 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4422
4423 // Resume network start for headers_transaction. It will doom the entry as it
4424 // will be a 200 and will go to network for the response body.
4425 context_list[3]->trans->ResumeNetworkStart();
4426
4427 // The pending transactions will be added to a new entry as writers.
4428 base::RunLoop().RunUntilIdle();
4429
4430 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4431
4432 // Complete the rest of the transactions.
4433 for (int i = 2; i < kNumTransactions; ++i) {
4434 ReadAndVerifyTransaction(context_list[i]->trans.get(),
4435 kSimpleGET_Transaction);
4436 }
4437
4438 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4439 EXPECT_EQ(0, cache.disk_cache()->open_count());
4440 EXPECT_EQ(2, cache.disk_cache()->create_count());
4441 }
4442
4443 // Tests that when the only writer goes away, it immediately cleans up rather
4444 // than wait for the network request to finish. See https://crbug.com/804868.
TEST_F(HttpCacheTest,SimpleGET_HangingCacheWriteCleanup)4445 TEST_F(HttpCacheTest, SimpleGET_HangingCacheWriteCleanup) {
4446 MockHttpCache mock_cache;
4447 MockHttpRequest request(kSimpleGET_Transaction);
4448
4449 std::unique_ptr<HttpTransaction> transaction;
4450 mock_cache.CreateTransaction(&transaction);
4451 TestCompletionCallback callback;
4452 int result =
4453 transaction->Start(&request, callback.callback(), NetLogWithSource());
4454
4455 // Get the transaction ready to read.
4456 result = callback.GetResult(result);
4457
4458 // Read the first byte.
4459 scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(1);
4460 ReleaseBufferCompletionCallback buffer_callback(buffer.get());
4461 result = transaction->Read(buffer.get(), 1, buffer_callback.callback());
4462 EXPECT_EQ(1, buffer_callback.GetResult(result));
4463
4464 // Read the second byte, but leave the cache write hanging.
4465 std::string cache_key = request.CacheKey();
4466 scoped_refptr<MockDiskEntry> entry =
4467 mock_cache.disk_cache()->GetDiskEntryRef(cache_key);
4468 entry->SetDefer(MockDiskEntry::DEFER_WRITE);
4469
4470 buffer = base::MakeRefCounted<IOBuffer>(1);
4471 ReleaseBufferCompletionCallback buffer_callback2(buffer.get());
4472 result = transaction->Read(buffer.get(), 1, buffer_callback2.callback());
4473 EXPECT_EQ(ERR_IO_PENDING, result);
4474 base::RunLoop().RunUntilIdle();
4475 EXPECT_TRUE(mock_cache.IsWriterPresent(cache_key));
4476
4477 // At this point the next byte should have been read from the network but is
4478 // waiting to be written to the cache. Destroy the transaction and make sure
4479 // that everything has been cleaned up.
4480 transaction = nullptr;
4481 EXPECT_FALSE(mock_cache.IsWriterPresent(cache_key));
4482 EXPECT_FALSE(mock_cache.network_layer()->last_transaction());
4483 }
4484
4485 // Tests that a transaction writer can be destroyed mid-read.
4486 // A waiting for read transaction should be able to read the data that was
4487 // driven by the Read started by the cancelled writer.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingCancelWriter)4488 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingCancelWriter) {
4489 MockHttpCache cache;
4490
4491 MockHttpRequest request(kSimpleGET_Transaction);
4492
4493 MockTransaction transaction(kSimpleGET_Transaction);
4494 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4495 MockHttpRequest validate_request(transaction);
4496
4497 const int kNumTransactions = 3;
4498 std::vector<std::unique_ptr<Context>> context_list;
4499
4500 for (int i = 0; i < kNumTransactions; ++i) {
4501 context_list.push_back(std::make_unique<Context>());
4502 auto& c = context_list[i];
4503
4504 c->result = cache.CreateTransaction(&c->trans);
4505 ASSERT_THAT(c->result, IsOk());
4506
4507 MockHttpRequest* this_request = &request;
4508 if (i == 2) {
4509 this_request = &validate_request;
4510 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
4511 }
4512
4513 c->result = c->trans->Start(this_request, c->callback.callback(),
4514 NetLogWithSource());
4515 }
4516
4517 // Allow all requests to move from the Create queue to the active entry.
4518 base::RunLoop().RunUntilIdle();
4519
4520 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4521 EXPECT_EQ(0, cache.disk_cache()->open_count());
4522 EXPECT_EQ(1, cache.disk_cache()->create_count());
4523
4524 std::string cache_key = validate_request.CacheKey();
4525 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4526 EXPECT_EQ(2, cache.GetCountWriterTransactions(cache_key));
4527
4528 // Initiate Read from both writers and kill 1 of them mid-read.
4529 std::string first_read;
4530 for (int i = 0; i < 2; i++) {
4531 auto& c = context_list[i];
4532 const int kBufferSize = 5;
4533 scoped_refptr<IOBuffer> buffer =
4534 base::MakeRefCounted<IOBuffer>(kBufferSize);
4535 ReleaseBufferCompletionCallback cb(buffer.get());
4536 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
4537 EXPECT_EQ(ERR_IO_PENDING, c->result);
4538 // Deleting one writer at this point will not impact other transactions
4539 // since writers contain more transactions.
4540 if (i == 1) {
4541 context_list[0].reset();
4542 base::RunLoop().RunUntilIdle();
4543 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
4544 std::string data_read(buffer->data(), kBufferSize);
4545 first_read = data_read;
4546 }
4547 }
4548
4549 // Resume network start for headers_transaction. It will doom the existing
4550 // entry and create a new entry due to validation returning a 200.
4551 auto& c = context_list[2];
4552 c->trans->ResumeNetworkStart();
4553
4554 base::RunLoop().RunUntilIdle();
4555
4556 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4557
4558 // Complete the rest of the transactions.
4559 for (int i = 0; i < kNumTransactions; i++) {
4560 auto& context = context_list[i];
4561 if (!context)
4562 continue;
4563 if (i == 1)
4564 ReadRemainingAndVerifyTransaction(context->trans.get(), first_read,
4565 kSimpleGET_Transaction);
4566 else
4567 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4568 }
4569
4570 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4571 EXPECT_EQ(0, cache.disk_cache()->open_count());
4572 EXPECT_EQ(2, cache.disk_cache()->create_count());
4573 }
4574
4575 // Tests the case when network read failure happens. Idle and waiting
4576 // transactions should fail and headers transaction should be restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingNetworkReadFailed)4577 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingNetworkReadFailed) {
4578 MockHttpCache cache;
4579
4580 ScopedMockTransaction fail_transaction(kSimpleGET_Transaction);
4581 fail_transaction.read_return_code = ERR_INTERNET_DISCONNECTED;
4582 MockHttpRequest failing_request(fail_transaction);
4583
4584 MockHttpRequest request(kSimpleGET_Transaction);
4585
4586 MockTransaction transaction(kSimpleGET_Transaction);
4587 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4588 MockHttpRequest read_request(transaction);
4589
4590 const int kNumTransactions = 4;
4591 std::vector<std::unique_ptr<Context>> context_list;
4592
4593 for (int i = 0; i < kNumTransactions; ++i) {
4594 context_list.push_back(std::make_unique<Context>());
4595 auto& c = context_list[i];
4596
4597 c->result = cache.CreateTransaction(&c->trans);
4598 ASSERT_THAT(c->result, IsOk());
4599
4600 MockHttpRequest* this_request = &request;
4601 if (i == 0)
4602 this_request = &failing_request;
4603 if (i == 3)
4604 this_request = &read_request;
4605
4606 c->result = c->trans->Start(this_request, c->callback.callback(),
4607 NetLogWithSource());
4608 }
4609
4610 // Allow all requests to move from the Create queue to the active entry.
4611 base::RunLoop().RunUntilIdle();
4612
4613 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4614 EXPECT_EQ(0, cache.disk_cache()->open_count());
4615 EXPECT_EQ(1, cache.disk_cache()->create_count());
4616
4617 std::string cache_key = read_request.CacheKey();
4618 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4619 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4620
4621 // Initiate Read from two writers and let the first get a network failure.
4622 for (int i = 0; i < 2; i++) {
4623 auto& c = context_list[i];
4624 const int kBufferSize = 5;
4625 scoped_refptr<IOBuffer> buffer =
4626 base::MakeRefCounted<IOBuffer>(kBufferSize);
4627 c->result =
4628 c->trans->Read(buffer.get(), kBufferSize, c->callback.callback());
4629 EXPECT_EQ(ERR_IO_PENDING, c->result);
4630 }
4631
4632 base::RunLoop().RunUntilIdle();
4633 for (int i = 0; i < 2; i++) {
4634 auto& c = context_list[i];
4635 c->result = c->callback.WaitForResult();
4636 EXPECT_EQ(ERR_INTERNET_DISCONNECTED, c->result);
4637 }
4638
4639 // The entry should have been doomed and destroyed and the headers transaction
4640 // restarted. Since headers transaction is read-only it will error out.
4641 auto& read_only = context_list[3];
4642 read_only->result = read_only->callback.WaitForResult();
4643 EXPECT_EQ(ERR_CACHE_MISS, read_only->result);
4644
4645 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
4646
4647 // Invoke Read on the 3rd transaction and it should get the error code back.
4648 auto& c = context_list[2];
4649 const int kBufferSize = 5;
4650 scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(kBufferSize);
4651 c->result = c->trans->Read(buffer.get(), kBufferSize, c->callback.callback());
4652 EXPECT_EQ(ERR_INTERNET_DISCONNECTED, c->result);
4653 }
4654
4655 // Tests the case when cache write failure happens. Idle and waiting
4656 // transactions should fail and headers transaction should be restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingCacheWriteFailed)4657 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingCacheWriteFailed) {
4658 MockHttpCache cache;
4659
4660 MockHttpRequest request(kSimpleGET_Transaction);
4661
4662 MockTransaction transaction(kSimpleGET_Transaction);
4663 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4664 MockHttpRequest read_request(transaction);
4665
4666 const int kNumTransactions = 4;
4667 std::vector<std::unique_ptr<Context>> context_list;
4668
4669 for (int i = 0; i < kNumTransactions; ++i) {
4670 context_list.push_back(std::make_unique<Context>());
4671 auto& c = context_list[i];
4672
4673 c->result = cache.CreateTransaction(&c->trans);
4674 ASSERT_THAT(c->result, IsOk());
4675
4676 MockHttpRequest* this_request = &request;
4677 if (i == 3)
4678 this_request = &read_request;
4679
4680 c->result = c->trans->Start(this_request, c->callback.callback(),
4681 NetLogWithSource());
4682 }
4683
4684 // Allow all requests to move from the Create queue to the active entry.
4685 base::RunLoop().RunUntilIdle();
4686
4687 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4688 EXPECT_EQ(0, cache.disk_cache()->open_count());
4689 EXPECT_EQ(1, cache.disk_cache()->create_count());
4690
4691 std::string cache_key = read_request.CacheKey();
4692 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4693 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4694
4695 // Initiate Read from two writers and let the first get a cache write failure.
4696 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
4697 // We have to open the entry again to propagate the failure flag.
4698 disk_cache::Entry* en;
4699 cache.OpenBackendEntry(cache_key, &en);
4700 en->Close();
4701 const int kBufferSize = 5;
4702 std::vector<scoped_refptr<IOBuffer>> buffer(
4703 3, base::MakeRefCounted<IOBuffer>(kBufferSize));
4704 for (int i = 0; i < 2; i++) {
4705 auto& c = context_list[i];
4706 c->result =
4707 c->trans->Read(buffer[i].get(), kBufferSize, c->callback.callback());
4708 EXPECT_EQ(ERR_IO_PENDING, c->result);
4709 }
4710
4711 std::string first_read;
4712 base::RunLoop().RunUntilIdle();
4713 for (int i = 0; i < 2; i++) {
4714 auto& c = context_list[i];
4715 c->result = c->callback.WaitForResult();
4716 if (i == 0) {
4717 EXPECT_EQ(5, c->result);
4718 std::string data_read(buffer[i]->data(), kBufferSize);
4719 first_read = data_read;
4720 } else {
4721 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, c->result);
4722 }
4723 }
4724
4725 // The entry should have been doomed and destroyed and the headers transaction
4726 // restarted. Since headers transaction is read-only it will error out.
4727 auto& read_only = context_list[3];
4728 read_only->result = read_only->callback.WaitForResult();
4729 EXPECT_EQ(ERR_CACHE_MISS, read_only->result);
4730
4731 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
4732
4733 // Invoke Read on the 3rd transaction and it should get the error code back.
4734 auto& c = context_list[2];
4735 c->result =
4736 c->trans->Read(buffer[2].get(), kBufferSize, c->callback.callback());
4737 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, c->result);
4738
4739 // The first transaction should be able to continue to read from the network
4740 // without writing to the cache.
4741 auto& succ_read = context_list[0];
4742 ReadRemainingAndVerifyTransaction(succ_read->trans.get(), first_read,
4743 kSimpleGET_Transaction);
4744 }
4745
4746 // Tests that POST requests do not join existing transactions for parallel
4747 // writing to the cache. Note that two POSTs only map to the same entry if their
4748 // upload data identifier is same and that should happen for back-forward case
4749 // (LOAD_ONLY_FROM_CACHE). But this test tests without LOAD_ONLY_FROM_CACHE
4750 // because read-only transactions anyways do not join parallel writing.
4751 // TODO(shivanisha) Testing this because it is allowed by the code but looks
4752 // like the code should disallow two POSTs without LOAD_ONLY_FROM_CACHE with the
4753 // same upload data identifier to map to the same entry.
TEST_F(HttpCacheTest,SimplePOST_ParallelWritingDisallowed)4754 TEST_F(HttpCacheTest, SimplePOST_ParallelWritingDisallowed) {
4755 MockHttpCache cache;
4756
4757 MockTransaction transaction(kSimplePOST_Transaction);
4758
4759 const int64_t kUploadId = 1; // Just a dummy value.
4760
4761 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
4762 element_readers.push_back(
4763 std::make_unique<UploadBytesElementReader>("hello", 5));
4764 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
4765 kUploadId);
4766
4767 // Note that both transactions should have the same upload_data_stream
4768 // identifier to map to the same entry.
4769 transaction.load_flags = LOAD_SKIP_CACHE_VALIDATION;
4770 MockHttpRequest request(transaction);
4771 request.upload_data_stream = &upload_data_stream;
4772
4773 const int kNumTransactions = 2;
4774 std::vector<std::unique_ptr<Context>> context_list;
4775
4776 for (int i = 0; i < kNumTransactions; ++i) {
4777 context_list.push_back(std::make_unique<Context>());
4778 auto& c = context_list[i];
4779
4780 c->result = cache.CreateTransaction(&c->trans);
4781 ASSERT_THAT(c->result, IsOk());
4782
4783 c->result =
4784 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4785
4786 // Complete the headers phase request.
4787 base::RunLoop().RunUntilIdle();
4788 }
4789
4790 std::string cache_key = request.CacheKey();
4791 // Only the 1st transaction gets added to writers.
4792 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4793 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4794
4795 // Read the 1st transaction.
4796 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4797 kSimplePOST_Transaction);
4798
4799 // 2nd transaction should now become a reader.
4800 base::RunLoop().RunUntilIdle();
4801 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
4802 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4803 ReadAndVerifyTransaction(context_list[1]->trans.get(),
4804 kSimplePOST_Transaction);
4805
4806 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4807 EXPECT_EQ(0, cache.disk_cache()->open_count());
4808 EXPECT_EQ(1, cache.disk_cache()->create_count());
4809
4810 context_list.clear();
4811 }
4812
4813 // Tests the case when parallel writing succeeds. Tests both idle and waiting
4814 // transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingSuccess)4815 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingSuccess) {
4816 MockHttpCache cache;
4817
4818 MockHttpRequest request(kSimpleGET_Transaction);
4819
4820 MockTransaction transaction(kSimpleGET_Transaction);
4821 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4822 MockHttpRequest read_request(transaction);
4823
4824 const int kNumTransactions = 4;
4825 std::vector<std::unique_ptr<Context>> context_list;
4826
4827 for (int i = 0; i < kNumTransactions; ++i) {
4828 context_list.push_back(std::make_unique<Context>());
4829 auto& c = context_list[i];
4830
4831 c->result = cache.CreateTransaction(&c->trans);
4832 ASSERT_THAT(c->result, IsOk());
4833
4834 MockHttpRequest* this_request = &request;
4835 if (i == 3)
4836 this_request = &read_request;
4837
4838 c->result = c->trans->Start(this_request, c->callback.callback(),
4839 NetLogWithSource());
4840 }
4841
4842 // Allow all requests to move from the Create queue to the active entry.
4843 base::RunLoop().RunUntilIdle();
4844
4845 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4846 EXPECT_EQ(0, cache.disk_cache()->open_count());
4847 EXPECT_EQ(1, cache.disk_cache()->create_count());
4848
4849 std::string cache_key = request.CacheKey();
4850 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4851 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4852
4853 // Initiate Read from two writers.
4854 const int kBufferSize = 5;
4855 std::vector<scoped_refptr<IOBuffer>> buffer(
4856 3, base::MakeRefCounted<IOBuffer>(kBufferSize));
4857 for (int i = 0; i < 2; i++) {
4858 auto& c = context_list[i];
4859 c->result =
4860 c->trans->Read(buffer[i].get(), kBufferSize, c->callback.callback());
4861 EXPECT_EQ(ERR_IO_PENDING, c->result);
4862 }
4863
4864 std::vector<std::string> first_read(2);
4865 base::RunLoop().RunUntilIdle();
4866 for (int i = 0; i < 2; i++) {
4867 auto& c = context_list[i];
4868 c->result = c->callback.WaitForResult();
4869 EXPECT_EQ(5, c->result);
4870 std::string data_read(buffer[i]->data(), kBufferSize);
4871 first_read[i] = data_read;
4872 }
4873 EXPECT_EQ(first_read[0], first_read[1]);
4874
4875 // The first transaction should be able to continue to read from the network
4876 // without writing to the cache.
4877 for (int i = 0; i < 2; i++) {
4878 auto& c = context_list[i];
4879 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read[i],
4880 kSimpleGET_Transaction);
4881 if (i == 0) {
4882 // Remaining transactions should now be readers.
4883 EXPECT_EQ(3, cache.GetCountReaders(cache_key));
4884 }
4885 }
4886
4887 // Verify the rest of the transactions.
4888 for (int i = 2; i < kNumTransactions; i++) {
4889 auto& c = context_list[i];
4890 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
4891 }
4892
4893 context_list.clear();
4894 }
4895
4896 // Tests the case when parallel writing involves things bigger than what cache
4897 // can store. In this case, the best we can do is re-fetch it.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingHuge)4898 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingHuge) {
4899 MockHttpCache cache;
4900 cache.disk_cache()->set_max_file_size(10);
4901
4902 MockTransaction transaction(kSimpleGET_Transaction);
4903 std::string response_headers = base::StrCat(
4904 {kSimpleGET_Transaction.response_headers, "Content-Length: ",
4905 base::NumberToString(strlen(kSimpleGET_Transaction.data)), "\n"});
4906 transaction.response_headers = response_headers.c_str();
4907 AddMockTransaction(&transaction);
4908 MockHttpRequest request(transaction);
4909
4910 const int kNumTransactions = 4;
4911 std::vector<std::unique_ptr<Context>> context_list;
4912
4913 for (int i = 0; i < kNumTransactions; ++i) {
4914 context_list.push_back(std::make_unique<Context>());
4915 auto& c = context_list[i];
4916
4917 c->result = cache.CreateTransaction(&c->trans);
4918 ASSERT_THAT(c->result, IsOk());
4919
4920 MockHttpRequest* this_request = &request;
4921 c->result = c->trans->Start(this_request, c->callback.callback(),
4922 NetLogWithSource());
4923 }
4924
4925 // Start them up.
4926 base::RunLoop().RunUntilIdle();
4927
4928 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4929 EXPECT_EQ(0, cache.disk_cache()->open_count());
4930 EXPECT_EQ(1, cache.disk_cache()->create_count());
4931
4932 std::string cache_key = request.CacheKey();
4933 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4934 EXPECT_EQ(kNumTransactions - 1, cache.GetCountDoneHeadersQueue(cache_key));
4935
4936 // Initiate Read from first transaction.
4937 const int kBufferSize = 5;
4938 std::vector<scoped_refptr<IOBuffer>> buffer(
4939 kNumTransactions, base::MakeRefCounted<IOBuffer>(kBufferSize));
4940 auto& c = context_list[0];
4941 c->result =
4942 c->trans->Read(buffer[0].get(), kBufferSize, c->callback.callback());
4943 EXPECT_EQ(ERR_IO_PENDING, c->result);
4944
4945 // ... and complete it.
4946 std::vector<std::string> first_read(kNumTransactions);
4947 base::RunLoop().RunUntilIdle();
4948 c->result = c->callback.WaitForResult();
4949 EXPECT_EQ(kBufferSize, c->result);
4950 std::string data_read(buffer[0]->data(), kBufferSize);
4951 first_read[0] = data_read;
4952 EXPECT_EQ("<html", first_read[0]);
4953
4954 // Complete all of them.
4955 for (int i = 0; i < kNumTransactions; i++) {
4956 ReadRemainingAndVerifyTransaction(context_list[i]->trans.get(),
4957 first_read[i], kSimpleGET_Transaction);
4958 }
4959
4960 // Sadly all of them have to hit the network
4961 EXPECT_EQ(kNumTransactions, cache.network_layer()->transaction_count());
4962
4963 context_list.clear();
4964 RemoveMockTransaction(&transaction);
4965 }
4966
4967 // Tests that network transaction's info is saved correctly when a writer
4968 // transaction that created the network transaction becomes a reader. Also
4969 // verifies that the network bytes are only attributed to the transaction that
4970 // created the network transaction.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingVerifyNetworkBytes)4971 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingVerifyNetworkBytes) {
4972 MockHttpCache cache;
4973
4974 MockHttpRequest request(kSimpleGET_Transaction);
4975
4976 const int kNumTransactions = 2;
4977 std::vector<std::unique_ptr<Context>> context_list;
4978
4979 for (int i = 0; i < kNumTransactions; ++i) {
4980 context_list.push_back(std::make_unique<Context>());
4981 auto& c = context_list[i];
4982
4983 c->result = cache.CreateTransaction(&c->trans);
4984 ASSERT_THAT(c->result, IsOk());
4985
4986 c->result =
4987 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4988 }
4989
4990 // Allow all requests to move from the Create queue to the active entry.
4991 base::RunLoop().RunUntilIdle();
4992
4993 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4994 EXPECT_EQ(0, cache.disk_cache()->open_count());
4995 EXPECT_EQ(1, cache.disk_cache()->create_count());
4996
4997 std::string cache_key = request.CacheKey();
4998 EXPECT_EQ(2, cache.GetCountWriterTransactions(cache_key));
4999 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
5000
5001 // Get the network bytes read by the first transaction.
5002 int total_received_bytes = context_list[0]->trans->GetTotalReceivedBytes();
5003 EXPECT_GT(total_received_bytes, 0);
5004
5005 // Complete Read by the 2nd transaction so that the 1st transaction that
5006 // created the network transaction is now a reader.
5007 ReadAndVerifyTransaction(context_list[1]->trans.get(),
5008 kSimpleGET_Transaction);
5009
5010 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
5011
5012 // Verify that the network bytes read are not attributed to the 2nd
5013 // transaction but to the 1st.
5014 EXPECT_EQ(0, context_list[1]->trans->GetTotalReceivedBytes());
5015
5016 EXPECT_GE(total_received_bytes,
5017 context_list[0]->trans->GetTotalReceivedBytes());
5018
5019 ReadAndVerifyTransaction(context_list[0]->trans.get(),
5020 kSimpleGET_Transaction);
5021 }
5022
5023 // Tests than extra Read from the consumer should not hang/crash the browser.
TEST_F(HttpCacheTest,SimpleGET_ExtraRead)5024 TEST_F(HttpCacheTest, SimpleGET_ExtraRead) {
5025 MockHttpCache cache;
5026 MockHttpRequest request(kSimpleGET_Transaction);
5027 Context c;
5028
5029 c.result = cache.CreateTransaction(&c.trans);
5030 ASSERT_THAT(c.result, IsOk());
5031
5032 c.result =
5033 c.trans->Start(&request, c.callback.callback(), NetLogWithSource());
5034
5035 base::RunLoop().RunUntilIdle();
5036
5037 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5038 EXPECT_EQ(0, cache.disk_cache()->open_count());
5039 EXPECT_EQ(1, cache.disk_cache()->create_count());
5040
5041 std::string cache_key = request.CacheKey();
5042 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
5043 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
5044
5045 ReadAndVerifyTransaction(c.trans.get(), kSimpleGET_Transaction);
5046
5047 // Perform an extra Read.
5048 const int kBufferSize = 10;
5049 scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(kBufferSize);
5050 c.result = c.trans->Read(buffer.get(), kBufferSize, c.callback.callback());
5051 EXPECT_EQ(0, c.result);
5052 }
5053
5054 // Tests when a writer is destroyed mid-read, all the other writer transactions
5055 // can continue writing to the entry.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelWriter)5056 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelWriter) {
5057 MockHttpCache cache;
5058
5059 ScopedMockTransaction transaction(kSimpleGET_Transaction);
5060 transaction.response_headers =
5061 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
5062 "Content-Length: 22\n"
5063 "Etag: \"foopy\"\n";
5064 MockHttpRequest request(transaction);
5065
5066 const int kNumTransactions = 3;
5067 std::vector<std::unique_ptr<Context>> context_list;
5068
5069 for (int i = 0; i < kNumTransactions; ++i) {
5070 context_list.push_back(std::make_unique<Context>());
5071 auto& c = context_list[i];
5072
5073 c->result = cache.CreateTransaction(&c->trans);
5074 ASSERT_THAT(c->result, IsOk());
5075
5076 c->result =
5077 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5078 }
5079
5080 // Allow all requests to move from the Create queue to the active entry.
5081 base::RunLoop().RunUntilIdle();
5082
5083 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5084 EXPECT_EQ(0, cache.disk_cache()->open_count());
5085 EXPECT_EQ(1, cache.disk_cache()->create_count());
5086
5087 std::string cache_key = request.CacheKey();
5088 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
5089
5090 // Let first transaction read some bytes.
5091 {
5092 auto& c = context_list[0];
5093 const int kBufferSize = 5;
5094 scoped_refptr<IOBuffer> buffer =
5095 base::MakeRefCounted<IOBuffer>(kBufferSize);
5096 ReleaseBufferCompletionCallback cb(buffer.get());
5097 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
5098 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
5099 }
5100
5101 // Deleting the active transaction at this point will not impact the other
5102 // transactions since there are other transactions in writers.
5103 context_list[0].reset();
5104
5105 base::RunLoop().RunUntilIdle();
5106
5107 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5108 EXPECT_EQ(0, cache.disk_cache()->open_count());
5109 EXPECT_EQ(1, cache.disk_cache()->create_count());
5110
5111 // Complete the rest of the transactions.
5112 for (auto& context : context_list) {
5113 if (!context)
5114 continue;
5115 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
5116 }
5117 }
5118
5119 // Tests that when StopCaching is invoked on a writer, dependent transactions
5120 // are restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationStopCaching)5121 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationStopCaching) {
5122 MockHttpCache cache;
5123
5124 MockHttpRequest request(kSimpleGET_Transaction);
5125
5126 MockTransaction transaction(kSimpleGET_Transaction);
5127 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
5128 MockHttpRequest read_only_request(transaction);
5129
5130 const int kNumTransactions = 2;
5131 std::vector<std::unique_ptr<Context>> context_list;
5132
5133 for (int i = 0; i < kNumTransactions; ++i) {
5134 context_list.push_back(std::make_unique<Context>());
5135 auto& c = context_list[i];
5136
5137 c->result = cache.CreateTransaction(&c->trans);
5138 ASSERT_THAT(c->result, IsOk());
5139
5140 MockHttpRequest* this_request = &request;
5141 if (i == 1) {
5142 this_request = &read_only_request;
5143 }
5144
5145 c->result = c->trans->Start(this_request, c->callback.callback(),
5146 NetLogWithSource());
5147 }
5148
5149 // Allow all requests to move from the Create queue to the active entry.
5150 base::RunLoop().RunUntilIdle();
5151
5152 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5153 EXPECT_EQ(0, cache.disk_cache()->open_count());
5154 EXPECT_EQ(1, cache.disk_cache()->create_count());
5155
5156 std::string cache_key = request.CacheKey();
5157 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
5158 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
5159
5160 // Invoking StopCaching on the writer will lead to dooming the entry and
5161 // restarting the validated transactions. Since it is a read-only transaction
5162 // it will error out.
5163 context_list[0]->trans->StopCaching();
5164
5165 base::RunLoop().RunUntilIdle();
5166
5167 int rv = context_list[1]->callback.WaitForResult();
5168 EXPECT_EQ(ERR_CACHE_MISS, rv);
5169
5170 ReadAndVerifyTransaction(context_list[0]->trans.get(),
5171 kSimpleGET_Transaction);
5172 }
5173
5174 // Tests that when StopCaching is invoked on a writer transaction, it is a
5175 // no-op if there are other writer transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritersStopCachingNoOp)5176 TEST_F(HttpCacheTest, SimpleGET_ParallelWritersStopCachingNoOp) {
5177 MockHttpCache cache;
5178
5179 MockHttpRequest request(kSimpleGET_Transaction);
5180
5181 MockTransaction transaction(kSimpleGET_Transaction);
5182 transaction.load_flags |= LOAD_VALIDATE_CACHE;
5183 MockHttpRequest validate_request(transaction);
5184
5185 const int kNumTransactions = 3;
5186 std::vector<std::unique_ptr<Context>> context_list;
5187
5188 for (int i = 0; i < kNumTransactions; ++i) {
5189 context_list.push_back(std::make_unique<Context>());
5190 auto& c = context_list[i];
5191
5192 c->result = cache.CreateTransaction(&c->trans);
5193 ASSERT_THAT(c->result, IsOk());
5194
5195 MockHttpRequest* this_request = &request;
5196 if (i == 2) {
5197 this_request = &validate_request;
5198 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
5199 }
5200
5201 c->result = c->trans->Start(this_request, c->callback.callback(),
5202 NetLogWithSource());
5203 }
5204
5205 // Allow all requests to move from the Create queue to the active entry.
5206 base::RunLoop().RunUntilIdle();
5207
5208 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5209 EXPECT_EQ(0, cache.disk_cache()->open_count());
5210 EXPECT_EQ(1, cache.disk_cache()->create_count());
5211
5212 std::string cache_key = request.CacheKey();
5213 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
5214 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
5215
5216 // Invoking StopCaching on the writer will be a no-op since there are multiple
5217 // transaction in writers.
5218 context_list[0]->trans->StopCaching();
5219
5220 // Resume network start for headers_transaction.
5221 auto& c = context_list[2];
5222 c->trans->ResumeNetworkStart();
5223 base::RunLoop().RunUntilIdle();
5224 // After validation old entry will be doomed and headers_transaction will be
5225 // added to the new entry.
5226 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
5227
5228 // Complete the rest of the transactions.
5229 for (auto& context : context_list) {
5230 if (!context)
5231 continue;
5232 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
5233 }
5234
5235 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5236 EXPECT_EQ(0, cache.disk_cache()->open_count());
5237 EXPECT_EQ(2, cache.disk_cache()->create_count());
5238 }
5239
5240 // Tests that a transaction is currently in headers phase and is destroyed
5241 // leading to destroying the entry.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelHeaders)5242 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelHeaders) {
5243 MockHttpCache cache;
5244
5245 MockHttpRequest request(kSimpleGET_Transaction);
5246
5247 const int kNumTransactions = 2;
5248 std::vector<std::unique_ptr<Context>> context_list;
5249
5250 for (int i = 0; i < kNumTransactions; ++i) {
5251 context_list.push_back(std::make_unique<Context>());
5252 auto& c = context_list[i];
5253
5254 c->result = cache.CreateTransaction(&c->trans);
5255 ASSERT_THAT(c->result, IsOk());
5256
5257 if (i == 0)
5258 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
5259
5260 c->result =
5261 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5262 }
5263
5264 base::RunLoop().RunUntilIdle();
5265
5266 std::string cache_key = request.CacheKey();
5267 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
5268 EXPECT_EQ(1, cache.GetCountAddToEntryQueue(cache_key));
5269
5270 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5271 EXPECT_EQ(0, cache.disk_cache()->open_count());
5272 EXPECT_EQ(1, cache.disk_cache()->create_count());
5273
5274 // Delete the headers transaction.
5275 context_list[0].reset();
5276
5277 base::RunLoop().RunUntilIdle();
5278
5279 // Complete the rest of the transactions.
5280 for (auto& context : context_list) {
5281 if (!context)
5282 continue;
5283 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
5284 }
5285
5286 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5287 EXPECT_EQ(0, cache.disk_cache()->open_count());
5288 EXPECT_EQ(2, cache.disk_cache()->create_count());
5289 }
5290
5291 // Similar to the above test, except here cache write fails and the
5292 // validated transactions should be restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritersFailWrite)5293 TEST_F(HttpCacheTest, SimpleGET_ParallelWritersFailWrite) {
5294 MockHttpCache cache;
5295
5296 MockHttpRequest request(kSimpleGET_Transaction);
5297
5298 const int kNumTransactions = 5;
5299 std::vector<std::unique_ptr<Context>> context_list;
5300
5301 for (int i = 0; i < kNumTransactions; ++i) {
5302 context_list.push_back(std::make_unique<Context>());
5303 auto& c = context_list[i];
5304
5305 c->result = cache.CreateTransaction(&c->trans);
5306 ASSERT_THAT(c->result, IsOk());
5307 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
5308
5309 c->result =
5310 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5311 }
5312
5313 // All requests are waiting for the active entry.
5314 for (auto& context : context_list) {
5315 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
5316 }
5317
5318 // Allow all requests to move from the Create queue to the active entry.
5319 base::RunLoop().RunUntilIdle();
5320
5321 // All transactions become writers.
5322 std::string cache_key = request.CacheKey();
5323 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
5324
5325 // All requests depend on the writer, and the writer is between Start and
5326 // Read, i.e. idle.
5327 for (auto& context : context_list) {
5328 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
5329 }
5330
5331 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5332 EXPECT_EQ(0, cache.disk_cache()->open_count());
5333 EXPECT_EQ(1, cache.disk_cache()->create_count());
5334
5335 // Fail the request.
5336 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
5337 // We have to open the entry again to propagate the failure flag.
5338 disk_cache::Entry* en;
5339 cache.OpenBackendEntry(cache_key, &en);
5340 en->Close();
5341
5342 for (int i = 0; i < kNumTransactions; ++i) {
5343 auto& c = context_list[i];
5344 if (c->result == ERR_IO_PENDING)
5345 c->result = c->callback.WaitForResult();
5346 if (i == 1) {
5347 // The earlier entry must be destroyed and its disk entry doomed.
5348 EXPECT_TRUE(cache.disk_cache()->IsDiskEntryDoomed(cache_key));
5349 }
5350
5351 if (i == 0) {
5352 // Consumer gets the response even if cache write failed.
5353 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5354 } else {
5355 // Read should lead to a failure being returned.
5356 const int kBufferSize = 5;
5357 scoped_refptr<IOBuffer> buffer =
5358 base::MakeRefCounted<IOBuffer>(kBufferSize);
5359 ReleaseBufferCompletionCallback cb(buffer.get());
5360 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
5361 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, cb.GetResult(c->result));
5362 }
5363 }
5364 }
5365
5366 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4769.
5367 // If cancelling a request is racing with another request for the same resource
5368 // finishing, we have to make sure that we remove both transactions from the
5369 // entry.
TEST_F(HttpCacheTest,SimpleGET_RacingReaders)5370 TEST_F(HttpCacheTest, SimpleGET_RacingReaders) {
5371 MockHttpCache cache;
5372
5373 MockHttpRequest request(kSimpleGET_Transaction);
5374 MockHttpRequest reader_request(kSimpleGET_Transaction);
5375 reader_request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
5376
5377 std::vector<std::unique_ptr<Context>> context_list;
5378 const int kNumTransactions = 5;
5379
5380 for (int i = 0; i < kNumTransactions; ++i) {
5381 context_list.push_back(std::make_unique<Context>());
5382 Context* c = context_list[i].get();
5383
5384 c->result = cache.CreateTransaction(&c->trans);
5385 ASSERT_THAT(c->result, IsOk());
5386
5387 MockHttpRequest* this_request = &request;
5388 if (i == 1 || i == 2)
5389 this_request = &reader_request;
5390
5391 c->result = c->trans->Start(this_request, c->callback.callback(),
5392 NetLogWithSource());
5393 }
5394
5395 // Allow all requests to move from the Create queue to the active entry.
5396 base::RunLoop().RunUntilIdle();
5397
5398 // The first request should be a writer at this point, and the subsequent
5399 // requests should be pending.
5400
5401 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5402 EXPECT_EQ(0, cache.disk_cache()->open_count());
5403 EXPECT_EQ(1, cache.disk_cache()->create_count());
5404
5405 Context* c = context_list[0].get();
5406 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5407 c->result = c->callback.WaitForResult();
5408 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5409
5410 // Now all transactions should be waiting for read to be invoked. Two readers
5411 // are because of the load flags and remaining two transactions were converted
5412 // to readers after skipping validation. Note that the remaining two went on
5413 // to process the headers in parallel with readers present on the entry.
5414 EXPECT_EQ(LOAD_STATE_IDLE, context_list[2]->trans->GetLoadState());
5415 EXPECT_EQ(LOAD_STATE_IDLE, context_list[3]->trans->GetLoadState());
5416
5417 c = context_list[1].get();
5418 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5419 c->result = c->callback.WaitForResult();
5420 if (c->result == OK)
5421 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5422
5423 // At this point we have one reader, two pending transactions and a task on
5424 // the queue to move to the next transaction. Now we cancel the request that
5425 // is the current reader, and expect the queued task to be able to start the
5426 // next request.
5427
5428 c = context_list[2].get();
5429 c->trans.reset();
5430
5431 for (int i = 3; i < kNumTransactions; ++i) {
5432 c = context_list[i].get();
5433 if (c->result == ERR_IO_PENDING)
5434 c->result = c->callback.WaitForResult();
5435 if (c->result == OK)
5436 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5437 }
5438
5439 // We should not have had to re-open the disk entry.
5440
5441 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5442 EXPECT_EQ(0, cache.disk_cache()->open_count());
5443 EXPECT_EQ(1, cache.disk_cache()->create_count());
5444 }
5445
5446 // Tests that we can doom an entry with pending transactions and delete one of
5447 // the pending transactions before the first one completes.
5448 // See http://code.google.com/p/chromium/issues/detail?id=25588
TEST_F(HttpCacheTest,SimpleGET_DoomWithPending)5449 TEST_F(HttpCacheTest, SimpleGET_DoomWithPending) {
5450 // We need simultaneous doomed / not_doomed entries so let's use a real cache.
5451 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
5452
5453 MockHttpRequest request(kSimpleGET_Transaction);
5454 MockHttpRequest writer_request(kSimpleGET_Transaction);
5455 writer_request.load_flags = LOAD_BYPASS_CACHE;
5456
5457 std::vector<std::unique_ptr<Context>> context_list;
5458 const int kNumTransactions = 4;
5459
5460 for (int i = 0; i < kNumTransactions; ++i) {
5461 context_list.push_back(std::make_unique<Context>());
5462 Context* c = context_list[i].get();
5463
5464 c->result = cache.CreateTransaction(&c->trans);
5465 ASSERT_THAT(c->result, IsOk());
5466
5467 MockHttpRequest* this_request = &request;
5468 if (i == 3)
5469 this_request = &writer_request;
5470
5471 c->result = c->trans->Start(this_request, c->callback.callback(),
5472 NetLogWithSource());
5473 }
5474
5475 base::RunLoop().RunUntilIdle();
5476
5477 // The first request should be a writer at this point, and the two subsequent
5478 // requests should be pending. The last request doomed the first entry.
5479
5480 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5481
5482 // Cancel the second transaction. Note that this and the 3rd transactions
5483 // would have completed their headers phase and would be waiting in the
5484 // done_headers_queue when the 2nd transaction is cancelled.
5485 context_list[1].reset();
5486
5487 for (int i = 0; i < kNumTransactions; ++i) {
5488 if (i == 1)
5489 continue;
5490 Context* c = context_list[i].get();
5491 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5492 c->result = c->callback.WaitForResult();
5493 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5494 }
5495 }
5496
TEST_F(HttpCacheTest,DoomDoesNotSetHints)5497 TEST_F(HttpCacheTest, DoomDoesNotSetHints) {
5498 // Test that a doomed writer doesn't set in-memory index hints.
5499 MockHttpCache cache;
5500 cache.disk_cache()->set_support_in_memory_entry_data(true);
5501
5502 // Request 1 is a normal one to a no-cache/no-etag resource, to potentially
5503 // set a "this is unvalidatable" hint in the cache. We also need it to
5504 // actually write out to the doomed entry after request 2 does its thing,
5505 // so its transaction is paused.
5506 MockTransaction no_cache_transaction(kSimpleGET_Transaction);
5507 no_cache_transaction.response_headers = "Cache-Control: no-cache\n";
5508 AddMockTransaction(&no_cache_transaction);
5509 MockHttpRequest request1(no_cache_transaction);
5510
5511 Context c1;
5512 c1.result = cache.CreateTransaction(&c1.trans);
5513 ASSERT_THAT(c1.result, IsOk());
5514 c1.trans->SetBeforeNetworkStartCallback(
5515 base::BindOnce([](bool* defer) { *defer = true; }));
5516 c1.result =
5517 c1.trans->Start(&request1, c1.callback.callback(), NetLogWithSource());
5518 ASSERT_THAT(c1.result, IsError(ERR_IO_PENDING));
5519
5520 // It starts, copies over headers info, but doesn't get to proceed.
5521 base::RunLoop().RunUntilIdle();
5522 RemoveMockTransaction(&no_cache_transaction);
5523
5524 // Request 2 sets LOAD_BYPASS_CACHE to force the first one to be doomed ---
5525 // it'll want to be a writer.
5526 MockHttpRequest request2(kSimpleGET_Transaction);
5527 request2.load_flags = LOAD_BYPASS_CACHE;
5528
5529 Context c2;
5530 c2.result = cache.CreateTransaction(&c2.trans);
5531 ASSERT_THAT(c2.result, IsOk());
5532 c2.result =
5533 c2.trans->Start(&request2, c2.callback.callback(), NetLogWithSource());
5534 ASSERT_THAT(c2.result, IsError(ERR_IO_PENDING));
5535
5536 // Run Request2, then let the first one wrap up.
5537 base::RunLoop().RunUntilIdle();
5538 c2.callback.WaitForResult();
5539 ReadAndVerifyTransaction(c2.trans.get(), kSimpleGET_Transaction);
5540
5541 c1.trans->ResumeNetworkStart();
5542 c1.callback.WaitForResult();
5543 ReadAndVerifyTransaction(c1.trans.get(), no_cache_transaction);
5544
5545 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5546 EXPECT_EQ(0, cache.disk_cache()->open_count());
5547 EXPECT_EQ(2, cache.disk_cache()->create_count());
5548
5549 // Request 3 tries to read from cache, and it should successfully do so. It's
5550 // run after the previous two transactions finish so it doesn't try to
5551 // cooperate with them, and is entirely driven by the state of the cache.
5552 MockHttpRequest request3(kSimpleGET_Transaction);
5553 Context context3;
5554 context3.result = cache.CreateTransaction(&context3.trans);
5555 ASSERT_THAT(context3.result, IsOk());
5556 context3.result = context3.trans->Start(
5557 &request3, context3.callback.callback(), NetLogWithSource());
5558 base::RunLoop().RunUntilIdle();
5559 ASSERT_THAT(context3.result, IsError(ERR_IO_PENDING));
5560 context3.result = context3.callback.WaitForResult();
5561 ReadAndVerifyTransaction(context3.trans.get(), kSimpleGET_Transaction);
5562
5563 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5564 EXPECT_EQ(1, cache.disk_cache()->open_count());
5565 EXPECT_EQ(2, cache.disk_cache()->create_count());
5566 }
5567
5568 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4731.
5569 // We may attempt to delete an entry synchronously with the act of adding a new
5570 // transaction to said entry.
TEST_F(HttpCacheTest,FastNoStoreGET_DoneWithPending)5571 TEST_F(HttpCacheTest, FastNoStoreGET_DoneWithPending) {
5572 MockHttpCache cache;
5573
5574 // The headers will be served right from the call to Start() the request.
5575 MockHttpRequest request(kFastNoStoreGET_Transaction);
5576 FastTransactionServer request_handler;
5577 AddMockTransaction(&kFastNoStoreGET_Transaction);
5578
5579 std::vector<std::unique_ptr<Context>> context_list;
5580 const int kNumTransactions = 3;
5581
5582 for (int i = 0; i < kNumTransactions; ++i) {
5583 context_list.push_back(std::make_unique<Context>());
5584 Context* c = context_list[i].get();
5585
5586 c->result = cache.CreateTransaction(&c->trans);
5587 ASSERT_THAT(c->result, IsOk());
5588
5589 c->result =
5590 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5591 }
5592
5593 // Allow all requests to move from the Create queue to the active entry.
5594 base::RunLoop().RunUntilIdle();
5595
5596 // The first request should be a writer at this point, and the subsequent
5597 // requests should have completed validation. Since the validation does not
5598 // result in a match, a new entry would be created.
5599
5600 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5601 EXPECT_EQ(0, cache.disk_cache()->open_count());
5602 EXPECT_EQ(3, cache.disk_cache()->create_count());
5603
5604 // Now, make sure that the second request asks for the entry not to be stored.
5605 request_handler.set_no_store(true);
5606
5607 for (int i = 0; i < kNumTransactions; ++i) {
5608 Context* c = context_list[i].get();
5609 if (c->result == ERR_IO_PENDING)
5610 c->result = c->callback.WaitForResult();
5611 ReadAndVerifyTransaction(c->trans.get(), kFastNoStoreGET_Transaction);
5612 context_list[i].reset();
5613 }
5614
5615 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5616 EXPECT_EQ(0, cache.disk_cache()->open_count());
5617 EXPECT_EQ(3, cache.disk_cache()->create_count());
5618
5619 RemoveMockTransaction(&kFastNoStoreGET_Transaction);
5620 }
5621
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_CancelFirst)5622 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_CancelFirst) {
5623 MockHttpCache cache;
5624
5625 MockHttpRequest request(kSimpleGET_Transaction);
5626
5627 std::vector<std::unique_ptr<Context>> context_list;
5628 const int kNumTransactions = 2;
5629
5630 for (int i = 0; i < kNumTransactions; ++i) {
5631 context_list.push_back(std::make_unique<Context>());
5632 Context* c = context_list[i].get();
5633
5634 c->result = cache.CreateTransaction(&c->trans);
5635 ASSERT_THAT(c->result, IsOk());
5636
5637 c->result =
5638 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5639 }
5640
5641 // Allow all requests to move from the Create queue to the active entry.
5642 // All would have been added to writers.
5643 base::RunLoop().RunUntilIdle();
5644 std::string cache_key =
5645 *cache.http_cache()->GenerateCacheKeyForRequest(&request);
5646 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
5647
5648 // The second transaction skipped validation, thus only one network
5649 // transaction is created.
5650 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5651 EXPECT_EQ(0, cache.disk_cache()->open_count());
5652 EXPECT_EQ(1, cache.disk_cache()->create_count());
5653
5654 for (int i = 0; i < kNumTransactions; ++i) {
5655 Context* c = context_list[i].get();
5656 if (c->result == ERR_IO_PENDING)
5657 c->result = c->callback.WaitForResult();
5658 // Destroy only the first transaction.
5659 // This should not impact the other writer transaction and the network
5660 // transaction will continue to be used by that transaction.
5661 if (i == 0) {
5662 context_list[i].reset();
5663 }
5664 }
5665
5666 // Complete the rest of the transactions.
5667 for (int i = 1; i < kNumTransactions; ++i) {
5668 Context* c = context_list[i].get();
5669 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5670 }
5671
5672 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5673 EXPECT_EQ(0, cache.disk_cache()->open_count());
5674 EXPECT_EQ(1, cache.disk_cache()->create_count());
5675 }
5676
5677 // Tests that we can cancel requests that are queued waiting to open the disk
5678 // cache entry.
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_CancelCreate)5679 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_CancelCreate) {
5680 MockHttpCache cache;
5681
5682 MockHttpRequest request(kSimpleGET_Transaction);
5683
5684 std::vector<std::unique_ptr<Context>> context_list;
5685 const int kNumTransactions = 5;
5686
5687 for (int i = 0; i < kNumTransactions; i++) {
5688 context_list.push_back(std::make_unique<Context>());
5689 Context* c = context_list[i].get();
5690
5691 c->result = cache.CreateTransaction(&c->trans);
5692 ASSERT_THAT(c->result, IsOk());
5693
5694 c->result =
5695 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5696 }
5697
5698 // The first request should be creating the disk cache entry and the others
5699 // should be pending.
5700
5701 EXPECT_EQ(0, cache.network_layer()->transaction_count());
5702 EXPECT_EQ(0, cache.disk_cache()->open_count());
5703 EXPECT_EQ(1, cache.disk_cache()->create_count());
5704
5705 // Cancel a request from the pending queue.
5706 context_list[3].reset();
5707
5708 // Cancel the request that is creating the entry. This will force the pending
5709 // operations to restart.
5710 context_list[0].reset();
5711
5712 // Complete the rest of the transactions.
5713 for (int i = 1; i < kNumTransactions; i++) {
5714 Context* c = context_list[i].get();
5715 if (c) {
5716 c->result = c->callback.GetResult(c->result);
5717 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5718 }
5719 }
5720
5721 // We should have had to re-create the disk entry.
5722
5723 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5724 EXPECT_EQ(0, cache.disk_cache()->open_count());
5725 EXPECT_EQ(2, cache.disk_cache()->create_count());
5726 }
5727
5728 // Tests that we can cancel a single request to open a disk cache entry.
TEST_F(HttpCacheTest,SimpleGET_CancelCreate)5729 TEST_F(HttpCacheTest, SimpleGET_CancelCreate) {
5730 MockHttpCache cache;
5731
5732 MockHttpRequest request(kSimpleGET_Transaction);
5733
5734 auto c = std::make_unique<Context>();
5735
5736 c->result = cache.CreateTransaction(&c->trans);
5737 ASSERT_THAT(c->result, IsOk());
5738
5739 c->result =
5740 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5741 EXPECT_THAT(c->result, IsError(ERR_IO_PENDING));
5742
5743 // Release the reference that the mock disk cache keeps for this entry, so
5744 // that we test that the http cache handles the cancellation correctly.
5745 cache.disk_cache()->ReleaseAll();
5746 c.reset();
5747
5748 base::RunLoop().RunUntilIdle();
5749 EXPECT_EQ(1, cache.disk_cache()->create_count());
5750 }
5751
5752 // Tests that we delete/create entries even if multiple requests are queued.
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_BypassCache)5753 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_BypassCache) {
5754 MockHttpCache cache;
5755
5756 MockHttpRequest request(kSimpleGET_Transaction);
5757 request.load_flags = LOAD_BYPASS_CACHE;
5758
5759 std::vector<std::unique_ptr<Context>> context_list;
5760 const int kNumTransactions = 5;
5761
5762 for (int i = 0; i < kNumTransactions; i++) {
5763 context_list.push_back(std::make_unique<Context>());
5764 Context* c = context_list[i].get();
5765
5766 c->result = cache.CreateTransaction(&c->trans);
5767 ASSERT_THAT(c->result, IsOk());
5768
5769 c->result =
5770 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5771 }
5772
5773 // The first request should be deleting the disk cache entry and the others
5774 // should be pending.
5775
5776 EXPECT_EQ(0, cache.network_layer()->transaction_count());
5777 EXPECT_EQ(0, cache.disk_cache()->open_count());
5778 EXPECT_EQ(0, cache.disk_cache()->create_count());
5779
5780 // Complete the transactions.
5781 for (int i = 0; i < kNumTransactions; i++) {
5782 Context* c = context_list[i].get();
5783 c->result = c->callback.GetResult(c->result);
5784 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5785 }
5786
5787 // We should have had to re-create the disk entry multiple times.
5788
5789 EXPECT_EQ(5, cache.network_layer()->transaction_count());
5790 EXPECT_EQ(0, cache.disk_cache()->open_count());
5791 EXPECT_EQ(5, cache.disk_cache()->create_count());
5792 }
5793
5794 // Tests that a (simulated) timeout allows transactions waiting on the cache
5795 // lock to continue.
TEST_F(HttpCacheTest,SimpleGET_WriterTimeout)5796 TEST_F(HttpCacheTest, SimpleGET_WriterTimeout) {
5797 MockHttpCache cache;
5798 cache.SimulateCacheLockTimeout();
5799
5800 MockHttpRequest request(kSimpleGET_Transaction);
5801 Context c1, c2;
5802 ASSERT_THAT(cache.CreateTransaction(&c1.trans), IsOk());
5803 ASSERT_EQ(ERR_IO_PENDING, c1.trans->Start(&request, c1.callback.callback(),
5804 NetLogWithSource()));
5805 ASSERT_THAT(cache.CreateTransaction(&c2.trans), IsOk());
5806 ASSERT_EQ(ERR_IO_PENDING, c2.trans->Start(&request, c2.callback.callback(),
5807 NetLogWithSource()));
5808
5809 // The second request is queued after the first one.
5810
5811 c2.callback.WaitForResult();
5812 ReadAndVerifyTransaction(c2.trans.get(), kSimpleGET_Transaction);
5813
5814 // Complete the first transaction.
5815 c1.callback.WaitForResult();
5816 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
5817 }
5818
5819 // Tests that a (simulated) timeout allows transactions waiting on the cache
5820 // lock to continue but read only transactions to error out.
TEST_F(HttpCacheTest,SimpleGET_WriterTimeoutReadOnlyError)5821 TEST_F(HttpCacheTest, SimpleGET_WriterTimeoutReadOnlyError) {
5822 MockHttpCache cache;
5823
5824 // Simulate timeout.
5825 cache.SimulateCacheLockTimeout();
5826
5827 MockHttpRequest request(kSimpleGET_Transaction);
5828 Context c1, c2;
5829 ASSERT_THAT(cache.CreateTransaction(&c1.trans), IsOk());
5830 ASSERT_EQ(ERR_IO_PENDING, c1.trans->Start(&request, c1.callback.callback(),
5831 NetLogWithSource()));
5832
5833 request.load_flags = LOAD_ONLY_FROM_CACHE;
5834 ASSERT_THAT(cache.CreateTransaction(&c2.trans), IsOk());
5835 ASSERT_EQ(ERR_IO_PENDING, c2.trans->Start(&request, c2.callback.callback(),
5836 NetLogWithSource()));
5837
5838 // The second request is queued after the first one.
5839 int res = c2.callback.WaitForResult();
5840 ASSERT_EQ(ERR_CACHE_MISS, res);
5841
5842 // Complete the first transaction.
5843 c1.callback.WaitForResult();
5844 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
5845 }
5846
TEST_F(HttpCacheTest,SimpleGET_AbandonedCacheRead)5847 TEST_F(HttpCacheTest, SimpleGET_AbandonedCacheRead) {
5848 MockHttpCache cache;
5849
5850 // write to the cache
5851 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5852
5853 MockHttpRequest request(kSimpleGET_Transaction);
5854 TestCompletionCallback callback;
5855
5856 std::unique_ptr<HttpTransaction> trans;
5857 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
5858 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5859 if (rv == ERR_IO_PENDING)
5860 rv = callback.WaitForResult();
5861 ASSERT_THAT(rv, IsOk());
5862
5863 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
5864 rv = trans->Read(buf.get(), 256, callback.callback());
5865 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5866
5867 // Test that destroying the transaction while it is reading from the cache
5868 // works properly.
5869 trans.reset();
5870
5871 // Make sure we pump any pending events, which should include a call to
5872 // HttpCache::Transaction::OnCacheReadCompleted.
5873 base::RunLoop().RunUntilIdle();
5874 }
5875
5876 // Tests that we can delete the HttpCache and deal with queued transactions
5877 // ("waiting for the backend" as opposed to Active or Doomed entries).
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_DeleteCache)5878 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_DeleteCache) {
5879 auto cache = std::make_unique<MockHttpCache>(
5880 std::make_unique<MockBackendNoCbFactory>());
5881
5882 MockHttpRequest request(kSimpleGET_Transaction);
5883
5884 std::vector<std::unique_ptr<Context>> context_list;
5885 const int kNumTransactions = 5;
5886
5887 for (int i = 0; i < kNumTransactions; i++) {
5888 context_list.push_back(std::make_unique<Context>());
5889 Context* c = context_list[i].get();
5890
5891 c->result = cache->CreateTransaction(&c->trans);
5892 ASSERT_THAT(c->result, IsOk());
5893
5894 c->result =
5895 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5896 }
5897
5898 // The first request should be creating the disk cache entry and the others
5899 // should be pending.
5900
5901 EXPECT_EQ(0, cache->network_layer()->transaction_count());
5902 EXPECT_EQ(0, cache->disk_cache()->open_count());
5903 EXPECT_EQ(0, cache->disk_cache()->create_count());
5904
5905 cache.reset();
5906 }
5907
5908 // Tests that we queue requests when initializing the backend.
TEST_F(HttpCacheTest,SimpleGET_WaitForBackend)5909 TEST_F(HttpCacheTest, SimpleGET_WaitForBackend) {
5910 auto factory = std::make_unique<MockBlockingBackendFactory>();
5911 MockBlockingBackendFactory* factory_ptr = factory.get();
5912 MockHttpCache cache(std::move(factory));
5913
5914 MockHttpRequest request0(kSimpleGET_Transaction);
5915 MockHttpRequest request1(kTypicalGET_Transaction);
5916 MockHttpRequest request2(kETagGET_Transaction);
5917
5918 std::vector<std::unique_ptr<Context>> context_list;
5919 const int kNumTransactions = 3;
5920
5921 for (int i = 0; i < kNumTransactions; i++) {
5922 context_list.push_back(std::make_unique<Context>());
5923 Context* c = context_list[i].get();
5924
5925 c->result = cache.CreateTransaction(&c->trans);
5926 ASSERT_THAT(c->result, IsOk());
5927 }
5928
5929 context_list[0]->result = context_list[0]->trans->Start(
5930 &request0, context_list[0]->callback.callback(), NetLogWithSource());
5931 context_list[1]->result = context_list[1]->trans->Start(
5932 &request1, context_list[1]->callback.callback(), NetLogWithSource());
5933 context_list[2]->result = context_list[2]->trans->Start(
5934 &request2, context_list[2]->callback.callback(), NetLogWithSource());
5935
5936 // Just to make sure that everything is still pending.
5937 base::RunLoop().RunUntilIdle();
5938
5939 // The first request should be creating the disk cache.
5940 EXPECT_FALSE(context_list[0]->callback.have_result());
5941
5942 factory_ptr->FinishCreation();
5943
5944 base::RunLoop().RunUntilIdle();
5945 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5946 EXPECT_EQ(3, cache.disk_cache()->create_count());
5947
5948 for (int i = 0; i < kNumTransactions; ++i) {
5949 EXPECT_TRUE(context_list[i]->callback.have_result());
5950 context_list[i].reset();
5951 }
5952 }
5953
5954 // Tests that we can cancel requests that are queued waiting for the backend
5955 // to be initialized.
TEST_F(HttpCacheTest,SimpleGET_WaitForBackend_CancelCreate)5956 TEST_F(HttpCacheTest, SimpleGET_WaitForBackend_CancelCreate) {
5957 auto factory = std::make_unique<MockBlockingBackendFactory>();
5958 MockBlockingBackendFactory* factory_ptr = factory.get();
5959 MockHttpCache cache(std::move(factory));
5960
5961 MockHttpRequest request0(kSimpleGET_Transaction);
5962 MockHttpRequest request1(kTypicalGET_Transaction);
5963 MockHttpRequest request2(kETagGET_Transaction);
5964
5965 std::vector<std::unique_ptr<Context>> context_list;
5966 const int kNumTransactions = 3;
5967
5968 for (int i = 0; i < kNumTransactions; i++) {
5969 context_list.push_back(std::make_unique<Context>());
5970 Context* c = context_list[i].get();
5971
5972 c->result = cache.CreateTransaction(&c->trans);
5973 ASSERT_THAT(c->result, IsOk());
5974 }
5975
5976 context_list[0]->result = context_list[0]->trans->Start(
5977 &request0, context_list[0]->callback.callback(), NetLogWithSource());
5978 context_list[1]->result = context_list[1]->trans->Start(
5979 &request1, context_list[1]->callback.callback(), NetLogWithSource());
5980 context_list[2]->result = context_list[2]->trans->Start(
5981 &request2, context_list[2]->callback.callback(), NetLogWithSource());
5982
5983 // Just to make sure that everything is still pending.
5984 base::RunLoop().RunUntilIdle();
5985
5986 // The first request should be creating the disk cache.
5987 EXPECT_FALSE(context_list[0]->callback.have_result());
5988
5989 // Cancel a request from the pending queue.
5990 context_list[1].reset();
5991
5992 // Cancel the request that is creating the entry.
5993 context_list[0].reset();
5994
5995 // Complete the last transaction.
5996 factory_ptr->FinishCreation();
5997
5998 context_list[2]->result =
5999 context_list[2]->callback.GetResult(context_list[2]->result);
6000 ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction);
6001
6002 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6003 EXPECT_EQ(1, cache.disk_cache()->create_count());
6004 }
6005
6006 // Tests that we can delete the HttpCache while creating the backend.
TEST_F(HttpCacheTest,DeleteCacheWaitingForBackend)6007 TEST_F(HttpCacheTest, DeleteCacheWaitingForBackend) {
6008 auto factory = std::make_unique<MockBlockingBackendFactory>();
6009 MockBlockingBackendFactory* factory_ptr = factory.get();
6010 auto cache = std::make_unique<MockHttpCache>(std::move(factory));
6011
6012 MockHttpRequest request(kSimpleGET_Transaction);
6013
6014 auto c = std::make_unique<Context>();
6015 c->result = cache->CreateTransaction(&c->trans);
6016 ASSERT_THAT(c->result, IsOk());
6017
6018 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
6019
6020 // Just to make sure that everything is still pending.
6021 base::RunLoop().RunUntilIdle();
6022
6023 // The request should be creating the disk cache.
6024 EXPECT_FALSE(c->callback.have_result());
6025
6026 // Manually arrange for completion to happen after ~HttpCache.
6027 // This can't be done via FinishCreation() since that's in `factory`, and
6028 // that's owned by `cache`.
6029 disk_cache::BackendResultCallback callback = factory_ptr->ReleaseCallback();
6030
6031 cache.reset();
6032 base::RunLoop().RunUntilIdle();
6033
6034 // Simulate the backend completion callback running now the HttpCache is gone.
6035 std::move(callback).Run(disk_cache::BackendResult::MakeError(ERR_ABORTED));
6036 }
6037
6038 // Tests that we can delete the cache while creating the backend, from within
6039 // one of the callbacks.
TEST_F(HttpCacheTest,DeleteCacheWaitingForBackend2)6040 TEST_F(HttpCacheTest, DeleteCacheWaitingForBackend2) {
6041 auto factory = std::make_unique<MockBlockingBackendFactory>();
6042 MockBlockingBackendFactory* factory_ptr = factory.get();
6043 auto cache = std::make_unique<MockHttpCache>(std::move(factory));
6044 auto* cache_ptr = cache.get();
6045
6046 DeleteCacheCompletionCallback cb(std::move(cache));
6047 disk_cache::Backend* backend;
6048 int rv = cache_ptr->http_cache()->GetBackend(&backend, cb.callback());
6049 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6050
6051 // Now let's queue a regular transaction
6052 MockHttpRequest request(kSimpleGET_Transaction);
6053
6054 auto c = std::make_unique<Context>();
6055 c->result = cache_ptr->CreateTransaction(&c->trans);
6056 ASSERT_THAT(c->result, IsOk());
6057
6058 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
6059
6060 // And another direct backend request.
6061 TestCompletionCallback cb2;
6062 rv = cache_ptr->http_cache()->GetBackend(&backend, cb2.callback());
6063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6064
6065 // Just to make sure that everything is still pending.
6066 base::RunLoop().RunUntilIdle();
6067
6068 // The request should be queued.
6069 EXPECT_FALSE(c->callback.have_result());
6070
6071 // Generate the callback.
6072 factory_ptr->FinishCreation();
6073 rv = cb.WaitForResult();
6074
6075 // The cache should be gone by now.
6076 base::RunLoop().RunUntilIdle();
6077 EXPECT_THAT(c->callback.GetResult(c->result), IsOk());
6078 EXPECT_FALSE(cb2.have_result());
6079 }
6080
TEST_F(HttpCacheTest,TypicalGET_ConditionalRequest)6081 TEST_F(HttpCacheTest, TypicalGET_ConditionalRequest) {
6082 MockHttpCache cache;
6083
6084 // write to the cache
6085 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
6086
6087 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6088 EXPECT_EQ(0, cache.disk_cache()->open_count());
6089 EXPECT_EQ(1, cache.disk_cache()->create_count());
6090
6091 // Get the same URL again, but this time we expect it to result
6092 // in a conditional request.
6093 LoadTimingInfo load_timing_info;
6094 RunTransactionTestAndGetTiming(cache.http_cache(), kTypicalGET_Transaction,
6095 NetLogWithSource::Make(NetLogSourceType::NONE),
6096 &load_timing_info);
6097
6098 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6099 EXPECT_EQ(1, cache.disk_cache()->open_count());
6100 EXPECT_EQ(1, cache.disk_cache()->create_count());
6101 TestLoadTimingNetworkRequest(load_timing_info);
6102 }
6103
ETagGet_ConditionalRequest_Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)6104 static void ETagGet_ConditionalRequest_Handler(const HttpRequestInfo* request,
6105 std::string* response_status,
6106 std::string* response_headers,
6107 std::string* response_data) {
6108 EXPECT_TRUE(
6109 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6110 response_status->assign("HTTP/1.1 304 Not Modified");
6111 response_headers->assign(kETagGET_Transaction.response_headers);
6112 response_data->clear();
6113 }
6114
TEST_F(HttpCacheTest,ETagGET_ConditionalRequest_304)6115 TEST_F(HttpCacheTest, ETagGET_ConditionalRequest_304) {
6116 MockHttpCache cache;
6117
6118 ScopedMockTransaction transaction(kETagGET_Transaction);
6119
6120 // write to the cache
6121 RunTransactionTest(cache.http_cache(), transaction);
6122
6123 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6124 EXPECT_EQ(0, cache.disk_cache()->open_count());
6125 EXPECT_EQ(1, cache.disk_cache()->create_count());
6126
6127 // Get the same URL again, but this time we expect it to result
6128 // in a conditional request.
6129 transaction.load_flags = LOAD_VALIDATE_CACHE;
6130 transaction.handler = ETagGet_ConditionalRequest_Handler;
6131 LoadTimingInfo load_timing_info;
6132 IPEndPoint remote_endpoint;
6133 RunTransactionTestAndGetTimingAndConnectedSocketAddress(
6134 cache.http_cache(), transaction,
6135 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info,
6136 &remote_endpoint);
6137
6138 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6139 EXPECT_EQ(1, cache.disk_cache()->open_count());
6140 EXPECT_EQ(1, cache.disk_cache()->create_count());
6141 TestLoadTimingNetworkRequest(load_timing_info);
6142
6143 EXPECT_FALSE(remote_endpoint.address().empty());
6144 }
6145
6146 class RevalidationServer {
6147 public:
RevalidationServer()6148 RevalidationServer() {
6149 s_etag_used_ = false;
6150 s_last_modified_used_ = false;
6151 }
6152
EtagUsed()6153 bool EtagUsed() { return s_etag_used_; }
LastModifiedUsed()6154 bool LastModifiedUsed() { return s_last_modified_used_; }
6155
6156 static void Handler(const HttpRequestInfo* request,
6157 std::string* response_status,
6158 std::string* response_headers,
6159 std::string* response_data);
6160
6161 private:
6162 static bool s_etag_used_;
6163 static bool s_last_modified_used_;
6164 };
6165 bool RevalidationServer::s_etag_used_ = false;
6166 bool RevalidationServer::s_last_modified_used_ = false;
6167
Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)6168 void RevalidationServer::Handler(const HttpRequestInfo* request,
6169 std::string* response_status,
6170 std::string* response_headers,
6171 std::string* response_data) {
6172 if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch))
6173 s_etag_used_ = true;
6174
6175 if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfModifiedSince)) {
6176 s_last_modified_used_ = true;
6177 }
6178
6179 if (s_etag_used_ || s_last_modified_used_) {
6180 response_status->assign("HTTP/1.1 304 Not Modified");
6181 response_headers->assign(kTypicalGET_Transaction.response_headers);
6182 response_data->clear();
6183 } else {
6184 response_status->assign(kTypicalGET_Transaction.status);
6185 response_headers->assign(kTypicalGET_Transaction.response_headers);
6186 response_data->assign(kTypicalGET_Transaction.data);
6187 }
6188 }
6189
6190 // Tests revalidation after a vary match.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch)6191 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch) {
6192 MockHttpCache cache;
6193
6194 // Write to the cache.
6195 MockTransaction transaction(kTypicalGET_Transaction);
6196 transaction.request_headers = "Foo: bar\r\n";
6197 transaction.response_headers =
6198 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6199 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6200 "Etag: \"foopy\"\n"
6201 "Cache-Control: max-age=0\n"
6202 "Vary: Foo\n";
6203 AddMockTransaction(&transaction);
6204 RunTransactionTest(cache.http_cache(), transaction);
6205
6206 // Read from the cache.
6207 RevalidationServer server;
6208 transaction.handler = server.Handler;
6209 LoadTimingInfo load_timing_info;
6210 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6211 NetLogWithSource::Make(NetLogSourceType::NONE),
6212 &load_timing_info);
6213
6214 EXPECT_TRUE(server.EtagUsed());
6215 EXPECT_TRUE(server.LastModifiedUsed());
6216 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6217 EXPECT_EQ(1, cache.disk_cache()->open_count());
6218 EXPECT_EQ(1, cache.disk_cache()->create_count());
6219 TestLoadTimingNetworkRequest(load_timing_info);
6220 RemoveMockTransaction(&transaction);
6221 }
6222
6223 // Tests revalidation after a vary mismatch if etag is present.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch)6224 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch) {
6225 MockHttpCache cache;
6226
6227 // Write to the cache.
6228 MockTransaction transaction(kTypicalGET_Transaction);
6229 transaction.request_headers = "Foo: bar\r\n";
6230 transaction.response_headers =
6231 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6232 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6233 "Etag: \"foopy\"\n"
6234 "Cache-Control: max-age=0\n"
6235 "Vary: Foo\n";
6236 AddMockTransaction(&transaction);
6237 RunTransactionTest(cache.http_cache(), transaction);
6238
6239 // Read from the cache and revalidate the entry.
6240 RevalidationServer server;
6241 transaction.handler = server.Handler;
6242 transaction.request_headers = "Foo: none\r\n";
6243 LoadTimingInfo load_timing_info;
6244 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6245 NetLogWithSource::Make(NetLogSourceType::NONE),
6246 &load_timing_info);
6247
6248 EXPECT_TRUE(server.EtagUsed());
6249 EXPECT_FALSE(server.LastModifiedUsed());
6250 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6251 EXPECT_EQ(1, cache.disk_cache()->open_count());
6252 EXPECT_EQ(1, cache.disk_cache()->create_count());
6253 TestLoadTimingNetworkRequest(load_timing_info);
6254 RemoveMockTransaction(&transaction);
6255 }
6256
6257 // Tests revalidation after a vary mismatch due to vary: * if etag is present.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatchStar)6258 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatchStar) {
6259 MockHttpCache cache;
6260
6261 // Write to the cache.
6262 MockTransaction transaction(kTypicalGET_Transaction);
6263 transaction.response_headers =
6264 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6265 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6266 "Etag: \"foopy\"\n"
6267 "Cache-Control: max-age=0\n"
6268 "Vary: *\n";
6269 AddMockTransaction(&transaction);
6270 RunTransactionTest(cache.http_cache(), transaction);
6271
6272 // Read from the cache and revalidate the entry.
6273 RevalidationServer server;
6274 transaction.handler = server.Handler;
6275 LoadTimingInfo load_timing_info;
6276 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6277 NetLogWithSource::Make(NetLogSourceType::NONE),
6278 &load_timing_info);
6279
6280 EXPECT_TRUE(server.EtagUsed());
6281 EXPECT_FALSE(server.LastModifiedUsed());
6282 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6283 EXPECT_EQ(1, cache.disk_cache()->open_count());
6284 EXPECT_EQ(1, cache.disk_cache()->create_count());
6285 TestLoadTimingNetworkRequest(load_timing_info);
6286 RemoveMockTransaction(&transaction);
6287 }
6288
6289 // Tests lack of revalidation after a vary mismatch and no etag.
TEST_F(HttpCacheTest,GET_DontValidateCache_VaryMismatch)6290 TEST_F(HttpCacheTest, GET_DontValidateCache_VaryMismatch) {
6291 MockHttpCache cache;
6292
6293 // Write to the cache.
6294 MockTransaction transaction(kTypicalGET_Transaction);
6295 transaction.request_headers = "Foo: bar\r\n";
6296 transaction.response_headers =
6297 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6298 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6299 "Cache-Control: max-age=0\n"
6300 "Vary: Foo\n";
6301 AddMockTransaction(&transaction);
6302 RunTransactionTest(cache.http_cache(), transaction);
6303
6304 // Read from the cache and don't revalidate the entry.
6305 RevalidationServer server;
6306 transaction.handler = server.Handler;
6307 transaction.request_headers = "Foo: none\r\n";
6308 LoadTimingInfo load_timing_info;
6309 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6310 NetLogWithSource::Make(NetLogSourceType::NONE),
6311 &load_timing_info);
6312
6313 EXPECT_FALSE(server.EtagUsed());
6314 EXPECT_FALSE(server.LastModifiedUsed());
6315 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6316 EXPECT_EQ(1, cache.disk_cache()->open_count());
6317 EXPECT_EQ(1, cache.disk_cache()->create_count());
6318 TestLoadTimingNetworkRequest(load_timing_info);
6319 RemoveMockTransaction(&transaction);
6320 }
6321
6322 // Tests that a new vary header provided when revalidating an entry is saved.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch_UpdateVary)6323 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch_UpdateVary) {
6324 MockHttpCache cache;
6325
6326 // Write to the cache.
6327 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6328 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
6329 transaction.response_headers =
6330 "Etag: \"foopy\"\n"
6331 "Cache-Control: max-age=0\n"
6332 "Vary: Foo\n";
6333 RunTransactionTest(cache.http_cache(), transaction);
6334
6335 // Validate the entry and change the vary field in the response.
6336 transaction.request_headers = "Foo: bar\r\n Name: none\r\n";
6337 transaction.status = "HTTP/1.1 304 Not Modified";
6338 transaction.response_headers =
6339 "Etag: \"foopy\"\n"
6340 "Cache-Control: max-age=3600\n"
6341 "Vary: Name\n";
6342 RunTransactionTest(cache.http_cache(), transaction);
6343
6344 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6345 EXPECT_EQ(1, cache.disk_cache()->open_count());
6346 EXPECT_EQ(1, cache.disk_cache()->create_count());
6347
6348 // Make sure that the ActiveEntry is gone.
6349 base::RunLoop().RunUntilIdle();
6350
6351 // Generate a vary mismatch.
6352 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
6353 RunTransactionTest(cache.http_cache(), transaction);
6354
6355 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6356 EXPECT_EQ(2, cache.disk_cache()->open_count());
6357 EXPECT_EQ(1, cache.disk_cache()->create_count());
6358 }
6359
6360 // Tests that new request headers causing a vary mismatch are paired with the
6361 // new response when the server says the old response can be used.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch_UpdateRequestHeader)6362 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch_UpdateRequestHeader) {
6363 MockHttpCache cache;
6364
6365 // Write to the cache.
6366 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6367 transaction.request_headers = "Foo: bar\r\n";
6368 transaction.response_headers =
6369 "Etag: \"foopy\"\n"
6370 "Cache-Control: max-age=3600\n"
6371 "Vary: Foo\n";
6372 RunTransactionTest(cache.http_cache(), transaction);
6373
6374 // Vary-mismatch validation receives 304.
6375 transaction.request_headers = "Foo: none\r\n";
6376 transaction.status = "HTTP/1.1 304 Not Modified";
6377 RunTransactionTest(cache.http_cache(), transaction);
6378
6379 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6380 EXPECT_EQ(1, cache.disk_cache()->open_count());
6381 EXPECT_EQ(1, cache.disk_cache()->create_count());
6382
6383 // Make sure that the ActiveEntry is gone.
6384 base::RunLoop().RunUntilIdle();
6385
6386 // Generate a vary mismatch.
6387 transaction.request_headers = "Foo: bar\r\n";
6388 RunTransactionTest(cache.http_cache(), transaction);
6389
6390 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6391 EXPECT_EQ(2, cache.disk_cache()->open_count());
6392 EXPECT_EQ(1, cache.disk_cache()->create_count());
6393 }
6394
6395 // Tests that a 304 without vary headers doesn't delete the previously stored
6396 // vary data after a vary match revalidation.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch_DontDeleteVary)6397 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch_DontDeleteVary) {
6398 MockHttpCache cache;
6399
6400 // Write to the cache.
6401 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6402 transaction.request_headers = "Foo: bar\r\n";
6403 transaction.response_headers =
6404 "Etag: \"foopy\"\n"
6405 "Cache-Control: max-age=0\n"
6406 "Vary: Foo\n";
6407 RunTransactionTest(cache.http_cache(), transaction);
6408
6409 // Validate the entry and remove the vary field in the response.
6410 transaction.status = "HTTP/1.1 304 Not Modified";
6411 transaction.response_headers =
6412 "Etag: \"foopy\"\n"
6413 "Cache-Control: max-age=3600\n";
6414 RunTransactionTest(cache.http_cache(), transaction);
6415
6416 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6417 EXPECT_EQ(1, cache.disk_cache()->open_count());
6418 EXPECT_EQ(1, cache.disk_cache()->create_count());
6419
6420 // Make sure that the ActiveEntry is gone.
6421 base::RunLoop().RunUntilIdle();
6422
6423 // Generate a vary mismatch.
6424 transaction.request_headers = "Foo: none\r\n";
6425 RunTransactionTest(cache.http_cache(), transaction);
6426
6427 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6428 EXPECT_EQ(2, cache.disk_cache()->open_count());
6429 EXPECT_EQ(1, cache.disk_cache()->create_count());
6430 }
6431
6432 // Tests that a 304 without vary headers doesn't delete the previously stored
6433 // vary data after a vary mismatch.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch_DontDeleteVary)6434 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch_DontDeleteVary) {
6435 MockHttpCache cache;
6436
6437 // Write to the cache.
6438 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6439 transaction.request_headers = "Foo: bar\r\n";
6440 transaction.response_headers =
6441 "Etag: \"foopy\"\n"
6442 "Cache-Control: max-age=3600\n"
6443 "Vary: Foo\n";
6444 RunTransactionTest(cache.http_cache(), transaction);
6445
6446 // Vary-mismatch validation receives 304 and no vary header.
6447 transaction.request_headers = "Foo: none\r\n";
6448 transaction.status = "HTTP/1.1 304 Not Modified";
6449 transaction.response_headers =
6450 "Etag: \"foopy\"\n"
6451 "Cache-Control: max-age=3600\n";
6452 RunTransactionTest(cache.http_cache(), transaction);
6453
6454 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6455 EXPECT_EQ(1, cache.disk_cache()->open_count());
6456 EXPECT_EQ(1, cache.disk_cache()->create_count());
6457
6458 // Make sure that the ActiveEntry is gone.
6459 base::RunLoop().RunUntilIdle();
6460
6461 // Generate a vary mismatch.
6462 transaction.request_headers = "Foo: bar\r\n";
6463 RunTransactionTest(cache.http_cache(), transaction);
6464
6465 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6466 EXPECT_EQ(2, cache.disk_cache()->open_count());
6467 EXPECT_EQ(1, cache.disk_cache()->create_count());
6468 }
6469
ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)6470 static void ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo* request,
6471 std::string* response_status,
6472 std::string* response_headers,
6473 std::string* response_data) {
6474 EXPECT_FALSE(
6475 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6476 }
6477
TEST_F(HttpCacheTest,ETagGET_Http10)6478 TEST_F(HttpCacheTest, ETagGET_Http10) {
6479 MockHttpCache cache;
6480
6481 ScopedMockTransaction transaction(kETagGET_Transaction);
6482 transaction.status = "HTTP/1.0 200 OK";
6483
6484 // Write to the cache.
6485 RunTransactionTest(cache.http_cache(), transaction);
6486
6487 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6488 EXPECT_EQ(0, cache.disk_cache()->open_count());
6489 EXPECT_EQ(1, cache.disk_cache()->create_count());
6490
6491 // Get the same URL again, without generating a conditional request.
6492 transaction.load_flags = LOAD_VALIDATE_CACHE;
6493 transaction.handler = ETagGet_UnconditionalRequest_Handler;
6494 RunTransactionTest(cache.http_cache(), transaction);
6495
6496 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6497 EXPECT_EQ(1, cache.disk_cache()->open_count());
6498 EXPECT_EQ(1, cache.disk_cache()->create_count());
6499 }
6500
TEST_F(HttpCacheTest,ETagGET_Http10_Range)6501 TEST_F(HttpCacheTest, ETagGET_Http10_Range) {
6502 MockHttpCache cache;
6503
6504 ScopedMockTransaction transaction(kETagGET_Transaction);
6505 transaction.status = "HTTP/1.0 200 OK";
6506
6507 // Write to the cache.
6508 RunTransactionTest(cache.http_cache(), transaction);
6509
6510 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6511 EXPECT_EQ(0, cache.disk_cache()->open_count());
6512 EXPECT_EQ(1, cache.disk_cache()->create_count());
6513
6514 // Get the same URL again, but use a byte range request.
6515 transaction.load_flags = LOAD_VALIDATE_CACHE;
6516 transaction.handler = ETagGet_UnconditionalRequest_Handler;
6517 transaction.request_headers = "Range: bytes = 5-\r\n";
6518 RunTransactionTest(cache.http_cache(), transaction);
6519
6520 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6521 EXPECT_EQ(1, cache.disk_cache()->open_count());
6522 EXPECT_EQ(2, cache.disk_cache()->create_count());
6523 }
6524
ETagGet_ConditionalRequest_NoStore_Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)6525 static void ETagGet_ConditionalRequest_NoStore_Handler(
6526 const HttpRequestInfo* request,
6527 std::string* response_status,
6528 std::string* response_headers,
6529 std::string* response_data) {
6530 EXPECT_TRUE(
6531 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6532 response_status->assign("HTTP/1.1 304 Not Modified");
6533 response_headers->assign("Cache-Control: no-store\n");
6534 response_data->clear();
6535 }
6536
TEST_F(HttpCacheTest,ETagGET_ConditionalRequest_304_NoStore)6537 TEST_F(HttpCacheTest, ETagGET_ConditionalRequest_304_NoStore) {
6538 MockHttpCache cache;
6539
6540 ScopedMockTransaction transaction(kETagGET_Transaction);
6541
6542 // Write to the cache.
6543 RunTransactionTest(cache.http_cache(), transaction);
6544
6545 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6546 EXPECT_EQ(0, cache.disk_cache()->open_count());
6547 EXPECT_EQ(1, cache.disk_cache()->create_count());
6548
6549 // Get the same URL again, but this time we expect it to result
6550 // in a conditional request.
6551 transaction.load_flags = LOAD_VALIDATE_CACHE;
6552 transaction.handler = ETagGet_ConditionalRequest_NoStore_Handler;
6553 RunTransactionTest(cache.http_cache(), transaction);
6554
6555 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6556 EXPECT_EQ(1, cache.disk_cache()->open_count());
6557 EXPECT_EQ(1, cache.disk_cache()->create_count());
6558
6559 ScopedMockTransaction transaction2(kETagGET_Transaction);
6560
6561 // Write to the cache again. This should create a new entry.
6562 RunTransactionTest(cache.http_cache(), transaction2);
6563
6564 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6565 EXPECT_EQ(1, cache.disk_cache()->open_count());
6566 EXPECT_EQ(2, cache.disk_cache()->create_count());
6567 }
6568
6569 // Helper that does 4 requests using HttpCache:
6570 //
6571 // (1) loads |kUrl| -- expects |net_response_1| to be returned.
6572 // (2) loads |kUrl| from cache only -- expects |net_response_1| to be returned.
6573 // (3) loads |kUrl| using |extra_request_headers| -- expects |net_response_2| to
6574 // be returned.
6575 // (4) loads |kUrl| from cache only -- expects |cached_response_2| to be
6576 // returned.
6577 // The entry will be created once and will be opened for the 3 subsequent
6578 // requests.
ConditionalizedRequestUpdatesCacheHelper(const Response & net_response_1,const Response & net_response_2,const Response & cached_response_2,const char * extra_request_headers)6579 static void ConditionalizedRequestUpdatesCacheHelper(
6580 const Response& net_response_1,
6581 const Response& net_response_2,
6582 const Response& cached_response_2,
6583 const char* extra_request_headers) {
6584 MockHttpCache cache;
6585
6586 // The URL we will be requesting.
6587 const char kUrl[] = "http://foobar.com/main.css";
6588
6589 // Junk network response.
6590 static const Response kUnexpectedResponse = {
6591 "HTTP/1.1 500 Unexpected",
6592 "Server: unexpected_header",
6593 "unexpected body"
6594 };
6595
6596 // We will control the network layer's responses for |kUrl| using
6597 // |mock_network_response|.
6598 MockTransaction mock_network_response = {nullptr};
6599 mock_network_response.url = kUrl;
6600 AddMockTransaction(&mock_network_response);
6601
6602 // Request |kUrl| for the first time. It should hit the network and
6603 // receive |kNetResponse1|, which it saves into the HTTP cache.
6604
6605 MockTransaction request = {nullptr};
6606 request.url = kUrl;
6607 request.method = "GET";
6608 request.request_headers = "";
6609
6610 net_response_1.AssignTo(&mock_network_response); // Network mock.
6611 net_response_1.AssignTo(&request); // Expected result.
6612
6613 std::string response_headers;
6614 RunTransactionTestWithResponse(
6615 cache.http_cache(), request, &response_headers);
6616
6617 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
6618 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6619 EXPECT_EQ(0, cache.disk_cache()->open_count());
6620 EXPECT_EQ(1, cache.disk_cache()->create_count());
6621
6622 // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP
6623 // cache, so we don't hit the network.
6624
6625 request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
6626
6627 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
6628 net_response_1.AssignTo(&request); // Expected result.
6629
6630 RunTransactionTestWithResponse(
6631 cache.http_cache(), request, &response_headers);
6632
6633 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
6634 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6635 EXPECT_EQ(1, cache.disk_cache()->open_count());
6636 EXPECT_EQ(1, cache.disk_cache()->create_count());
6637
6638 // Request |kUrl| yet again, but this time give the request an
6639 // "If-Modified-Since" header. This will cause the request to re-hit the
6640 // network. However now the network response is going to be
6641 // different -- this simulates a change made to the CSS file.
6642
6643 request.request_headers = extra_request_headers;
6644 request.load_flags = LOAD_NORMAL;
6645
6646 net_response_2.AssignTo(&mock_network_response); // Network mock.
6647 net_response_2.AssignTo(&request); // Expected result.
6648
6649 RunTransactionTestWithResponse(
6650 cache.http_cache(), request, &response_headers);
6651
6652 EXPECT_EQ(net_response_2.status_and_headers(), response_headers);
6653 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6654 EXPECT_EQ(1, cache.disk_cache()->open_count());
6655 EXPECT_EQ(1, cache.disk_cache()->create_count());
6656
6657 // Finally, request |kUrl| again. This request should be serviced from
6658 // the cache. Moreover, the value in the cache should be |kNetResponse2|
6659 // and NOT |kNetResponse1|. The previous step should have replaced the
6660 // value in the cache with the modified response.
6661
6662 request.request_headers = "";
6663 request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
6664
6665 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
6666 cached_response_2.AssignTo(&request); // Expected result.
6667
6668 RunTransactionTestWithResponse(
6669 cache.http_cache(), request, &response_headers);
6670
6671 EXPECT_EQ(cached_response_2.status_and_headers(), response_headers);
6672 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6673 EXPECT_EQ(2, cache.disk_cache()->open_count());
6674 EXPECT_EQ(1, cache.disk_cache()->create_count());
6675
6676 RemoveMockTransaction(&mock_network_response);
6677 }
6678
6679 // Check that when an "if-modified-since" header is attached
6680 // to the request, the result still updates the cached entry.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache1)6681 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache1) {
6682 // First network response for |kUrl|.
6683 static const Response kNetResponse1 = {
6684 "HTTP/1.1 200 OK",
6685 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6686 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6687 "body1"
6688 };
6689
6690 // Second network response for |kUrl|.
6691 static const Response kNetResponse2 = {
6692 "HTTP/1.1 200 OK",
6693 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6694 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6695 "body2"
6696 };
6697
6698 const char extra_headers[] =
6699 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6700
6701 ConditionalizedRequestUpdatesCacheHelper(
6702 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
6703 }
6704
6705 // Check that when an "if-none-match" header is attached
6706 // to the request, the result updates the cached entry.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache2)6707 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache2) {
6708 // First network response for |kUrl|.
6709 static const Response kNetResponse1 = {
6710 "HTTP/1.1 200 OK",
6711 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6712 "Etag: \"ETAG1\"\n"
6713 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
6714 "body1"
6715 };
6716
6717 // Second network response for |kUrl|.
6718 static const Response kNetResponse2 = {
6719 "HTTP/1.1 200 OK",
6720 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6721 "Etag: \"ETAG2\"\n"
6722 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
6723 "body2"
6724 };
6725
6726 const char extra_headers[] = "If-None-Match: \"ETAG1\"\r\n";
6727
6728 ConditionalizedRequestUpdatesCacheHelper(
6729 kNetResponse1, kNetResponse2, kNetResponse2, extra_headers);
6730 }
6731
6732 // Check that when an "if-modified-since" header is attached
6733 // to a request, the 304 (not modified result) result updates the cached
6734 // headers, and the 304 response is returned rather than the cached response.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache3)6735 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache3) {
6736 // First network response for |kUrl|.
6737 static const Response kNetResponse1 = {
6738 "HTTP/1.1 200 OK",
6739 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6740 "Server: server1\n"
6741 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6742 "body1"
6743 };
6744
6745 // Second network response for |kUrl|.
6746 static const Response kNetResponse2 = {
6747 "HTTP/1.1 304 Not Modified",
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 ""
6752 };
6753
6754 static const Response kCachedResponse2 = {
6755 "HTTP/1.1 200 OK",
6756 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6757 "Server: server2\n"
6758 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6759 "body1"
6760 };
6761
6762 const char extra_headers[] =
6763 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6764
6765 ConditionalizedRequestUpdatesCacheHelper(
6766 kNetResponse1, kNetResponse2, kCachedResponse2, extra_headers);
6767 }
6768
6769 // Test that when doing an externally conditionalized if-modified-since
6770 // and there is no corresponding cache entry, a new cache entry is NOT
6771 // created (304 response).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache4)6772 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache4) {
6773 MockHttpCache cache;
6774
6775 const char kUrl[] = "http://foobar.com/main.css";
6776
6777 static const Response kNetResponse = {
6778 "HTTP/1.1 304 Not Modified",
6779 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6780 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6781 ""
6782 };
6783
6784 const char kExtraRequestHeaders[] =
6785 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6786
6787 // We will control the network layer's responses for |kUrl| using
6788 // |mock_network_response|.
6789 MockTransaction mock_network_response = {nullptr};
6790 mock_network_response.url = kUrl;
6791 AddMockTransaction(&mock_network_response);
6792
6793 MockTransaction request = {nullptr};
6794 request.url = kUrl;
6795 request.method = "GET";
6796 request.request_headers = kExtraRequestHeaders;
6797
6798 kNetResponse.AssignTo(&mock_network_response); // Network mock.
6799 kNetResponse.AssignTo(&request); // Expected result.
6800
6801 std::string response_headers;
6802 RunTransactionTestWithResponse(
6803 cache.http_cache(), request, &response_headers);
6804
6805 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
6806 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6807 EXPECT_EQ(0, cache.disk_cache()->open_count());
6808 EXPECT_EQ(0, cache.disk_cache()->create_count());
6809
6810 RemoveMockTransaction(&mock_network_response);
6811 }
6812
6813 // Test that when doing an externally conditionalized if-modified-since
6814 // and there is no corresponding cache entry, a new cache entry is NOT
6815 // created (200 response).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache5)6816 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache5) {
6817 MockHttpCache cache;
6818
6819 const char kUrl[] = "http://foobar.com/main.css";
6820
6821 static const Response kNetResponse = {
6822 "HTTP/1.1 200 OK",
6823 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6824 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6825 "foobar!!!"
6826 };
6827
6828 const char kExtraRequestHeaders[] =
6829 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6830
6831 // We will control the network layer's responses for |kUrl| using
6832 // |mock_network_response|.
6833 MockTransaction mock_network_response = {nullptr};
6834 mock_network_response.url = kUrl;
6835 AddMockTransaction(&mock_network_response);
6836
6837 MockTransaction request = {nullptr};
6838 request.url = kUrl;
6839 request.method = "GET";
6840 request.request_headers = kExtraRequestHeaders;
6841
6842 kNetResponse.AssignTo(&mock_network_response); // Network mock.
6843 kNetResponse.AssignTo(&request); // Expected result.
6844
6845 std::string response_headers;
6846 RunTransactionTestWithResponse(
6847 cache.http_cache(), request, &response_headers);
6848
6849 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
6850 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6851 EXPECT_EQ(0, cache.disk_cache()->open_count());
6852 EXPECT_EQ(0, cache.disk_cache()->create_count());
6853
6854 RemoveMockTransaction(&mock_network_response);
6855 }
6856
6857 // Test that when doing an externally conditionalized if-modified-since
6858 // if the date does not match the cache entry's last-modified date,
6859 // then we do NOT use the response (304) to update the cache.
6860 // (the if-modified-since date is 2 days AFTER the cache's modification date).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache6)6861 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache6) {
6862 static const Response kNetResponse1 = {
6863 "HTTP/1.1 200 OK",
6864 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6865 "Server: server1\n"
6866 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6867 "body1"
6868 };
6869
6870 // Second network response for |kUrl|.
6871 static const Response kNetResponse2 = {
6872 "HTTP/1.1 304 Not Modified",
6873 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6874 "Server: server2\n"
6875 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6876 ""
6877 };
6878
6879 // This is two days in the future from the original response's last-modified
6880 // date!
6881 const char kExtraRequestHeaders[] =
6882 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n";
6883
6884 ConditionalizedRequestUpdatesCacheHelper(
6885 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
6886 }
6887
6888 // Test that when doing an externally conditionalized if-none-match
6889 // if the etag does not match the cache entry's etag, then we do not use the
6890 // response (304) to update the cache.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache7)6891 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache7) {
6892 static const Response kNetResponse1 = {
6893 "HTTP/1.1 200 OK",
6894 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6895 "Etag: \"Foo1\"\n"
6896 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6897 "body1"
6898 };
6899
6900 // Second network response for |kUrl|.
6901 static const Response kNetResponse2 = {
6902 "HTTP/1.1 304 Not Modified",
6903 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6904 "Etag: \"Foo2\"\n"
6905 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6906 ""
6907 };
6908
6909 // Different etag from original response.
6910 const char kExtraRequestHeaders[] = "If-None-Match: \"Foo2\"\r\n";
6911
6912 ConditionalizedRequestUpdatesCacheHelper(
6913 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
6914 }
6915
6916 // Test that doing an externally conditionalized request with both if-none-match
6917 // and if-modified-since updates the cache.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache8)6918 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache8) {
6919 static const Response kNetResponse1 = {
6920 "HTTP/1.1 200 OK",
6921 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6922 "Etag: \"Foo1\"\n"
6923 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6924 "body1"
6925 };
6926
6927 // Second network response for |kUrl|.
6928 static const Response kNetResponse2 = {
6929 "HTTP/1.1 200 OK",
6930 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6931 "Etag: \"Foo2\"\n"
6932 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6933 "body2"
6934 };
6935
6936 const char kExtraRequestHeaders[] =
6937 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
6938 "If-None-Match: \"Foo1\"\r\n";
6939
6940 ConditionalizedRequestUpdatesCacheHelper(
6941 kNetResponse1, kNetResponse2, kNetResponse2, kExtraRequestHeaders);
6942 }
6943
6944 // Test that doing an externally conditionalized request with both if-none-match
6945 // and if-modified-since does not update the cache with only one match.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache9)6946 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache9) {
6947 static const Response kNetResponse1 = {
6948 "HTTP/1.1 200 OK",
6949 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6950 "Etag: \"Foo1\"\n"
6951 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6952 "body1"
6953 };
6954
6955 // Second network response for |kUrl|.
6956 static const Response kNetResponse2 = {
6957 "HTTP/1.1 200 OK",
6958 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6959 "Etag: \"Foo2\"\n"
6960 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6961 "body2"
6962 };
6963
6964 // The etag doesn't match what we have stored.
6965 const char kExtraRequestHeaders[] =
6966 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
6967 "If-None-Match: \"Foo2\"\r\n";
6968
6969 ConditionalizedRequestUpdatesCacheHelper(
6970 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
6971 }
6972
6973 // Test that doing an externally conditionalized request with both if-none-match
6974 // and if-modified-since does not update the cache with only one match.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache10)6975 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache10) {
6976 static const Response kNetResponse1 = {
6977 "HTTP/1.1 200 OK",
6978 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6979 "Etag: \"Foo1\"\n"
6980 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6981 "body1"
6982 };
6983
6984 // Second network response for |kUrl|.
6985 static const Response kNetResponse2 = {
6986 "HTTP/1.1 200 OK",
6987 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6988 "Etag: \"Foo2\"\n"
6989 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6990 "body2"
6991 };
6992
6993 // The modification date doesn't match what we have stored.
6994 const char kExtraRequestHeaders[] =
6995 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n"
6996 "If-None-Match: \"Foo1\"\r\n";
6997
6998 ConditionalizedRequestUpdatesCacheHelper(
6999 kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders);
7000 }
7001
TEST_F(HttpCacheTest,UrlContainingHash)7002 TEST_F(HttpCacheTest, UrlContainingHash) {
7003 MockHttpCache cache;
7004
7005 // Do a typical GET request -- should write an entry into our cache.
7006 MockTransaction trans(kTypicalGET_Transaction);
7007 RunTransactionTest(cache.http_cache(), trans);
7008
7009 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7010 EXPECT_EQ(0, cache.disk_cache()->open_count());
7011 EXPECT_EQ(1, cache.disk_cache()->create_count());
7012
7013 // Request the same URL, but this time with a reference section (hash).
7014 // Since the cache key strips the hash sections, this should be a cache hit.
7015 std::string url_with_hash = std::string(trans.url) + "#multiple#hashes";
7016 trans.url = url_with_hash.c_str();
7017 trans.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7018
7019 RunTransactionTest(cache.http_cache(), trans);
7020
7021 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7022 EXPECT_EQ(1, cache.disk_cache()->open_count());
7023 EXPECT_EQ(1, cache.disk_cache()->create_count());
7024 }
7025
7026 // Tests that we skip the cache for POST requests that do not have an upload
7027 // identifier.
TEST_F(HttpCacheTest,SimplePOST_SkipsCache)7028 TEST_F(HttpCacheTest, SimplePOST_SkipsCache) {
7029 MockHttpCache cache;
7030
7031 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
7032
7033 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7034 EXPECT_EQ(0, cache.disk_cache()->open_count());
7035 EXPECT_EQ(0, cache.disk_cache()->create_count());
7036 }
7037
7038 // Tests POST handling with a disabled cache (no DCHECK).
TEST_F(HttpCacheTest,SimplePOST_DisabledCache)7039 TEST_F(HttpCacheTest, SimplePOST_DisabledCache) {
7040 MockHttpCache cache;
7041 cache.http_cache()->set_mode(HttpCache::Mode::DISABLE);
7042
7043 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
7044
7045 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7046 EXPECT_EQ(0, cache.disk_cache()->open_count());
7047 EXPECT_EQ(0, cache.disk_cache()->create_count());
7048 }
7049
TEST_F(HttpCacheTest,SimplePOST_LoadOnlyFromCache_Miss)7050 TEST_F(HttpCacheTest, SimplePOST_LoadOnlyFromCache_Miss) {
7051 MockHttpCache cache;
7052
7053 MockTransaction transaction(kSimplePOST_Transaction);
7054 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7055
7056 MockHttpRequest request(transaction);
7057 TestCompletionCallback callback;
7058
7059 std::unique_ptr<HttpTransaction> trans;
7060 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
7061 ASSERT_TRUE(trans.get());
7062
7063 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
7064 ASSERT_THAT(callback.GetResult(rv), IsError(ERR_CACHE_MISS));
7065
7066 trans.reset();
7067
7068 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7069 EXPECT_EQ(0, cache.disk_cache()->open_count());
7070 EXPECT_EQ(0, cache.disk_cache()->create_count());
7071 }
7072
TEST_F(HttpCacheTest,SimplePOST_LoadOnlyFromCache_Hit)7073 TEST_F(HttpCacheTest, SimplePOST_LoadOnlyFromCache_Hit) {
7074 MockHttpCache cache;
7075
7076 // Test that we hit the cache for POST requests.
7077
7078 MockTransaction transaction(kSimplePOST_Transaction);
7079
7080 const int64_t kUploadId = 1; // Just a dummy value.
7081
7082 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7083 element_readers.push_back(
7084 std::make_unique<UploadBytesElementReader>("hello", 5));
7085 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
7086 kUploadId);
7087 MockHttpRequest request(transaction);
7088 request.upload_data_stream = &upload_data_stream;
7089
7090 // Populate the cache.
7091 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7092 nullptr);
7093
7094 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7095 EXPECT_EQ(0, cache.disk_cache()->open_count());
7096 EXPECT_EQ(1, cache.disk_cache()->create_count());
7097
7098 // Load from cache.
7099 request.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7100 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7101 nullptr);
7102
7103 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7104 EXPECT_EQ(1, cache.disk_cache()->open_count());
7105 EXPECT_EQ(1, cache.disk_cache()->create_count());
7106 }
7107
7108 // Test that we don't hit the cache for POST requests if there is a byte range.
TEST_F(HttpCacheTest,SimplePOST_WithRanges)7109 TEST_F(HttpCacheTest, SimplePOST_WithRanges) {
7110 MockHttpCache cache;
7111
7112 MockTransaction transaction(kSimplePOST_Transaction);
7113 transaction.request_headers = "Range: bytes = 0-4\r\n";
7114
7115 const int64_t kUploadId = 1; // Just a dummy value.
7116
7117 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7118 element_readers.push_back(
7119 std::make_unique<UploadBytesElementReader>("hello", 5));
7120 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
7121 kUploadId);
7122
7123 MockHttpRequest request(transaction);
7124 request.upload_data_stream = &upload_data_stream;
7125
7126 // Attempt to populate the cache.
7127 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7128 nullptr);
7129
7130 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7131 EXPECT_EQ(0, cache.disk_cache()->open_count());
7132 EXPECT_EQ(0, cache.disk_cache()->create_count());
7133 }
7134
7135 // Tests that a POST is cached separately from a GET.
TEST_F(HttpCacheTest,SimplePOST_SeparateCache)7136 TEST_F(HttpCacheTest, SimplePOST_SeparateCache) {
7137 MockHttpCache cache;
7138
7139 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7140 element_readers.push_back(
7141 std::make_unique<UploadBytesElementReader>("hello", 5));
7142 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7143
7144 MockTransaction transaction(kSimplePOST_Transaction);
7145 MockHttpRequest req1(transaction);
7146 req1.upload_data_stream = &upload_data_stream;
7147
7148 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7149
7150 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7151 EXPECT_EQ(0, cache.disk_cache()->open_count());
7152 EXPECT_EQ(1, cache.disk_cache()->create_count());
7153
7154 transaction.method = "GET";
7155 MockHttpRequest req2(transaction);
7156
7157 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7158
7159 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7160 EXPECT_EQ(0, cache.disk_cache()->open_count());
7161 EXPECT_EQ(2, cache.disk_cache()->create_count());
7162 }
7163
7164 // Tests that a successful POST invalidates a previously cached GET.
TEST_F(HttpCacheTest,SimplePOST_Invalidate_205)7165 TEST_F(HttpCacheTest, SimplePOST_Invalidate_205) {
7166 MockHttpCache cache;
7167
7168 MockTransaction transaction(kSimpleGET_Transaction);
7169 AddMockTransaction(&transaction);
7170 MockHttpRequest req1(transaction);
7171
7172 // Attempt to populate the cache.
7173 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7174
7175 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7176 EXPECT_EQ(0, cache.disk_cache()->open_count());
7177 EXPECT_EQ(1, cache.disk_cache()->create_count());
7178
7179 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7180 element_readers.push_back(
7181 std::make_unique<UploadBytesElementReader>("hello", 5));
7182 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7183
7184 transaction.method = "POST";
7185 transaction.status = "HTTP/1.1 205 No Content";
7186 MockHttpRequest req2(transaction);
7187 req2.upload_data_stream = &upload_data_stream;
7188
7189 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7190
7191 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7192 EXPECT_EQ(0, cache.disk_cache()->open_count());
7193 EXPECT_EQ(2, cache.disk_cache()->create_count());
7194
7195 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7196
7197 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7198 EXPECT_EQ(0, cache.disk_cache()->open_count());
7199 EXPECT_EQ(3, cache.disk_cache()->create_count());
7200 RemoveMockTransaction(&transaction);
7201 }
7202
7203 // Tests that a successful POST invalidates a previously cached GET,
7204 // with cache split by top-frame origin.
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SimplePOST_Invalidate_205_SplitCache)7205 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
7206 SimplePOST_Invalidate_205_SplitCache) {
7207 SchemefulSite site_a(GURL("http://a.com"));
7208 SchemefulSite site_b(GURL("http://b.com"));
7209
7210 MockHttpCache cache;
7211
7212 MockTransaction transaction(kSimpleGET_Transaction);
7213 AddMockTransaction(&transaction);
7214 MockHttpRequest req1(transaction);
7215 req1.network_isolation_key = NetworkIsolationKey(site_a, site_a);
7216 req1.network_anonymization_key =
7217 net::NetworkAnonymizationKey::CreateSameSite(site_a);
7218
7219 // Attempt to populate the cache.
7220 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7221
7222 // Same for a different origin.
7223 MockHttpRequest req1b(transaction);
7224 req1b.network_isolation_key = NetworkIsolationKey(site_b, site_b);
7225 req1b.network_anonymization_key =
7226 net::NetworkAnonymizationKey::CreateSameSite(site_b);
7227 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1b,
7228 nullptr);
7229
7230 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7231 EXPECT_EQ(0, cache.disk_cache()->open_count());
7232 EXPECT_EQ(2, cache.disk_cache()->create_count());
7233
7234 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7235 element_readers.push_back(
7236 std::make_unique<UploadBytesElementReader>("hello", 5));
7237 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7238
7239 transaction.method = "POST";
7240 transaction.status = "HTTP/1.1 205 No Content";
7241 MockHttpRequest req2(transaction);
7242 req2.upload_data_stream = &upload_data_stream;
7243 req2.network_isolation_key = NetworkIsolationKey(site_a, site_a);
7244 req2.network_anonymization_key =
7245 net::NetworkAnonymizationKey::CreateSameSite(site_a);
7246
7247 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7248
7249 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7250 EXPECT_EQ(0, cache.disk_cache()->open_count());
7251 EXPECT_EQ(3, cache.disk_cache()->create_count());
7252
7253 // req1b should still be cached, since it has a different top-level frame
7254 // origin.
7255 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1b,
7256 nullptr);
7257 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7258 EXPECT_EQ(1, cache.disk_cache()->open_count());
7259 EXPECT_EQ(3, cache.disk_cache()->create_count());
7260
7261 // req1 should not be cached after the POST.
7262 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7263 EXPECT_EQ(4, cache.network_layer()->transaction_count());
7264 EXPECT_EQ(1, cache.disk_cache()->open_count());
7265 EXPECT_EQ(4, cache.disk_cache()->create_count());
7266
7267 RemoveMockTransaction(&transaction);
7268 }
7269
7270 // Tests that a successful POST invalidates a previously cached GET, even when
7271 // there is no upload identifier.
TEST_F(HttpCacheTest,SimplePOST_NoUploadId_Invalidate_205)7272 TEST_F(HttpCacheTest, SimplePOST_NoUploadId_Invalidate_205) {
7273 MockHttpCache cache;
7274
7275 MockTransaction transaction(kSimpleGET_Transaction);
7276 AddMockTransaction(&transaction);
7277 MockHttpRequest req1(transaction);
7278
7279 // Attempt to populate the cache.
7280 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7281
7282 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7283 EXPECT_EQ(0, cache.disk_cache()->open_count());
7284 EXPECT_EQ(1, cache.disk_cache()->create_count());
7285
7286 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7287 element_readers.push_back(
7288 std::make_unique<UploadBytesElementReader>("hello", 5));
7289 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7290
7291 transaction.method = "POST";
7292 transaction.status = "HTTP/1.1 205 No Content";
7293 MockHttpRequest req2(transaction);
7294 req2.upload_data_stream = &upload_data_stream;
7295
7296 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7297
7298 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7299 EXPECT_EQ(0, cache.disk_cache()->open_count());
7300 EXPECT_EQ(1, cache.disk_cache()->create_count());
7301
7302 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7303
7304 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7305 EXPECT_EQ(0, cache.disk_cache()->open_count());
7306 EXPECT_EQ(2, cache.disk_cache()->create_count());
7307 RemoveMockTransaction(&transaction);
7308 }
7309
7310 // Tests that processing a POST before creating the backend doesn't crash.
TEST_F(HttpCacheTest,SimplePOST_NoUploadId_NoBackend)7311 TEST_F(HttpCacheTest, SimplePOST_NoUploadId_NoBackend) {
7312 // This will initialize a cache object with NULL backend.
7313 auto factory = std::make_unique<MockBlockingBackendFactory>();
7314 factory->set_fail(true);
7315 factory->FinishCreation();
7316 MockHttpCache cache(std::move(factory));
7317
7318 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7319 element_readers.push_back(
7320 std::make_unique<UploadBytesElementReader>("hello", 5));
7321 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7322
7323 MockTransaction transaction(kSimplePOST_Transaction);
7324 AddMockTransaction(&transaction);
7325 MockHttpRequest req(transaction);
7326 req.upload_data_stream = &upload_data_stream;
7327
7328 RunTransactionTestWithRequest(cache.http_cache(), transaction, req, nullptr);
7329
7330 RemoveMockTransaction(&transaction);
7331 }
7332
7333 // Tests that we don't invalidate entries as a result of a failed POST.
TEST_F(HttpCacheTest,SimplePOST_DontInvalidate_100)7334 TEST_F(HttpCacheTest, SimplePOST_DontInvalidate_100) {
7335 MockHttpCache cache;
7336
7337 MockTransaction transaction(kSimpleGET_Transaction);
7338 AddMockTransaction(&transaction);
7339 MockHttpRequest req1(transaction);
7340
7341 // Attempt to populate the cache.
7342 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7343
7344 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7345 EXPECT_EQ(0, cache.disk_cache()->open_count());
7346 EXPECT_EQ(1, cache.disk_cache()->create_count());
7347
7348 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7349 element_readers.push_back(
7350 std::make_unique<UploadBytesElementReader>("hello", 5));
7351 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7352
7353 transaction.method = "POST";
7354 transaction.status = "HTTP/1.1 100 Continue";
7355 MockHttpRequest req2(transaction);
7356 req2.upload_data_stream = &upload_data_stream;
7357
7358 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7359
7360 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7361 EXPECT_EQ(0, cache.disk_cache()->open_count());
7362 EXPECT_EQ(2, cache.disk_cache()->create_count());
7363
7364 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7365
7366 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7367 EXPECT_EQ(1, cache.disk_cache()->open_count());
7368 EXPECT_EQ(2, cache.disk_cache()->create_count());
7369 RemoveMockTransaction(&transaction);
7370 }
7371
7372 // Tests that a HEAD request is not cached by itself.
TEST_F(HttpCacheTest,SimpleHEAD_LoadOnlyFromCache_Miss)7373 TEST_F(HttpCacheTest, SimpleHEAD_LoadOnlyFromCache_Miss) {
7374 MockHttpCache cache;
7375 MockTransaction transaction(kSimplePOST_Transaction);
7376 AddMockTransaction(&transaction);
7377 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7378 transaction.method = "HEAD";
7379
7380 MockHttpRequest request(transaction);
7381 TestCompletionCallback callback;
7382
7383 std::unique_ptr<HttpTransaction> trans;
7384 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
7385 ASSERT_TRUE(trans.get());
7386
7387 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
7388 ASSERT_THAT(callback.GetResult(rv), IsError(ERR_CACHE_MISS));
7389
7390 trans.reset();
7391
7392 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7393 EXPECT_EQ(0, cache.disk_cache()->open_count());
7394 EXPECT_EQ(0, cache.disk_cache()->create_count());
7395 RemoveMockTransaction(&transaction);
7396 }
7397
7398 // Tests that a HEAD request is served from a cached GET.
TEST_F(HttpCacheTest,SimpleHEAD_LoadOnlyFromCache_Hit)7399 TEST_F(HttpCacheTest, SimpleHEAD_LoadOnlyFromCache_Hit) {
7400 MockHttpCache cache;
7401 MockTransaction transaction(kSimpleGET_Transaction);
7402 AddMockTransaction(&transaction);
7403
7404 // Populate the cache.
7405 RunTransactionTest(cache.http_cache(), transaction);
7406
7407 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7408 EXPECT_EQ(0, cache.disk_cache()->open_count());
7409 EXPECT_EQ(1, cache.disk_cache()->create_count());
7410
7411 // Load from cache.
7412 transaction.method = "HEAD";
7413 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7414 transaction.data = "";
7415 RunTransactionTest(cache.http_cache(), transaction);
7416
7417 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7418 EXPECT_EQ(1, cache.disk_cache()->open_count());
7419 EXPECT_EQ(1, cache.disk_cache()->create_count());
7420 RemoveMockTransaction(&transaction);
7421 }
7422
7423 // Tests that a read-only request served from the cache preserves CL.
TEST_F(HttpCacheTest,SimpleHEAD_ContentLengthOnHit_Read)7424 TEST_F(HttpCacheTest, SimpleHEAD_ContentLengthOnHit_Read) {
7425 MockHttpCache cache;
7426 MockTransaction transaction(kSimpleGET_Transaction);
7427 AddMockTransaction(&transaction);
7428 transaction.response_headers = "Content-Length: 42\n";
7429
7430 // Populate the cache.
7431 RunTransactionTest(cache.http_cache(), transaction);
7432
7433 // Load from cache.
7434 transaction.method = "HEAD";
7435 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7436 transaction.data = "";
7437 std::string headers;
7438
7439 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7440
7441 EXPECT_EQ("HTTP/1.1 200 OK\nContent-Length: 42\n", headers);
7442 RemoveMockTransaction(&transaction);
7443 }
7444
7445 // Tests that a read-write request served from the cache preserves CL.
TEST_F(HttpCacheTest,ETagHEAD_ContentLengthOnHit_ReadWrite)7446 TEST_F(HttpCacheTest, ETagHEAD_ContentLengthOnHit_ReadWrite) {
7447 MockHttpCache cache;
7448 MockTransaction transaction(kETagGET_Transaction);
7449 AddMockTransaction(&transaction);
7450 std::string server_headers(kETagGET_Transaction.response_headers);
7451 server_headers.append("Content-Length: 42\n");
7452 transaction.response_headers = server_headers.data();
7453
7454 // Populate the cache.
7455 RunTransactionTest(cache.http_cache(), transaction);
7456
7457 // Load from cache.
7458 transaction.method = "HEAD";
7459 transaction.data = "";
7460 std::string headers;
7461
7462 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7463
7464 EXPECT_NE(std::string::npos, headers.find("Content-Length: 42\n"));
7465 RemoveMockTransaction(&transaction);
7466 }
7467
7468 // Tests that a HEAD request that includes byte ranges bypasses the cache.
TEST_F(HttpCacheTest,SimpleHEAD_WithRanges)7469 TEST_F(HttpCacheTest, SimpleHEAD_WithRanges) {
7470 MockHttpCache cache;
7471 MockTransaction transaction(kSimpleGET_Transaction);
7472 AddMockTransaction(&transaction);
7473
7474 // Populate the cache.
7475 RunTransactionTest(cache.http_cache(), transaction);
7476
7477 // Load from cache.
7478 transaction.method = "HEAD";
7479 transaction.request_headers = "Range: bytes = 0-4\r\n";
7480 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7481 transaction.start_return_code = ERR_CACHE_MISS;
7482 RunTransactionTest(cache.http_cache(), transaction);
7483
7484 EXPECT_EQ(0, cache.disk_cache()->open_count());
7485 EXPECT_EQ(1, cache.disk_cache()->create_count());
7486 RemoveMockTransaction(&transaction);
7487 }
7488
7489 // Tests that a HEAD request can be served from a partialy cached resource.
TEST_F(HttpCacheTest,SimpleHEAD_WithCachedRanges)7490 TEST_F(HttpCacheTest, SimpleHEAD_WithCachedRanges) {
7491 MockHttpCache cache;
7492 AddMockTransaction(&kRangeGET_TransactionOK);
7493
7494 // Write to the cache (40-49).
7495 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
7496 RemoveMockTransaction(&kRangeGET_TransactionOK);
7497
7498 MockTransaction transaction(kSimpleGET_Transaction);
7499
7500 transaction.url = kRangeGET_TransactionOK.url;
7501 transaction.method = "HEAD";
7502 transaction.data = "";
7503 AddMockTransaction(&transaction);
7504 std::string headers;
7505
7506 // Load from cache.
7507 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7508
7509 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7510 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
7511 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
7512 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7513 EXPECT_EQ(1, cache.disk_cache()->open_count());
7514 EXPECT_EQ(1, cache.disk_cache()->create_count());
7515 RemoveMockTransaction(&transaction);
7516 }
7517
7518 // Tests that a HEAD request can be served from a truncated resource.
TEST_F(HttpCacheTest,SimpleHEAD_WithTruncatedEntry)7519 TEST_F(HttpCacheTest, SimpleHEAD_WithTruncatedEntry) {
7520 MockHttpCache cache;
7521 AddMockTransaction(&kRangeGET_TransactionOK);
7522
7523 std::string raw_headers("HTTP/1.1 200 OK\n"
7524 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7525 "ETag: \"foo\"\n"
7526 "Accept-Ranges: bytes\n"
7527 "Content-Length: 80\n");
7528 CreateTruncatedEntry(raw_headers, &cache);
7529 RemoveMockTransaction(&kRangeGET_TransactionOK);
7530
7531 MockTransaction transaction(kSimpleGET_Transaction);
7532
7533 transaction.url = kRangeGET_TransactionOK.url;
7534 transaction.method = "HEAD";
7535 transaction.data = "";
7536 AddMockTransaction(&transaction);
7537 std::string headers;
7538
7539 // Load from cache.
7540 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7541
7542 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7543 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
7544 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
7545 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7546 EXPECT_EQ(1, cache.disk_cache()->open_count());
7547 EXPECT_EQ(1, cache.disk_cache()->create_count());
7548 RemoveMockTransaction(&transaction);
7549 }
7550
7551 // Tests that a HEAD request updates the cached response.
TEST_F(HttpCacheTest,TypicalHEAD_UpdatesResponse)7552 TEST_F(HttpCacheTest, TypicalHEAD_UpdatesResponse) {
7553 MockHttpCache cache;
7554 MockTransaction transaction(kTypicalGET_Transaction);
7555 AddMockTransaction(&transaction);
7556
7557 // Populate the cache.
7558 RunTransactionTest(cache.http_cache(), transaction);
7559
7560 // Update the cache.
7561 transaction.method = "HEAD";
7562 transaction.response_headers = "Foo: bar\n";
7563 transaction.data = "";
7564 transaction.status = "HTTP/1.1 304 Not Modified\n";
7565 std::string headers;
7566 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7567 RemoveMockTransaction(&transaction);
7568
7569 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7570 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7571
7572 MockTransaction transaction2(kTypicalGET_Transaction);
7573 AddMockTransaction(&transaction2);
7574
7575 // Make sure we are done with the previous transaction.
7576 base::RunLoop().RunUntilIdle();
7577
7578 // Load from the cache.
7579 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7580 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
7581
7582 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
7583 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7584 EXPECT_EQ(2, cache.disk_cache()->open_count());
7585 EXPECT_EQ(1, cache.disk_cache()->create_count());
7586 RemoveMockTransaction(&transaction2);
7587 }
7588
7589 // Tests that an externally conditionalized HEAD request updates the cache.
TEST_F(HttpCacheTest,TypicalHEAD_ConditionalizedRequestUpdatesResponse)7590 TEST_F(HttpCacheTest, TypicalHEAD_ConditionalizedRequestUpdatesResponse) {
7591 MockHttpCache cache;
7592 MockTransaction transaction(kTypicalGET_Transaction);
7593 AddMockTransaction(&transaction);
7594
7595 // Populate the cache.
7596 RunTransactionTest(cache.http_cache(), transaction);
7597
7598 // Update the cache.
7599 transaction.method = "HEAD";
7600 transaction.request_headers =
7601 "If-Modified-Since: Wed, 28 Nov 2007 00:40:09 GMT\r\n";
7602 transaction.response_headers = "Foo: bar\n";
7603 transaction.data = "";
7604 transaction.status = "HTTP/1.1 304 Not Modified\n";
7605 std::string headers;
7606 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7607 RemoveMockTransaction(&transaction);
7608
7609 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 304 Not Modified\n"));
7610 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7611
7612 MockTransaction transaction2(kTypicalGET_Transaction);
7613 AddMockTransaction(&transaction2);
7614
7615 // Make sure we are done with the previous transaction.
7616 base::RunLoop().RunUntilIdle();
7617
7618 // Load from the cache.
7619 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7620 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
7621
7622 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
7623 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7624 EXPECT_EQ(2, cache.disk_cache()->open_count());
7625 EXPECT_EQ(1, cache.disk_cache()->create_count());
7626 RemoveMockTransaction(&transaction2);
7627 }
7628
7629 // Tests that a HEAD request invalidates an old cached entry.
TEST_F(HttpCacheTest,SimpleHEAD_InvalidatesEntry)7630 TEST_F(HttpCacheTest, SimpleHEAD_InvalidatesEntry) {
7631 MockHttpCache cache;
7632 MockTransaction transaction(kTypicalGET_Transaction);
7633 AddMockTransaction(&transaction);
7634
7635 // Populate the cache.
7636 RunTransactionTest(cache.http_cache(), transaction);
7637
7638 // Update the cache.
7639 transaction.method = "HEAD";
7640 transaction.data = "";
7641 RunTransactionTest(cache.http_cache(), transaction);
7642 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7643
7644 // Load from the cache.
7645 transaction.method = "GET";
7646 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7647 transaction.start_return_code = ERR_CACHE_MISS;
7648 RunTransactionTest(cache.http_cache(), transaction);
7649
7650 RemoveMockTransaction(&transaction);
7651 }
7652
7653 // Tests that we do not cache the response of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Miss)7654 TEST_F(HttpCacheTest, SimplePUT_Miss) {
7655 MockHttpCache cache;
7656
7657 MockTransaction transaction(kSimplePOST_Transaction);
7658 transaction.method = "PUT";
7659
7660 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7661 element_readers.push_back(
7662 std::make_unique<UploadBytesElementReader>("hello", 5));
7663 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7664
7665 MockHttpRequest request(transaction);
7666 request.upload_data_stream = &upload_data_stream;
7667
7668 // Attempt to populate the cache.
7669 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7670 nullptr);
7671
7672 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7673 EXPECT_EQ(0, cache.disk_cache()->open_count());
7674 EXPECT_EQ(0, cache.disk_cache()->create_count());
7675 }
7676
7677 // Tests that we invalidate entries as a result of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Invalidate)7678 TEST_F(HttpCacheTest, SimplePUT_Invalidate) {
7679 MockHttpCache cache;
7680
7681 MockTransaction transaction(kSimpleGET_Transaction);
7682 MockHttpRequest req1(transaction);
7683
7684 // Attempt to populate the cache.
7685 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7686
7687 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7688 EXPECT_EQ(0, cache.disk_cache()->open_count());
7689 EXPECT_EQ(1, cache.disk_cache()->create_count());
7690
7691 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7692 element_readers.push_back(
7693 std::make_unique<UploadBytesElementReader>("hello", 5));
7694 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7695
7696 transaction.method = "PUT";
7697 MockHttpRequest req2(transaction);
7698 req2.upload_data_stream = &upload_data_stream;
7699
7700 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7701
7702 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7703 EXPECT_EQ(1, cache.disk_cache()->open_count());
7704 EXPECT_EQ(1, cache.disk_cache()->create_count());
7705
7706 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7707
7708 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7709 EXPECT_EQ(1, cache.disk_cache()->open_count());
7710 EXPECT_EQ(2, cache.disk_cache()->create_count());
7711 }
7712
7713 // Tests that we invalidate entries as a result of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Invalidate_305)7714 TEST_F(HttpCacheTest, SimplePUT_Invalidate_305) {
7715 MockHttpCache cache;
7716
7717 MockTransaction transaction(kSimpleGET_Transaction);
7718 AddMockTransaction(&transaction);
7719 MockHttpRequest req1(transaction);
7720
7721 // Attempt to populate the cache.
7722 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7723
7724 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7725 EXPECT_EQ(0, cache.disk_cache()->open_count());
7726 EXPECT_EQ(1, cache.disk_cache()->create_count());
7727
7728 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7729 element_readers.push_back(
7730 std::make_unique<UploadBytesElementReader>("hello", 5));
7731 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7732
7733 transaction.method = "PUT";
7734 transaction.status = "HTTP/1.1 305 Use Proxy";
7735 MockHttpRequest req2(transaction);
7736 req2.upload_data_stream = &upload_data_stream;
7737
7738 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7739
7740 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7741 EXPECT_EQ(1, cache.disk_cache()->open_count());
7742 EXPECT_EQ(1, cache.disk_cache()->create_count());
7743
7744 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7745
7746 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7747 EXPECT_EQ(1, cache.disk_cache()->open_count());
7748 EXPECT_EQ(2, cache.disk_cache()->create_count());
7749 RemoveMockTransaction(&transaction);
7750 }
7751
7752 // Tests that we don't invalidate entries as a result of a failed PUT.
TEST_F(HttpCacheTest,SimplePUT_DontInvalidate_404)7753 TEST_F(HttpCacheTest, SimplePUT_DontInvalidate_404) {
7754 MockHttpCache cache;
7755
7756 MockTransaction transaction(kSimpleGET_Transaction);
7757 AddMockTransaction(&transaction);
7758 MockHttpRequest req1(transaction);
7759
7760 // Attempt to populate the cache.
7761 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7762
7763 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7764 EXPECT_EQ(0, cache.disk_cache()->open_count());
7765 EXPECT_EQ(1, cache.disk_cache()->create_count());
7766
7767 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7768 element_readers.push_back(
7769 std::make_unique<UploadBytesElementReader>("hello", 5));
7770 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7771
7772 transaction.method = "PUT";
7773 transaction.status = "HTTP/1.1 404 Not Found";
7774 MockHttpRequest req2(transaction);
7775 req2.upload_data_stream = &upload_data_stream;
7776
7777 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7778
7779 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7780 EXPECT_EQ(1, cache.disk_cache()->open_count());
7781 EXPECT_EQ(1, cache.disk_cache()->create_count());
7782
7783 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7784
7785 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7786 EXPECT_EQ(2, cache.disk_cache()->open_count());
7787 EXPECT_EQ(1, cache.disk_cache()->create_count());
7788 RemoveMockTransaction(&transaction);
7789 }
7790
7791 // Tests that we do not cache the response of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Miss)7792 TEST_F(HttpCacheTest, SimpleDELETE_Miss) {
7793 MockHttpCache cache;
7794
7795 MockTransaction transaction(kSimplePOST_Transaction);
7796 transaction.method = "DELETE";
7797
7798 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7799 element_readers.push_back(
7800 std::make_unique<UploadBytesElementReader>("hello", 5));
7801 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7802
7803 MockHttpRequest request(transaction);
7804 request.upload_data_stream = &upload_data_stream;
7805
7806 // Attempt to populate the cache.
7807 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7808 nullptr);
7809
7810 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7811 EXPECT_EQ(0, cache.disk_cache()->open_count());
7812 EXPECT_EQ(0, cache.disk_cache()->create_count());
7813 }
7814
7815 // Tests that we invalidate entries as a result of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Invalidate)7816 TEST_F(HttpCacheTest, SimpleDELETE_Invalidate) {
7817 MockHttpCache cache;
7818
7819 MockTransaction transaction(kSimpleGET_Transaction);
7820 MockHttpRequest req1(transaction);
7821
7822 // Attempt to populate the cache.
7823 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7824
7825 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7826 EXPECT_EQ(0, cache.disk_cache()->open_count());
7827 EXPECT_EQ(1, cache.disk_cache()->create_count());
7828
7829 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7830 element_readers.push_back(
7831 std::make_unique<UploadBytesElementReader>("hello", 5));
7832 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7833
7834 transaction.method = "DELETE";
7835 MockHttpRequest req2(transaction);
7836 req2.upload_data_stream = &upload_data_stream;
7837
7838 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7839
7840 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7841 EXPECT_EQ(1, cache.disk_cache()->open_count());
7842 EXPECT_EQ(1, cache.disk_cache()->create_count());
7843
7844 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7845
7846 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7847 EXPECT_EQ(1, cache.disk_cache()->open_count());
7848 EXPECT_EQ(2, cache.disk_cache()->create_count());
7849 }
7850
7851 // Tests that we invalidate entries as a result of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Invalidate_301)7852 TEST_F(HttpCacheTest, SimpleDELETE_Invalidate_301) {
7853 MockHttpCache cache;
7854
7855 MockTransaction transaction(kSimpleGET_Transaction);
7856 AddMockTransaction(&transaction);
7857
7858 // Attempt to populate the cache.
7859 RunTransactionTest(cache.http_cache(), transaction);
7860
7861 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7862 EXPECT_EQ(0, cache.disk_cache()->open_count());
7863 EXPECT_EQ(1, cache.disk_cache()->create_count());
7864
7865 transaction.method = "DELETE";
7866 transaction.status = "HTTP/1.1 301 Moved Permanently ";
7867
7868 RunTransactionTest(cache.http_cache(), transaction);
7869
7870 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7871 EXPECT_EQ(1, cache.disk_cache()->open_count());
7872 EXPECT_EQ(1, cache.disk_cache()->create_count());
7873
7874 transaction.method = "GET";
7875 RunTransactionTest(cache.http_cache(), transaction);
7876
7877 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7878 EXPECT_EQ(1, cache.disk_cache()->open_count());
7879 EXPECT_EQ(2, cache.disk_cache()->create_count());
7880 RemoveMockTransaction(&transaction);
7881 }
7882
7883 // Tests that we don't invalidate entries as a result of a failed DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_DontInvalidate_416)7884 TEST_F(HttpCacheTest, SimpleDELETE_DontInvalidate_416) {
7885 MockHttpCache cache;
7886
7887 MockTransaction transaction(kSimpleGET_Transaction);
7888 AddMockTransaction(&transaction);
7889
7890 // Attempt to populate the cache.
7891 RunTransactionTest(cache.http_cache(), transaction);
7892
7893 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7894 EXPECT_EQ(0, cache.disk_cache()->open_count());
7895 EXPECT_EQ(1, cache.disk_cache()->create_count());
7896
7897 transaction.method = "DELETE";
7898 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
7899
7900 RunTransactionTest(cache.http_cache(), transaction);
7901
7902 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7903 EXPECT_EQ(1, cache.disk_cache()->open_count());
7904 EXPECT_EQ(1, cache.disk_cache()->create_count());
7905
7906 transaction.method = "GET";
7907 transaction.status = "HTTP/1.1 200 OK";
7908 RunTransactionTest(cache.http_cache(), transaction);
7909
7910 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7911 EXPECT_EQ(2, cache.disk_cache()->open_count());
7912 EXPECT_EQ(1, cache.disk_cache()->create_count());
7913 RemoveMockTransaction(&transaction);
7914 }
7915
7916 // Tests that we invalidate entries as a result of a PATCH.
TEST_F(HttpCacheTest,SimplePATCH_Invalidate)7917 TEST_F(HttpCacheTest, SimplePATCH_Invalidate) {
7918 MockHttpCache cache;
7919
7920 MockTransaction transaction(kSimpleGET_Transaction);
7921 MockHttpRequest req1(transaction);
7922
7923 // Attempt to populate the cache.
7924 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7925
7926 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7927 EXPECT_EQ(0, cache.disk_cache()->open_count());
7928 EXPECT_EQ(1, cache.disk_cache()->create_count());
7929
7930 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7931 element_readers.push_back(
7932 std::make_unique<UploadBytesElementReader>("hello", 5));
7933 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7934
7935 transaction.method = "PATCH";
7936 MockHttpRequest req2(transaction);
7937 req2.upload_data_stream = &upload_data_stream;
7938
7939 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7940
7941 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7942 EXPECT_EQ(1, cache.disk_cache()->open_count());
7943 EXPECT_EQ(1, cache.disk_cache()->create_count());
7944
7945 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7946
7947 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7948 EXPECT_EQ(1, cache.disk_cache()->open_count());
7949 EXPECT_EQ(2, cache.disk_cache()->create_count());
7950 }
7951
7952 // Tests that we invalidate entries as a result of a PATCH.
TEST_F(HttpCacheTest,SimplePATCH_Invalidate_301)7953 TEST_F(HttpCacheTest, SimplePATCH_Invalidate_301) {
7954 MockHttpCache cache;
7955
7956 MockTransaction transaction(kSimpleGET_Transaction);
7957 AddMockTransaction(&transaction);
7958
7959 // Attempt to populate the cache.
7960 RunTransactionTest(cache.http_cache(), transaction);
7961
7962 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7963 EXPECT_EQ(0, cache.disk_cache()->open_count());
7964 EXPECT_EQ(1, cache.disk_cache()->create_count());
7965
7966 transaction.method = "PATCH";
7967 transaction.status = "HTTP/1.1 301 Moved Permanently ";
7968
7969 RunTransactionTest(cache.http_cache(), transaction);
7970
7971 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7972 EXPECT_EQ(1, cache.disk_cache()->open_count());
7973 EXPECT_EQ(1, cache.disk_cache()->create_count());
7974
7975 transaction.method = "GET";
7976 RunTransactionTest(cache.http_cache(), transaction);
7977
7978 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7979 EXPECT_EQ(1, cache.disk_cache()->open_count());
7980 EXPECT_EQ(2, cache.disk_cache()->create_count());
7981 RemoveMockTransaction(&transaction);
7982 }
7983
7984 // Tests that we don't invalidate entries as a result of a failed PATCH.
TEST_F(HttpCacheTest,SimplePATCH_DontInvalidate_416)7985 TEST_F(HttpCacheTest, SimplePATCH_DontInvalidate_416) {
7986 MockHttpCache cache;
7987
7988 MockTransaction transaction(kSimpleGET_Transaction);
7989 AddMockTransaction(&transaction);
7990
7991 // Attempt to populate the cache.
7992 RunTransactionTest(cache.http_cache(), transaction);
7993
7994 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7995 EXPECT_EQ(0, cache.disk_cache()->open_count());
7996 EXPECT_EQ(1, cache.disk_cache()->create_count());
7997
7998 transaction.method = "PATCH";
7999 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
8000
8001 RunTransactionTest(cache.http_cache(), transaction);
8002
8003 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8004 EXPECT_EQ(1, cache.disk_cache()->open_count());
8005 EXPECT_EQ(1, cache.disk_cache()->create_count());
8006
8007 transaction.method = "GET";
8008 transaction.status = "HTTP/1.1 200 OK";
8009 RunTransactionTest(cache.http_cache(), transaction);
8010
8011 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8012 EXPECT_EQ(2, cache.disk_cache()->open_count());
8013 EXPECT_EQ(1, cache.disk_cache()->create_count());
8014 RemoveMockTransaction(&transaction);
8015 }
8016
8017 // Tests that we don't invalidate entries after a failed network transaction.
TEST_F(HttpCacheTest,SimpleGET_DontInvalidateOnFailure)8018 TEST_F(HttpCacheTest, SimpleGET_DontInvalidateOnFailure) {
8019 MockHttpCache cache;
8020
8021 // Populate the cache.
8022 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
8023 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8024
8025 // Fail the network request.
8026 MockTransaction transaction(kSimpleGET_Transaction);
8027 transaction.start_return_code = ERR_FAILED;
8028 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8029
8030 AddMockTransaction(&transaction);
8031 RunTransactionTest(cache.http_cache(), transaction);
8032 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8033 RemoveMockTransaction(&transaction);
8034
8035 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
8036 transaction.start_return_code = OK;
8037 AddMockTransaction(&transaction);
8038 RunTransactionTest(cache.http_cache(), transaction);
8039
8040 // Make sure the transaction didn't reach the network.
8041 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8042 RemoveMockTransaction(&transaction);
8043 }
8044
TEST_F(HttpCacheTest,RangeGET_SkipsCache)8045 TEST_F(HttpCacheTest, RangeGET_SkipsCache) {
8046 MockHttpCache cache;
8047
8048 // Test that we skip the cache for range GET requests. Eventually, we will
8049 // want to cache these, but we'll still have cases where skipping the cache
8050 // makes sense, so we want to make sure that it works properly.
8051
8052 RunTransactionTest(cache.http_cache(), kRangeGET_Transaction);
8053
8054 EXPECT_EQ(1, 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 MockTransaction transaction(kSimpleGET_Transaction);
8059 transaction.request_headers = "If-None-Match: foo\r\n";
8060 RunTransactionTest(cache.http_cache(), transaction);
8061
8062 EXPECT_EQ(2, 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 transaction.request_headers =
8067 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n";
8068 RunTransactionTest(cache.http_cache(), transaction);
8069
8070 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8071 EXPECT_EQ(0, cache.disk_cache()->open_count());
8072 EXPECT_EQ(0, cache.disk_cache()->create_count());
8073 }
8074
8075 // Test that we skip the cache for range requests that include a validation
8076 // header.
TEST_F(HttpCacheTest,RangeGET_SkipsCache2)8077 TEST_F(HttpCacheTest, RangeGET_SkipsCache2) {
8078 MockHttpCache cache;
8079
8080 MockTransaction transaction(kRangeGET_Transaction);
8081 transaction.request_headers = "If-None-Match: foo\r\n"
8082 EXTRA_HEADER
8083 "Range: bytes = 40-49\r\n";
8084 RunTransactionTest(cache.http_cache(), transaction);
8085
8086 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8087 EXPECT_EQ(0, cache.disk_cache()->open_count());
8088 EXPECT_EQ(0, cache.disk_cache()->create_count());
8089
8090 transaction.request_headers =
8091 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n"
8092 EXTRA_HEADER
8093 "Range: bytes = 40-49\r\n";
8094 RunTransactionTest(cache.http_cache(), transaction);
8095
8096 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8097 EXPECT_EQ(0, cache.disk_cache()->open_count());
8098 EXPECT_EQ(0, cache.disk_cache()->create_count());
8099
8100 transaction.request_headers = "If-Range: bla\r\n"
8101 EXTRA_HEADER
8102 "Range: bytes = 40-49\r\n";
8103 RunTransactionTest(cache.http_cache(), transaction);
8104
8105 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8106 EXPECT_EQ(0, cache.disk_cache()->open_count());
8107 EXPECT_EQ(0, cache.disk_cache()->create_count());
8108 }
8109
TEST_F(HttpCacheTest,SimpleGET_DoesntLogHeaders)8110 TEST_F(HttpCacheTest, SimpleGET_DoesntLogHeaders) {
8111 MockHttpCache cache;
8112
8113 RecordingNetLogObserver net_log_observer;
8114 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction,
8115 NetLogWithSource::Make(NetLogSourceType::NONE));
8116
8117 EXPECT_FALSE(LogContainsEventType(
8118 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8119 }
8120
TEST_F(HttpCacheTest,RangeGET_LogsHeaders)8121 TEST_F(HttpCacheTest, RangeGET_LogsHeaders) {
8122 MockHttpCache cache;
8123
8124 RecordingNetLogObserver net_log_observer;
8125 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_Transaction,
8126 NetLogWithSource::Make(NetLogSourceType::NONE));
8127
8128 EXPECT_TRUE(LogContainsEventType(
8129 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8130 }
8131
TEST_F(HttpCacheTest,ExternalValidation_LogsHeaders)8132 TEST_F(HttpCacheTest, ExternalValidation_LogsHeaders) {
8133 MockHttpCache cache;
8134
8135 RecordingNetLogObserver net_log_observer;
8136 MockTransaction transaction(kSimpleGET_Transaction);
8137 transaction.request_headers = "If-None-Match: foo\r\n" EXTRA_HEADER;
8138 RunTransactionTestWithLog(cache.http_cache(), transaction,
8139 NetLogWithSource::Make(NetLogSourceType::NONE));
8140
8141 EXPECT_TRUE(LogContainsEventType(
8142 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8143 }
8144
TEST_F(HttpCacheTest,SpecialHeaders_LogsHeaders)8145 TEST_F(HttpCacheTest, SpecialHeaders_LogsHeaders) {
8146 MockHttpCache cache;
8147
8148 RecordingNetLogObserver net_log_observer;
8149 MockTransaction transaction(kSimpleGET_Transaction);
8150 transaction.request_headers = "cache-control: no-cache\r\n" EXTRA_HEADER;
8151 RunTransactionTestWithLog(cache.http_cache(), transaction,
8152 NetLogWithSource::Make(NetLogSourceType::NONE));
8153
8154 EXPECT_TRUE(LogContainsEventType(
8155 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8156 }
8157
8158 // Tests that receiving 206 for a regular request is handled correctly.
TEST_F(HttpCacheTest,GET_Crazy206)8159 TEST_F(HttpCacheTest, GET_Crazy206) {
8160 MockHttpCache cache;
8161
8162 // Write to the cache.
8163 MockTransaction transaction(kRangeGET_TransactionOK);
8164 AddMockTransaction(&transaction);
8165 transaction.request_headers = EXTRA_HEADER;
8166 transaction.handler = nullptr;
8167 RunTransactionTest(cache.http_cache(), transaction);
8168
8169 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8170 EXPECT_EQ(0, cache.disk_cache()->open_count());
8171 EXPECT_EQ(1, cache.disk_cache()->create_count());
8172
8173 // This should read again from the net.
8174 RunTransactionTest(cache.http_cache(), transaction);
8175
8176 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8177 EXPECT_EQ(0, cache.disk_cache()->open_count());
8178 EXPECT_EQ(2, cache.disk_cache()->create_count());
8179 RemoveMockTransaction(&transaction);
8180 }
8181
8182 // Tests that receiving 416 for a regular request is handled correctly.
TEST_F(HttpCacheTest,GET_Crazy416)8183 TEST_F(HttpCacheTest, GET_Crazy416) {
8184 MockHttpCache cache;
8185
8186 // Write to the cache.
8187 MockTransaction transaction(kSimpleGET_Transaction);
8188 AddMockTransaction(&transaction);
8189 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
8190 RunTransactionTest(cache.http_cache(), transaction);
8191
8192 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8193 EXPECT_EQ(0, cache.disk_cache()->open_count());
8194 EXPECT_EQ(1, cache.disk_cache()->create_count());
8195
8196 RemoveMockTransaction(&transaction);
8197 }
8198
8199 // Tests that we don't store partial responses that can't be validated.
TEST_F(HttpCacheTest,RangeGET_NoStrongValidators)8200 TEST_F(HttpCacheTest, RangeGET_NoStrongValidators) {
8201 MockHttpCache cache;
8202 std::string headers;
8203
8204 // Attempt to write to the cache (40-49).
8205 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8206 transaction.response_headers = "Content-Length: 10\n"
8207 "Cache-Control: max-age=3600\n"
8208 "ETag: w/\"foo\"\n";
8209 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8210
8211 Verify206Response(headers, 40, 49);
8212 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8213 EXPECT_EQ(0, cache.disk_cache()->open_count());
8214 EXPECT_EQ(1, cache.disk_cache()->create_count());
8215
8216 // Now verify that there's no cached data.
8217 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8218 &headers);
8219
8220 Verify206Response(headers, 40, 49);
8221 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8222 EXPECT_EQ(0, cache.disk_cache()->open_count());
8223 EXPECT_EQ(2, cache.disk_cache()->create_count());
8224 }
8225
8226 // Tests failures to conditionalize byte range requests.
TEST_F(HttpCacheTest,RangeGET_NoConditionalization)8227 TEST_F(HttpCacheTest, RangeGET_NoConditionalization) {
8228 MockHttpCache cache;
8229 cache.FailConditionalizations();
8230 std::string headers;
8231
8232 // Write to the cache (40-49).
8233 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8234 transaction.response_headers = "Content-Length: 10\n"
8235 "ETag: \"foo\"\n";
8236 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8237
8238 Verify206Response(headers, 40, 49);
8239 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8240 EXPECT_EQ(0, cache.disk_cache()->open_count());
8241 EXPECT_EQ(1, cache.disk_cache()->create_count());
8242
8243 // Now verify that the cached data is not used.
8244 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8245 &headers);
8246
8247 Verify206Response(headers, 40, 49);
8248 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8249 EXPECT_EQ(1, cache.disk_cache()->open_count());
8250 EXPECT_EQ(2, cache.disk_cache()->create_count());
8251 }
8252
8253 // Tests that restarting a partial request when the cached data cannot be
8254 // revalidated logs an event.
TEST_F(HttpCacheTest,RangeGET_NoValidation_LogsRestart)8255 TEST_F(HttpCacheTest, RangeGET_NoValidation_LogsRestart) {
8256 MockHttpCache cache;
8257 cache.FailConditionalizations();
8258
8259 // Write to the cache (40-49).
8260 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8261 transaction.response_headers = "Content-Length: 10\n"
8262 "ETag: \"foo\"\n";
8263 RunTransactionTest(cache.http_cache(), transaction);
8264
8265 // Now verify that the cached data is not used.
8266 RecordingNetLogObserver net_log_observer;
8267 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_TransactionOK,
8268 NetLogWithSource::Make(NetLogSourceType::NONE));
8269
8270 EXPECT_TRUE(LogContainsEventType(
8271 net_log_observer, NetLogEventType::HTTP_CACHE_RESTART_PARTIAL_REQUEST));
8272 }
8273
8274 // Tests that a failure to conditionalize a regular request (no range) with a
8275 // sparse entry results in a full response.
TEST_F(HttpCacheTest,GET_NoConditionalization)8276 TEST_F(HttpCacheTest, GET_NoConditionalization) {
8277 for (bool use_memory_entry_data : {false, true}) {
8278 MockHttpCache cache;
8279 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
8280 cache.FailConditionalizations();
8281 std::string headers;
8282
8283 // Write to the cache (40-49).
8284 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8285 transaction.response_headers =
8286 "Content-Length: 10\n"
8287 "ETag: \"foo\"\n";
8288 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8289
8290 Verify206Response(headers, 40, 49);
8291 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8292 EXPECT_EQ(0, cache.disk_cache()->open_count());
8293 EXPECT_EQ(1, cache.disk_cache()->create_count());
8294
8295 // Now verify that the cached data is not used.
8296 // Don't ask for a range. The cache will attempt to use the cached data but
8297 // should discard it as it cannot be validated. A regular request should go
8298 // to the server and a new entry should be created.
8299 transaction.request_headers = EXTRA_HEADER;
8300 transaction.data = "Not a range";
8301 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8302
8303 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
8304 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8305 EXPECT_EQ(1, cache.disk_cache()->open_count());
8306 EXPECT_EQ(2, cache.disk_cache()->create_count());
8307
8308 // The last response was saved.
8309 RunTransactionTest(cache.http_cache(), transaction);
8310 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8311 if (use_memory_entry_data) {
8312 // The cache entry isn't really useful, since when
8313 // &RangeTransactionServer::RangeHandler gets a non-range request,
8314 // (the network transaction #2) it returns headers without ETag,
8315 // Last-Modified or caching headers, with a Date in 2007 (so no heuristic
8316 // freshness), so it's both expired and not conditionalizable --- so in
8317 // this branch we avoid opening it.
8318 EXPECT_EQ(1, cache.disk_cache()->open_count());
8319 EXPECT_EQ(3, cache.disk_cache()->create_count());
8320 } else {
8321 EXPECT_EQ(2, cache.disk_cache()->open_count());
8322 EXPECT_EQ(2, cache.disk_cache()->create_count());
8323 }
8324 }
8325 }
8326
8327 // Verifies that conditionalization failures when asking for a range that would
8328 // require the cache to modify the range to ask, result in a network request
8329 // that matches the user's one.
TEST_F(HttpCacheTest,RangeGET_NoConditionalization2)8330 TEST_F(HttpCacheTest, RangeGET_NoConditionalization2) {
8331 MockHttpCache cache;
8332 cache.FailConditionalizations();
8333 std::string headers;
8334
8335 // Write to the cache (40-49).
8336 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8337 transaction.response_headers = "Content-Length: 10\n"
8338 "ETag: \"foo\"\n";
8339 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8340
8341 Verify206Response(headers, 40, 49);
8342 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8343 EXPECT_EQ(0, cache.disk_cache()->open_count());
8344 EXPECT_EQ(1, cache.disk_cache()->create_count());
8345
8346 // Now verify that the cached data is not used.
8347 // Ask for a range that extends before and after the cached data so that the
8348 // cache would normally mix data from three sources. After deleting the entry,
8349 // the response will come from a single network request.
8350 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8351 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8352 transaction.response_headers = kRangeGET_TransactionOK.response_headers;
8353 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8354
8355 Verify206Response(headers, 20, 59);
8356 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8357 EXPECT_EQ(1, cache.disk_cache()->open_count());
8358 EXPECT_EQ(2, cache.disk_cache()->create_count());
8359
8360 // The last response was saved.
8361 RunTransactionTest(cache.http_cache(), transaction);
8362 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8363 EXPECT_EQ(2, cache.disk_cache()->open_count());
8364 EXPECT_EQ(2, cache.disk_cache()->create_count());
8365 }
8366
8367 // Tests that we cache partial responses that lack content-length.
TEST_F(HttpCacheTest,RangeGET_NoContentLength)8368 TEST_F(HttpCacheTest, RangeGET_NoContentLength) {
8369 MockHttpCache cache;
8370 std::string headers;
8371
8372 // Attempt to write to the cache (40-49).
8373 MockTransaction transaction(kRangeGET_TransactionOK);
8374 AddMockTransaction(&transaction);
8375 transaction.response_headers = "ETag: \"foo\"\n"
8376 "Accept-Ranges: bytes\n"
8377 "Content-Range: bytes 40-49/80\n";
8378 transaction.handler = nullptr;
8379 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8380
8381 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8382 EXPECT_EQ(0, cache.disk_cache()->open_count());
8383 EXPECT_EQ(1, cache.disk_cache()->create_count());
8384
8385 // Now verify that there's no cached data.
8386 transaction.handler = &RangeTransactionServer::RangeHandler;
8387 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8388 &headers);
8389
8390 Verify206Response(headers, 40, 49);
8391 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8392 EXPECT_EQ(1, cache.disk_cache()->open_count());
8393 EXPECT_EQ(1, cache.disk_cache()->create_count());
8394
8395 RemoveMockTransaction(&transaction);
8396 }
8397
8398 // Tests that we can cache range requests and fetch random blocks from the
8399 // cache and the network.
TEST_F(HttpCacheTest,RangeGET_OK)8400 TEST_F(HttpCacheTest, RangeGET_OK) {
8401 MockHttpCache cache;
8402 AddMockTransaction(&kRangeGET_TransactionOK);
8403 std::string headers;
8404
8405 // Write to the cache (40-49).
8406 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8407 &headers);
8408
8409 Verify206Response(headers, 40, 49);
8410 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8411 EXPECT_EQ(0, cache.disk_cache()->open_count());
8412 EXPECT_EQ(1, cache.disk_cache()->create_count());
8413
8414 // Read from the cache (40-49).
8415 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8416 &headers);
8417
8418 Verify206Response(headers, 40, 49);
8419 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8420 EXPECT_EQ(1, cache.disk_cache()->open_count());
8421 EXPECT_EQ(1, cache.disk_cache()->create_count());
8422
8423 // Make sure we are done with the previous transaction.
8424 base::RunLoop().RunUntilIdle();
8425
8426 // Write to the cache (30-39).
8427 MockTransaction transaction(kRangeGET_TransactionOK);
8428 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
8429 transaction.data = "rg: 30-39 ";
8430 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8431
8432 Verify206Response(headers, 30, 39);
8433 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8434 EXPECT_EQ(2, cache.disk_cache()->open_count());
8435 EXPECT_EQ(1, cache.disk_cache()->create_count());
8436
8437 // Make sure we are done with the previous transaction.
8438 base::RunLoop().RunUntilIdle();
8439
8440 // Write and read from the cache (20-59).
8441 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8442 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8443 LoadTimingInfo load_timing_info;
8444 RunTransactionTestWithResponseAndGetTiming(
8445 cache.http_cache(), transaction, &headers,
8446 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
8447
8448 Verify206Response(headers, 20, 59);
8449 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8450 EXPECT_EQ(3, cache.disk_cache()->open_count());
8451 EXPECT_EQ(1, cache.disk_cache()->create_count());
8452 TestLoadTimingNetworkRequest(load_timing_info);
8453
8454 RemoveMockTransaction(&kRangeGET_TransactionOK);
8455 }
8456
TEST_F(HttpCacheTest,RangeGET_CacheReadError)8457 TEST_F(HttpCacheTest, RangeGET_CacheReadError) {
8458 // Tests recovery on cache read error on range request.
8459 MockHttpCache cache;
8460 AddMockTransaction(&kRangeGET_TransactionOK);
8461 std::string headers;
8462
8463 // Write to the cache (40-49).
8464 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8465 &headers);
8466
8467 Verify206Response(headers, 40, 49);
8468 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8469 EXPECT_EQ(0, cache.disk_cache()->open_count());
8470 EXPECT_EQ(1, cache.disk_cache()->create_count());
8471
8472 cache.disk_cache()->set_soft_failures_one_instance(MockDiskEntry::FAIL_ALL);
8473
8474 // Try to read from the cache (40-49), which will fail quickly enough to
8475 // restart, due to the failure injected above. This should still be a range
8476 // request. (https://crbug.com/891212)
8477 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8478 &headers);
8479
8480 Verify206Response(headers, 40, 49);
8481 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8482 EXPECT_EQ(1, cache.disk_cache()->open_count());
8483 EXPECT_EQ(2, cache.disk_cache()->create_count());
8484
8485 RemoveMockTransaction(&kRangeGET_TransactionOK);
8486 }
8487
8488 // Tests that range requests with no-store get correct content-length
8489 // (https://crbug.com/700197).
TEST_F(HttpCacheTest,RangeGET_NoStore)8490 TEST_F(HttpCacheTest, RangeGET_NoStore) {
8491 MockHttpCache cache;
8492
8493 MockTransaction transaction(kRangeGET_TransactionOK);
8494 std::string response_headers = base::StrCat(
8495 {kRangeGET_TransactionOK.response_headers, "Cache-Control: no-store\n"});
8496 transaction.response_headers = response_headers.c_str();
8497 AddMockTransaction(&transaction);
8498
8499 std::string headers;
8500 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8501
8502 Verify206Response(headers, 40, 49);
8503 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8504 EXPECT_EQ(0, cache.disk_cache()->open_count());
8505 EXPECT_EQ(1, cache.disk_cache()->create_count());
8506
8507 RemoveMockTransaction(&transaction);
8508 }
8509
8510 // Tests a 304 setting no-store on existing 206 entry.
TEST_F(HttpCacheTest,RangeGET_NoStore304)8511 TEST_F(HttpCacheTest, RangeGET_NoStore304) {
8512 MockHttpCache cache;
8513
8514 MockTransaction transaction(kRangeGET_TransactionOK);
8515 std::string response_headers = base::StrCat(
8516 {kRangeGET_TransactionOK.response_headers, "Cache-Control: max-age=0\n"});
8517 transaction.response_headers = response_headers.c_str();
8518 AddMockTransaction(&transaction);
8519
8520 std::string headers;
8521 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8522
8523 Verify206Response(headers, 40, 49);
8524 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8525 EXPECT_EQ(0, cache.disk_cache()->open_count());
8526 EXPECT_EQ(1, cache.disk_cache()->create_count());
8527
8528 response_headers = base::StrCat(
8529 {kRangeGET_TransactionOK.response_headers, "Cache-Control: no-store\n"});
8530 transaction.response_headers = response_headers.c_str();
8531 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8532 Verify206Response(headers, 40, 49);
8533
8534 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8535 EXPECT_EQ(1, cache.disk_cache()->open_count());
8536 EXPECT_EQ(1, cache.disk_cache()->create_count());
8537
8538 // Fetch again, this one should be from newly created cache entry, due to
8539 // earlier no-store.
8540 transaction.response_headers = kRangeGET_TransactionOK.response_headers;
8541 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8542 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8543 EXPECT_EQ(1, cache.disk_cache()->open_count());
8544 EXPECT_EQ(2, cache.disk_cache()->create_count());
8545 Verify206Response(headers, 40, 49);
8546
8547 RemoveMockTransaction(&transaction);
8548 }
8549
8550 // Tests that we can cache range requests and fetch random blocks from the
8551 // cache and the network, with synchronous responses.
TEST_F(HttpCacheTest,RangeGET_SyncOK)8552 TEST_F(HttpCacheTest, RangeGET_SyncOK) {
8553 MockHttpCache cache;
8554
8555 MockTransaction transaction(kRangeGET_TransactionOK);
8556 transaction.test_mode = TEST_MODE_SYNC_ALL;
8557 AddMockTransaction(&transaction);
8558
8559 // Write to the cache (40-49).
8560 std::string headers;
8561 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8562
8563 Verify206Response(headers, 40, 49);
8564 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8565 EXPECT_EQ(0, cache.disk_cache()->open_count());
8566 EXPECT_EQ(1, cache.disk_cache()->create_count());
8567
8568 // Read from the cache (40-49).
8569 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8570
8571 Verify206Response(headers, 40, 49);
8572 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8573 EXPECT_EQ(0, cache.disk_cache()->open_count());
8574 EXPECT_EQ(1, cache.disk_cache()->create_count());
8575
8576 // Make sure we are done with the previous transaction.
8577 base::RunLoop().RunUntilIdle();
8578
8579 // Write to the cache (30-39).
8580 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
8581 transaction.data = "rg: 30-39 ";
8582 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8583
8584 Verify206Response(headers, 30, 39);
8585 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8586 EXPECT_EQ(1, cache.disk_cache()->open_count());
8587 EXPECT_EQ(1, cache.disk_cache()->create_count());
8588
8589 // Make sure we are done with the previous transaction.
8590 base::RunLoop().RunUntilIdle();
8591
8592 // Write and read from the cache (20-59).
8593 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8594 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8595 LoadTimingInfo load_timing_info;
8596 RunTransactionTestWithResponseAndGetTiming(
8597 cache.http_cache(), transaction, &headers,
8598 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
8599
8600 Verify206Response(headers, 20, 59);
8601 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8602 EXPECT_EQ(2, cache.disk_cache()->open_count());
8603 EXPECT_EQ(1, cache.disk_cache()->create_count());
8604 TestLoadTimingNetworkRequest(load_timing_info);
8605
8606 RemoveMockTransaction(&transaction);
8607 }
8608
8609 // Tests that if the previous transaction is cancelled while busy (doing sparse
8610 // IO), a new transaction (that reuses that same ActiveEntry) waits until the
8611 // entry is ready again.
TEST_F(HttpCacheTest,Sparse_WaitForEntry)8612 TEST_F(HttpCacheTest, Sparse_WaitForEntry) {
8613 MockHttpCache cache;
8614
8615 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8616
8617 // Create a sparse entry.
8618 RunTransactionTest(cache.http_cache(), transaction);
8619
8620 // Simulate a previous transaction being cancelled.
8621 disk_cache::Entry* entry;
8622 MockHttpRequest request(transaction);
8623 std::string cache_key =
8624 *cache.http_cache()->GenerateCacheKeyForRequest(&request);
8625 ASSERT_TRUE(cache.OpenBackendEntry(cache_key, &entry));
8626 entry->CancelSparseIO();
8627
8628 // Test with a range request.
8629 RunTransactionTest(cache.http_cache(), transaction);
8630
8631 // Now test with a regular request.
8632 entry->CancelSparseIO();
8633 transaction.request_headers = EXTRA_HEADER;
8634 transaction.data = kFullRangeData;
8635 RunTransactionTest(cache.http_cache(), transaction);
8636
8637 entry->Close();
8638 }
8639
8640 // Tests that we don't revalidate an entry unless we are required to do so.
TEST_F(HttpCacheTest,RangeGET_Revalidate1)8641 TEST_F(HttpCacheTest, RangeGET_Revalidate1) {
8642 MockHttpCache cache;
8643 std::string headers;
8644
8645 // Write to the cache (40-49).
8646 MockTransaction transaction(kRangeGET_TransactionOK);
8647 transaction.response_headers =
8648 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
8649 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n" // Should never expire.
8650 "ETag: \"foo\"\n"
8651 "Accept-Ranges: bytes\n"
8652 "Content-Length: 10\n";
8653 AddMockTransaction(&transaction);
8654 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8655
8656 Verify206Response(headers, 40, 49);
8657 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8658 EXPECT_EQ(0, cache.disk_cache()->open_count());
8659 EXPECT_EQ(1, cache.disk_cache()->create_count());
8660
8661 // Read from the cache (40-49).
8662 NetLogWithSource net_log_with_source =
8663 NetLogWithSource::Make(NetLogSourceType::NONE);
8664 LoadTimingInfo load_timing_info;
8665 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
8666 &headers, net_log_with_source,
8667 &load_timing_info);
8668
8669 Verify206Response(headers, 40, 49);
8670 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8671 EXPECT_EQ(1, cache.disk_cache()->open_count());
8672 EXPECT_EQ(1, cache.disk_cache()->create_count());
8673 TestLoadTimingCachedResponse(load_timing_info);
8674
8675 // Read again forcing the revalidation.
8676 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8677 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
8678 &headers, net_log_with_source,
8679 &load_timing_info);
8680
8681 Verify206Response(headers, 40, 49);
8682 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8683 EXPECT_EQ(1, cache.disk_cache()->open_count());
8684 EXPECT_EQ(1, cache.disk_cache()->create_count());
8685 TestLoadTimingNetworkRequest(load_timing_info);
8686
8687 RemoveMockTransaction(&transaction);
8688 }
8689
8690 // Checks that we revalidate an entry when the headers say so.
TEST_F(HttpCacheTest,RangeGET_Revalidate2)8691 TEST_F(HttpCacheTest, RangeGET_Revalidate2) {
8692 MockHttpCache cache;
8693 std::string headers;
8694
8695 // Write to the cache (40-49).
8696 MockTransaction transaction(kRangeGET_TransactionOK);
8697 transaction.response_headers =
8698 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
8699 "Expires: Sat, 18 Apr 2009 01:10:43 GMT\n" // Expired.
8700 "ETag: \"foo\"\n"
8701 "Accept-Ranges: bytes\n"
8702 "Content-Length: 10\n";
8703 AddMockTransaction(&transaction);
8704 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8705
8706 Verify206Response(headers, 40, 49);
8707 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8708 EXPECT_EQ(0, cache.disk_cache()->open_count());
8709 EXPECT_EQ(1, cache.disk_cache()->create_count());
8710
8711 // Read from the cache (40-49).
8712 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8713 Verify206Response(headers, 40, 49);
8714
8715 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8716 EXPECT_EQ(1, cache.disk_cache()->open_count());
8717 EXPECT_EQ(1, cache.disk_cache()->create_count());
8718
8719 RemoveMockTransaction(&transaction);
8720 }
8721
8722 // Tests that we deal with 304s for range requests.
TEST_F(HttpCacheTest,RangeGET_304)8723 TEST_F(HttpCacheTest, RangeGET_304) {
8724 MockHttpCache cache;
8725 AddMockTransaction(&kRangeGET_TransactionOK);
8726 std::string headers;
8727
8728 // Write to the cache (40-49).
8729 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8730 &headers);
8731
8732 Verify206Response(headers, 40, 49);
8733 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8734 EXPECT_EQ(0, cache.disk_cache()->open_count());
8735 EXPECT_EQ(1, cache.disk_cache()->create_count());
8736
8737 // Read from the cache (40-49).
8738 RangeTransactionServer handler;
8739 handler.set_not_modified(true);
8740 MockTransaction transaction(kRangeGET_TransactionOK);
8741 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8742 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8743
8744 Verify206Response(headers, 40, 49);
8745 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8746 EXPECT_EQ(1, cache.disk_cache()->open_count());
8747 EXPECT_EQ(1, cache.disk_cache()->create_count());
8748
8749 RemoveMockTransaction(&kRangeGET_TransactionOK);
8750 }
8751
8752 // Tests that we deal with 206s when revalidating range requests.
TEST_F(HttpCacheTest,RangeGET_ModifiedResult)8753 TEST_F(HttpCacheTest, RangeGET_ModifiedResult) {
8754 MockHttpCache cache;
8755 AddMockTransaction(&kRangeGET_TransactionOK);
8756 std::string headers;
8757
8758 // Write to the cache (40-49).
8759 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8760 &headers);
8761
8762 Verify206Response(headers, 40, 49);
8763 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8764 EXPECT_EQ(0, cache.disk_cache()->open_count());
8765 EXPECT_EQ(1, cache.disk_cache()->create_count());
8766
8767 // Attempt to read from the cache (40-49).
8768 RangeTransactionServer handler;
8769 handler.set_modified(true);
8770 MockTransaction transaction(kRangeGET_TransactionOK);
8771 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8772 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8773
8774 Verify206Response(headers, 40, 49);
8775 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8776 EXPECT_EQ(1, cache.disk_cache()->open_count());
8777 EXPECT_EQ(1, cache.disk_cache()->create_count());
8778
8779 // And the entry should be gone.
8780 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
8781 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8782 EXPECT_EQ(1, cache.disk_cache()->open_count());
8783 EXPECT_EQ(2, cache.disk_cache()->create_count());
8784
8785 RemoveMockTransaction(&kRangeGET_TransactionOK);
8786 }
8787
8788 // Tests that when a server returns 206 with a sub-range of the requested range,
8789 // and there is nothing stored in the cache, the returned response is passed to
8790 // the caller as is. In this context, a subrange means a response that starts
8791 // with the same byte that was requested, but that is not the whole range that
8792 // was requested.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSubrangeRange_NoCachedContent)8793 TEST_F(HttpCacheTest, RangeGET_206ReturnsSubrangeRange_NoCachedContent) {
8794 MockHttpCache cache;
8795 std::string headers;
8796
8797 // Request a large range (40-59). The server sends 40-49.
8798 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8799 transaction.request_headers = "Range: bytes = 40-59\r\n" EXTRA_HEADER;
8800 transaction.response_headers =
8801 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8802 "ETag: \"foo\"\n"
8803 "Accept-Ranges: bytes\n"
8804 "Content-Length: 10\n"
8805 "Content-Range: bytes 40-49/80\n";
8806 transaction.handler = nullptr;
8807 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8808
8809 Verify206Response(headers, 40, 49);
8810 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8811 EXPECT_EQ(0, cache.disk_cache()->open_count());
8812 EXPECT_EQ(1, cache.disk_cache()->create_count());
8813 }
8814
8815 // Tests that when a server returns 206 with a sub-range of the requested range,
8816 // and there was an entry stored in the cache, the cache gets out of the way.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSubrangeRange_CachedContent)8817 TEST_F(HttpCacheTest, RangeGET_206ReturnsSubrangeRange_CachedContent) {
8818 MockHttpCache cache;
8819 std::string headers;
8820
8821 // Write to the cache (70-79).
8822 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8823 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8824 transaction.data = "rg: 70-79 ";
8825 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8826 Verify206Response(headers, 70, 79);
8827
8828 // Request a large range (40-79). The cache will ask the server for 40-59.
8829 // The server returns 40-49. The cache should consider the server confused and
8830 // abort caching, restarting the request without caching.
8831 transaction.request_headers = "Range: bytes = 40-79\r\n" EXTRA_HEADER;
8832 transaction.response_headers =
8833 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8834 "ETag: \"foo\"\n"
8835 "Accept-Ranges: bytes\n"
8836 "Content-Length: 10\n"
8837 "Content-Range: bytes 40-49/80\n";
8838 transaction.handler = nullptr;
8839 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8840
8841 // Two new network requests were issued, one from the cache and another after
8842 // deleting the entry.
8843 Verify206Response(headers, 40, 49);
8844 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8845 EXPECT_EQ(1, cache.disk_cache()->open_count());
8846 EXPECT_EQ(1, cache.disk_cache()->create_count());
8847
8848 // The entry was deleted.
8849 RunTransactionTest(cache.http_cache(), transaction);
8850 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8851 EXPECT_EQ(1, cache.disk_cache()->open_count());
8852 EXPECT_EQ(2, cache.disk_cache()->create_count());
8853 }
8854
8855 // Tests that when a server returns 206 with a sub-range of the requested range,
8856 // and there was an entry stored in the cache, the cache gets out of the way,
8857 // when the caller is not using ranges.
TEST_F(HttpCacheTest,GET_206ReturnsSubrangeRange_CachedContent)8858 TEST_F(HttpCacheTest, GET_206ReturnsSubrangeRange_CachedContent) {
8859 MockHttpCache cache;
8860 std::string headers;
8861
8862 // Write to the cache (70-79).
8863 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8864 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8865 transaction.data = "rg: 70-79 ";
8866 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8867 Verify206Response(headers, 70, 79);
8868
8869 // Don't ask for a range. The cache will ask the server for 0-69.
8870 // The server returns 40-49. The cache should consider the server confused and
8871 // abort caching, restarting the request.
8872 // The second network request should not be a byte range request so the server
8873 // should return 200 + "Not a range"
8874 transaction.request_headers = "X-Return-Default-Range:\r\n" EXTRA_HEADER;
8875 transaction.data = "Not a range";
8876 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8877
8878 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
8879 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8880 EXPECT_EQ(1, cache.disk_cache()->open_count());
8881 EXPECT_EQ(1, cache.disk_cache()->create_count());
8882
8883 // The entry was deleted.
8884 RunTransactionTest(cache.http_cache(), transaction);
8885 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8886 EXPECT_EQ(1, cache.disk_cache()->open_count());
8887 EXPECT_EQ(2, cache.disk_cache()->create_count());
8888 }
8889
8890 // Tests that when a server returns 206 with a random range and there is
8891 // nothing stored in the cache, the returned response is passed to the caller
8892 // as is. In this context, a WrongRange means that the returned range may or may
8893 // not have any relationship with the requested range (may or may not be
8894 // contained). The important part is that the first byte doesn't match the first
8895 // requested byte.
TEST_F(HttpCacheTest,RangeGET_206ReturnsWrongRange_NoCachedContent)8896 TEST_F(HttpCacheTest, RangeGET_206ReturnsWrongRange_NoCachedContent) {
8897 MockHttpCache cache;
8898 std::string headers;
8899
8900 // Request a large range (30-59). The server sends (40-49).
8901 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8902 transaction.request_headers = "Range: bytes = 30-59\r\n" EXTRA_HEADER;
8903 transaction.response_headers =
8904 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8905 "ETag: \"foo\"\n"
8906 "Accept-Ranges: bytes\n"
8907 "Content-Length: 10\n"
8908 "Content-Range: bytes 40-49/80\n";
8909 transaction.handler = nullptr;
8910 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8911
8912 Verify206Response(headers, 40, 49);
8913 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8914 EXPECT_EQ(0, cache.disk_cache()->open_count());
8915 EXPECT_EQ(1, cache.disk_cache()->create_count());
8916
8917 // The entry was deleted.
8918 RunTransactionTest(cache.http_cache(), transaction);
8919 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8920 EXPECT_EQ(0, cache.disk_cache()->open_count());
8921 EXPECT_EQ(2, cache.disk_cache()->create_count());
8922 }
8923
8924 // Tests that when a server returns 206 with a random range and there is
8925 // an entry stored in the cache, the cache gets out of the way.
TEST_F(HttpCacheTest,RangeGET_206ReturnsWrongRange_CachedContent)8926 TEST_F(HttpCacheTest, RangeGET_206ReturnsWrongRange_CachedContent) {
8927 MockHttpCache cache;
8928 std::string headers;
8929
8930 // Write to the cache (70-79).
8931 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8932 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8933 transaction.data = "rg: 70-79 ";
8934 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8935 Verify206Response(headers, 70, 79);
8936
8937 // Request a large range (30-79). The cache will ask the server for 30-69.
8938 // The server returns 40-49. The cache should consider the server confused and
8939 // abort caching, returning the weird range to the caller.
8940 transaction.request_headers = "Range: bytes = 30-79\r\n" EXTRA_HEADER;
8941 transaction.response_headers =
8942 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8943 "ETag: \"foo\"\n"
8944 "Accept-Ranges: bytes\n"
8945 "Content-Length: 10\n"
8946 "Content-Range: bytes 40-49/80\n";
8947 transaction.handler = nullptr;
8948 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8949
8950 Verify206Response(headers, 40, 49);
8951 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8952 EXPECT_EQ(1, cache.disk_cache()->open_count());
8953 EXPECT_EQ(1, cache.disk_cache()->create_count());
8954
8955 // The entry was deleted.
8956 RunTransactionTest(cache.http_cache(), transaction);
8957 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8958 EXPECT_EQ(1, cache.disk_cache()->open_count());
8959 EXPECT_EQ(2, cache.disk_cache()->create_count());
8960 }
8961
8962 // Tests that when a caller asks for a range beyond EOF, with an empty cache,
8963 // the response matches the one provided by the server.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSmallerFile_NoCachedContent)8964 TEST_F(HttpCacheTest, RangeGET_206ReturnsSmallerFile_NoCachedContent) {
8965 MockHttpCache cache;
8966 std::string headers;
8967
8968 // Request a large range (70-99). The server sends 70-79.
8969 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8970 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
8971 transaction.data = "rg: 70-79 ";
8972 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8973
8974 Verify206Response(headers, 70, 79);
8975 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8976 EXPECT_EQ(0, cache.disk_cache()->open_count());
8977 EXPECT_EQ(1, cache.disk_cache()->create_count());
8978
8979 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
8980 EXPECT_EQ(1, cache.disk_cache()->open_count());
8981 }
8982
8983 // Tests that when a caller asks for a range beyond EOF, with a cached entry,
8984 // the cache automatically fixes the request.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSmallerFile_CachedContent)8985 TEST_F(HttpCacheTest, RangeGET_206ReturnsSmallerFile_CachedContent) {
8986 MockHttpCache cache;
8987 std::string headers;
8988
8989 // Write to the cache (40-49).
8990 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8991 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8992
8993 // Request a large range (70-99). The server sends 70-79.
8994 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
8995 transaction.data = "rg: 70-79 ";
8996 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8997
8998 Verify206Response(headers, 70, 79);
8999 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9000 EXPECT_EQ(1, cache.disk_cache()->open_count());
9001 EXPECT_EQ(1, cache.disk_cache()->create_count());
9002
9003 // The entry was not deleted (the range was automatically fixed).
9004 RunTransactionTest(cache.http_cache(), transaction);
9005 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9006 EXPECT_EQ(2, cache.disk_cache()->open_count());
9007 EXPECT_EQ(1, cache.disk_cache()->create_count());
9008 }
9009
9010 // Tests that when a caller asks for a not-satisfiable range, the server's
9011 // response is forwarded to the caller.
TEST_F(HttpCacheTest,RangeGET_416_NoCachedContent)9012 TEST_F(HttpCacheTest, RangeGET_416_NoCachedContent) {
9013 MockHttpCache cache;
9014 std::string headers;
9015
9016 // Request a range beyond EOF (80-99).
9017 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9018 transaction.request_headers = "Range: bytes = 80-99\r\n" EXTRA_HEADER;
9019 transaction.data = "";
9020 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
9021 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9022
9023 EXPECT_EQ(0U, headers.find(transaction.status));
9024 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9025 EXPECT_EQ(0, cache.disk_cache()->open_count());
9026 EXPECT_EQ(1, cache.disk_cache()->create_count());
9027
9028 // The entry was deleted.
9029 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9030 EXPECT_EQ(2, cache.disk_cache()->create_count());
9031 }
9032
9033 // Tests that we cache 301s for range requests.
TEST_F(HttpCacheTest,RangeGET_301)9034 TEST_F(HttpCacheTest, RangeGET_301) {
9035 MockHttpCache cache;
9036 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9037 transaction.status = "HTTP/1.1 301 Moved Permanently";
9038 transaction.response_headers = "Location: http://www.bar.com/\n";
9039 transaction.data = "";
9040 transaction.handler = nullptr;
9041
9042 // Write to the cache.
9043 RunTransactionTest(cache.http_cache(), transaction);
9044 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9045 EXPECT_EQ(0, cache.disk_cache()->open_count());
9046 EXPECT_EQ(1, cache.disk_cache()->create_count());
9047
9048 // Read from the cache.
9049 RunTransactionTest(cache.http_cache(), transaction);
9050 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9051 EXPECT_EQ(1, cache.disk_cache()->open_count());
9052 EXPECT_EQ(1, cache.disk_cache()->create_count());
9053 }
9054
9055 // Tests that we can cache range requests when the start or end is unknown.
9056 // We start with one suffix request, followed by a request from a given point.
TEST_F(HttpCacheTest,UnknownRangeGET_1)9057 TEST_F(HttpCacheTest, UnknownRangeGET_1) {
9058 MockHttpCache cache;
9059 AddMockTransaction(&kRangeGET_TransactionOK);
9060 std::string headers;
9061
9062 // Write to the cache (70-79).
9063 MockTransaction transaction(kRangeGET_TransactionOK);
9064 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
9065 transaction.data = "rg: 70-79 ";
9066 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9067
9068 Verify206Response(headers, 70, 79);
9069 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9070 EXPECT_EQ(0, cache.disk_cache()->open_count());
9071 EXPECT_EQ(1, cache.disk_cache()->create_count());
9072
9073 // Make sure we are done with the previous transaction.
9074 base::RunLoop().RunUntilIdle();
9075
9076 // Write and read from the cache (60-79).
9077 transaction.request_headers = "Range: bytes = 60-\r\n" EXTRA_HEADER;
9078 transaction.data = "rg: 60-69 rg: 70-79 ";
9079 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9080
9081 Verify206Response(headers, 60, 79);
9082 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9083 EXPECT_EQ(1, cache.disk_cache()->open_count());
9084 EXPECT_EQ(1, cache.disk_cache()->create_count());
9085
9086 RemoveMockTransaction(&kRangeGET_TransactionOK);
9087 }
9088
9089 // Tests that we can cache range requests when the start or end is unknown.
9090 // We start with one request from a given point, followed by a suffix request.
9091 // We'll also verify that synchronous cache responses work as intended.
TEST_F(HttpCacheTest,UnknownRangeGET_2)9092 TEST_F(HttpCacheTest, UnknownRangeGET_2) {
9093 MockHttpCache cache;
9094 std::string headers;
9095
9096 MockTransaction transaction(kRangeGET_TransactionOK);
9097 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9098 TEST_MODE_SYNC_CACHE_READ |
9099 TEST_MODE_SYNC_CACHE_WRITE;
9100 AddMockTransaction(&transaction);
9101
9102 // Write to the cache (70-79).
9103 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
9104 transaction.data = "rg: 70-79 ";
9105 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9106
9107 Verify206Response(headers, 70, 79);
9108 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9109 EXPECT_EQ(0, cache.disk_cache()->open_count());
9110 EXPECT_EQ(1, cache.disk_cache()->create_count());
9111
9112 // Make sure we are done with the previous transaction.
9113 base::RunLoop().RunUntilIdle();
9114
9115 // Write and read from the cache (60-79).
9116 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
9117 transaction.data = "rg: 60-69 rg: 70-79 ";
9118 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9119
9120 Verify206Response(headers, 60, 79);
9121 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9122 EXPECT_EQ(1, cache.disk_cache()->open_count());
9123 EXPECT_EQ(1, cache.disk_cache()->create_count());
9124
9125 RemoveMockTransaction(&transaction);
9126 }
9127
9128 // Similar to UnknownRangeGET_2, except that the resource size is empty.
9129 // Regression test for crbug.com/813061, and probably https://crbug.com/1375128
TEST_F(HttpCacheTest,UnknownRangeGET_3)9130 TEST_F(HttpCacheTest, UnknownRangeGET_3) {
9131 MockHttpCache cache;
9132 std::string headers;
9133
9134 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9135 transaction.response_headers =
9136 "Cache-Control: max-age=10000\n"
9137 "Content-Length: 0\n",
9138 transaction.data = "";
9139 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9140 TEST_MODE_SYNC_CACHE_READ |
9141 TEST_MODE_SYNC_CACHE_WRITE;
9142
9143 // Write the empty resource to the cache.
9144 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9145
9146 EXPECT_EQ(
9147 "HTTP/1.1 200 OK\nCache-Control: max-age=10000\nContent-Length: 0\n",
9148 headers);
9149 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9150 EXPECT_EQ(0, cache.disk_cache()->open_count());
9151 EXPECT_EQ(1, cache.disk_cache()->create_count());
9152
9153 // Make sure we are done with the previous transaction.
9154 base::RunLoop().RunUntilIdle();
9155
9156 // Write and read from the cache. This used to trigger a DCHECK
9157 // (or loop infinitely with it off).
9158 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
9159 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9160
9161 EXPECT_EQ(
9162 "HTTP/1.1 200 OK\nCache-Control: max-age=10000\nContent-Length: 0\n",
9163 headers);
9164 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9165 EXPECT_EQ(1, cache.disk_cache()->open_count());
9166 EXPECT_EQ(1, cache.disk_cache()->create_count());
9167 }
9168
9169 // Testcase for https://crbug.com/1433305, validation of range request to a
9170 // cache 302, which is notably bodiless.
TEST_F(HttpCacheTest,UnknownRangeGET_302)9171 TEST_F(HttpCacheTest, UnknownRangeGET_302) {
9172 MockHttpCache cache;
9173 std::string headers;
9174
9175 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9176 transaction.status = "HTTP/1.1 302 Found";
9177 transaction.response_headers =
9178 "Cache-Control: max-age=0\n"
9179 "Content-Length: 0\n"
9180 "Location: https://example.org/\n",
9181
9182 transaction.data = "";
9183 transaction.request_headers = "Range: bytes = 0-\r\n" EXTRA_HEADER;
9184 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9185 TEST_MODE_SYNC_CACHE_READ |
9186 TEST_MODE_SYNC_CACHE_WRITE;
9187
9188 // Write the empty resource to the cache.
9189 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9190
9191 EXPECT_EQ(
9192 "HTTP/1.1 302 Found\n"
9193 "Cache-Control: max-age=0\n"
9194 "Content-Length: 0\n"
9195 "Location: https://example.org/\n",
9196 headers);
9197 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9198 EXPECT_EQ(0, cache.disk_cache()->open_count());
9199 EXPECT_EQ(1, cache.disk_cache()->create_count());
9200
9201 // Make sure we are done with the previous transaction.
9202 base::RunLoop().RunUntilIdle();
9203
9204 // Try to read from the cache. This should send a network request to
9205 // validate it, and get a different redirect.
9206 transaction.response_headers =
9207 "Cache-Control: max-age=0\n"
9208 "Content-Length: 0\n"
9209 "Location: https://example.com/\n",
9210 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9211
9212 EXPECT_EQ(
9213 "HTTP/1.1 302 Found\n"
9214 "Cache-Control: max-age=0\n"
9215 "Content-Length: 0\n"
9216 "Location: https://example.com/\n",
9217 headers);
9218 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9219 EXPECT_EQ(1, cache.disk_cache()->open_count());
9220 // A new entry is created since this one isn't conditionalizable.
9221 EXPECT_EQ(2, cache.disk_cache()->create_count());
9222 }
9223
9224 // Testcase for https://crbug.com/1433305, validation of range request to a
9225 // cache 302, which is notably bodiless, where the 302 is replaced with an
9226 // actual body.
TEST_F(HttpCacheTest,UnknownRangeGET_302_Replaced)9227 TEST_F(HttpCacheTest, UnknownRangeGET_302_Replaced) {
9228 MockHttpCache cache;
9229 std::string headers;
9230
9231 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9232 transaction.status = "HTTP/1.1 302 Found";
9233 transaction.response_headers =
9234 "Cache-Control: max-age=0\n"
9235 "Content-Length: 0\n"
9236 "Location: https://example.org/\n",
9237
9238 transaction.data = "";
9239 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9240 TEST_MODE_SYNC_CACHE_READ |
9241 TEST_MODE_SYNC_CACHE_WRITE;
9242
9243 // Write the empty resource to the cache.
9244 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9245
9246 EXPECT_EQ(
9247 "HTTP/1.1 302 Found\n"
9248 "Cache-Control: max-age=0\n"
9249 "Content-Length: 0\n"
9250 "Location: https://example.org/\n",
9251 headers);
9252 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9253 EXPECT_EQ(0, cache.disk_cache()->open_count());
9254 EXPECT_EQ(1, cache.disk_cache()->create_count());
9255
9256 // Make sure we are done with the previous transaction.
9257 base::RunLoop().RunUntilIdle();
9258
9259 // Try to read from the cache. This should send a network request to
9260 // validate it, and get a different response.
9261 transaction.handler = &RangeTransactionServer::RangeHandler;
9262 transaction.request_headers = "Range: bytes = -30\r\n" EXTRA_HEADER;
9263 // Tail 30 bytes out of 80
9264 transaction.data = "rg: 50-59 rg: 60-69 rg: 70-79 ";
9265 transaction.status = "HTTP/1.1 206 Partial Content";
9266 transaction.response_headers = "Content-Length: 10\n";
9267 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9268
9269 EXPECT_EQ(
9270 "HTTP/1.1 206 Partial Content\n"
9271 "Content-Range: bytes 50-79/80\n"
9272 "Content-Length: 30\n",
9273 headers);
9274 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9275 EXPECT_EQ(1, cache.disk_cache()->open_count());
9276 // A new entry is created since this one isn't conditionalizable.
9277 EXPECT_EQ(2, cache.disk_cache()->create_count());
9278 }
9279
9280 // Tests that receiving Not Modified when asking for an open range doesn't mess
9281 // up things.
TEST_F(HttpCacheTest,UnknownRangeGET_304)9282 TEST_F(HttpCacheTest, UnknownRangeGET_304) {
9283 MockHttpCache cache;
9284 std::string headers;
9285
9286 MockTransaction transaction(kRangeGET_TransactionOK);
9287 AddMockTransaction(&transaction);
9288
9289 RangeTransactionServer handler;
9290 handler.set_not_modified(true);
9291
9292 // Ask for the end of the file, without knowing the length.
9293 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
9294 transaction.data = "";
9295 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9296
9297 // We just bypass the cache.
9298 EXPECT_EQ(0U, headers.find("HTTP/1.1 304 Not Modified\n"));
9299 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9300 EXPECT_EQ(0, cache.disk_cache()->open_count());
9301 EXPECT_EQ(1, cache.disk_cache()->create_count());
9302
9303 RunTransactionTest(cache.http_cache(), transaction);
9304 EXPECT_EQ(2, cache.disk_cache()->create_count());
9305
9306 RemoveMockTransaction(&transaction);
9307 }
9308
9309 // Tests that we can handle non-range requests when we have cached a range.
TEST_F(HttpCacheTest,GET_Previous206)9310 TEST_F(HttpCacheTest, GET_Previous206) {
9311 MockHttpCache cache;
9312 AddMockTransaction(&kRangeGET_TransactionOK);
9313 std::string headers;
9314 NetLogWithSource net_log_with_source =
9315 NetLogWithSource::Make(NetLogSourceType::NONE);
9316 LoadTimingInfo load_timing_info;
9317
9318 // Write to the cache (40-49).
9319 RunTransactionTestWithResponseAndGetTiming(
9320 cache.http_cache(), kRangeGET_TransactionOK, &headers,
9321 net_log_with_source, &load_timing_info);
9322
9323 Verify206Response(headers, 40, 49);
9324 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9325 EXPECT_EQ(0, cache.disk_cache()->open_count());
9326 EXPECT_EQ(1, cache.disk_cache()->create_count());
9327 TestLoadTimingNetworkRequest(load_timing_info);
9328
9329 // Write and read from the cache (0-79), when not asked for a range.
9330 MockTransaction transaction(kRangeGET_TransactionOK);
9331 transaction.request_headers = EXTRA_HEADER;
9332 transaction.data = kFullRangeData;
9333 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9334 &headers, net_log_with_source,
9335 &load_timing_info);
9336
9337 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9338 EXPECT_EQ(3, cache.network_layer()->transaction_count());
9339 EXPECT_EQ(1, cache.disk_cache()->open_count());
9340 EXPECT_EQ(1, cache.disk_cache()->create_count());
9341 TestLoadTimingNetworkRequest(load_timing_info);
9342
9343 RemoveMockTransaction(&kRangeGET_TransactionOK);
9344 }
9345
9346 // Tests that we can handle non-range requests when we have cached the first
9347 // part of the object and the server replies with 304 (Not Modified).
TEST_F(HttpCacheTest,GET_Previous206_NotModified)9348 TEST_F(HttpCacheTest, GET_Previous206_NotModified) {
9349 MockHttpCache cache;
9350
9351 MockTransaction transaction(kRangeGET_TransactionOK);
9352 AddMockTransaction(&transaction);
9353 std::string headers;
9354 NetLogWithSource net_log_with_source =
9355 NetLogWithSource::Make(NetLogSourceType::NONE);
9356
9357 LoadTimingInfo load_timing_info;
9358
9359 // Write to the cache (0-9).
9360 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
9361 transaction.data = "rg: 00-09 ";
9362 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9363 &headers, net_log_with_source,
9364 &load_timing_info);
9365 Verify206Response(headers, 0, 9);
9366 TestLoadTimingNetworkRequest(load_timing_info);
9367
9368 // Write to the cache (70-79).
9369 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
9370 transaction.data = "rg: 70-79 ";
9371 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9372 &headers, net_log_with_source,
9373 &load_timing_info);
9374 Verify206Response(headers, 70, 79);
9375
9376 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9377 EXPECT_EQ(1, cache.disk_cache()->open_count());
9378 EXPECT_EQ(1, cache.disk_cache()->create_count());
9379 TestLoadTimingNetworkRequest(load_timing_info);
9380
9381 // Read from the cache (0-9), write and read from cache (10 - 79).
9382 transaction.load_flags |= LOAD_VALIDATE_CACHE;
9383 transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER;
9384 transaction.data = kFullRangeData;
9385 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9386 &headers, net_log_with_source,
9387 &load_timing_info);
9388
9389 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9390 EXPECT_EQ(4, cache.network_layer()->transaction_count());
9391 EXPECT_EQ(2, cache.disk_cache()->open_count());
9392 EXPECT_EQ(1, cache.disk_cache()->create_count());
9393 TestLoadTimingNetworkRequest(load_timing_info);
9394
9395 RemoveMockTransaction(&transaction);
9396 }
9397
9398 // Tests that we can handle a regular request to a sparse entry, that results in
9399 // new content provided by the server (206).
TEST_F(HttpCacheTest,GET_Previous206_NewContent)9400 TEST_F(HttpCacheTest, GET_Previous206_NewContent) {
9401 MockHttpCache cache;
9402 AddMockTransaction(&kRangeGET_TransactionOK);
9403 std::string headers;
9404
9405 // Write to the cache (0-9).
9406 MockTransaction transaction(kRangeGET_TransactionOK);
9407 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
9408 transaction.data = "rg: 00-09 ";
9409 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9410
9411 Verify206Response(headers, 0, 9);
9412 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9413 EXPECT_EQ(0, cache.disk_cache()->open_count());
9414 EXPECT_EQ(1, cache.disk_cache()->create_count());
9415
9416 // Now we'll issue a request without any range that should result first in a
9417 // 206 (when revalidating), and then in a weird standard answer: the test
9418 // server will not modify the response so we'll get the default range... a
9419 // real server will answer with 200.
9420 MockTransaction transaction2(kRangeGET_TransactionOK);
9421 transaction2.request_headers = EXTRA_HEADER;
9422 transaction2.load_flags |= LOAD_VALIDATE_CACHE;
9423 transaction2.data = "Not a range";
9424 RangeTransactionServer handler;
9425 handler.set_modified(true);
9426 LoadTimingInfo load_timing_info;
9427 RunTransactionTestWithResponseAndGetTiming(
9428 cache.http_cache(), transaction2, &headers,
9429 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
9430
9431 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9432 EXPECT_EQ(3, cache.network_layer()->transaction_count());
9433 EXPECT_EQ(1, cache.disk_cache()->open_count());
9434 EXPECT_EQ(1, cache.disk_cache()->create_count());
9435 TestLoadTimingNetworkRequest(load_timing_info);
9436
9437 // Verify that the previous request deleted the entry.
9438 RunTransactionTest(cache.http_cache(), transaction);
9439 EXPECT_EQ(2, cache.disk_cache()->create_count());
9440
9441 RemoveMockTransaction(&transaction);
9442 }
9443
9444 // Tests that we can handle cached 206 responses that are not sparse.
TEST_F(HttpCacheTest,GET_Previous206_NotSparse)9445 TEST_F(HttpCacheTest, GET_Previous206_NotSparse) {
9446 MockHttpCache cache;
9447
9448 MockHttpRequest request(kSimpleGET_Transaction);
9449 // Create a disk cache entry that stores 206 headers while not being sparse.
9450 disk_cache::Entry* entry;
9451 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9452
9453 std::string raw_headers(kRangeGET_TransactionOK.status);
9454 raw_headers.append("\n");
9455 raw_headers.append(kRangeGET_TransactionOK.response_headers);
9456
9457 HttpResponseInfo response;
9458 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9459 HttpUtil::AssembleRawHeaders(raw_headers));
9460 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9461
9462 scoped_refptr<IOBuffer> buf(base::MakeRefCounted<IOBuffer>(500));
9463 int len = static_cast<int>(base::strlcpy(buf->data(),
9464 kRangeGET_TransactionOK.data, 500));
9465 TestCompletionCallback cb;
9466 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9467 EXPECT_EQ(len, cb.GetResult(rv));
9468 entry->Close();
9469
9470 // Now see that we don't use the stored entry.
9471 std::string headers;
9472 LoadTimingInfo load_timing_info;
9473 RunTransactionTestWithResponseAndGetTiming(
9474 cache.http_cache(), kSimpleGET_Transaction, &headers,
9475 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
9476
9477 // We are expecting a 200.
9478 std::string expected_headers(kSimpleGET_Transaction.status);
9479 expected_headers.append("\n");
9480 expected_headers.append(kSimpleGET_Transaction.response_headers);
9481 EXPECT_EQ(expected_headers, headers);
9482 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9483 EXPECT_EQ(1, cache.disk_cache()->open_count());
9484 EXPECT_EQ(2, cache.disk_cache()->create_count());
9485 TestLoadTimingNetworkRequest(load_timing_info);
9486 }
9487
9488 // Tests that we can handle cached 206 responses that are not sparse. This time
9489 // we issue a range request and expect to receive a range.
TEST_F(HttpCacheTest,RangeGET_Previous206_NotSparse_2)9490 TEST_F(HttpCacheTest, RangeGET_Previous206_NotSparse_2) {
9491 MockHttpCache cache;
9492 AddMockTransaction(&kRangeGET_TransactionOK);
9493
9494 // Create a disk cache entry that stores 206 headers while not being sparse.
9495 MockHttpRequest request(kRangeGET_TransactionOK);
9496 disk_cache::Entry* entry;
9497 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9498
9499 std::string raw_headers(kRangeGET_TransactionOK.status);
9500 raw_headers.append("\n");
9501 raw_headers.append(kRangeGET_TransactionOK.response_headers);
9502
9503 HttpResponseInfo response;
9504 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9505 HttpUtil::AssembleRawHeaders(raw_headers));
9506 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9507
9508 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(500);
9509 int len = static_cast<int>(base::strlcpy(buf->data(),
9510 kRangeGET_TransactionOK.data, 500));
9511 TestCompletionCallback cb;
9512 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9513 EXPECT_EQ(len, cb.GetResult(rv));
9514 entry->Close();
9515
9516 // Now see that we don't use the stored entry.
9517 std::string headers;
9518 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9519 &headers);
9520
9521 // We are expecting a 206.
9522 Verify206Response(headers, 40, 49);
9523 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9524 EXPECT_EQ(1, cache.disk_cache()->open_count());
9525 EXPECT_EQ(2, cache.disk_cache()->create_count());
9526
9527 RemoveMockTransaction(&kRangeGET_TransactionOK);
9528 }
9529
9530 // Tests that we can handle cached 206 responses that can't be validated.
TEST_F(HttpCacheTest,GET_Previous206_NotValidation)9531 TEST_F(HttpCacheTest, GET_Previous206_NotValidation) {
9532 MockHttpCache cache;
9533
9534 MockHttpRequest request(kSimpleGET_Transaction);
9535 // Create a disk cache entry that stores 206 headers.
9536 disk_cache::Entry* entry;
9537 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9538
9539 // Make sure that the headers cannot be validated with the server.
9540 std::string raw_headers(kRangeGET_TransactionOK.status);
9541 raw_headers.append("\n");
9542 raw_headers.append("Content-Length: 80\n");
9543
9544 HttpResponseInfo response;
9545 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9546 HttpUtil::AssembleRawHeaders(raw_headers));
9547 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9548
9549 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(500);
9550 int len = static_cast<int>(base::strlcpy(buf->data(),
9551 kRangeGET_TransactionOK.data, 500));
9552 TestCompletionCallback cb;
9553 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9554 EXPECT_EQ(len, cb.GetResult(rv));
9555 entry->Close();
9556
9557 // Now see that we don't use the stored entry.
9558 std::string headers;
9559 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction,
9560 &headers);
9561
9562 // We are expecting a 200.
9563 std::string expected_headers(kSimpleGET_Transaction.status);
9564 expected_headers.append("\n");
9565 expected_headers.append(kSimpleGET_Transaction.response_headers);
9566 EXPECT_EQ(expected_headers, headers);
9567 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9568 EXPECT_EQ(1, cache.disk_cache()->open_count());
9569 EXPECT_EQ(2, cache.disk_cache()->create_count());
9570 }
9571
9572 // Tests that we can handle range requests with cached 200 responses.
TEST_F(HttpCacheTest,RangeGET_Previous200)9573 TEST_F(HttpCacheTest, RangeGET_Previous200) {
9574 MockHttpCache cache;
9575
9576 // Store the whole thing with status 200.
9577 MockTransaction transaction(kTypicalGET_Transaction);
9578 transaction.url = kRangeGET_TransactionOK.url;
9579 transaction.data = kFullRangeData;
9580 AddMockTransaction(&transaction);
9581 RunTransactionTest(cache.http_cache(), transaction);
9582 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9583 EXPECT_EQ(0, cache.disk_cache()->open_count());
9584 EXPECT_EQ(1, cache.disk_cache()->create_count());
9585
9586 RemoveMockTransaction(&transaction);
9587 AddMockTransaction(&kRangeGET_TransactionOK);
9588
9589 // Now see that we use the stored entry.
9590 std::string headers;
9591 MockTransaction transaction2(kRangeGET_TransactionOK);
9592 RangeTransactionServer handler;
9593 handler.set_not_modified(true);
9594 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9595
9596 // We are expecting a 206.
9597 Verify206Response(headers, 40, 49);
9598 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9599 EXPECT_EQ(1, cache.disk_cache()->open_count());
9600 EXPECT_EQ(1, cache.disk_cache()->create_count());
9601
9602 // The last transaction has finished so make sure the entry is deactivated.
9603 base::RunLoop().RunUntilIdle();
9604
9605 // Make a request for an invalid range.
9606 MockTransaction transaction3(kRangeGET_TransactionOK);
9607 transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER;
9608 transaction3.data = transaction.data;
9609 transaction3.load_flags = LOAD_SKIP_CACHE_VALIDATION;
9610 RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers);
9611 EXPECT_EQ(2, cache.disk_cache()->open_count());
9612 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 "));
9613 EXPECT_EQ(std::string::npos, headers.find("Content-Range:"));
9614 EXPECT_EQ(std::string::npos, headers.find("Content-Length: 80"));
9615
9616 // Make sure the entry is deactivated.
9617 base::RunLoop().RunUntilIdle();
9618
9619 // Even though the request was invalid, we should have the entry.
9620 RunTransactionTest(cache.http_cache(), transaction2);
9621 EXPECT_EQ(3, cache.disk_cache()->open_count());
9622
9623 // Make sure the entry is deactivated.
9624 base::RunLoop().RunUntilIdle();
9625
9626 // Now we should receive a range from the server and drop the stored entry.
9627 handler.set_not_modified(false);
9628 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
9629 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9630 Verify206Response(headers, 40, 49);
9631 EXPECT_EQ(4, cache.network_layer()->transaction_count());
9632 EXPECT_EQ(4, cache.disk_cache()->open_count());
9633 EXPECT_EQ(1, cache.disk_cache()->create_count());
9634
9635 RunTransactionTest(cache.http_cache(), transaction2);
9636 EXPECT_EQ(2, cache.disk_cache()->create_count());
9637
9638 RemoveMockTransaction(&kRangeGET_TransactionOK);
9639 }
9640
9641 // Tests that we can handle a 200 response when dealing with sparse entries.
TEST_F(HttpCacheTest,RangeRequestResultsIn200)9642 TEST_F(HttpCacheTest, RangeRequestResultsIn200) {
9643 MockHttpCache cache;
9644 AddMockTransaction(&kRangeGET_TransactionOK);
9645 std::string headers;
9646
9647 // Write to the cache (70-79).
9648 MockTransaction transaction(kRangeGET_TransactionOK);
9649 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
9650 transaction.data = "rg: 70-79 ";
9651 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9652
9653 Verify206Response(headers, 70, 79);
9654 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9655 EXPECT_EQ(0, cache.disk_cache()->open_count());
9656 EXPECT_EQ(1, cache.disk_cache()->create_count());
9657
9658 // Now we'll issue a request that results in a plain 200 response, but to
9659 // the to the same URL that we used to store sparse data, and making sure
9660 // that we ask for a range.
9661 RemoveMockTransaction(&kRangeGET_TransactionOK);
9662 MockTransaction transaction2(kSimpleGET_Transaction);
9663 transaction2.url = kRangeGET_TransactionOK.url;
9664 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
9665 AddMockTransaction(&transaction2);
9666
9667 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9668
9669 std::string expected_headers(kSimpleGET_Transaction.status);
9670 expected_headers.append("\n");
9671 expected_headers.append(kSimpleGET_Transaction.response_headers);
9672 EXPECT_EQ(expected_headers, headers);
9673 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9674 EXPECT_EQ(1, cache.disk_cache()->open_count());
9675 EXPECT_EQ(1, cache.disk_cache()->create_count());
9676
9677 RemoveMockTransaction(&transaction2);
9678 }
9679
9680 // Tests that a range request that falls outside of the size that we know about
9681 // only deletes the entry if the resource has indeed changed.
TEST_F(HttpCacheTest,RangeGET_MoreThanCurrentSize)9682 TEST_F(HttpCacheTest, RangeGET_MoreThanCurrentSize) {
9683 MockHttpCache cache;
9684 AddMockTransaction(&kRangeGET_TransactionOK);
9685 std::string headers;
9686
9687 // Write to the cache (40-49).
9688 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9689 &headers);
9690
9691 Verify206Response(headers, 40, 49);
9692 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9693 EXPECT_EQ(0, cache.disk_cache()->open_count());
9694 EXPECT_EQ(1, cache.disk_cache()->create_count());
9695
9696 // A weird request should not delete this entry. Ask for bytes 120-.
9697 MockTransaction transaction(kRangeGET_TransactionOK);
9698 transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER;
9699 transaction.data = "";
9700 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9701
9702 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
9703 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9704 EXPECT_EQ(1, cache.disk_cache()->open_count());
9705 EXPECT_EQ(1, cache.disk_cache()->create_count());
9706
9707 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9708 EXPECT_EQ(2, cache.disk_cache()->open_count());
9709 EXPECT_EQ(1, cache.disk_cache()->create_count());
9710
9711 RemoveMockTransaction(&kRangeGET_TransactionOK);
9712 }
9713
9714 // Tests that we don't delete a sparse entry when we cancel a request.
TEST_F(HttpCacheTest,RangeGET_Cancel)9715 TEST_F(HttpCacheTest, RangeGET_Cancel) {
9716 MockHttpCache cache;
9717 AddMockTransaction(&kRangeGET_TransactionOK);
9718
9719 MockHttpRequest request(kRangeGET_TransactionOK);
9720
9721 auto c = std::make_unique<Context>();
9722 int rv = cache.CreateTransaction(&c->trans);
9723 ASSERT_THAT(rv, IsOk());
9724
9725 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9726 if (rv == ERR_IO_PENDING)
9727 rv = c->callback.WaitForResult();
9728
9729 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9730 EXPECT_EQ(0, cache.disk_cache()->open_count());
9731 EXPECT_EQ(1, cache.disk_cache()->create_count());
9732
9733 // Make sure that the entry has some data stored.
9734 scoped_refptr<IOBufferWithSize> buf =
9735 base::MakeRefCounted<IOBufferWithSize>(10);
9736 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9737 if (rv == ERR_IO_PENDING)
9738 rv = c->callback.WaitForResult();
9739 EXPECT_EQ(buf->size(), rv);
9740
9741 // Destroy the transaction.
9742 c.reset();
9743
9744 // Verify that the entry has not been deleted.
9745 disk_cache::Entry* entry;
9746 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9747 entry->Close();
9748 RemoveMockTransaction(&kRangeGET_TransactionOK);
9749 }
9750
9751 // Tests that we don't mark an entry as truncated if it is partial and not
9752 // already truncated.
TEST_F(HttpCacheTest,RangeGET_CancelWhileReading)9753 TEST_F(HttpCacheTest, RangeGET_CancelWhileReading) {
9754 MockHttpCache cache;
9755 AddMockTransaction(&kRangeGET_TransactionOK);
9756
9757 MockHttpRequest request(kRangeGET_TransactionOK);
9758
9759 auto context = std::make_unique<Context>();
9760 int rv = cache.CreateTransaction(&context->trans);
9761 ASSERT_THAT(rv, IsOk());
9762
9763 rv = context->trans->Start(&request, context->callback.callback(),
9764 NetLogWithSource());
9765 if (rv == ERR_IO_PENDING)
9766 rv = context->callback.WaitForResult();
9767
9768 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9769 EXPECT_EQ(0, cache.disk_cache()->open_count());
9770 EXPECT_EQ(1, cache.disk_cache()->create_count());
9771
9772 // Start Read.
9773 scoped_refptr<IOBufferWithSize> buf =
9774 base::MakeRefCounted<IOBufferWithSize>(5);
9775 rv = context->trans->Read(buf.get(), buf->size(),
9776 context->callback.callback());
9777 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9778
9779 // Destroy the transaction.
9780 context.reset();
9781
9782 // Complete Read.
9783 base::RunLoop().RunUntilIdle();
9784
9785 // Verify that the entry has not been marked as truncated.
9786 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 0);
9787 RemoveMockTransaction(&kRangeGET_TransactionOK);
9788 }
9789
9790 // Tests that we don't delete a sparse entry when we start a new request after
9791 // cancelling the previous one.
TEST_F(HttpCacheTest,RangeGET_Cancel2)9792 TEST_F(HttpCacheTest, RangeGET_Cancel2) {
9793 MockHttpCache cache;
9794 AddMockTransaction(&kRangeGET_TransactionOK);
9795
9796 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9797 MockHttpRequest request(kRangeGET_TransactionOK);
9798 request.load_flags |= LOAD_VALIDATE_CACHE;
9799
9800 auto c = std::make_unique<Context>();
9801 int rv = cache.CreateTransaction(&c->trans);
9802 ASSERT_THAT(rv, IsOk());
9803
9804 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9805 if (rv == ERR_IO_PENDING)
9806 rv = c->callback.WaitForResult();
9807
9808 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9809 EXPECT_EQ(1, cache.disk_cache()->open_count());
9810 EXPECT_EQ(1, cache.disk_cache()->create_count());
9811
9812 // Make sure that we revalidate the entry and read from the cache (a single
9813 // read will return while waiting for the network).
9814 scoped_refptr<IOBufferWithSize> buf =
9815 base::MakeRefCounted<IOBufferWithSize>(5);
9816 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9817 EXPECT_EQ(5, c->callback.GetResult(rv));
9818 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9819 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9820
9821 // Destroy the transaction before completing the read.
9822 c.reset();
9823
9824 // We have the read and the delete (OnProcessPendingQueue) waiting on the
9825 // message loop. This means that a new transaction will just reuse the same
9826 // active entry (no open or create).
9827
9828 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9829
9830 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9831 EXPECT_EQ(1, cache.disk_cache()->open_count());
9832 EXPECT_EQ(1, cache.disk_cache()->create_count());
9833 RemoveMockTransaction(&kRangeGET_TransactionOK);
9834 }
9835
9836 // A slight variation of the previous test, this time we cancel two requests in
9837 // a row, making sure that the second is waiting for the entry to be ready.
TEST_F(HttpCacheTest,RangeGET_Cancel3)9838 TEST_F(HttpCacheTest, RangeGET_Cancel3) {
9839 MockHttpCache cache;
9840 AddMockTransaction(&kRangeGET_TransactionOK);
9841
9842 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9843 MockHttpRequest request(kRangeGET_TransactionOK);
9844 request.load_flags |= LOAD_VALIDATE_CACHE;
9845
9846 auto c = std::make_unique<Context>();
9847 int rv = cache.CreateTransaction(&c->trans);
9848 ASSERT_THAT(rv, IsOk());
9849
9850 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9851 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9852 rv = c->callback.WaitForResult();
9853
9854 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9855 EXPECT_EQ(1, cache.disk_cache()->open_count());
9856 EXPECT_EQ(1, cache.disk_cache()->create_count());
9857
9858 // Make sure that we revalidate the entry and read from the cache (a single
9859 // read will return while waiting for the network).
9860 scoped_refptr<IOBufferWithSize> buf =
9861 base::MakeRefCounted<IOBufferWithSize>(5);
9862 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9863 EXPECT_EQ(5, c->callback.GetResult(rv));
9864 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9865 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9866
9867 // Destroy the previous transaction before completing the read.
9868 c.reset();
9869
9870 // We have the read and the delete (OnProcessPendingQueue) waiting on the
9871 // message loop. This means that a new transaction will just reuse the same
9872 // active entry (no open or create).
9873
9874 c = std::make_unique<Context>();
9875 rv = cache.CreateTransaction(&c->trans);
9876 ASSERT_THAT(rv, IsOk());
9877
9878 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9879 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9880
9881 MockDiskEntry::IgnoreCallbacks(true);
9882 base::RunLoop().RunUntilIdle();
9883 MockDiskEntry::IgnoreCallbacks(false);
9884
9885 // The new transaction is waiting for the query range callback.
9886 c.reset();
9887
9888 // And we should not crash when the callback is delivered.
9889 base::RunLoop().RunUntilIdle();
9890
9891 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9892 EXPECT_EQ(1, cache.disk_cache()->open_count());
9893 EXPECT_EQ(1, cache.disk_cache()->create_count());
9894 RemoveMockTransaction(&kRangeGET_TransactionOK);
9895 }
9896
9897 // Tests that an invalid range response results in no cached entry.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse1)9898 TEST_F(HttpCacheTest, RangeGET_InvalidResponse1) {
9899 MockHttpCache cache;
9900 std::string headers;
9901
9902 MockTransaction transaction(kRangeGET_TransactionOK);
9903 transaction.handler = nullptr;
9904 transaction.response_headers = "Content-Range: bytes 40-49/45\n"
9905 "Content-Length: 10\n";
9906 AddMockTransaction(&transaction);
9907 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9908
9909 std::string expected(transaction.status);
9910 expected.append("\n");
9911 expected.append(transaction.response_headers);
9912 EXPECT_EQ(expected, headers);
9913
9914 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9915 EXPECT_EQ(0, cache.disk_cache()->open_count());
9916 EXPECT_EQ(1, cache.disk_cache()->create_count());
9917
9918 // Verify that we don't have a cached entry.
9919 disk_cache::Entry* entry;
9920 MockHttpRequest request(transaction);
9921 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9922
9923 RemoveMockTransaction(&kRangeGET_TransactionOK);
9924 }
9925
9926 // Tests that we reject a range that doesn't match the content-length.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse2)9927 TEST_F(HttpCacheTest, RangeGET_InvalidResponse2) {
9928 MockHttpCache cache;
9929 std::string headers;
9930
9931 MockTransaction transaction(kRangeGET_TransactionOK);
9932 transaction.handler = nullptr;
9933 transaction.response_headers = "Content-Range: bytes 40-49/80\n"
9934 "Content-Length: 20\n";
9935 AddMockTransaction(&transaction);
9936 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9937
9938 std::string expected(transaction.status);
9939 expected.append("\n");
9940 expected.append(transaction.response_headers);
9941 EXPECT_EQ(expected, headers);
9942
9943 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9944 EXPECT_EQ(0, cache.disk_cache()->open_count());
9945 EXPECT_EQ(1, cache.disk_cache()->create_count());
9946
9947 // Verify that we don't have a cached entry.
9948 disk_cache::Entry* entry;
9949 MockHttpRequest request(transaction);
9950 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9951
9952 RemoveMockTransaction(&kRangeGET_TransactionOK);
9953 }
9954
9955 // Tests that if a server tells us conflicting information about a resource we
9956 // drop the entry.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse3)9957 TEST_F(HttpCacheTest, RangeGET_InvalidResponse3) {
9958 MockHttpCache cache;
9959 std::string headers;
9960
9961 MockTransaction transaction(kRangeGET_TransactionOK);
9962 transaction.handler = nullptr;
9963 transaction.request_headers = "Range: bytes = 50-59\r\n" EXTRA_HEADER;
9964 std::string response_headers(transaction.response_headers);
9965 response_headers.append("Content-Range: bytes 50-59/160\n");
9966 transaction.response_headers = response_headers.c_str();
9967 AddMockTransaction(&transaction);
9968 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9969
9970 Verify206Response(headers, 50, 59);
9971 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9972 EXPECT_EQ(0, cache.disk_cache()->open_count());
9973 EXPECT_EQ(1, cache.disk_cache()->create_count());
9974
9975 RemoveMockTransaction(&transaction);
9976 AddMockTransaction(&kRangeGET_TransactionOK);
9977
9978 // This transaction will report a resource size of 80 bytes, and we think it's
9979 // 160 so we should ignore the response.
9980 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9981 &headers);
9982
9983 Verify206Response(headers, 40, 49);
9984 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9985 EXPECT_EQ(1, cache.disk_cache()->open_count());
9986 EXPECT_EQ(1, cache.disk_cache()->create_count());
9987
9988 // Verify that the entry is gone.
9989 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9990 EXPECT_EQ(1, cache.disk_cache()->open_count());
9991 EXPECT_EQ(2, cache.disk_cache()->create_count());
9992 RemoveMockTransaction(&kRangeGET_TransactionOK);
9993 }
9994
9995 // Tests that we handle large range values properly.
TEST_F(HttpCacheTest,RangeGET_LargeValues)9996 TEST_F(HttpCacheTest, RangeGET_LargeValues) {
9997 // We need a real sparse cache for this test.
9998 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
9999 std::string headers;
10000
10001 MockTransaction transaction(kRangeGET_TransactionOK);
10002 transaction.handler = nullptr;
10003 transaction.request_headers = "Range: bytes = 4294967288-4294967297\r\n"
10004 EXTRA_HEADER;
10005 transaction.response_headers =
10006 "ETag: \"foo\"\n"
10007 "Content-Range: bytes 4294967288-4294967297/4294967299\n"
10008 "Content-Length: 10\n";
10009 AddMockTransaction(&transaction);
10010 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10011
10012 std::string expected(transaction.status);
10013 expected.append("\n");
10014 expected.append(transaction.response_headers);
10015 EXPECT_EQ(expected, headers);
10016
10017 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10018
10019 // Verify that we have a cached entry.
10020 disk_cache::Entry* en;
10021 MockHttpRequest request(transaction);
10022 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &en));
10023 en->Close();
10024
10025 RemoveMockTransaction(&kRangeGET_TransactionOK);
10026 }
10027
10028 // Tests that we don't crash with a range request if the disk cache was not
10029 // initialized properly.
TEST_F(HttpCacheTest,RangeGET_NoDiskCache)10030 TEST_F(HttpCacheTest, RangeGET_NoDiskCache) {
10031 auto factory = std::make_unique<MockBlockingBackendFactory>();
10032 factory->set_fail(true);
10033 factory->FinishCreation(); // We'll complete synchronously.
10034 MockHttpCache cache(std::move(factory));
10035
10036 AddMockTransaction(&kRangeGET_TransactionOK);
10037
10038 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
10039 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10040
10041 RemoveMockTransaction(&kRangeGET_TransactionOK);
10042 }
10043
10044 // Tests that we handle byte range requests that skip the cache.
TEST_F(HttpCacheTest,RangeHEAD)10045 TEST_F(HttpCacheTest, RangeHEAD) {
10046 MockHttpCache cache;
10047 AddMockTransaction(&kRangeGET_TransactionOK);
10048
10049 MockTransaction transaction(kRangeGET_TransactionOK);
10050 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
10051 transaction.method = "HEAD";
10052 transaction.data = "rg: 70-79 ";
10053
10054 std::string headers;
10055 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10056
10057 Verify206Response(headers, 70, 79);
10058 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10059 EXPECT_EQ(0, cache.disk_cache()->open_count());
10060 EXPECT_EQ(0, cache.disk_cache()->create_count());
10061
10062 RemoveMockTransaction(&kRangeGET_TransactionOK);
10063 }
10064
10065 // Tests that we don't crash when after reading from the cache we issue a
10066 // request for the next range and the server gives us a 200 synchronously.
TEST_F(HttpCacheTest,RangeGET_FastFlakyServer)10067 TEST_F(HttpCacheTest, RangeGET_FastFlakyServer) {
10068 MockHttpCache cache;
10069
10070 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10071 transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER;
10072 transaction.test_mode = TEST_MODE_SYNC_NET_START;
10073 transaction.load_flags |= LOAD_VALIDATE_CACHE;
10074
10075 // Write to the cache.
10076 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
10077
10078 // And now read from the cache and the network.
10079 RangeTransactionServer handler;
10080 handler.set_bad_200(true);
10081 transaction.data = "Not a range";
10082 RecordingNetLogObserver net_log_observer;
10083 RunTransactionTestWithLog(cache.http_cache(), transaction,
10084 NetLogWithSource::Make(NetLogSourceType::NONE));
10085
10086 EXPECT_EQ(3, cache.network_layer()->transaction_count());
10087 EXPECT_EQ(1, cache.disk_cache()->open_count());
10088 EXPECT_EQ(1, cache.disk_cache()->create_count());
10089 EXPECT_TRUE(LogContainsEventType(
10090 net_log_observer, NetLogEventType::HTTP_CACHE_RE_SEND_PARTIAL_REQUEST));
10091 }
10092
10093 // Tests that when the server gives us less data than expected, we don't keep
10094 // asking for more data.
TEST_F(HttpCacheTest,RangeGET_FastFlakyServer2)10095 TEST_F(HttpCacheTest, RangeGET_FastFlakyServer2) {
10096 MockHttpCache cache;
10097
10098 // First, check with an empty cache (WRITE mode).
10099 MockTransaction transaction(kRangeGET_TransactionOK);
10100 transaction.request_headers = "Range: bytes = 40-49\r\n" EXTRA_HEADER;
10101 transaction.data = "rg: 40-"; // Less than expected.
10102 transaction.handler = nullptr;
10103 std::string headers(transaction.response_headers);
10104 headers.append("Content-Range: bytes 40-49/80\n");
10105 transaction.response_headers = headers.c_str();
10106
10107 AddMockTransaction(&transaction);
10108
10109 // Write to the cache.
10110 RunTransactionTest(cache.http_cache(), transaction);
10111
10112 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10113 EXPECT_EQ(0, cache.disk_cache()->open_count());
10114 EXPECT_EQ(1, cache.disk_cache()->create_count());
10115
10116 // Now verify that even in READ_WRITE mode, we forward the bad response to
10117 // the caller.
10118 transaction.request_headers = "Range: bytes = 60-69\r\n" EXTRA_HEADER;
10119 transaction.data = "rg: 60-"; // Less than expected.
10120 headers = kRangeGET_TransactionOK.response_headers;
10121 headers.append("Content-Range: bytes 60-69/80\n");
10122 transaction.response_headers = headers.c_str();
10123
10124 RunTransactionTest(cache.http_cache(), transaction);
10125
10126 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10127 EXPECT_EQ(1, cache.disk_cache()->open_count());
10128 EXPECT_EQ(1, cache.disk_cache()->create_count());
10129
10130 RemoveMockTransaction(&transaction);
10131 }
10132
TEST_F(HttpCacheTest,RangeGET_OK_LoadOnlyFromCache)10133 TEST_F(HttpCacheTest, RangeGET_OK_LoadOnlyFromCache) {
10134 MockHttpCache cache;
10135 AddMockTransaction(&kRangeGET_TransactionOK);
10136
10137 // Write to the cache (40-49).
10138 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
10139 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10140 EXPECT_EQ(0, cache.disk_cache()->open_count());
10141 EXPECT_EQ(1, cache.disk_cache()->create_count());
10142
10143 // Force this transaction to read from the cache.
10144 MockTransaction transaction(kRangeGET_TransactionOK);
10145 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
10146
10147 MockHttpRequest request(transaction);
10148 TestCompletionCallback callback;
10149
10150 std::unique_ptr<HttpTransaction> trans;
10151 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
10152 EXPECT_THAT(rv, IsOk());
10153 ASSERT_TRUE(trans.get());
10154
10155 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
10156 if (rv == ERR_IO_PENDING)
10157 rv = callback.WaitForResult();
10158 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
10159
10160 trans.reset();
10161
10162 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10163 EXPECT_EQ(1, cache.disk_cache()->open_count());
10164 EXPECT_EQ(1, cache.disk_cache()->create_count());
10165
10166 RemoveMockTransaction(&kRangeGET_TransactionOK);
10167 }
10168
10169 // Tests the handling of the "truncation" flag.
TEST_F(HttpCacheTest,WriteResponseInfo_Truncated)10170 TEST_F(HttpCacheTest, WriteResponseInfo_Truncated) {
10171 MockHttpCache cache;
10172 disk_cache::Entry* entry;
10173 ASSERT_TRUE(cache.CreateBackendEntry(
10174 GenerateCacheKey("http://www.google.com"), &entry, nullptr));
10175
10176 HttpResponseInfo response;
10177 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
10178 HttpUtil::AssembleRawHeaders("HTTP/1.1 200 OK"));
10179
10180 // Set the last argument for this to be an incomplete request.
10181 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
10182 bool truncated = false;
10183 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
10184 EXPECT_TRUE(truncated);
10185
10186 // And now test the opposite case.
10187 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
10188 truncated = true;
10189 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
10190 EXPECT_FALSE(truncated);
10191 entry->Close();
10192 }
10193
10194 // Tests basic pickling/unpickling of HttpResponseInfo.
TEST_F(HttpCacheTest,PersistHttpResponseInfo)10195 TEST_F(HttpCacheTest, PersistHttpResponseInfo) {
10196 const IPEndPoint expected_endpoint = IPEndPoint(IPAddress(1, 2, 3, 4), 80);
10197 // Set some fields (add more if needed.)
10198 HttpResponseInfo response1;
10199 response1.was_cached = false;
10200 response1.remote_endpoint = expected_endpoint;
10201 response1.headers =
10202 base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
10203
10204 // Pickle.
10205 base::Pickle pickle;
10206 response1.Persist(&pickle, false, false);
10207
10208 // Unpickle.
10209 HttpResponseInfo response2;
10210 bool response_truncated;
10211 EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated));
10212 EXPECT_FALSE(response_truncated);
10213
10214 // Verify fields.
10215 EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag.
10216 EXPECT_EQ(expected_endpoint, response2.remote_endpoint);
10217 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
10218 }
10219
10220 // Tests that we delete an entry when the request is cancelled before starting
10221 // to read from the network.
TEST_F(HttpCacheTest,DoomOnDestruction)10222 TEST_F(HttpCacheTest, DoomOnDestruction) {
10223 MockHttpCache cache;
10224
10225 MockHttpRequest request(kSimpleGET_Transaction);
10226
10227 auto c = std::make_unique<Context>();
10228 int rv = cache.CreateTransaction(&c->trans);
10229 ASSERT_THAT(rv, IsOk());
10230
10231 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10232 if (rv == ERR_IO_PENDING)
10233 c->result = c->callback.WaitForResult();
10234
10235 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10236 EXPECT_EQ(0, cache.disk_cache()->open_count());
10237 EXPECT_EQ(1, cache.disk_cache()->create_count());
10238
10239 // Destroy the transaction. We only have the headers so we should delete this
10240 // entry.
10241 c.reset();
10242
10243 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10244
10245 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10246 EXPECT_EQ(0, cache.disk_cache()->open_count());
10247 EXPECT_EQ(2, cache.disk_cache()->create_count());
10248 }
10249
10250 // Tests that we delete an entry when the request is cancelled if the response
10251 // does not have content-length and strong validators.
TEST_F(HttpCacheTest,DoomOnDestruction2)10252 TEST_F(HttpCacheTest, DoomOnDestruction2) {
10253 MockHttpCache cache;
10254
10255 MockHttpRequest request(kSimpleGET_Transaction);
10256
10257 auto c = std::make_unique<Context>();
10258 int rv = cache.CreateTransaction(&c->trans);
10259 ASSERT_THAT(rv, IsOk());
10260
10261 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10262 if (rv == ERR_IO_PENDING)
10263 rv = c->callback.WaitForResult();
10264
10265 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10266 EXPECT_EQ(0, cache.disk_cache()->open_count());
10267 EXPECT_EQ(1, cache.disk_cache()->create_count());
10268
10269 // Make sure that the entry has some data stored.
10270 scoped_refptr<IOBufferWithSize> buf =
10271 base::MakeRefCounted<IOBufferWithSize>(10);
10272 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10273 if (rv == ERR_IO_PENDING)
10274 rv = c->callback.WaitForResult();
10275 EXPECT_EQ(buf->size(), rv);
10276
10277 // Destroy the transaction.
10278 c.reset();
10279
10280 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10281
10282 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10283 EXPECT_EQ(0, cache.disk_cache()->open_count());
10284 EXPECT_EQ(2, cache.disk_cache()->create_count());
10285 }
10286
10287 // Tests that we delete an entry when the request is cancelled if the response
10288 // has an "Accept-Ranges: none" header.
TEST_F(HttpCacheTest,DoomOnDestruction3)10289 TEST_F(HttpCacheTest, DoomOnDestruction3) {
10290 MockHttpCache cache;
10291
10292 MockTransaction transaction(kSimpleGET_Transaction);
10293 transaction.response_headers =
10294 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10295 "Content-Length: 22\n"
10296 "Accept-Ranges: none\n"
10297 "Etag: \"foopy\"\n";
10298 AddMockTransaction(&transaction);
10299 MockHttpRequest request(transaction);
10300
10301 auto c = std::make_unique<Context>();
10302 int rv = cache.CreateTransaction(&c->trans);
10303 ASSERT_THAT(rv, IsOk());
10304
10305 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10306 if (rv == ERR_IO_PENDING)
10307 rv = c->callback.WaitForResult();
10308
10309 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10310 EXPECT_EQ(0, cache.disk_cache()->open_count());
10311 EXPECT_EQ(1, cache.disk_cache()->create_count());
10312
10313 // Make sure that the entry has some data stored.
10314 scoped_refptr<IOBufferWithSize> buf =
10315 base::MakeRefCounted<IOBufferWithSize>(10);
10316 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10317 if (rv == ERR_IO_PENDING)
10318 rv = c->callback.WaitForResult();
10319 EXPECT_EQ(buf->size(), rv);
10320
10321 // Destroy the transaction.
10322 c.reset();
10323
10324 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10325
10326 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10327 EXPECT_EQ(0, cache.disk_cache()->open_count());
10328 EXPECT_EQ(2, cache.disk_cache()->create_count());
10329
10330 RemoveMockTransaction(&transaction);
10331 }
10332
10333 // Tests that we mark an entry as incomplete when the request is cancelled.
TEST_F(HttpCacheTest,SetTruncatedFlag)10334 TEST_F(HttpCacheTest, SetTruncatedFlag) {
10335 MockHttpCache cache;
10336
10337 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10338 transaction.response_headers =
10339 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10340 "Content-Length: 22\n"
10341 "Etag: \"foopy\"\n";
10342 MockHttpRequest request(transaction);
10343
10344 auto c = std::make_unique<Context>();
10345
10346 int rv = cache.CreateTransaction(&c->trans);
10347 ASSERT_THAT(rv, IsOk());
10348
10349 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10350 if (rv == ERR_IO_PENDING)
10351 rv = c->callback.WaitForResult();
10352
10353 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10354 EXPECT_EQ(0, cache.disk_cache()->open_count());
10355 EXPECT_EQ(1, cache.disk_cache()->create_count());
10356
10357 // Make sure that the entry has some data stored.
10358 scoped_refptr<IOBufferWithSize> buf =
10359 base::MakeRefCounted<IOBufferWithSize>(10);
10360 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10361 if (rv == ERR_IO_PENDING)
10362 rv = c->callback.WaitForResult();
10363 EXPECT_EQ(buf->size(), rv);
10364
10365 // We want to cancel the request when the transaction is busy.
10366 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10367 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10368 EXPECT_FALSE(c->callback.have_result());
10369
10370 // Destroy the transaction.
10371 c->trans.reset();
10372
10373 // Make sure that we don't invoke the callback. We may have an issue if the
10374 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
10375 // could end up with the transaction being deleted twice if we send any
10376 // notification from the transaction destructor (see http://crbug.com/31723).
10377 EXPECT_FALSE(c->callback.have_result());
10378
10379 base::RunLoop().RunUntilIdle();
10380 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 0);
10381 }
10382
10383 // Tests that we do not mark an entry as truncated when the request is
10384 // cancelled.
TEST_F(HttpCacheTest,DontSetTruncatedFlagForGarbledResponseCode)10385 TEST_F(HttpCacheTest, DontSetTruncatedFlagForGarbledResponseCode) {
10386 MockHttpCache cache;
10387
10388 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10389 transaction.response_headers =
10390 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10391 "Content-Length: 22\n"
10392 "Etag: \"foopy\"\n";
10393 transaction.status = "HTTP/1.1 2";
10394 MockHttpRequest request(transaction);
10395
10396 auto c = std::make_unique<Context>();
10397
10398 int rv = cache.CreateTransaction(&c->trans);
10399 ASSERT_THAT(rv, IsOk());
10400
10401 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10402 if (rv == ERR_IO_PENDING)
10403 rv = c->callback.WaitForResult();
10404
10405 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10406 EXPECT_EQ(0, cache.disk_cache()->open_count());
10407 EXPECT_EQ(1, cache.disk_cache()->create_count());
10408
10409 // Make sure that the entry has some data stored.
10410 scoped_refptr<IOBufferWithSize> buf =
10411 base::MakeRefCounted<IOBufferWithSize>(10);
10412 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10413 if (rv == ERR_IO_PENDING)
10414 rv = c->callback.WaitForResult();
10415 EXPECT_EQ(buf->size(), rv);
10416
10417 // We want to cancel the request when the transaction is busy.
10418 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10419 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10420 EXPECT_FALSE(c->callback.have_result());
10421
10422 MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL);
10423
10424 // Destroy the transaction.
10425 c->trans.reset();
10426 MockHttpCache::SetTestMode(0);
10427
10428 // Make sure that we don't invoke the callback. We may have an issue if the
10429 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
10430 // could end up with the transaction being deleted twice if we send any
10431 // notification from the transaction destructor (see http://crbug.com/31723).
10432 EXPECT_FALSE(c->callback.have_result());
10433
10434 // Verify that the entry is deleted as well, since the response status is
10435 // garbled. Note that the entry will be deleted after the pending Read is
10436 // complete.
10437 base::RunLoop().RunUntilIdle();
10438 disk_cache::Entry* entry;
10439 ASSERT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10440 }
10441
10442 // Tests that we don't mark an entry as truncated when we read everything.
TEST_F(HttpCacheTest,DontSetTruncatedFlag)10443 TEST_F(HttpCacheTest, DontSetTruncatedFlag) {
10444 MockHttpCache cache;
10445
10446 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10447 transaction.response_headers =
10448 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10449 "Content-Length: 22\n"
10450 "Etag: \"foopy\"\n";
10451 MockHttpRequest request(transaction);
10452
10453 auto c = std::make_unique<Context>();
10454 int rv = cache.CreateTransaction(&c->trans);
10455 ASSERT_THAT(rv, IsOk());
10456
10457 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10458 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10459
10460 // Read everything.
10461 scoped_refptr<IOBufferWithSize> buf =
10462 base::MakeRefCounted<IOBufferWithSize>(22);
10463 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10464 EXPECT_EQ(buf->size(), c->callback.GetResult(rv));
10465
10466 // Destroy the transaction.
10467 c->trans.reset();
10468
10469 // Verify that the entry is not marked as truncated.
10470 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 0);
10471 }
10472
10473 // Tests that sparse entries don't set the truncate flag.
TEST_F(HttpCacheTest,RangeGET_DontTruncate)10474 TEST_F(HttpCacheTest, RangeGET_DontTruncate) {
10475 MockHttpCache cache;
10476
10477 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10478 transaction.request_headers = "Range: bytes = 0-19\r\n" EXTRA_HEADER;
10479
10480 auto request = std::make_unique<MockHttpRequest>(transaction);
10481 std::unique_ptr<HttpTransaction> trans;
10482
10483 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
10484 EXPECT_THAT(rv, IsOk());
10485
10486 TestCompletionCallback cb;
10487 rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
10488 EXPECT_EQ(0, cb.GetResult(rv));
10489
10490 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(10);
10491 rv = trans->Read(buf.get(), 10, cb.callback());
10492 EXPECT_EQ(10, cb.GetResult(rv));
10493
10494 // Should not trigger any DCHECK.
10495 trans.reset();
10496 VerifyTruncatedFlag(&cache, request->CacheKey(), false, 0);
10497 }
10498
10499 // Tests that sparse entries don't set the truncate flag (when the byte range
10500 // starts after 0).
TEST_F(HttpCacheTest,RangeGET_DontTruncate2)10501 TEST_F(HttpCacheTest, RangeGET_DontTruncate2) {
10502 MockHttpCache cache;
10503
10504 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10505 transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
10506
10507 auto request = std::make_unique<MockHttpRequest>(transaction);
10508 std::unique_ptr<HttpTransaction> trans;
10509
10510 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
10511 EXPECT_THAT(rv, IsOk());
10512
10513 TestCompletionCallback cb;
10514 rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
10515 EXPECT_EQ(0, cb.GetResult(rv));
10516
10517 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(10);
10518 rv = trans->Read(buf.get(), 10, cb.callback());
10519 EXPECT_EQ(10, cb.GetResult(rv));
10520
10521 // Should not trigger any DCHECK.
10522 trans.reset();
10523 VerifyTruncatedFlag(&cache, request->CacheKey(), false, 0);
10524 }
10525
10526 // Tests that we can continue with a request that was interrupted.
TEST_F(HttpCacheTest,GET_IncompleteResource)10527 TEST_F(HttpCacheTest, GET_IncompleteResource) {
10528 MockHttpCache cache;
10529 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10530
10531 std::string raw_headers("HTTP/1.1 200 OK\n"
10532 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10533 "ETag: \"foo\"\n"
10534 "Accept-Ranges: bytes\n"
10535 "Content-Length: 80\n");
10536 CreateTruncatedEntry(raw_headers, &cache);
10537
10538 // Now make a regular request.
10539 std::string headers;
10540 transaction.request_headers = EXTRA_HEADER;
10541 transaction.data = kFullRangeData;
10542 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10543
10544 // We update the headers with the ones received while revalidating.
10545 std::string expected_headers(
10546 "HTTP/1.1 200 OK\n"
10547 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10548 "Accept-Ranges: bytes\n"
10549 "ETag: \"foo\"\n"
10550 "Content-Length: 80\n");
10551
10552 EXPECT_EQ(expected_headers, headers);
10553 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10554 EXPECT_EQ(1, cache.disk_cache()->open_count());
10555 EXPECT_EQ(1, cache.disk_cache()->create_count());
10556
10557 // Verify that the disk entry was updated.
10558 MockHttpRequest request(transaction);
10559 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 80);
10560 }
10561
10562 // Tests the handling of no-store when revalidating a truncated entry.
TEST_F(HttpCacheTest,GET_IncompleteResource_NoStore)10563 TEST_F(HttpCacheTest, GET_IncompleteResource_NoStore) {
10564 MockHttpCache cache;
10565 AddMockTransaction(&kRangeGET_TransactionOK);
10566
10567 std::string raw_headers("HTTP/1.1 200 OK\n"
10568 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10569 "ETag: \"foo\"\n"
10570 "Accept-Ranges: bytes\n"
10571 "Content-Length: 80\n");
10572 CreateTruncatedEntry(raw_headers, &cache);
10573 RemoveMockTransaction(&kRangeGET_TransactionOK);
10574
10575 // Now make a regular request.
10576 MockTransaction transaction(kRangeGET_TransactionOK);
10577 transaction.request_headers = EXTRA_HEADER;
10578 std::string response_headers(transaction.response_headers);
10579 response_headers += ("Cache-Control: no-store\n");
10580 transaction.response_headers = response_headers.c_str();
10581 transaction.data = kFullRangeData;
10582 AddMockTransaction(&transaction);
10583
10584 std::string headers;
10585 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10586
10587 // We update the headers with the ones received while revalidating.
10588 std::string expected_headers(
10589 "HTTP/1.1 200 OK\n"
10590 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10591 "Accept-Ranges: bytes\n"
10592 "Cache-Control: no-store\n"
10593 "ETag: \"foo\"\n"
10594 "Content-Length: 80\n");
10595
10596 EXPECT_EQ(expected_headers, headers);
10597 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10598 EXPECT_EQ(1, cache.disk_cache()->open_count());
10599 EXPECT_EQ(1, cache.disk_cache()->create_count());
10600
10601 // Verify that the disk entry was deleted.
10602 disk_cache::Entry* entry;
10603 MockHttpRequest request(transaction);
10604 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10605 RemoveMockTransaction(&transaction);
10606 }
10607
10608 // Tests cancelling a request after the server sent no-store.
TEST_F(HttpCacheTest,GET_IncompleteResource_Cancel)10609 TEST_F(HttpCacheTest, GET_IncompleteResource_Cancel) {
10610 MockHttpCache cache;
10611 AddMockTransaction(&kRangeGET_TransactionOK);
10612
10613 std::string raw_headers("HTTP/1.1 200 OK\n"
10614 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10615 "ETag: \"foo\"\n"
10616 "Accept-Ranges: bytes\n"
10617 "Content-Length: 80\n");
10618 CreateTruncatedEntry(raw_headers, &cache);
10619 RemoveMockTransaction(&kRangeGET_TransactionOK);
10620
10621 // Now make a regular request.
10622 MockTransaction transaction(kRangeGET_TransactionOK);
10623 transaction.request_headers = EXTRA_HEADER;
10624 std::string response_headers(transaction.response_headers);
10625 response_headers += ("Cache-Control: no-store\n");
10626 transaction.response_headers = response_headers.c_str();
10627 transaction.data = kFullRangeData;
10628 AddMockTransaction(&transaction);
10629
10630 MockHttpRequest request(transaction);
10631 auto c = std::make_unique<Context>();
10632
10633 int rv = cache.CreateTransaction(&c->trans);
10634 ASSERT_THAT(rv, IsOk());
10635
10636 // Queue another request to this transaction. We have to start this request
10637 // before the first one gets the response from the server and dooms the entry,
10638 // otherwise it will just create a new entry without being queued to the first
10639 // request.
10640 auto pending = std::make_unique<Context>();
10641 ASSERT_THAT(cache.CreateTransaction(&pending->trans), IsOk());
10642
10643 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10644 EXPECT_EQ(ERR_IO_PENDING,
10645 pending->trans->Start(&request, pending->callback.callback(),
10646 NetLogWithSource()));
10647 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10648
10649 // Make sure that the entry has some data stored.
10650 scoped_refptr<IOBufferWithSize> buf =
10651 base::MakeRefCounted<IOBufferWithSize>(5);
10652 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10653 EXPECT_EQ(5, c->callback.GetResult(rv));
10654
10655 // Since |pending| is currently validating the already written headers
10656 // it will be restarted as well.
10657 c.reset();
10658 pending.reset();
10659
10660 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10661 EXPECT_EQ(1, cache.disk_cache()->open_count());
10662 EXPECT_EQ(1, cache.disk_cache()->create_count());
10663
10664 base::RunLoop().RunUntilIdle();
10665 RemoveMockTransaction(&transaction);
10666 }
10667
10668 // Tests that we delete truncated entries if the server changes its mind midway.
TEST_F(HttpCacheTest,GET_IncompleteResource2)10669 TEST_F(HttpCacheTest, GET_IncompleteResource2) {
10670 MockHttpCache cache;
10671 AddMockTransaction(&kRangeGET_TransactionOK);
10672
10673 // Content-length will be intentionally bad.
10674 std::string raw_headers("HTTP/1.1 200 OK\n"
10675 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10676 "ETag: \"foo\"\n"
10677 "Accept-Ranges: bytes\n"
10678 "Content-Length: 50\n");
10679 CreateTruncatedEntry(raw_headers, &cache);
10680
10681 // Now make a regular request. We expect the code to fail the validation and
10682 // retry the request without using byte ranges.
10683 std::string headers;
10684 MockTransaction transaction(kRangeGET_TransactionOK);
10685 transaction.request_headers = EXTRA_HEADER;
10686 transaction.data = "Not a range";
10687 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10688
10689 // The server will return 200 instead of a byte range.
10690 std::string expected_headers(
10691 "HTTP/1.1 200 OK\n"
10692 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
10693
10694 EXPECT_EQ(expected_headers, headers);
10695 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10696 EXPECT_EQ(1, cache.disk_cache()->open_count());
10697 EXPECT_EQ(1, cache.disk_cache()->create_count());
10698
10699 // Verify that the disk entry was deleted.
10700 disk_cache::Entry* entry;
10701 MockHttpRequest request(transaction);
10702 ASSERT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10703 RemoveMockTransaction(&kRangeGET_TransactionOK);
10704 }
10705
10706 // Tests that we always validate a truncated request.
TEST_F(HttpCacheTest,GET_IncompleteResource3)10707 TEST_F(HttpCacheTest, GET_IncompleteResource3) {
10708 MockHttpCache cache;
10709 AddMockTransaction(&kRangeGET_TransactionOK);
10710
10711 // This should not require validation for 10 hours.
10712 std::string raw_headers("HTTP/1.1 200 OK\n"
10713 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10714 "ETag: \"foo\"\n"
10715 "Cache-Control: max-age= 36000\n"
10716 "Accept-Ranges: bytes\n"
10717 "Content-Length: 80\n");
10718 CreateTruncatedEntry(raw_headers, &cache);
10719
10720 // Now make a regular request.
10721 std::string headers;
10722 MockTransaction transaction(kRangeGET_TransactionOK);
10723 transaction.request_headers = EXTRA_HEADER;
10724 transaction.data = kFullRangeData;
10725
10726 auto c = std::make_unique<Context>();
10727 int rv = cache.CreateTransaction(&c->trans);
10728 ASSERT_THAT(rv, IsOk());
10729
10730 MockHttpRequest request(transaction);
10731 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10732 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10733
10734 // We should have checked with the server before finishing Start().
10735 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10736 EXPECT_EQ(1, cache.disk_cache()->open_count());
10737 EXPECT_EQ(1, cache.disk_cache()->create_count());
10738
10739 RemoveMockTransaction(&kRangeGET_TransactionOK);
10740 }
10741
10742 // Tests that we handle 401s for truncated resources.
TEST_F(HttpCacheTest,GET_IncompleteResourceWithAuth)10743 TEST_F(HttpCacheTest, GET_IncompleteResourceWithAuth) {
10744 MockHttpCache cache;
10745 AddMockTransaction(&kRangeGET_TransactionOK);
10746
10747 std::string raw_headers("HTTP/1.1 200 OK\n"
10748 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10749 "ETag: \"foo\"\n"
10750 "Accept-Ranges: bytes\n"
10751 "Content-Length: 80\n");
10752 CreateTruncatedEntry(raw_headers, &cache);
10753
10754 // Now make a regular request.
10755 MockTransaction transaction(kRangeGET_TransactionOK);
10756 transaction.request_headers = "X-Require-Mock-Auth: dummy\r\n"
10757 EXTRA_HEADER;
10758 transaction.data = kFullRangeData;
10759 RangeTransactionServer handler;
10760
10761 auto c = std::make_unique<Context>();
10762 int rv = cache.CreateTransaction(&c->trans);
10763 ASSERT_THAT(rv, IsOk());
10764
10765 MockHttpRequest request(transaction);
10766 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10767 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10768
10769 const HttpResponseInfo* response = c->trans->GetResponseInfo();
10770 ASSERT_TRUE(response);
10771 ASSERT_EQ(401, response->headers->response_code());
10772 rv = c->trans->RestartWithAuth(AuthCredentials(), c->callback.callback());
10773 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10774 response = c->trans->GetResponseInfo();
10775 ASSERT_TRUE(response);
10776 ASSERT_EQ(200, response->headers->response_code());
10777
10778 ReadAndVerifyTransaction(c->trans.get(), transaction);
10779 c.reset(); // The destructor could delete the entry.
10780 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10781
10782 // Verify that the entry was deleted.
10783 disk_cache::Entry* entry;
10784 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10785 entry->Close();
10786
10787 RemoveMockTransaction(&kRangeGET_TransactionOK);
10788 }
10789
10790 // Test that the transaction won't retry failed partial requests
10791 // after it starts reading data. http://crbug.com/474835
TEST_F(HttpCacheTest,TransactionRetryLimit)10792 TEST_F(HttpCacheTest, TransactionRetryLimit) {
10793 MockHttpCache cache;
10794
10795 // Cache 0-9, so that we have data to read before failing.
10796 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10797 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
10798 transaction.data = "rg: 00-09 ";
10799
10800 // Write to the cache.
10801 RunTransactionTest(cache.http_cache(), transaction);
10802 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10803
10804 // And now read from the cache and the network. 10-19 will get a
10805 // 401, but will have already returned 0-9.
10806 // We do not set X-Require-Mock-Auth because that causes the mock
10807 // network transaction to become IsReadyToRestartForAuth().
10808 transaction.request_headers =
10809 "Range: bytes = 0-79\r\n"
10810 "X-Require-Mock-Auth-Alt: dummy\r\n" EXTRA_HEADER;
10811
10812 auto c = std::make_unique<Context>();
10813 int rv = cache.CreateTransaction(&c->trans);
10814 ASSERT_THAT(rv, IsOk());
10815
10816 MockHttpRequest request(transaction);
10817
10818 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10819 if (rv == ERR_IO_PENDING)
10820 rv = c->callback.WaitForResult();
10821 std::string content;
10822 rv = ReadTransaction(c->trans.get(), &content);
10823 EXPECT_THAT(rv, IsError(ERR_CACHE_AUTH_FAILURE_AFTER_READ));
10824 }
10825
10826 // Tests that we cache a 200 response to the validation request.
TEST_F(HttpCacheTest,GET_IncompleteResource4)10827 TEST_F(HttpCacheTest, GET_IncompleteResource4) {
10828 MockHttpCache cache;
10829 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10830
10831 std::string raw_headers("HTTP/1.1 200 OK\n"
10832 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10833 "ETag: \"foo\"\n"
10834 "Accept-Ranges: bytes\n"
10835 "Content-Length: 80\n");
10836 CreateTruncatedEntry(raw_headers, &cache);
10837
10838 // Now make a regular request.
10839 std::string headers;
10840 transaction.request_headers = EXTRA_HEADER;
10841 transaction.data = "Not a range";
10842 RangeTransactionServer handler;
10843 handler.set_bad_200(true);
10844 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10845
10846 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10847 EXPECT_EQ(1, cache.disk_cache()->open_count());
10848 EXPECT_EQ(1, cache.disk_cache()->create_count());
10849
10850 // Verify that the disk entry was updated.
10851 MockHttpRequest request(transaction);
10852 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 11);
10853 }
10854
10855 // Tests that when we cancel a request that was interrupted, we mark it again
10856 // as truncated.
TEST_F(HttpCacheTest,GET_CancelIncompleteResource)10857 TEST_F(HttpCacheTest, GET_CancelIncompleteResource) {
10858 MockHttpCache cache;
10859 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10860
10861 std::string raw_headers("HTTP/1.1 200 OK\n"
10862 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10863 "ETag: \"foo\"\n"
10864 "Accept-Ranges: bytes\n"
10865 "Content-Length: 80\n");
10866 CreateTruncatedEntry(raw_headers, &cache);
10867
10868 // Now make a regular request.
10869 transaction.request_headers = EXTRA_HEADER;
10870
10871 MockHttpRequest request(transaction);
10872 auto c = std::make_unique<Context>();
10873 int rv = cache.CreateTransaction(&c->trans);
10874 ASSERT_THAT(rv, IsOk());
10875
10876 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10877 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10878
10879 // Read 20 bytes from the cache, and 10 from the net.
10880 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(100);
10881 rv = c->trans->Read(buf.get(), 20, c->callback.callback());
10882 EXPECT_EQ(20, c->callback.GetResult(rv));
10883 rv = c->trans->Read(buf.get(), 10, c->callback.callback());
10884 EXPECT_EQ(10, c->callback.GetResult(rv));
10885
10886 // At this point, we are already reading so canceling the request should leave
10887 // a truncated one.
10888 c.reset();
10889
10890 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10891 EXPECT_EQ(1, cache.disk_cache()->open_count());
10892 EXPECT_EQ(1, cache.disk_cache()->create_count());
10893
10894 // Verify that the disk entry was updated: now we have 30 bytes.
10895 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 30);
10896 }
10897
10898 // Tests that we can handle range requests when we have a truncated entry.
TEST_F(HttpCacheTest,RangeGET_IncompleteResource)10899 TEST_F(HttpCacheTest, RangeGET_IncompleteResource) {
10900 MockHttpCache cache;
10901 AddMockTransaction(&kRangeGET_TransactionOK);
10902
10903 // Content-length will be intentionally bogus.
10904 std::string raw_headers("HTTP/1.1 200 OK\n"
10905 "Last-Modified: something\n"
10906 "ETag: \"foo\"\n"
10907 "Accept-Ranges: bytes\n"
10908 "Content-Length: 10\n");
10909 CreateTruncatedEntry(raw_headers, &cache);
10910
10911 // Now make a range request.
10912 std::string headers;
10913 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
10914 &headers);
10915
10916 Verify206Response(headers, 40, 49);
10917 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10918 EXPECT_EQ(1, cache.disk_cache()->open_count());
10919 EXPECT_EQ(2, cache.disk_cache()->create_count());
10920
10921 RemoveMockTransaction(&kRangeGET_TransactionOK);
10922 }
10923
TEST_F(HttpCacheTest,SyncRead)10924 TEST_F(HttpCacheTest, SyncRead) {
10925 MockHttpCache cache;
10926
10927 // This test ensures that a read that completes synchronously does not cause
10928 // any problems.
10929
10930 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10931 transaction.test_mode |= (TEST_MODE_SYNC_CACHE_START |
10932 TEST_MODE_SYNC_CACHE_READ |
10933 TEST_MODE_SYNC_CACHE_WRITE);
10934
10935 MockHttpRequest r1(transaction),
10936 r2(transaction),
10937 r3(transaction);
10938
10939 TestTransactionConsumer c1(DEFAULT_PRIORITY, cache.http_cache()),
10940 c2(DEFAULT_PRIORITY, cache.http_cache()),
10941 c3(DEFAULT_PRIORITY, cache.http_cache());
10942
10943 c1.Start(&r1, NetLogWithSource());
10944
10945 r2.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
10946 c2.Start(&r2, NetLogWithSource());
10947
10948 r3.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
10949 c3.Start(&r3, NetLogWithSource());
10950
10951 base::RunLoop().Run();
10952
10953 EXPECT_TRUE(c1.is_done());
10954 EXPECT_TRUE(c2.is_done());
10955 EXPECT_TRUE(c3.is_done());
10956
10957 EXPECT_THAT(c1.error(), IsOk());
10958 EXPECT_THAT(c2.error(), IsOk());
10959 EXPECT_THAT(c3.error(), IsOk());
10960 }
10961
TEST_F(HttpCacheTest,ValidationResultsIn200)10962 TEST_F(HttpCacheTest, ValidationResultsIn200) {
10963 MockHttpCache cache;
10964
10965 // This test ensures that a conditional request, which results in a 200
10966 // instead of a 304, properly truncates the existing response data.
10967
10968 // write to the cache
10969 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
10970
10971 // force this transaction to validate the cache
10972 MockTransaction transaction(kETagGET_Transaction);
10973 transaction.load_flags |= LOAD_VALIDATE_CACHE;
10974 RunTransactionTest(cache.http_cache(), transaction);
10975
10976 // read from the cache
10977 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
10978 }
10979
TEST_F(HttpCacheTest,CachedRedirect)10980 TEST_F(HttpCacheTest, CachedRedirect) {
10981 MockHttpCache cache;
10982
10983 ScopedMockTransaction kTestTransaction(kSimpleGET_Transaction);
10984 kTestTransaction.status = "HTTP/1.1 301 Moved Permanently";
10985 kTestTransaction.response_headers = "Location: http://www.bar.com/\n";
10986
10987 MockHttpRequest request(kTestTransaction);
10988 TestCompletionCallback callback;
10989
10990 // Write to the cache.
10991 {
10992 std::unique_ptr<HttpTransaction> trans;
10993 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
10994
10995 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
10996 if (rv == ERR_IO_PENDING)
10997 rv = callback.WaitForResult();
10998 ASSERT_THAT(rv, IsOk());
10999
11000 const HttpResponseInfo* info = trans->GetResponseInfo();
11001 ASSERT_TRUE(info);
11002
11003 EXPECT_EQ(info->headers->response_code(), 301);
11004
11005 std::string location;
11006 info->headers->EnumerateHeader(nullptr, "Location", &location);
11007 EXPECT_EQ(location, "http://www.bar.com/");
11008
11009 // Mark the transaction as completed so it is cached.
11010 trans->DoneReading();
11011
11012 // Destroy transaction when going out of scope. We have not actually
11013 // read the response body -- want to test that it is still getting cached.
11014 }
11015 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11016 EXPECT_EQ(0, cache.disk_cache()->open_count());
11017 EXPECT_EQ(1, cache.disk_cache()->create_count());
11018
11019 // Active entries in the cache are not retired synchronously. Make
11020 // sure the next run hits the MockHttpCache and open_count is
11021 // correct.
11022 base::RunLoop().RunUntilIdle();
11023
11024 // Read from the cache.
11025 {
11026 std::unique_ptr<HttpTransaction> trans;
11027 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11028
11029 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11030 if (rv == ERR_IO_PENDING)
11031 rv = callback.WaitForResult();
11032 ASSERT_THAT(rv, IsOk());
11033
11034 const HttpResponseInfo* info = trans->GetResponseInfo();
11035 ASSERT_TRUE(info);
11036
11037 EXPECT_EQ(info->headers->response_code(), 301);
11038
11039 std::string location;
11040 info->headers->EnumerateHeader(nullptr, "Location", &location);
11041 EXPECT_EQ(location, "http://www.bar.com/");
11042
11043 // Mark the transaction as completed so it is cached.
11044 trans->DoneReading();
11045
11046 // Destroy transaction when going out of scope. We have not actually
11047 // read the response body -- want to test that it is still getting cached.
11048 }
11049 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11050 EXPECT_EQ(1, cache.disk_cache()->open_count());
11051 EXPECT_EQ(1, cache.disk_cache()->create_count());
11052 }
11053
11054 // Verify that no-cache resources are stored in cache, but are not fetched from
11055 // cache during normal loads.
TEST_F(HttpCacheTest,CacheControlNoCacheNormalLoad)11056 TEST_F(HttpCacheTest, CacheControlNoCacheNormalLoad) {
11057 for (bool use_memory_entry_data : {false, true}) {
11058 MockHttpCache cache;
11059 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
11060
11061 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11062 transaction.response_headers = "cache-control: no-cache\n";
11063
11064 // Initial load.
11065 RunTransactionTest(cache.http_cache(), transaction);
11066
11067 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11068 EXPECT_EQ(0, cache.disk_cache()->open_count());
11069 EXPECT_EQ(1, cache.disk_cache()->create_count());
11070
11071 // Try loading again; it should result in a network fetch.
11072 RunTransactionTest(cache.http_cache(), transaction);
11073
11074 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11075 if (use_memory_entry_data) {
11076 EXPECT_EQ(0, cache.disk_cache()->open_count());
11077 EXPECT_EQ(2, cache.disk_cache()->create_count());
11078 } else {
11079 EXPECT_EQ(1, cache.disk_cache()->open_count());
11080 EXPECT_EQ(1, cache.disk_cache()->create_count());
11081 }
11082
11083 disk_cache::Entry* entry;
11084 MockHttpRequest request(transaction);
11085 EXPECT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11086 entry->Close();
11087 }
11088 }
11089
11090 // Verify that no-cache resources are stored in cache and fetched from cache
11091 // when the LOAD_SKIP_CACHE_VALIDATION flag is set.
TEST_F(HttpCacheTest,CacheControlNoCacheHistoryLoad)11092 TEST_F(HttpCacheTest, CacheControlNoCacheHistoryLoad) {
11093 MockHttpCache cache;
11094
11095 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11096 transaction.response_headers = "cache-control: no-cache\n";
11097
11098 // Initial load.
11099 RunTransactionTest(cache.http_cache(), transaction);
11100
11101 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11102 EXPECT_EQ(0, cache.disk_cache()->open_count());
11103 EXPECT_EQ(1, cache.disk_cache()->create_count());
11104
11105 // Try loading again with LOAD_SKIP_CACHE_VALIDATION.
11106 transaction.load_flags = LOAD_SKIP_CACHE_VALIDATION;
11107 RunTransactionTest(cache.http_cache(), transaction);
11108
11109 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11110 EXPECT_EQ(1, cache.disk_cache()->open_count());
11111 EXPECT_EQ(1, cache.disk_cache()->create_count());
11112
11113 disk_cache::Entry* entry;
11114 MockHttpRequest request(transaction);
11115 EXPECT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11116 entry->Close();
11117 }
11118
TEST_F(HttpCacheTest,CacheControlNoStore)11119 TEST_F(HttpCacheTest, CacheControlNoStore) {
11120 MockHttpCache cache;
11121
11122 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11123 transaction.response_headers = "cache-control: no-store\n";
11124
11125 // initial load
11126 RunTransactionTest(cache.http_cache(), transaction);
11127
11128 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11129 EXPECT_EQ(0, cache.disk_cache()->open_count());
11130 EXPECT_EQ(1, cache.disk_cache()->create_count());
11131
11132 // try loading again; it should result in a network fetch
11133 RunTransactionTest(cache.http_cache(), transaction);
11134
11135 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11136 EXPECT_EQ(0, cache.disk_cache()->open_count());
11137 EXPECT_EQ(2, cache.disk_cache()->create_count());
11138
11139 disk_cache::Entry* entry;
11140 MockHttpRequest request(transaction);
11141 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11142 }
11143
TEST_F(HttpCacheTest,CacheControlNoStore2)11144 TEST_F(HttpCacheTest, CacheControlNoStore2) {
11145 // this test is similar to the above test, except that the initial response
11146 // is cachable, but when it is validated, no-store is received causing the
11147 // cached document to be deleted.
11148 MockHttpCache cache;
11149
11150 ScopedMockTransaction transaction(kETagGET_Transaction);
11151
11152 // initial load
11153 RunTransactionTest(cache.http_cache(), transaction);
11154
11155 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11156 EXPECT_EQ(0, cache.disk_cache()->open_count());
11157 EXPECT_EQ(1, cache.disk_cache()->create_count());
11158
11159 // try loading again; it should result in a network fetch
11160 transaction.load_flags = LOAD_VALIDATE_CACHE;
11161 transaction.response_headers = "cache-control: no-store\n";
11162 RunTransactionTest(cache.http_cache(), transaction);
11163
11164 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11165 EXPECT_EQ(1, cache.disk_cache()->open_count());
11166 EXPECT_EQ(1, cache.disk_cache()->create_count());
11167
11168 disk_cache::Entry* entry;
11169 MockHttpRequest request(transaction);
11170 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11171 }
11172
TEST_F(HttpCacheTest,CacheControlNoStore3)11173 TEST_F(HttpCacheTest, CacheControlNoStore3) {
11174 // this test is similar to the above test, except that the response is a 304
11175 // instead of a 200. this should never happen in practice, but it seems like
11176 // a good thing to verify that we still destroy the cache entry.
11177 MockHttpCache cache;
11178
11179 ScopedMockTransaction transaction(kETagGET_Transaction);
11180
11181 // initial load
11182 RunTransactionTest(cache.http_cache(), transaction);
11183
11184 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11185 EXPECT_EQ(0, cache.disk_cache()->open_count());
11186 EXPECT_EQ(1, cache.disk_cache()->create_count());
11187
11188 // try loading again; it should result in a network fetch
11189 transaction.load_flags = LOAD_VALIDATE_CACHE;
11190 transaction.response_headers = "cache-control: no-store\n";
11191 transaction.status = "HTTP/1.1 304 Not Modified";
11192 RunTransactionTest(cache.http_cache(), transaction);
11193
11194 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11195 EXPECT_EQ(1, cache.disk_cache()->open_count());
11196 EXPECT_EQ(1, cache.disk_cache()->create_count());
11197
11198 disk_cache::Entry* entry;
11199 MockHttpRequest request(transaction);
11200 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11201 }
11202
11203 // Ensure that we don't cache requests served over bad HTTPS.
TEST_F(HttpCacheTest,SimpleGET_SSLError)11204 TEST_F(HttpCacheTest, SimpleGET_SSLError) {
11205 MockHttpCache cache;
11206
11207 MockTransaction transaction = kSimpleGET_Transaction;
11208 transaction.cert_status = CERT_STATUS_REVOKED;
11209 ScopedMockTransaction scoped_transaction(transaction);
11210
11211 // write to the cache
11212 RunTransactionTest(cache.http_cache(), transaction);
11213
11214 // Test that it was not cached.
11215 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
11216
11217 MockHttpRequest request(transaction);
11218 TestCompletionCallback callback;
11219
11220 std::unique_ptr<HttpTransaction> trans;
11221 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11222
11223 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11224 if (rv == ERR_IO_PENDING)
11225 rv = callback.WaitForResult();
11226 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
11227 }
11228
11229 // Ensure that we don't crash by if left-behind transactions.
TEST_F(HttpCacheTest,OutlivedTransactions)11230 TEST_F(HttpCacheTest, OutlivedTransactions) {
11231 auto cache = std::make_unique<MockHttpCache>();
11232
11233 std::unique_ptr<HttpTransaction> trans;
11234 EXPECT_THAT(cache->CreateTransaction(&trans), IsOk());
11235
11236 cache.reset();
11237 trans.reset();
11238 }
11239
11240 // Test that the disabled mode works.
TEST_F(HttpCacheTest,CacheDisabledMode)11241 TEST_F(HttpCacheTest, CacheDisabledMode) {
11242 MockHttpCache cache;
11243
11244 // write to the cache
11245 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11246
11247 // go into disabled mode
11248 cache.http_cache()->set_mode(HttpCache::DISABLE);
11249
11250 // force this transaction to write to the cache again
11251 MockTransaction transaction(kSimpleGET_Transaction);
11252
11253 RunTransactionTest(cache.http_cache(), transaction);
11254
11255 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11256 EXPECT_EQ(0, cache.disk_cache()->open_count());
11257 EXPECT_EQ(1, cache.disk_cache()->create_count());
11258 }
11259
11260 // Other tests check that the response headers of the cached response
11261 // get updated on 304. Here we specifically check that the
11262 // HttpResponseHeaders::request_time and HttpResponseHeaders::response_time
11263 // fields also gets updated.
11264 // http://crbug.com/20594.
TEST_F(HttpCacheTest,UpdatesRequestResponseTimeOn304)11265 TEST_F(HttpCacheTest, UpdatesRequestResponseTimeOn304) {
11266 MockHttpCache cache;
11267
11268 const char kUrl[] = "http://foobar";
11269 const char kData[] = "body";
11270
11271 MockTransaction mock_network_response = {nullptr};
11272 mock_network_response.url = kUrl;
11273
11274 AddMockTransaction(&mock_network_response);
11275
11276 // Request |kUrl|, causing |kNetResponse1| to be written to the cache.
11277
11278 MockTransaction request = {nullptr};
11279 request.url = kUrl;
11280 request.method = "GET";
11281 request.request_headers = "\r\n";
11282 request.data = kData;
11283
11284 static const Response kNetResponse1 = {
11285 "HTTP/1.1 200 OK",
11286 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
11287 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
11288 kData
11289 };
11290
11291 kNetResponse1.AssignTo(&mock_network_response);
11292
11293 RunTransactionTest(cache.http_cache(), request);
11294
11295 // Request |kUrl| again, this time validating the cache and getting
11296 // a 304 back.
11297
11298 request.load_flags = LOAD_VALIDATE_CACHE;
11299
11300 static const Response kNetResponse2 = {
11301 "HTTP/1.1 304 Not Modified",
11302 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n",
11303 ""
11304 };
11305
11306 kNetResponse2.AssignTo(&mock_network_response);
11307
11308 base::Time request_time = base::Time() + base::Hours(1234);
11309 base::Time response_time = base::Time() + base::Hours(1235);
11310
11311 mock_network_response.request_time = request_time;
11312 mock_network_response.response_time = response_time;
11313
11314 HttpResponseInfo response;
11315 RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response);
11316
11317 // The request and response times should have been updated.
11318 EXPECT_EQ(request_time.ToInternalValue(),
11319 response.request_time.ToInternalValue());
11320 EXPECT_EQ(response_time.ToInternalValue(),
11321 response.response_time.ToInternalValue());
11322
11323 EXPECT_EQ("HTTP/1.1 200 OK\n"
11324 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
11325 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
11326 ToSimpleString(response.headers));
11327
11328 RemoveMockTransaction(&mock_network_response);
11329 }
11330
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCacheWithNetworkIsolationKey)11331 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
11332 SplitCacheWithNetworkIsolationKey) {
11333 MockHttpCache cache;
11334 HttpResponseInfo response;
11335
11336 SchemefulSite site_a(GURL("http://a.com"));
11337 SchemefulSite site_b(GURL("http://b.com"));
11338 SchemefulSite site_data(GURL("data:text/html,<body>Hello World</body>"));
11339
11340 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11341 // Request with a.com as the top frame and subframe origins. This should
11342 // result in a cache miss.
11343 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11344 trans_info.network_anonymization_key =
11345 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11346 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11347 trans_info, &response);
11348 EXPECT_FALSE(response.was_cached);
11349
11350 // The second request should result in a cache hit.
11351 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11352 trans_info, &response);
11353 EXPECT_TRUE(response.was_cached);
11354
11355 // Now request with b.com as the subframe origin. It should result in a cache
11356 // miss.
11357 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_b);
11358 trans_info.network_anonymization_key =
11359 net::NetworkAnonymizationKey::CreateCrossSite(site_a);
11360 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11361 trans_info, &response);
11362 EXPECT_FALSE(response.was_cached);
11363
11364 // The second request should result in a cache hit.
11365 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11366 trans_info, &response);
11367 EXPECT_TRUE(response.was_cached);
11368
11369 // Another request with a.com as the top frame and subframe origin should
11370 // still result in a cache hit.
11371 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11372 trans_info.network_anonymization_key =
11373 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11374 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11375 trans_info, &response);
11376 EXPECT_TRUE(response.was_cached);
11377
11378 // Now make a request with an opaque subframe site. It shouldn't cause
11379 // anything to be added to the cache when the NIK makes use of the frame site.
11380 // Note that we will use `site_b` as the top-level site so that this resource
11381 // won't be in the cache at first regardless of the NIK partitioning scheme.
11382 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_data);
11383 trans_info.network_anonymization_key =
11384 net::NetworkAnonymizationKey::CreateCrossSite(site_b);
11385 if (IsNikFrameSiteEnabled()) {
11386 EXPECT_EQ(absl::nullopt,
11387 trans_info.network_isolation_key.ToCacheKeyString());
11388 } else {
11389 EXPECT_EQ("http://b.com _1",
11390 trans_info.network_isolation_key.ToCacheKeyString().value());
11391 }
11392 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11393 trans_info, &response);
11394 EXPECT_FALSE(response.was_cached);
11395
11396 // On the second request, expect a cache miss if the NIK uses the frame site.
11397 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11398 trans_info, &response);
11399 if (IsNikFrameSiteEnabled()) {
11400 EXPECT_FALSE(response.was_cached);
11401 } else {
11402 EXPECT_TRUE(response.was_cached);
11403 }
11404
11405 // Verify that a post transaction with a data stream uses a separate key.
11406 const int64_t kUploadId = 1; // Just a dummy value.
11407
11408 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11409 element_readers.push_back(
11410 std::make_unique<UploadBytesElementReader>("hello", 5));
11411 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
11412 kUploadId);
11413
11414 MockHttpRequest post_info = MockHttpRequest(kSimplePOST_Transaction);
11415 post_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11416 post_info.network_anonymization_key =
11417 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11418 post_info.upload_data_stream = &upload_data_stream;
11419
11420 RunTransactionTestWithRequest(cache.http_cache(), kSimplePOST_Transaction,
11421 post_info, &response);
11422 EXPECT_FALSE(response.was_cached);
11423 }
11424
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyCSS)11425 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyCSS) {
11426 base::HistogramTester histograms;
11427 MockHttpCache cache;
11428 HttpResponseInfo response;
11429
11430 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11431 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11432 SchemefulSite site_a(origin_a);
11433 SchemefulSite site_b(origin_b);
11434
11435 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11436 transaction.response_headers = "Content-Type: text/css\n";
11437
11438 MockHttpRequest trans_info = MockHttpRequest(transaction);
11439
11440 // Requesting with the same top-frame site should not count as third-party
11441 // but should still be recorded as CSS
11442 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11443 trans_info.network_anonymization_key =
11444 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11445 trans_info.possibly_top_frame_origin = origin_a;
11446
11447 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11448 &response);
11449
11450 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11451 histograms.ExpectTotalCount("HttpCache.Pattern.CSS", 1);
11452 histograms.ExpectTotalCount("HttpCache.Pattern.CSSThirdParty", 0);
11453
11454 // Requesting with a different top-frame site should count as third-party
11455 // and recorded as CSS
11456 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11457 trans_info.network_anonymization_key =
11458 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11459 trans_info.possibly_top_frame_origin = origin_b;
11460
11461 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11462 &response);
11463 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11464 histograms.ExpectTotalCount("HttpCache.Pattern.CSS", 2);
11465 histograms.ExpectTotalCount("HttpCache.Pattern.CSSThirdParty", 1);
11466 }
11467
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyJavaScript)11468 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyJavaScript) {
11469 base::HistogramTester histograms;
11470 MockHttpCache cache;
11471 HttpResponseInfo response;
11472
11473 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11474 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11475 SchemefulSite site_a(origin_a);
11476 SchemefulSite site_b(origin_b);
11477
11478 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11479 transaction.response_headers = "Content-Type: application/javascript\n";
11480
11481 MockHttpRequest trans_info = MockHttpRequest(transaction);
11482
11483 // Requesting with the same top-frame site should not count as third-party
11484 // but should still be recorded as JavaScript
11485 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11486 trans_info.network_anonymization_key =
11487 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11488 trans_info.possibly_top_frame_origin = origin_a;
11489
11490 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11491 &response);
11492
11493 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11494 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScript", 1);
11495 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScriptThirdParty", 0);
11496
11497 // Requesting with a different top-frame site should count as third-party
11498 // and recorded as JavaScript
11499 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11500 trans_info.network_anonymization_key =
11501 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11502 trans_info.possibly_top_frame_origin = origin_b;
11503
11504 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11505 &response);
11506 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11507 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScript", 2);
11508 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScriptThirdParty", 1);
11509 }
11510
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyFont)11511 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyFont) {
11512 base::HistogramTester histograms;
11513 MockHttpCache cache;
11514 HttpResponseInfo response;
11515
11516 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11517 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11518 SchemefulSite site_a(origin_a);
11519 SchemefulSite site_b(origin_b);
11520
11521 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11522 transaction.response_headers = "Content-Type: font/otf\n";
11523
11524 MockHttpRequest trans_info = MockHttpRequest(transaction);
11525
11526 // Requesting with the same top-frame site should not count as third-party
11527 // but should still be recorded as a font
11528 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11529 trans_info.network_anonymization_key =
11530 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11531 trans_info.possibly_top_frame_origin = origin_a;
11532
11533 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11534 &response);
11535
11536 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11537 histograms.ExpectTotalCount("HttpCache.Pattern.Font", 1);
11538 histograms.ExpectTotalCount("HttpCache.Pattern.FontThirdParty", 0);
11539
11540 // Requesting with a different top-frame site should count as third-party
11541 // and recorded as a font
11542 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11543 trans_info.network_anonymization_key =
11544 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11545 trans_info.possibly_top_frame_origin = origin_b;
11546
11547 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11548 &response);
11549 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11550 histograms.ExpectTotalCount("HttpCache.Pattern.Font", 2);
11551 histograms.ExpectTotalCount("HttpCache.Pattern.FontThirdParty", 1);
11552 }
11553
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCache)11554 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled, SplitCache) {
11555 MockHttpCache cache;
11556 HttpResponseInfo response;
11557
11558 SchemefulSite site_a(GURL("http://a.com"));
11559 SchemefulSite site_b(GURL("http://b.com"));
11560 SchemefulSite site_data(GURL("data:text/html,<body>Hello World</body>"));
11561
11562 // A request without a top frame origin shouldn't result in anything being
11563 // added to the cache.
11564 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11565 trans_info.network_isolation_key = net::NetworkIsolationKey();
11566 trans_info.network_anonymization_key = net::NetworkAnonymizationKey();
11567 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11568 trans_info, &response);
11569 EXPECT_FALSE(response.was_cached);
11570
11571 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11572 trans_info, &response);
11573 EXPECT_FALSE(response.was_cached);
11574
11575 // Now request with a.com as the top frame origin. This should initially
11576 // result in a cache miss since the cached resource has a different top frame
11577 // origin.
11578 net::NetworkIsolationKey key_a(site_a, site_a);
11579 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11580 trans_info.network_isolation_key = key_a;
11581 trans_info.network_anonymization_key = nak_a;
11582 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11583 trans_info, &response);
11584 EXPECT_FALSE(response.was_cached);
11585
11586 // The second request should result in a cache hit.
11587 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11588 trans_info, &response);
11589 EXPECT_TRUE(response.was_cached);
11590
11591 // If the same resource with the same NIK is for a subframe document resource,
11592 // it should not be a cache hit.
11593 MockHttpRequest subframe_document_trans_info = trans_info;
11594 subframe_document_trans_info.is_subframe_document_resource = true;
11595 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11596 subframe_document_trans_info, &response);
11597 EXPECT_FALSE(response.was_cached);
11598
11599 // Same request again should be a cache hit.
11600 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11601 subframe_document_trans_info, &response);
11602 EXPECT_TRUE(response.was_cached);
11603
11604 // Now request with b.com as the top frame origin. It should be a cache miss.
11605 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11606 trans_info.network_anonymization_key =
11607 NetworkAnonymizationKey::CreateSameSite(site_b);
11608 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11609 trans_info, &response);
11610 EXPECT_FALSE(response.was_cached);
11611
11612 // The second request should be a cache hit.
11613 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11614 trans_info, &response);
11615 EXPECT_TRUE(response.was_cached);
11616
11617 // Another request for a.com should still result in a cache hit.
11618 trans_info.network_isolation_key = key_a;
11619 trans_info.network_anonymization_key = nak_a;
11620 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11621 trans_info, &response);
11622 EXPECT_TRUE(response.was_cached);
11623
11624 // Now make a request with an opaque top frame origin. It shouldn't result in
11625 // a cache hit.
11626 trans_info.network_isolation_key = NetworkIsolationKey(site_data, site_data);
11627 trans_info.network_anonymization_key =
11628 NetworkAnonymizationKey::CreateSameSite(site_data);
11629 EXPECT_EQ(absl::nullopt, trans_info.network_isolation_key.ToCacheKeyString());
11630 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11631 trans_info, &response);
11632 EXPECT_FALSE(response.was_cached);
11633
11634 // On the second request, it still shouldn't result in a cache hit.
11635 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11636 trans_info, &response);
11637 EXPECT_FALSE(response.was_cached);
11638
11639 // Verify that a post transaction with a data stream uses a separate key.
11640 const int64_t kUploadId = 1; // Just a dummy value.
11641
11642 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11643 element_readers.push_back(
11644 std::make_unique<UploadBytesElementReader>("hello", 5));
11645 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
11646 kUploadId);
11647
11648 MockHttpRequest post_info = MockHttpRequest(kSimplePOST_Transaction);
11649 post_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11650 post_info.network_anonymization_key =
11651 NetworkAnonymizationKey::CreateSameSite(site_a);
11652 post_info.upload_data_stream = &upload_data_stream;
11653
11654 RunTransactionTestWithRequest(cache.http_cache(), kSimplePOST_Transaction,
11655 post_info, &response);
11656 EXPECT_FALSE(response.was_cached);
11657 }
11658
TEST_F(HttpCacheTest,SplitCacheEnabledByDefault)11659 TEST_F(HttpCacheTest, SplitCacheEnabledByDefault) {
11660 HttpCache::ClearGlobalsForTesting();
11661 HttpCache::SplitCacheFeatureEnableByDefault();
11662 EXPECT_TRUE(HttpCache::IsSplitCacheEnabled());
11663
11664 MockHttpCache cache;
11665 HttpResponseInfo response;
11666
11667 SchemefulSite site_a(GURL("http://a.com"));
11668 SchemefulSite site_b(GURL("http://b.com"));
11669 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11670 net::NetworkIsolationKey key_a(site_a, site_a);
11671 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11672 trans_info.network_isolation_key = key_a;
11673 trans_info.network_anonymization_key = nak_a;
11674 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11675 trans_info, &response);
11676 EXPECT_FALSE(response.was_cached);
11677
11678 // Subsequent requests with the same NIK and different NIK will be a cache hit
11679 // and miss respectively.
11680 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11681 trans_info, &response);
11682 EXPECT_TRUE(response.was_cached);
11683
11684 net::NetworkIsolationKey key_b(site_b, site_b);
11685 auto nak_b = net::NetworkAnonymizationKey::CreateSameSite(site_b);
11686 trans_info.network_isolation_key = key_b;
11687 trans_info.network_anonymization_key = nak_b;
11688 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11689 trans_info, &response);
11690 EXPECT_FALSE(response.was_cached);
11691 }
11692
TEST_F(HttpCacheTest,SplitCacheEnabledByDefaultButOverridden)11693 TEST_F(HttpCacheTest, SplitCacheEnabledByDefaultButOverridden) {
11694 HttpCache::ClearGlobalsForTesting();
11695 base::test::ScopedFeatureList feature_list;
11696 feature_list.InitAndDisableFeature(
11697 net::features::kSplitCacheByNetworkIsolationKey);
11698
11699 // Enabling it here should have no effect as it is already overridden.
11700 HttpCache::SplitCacheFeatureEnableByDefault();
11701 EXPECT_FALSE(HttpCache::IsSplitCacheEnabled());
11702 }
11703
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCacheUsesRegistrableDomain)11704 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
11705 SplitCacheUsesRegistrableDomain) {
11706 MockHttpCache cache;
11707 HttpResponseInfo response;
11708 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11709
11710 SchemefulSite site_a(GURL("http://a.foo.com"));
11711 SchemefulSite site_b(GURL("http://b.foo.com"));
11712
11713 net::NetworkIsolationKey key_a(site_a, site_a);
11714 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11715 trans_info.network_isolation_key = key_a;
11716 trans_info.network_anonymization_key = nak_a;
11717 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11718 trans_info, &response);
11719 EXPECT_FALSE(response.was_cached);
11720
11721 // The second request with a different origin but the same registrable domain
11722 // should be a cache hit.
11723 net::NetworkIsolationKey key_b(site_b, site_b);
11724 auto nak_b = net::NetworkAnonymizationKey::CreateSameSite(site_b);
11725 trans_info.network_isolation_key = key_b;
11726 trans_info.network_anonymization_key = nak_b;
11727 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11728 trans_info, &response);
11729 EXPECT_TRUE(response.was_cached);
11730
11731 // Request with a different registrable domain. It should be a cache miss.
11732 SchemefulSite new_site_a(GURL("http://a.bar.com"));
11733 net::NetworkIsolationKey new_key_a(new_site_a, new_site_a);
11734 auto new_nak_a = net::NetworkAnonymizationKey::CreateSameSite(new_site_a);
11735 trans_info.network_isolation_key = new_key_a;
11736 trans_info.network_anonymization_key = new_nak_a;
11737 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11738 trans_info, &response);
11739 EXPECT_FALSE(response.was_cached);
11740 }
11741
TEST_F(HttpCacheTest,NonSplitCache)11742 TEST_F(HttpCacheTest, NonSplitCache) {
11743 base::test::ScopedFeatureList feature_list;
11744 feature_list.InitAndDisableFeature(
11745 net::features::kSplitCacheByNetworkIsolationKey);
11746
11747 MockHttpCache cache;
11748 HttpResponseInfo response;
11749
11750 // A request without a top frame is added to the cache normally.
11751 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11752 trans_info.network_isolation_key = NetworkIsolationKey();
11753 trans_info.network_anonymization_key = NetworkAnonymizationKey();
11754 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11755 trans_info, &response);
11756 EXPECT_FALSE(response.was_cached);
11757
11758 // The second request should result in a cache hit.
11759 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11760 trans_info, &response);
11761 EXPECT_TRUE(response.was_cached);
11762
11763 // Now request with a.com as the top frame origin. The same cached object
11764 // should be used.
11765 const SchemefulSite kSiteA(GURL("http://a.com/"));
11766 trans_info.network_isolation_key = NetworkIsolationKey(kSiteA, kSiteA);
11767 trans_info.network_anonymization_key =
11768 NetworkAnonymizationKey::CreateSameSite(kSiteA);
11769 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11770 trans_info, &response);
11771 EXPECT_TRUE(response.was_cached);
11772 }
11773
TEST_F(HttpCacheTest,SkipVaryCheck)11774 TEST_F(HttpCacheTest, SkipVaryCheck) {
11775 MockHttpCache cache;
11776
11777 // Write a simple vary transaction to the cache.
11778 HttpResponseInfo response;
11779 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11780 transaction.request_headers = "accept-encoding: gzip\r\n";
11781 transaction.response_headers =
11782 "Vary: accept-encoding\n"
11783 "Cache-Control: max-age=10000\n";
11784 RunTransactionTest(cache.http_cache(), transaction);
11785
11786 // Change the request headers so that the request doesn't match due to vary.
11787 // The request should fail.
11788 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11789 transaction.request_headers = "accept-encoding: foo\r\n";
11790 transaction.start_return_code = ERR_CACHE_MISS;
11791 RunTransactionTest(cache.http_cache(), transaction);
11792
11793 // Change the load flags to ignore vary checks, the request should now hit.
11794 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_VARY_CHECK;
11795 transaction.start_return_code = OK;
11796 RunTransactionTest(cache.http_cache(), transaction);
11797 }
11798
TEST_F(HttpCacheTest,SkipVaryCheckStar)11799 TEST_F(HttpCacheTest, SkipVaryCheckStar) {
11800 MockHttpCache cache;
11801
11802 // Write a simple vary:* transaction to the cache.
11803 HttpResponseInfo response;
11804 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11805 transaction.request_headers = "accept-encoding: gzip\r\n";
11806 transaction.response_headers =
11807 "Vary: *\n"
11808 "Cache-Control: max-age=10000\n";
11809 RunTransactionTest(cache.http_cache(), transaction);
11810
11811 // The request shouldn't match even with the same request headers due to the
11812 // Vary: *. The request should fail.
11813 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11814 transaction.start_return_code = ERR_CACHE_MISS;
11815 RunTransactionTest(cache.http_cache(), transaction);
11816
11817 // Change the load flags to ignore vary checks, the request should now hit.
11818 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_VARY_CHECK;
11819 transaction.start_return_code = OK;
11820 RunTransactionTest(cache.http_cache(), transaction);
11821 }
11822
11823 // Tests that we only return valid entries with LOAD_ONLY_FROM_CACHE
11824 // transactions unless LOAD_SKIP_CACHE_VALIDATION is set.
TEST_F(HttpCacheTest,ValidLoadOnlyFromCache)11825 TEST_F(HttpCacheTest, ValidLoadOnlyFromCache) {
11826 MockHttpCache cache;
11827 base::SimpleTestClock clock;
11828 cache.http_cache()->SetClockForTesting(&clock);
11829 cache.network_layer()->SetClock(&clock);
11830
11831 // Write a resource that will expire in 100 seconds.
11832 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11833 transaction.response_headers = "Cache-Control: max-age=100\n";
11834 RunTransactionTest(cache.http_cache(), transaction);
11835
11836 // Move forward in time such that the cached response is no longer valid.
11837 clock.Advance(base::Seconds(101));
11838
11839 // Skipping cache validation should still return a response.
11840 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
11841 RunTransactionTest(cache.http_cache(), transaction);
11842
11843 // If the cache entry is checked for validitiy, it should fail.
11844 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11845 transaction.start_return_code = ERR_CACHE_MISS;
11846 RunTransactionTest(cache.http_cache(), transaction);
11847 }
11848
TEST_F(HttpCacheTest,InvalidLoadFlagCombination)11849 TEST_F(HttpCacheTest, InvalidLoadFlagCombination) {
11850 MockHttpCache cache;
11851
11852 // Put the resource in the cache.
11853 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11854
11855 // Now try to fetch it again, but with a flag combination disallowing both
11856 // cache and network access.
11857 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11858 // DevTools relies on this combination of flags for "disable cache" mode
11859 // when a resource is only supposed to be loaded from cache.
11860 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_BYPASS_CACHE;
11861 transaction.start_return_code = ERR_CACHE_MISS;
11862 RunTransactionTest(cache.http_cache(), transaction);
11863 }
11864
11865 // Tests that we don't mark entries as truncated when a filter detects the end
11866 // of the stream.
TEST_F(HttpCacheTest,FilterCompletion)11867 TEST_F(HttpCacheTest, FilterCompletion) {
11868 MockHttpCache cache;
11869 TestCompletionCallback callback;
11870
11871 {
11872 MockHttpRequest request(kSimpleGET_Transaction);
11873 std::unique_ptr<HttpTransaction> trans;
11874 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11875
11876 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11877 EXPECT_THAT(callback.GetResult(rv), IsOk());
11878
11879 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
11880 rv = trans->Read(buf.get(), 256, callback.callback());
11881 EXPECT_GT(callback.GetResult(rv), 0);
11882
11883 // Now make sure that the entry is preserved.
11884 trans->DoneReading();
11885 }
11886
11887 // Make sure that the ActiveEntry is gone.
11888 base::RunLoop().RunUntilIdle();
11889
11890 // Read from the cache.
11891 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11892
11893 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11894 EXPECT_EQ(1, cache.disk_cache()->open_count());
11895 EXPECT_EQ(1, cache.disk_cache()->create_count());
11896 }
11897
11898 // Tests that we don't mark entries as truncated and release the cache
11899 // entry when DoneReading() is called before any Read() calls, such as
11900 // for a redirect.
TEST_F(HttpCacheTest,DoneReading)11901 TEST_F(HttpCacheTest, DoneReading) {
11902 MockHttpCache cache;
11903 TestCompletionCallback callback;
11904
11905 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11906 transaction.data = "";
11907 MockHttpRequest request(transaction);
11908
11909 std::unique_ptr<HttpTransaction> trans;
11910 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11911
11912 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11913 EXPECT_THAT(callback.GetResult(rv), IsOk());
11914
11915 trans->DoneReading();
11916 // Leave the transaction around.
11917
11918 // Make sure that the ActiveEntry is gone.
11919 base::RunLoop().RunUntilIdle();
11920
11921 // Read from the cache. This should not deadlock.
11922 RunTransactionTest(cache.http_cache(), transaction);
11923
11924 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11925 EXPECT_EQ(1, cache.disk_cache()->open_count());
11926 EXPECT_EQ(1, cache.disk_cache()->create_count());
11927 }
11928
11929 // Tests that we stop caching when told.
TEST_F(HttpCacheTest,StopCachingDeletesEntry)11930 TEST_F(HttpCacheTest, StopCachingDeletesEntry) {
11931 MockHttpCache cache;
11932 TestCompletionCallback callback;
11933 MockHttpRequest request(kSimpleGET_Transaction);
11934
11935 {
11936 std::unique_ptr<HttpTransaction> trans;
11937 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11938
11939 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11940 EXPECT_THAT(callback.GetResult(rv), IsOk());
11941
11942 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
11943 rv = trans->Read(buf.get(), 10, callback.callback());
11944 EXPECT_EQ(10, callback.GetResult(rv));
11945
11946 trans->StopCaching();
11947
11948 // We should be able to keep reading.
11949 rv = trans->Read(buf.get(), 256, callback.callback());
11950 EXPECT_GT(callback.GetResult(rv), 0);
11951 rv = trans->Read(buf.get(), 256, callback.callback());
11952 EXPECT_EQ(0, callback.GetResult(rv));
11953 }
11954
11955 // Make sure that the ActiveEntry is gone.
11956 base::RunLoop().RunUntilIdle();
11957
11958 // Verify that the entry is gone.
11959 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11960
11961 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11962 EXPECT_EQ(0, cache.disk_cache()->open_count());
11963 EXPECT_EQ(2, cache.disk_cache()->create_count());
11964 }
11965
11966 // Tests that we stop caching when told, even if DoneReading is called
11967 // after StopCaching.
TEST_F(HttpCacheTest,StopCachingThenDoneReadingDeletesEntry)11968 TEST_F(HttpCacheTest, StopCachingThenDoneReadingDeletesEntry) {
11969 MockHttpCache cache;
11970 TestCompletionCallback callback;
11971 MockHttpRequest request(kSimpleGET_Transaction);
11972
11973 {
11974 std::unique_ptr<HttpTransaction> trans;
11975 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11976
11977 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11978 EXPECT_THAT(callback.GetResult(rv), IsOk());
11979
11980 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
11981 rv = trans->Read(buf.get(), 10, callback.callback());
11982 EXPECT_EQ(10, callback.GetResult(rv));
11983
11984 trans->StopCaching();
11985
11986 // We should be able to keep reading.
11987 rv = trans->Read(buf.get(), 256, callback.callback());
11988 EXPECT_GT(callback.GetResult(rv), 0);
11989 rv = trans->Read(buf.get(), 256, callback.callback());
11990 EXPECT_EQ(0, callback.GetResult(rv));
11991
11992 // We should be able to call DoneReading.
11993 trans->DoneReading();
11994 }
11995
11996 // Make sure that the ActiveEntry is gone.
11997 base::RunLoop().RunUntilIdle();
11998
11999 // Verify that the entry is gone.
12000 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
12001
12002 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12003 EXPECT_EQ(0, cache.disk_cache()->open_count());
12004 EXPECT_EQ(2, cache.disk_cache()->create_count());
12005 }
12006
12007 // Tests that we stop caching when told, when using auth.
TEST_F(HttpCacheTest,StopCachingWithAuthDeletesEntry)12008 TEST_F(HttpCacheTest, StopCachingWithAuthDeletesEntry) {
12009 MockHttpCache cache;
12010 TestCompletionCallback callback;
12011 MockTransaction mock_transaction(kSimpleGET_Transaction);
12012 mock_transaction.status = "HTTP/1.1 401 Unauthorized";
12013 AddMockTransaction(&mock_transaction);
12014 MockHttpRequest request(mock_transaction);
12015
12016 {
12017 std::unique_ptr<HttpTransaction> trans;
12018 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
12019
12020 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12021 EXPECT_THAT(callback.GetResult(rv), IsOk());
12022
12023 trans->StopCaching();
12024 }
12025 RemoveMockTransaction(&mock_transaction);
12026
12027 // Make sure that the ActiveEntry is gone.
12028 base::RunLoop().RunUntilIdle();
12029
12030 // Verify that the entry is gone.
12031 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
12032
12033 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12034 EXPECT_EQ(0, cache.disk_cache()->open_count());
12035 EXPECT_EQ(2, cache.disk_cache()->create_count());
12036 }
12037
12038 // Tests that when we are told to stop caching we don't throw away valid data.
TEST_F(HttpCacheTest,StopCachingSavesEntry)12039 TEST_F(HttpCacheTest, StopCachingSavesEntry) {
12040 MockHttpCache cache;
12041 TestCompletionCallback callback;
12042 MockHttpRequest request(kSimpleGET_Transaction);
12043
12044 {
12045 std::unique_ptr<HttpTransaction> trans;
12046 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
12047
12048 // Force a response that can be resumed.
12049 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
12050 AddMockTransaction(&mock_transaction);
12051 mock_transaction.response_headers = "Cache-Control: max-age=10000\n"
12052 "Content-Length: 42\n"
12053 "Etag: \"foo\"\n";
12054
12055 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12056 EXPECT_THAT(callback.GetResult(rv), IsOk());
12057
12058 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
12059 rv = trans->Read(buf.get(), 10, callback.callback());
12060 EXPECT_EQ(callback.GetResult(rv), 10);
12061
12062 trans->StopCaching();
12063
12064 // We should be able to keep reading.
12065 rv = trans->Read(buf.get(), 256, callback.callback());
12066 EXPECT_GT(callback.GetResult(rv), 0);
12067 rv = trans->Read(buf.get(), 256, callback.callback());
12068 EXPECT_EQ(callback.GetResult(rv), 0);
12069 }
12070
12071 // Verify that the entry is marked as incomplete.
12072 // VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0);
12073 // Verify that the entry is doomed.
12074 cache.disk_cache()->IsDiskEntryDoomed(request.CacheKey());
12075 }
12076
12077 // Tests that we handle truncated enries when StopCaching is called.
TEST_F(HttpCacheTest,StopCachingTruncatedEntry)12078 TEST_F(HttpCacheTest, StopCachingTruncatedEntry) {
12079 MockHttpCache cache;
12080 TestCompletionCallback callback;
12081 MockHttpRequest request(kRangeGET_TransactionOK);
12082 request.extra_headers.Clear();
12083 request.extra_headers.AddHeaderFromString(EXTRA_HEADER_LINE);
12084 AddMockTransaction(&kRangeGET_TransactionOK);
12085
12086 std::string raw_headers("HTTP/1.1 200 OK\n"
12087 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12088 "ETag: \"foo\"\n"
12089 "Accept-Ranges: bytes\n"
12090 "Content-Length: 80\n");
12091 CreateTruncatedEntry(raw_headers, &cache);
12092
12093 {
12094 // Now make a regular request.
12095 std::unique_ptr<HttpTransaction> trans;
12096 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
12097
12098 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12099 EXPECT_THAT(callback.GetResult(rv), IsOk());
12100
12101 scoped_refptr<IOBuffer> buf = base::MakeRefCounted<IOBuffer>(256);
12102 rv = trans->Read(buf.get(), 10, callback.callback());
12103 EXPECT_EQ(callback.GetResult(rv), 10);
12104
12105 // This is actually going to do nothing.
12106 trans->StopCaching();
12107
12108 // We should be able to keep reading.
12109 rv = trans->Read(buf.get(), 256, callback.callback());
12110 EXPECT_GT(callback.GetResult(rv), 0);
12111 rv = trans->Read(buf.get(), 256, callback.callback());
12112 EXPECT_GT(callback.GetResult(rv), 0);
12113 rv = trans->Read(buf.get(), 256, callback.callback());
12114 EXPECT_EQ(callback.GetResult(rv), 0);
12115 }
12116
12117 // Verify that the disk entry was updated.
12118 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 80);
12119 RemoveMockTransaction(&kRangeGET_TransactionOK);
12120 }
12121
12122 namespace {
12123
12124 enum class TransactionPhase {
12125 BEFORE_FIRST_READ,
12126 AFTER_FIRST_READ,
12127 AFTER_NETWORK_READ
12128 };
12129
12130 using CacheInitializer = void (*)(MockHttpCache*);
12131 using HugeCacheTestConfiguration =
12132 std::pair<TransactionPhase, CacheInitializer>;
12133
12134 class HttpCacheHugeResourceTest
12135 : public ::testing::TestWithParam<HugeCacheTestConfiguration>,
12136 public WithTaskEnvironment {
12137 public:
12138 static std::list<HugeCacheTestConfiguration> GetTestModes();
12139 static std::list<HugeCacheTestConfiguration> kTestModes;
12140
12141 // CacheInitializer callbacks. These are used to initialize the cache
12142 // depending on the test run configuration.
12143
12144 // Initializes a cache containing a truncated entry containing the first 20
12145 // bytes of the reponse body.
12146 static void SetupTruncatedCacheEntry(MockHttpCache* cache);
12147
12148 // Initializes a cache containing a sparse entry. The first 10 bytes are
12149 // present in the cache.
12150 static void SetupPrefixSparseCacheEntry(MockHttpCache* cache);
12151
12152 // Initializes a cache containing a sparse entry. The 10 bytes at offset
12153 // 99990 are present in the cache.
12154 static void SetupInfixSparseCacheEntry(MockHttpCache* cache);
12155
12156 protected:
12157 static void LargeResourceTransactionHandler(
12158 const net::HttpRequestInfo* request,
12159 std::string* response_status,
12160 std::string* response_headers,
12161 std::string* response_data);
12162 static int LargeBufferReader(int64_t content_length,
12163 int64_t offset,
12164 net::IOBuffer* buf,
12165 int buf_len);
12166
12167 static void SetFlagOnBeforeNetworkStart(bool* started, bool* /* defer */);
12168
12169 // Size of resource to be tested.
12170 static const int64_t kTotalSize = 5000LL * 1000 * 1000;
12171 };
12172
12173 const int64_t HttpCacheHugeResourceTest::kTotalSize;
12174
12175 // static
LargeResourceTransactionHandler(const net::HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)12176 void HttpCacheHugeResourceTest::LargeResourceTransactionHandler(
12177 const net::HttpRequestInfo* request,
12178 std::string* response_status,
12179 std::string* response_headers,
12180 std::string* response_data) {
12181 std::string if_range;
12182 if (!request->extra_headers.GetHeader(net::HttpRequestHeaders::kIfRange,
12183 &if_range)) {
12184 // If there were no range headers in the request, we are going to just
12185 // return the entire response body.
12186 *response_status = "HTTP/1.1 200 Success";
12187 *response_headers = base::StringPrintf("Content-Length: %" PRId64
12188 "\n"
12189 "ETag: \"foo\"\n"
12190 "Accept-Ranges: bytes\n",
12191 kTotalSize);
12192 return;
12193 }
12194
12195 // From this point on, we should be processing a valid byte-range request.
12196 EXPECT_EQ("\"foo\"", if_range);
12197
12198 std::string range_header;
12199 EXPECT_TRUE(request->extra_headers.GetHeader(net::HttpRequestHeaders::kRange,
12200 &range_header));
12201 std::vector<net::HttpByteRange> ranges;
12202
12203 EXPECT_TRUE(net::HttpUtil::ParseRangeHeader(range_header, &ranges));
12204 ASSERT_EQ(1u, ranges.size());
12205
12206 net::HttpByteRange range = ranges[0];
12207 EXPECT_TRUE(range.HasFirstBytePosition());
12208 int64_t last_byte_position =
12209 range.HasLastBytePosition() ? range.last_byte_position() : kTotalSize - 1;
12210
12211 *response_status = "HTTP/1.1 206 Partial";
12212 *response_headers = base::StringPrintf(
12213 "Content-Range: bytes %" PRId64 "-%" PRId64 "/%" PRId64
12214 "\n"
12215 "Content-Length: %" PRId64 "\n",
12216 range.first_byte_position(), last_byte_position, kTotalSize,
12217 last_byte_position - range.first_byte_position() + 1);
12218 }
12219
12220 // static
LargeBufferReader(int64_t content_length,int64_t offset,net::IOBuffer * buf,int buf_len)12221 int HttpCacheHugeResourceTest::LargeBufferReader(int64_t content_length,
12222 int64_t offset,
12223 net::IOBuffer* buf,
12224 int buf_len) {
12225 // This test involves reading multiple gigabytes of data. To make it run in a
12226 // reasonable amount of time, we are going to skip filling the buffer with
12227 // data. Instead the test relies on verifying that the count of bytes expected
12228 // at the end is correct.
12229 EXPECT_LT(0, content_length);
12230 EXPECT_LE(offset, content_length);
12231 int num = std::min(static_cast<int64_t>(buf_len), content_length - offset);
12232 return num;
12233 }
12234
12235 // static
SetFlagOnBeforeNetworkStart(bool * started,bool *)12236 void HttpCacheHugeResourceTest::SetFlagOnBeforeNetworkStart(bool* started,
12237 bool* /* defer */) {
12238 *started = true;
12239 }
12240
12241 // static
SetupTruncatedCacheEntry(MockHttpCache * cache)12242 void HttpCacheHugeResourceTest::SetupTruncatedCacheEntry(MockHttpCache* cache) {
12243 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
12244 std::string cached_headers = base::StringPrintf(
12245 "HTTP/1.1 200 OK\n"
12246 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12247 "ETag: \"foo\"\n"
12248 "Accept-Ranges: bytes\n"
12249 "Content-Length: %" PRId64 "\n",
12250 kTotalSize);
12251 CreateTruncatedEntry(cached_headers, cache);
12252 }
12253
12254 // static
SetupPrefixSparseCacheEntry(MockHttpCache * cache)12255 void HttpCacheHugeResourceTest::SetupPrefixSparseCacheEntry(
12256 MockHttpCache* cache) {
12257 MockTransaction transaction(kRangeGET_TransactionOK);
12258 transaction.handler = nullptr;
12259 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
12260 transaction.response_headers =
12261 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12262 "ETag: \"foo\"\n"
12263 "Accept-Ranges: bytes\n"
12264 "Content-Range: bytes 0-9/5000000000\n"
12265 "Content-Length: 10\n";
12266 AddMockTransaction(&transaction);
12267 std::string headers;
12268 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
12269 RemoveMockTransaction(&transaction);
12270 }
12271
12272 // static
SetupInfixSparseCacheEntry(MockHttpCache * cache)12273 void HttpCacheHugeResourceTest::SetupInfixSparseCacheEntry(
12274 MockHttpCache* cache) {
12275 MockTransaction transaction(kRangeGET_TransactionOK);
12276 transaction.handler = nullptr;
12277 transaction.request_headers = "Range: bytes = 99990-99999\r\n" EXTRA_HEADER;
12278 transaction.response_headers =
12279 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12280 "ETag: \"foo\"\n"
12281 "Accept-Ranges: bytes\n"
12282 "Content-Range: bytes 99990-99999/5000000000\n"
12283 "Content-Length: 10\n";
12284 AddMockTransaction(&transaction);
12285 std::string headers;
12286 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
12287 RemoveMockTransaction(&transaction);
12288 }
12289
12290 // static
12291 std::list<HugeCacheTestConfiguration>
GetTestModes()12292 HttpCacheHugeResourceTest::GetTestModes() {
12293 std::list<HugeCacheTestConfiguration> test_modes;
12294 const TransactionPhase kTransactionPhases[] = {
12295 TransactionPhase::BEFORE_FIRST_READ, TransactionPhase::AFTER_FIRST_READ,
12296 TransactionPhase::AFTER_NETWORK_READ};
12297 const CacheInitializer kInitializers[] = {&SetupTruncatedCacheEntry,
12298 &SetupPrefixSparseCacheEntry,
12299 &SetupInfixSparseCacheEntry};
12300
12301 for (const auto phase : kTransactionPhases)
12302 for (const auto initializer : kInitializers)
12303 test_modes.emplace_back(phase, initializer);
12304
12305 return test_modes;
12306 }
12307
12308 // static
12309 std::list<HugeCacheTestConfiguration> HttpCacheHugeResourceTest::kTestModes =
12310 HttpCacheHugeResourceTest::GetTestModes();
12311
12312 INSTANTIATE_TEST_SUITE_P(
12313 _,
12314 HttpCacheHugeResourceTest,
12315 ::testing::ValuesIn(HttpCacheHugeResourceTest::kTestModes));
12316
12317 } // namespace
12318
12319 // Test what happens when StopCaching() is called while reading a huge resource
12320 // fetched via GET. Various combinations of cache state and when StopCaching()
12321 // is called is controlled by the parameter passed into the test via the
12322 // INSTANTIATE_TEST_SUITE_P invocation above.
TEST_P(HttpCacheHugeResourceTest,StopCachingFollowedByReadForHugeTruncatedResource)12323 TEST_P(HttpCacheHugeResourceTest,
12324 StopCachingFollowedByReadForHugeTruncatedResource) {
12325 // This test is going to be repeated for all combinations of TransactionPhase
12326 // and CacheInitializers returned by GetTestModes().
12327 const TransactionPhase stop_caching_phase = GetParam().first;
12328 const CacheInitializer cache_initializer = GetParam().second;
12329
12330 MockHttpCache cache;
12331 (*cache_initializer)(&cache);
12332
12333 MockTransaction transaction(kSimpleGET_Transaction);
12334 transaction.url = kRangeGET_TransactionOK.url;
12335 transaction.handler = &LargeResourceTransactionHandler;
12336 transaction.read_handler = &LargeBufferReader;
12337 ScopedMockTransaction scoped_transaction(transaction);
12338
12339 MockHttpRequest request(transaction);
12340 net::TestCompletionCallback callback;
12341 std::unique_ptr<net::HttpTransaction> http_transaction;
12342 int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY,
12343 &http_transaction);
12344 ASSERT_EQ(net::OK, rv);
12345 ASSERT_TRUE(http_transaction.get());
12346
12347 bool network_transaction_started = false;
12348 if (stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
12349 http_transaction->SetBeforeNetworkStartCallback(base::BindOnce(
12350 &SetFlagOnBeforeNetworkStart, &network_transaction_started));
12351 }
12352
12353 rv = http_transaction->Start(&request, callback.callback(),
12354 NetLogWithSource());
12355 rv = callback.GetResult(rv);
12356 ASSERT_EQ(net::OK, rv);
12357
12358 if (stop_caching_phase == TransactionPhase::BEFORE_FIRST_READ)
12359 http_transaction->StopCaching();
12360
12361 int64_t total_bytes_received = 0;
12362
12363 EXPECT_EQ(kTotalSize,
12364 http_transaction->GetResponseInfo()->headers->GetContentLength());
12365 do {
12366 // This test simulates reading gigabytes of data. Buffer size is set to 10MB
12367 // to reduce the number of reads and speed up the test.
12368 const int kBufferSize = 1024 * 1024 * 10;
12369 scoped_refptr<net::IOBuffer> buf =
12370 base::MakeRefCounted<net::IOBuffer>(kBufferSize);
12371 rv = http_transaction->Read(buf.get(), kBufferSize, callback.callback());
12372 rv = callback.GetResult(rv);
12373
12374 if (stop_caching_phase == TransactionPhase::AFTER_FIRST_READ &&
12375 total_bytes_received == 0) {
12376 http_transaction->StopCaching();
12377 }
12378
12379 if (rv > 0)
12380 total_bytes_received += rv;
12381
12382 if (network_transaction_started &&
12383 stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
12384 http_transaction->StopCaching();
12385 network_transaction_started = false;
12386 }
12387 } while (rv > 0);
12388
12389 // The only verification we are going to do is that the received resource has
12390 // the correct size. This is sufficient to verify that the state machine
12391 // didn't terminate abruptly due to the StopCaching() call.
12392 EXPECT_EQ(kTotalSize, total_bytes_received);
12393 }
12394
12395 // Tests that we detect truncated resources from the net when there is
12396 // a Content-Length header.
TEST_F(HttpCacheTest,TruncatedByContentLength)12397 TEST_F(HttpCacheTest, TruncatedByContentLength) {
12398 MockHttpCache cache;
12399 TestCompletionCallback callback;
12400
12401 MockTransaction transaction(kSimpleGET_Transaction);
12402 AddMockTransaction(&transaction);
12403 transaction.response_headers = "Cache-Control: max-age=10000\n"
12404 "Content-Length: 100\n";
12405 RunTransactionTest(cache.http_cache(), transaction);
12406 RemoveMockTransaction(&transaction);
12407
12408 // Read from the cache.
12409 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
12410
12411 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12412 EXPECT_EQ(0, cache.disk_cache()->open_count());
12413 EXPECT_EQ(2, cache.disk_cache()->create_count());
12414 }
12415
12416 // Tests that we actually flag entries as truncated when we detect an error
12417 // from the net.
TEST_F(HttpCacheTest,TruncatedByContentLength2)12418 TEST_F(HttpCacheTest, TruncatedByContentLength2) {
12419 MockHttpCache cache;
12420 TestCompletionCallback callback;
12421
12422 MockTransaction transaction(kSimpleGET_Transaction);
12423 AddMockTransaction(&transaction);
12424 transaction.response_headers = "Cache-Control: max-age=10000\n"
12425 "Content-Length: 100\n"
12426 "Etag: \"foo\"\n";
12427 RunTransactionTest(cache.http_cache(), transaction);
12428 RemoveMockTransaction(&transaction);
12429
12430 // Verify that the entry is marked as incomplete.
12431 MockHttpRequest request(transaction);
12432 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 0);
12433 }
12434
12435 // Make sure that calling SetPriority on a cache transaction passes on
12436 // its priority updates to its underlying network transaction.
TEST_F(HttpCacheTest,SetPriority)12437 TEST_F(HttpCacheTest, SetPriority) {
12438 MockHttpCache cache;
12439
12440 HttpRequestInfo info;
12441 std::unique_ptr<HttpTransaction> trans;
12442 ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk());
12443
12444 // Shouldn't crash, but doesn't do anything either.
12445 trans->SetPriority(LOW);
12446
12447 EXPECT_FALSE(cache.network_layer()->last_transaction());
12448 EXPECT_EQ(DEFAULT_PRIORITY,
12449 cache.network_layer()->last_create_transaction_priority());
12450
12451 info.url = GURL(kSimpleGET_Transaction.url);
12452 TestCompletionCallback callback;
12453 EXPECT_EQ(ERR_IO_PENDING,
12454 trans->Start(&info, callback.callback(), NetLogWithSource()));
12455
12456 EXPECT_TRUE(cache.network_layer()->last_transaction());
12457 if (cache.network_layer()->last_transaction()) {
12458 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
12459 EXPECT_EQ(LOW, cache.network_layer()->last_transaction()->priority());
12460 }
12461
12462 trans->SetPriority(HIGHEST);
12463
12464 if (cache.network_layer()->last_transaction()) {
12465 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
12466 EXPECT_EQ(HIGHEST, cache.network_layer()->last_transaction()->priority());
12467 }
12468
12469 EXPECT_THAT(callback.WaitForResult(), IsOk());
12470 }
12471
12472 // Make sure that calling SetWebSocketHandshakeStreamCreateHelper on a cache
12473 // transaction passes on its argument to the underlying network transaction.
TEST_F(HttpCacheTest,SetWebSocketHandshakeStreamCreateHelper)12474 TEST_F(HttpCacheTest, SetWebSocketHandshakeStreamCreateHelper) {
12475 MockHttpCache cache;
12476 HttpRequestInfo info;
12477
12478 FakeWebSocketHandshakeStreamCreateHelper create_helper;
12479 std::unique_ptr<HttpTransaction> trans;
12480 ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk());
12481
12482 EXPECT_FALSE(cache.network_layer()->last_transaction());
12483
12484 info.url = GURL(kSimpleGET_Transaction.url);
12485 TestCompletionCallback callback;
12486 EXPECT_EQ(ERR_IO_PENDING,
12487 trans->Start(&info, callback.callback(), NetLogWithSource()));
12488
12489 ASSERT_TRUE(cache.network_layer()->last_transaction());
12490 EXPECT_FALSE(cache.network_layer()->last_transaction()->
12491 websocket_handshake_stream_create_helper());
12492 trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper);
12493 EXPECT_EQ(&create_helper,
12494 cache.network_layer()->last_transaction()->
12495 websocket_handshake_stream_create_helper());
12496 EXPECT_THAT(callback.WaitForResult(), IsOk());
12497 }
12498
12499 // Make sure that a cache transaction passes on its priority to
12500 // newly-created network transactions.
TEST_F(HttpCacheTest,SetPriorityNewTransaction)12501 TEST_F(HttpCacheTest, SetPriorityNewTransaction) {
12502 MockHttpCache cache;
12503 AddMockTransaction(&kRangeGET_TransactionOK);
12504
12505 std::string raw_headers("HTTP/1.1 200 OK\n"
12506 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12507 "ETag: \"foo\"\n"
12508 "Accept-Ranges: bytes\n"
12509 "Content-Length: 80\n");
12510 CreateTruncatedEntry(raw_headers, &cache);
12511
12512 // Now make a regular request.
12513 std::string headers;
12514 MockTransaction transaction(kRangeGET_TransactionOK);
12515 transaction.request_headers = EXTRA_HEADER;
12516 transaction.data = kFullRangeData;
12517
12518 std::unique_ptr<HttpTransaction> trans;
12519 ASSERT_THAT(cache.http_cache()->CreateTransaction(MEDIUM, &trans), IsOk());
12520 EXPECT_EQ(DEFAULT_PRIORITY,
12521 cache.network_layer()->last_create_transaction_priority());
12522
12523 MockHttpRequest info(transaction);
12524 TestCompletionCallback callback;
12525 EXPECT_EQ(ERR_IO_PENDING,
12526 trans->Start(&info, callback.callback(), NetLogWithSource()));
12527 EXPECT_THAT(callback.WaitForResult(), IsOk());
12528
12529 EXPECT_EQ(MEDIUM, cache.network_layer()->last_create_transaction_priority());
12530
12531 trans->SetPriority(HIGHEST);
12532 // Should trigger a new network transaction and pick up the new
12533 // priority.
12534 ReadAndVerifyTransaction(trans.get(), transaction);
12535
12536 EXPECT_EQ(HIGHEST, cache.network_layer()->last_create_transaction_priority());
12537
12538 RemoveMockTransaction(&kRangeGET_TransactionOK);
12539 }
12540
12541 namespace {
12542
RunTransactionAndGetNetworkBytes(MockHttpCache * cache,const MockTransaction & trans_info,int64_t * sent_bytes,int64_t * received_bytes)12543 void RunTransactionAndGetNetworkBytes(MockHttpCache* cache,
12544 const MockTransaction& trans_info,
12545 int64_t* sent_bytes,
12546 int64_t* received_bytes) {
12547 RunTransactionTestBase(
12548 cache->http_cache(), trans_info, MockHttpRequest(trans_info), nullptr,
12549 NetLogWithSource(), nullptr, sent_bytes, received_bytes, nullptr);
12550 }
12551
12552 } // namespace
12553
TEST_F(HttpCacheTest,NetworkBytesCacheMissAndThenHit)12554 TEST_F(HttpCacheTest, NetworkBytesCacheMissAndThenHit) {
12555 MockHttpCache cache;
12556
12557 MockTransaction transaction(kSimpleGET_Transaction);
12558 int64_t sent, received;
12559 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12560 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12561 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12562
12563 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12564 EXPECT_EQ(0, sent);
12565 EXPECT_EQ(0, received);
12566 }
12567
TEST_F(HttpCacheTest,NetworkBytesConditionalRequest304)12568 TEST_F(HttpCacheTest, NetworkBytesConditionalRequest304) {
12569 MockHttpCache cache;
12570
12571 ScopedMockTransaction transaction(kETagGET_Transaction);
12572 int64_t sent, received;
12573 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12574 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12575 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12576
12577 transaction.load_flags = LOAD_VALIDATE_CACHE;
12578 transaction.handler = ETagGet_ConditionalRequest_Handler;
12579 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12580 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12581 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12582 }
12583
TEST_F(HttpCacheTest,NetworkBytesConditionalRequest200)12584 TEST_F(HttpCacheTest, NetworkBytesConditionalRequest200) {
12585 MockHttpCache cache;
12586
12587 MockTransaction transaction(kTypicalGET_Transaction);
12588 transaction.request_headers = "Foo: bar\r\n";
12589 transaction.response_headers =
12590 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
12591 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
12592 "Etag: \"foopy\"\n"
12593 "Cache-Control: max-age=0\n"
12594 "Vary: Foo\n";
12595 AddMockTransaction(&transaction);
12596 int64_t sent, received;
12597 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12598 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12599 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12600
12601 RevalidationServer server;
12602 transaction.handler = server.Handler;
12603 transaction.request_headers = "Foo: none\r\n";
12604 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12605 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12606 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12607
12608 RemoveMockTransaction(&transaction);
12609 }
12610
TEST_F(HttpCacheTest,NetworkBytesRange)12611 TEST_F(HttpCacheTest, NetworkBytesRange) {
12612 MockHttpCache cache;
12613 AddMockTransaction(&kRangeGET_TransactionOK);
12614 MockTransaction transaction(kRangeGET_TransactionOK);
12615
12616 // Read bytes 40-49 from the network.
12617 int64_t sent, received;
12618 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12619 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12620 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12621
12622 // Read bytes 40-49 from the cache.
12623 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12624 EXPECT_EQ(0, sent);
12625 EXPECT_EQ(0, received);
12626 base::RunLoop().RunUntilIdle();
12627
12628 // Read bytes 30-39 from the network.
12629 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
12630 transaction.data = "rg: 30-39 ";
12631 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12632 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12633 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12634 base::RunLoop().RunUntilIdle();
12635
12636 // Read bytes 20-29 and 50-59 from the network, bytes 30-49 from the cache.
12637 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
12638 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
12639 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12640 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes * 2, sent);
12641 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes * 2, received);
12642
12643 RemoveMockTransaction(&kRangeGET_TransactionOK);
12644 }
12645
12646 class HttpCachePrefetchValidationTest : public TestWithTaskEnvironment {
12647 protected:
12648 static const int kNumSecondsPerMinute = 60;
12649 static const int kMaxAgeSecs = 100;
12650 static const int kRequireValidationSecs = kMaxAgeSecs + 1;
12651
HttpCachePrefetchValidationTest()12652 HttpCachePrefetchValidationTest() : transaction_(kSimpleGET_Transaction) {
12653 DCHECK_LT(kMaxAgeSecs, prefetch_reuse_mins() * kNumSecondsPerMinute);
12654
12655 cache_.http_cache()->SetClockForTesting(&clock_);
12656 cache_.network_layer()->SetClock(&clock_);
12657
12658 transaction_.response_headers = "Cache-Control: max-age=100\n";
12659 }
12660
TransactionRequiredNetwork(int load_flags)12661 bool TransactionRequiredNetwork(int load_flags) {
12662 int pre_transaction_count = transaction_count();
12663 transaction_.load_flags = load_flags;
12664 RunTransactionTest(cache_.http_cache(), transaction_);
12665 return pre_transaction_count != transaction_count();
12666 }
12667
AdvanceTime(int seconds)12668 void AdvanceTime(int seconds) { clock_.Advance(base::Seconds(seconds)); }
12669
prefetch_reuse_mins()12670 int prefetch_reuse_mins() { return HttpCache::kPrefetchReuseMins; }
12671
12672 // How many times this test has sent requests to the (fake) origin
12673 // server. Every test case needs to make at least one request to initialise
12674 // the cache.
transaction_count()12675 int transaction_count() {
12676 return cache_.network_layer()->transaction_count();
12677 }
12678
12679 MockHttpCache cache_;
12680 ScopedMockTransaction transaction_;
12681 std::string response_headers_;
12682 base::SimpleTestClock clock_;
12683 };
12684
TEST_F(HttpCachePrefetchValidationTest,SkipValidationShortlyAfterPrefetch)12685 TEST_F(HttpCachePrefetchValidationTest, SkipValidationShortlyAfterPrefetch) {
12686 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12687 AdvanceTime(kRequireValidationSecs);
12688 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12689 }
12690
TEST_F(HttpCachePrefetchValidationTest,ValidateLongAfterPrefetch)12691 TEST_F(HttpCachePrefetchValidationTest, ValidateLongAfterPrefetch) {
12692 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12693 AdvanceTime(prefetch_reuse_mins() * kNumSecondsPerMinute);
12694 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12695 }
12696
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnceOnly)12697 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceOnly) {
12698 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12699 AdvanceTime(kRequireValidationSecs);
12700 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12701 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12702 }
12703
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnceReadOnly)12704 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceReadOnly) {
12705 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12706 AdvanceTime(kRequireValidationSecs);
12707 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_ONLY_FROM_CACHE |
12708 LOAD_SKIP_CACHE_VALIDATION));
12709 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12710 }
12711
TEST_F(HttpCachePrefetchValidationTest,BypassCacheOverwritesPrefetch)12712 TEST_F(HttpCachePrefetchValidationTest, BypassCacheOverwritesPrefetch) {
12713 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12714 AdvanceTime(kRequireValidationSecs);
12715 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_BYPASS_CACHE));
12716 AdvanceTime(kRequireValidationSecs);
12717 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12718 }
12719
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnExistingEntryThatNeedsValidation)12720 TEST_F(HttpCachePrefetchValidationTest,
12721 SkipValidationOnExistingEntryThatNeedsValidation) {
12722 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12723 AdvanceTime(kRequireValidationSecs);
12724 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12725 AdvanceTime(kRequireValidationSecs);
12726 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12727 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12728 }
12729
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnExistingEntryThatDoesNotNeedValidation)12730 TEST_F(HttpCachePrefetchValidationTest,
12731 SkipValidationOnExistingEntryThatDoesNotNeedValidation) {
12732 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12733 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
12734 AdvanceTime(kRequireValidationSecs);
12735 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12736 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12737 }
12738
TEST_F(HttpCachePrefetchValidationTest,PrefetchMultipleTimes)12739 TEST_F(HttpCachePrefetchValidationTest, PrefetchMultipleTimes) {
12740 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12741 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
12742 AdvanceTime(kRequireValidationSecs);
12743 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12744 }
12745
TEST_F(HttpCachePrefetchValidationTest,ValidateOnDelayedSecondPrefetch)12746 TEST_F(HttpCachePrefetchValidationTest, ValidateOnDelayedSecondPrefetch) {
12747 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12748 AdvanceTime(kRequireValidationSecs);
12749 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12750 AdvanceTime(kRequireValidationSecs);
12751 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12752 }
12753
TEST_F(HttpCacheTest,StaleContentNotUsedWhenLoadFlagNotSet)12754 TEST_F(HttpCacheTest, StaleContentNotUsedWhenLoadFlagNotSet) {
12755 MockHttpCache cache;
12756
12757 ScopedMockTransaction stale_while_revalidate_transaction(
12758 kSimpleGET_Transaction);
12759
12760 stale_while_revalidate_transaction.response_headers =
12761 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12762 "Age: 10801\n"
12763 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12764
12765 // Write to the cache.
12766 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12767
12768 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12769
12770 // Send the request again and check that it is sent to the network again.
12771 HttpResponseInfo response_info;
12772 RunTransactionTestWithResponseInfo(
12773 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12774
12775 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12776 EXPECT_FALSE(response_info.async_revalidation_requested);
12777 }
12778
TEST_F(HttpCacheTest,StaleContentUsedWhenLoadFlagSetAndUsableThenTimesout)12779 TEST_F(HttpCacheTest, StaleContentUsedWhenLoadFlagSetAndUsableThenTimesout) {
12780 MockHttpCache cache;
12781 base::SimpleTestClock clock;
12782 cache.http_cache()->SetClockForTesting(&clock);
12783 cache.network_layer()->SetClock(&clock);
12784 clock.Advance(base::Seconds(10));
12785
12786 ScopedMockTransaction stale_while_revalidate_transaction(
12787 kSimpleGET_Transaction);
12788 stale_while_revalidate_transaction.load_flags |=
12789 LOAD_SUPPORT_ASYNC_REVALIDATION;
12790 stale_while_revalidate_transaction.response_headers =
12791 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12792 "Age: 10801\n"
12793 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12794
12795 // Write to the cache.
12796 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12797
12798 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12799
12800 // Send the request again and check that it is not sent to the network again.
12801 HttpResponseInfo response_info;
12802 RunTransactionTestWithResponseInfo(
12803 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12804
12805 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12806 EXPECT_TRUE(response_info.async_revalidation_requested);
12807 EXPECT_FALSE(response_info.stale_revalidate_timeout.is_null());
12808
12809 // Move forward in time such that the stale response is no longer valid.
12810 clock.SetNow(response_info.stale_revalidate_timeout);
12811 clock.Advance(base::Seconds(1));
12812
12813 RunTransactionTestWithResponseInfo(
12814 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12815
12816 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12817 EXPECT_FALSE(response_info.async_revalidation_requested);
12818 }
12819
TEST_F(HttpCacheTest,StaleContentUsedWhenLoadFlagSetAndUsable)12820 TEST_F(HttpCacheTest, StaleContentUsedWhenLoadFlagSetAndUsable) {
12821 MockHttpCache cache;
12822 base::SimpleTestClock clock;
12823 cache.http_cache()->SetClockForTesting(&clock);
12824 cache.network_layer()->SetClock(&clock);
12825 clock.Advance(base::Seconds(10));
12826
12827 ScopedMockTransaction stale_while_revalidate_transaction(
12828 kSimpleGET_Transaction);
12829 stale_while_revalidate_transaction.load_flags |=
12830 LOAD_SUPPORT_ASYNC_REVALIDATION;
12831 stale_while_revalidate_transaction.response_headers =
12832 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12833 "Age: 10801\n"
12834 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12835
12836 // Write to the cache.
12837 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12838
12839 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12840
12841 // Send the request again and check that it is not sent to the network again.
12842 HttpResponseInfo response_info;
12843 RunTransactionTestWithResponseInfo(
12844 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12845
12846 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12847 EXPECT_TRUE(response_info.async_revalidation_requested);
12848 EXPECT_FALSE(response_info.stale_revalidate_timeout.is_null());
12849 base::Time revalidation_timeout = response_info.stale_revalidate_timeout;
12850 clock.Advance(base::Seconds(1));
12851 EXPECT_TRUE(clock.Now() < revalidation_timeout);
12852
12853 // Fetch the resource again inside the revalidation timeout window.
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 // Expect that the original revalidation timeout hasn't changed.
12861 EXPECT_TRUE(revalidation_timeout == response_info.stale_revalidate_timeout);
12862
12863 // mask of async revalidation flag.
12864 stale_while_revalidate_transaction.load_flags &=
12865 ~LOAD_SUPPORT_ASYNC_REVALIDATION;
12866 stale_while_revalidate_transaction.status = "HTTP/1.1 304 Not Modified";
12867 // Write 304 to the cache.
12868 RunTransactionTestWithResponseInfo(
12869 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12870
12871 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12872 EXPECT_FALSE(response_info.async_revalidation_requested);
12873 EXPECT_TRUE(response_info.stale_revalidate_timeout.is_null());
12874 }
12875
TEST_F(HttpCacheTest,StaleContentNotUsedWhenUnusable)12876 TEST_F(HttpCacheTest, StaleContentNotUsedWhenUnusable) {
12877 MockHttpCache cache;
12878
12879 ScopedMockTransaction stale_while_revalidate_transaction(
12880 kSimpleGET_Transaction);
12881 stale_while_revalidate_transaction.load_flags |=
12882 LOAD_SUPPORT_ASYNC_REVALIDATION;
12883 stale_while_revalidate_transaction.response_headers =
12884 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12885 "Age: 10801\n"
12886 "Cache-Control: max-age=0,stale-while-revalidate=1800\n";
12887
12888 // Write to the cache.
12889 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12890
12891 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12892
12893 // Send the request again and check that it is sent to the network again.
12894 HttpResponseInfo response_info;
12895 RunTransactionTestWithResponseInfo(
12896 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12897
12898 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12899 EXPECT_FALSE(response_info.async_revalidation_requested);
12900 }
12901
TEST_F(HttpCacheTest,StaleContentWriteError)12902 TEST_F(HttpCacheTest, StaleContentWriteError) {
12903 MockHttpCache cache;
12904 base::SimpleTestClock clock;
12905 cache.http_cache()->SetClockForTesting(&clock);
12906 cache.network_layer()->SetClock(&clock);
12907 clock.Advance(base::Seconds(10));
12908
12909 ScopedMockTransaction stale_while_revalidate_transaction(
12910 kSimpleGET_Transaction);
12911 stale_while_revalidate_transaction.load_flags |=
12912 LOAD_SUPPORT_ASYNC_REVALIDATION;
12913 stale_while_revalidate_transaction.response_headers =
12914 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12915 "Age: 10801\n"
12916 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12917
12918 // Write to the cache.
12919 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12920
12921 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12922
12923 // Send the request again but inject a write fault. Should still work
12924 // (and not dereference any null pointers).
12925 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_WRITE);
12926 HttpResponseInfo response_info;
12927 RunTransactionTestWithResponseInfo(
12928 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12929
12930 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12931 }
12932
12933 // Tests that we allow multiple simultaneous, non-overlapping transactions to
12934 // take place on a sparse entry.
TEST_F(HttpCacheTest,RangeGET_MultipleRequests)12935 TEST_F(HttpCacheTest, RangeGET_MultipleRequests) {
12936 MockHttpCache cache;
12937
12938 // Create a transaction for bytes 0-9.
12939 MockHttpRequest request(kRangeGET_TransactionOK);
12940 MockTransaction transaction(kRangeGET_TransactionOK);
12941 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
12942 transaction.data = "rg: 00-09 ";
12943 AddMockTransaction(&transaction);
12944
12945 TestCompletionCallback callback;
12946 std::unique_ptr<HttpTransaction> trans;
12947 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
12948 EXPECT_THAT(rv, IsOk());
12949 ASSERT_TRUE(trans.get());
12950
12951 // Start our transaction.
12952 trans->Start(&request, callback.callback(), NetLogWithSource());
12953
12954 // A second transaction on a different part of the file (the default
12955 // kRangeGET_TransactionOK requests 40-49) should not be blocked by
12956 // the already pending transaction.
12957 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
12958
12959 // Let the first transaction complete.
12960 callback.WaitForResult();
12961
12962 RemoveMockTransaction(&transaction);
12963 }
12964
12965 // Verify that a range request can be satisfied from a completely cached
12966 // resource with the LOAD_ONLY_FROM_CACHE flag set. Currently it's not
12967 // implemented so it returns ERR_CACHE_MISS. See also
12968 // HttpCacheTest.RangeGET_OK_LoadOnlyFromCache.
12969 // TODO(ricea): Update this test if it is implemented in future.
TEST_F(HttpCacheTest,RangeGET_Previous200_LoadOnlyFromCache)12970 TEST_F(HttpCacheTest, RangeGET_Previous200_LoadOnlyFromCache) {
12971 MockHttpCache cache;
12972
12973 // Store the whole thing with status 200.
12974 MockTransaction transaction(kETagGET_Transaction);
12975 transaction.url = kRangeGET_TransactionOK.url;
12976 transaction.data = kFullRangeData;
12977 AddMockTransaction(&transaction);
12978 RunTransactionTest(cache.http_cache(), transaction);
12979 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12980 EXPECT_EQ(0, cache.disk_cache()->open_count());
12981 EXPECT_EQ(1, cache.disk_cache()->create_count());
12982
12983 RemoveMockTransaction(&transaction);
12984 AddMockTransaction(&kRangeGET_TransactionOK);
12985
12986 // Now see that we use the stored entry.
12987 MockTransaction transaction2(kRangeGET_TransactionOK);
12988 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE;
12989 MockHttpRequest request(transaction2);
12990 TestCompletionCallback callback;
12991
12992 std::unique_ptr<HttpTransaction> trans;
12993 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
12994 EXPECT_THAT(rv, IsOk());
12995 ASSERT_TRUE(trans);
12996
12997 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12998 if (rv == ERR_IO_PENDING) {
12999 rv = callback.WaitForResult();
13000 }
13001 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
13002
13003 EXPECT_EQ(1, cache.network_layer()->transaction_count());
13004 EXPECT_EQ(1, cache.disk_cache()->open_count());
13005 EXPECT_EQ(1, cache.disk_cache()->create_count());
13006 }
13007
13008 // Makes sure that a request stops using the cache when the response headers
13009 // with "Cache-Control: no-store" arrives. That means that another request for
13010 // the same URL can be processed before the response body of the original
13011 // request arrives.
TEST_F(HttpCacheTest,NoStoreResponseShouldNotBlockFollowingRequests)13012 TEST_F(HttpCacheTest, NoStoreResponseShouldNotBlockFollowingRequests) {
13013 MockHttpCache cache;
13014 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
13015 mock_transaction.response_headers = "Cache-Control: no-store\n";
13016 MockHttpRequest request(mock_transaction);
13017
13018 auto first = std::make_unique<Context>();
13019 first->result = cache.CreateTransaction(&first->trans);
13020 ASSERT_THAT(first->result, IsOk());
13021 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
13022 first->result = first->trans->Start(&request, first->callback.callback(),
13023 NetLogWithSource());
13024 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, first->trans->GetLoadState());
13025
13026 base::RunLoop().RunUntilIdle();
13027 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
13028 ASSERT_TRUE(first->trans->GetResponseInfo());
13029 EXPECT_TRUE(first->trans->GetResponseInfo()->headers->HasHeaderValue(
13030 "Cache-Control", "no-store"));
13031 // Here we have read the response header but not read the response body yet.
13032
13033 // Let us create the second (read) transaction.
13034 auto second = std::make_unique<Context>();
13035 second->result = cache.CreateTransaction(&second->trans);
13036 ASSERT_THAT(second->result, IsOk());
13037 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
13038 second->result = second->trans->Start(&request, second->callback.callback(),
13039 NetLogWithSource());
13040
13041 // Here the second transaction proceeds without reading the first body.
13042 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, second->trans->GetLoadState());
13043 base::RunLoop().RunUntilIdle();
13044 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
13045 ASSERT_TRUE(second->trans->GetResponseInfo());
13046 EXPECT_TRUE(second->trans->GetResponseInfo()->headers->HasHeaderValue(
13047 "Cache-Control", "no-store"));
13048 ReadAndVerifyTransaction(second->trans.get(), kSimpleGET_Transaction);
13049 }
13050
13051 // Tests that serving a response entirely from cache replays the previous
13052 // SSLInfo.
TEST_F(HttpCacheTest,CachePreservesSSLInfo)13053 TEST_F(HttpCacheTest, CachePreservesSSLInfo) {
13054 static const uint16_t kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f;
13055 int status = 0;
13056 SSLConnectionStatusSetCipherSuite(kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
13057 &status);
13058 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2, &status);
13059
13060 scoped_refptr<X509Certificate> cert =
13061 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13062
13063 MockHttpCache cache;
13064
13065 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13066 transaction.cert = cert;
13067 transaction.ssl_connection_status = status;
13068
13069 // Fetch the resource.
13070 HttpResponseInfo response_info;
13071 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13072 &response_info);
13073
13074 // The request should have hit the network and a cache entry created.
13075 EXPECT_EQ(1, cache.network_layer()->transaction_count());
13076 EXPECT_EQ(0, cache.disk_cache()->open_count());
13077 EXPECT_EQ(1, cache.disk_cache()->create_count());
13078
13079 // The expected SSL state was reported.
13080 EXPECT_EQ(transaction.ssl_connection_status,
13081 response_info.ssl_info.connection_status);
13082 EXPECT_TRUE(cert->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13083
13084 // Fetch the resource again.
13085 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13086 &response_info);
13087
13088 // The request should have been reused without hitting the network.
13089 EXPECT_EQ(1, cache.network_layer()->transaction_count());
13090 EXPECT_EQ(1, cache.disk_cache()->open_count());
13091 EXPECT_EQ(1, cache.disk_cache()->create_count());
13092
13093 // The SSL state was preserved.
13094 EXPECT_EQ(status, response_info.ssl_info.connection_status);
13095 EXPECT_TRUE(cert->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13096 }
13097
13098 // Tests that SSLInfo gets updated when revalidating a cached response.
TEST_F(HttpCacheTest,RevalidationUpdatesSSLInfo)13099 TEST_F(HttpCacheTest, RevalidationUpdatesSSLInfo) {
13100 static const uint16_t kTLS_RSA_WITH_RC4_128_MD5 = 0x0004;
13101 static const uint16_t kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f;
13102
13103 int status1 = 0;
13104 SSLConnectionStatusSetCipherSuite(kTLS_RSA_WITH_RC4_128_MD5, &status1);
13105 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1, &status1);
13106 int status2 = 0;
13107 SSLConnectionStatusSetCipherSuite(kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
13108 &status2);
13109 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2, &status2);
13110
13111 scoped_refptr<X509Certificate> cert1 =
13112 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
13113 scoped_refptr<X509Certificate> cert2 =
13114 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
13115
13116 MockHttpCache cache;
13117
13118 ScopedMockTransaction transaction(kTypicalGET_Transaction);
13119 transaction.cert = cert1;
13120 transaction.ssl_connection_status = status1;
13121
13122 // Fetch the resource.
13123 HttpResponseInfo response_info;
13124 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13125 &response_info);
13126
13127 // The request should have hit the network and a cache entry created.
13128 EXPECT_EQ(1, cache.network_layer()->transaction_count());
13129 EXPECT_EQ(0, cache.disk_cache()->open_count());
13130 EXPECT_EQ(1, cache.disk_cache()->create_count());
13131 EXPECT_FALSE(response_info.was_cached);
13132
13133 // The expected SSL state was reported.
13134 EXPECT_EQ(status1, response_info.ssl_info.connection_status);
13135 EXPECT_TRUE(cert1->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13136
13137 // The server deploys a more modern configuration but reports 304 on the
13138 // revalidation attempt.
13139 transaction.status = "HTTP/1.1 304 Not Modified";
13140 transaction.cert = cert2;
13141 transaction.ssl_connection_status = status2;
13142
13143 // Fetch the resource again, forcing a revalidation.
13144 transaction.request_headers = "Cache-Control: max-age=0\r\n";
13145 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13146 &response_info);
13147
13148 // The request should have been successfully revalidated.
13149 EXPECT_EQ(2, cache.network_layer()->transaction_count());
13150 EXPECT_EQ(1, cache.disk_cache()->open_count());
13151 EXPECT_EQ(1, cache.disk_cache()->create_count());
13152 EXPECT_TRUE(response_info.was_cached);
13153
13154 // The new SSL state is reported.
13155 EXPECT_EQ(status2, response_info.ssl_info.connection_status);
13156 EXPECT_TRUE(cert2->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13157 }
13158
TEST_F(HttpCacheTest,CacheEntryStatusOther)13159 TEST_F(HttpCacheTest, CacheEntryStatusOther) {
13160 MockHttpCache cache;
13161
13162 HttpResponseInfo response_info;
13163 RunTransactionTestWithResponseInfo(cache.http_cache(), kRangeGET_Transaction,
13164 &response_info);
13165
13166 EXPECT_FALSE(response_info.was_cached);
13167 EXPECT_TRUE(response_info.network_accessed);
13168 EXPECT_EQ(CacheEntryStatus::ENTRY_OTHER, response_info.cache_entry_status);
13169 }
13170
TEST_F(HttpCacheTest,CacheEntryStatusNotInCache)13171 TEST_F(HttpCacheTest, CacheEntryStatusNotInCache) {
13172 MockHttpCache cache;
13173
13174 HttpResponseInfo response_info;
13175 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
13176 &response_info);
13177
13178 EXPECT_FALSE(response_info.was_cached);
13179 EXPECT_TRUE(response_info.network_accessed);
13180 EXPECT_EQ(CacheEntryStatus::ENTRY_NOT_IN_CACHE,
13181 response_info.cache_entry_status);
13182 }
13183
TEST_F(HttpCacheTest,CacheEntryStatusUsed)13184 TEST_F(HttpCacheTest, CacheEntryStatusUsed) {
13185 MockHttpCache cache;
13186 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
13187
13188 HttpResponseInfo response_info;
13189 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
13190 &response_info);
13191
13192 EXPECT_TRUE(response_info.was_cached);
13193 EXPECT_FALSE(response_info.network_accessed);
13194 EXPECT_EQ(CacheEntryStatus::ENTRY_USED, response_info.cache_entry_status);
13195 }
13196
TEST_F(HttpCacheTest,CacheEntryStatusValidated)13197 TEST_F(HttpCacheTest, CacheEntryStatusValidated) {
13198 MockHttpCache cache;
13199 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
13200
13201 ScopedMockTransaction still_valid(kETagGET_Transaction);
13202 still_valid.load_flags = LOAD_VALIDATE_CACHE; // Force a validation.
13203 still_valid.handler = ETagGet_ConditionalRequest_Handler;
13204
13205 HttpResponseInfo response_info;
13206 RunTransactionTestWithResponseInfo(cache.http_cache(), still_valid,
13207 &response_info);
13208
13209 EXPECT_TRUE(response_info.was_cached);
13210 EXPECT_TRUE(response_info.network_accessed);
13211 EXPECT_EQ(CacheEntryStatus::ENTRY_VALIDATED,
13212 response_info.cache_entry_status);
13213 }
13214
TEST_F(HttpCacheTest,CacheEntryStatusUpdated)13215 TEST_F(HttpCacheTest, CacheEntryStatusUpdated) {
13216 MockHttpCache cache;
13217 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
13218
13219 ScopedMockTransaction update(kETagGET_Transaction);
13220 update.load_flags = LOAD_VALIDATE_CACHE; // Force a validation.
13221
13222 HttpResponseInfo response_info;
13223 RunTransactionTestWithResponseInfo(cache.http_cache(), update,
13224 &response_info);
13225
13226 EXPECT_FALSE(response_info.was_cached);
13227 EXPECT_TRUE(response_info.network_accessed);
13228 EXPECT_EQ(CacheEntryStatus::ENTRY_UPDATED, response_info.cache_entry_status);
13229 }
13230
TEST_F(HttpCacheTest,CacheEntryStatusCantConditionalize)13231 TEST_F(HttpCacheTest, CacheEntryStatusCantConditionalize) {
13232 MockHttpCache cache;
13233 cache.FailConditionalizations();
13234 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
13235
13236 HttpResponseInfo response_info;
13237 RunTransactionTestWithResponseInfo(cache.http_cache(),
13238 kTypicalGET_Transaction, &response_info);
13239
13240 EXPECT_FALSE(response_info.was_cached);
13241 EXPECT_TRUE(response_info.network_accessed);
13242 EXPECT_EQ(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE,
13243 response_info.cache_entry_status);
13244 }
13245
TEST_F(HttpSplitCacheKeyTest,GetResourceURLFromHttpCacheKey)13246 TEST_F(HttpSplitCacheKeyTest, GetResourceURLFromHttpCacheKey) {
13247 base::test::ScopedFeatureList feature_list;
13248 feature_list.InitAndEnableFeature(
13249 net::features::kSplitCacheByNetworkIsolationKey);
13250 MockHttpCache cache;
13251 std::string urls[] = {"http://www.a.com/", "https://b.com/example.html",
13252 "http://example.com/Some Path/Some Leaf?some query"};
13253
13254 for (const std::string& url : urls) {
13255 std::string key = ComputeCacheKey(url);
13256 EXPECT_EQ(GURL(url).spec(), HttpCache::GetResourceURLFromHttpCacheKey(key));
13257 }
13258 }
13259
TEST_F(HttpCacheTest,GetResourceURLFromHttpCacheKey)13260 TEST_F(HttpCacheTest, GetResourceURLFromHttpCacheKey) {
13261 const struct {
13262 std::string input;
13263 std::string output;
13264 } kTestCase[] = {
13265 // Valid input:
13266 {"0/0/https://a.com/", "https://a.com/"},
13267 {"0/0/https://a.com/path", "https://a.com/path"},
13268 {"0/0/https://a.com/?query", "https://a.com/?query"},
13269 {"0/0/https://a.com/#fragment", "https://a.com/#fragment"},
13270 {"0/0/_dk_s_ https://a.com/", "https://a.com/"},
13271 {"0/0/_dk_https://a.com https://b.com https://c.com/", "https://c.com/"},
13272 {"0/0/_dk_shttps://a.com https://b.com https://c.com/", "https://c.com/"},
13273
13274 // Invalid input, producing garbage, without crashing.
13275 {"", ""},
13276 {"0/a.com", "0/a.com"},
13277 {"https://a.com/", "a.com/"},
13278 {"0/https://a.com/", "/a.com/"},
13279 };
13280
13281 for (const auto& test : kTestCase) {
13282 EXPECT_EQ(test.output,
13283 HttpCache::GetResourceURLFromHttpCacheKey(test.input));
13284 }
13285 }
13286
13287 class TestCompletionCallbackForHttpCache : public TestCompletionCallbackBase {
13288 public:
13289 TestCompletionCallbackForHttpCache() = default;
13290 ~TestCompletionCallbackForHttpCache() override = default;
13291
callback()13292 CompletionRepeatingCallback callback() {
13293 return base::BindRepeating(&TestCompletionCallbackForHttpCache::SetResult,
13294 base::Unretained(this));
13295 }
13296
results()13297 const std::vector<int>& results() { return results_; }
13298
13299 private:
13300 std::vector<int> results_;
13301
13302 protected:
SetResult(int result)13303 void SetResult(int result) override {
13304 results_.push_back(result);
13305 DidSetResult();
13306 }
13307 };
13308
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByOpen)13309 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByOpen) {
13310 MockHttpCache cache;
13311 TestCompletionCallbackForHttpCache cb;
13312 std::unique_ptr<Transaction> transaction =
13313 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13314
13315 transaction->SetIOCallBackForTest(cb.callback());
13316
13317 // Create the backend here as our direct calls to DoomEntry and OpenEntry
13318 // below require that it exists.
13319 cache.backend();
13320
13321 // Need a mock transaction in order to use some of MockHttpCache's
13322 // functions.
13323 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13324
13325 ActiveEntry* entry1 = nullptr;
13326
13327 cache.disk_cache()->set_force_fail_callback_later(true);
13328
13329 // Queue up our operations.
13330 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13331 ASSERT_EQ(rv, ERR_IO_PENDING);
13332 cache.disk_cache()->set_force_fail_callback_later(false);
13333 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13334 transaction.get());
13335 ASSERT_EQ(rv, ERR_IO_PENDING);
13336
13337 // Wait for all the results to arrive.
13338 cb.GetResult(rv);
13339 ASSERT_EQ(cb.results().size(), 2u);
13340
13341 // Verify that DoomEntry failed correctly.
13342 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13343 // Verify that OpenEntry fails with the same code.
13344 ASSERT_EQ(cb.results()[1], ERR_CACHE_DOOM_FAILURE);
13345 ASSERT_EQ(entry1, nullptr);
13346 }
13347
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByCreate)13348 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByCreate) {
13349 MockHttpCache cache;
13350 TestCompletionCallbackForHttpCache cb;
13351 std::unique_ptr<Transaction> transaction =
13352 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13353
13354 transaction->SetIOCallBackForTest(cb.callback());
13355
13356 // Create the backend here as our direct calls to DoomEntry and CreateEntry
13357 // below require that it exists.
13358 cache.backend();
13359
13360 // Need a mock transaction in order to use some of MockHttpCache's
13361 // functions.
13362 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13363
13364 ActiveEntry* entry1 = nullptr;
13365
13366 cache.disk_cache()->set_force_fail_callback_later(true);
13367
13368 // Queue up our operations.
13369 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13370 ASSERT_EQ(rv, ERR_IO_PENDING);
13371 cache.disk_cache()->set_force_fail_callback_later(false);
13372 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13373 transaction.get());
13374 ASSERT_EQ(rv, ERR_IO_PENDING);
13375
13376 // Wait for all the results to arrive.
13377 cb.GetResult(rv);
13378 ASSERT_EQ(cb.results().size(), 2u);
13379
13380 // Verify that DoomEntry failed correctly.
13381 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13382 // Verify that CreateEntry requests a restart (CACHE_RACE).
13383 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13384 ASSERT_EQ(entry1, nullptr);
13385 }
13386
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByDoom)13387 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByDoom) {
13388 MockHttpCache cache;
13389 TestCompletionCallbackForHttpCache cb;
13390 std::unique_ptr<Transaction> transaction =
13391 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13392
13393 transaction->SetIOCallBackForTest(cb.callback());
13394
13395 // Create the backend here as our direct calls to DoomEntry below require that
13396 // it exists.
13397 cache.backend();
13398
13399 // Need a mock transaction in order to use some of MockHttpCache's
13400 // functions.
13401 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13402
13403 cache.disk_cache()->set_force_fail_callback_later(true);
13404
13405 // Queue up our operations.
13406 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13407 ASSERT_EQ(rv, ERR_IO_PENDING);
13408 cache.disk_cache()->set_force_fail_callback_later(false);
13409 rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13410 ASSERT_EQ(rv, ERR_IO_PENDING);
13411
13412 // Wait for all the results to arrive.
13413 cb.GetResult(rv);
13414 ASSERT_EQ(cb.results().size(), 2u);
13415
13416 // Verify that DoomEntry failed correctly.
13417 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13418 // Verify that the second DoomEntry requests a restart (CACHE_RACE).
13419 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13420 }
13421
TEST_F(HttpCacheIOCallbackTest,FailedOpenFollowedByCreate)13422 TEST_F(HttpCacheIOCallbackTest, FailedOpenFollowedByCreate) {
13423 MockHttpCache cache;
13424 TestCompletionCallbackForHttpCache cb;
13425 std::unique_ptr<Transaction> transaction =
13426 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13427
13428 transaction->SetIOCallBackForTest(cb.callback());
13429
13430 // Create the backend here as our direct calls to OpenEntry and CreateEntry
13431 // below require that it exists.
13432 cache.backend();
13433
13434 // Need a mock transaction in order to use some of MockHttpCache's
13435 // functions.
13436 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13437
13438 ActiveEntry* entry1 = nullptr;
13439 ActiveEntry* entry2 = nullptr;
13440
13441 cache.disk_cache()->set_force_fail_callback_later(true);
13442
13443 // Queue up our operations.
13444 int rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13445 transaction.get());
13446 ASSERT_EQ(rv, ERR_IO_PENDING);
13447 cache.disk_cache()->set_force_fail_callback_later(false);
13448 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13449 transaction.get());
13450 ASSERT_EQ(rv, ERR_IO_PENDING);
13451
13452 // Wait for all the results to arrive.
13453 cb.GetResult(rv);
13454 ASSERT_EQ(cb.results().size(), 2u);
13455
13456 // Verify that OpenEntry failed correctly.
13457 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_FAILURE);
13458 ASSERT_EQ(entry1, nullptr);
13459 // Verify that the CreateEntry requests a restart (CACHE_RACE).
13460 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13461 ASSERT_EQ(entry2, nullptr);
13462 }
13463
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByOpen)13464 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByOpen) {
13465 MockHttpCache cache;
13466 TestCompletionCallbackForHttpCache cb;
13467 std::unique_ptr<Transaction> transaction =
13468 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13469
13470 transaction->SetIOCallBackForTest(cb.callback());
13471
13472 // Create the backend here as our direct calls to CreateEntry and OpenEntry
13473 // below require that it exists.
13474 cache.backend();
13475
13476 // Need a mock transaction in order to use some of MockHttpCache's
13477 // functions.
13478 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13479
13480 ActiveEntry* entry1 = nullptr;
13481 ActiveEntry* entry2 = nullptr;
13482
13483 cache.disk_cache()->set_force_fail_callback_later(true);
13484
13485 // Queue up our operations.
13486 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13487 transaction.get());
13488 ASSERT_EQ(rv, ERR_IO_PENDING);
13489 cache.disk_cache()->set_force_fail_callback_later(false);
13490 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry2,
13491 transaction.get());
13492 ASSERT_EQ(rv, ERR_IO_PENDING);
13493
13494 // Wait for all the results to arrive.
13495 cb.GetResult(rv);
13496 ASSERT_EQ(cb.results().size(), 2u);
13497
13498 // Verify that CreateEntry failed correctly.
13499 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13500 ASSERT_EQ(entry1, nullptr);
13501 // Verify that the OpenEntry requests a restart (CACHE_RACE).
13502 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13503 ASSERT_EQ(entry2, nullptr);
13504 }
13505
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByCreate)13506 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByCreate) {
13507 MockHttpCache cache;
13508 TestCompletionCallbackForHttpCache cb;
13509 std::unique_ptr<Transaction> transaction =
13510 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13511
13512 transaction->SetIOCallBackForTest(cb.callback());
13513
13514 // Create the backend here as our direct calls to CreateEntry below require
13515 // that it exists.
13516 cache.backend();
13517
13518 // Need a mock transaction in order to use some of MockHttpCache's
13519 // functions.
13520 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13521
13522 ActiveEntry* entry1 = nullptr;
13523 ActiveEntry* entry2 = nullptr;
13524
13525 cache.disk_cache()->set_force_fail_callback_later(true);
13526
13527 // Queue up our operations.
13528 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13529 transaction.get());
13530 ASSERT_EQ(rv, ERR_IO_PENDING);
13531 cache.disk_cache()->set_force_fail_callback_later(false);
13532 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13533 transaction.get());
13534 ASSERT_EQ(rv, ERR_IO_PENDING);
13535
13536 // Wait for all the results to arrive.
13537 cb.GetResult(rv);
13538 ASSERT_EQ(cb.results().size(), 2u);
13539
13540 // Verify the CreateEntry(s) failed.
13541 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13542 ASSERT_EQ(entry1, nullptr);
13543 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13544 ASSERT_EQ(entry2, nullptr);
13545 }
13546
TEST_F(HttpCacheIOCallbackTest,CreateFollowedByCreate)13547 TEST_F(HttpCacheIOCallbackTest, CreateFollowedByCreate) {
13548 MockHttpCache cache;
13549 TestCompletionCallbackForHttpCache cb;
13550 std::unique_ptr<Transaction> transaction =
13551 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13552
13553 transaction->SetIOCallBackForTest(cb.callback());
13554
13555 // Create the backend here as our direct calls to CreateEntry below require
13556 // that it exists.
13557 cache.backend();
13558
13559 // Need a mock transaction in order to use some of MockHttpCache's
13560 // functions.
13561 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13562
13563 ActiveEntry* entry1 = nullptr;
13564 ActiveEntry* entry2 = nullptr;
13565
13566 // Queue up our operations.
13567 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13568 transaction.get());
13569 ASSERT_EQ(rv, ERR_IO_PENDING);
13570 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13571 transaction.get());
13572 ASSERT_EQ(rv, ERR_IO_PENDING);
13573
13574 // Wait for all the results to arrive.
13575 cb.GetResult(rv);
13576 ASSERT_EQ(cb.results().size(), 2u);
13577
13578 // Verify that the first CreateEntry succeeded.
13579 ASSERT_EQ(cb.results()[0], OK);
13580 ASSERT_NE(entry1, nullptr);
13581 // Verify that the second CreateEntry failed.
13582 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13583 ASSERT_EQ(entry2, nullptr);
13584 }
13585
TEST_F(HttpCacheIOCallbackTest,OperationFollowedByDoom)13586 TEST_F(HttpCacheIOCallbackTest, OperationFollowedByDoom) {
13587 MockHttpCache cache;
13588 TestCompletionCallbackForHttpCache cb;
13589 std::unique_ptr<Transaction> transaction =
13590 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13591
13592 transaction->SetIOCallBackForTest(cb.callback());
13593
13594 // Create the backend here as our direct calls to CreateEntry and DoomEntry
13595 // below require that it exists.
13596 cache.backend();
13597
13598 // Need a mock transaction in order to use some of MockHttpCache's
13599 // functions.
13600 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13601
13602 ActiveEntry* entry1 = nullptr;
13603
13604 // Queue up our operations.
13605 // For this test all we need is some operation followed by a doom, a create
13606 // fulfills that requirement.
13607 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13608 transaction.get());
13609 ASSERT_EQ(rv, ERR_IO_PENDING);
13610 rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13611 ASSERT_EQ(rv, ERR_IO_PENDING);
13612
13613 // Wait for all the results to arrive.
13614 cb.GetResult(rv);
13615 ASSERT_EQ(cb.results().size(), 2u);
13616
13617 // Verify that the CreateEntry succeeded.
13618 ASSERT_EQ(cb.results()[0], OK);
13619 // Verify that the DoomEntry requests a restart (CACHE_RACE).
13620 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13621 }
13622
TEST_F(HttpCacheIOCallbackTest,CreateFollowedByOpenOrCreate)13623 TEST_F(HttpCacheIOCallbackTest, CreateFollowedByOpenOrCreate) {
13624 MockHttpCache cache;
13625 TestCompletionCallbackForHttpCache cb;
13626 std::unique_ptr<Transaction> transaction =
13627 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13628
13629 transaction->SetIOCallBackForTest(cb.callback());
13630
13631 // Create the backend here as our direct calls to CreateEntry and
13632 // OpenOrCreateEntry below require that it exists.
13633 cache.backend();
13634
13635 // Need a mock transaction in order to use some of MockHttpCache's
13636 // functions.
13637 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13638
13639 ActiveEntry* entry1 = nullptr;
13640 ActiveEntry* entry2 = nullptr;
13641
13642 // Queue up our operations.
13643 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13644 transaction.get());
13645 ASSERT_EQ(rv, ERR_IO_PENDING);
13646 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13647 transaction.get());
13648 ASSERT_EQ(rv, ERR_IO_PENDING);
13649
13650 // Wait for all the results to arrive.
13651 cb.GetResult(rv);
13652 ASSERT_EQ(cb.results().size(), 2u);
13653
13654 // Verify that the CreateEntry succeeded.
13655 ASSERT_EQ(cb.results()[0], OK);
13656 ASSERT_NE(entry1, nullptr);
13657 // Verify that OpenOrCreateEntry succeeded.
13658 ASSERT_EQ(cb.results()[1], OK);
13659 ASSERT_NE(entry2, nullptr);
13660 ASSERT_EQ(entry1->disk_entry, entry2->disk_entry);
13661 }
13662
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByOpenOrCreate)13663 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByOpenOrCreate) {
13664 MockHttpCache cache;
13665 TestCompletionCallbackForHttpCache cb;
13666 std::unique_ptr<Transaction> transaction =
13667 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13668
13669 transaction->SetIOCallBackForTest(cb.callback());
13670
13671 // Create the backend here as our direct calls to CreateEntry and
13672 // OpenOrCreateEntry below require that it exists.
13673 cache.backend();
13674
13675 // Need a mock transaction in order to use some of MockHttpCache's
13676 // functions.
13677 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13678
13679 ActiveEntry* entry1 = nullptr;
13680 ActiveEntry* entry2 = nullptr;
13681
13682 cache.disk_cache()->set_force_fail_callback_later(true);
13683
13684 // Queue up our operations.
13685 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13686 transaction.get());
13687 ASSERT_EQ(rv, ERR_IO_PENDING);
13688 cache.disk_cache()->set_force_fail_callback_later(false);
13689 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13690 transaction.get());
13691 ASSERT_EQ(rv, ERR_IO_PENDING);
13692
13693 // Wait for all the results to arrive.
13694 cb.GetResult(rv);
13695 ASSERT_EQ(cb.results().size(), 2u);
13696
13697 // Verify that CreateEntry failed correctly.
13698 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13699 ASSERT_EQ(entry1, nullptr);
13700 // Verify that the OpenOrCreateEntry requests a restart (CACHE_RACE).
13701 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13702 ASSERT_EQ(entry2, nullptr);
13703 }
13704
TEST_F(HttpCacheIOCallbackTest,OpenFollowedByOpenOrCreate)13705 TEST_F(HttpCacheIOCallbackTest, OpenFollowedByOpenOrCreate) {
13706 MockHttpCache cache;
13707 TestCompletionCallbackForHttpCache cb;
13708 std::unique_ptr<Transaction> transaction =
13709 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13710
13711 transaction->SetIOCallBackForTest(cb.callback());
13712
13713 // Create the backend here as our direct calls to OpenEntry and
13714 // OpenOrCreateEntry below require that it exists.
13715 cache.backend();
13716
13717 // Need a mock transaction in order to use some of MockHttpCache's
13718 // functions.
13719 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13720
13721 ActiveEntry* entry0 = nullptr;
13722 ActiveEntry* entry1 = nullptr;
13723 ActiveEntry* entry2 = nullptr;
13724
13725 // First need to create and entry so we can open it.
13726 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry0,
13727 transaction.get());
13728 ASSERT_EQ(rv, ERR_IO_PENDING);
13729 cb.GetResult(rv);
13730 ASSERT_EQ(cb.results().size(), static_cast<size_t>(1));
13731 ASSERT_EQ(cb.results()[0], OK);
13732 ASSERT_NE(entry0, nullptr);
13733 // Manually DeactivateEntry() because OpenEntry() fails if there is an
13734 // existing active entry.
13735 DeactivateEntry(cache.http_cache(), entry0);
13736
13737 // Queue up our operations.
13738 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13739 transaction.get());
13740 ASSERT_EQ(rv, ERR_IO_PENDING);
13741 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13742 transaction.get());
13743 ASSERT_EQ(rv, ERR_IO_PENDING);
13744
13745 // Wait for all the results to arrive.
13746 cb.GetResult(rv);
13747 ASSERT_EQ(cb.results().size(), 3u);
13748
13749 // Verify that the OpenEntry succeeded.
13750 ASSERT_EQ(cb.results()[1], OK);
13751 ASSERT_NE(entry1, nullptr);
13752 // Verify that OpenOrCreateEntry succeeded.
13753 ASSERT_EQ(cb.results()[2], OK);
13754 ASSERT_NE(entry2, nullptr);
13755 ASSERT_EQ(entry1->disk_entry, entry2->disk_entry);
13756 }
13757
TEST_F(HttpCacheIOCallbackTest,FailedOpenFollowedByOpenOrCreate)13758 TEST_F(HttpCacheIOCallbackTest, FailedOpenFollowedByOpenOrCreate) {
13759 MockHttpCache cache;
13760 TestCompletionCallbackForHttpCache cb;
13761 std::unique_ptr<Transaction> transaction =
13762 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13763
13764 transaction->SetIOCallBackForTest(cb.callback());
13765
13766 // Create the backend here as our direct calls to OpenEntry and
13767 // OpenOrCreateEntry below require that it exists.
13768 cache.backend();
13769
13770 // Need a mock transaction in order to use some of MockHttpCache's
13771 // functions.
13772 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13773
13774 ActiveEntry* entry1 = nullptr;
13775 ActiveEntry* entry2 = nullptr;
13776
13777 cache.disk_cache()->set_force_fail_callback_later(true);
13778
13779 // Queue up our operations.
13780 int rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13781 transaction.get());
13782 ASSERT_EQ(rv, ERR_IO_PENDING);
13783 cache.disk_cache()->set_force_fail_callback_later(false);
13784 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13785 transaction.get());
13786 ASSERT_EQ(rv, ERR_IO_PENDING);
13787
13788 // Wait for all the results to arrive.
13789 cb.GetResult(rv);
13790 ASSERT_EQ(cb.results().size(), 2u);
13791
13792 // Verify that OpenEntry failed correctly.
13793 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_FAILURE);
13794 ASSERT_EQ(entry1, nullptr);
13795 // Verify that the OpenOrCreateEntry requests a restart (CACHE_RACE).
13796 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13797 ASSERT_EQ(entry2, nullptr);
13798 }
13799
TEST_F(HttpCacheIOCallbackTest,OpenOrCreateFollowedByCreate)13800 TEST_F(HttpCacheIOCallbackTest, OpenOrCreateFollowedByCreate) {
13801 MockHttpCache cache;
13802 TestCompletionCallbackForHttpCache cb;
13803 std::unique_ptr<Transaction> transaction =
13804 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13805
13806 transaction->SetIOCallBackForTest(cb.callback());
13807
13808 // Create the backend here as our direct calls to OpenOrCreateEntry and
13809 // CreateEntry below require that it exists.
13810 cache.backend();
13811
13812 // Need a mock transaction in order to use some of MockHttpCache's
13813 // functions.
13814 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13815
13816 ActiveEntry* entry1 = nullptr;
13817 ActiveEntry* entry2 = nullptr;
13818
13819 // Queue up our operations.
13820 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13821 transaction.get());
13822 ASSERT_EQ(rv, ERR_IO_PENDING);
13823 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13824 transaction.get());
13825 ASSERT_EQ(rv, ERR_IO_PENDING);
13826
13827 // Wait for all the results to arrive.
13828 cb.GetResult(rv);
13829 ASSERT_EQ(cb.results().size(), 2u);
13830
13831 // Verify that the OpenOrCreateEntry succeeded.
13832 ASSERT_EQ(cb.results()[0], OK);
13833 ASSERT_NE(entry1, nullptr);
13834 // Verify that CreateEntry failed.
13835 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13836 ASSERT_EQ(entry2, nullptr);
13837 }
13838
TEST_F(HttpCacheIOCallbackTest,OpenOrCreateFollowedByOpenOrCreate)13839 TEST_F(HttpCacheIOCallbackTest, OpenOrCreateFollowedByOpenOrCreate) {
13840 MockHttpCache cache;
13841 TestCompletionCallbackForHttpCache cb;
13842 std::unique_ptr<Transaction> transaction =
13843 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13844
13845 transaction->SetIOCallBackForTest(cb.callback());
13846
13847 // Create the backend here as our direct calls to OpenOrCreateEntry below
13848 // require that it exists.
13849 cache.backend();
13850
13851 // Need a mock transaction in order to use some of MockHttpCache's
13852 // functions.
13853 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13854
13855 ActiveEntry* entry1 = nullptr;
13856 ActiveEntry* entry2 = nullptr;
13857
13858 // Queue up our operations.
13859 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13860 transaction.get());
13861 ASSERT_EQ(rv, ERR_IO_PENDING);
13862 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13863 transaction.get());
13864 ASSERT_EQ(rv, ERR_IO_PENDING);
13865
13866 // Wait for all the results to arrive.
13867 cb.GetResult(rv);
13868 ASSERT_EQ(cb.results().size(), 2u);
13869
13870 // Verify that the OpenOrCreateEntry succeeded.
13871 ASSERT_EQ(cb.results()[0], OK);
13872 ASSERT_NE(entry1, nullptr);
13873 // Verify that the other succeeded.
13874 ASSERT_EQ(cb.results()[1], OK);
13875 ASSERT_NE(entry2, nullptr);
13876 }
13877
TEST_F(HttpCacheIOCallbackTest,FailedOpenOrCreateFollowedByOpenOrCreate)13878 TEST_F(HttpCacheIOCallbackTest, FailedOpenOrCreateFollowedByOpenOrCreate) {
13879 MockHttpCache cache;
13880 TestCompletionCallbackForHttpCache cb;
13881 std::unique_ptr<Transaction> transaction =
13882 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13883
13884 transaction->SetIOCallBackForTest(cb.callback());
13885
13886 // Create the backend here as our direct calls to OpenOrCreateEntry below
13887 // require that it exists.
13888 cache.backend();
13889
13890 // Need a mock transaction in order to use some of MockHttpCache's
13891 // functions.
13892 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13893
13894 ActiveEntry* entry1 = nullptr;
13895 ActiveEntry* entry2 = nullptr;
13896
13897 cache.disk_cache()->set_force_fail_callback_later(true);
13898
13899 // Queue up our operations.
13900 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13901 transaction.get());
13902 ASSERT_EQ(rv, ERR_IO_PENDING);
13903 cache.disk_cache()->set_force_fail_callback_later(false);
13904 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13905 transaction.get());
13906 ASSERT_EQ(rv, ERR_IO_PENDING);
13907
13908 // Wait for all the results to arrive.
13909 cb.GetResult(rv);
13910 ASSERT_EQ(cb.results().size(), 2u);
13911
13912 // Verify that the OpenOrCreateEntry failed.
13913 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_OR_CREATE_FAILURE);
13914 ASSERT_EQ(entry1, nullptr);
13915 // Verify that the other failed.
13916 ASSERT_EQ(cb.results()[1], ERR_CACHE_OPEN_OR_CREATE_FAILURE);
13917 ASSERT_EQ(entry2, nullptr);
13918 }
13919
TEST_F(HttpCacheTest,DnsAliasesNoRevalidation)13920 TEST_F(HttpCacheTest, DnsAliasesNoRevalidation) {
13921 MockHttpCache cache;
13922 HttpResponseInfo response;
13923 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13924 transaction.dns_aliases = {"alias1", "alias2"};
13925
13926 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13927 &response);
13928 EXPECT_FALSE(response.was_cached);
13929 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
13930
13931 // The second request result in a cache hit and the response used without
13932 // revalidation. Set the transaction alias list to empty to verify that the
13933 // cached aliases are being used.
13934 transaction.dns_aliases = {};
13935 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13936 &response);
13937 EXPECT_TRUE(response.was_cached);
13938 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
13939 }
13940
TEST_F(HttpCacheTest,NoDnsAliasesNoRevalidation)13941 TEST_F(HttpCacheTest, NoDnsAliasesNoRevalidation) {
13942 MockHttpCache cache;
13943 HttpResponseInfo response;
13944 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13945 transaction.dns_aliases = {};
13946
13947 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13948 &response);
13949 EXPECT_FALSE(response.was_cached);
13950 EXPECT_TRUE(response.dns_aliases.empty());
13951
13952 // The second request should result in a cache hit and the response used
13953 // without revalidation. Set the transaction alias list to nonempty to verify
13954 // that the cached aliases are being used.
13955 transaction.dns_aliases = {"alias"};
13956 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13957 &response);
13958 EXPECT_TRUE(response.was_cached);
13959 EXPECT_TRUE(response.dns_aliases.empty());
13960 }
13961
TEST_F(HttpCacheTest,DnsAliasesRevalidation)13962 TEST_F(HttpCacheTest, DnsAliasesRevalidation) {
13963 MockHttpCache cache;
13964 HttpResponseInfo response;
13965 ScopedMockTransaction transaction(kTypicalGET_Transaction);
13966 transaction.response_headers =
13967 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
13968 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
13969 "Cache-Control: max-age=0\n";
13970 transaction.dns_aliases = {"alias1", "alias2"};
13971
13972 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13973 &response);
13974 EXPECT_FALSE(response.was_cached);
13975 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
13976
13977 // On the second request, the cache should be revalidated. Change the aliases
13978 // to be sure that the new aliases are being used, and have the response be
13979 // cached for next time.
13980 transaction.response_headers = "Cache-Control: max-age=10000\n";
13981 transaction.dns_aliases = {"alias3", "alias4"};
13982 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13983 &response);
13984 EXPECT_FALSE(response.was_cached);
13985 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias3", "alias4"));
13986
13987 transaction.dns_aliases = {"alias5", "alias6"};
13988 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13989 &response);
13990 EXPECT_TRUE(response.was_cached);
13991 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias3", "alias4"));
13992 }
13993
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldBypass_NoId)13994 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldBypass_NoId) {
13995 MockHttpCache cache;
13996 HttpResponseInfo response;
13997 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13998
13999 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14000 &response);
14001 EXPECT_FALSE(response.was_cached);
14002
14003 transaction.fps_cache_filter = {5};
14004 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14005 &response);
14006 EXPECT_FALSE(response.was_cached);
14007 }
14008
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldBypass_IdTooSmall)14009 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldBypass_IdTooSmall) {
14010 MockHttpCache cache;
14011 HttpResponseInfo response;
14012 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14013 const int64_t kBrowserRunId = 4;
14014 transaction.browser_run_id = {kBrowserRunId};
14015 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14016 &response);
14017 EXPECT_FALSE(response.was_cached);
14018 EXPECT_TRUE(response.browser_run_id.has_value());
14019 EXPECT_EQ(kBrowserRunId, response.browser_run_id.value());
14020
14021 transaction.fps_cache_filter = {5};
14022 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14023 &response);
14024 EXPECT_FALSE(response.was_cached);
14025 }
14026
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldNotBypass)14027 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldNotBypass) {
14028 MockHttpCache cache;
14029 HttpResponseInfo response;
14030 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14031 const int64_t kBrowserRunId = 5;
14032 transaction.browser_run_id = {kBrowserRunId};
14033 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14034 &response);
14035 EXPECT_FALSE(response.was_cached);
14036 EXPECT_TRUE(response.browser_run_id.has_value());
14037 EXPECT_EQ(kBrowserRunId, response.browser_run_id.value());
14038
14039 transaction.fps_cache_filter = {5};
14040 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14041 &response);
14042 EXPECT_TRUE(response.was_cached);
14043 }
14044
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldNotBypass_NoFilter)14045 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldNotBypass_NoFilter) {
14046 MockHttpCache cache;
14047 HttpResponseInfo response;
14048 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14049
14050 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14051 &response);
14052 EXPECT_FALSE(response.was_cached);
14053
14054 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14055 &response);
14056 EXPECT_TRUE(response.was_cached);
14057 }
14058
TEST_F(HttpCacheTest,SecurityHeadersAreCopiedToConditionalizedResponse)14059 TEST_F(HttpCacheTest, SecurityHeadersAreCopiedToConditionalizedResponse) {
14060 MockHttpCache cache;
14061 HttpResponseInfo response;
14062 ScopedMockTransaction transaction(kSimpleGET_Transaction);
14063
14064 static const Response kNetResponse1 = {
14065 "HTTP/1.1 200 OK",
14066 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
14067 "Server: server1\n"
14068 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n"
14069 "Cross-Origin-Resource-Policy: cross-origin\n",
14070 "body1"};
14071
14072 static const Response kNetResponse2 = {
14073 "HTTP/1.1 304 Not Modified",
14074 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
14075 "Server: server2\n"
14076 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
14077 ""};
14078
14079 kNetResponse1.AssignTo(&transaction);
14080 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14081 &response);
14082
14083 // On the second request, the cache is revalidated.
14084 const char kExtraRequestHeaders[] =
14085 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
14086 transaction.request_headers = kExtraRequestHeaders;
14087 kNetResponse2.AssignTo(&transaction);
14088 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
14089 &response);
14090
14091 // Verify that the CORP header was carried over to the response.
14092 std::string response_corp_header;
14093 response.headers->GetNormalizedHeader("Cross-Origin-Resource-Policy",
14094 &response_corp_header);
14095
14096 EXPECT_EQ(304, response.headers->response_code());
14097 EXPECT_EQ("cross-origin", response_corp_header);
14098 }
14099 class CacheTransparencyHttpCacheTest
14100 : public HttpCacheTest_SplitCacheFeatureEnabled {
14101 public:
CacheTransparencyHttpCacheTest()14102 CacheTransparencyHttpCacheTest() {
14103 // The single-keyed cache feature is meaningless when the split cache is not
14104 // enabled. The //net layer doesn't care whether or not the
14105 // "CacheTransparency" feature is enabled.
14106 CHECK(base::FeatureList::IsEnabled(
14107 net::features::kSplitCacheByNetworkIsolationKey));
14108 }
14109
RunTransactionTestForSingleKeyedCache(HttpCache * cache,const MockTransaction & trans_info,const NetworkIsolationKey & network_isolation_key,const std::string & checksum)14110 void RunTransactionTestForSingleKeyedCache(
14111 HttpCache* cache,
14112 const MockTransaction& trans_info,
14113 const NetworkIsolationKey& network_isolation_key,
14114 const std::string& checksum) {
14115 ScopedMockTransaction transaction(trans_info);
14116
14117 MockHttpRequest request(transaction);
14118 request.network_isolation_key = network_isolation_key;
14119 request.network_anonymization_key =
14120 net::NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
14121 network_isolation_key);
14122 request.checksum = checksum;
14123
14124 HttpResponseInfo response_info;
14125 RunTransactionTestWithRequest(cache, transaction, request, &response_info);
14126 }
14127
RunSimpleTransactionTestForSingleKeyedCache(HttpCache * cache,const NetworkIsolationKey & network_isolation_key,const std::string & checksum)14128 void RunSimpleTransactionTestForSingleKeyedCache(
14129 HttpCache* cache,
14130 const NetworkIsolationKey& network_isolation_key,
14131 const std::string& checksum) {
14132 RunTransactionTestForSingleKeyedCache(cache, kSimpleGET_Transaction,
14133 network_isolation_key, checksum);
14134 }
14135 };
14136
14137 INSTANTIATE_TEST_SUITE_P(
14138 All,
14139 CacheTransparencyHttpCacheTest,
14140 testing::ValuesIn({SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled,
14141 SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled}),
__anonc87d1e5b0a02(const testing::TestParamInfo<SplitCacheTestCase>& info) 14142 [](const testing::TestParamInfo<SplitCacheTestCase>& info) {
14143 switch (info.param) {
14144 case (SplitCacheTestCase::kSplitCacheDisabled):
14145 return "NotUsedForThisTestSuite";
14146 case (SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled):
14147 return "SplitCacheNikFrameSiteEnabled";
14148 case (SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled):
14149 return "SplitCacheNikCrossSiteFlagEnabled";
14150 }
14151 });
14152
14153 constexpr char kChecksumForSimpleGET[] =
14154 "80B4C37CEF5CFE69B4A90830282AA2BB772DC4CBC00491A219CE5F2AD75C7B58";
14155
TEST_P(CacheTransparencyHttpCacheTest,SuccessfulGET)14156 TEST_P(CacheTransparencyHttpCacheTest, SuccessfulGET) {
14157 MockHttpCache cache;
14158 // The first request adds the item to the cache.
14159 {
14160 const auto site_a = SchemefulSite(GURL("https://a.com/"));
14161 RunSimpleTransactionTestForSingleKeyedCache(
14162 cache.http_cache(), NetworkIsolationKey(site_a, site_a),
14163 kChecksumForSimpleGET);
14164
14165 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14166 EXPECT_EQ(0, cache.disk_cache()->open_count());
14167 EXPECT_EQ(1, cache.disk_cache()->create_count());
14168 }
14169
14170 // The second request verifies that the same cache entry is used with a
14171 // different NetworkIsolationKey
14172 {
14173 const auto site_b = SchemefulSite(GURL("https://b.com/"));
14174 RunSimpleTransactionTestForSingleKeyedCache(
14175 cache.http_cache(), NetworkIsolationKey(site_b, site_b),
14176 kChecksumForSimpleGET);
14177
14178 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14179 EXPECT_EQ(1, cache.disk_cache()->open_count());
14180 EXPECT_EQ(1, cache.disk_cache()->create_count());
14181 }
14182 }
14183
TEST_P(CacheTransparencyHttpCacheTest,GETWithChecksumMismatch)14184 TEST_P(CacheTransparencyHttpCacheTest, GETWithChecksumMismatch) {
14185 MockHttpCache cache;
14186 const auto site_a = SchemefulSite(GURL("https://a.com/"));
14187 // The first request adds the item to the cache.
14188 {
14189 RunSimpleTransactionTestForSingleKeyedCache(
14190 cache.http_cache(), NetworkIsolationKey(site_a, site_a),
14191 "000000000000000000000000000000000000000000000000000000000000000");
14192
14193 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14194 EXPECT_EQ(0, cache.disk_cache()->open_count());
14195 EXPECT_EQ(1, cache.disk_cache()->create_count());
14196 }
14197
14198 // The second request doesn't use the item that was added to the single-keyed
14199 // cache, but adds it to the split cache instead.
14200 {
14201 RunSimpleTransactionTestForSingleKeyedCache(
14202 cache.http_cache(), NetworkIsolationKey(site_a, site_a),
14203 "000000000000000000000000000000000000000000000000000000000000000");
14204
14205 // Fetches from the network again, this time into the split cache.
14206 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14207 EXPECT_EQ(1, cache.disk_cache()->open_count());
14208 EXPECT_EQ(2, cache.disk_cache()->create_count());
14209 }
14210
14211 // The third request uses the split cache.
14212 {
14213 RunSimpleTransactionTestForSingleKeyedCache(
14214 cache.http_cache(), NetworkIsolationKey(site_a, site_a),
14215 "000000000000000000000000000000000000000000000000000000000000000");
14216
14217 // Fetches from the split cache.
14218 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14219 EXPECT_EQ(3, cache.disk_cache()->open_count()); // opens both cache entries
14220 EXPECT_EQ(2, cache.disk_cache()->create_count());
14221 }
14222 }
14223
TEST_P(CacheTransparencyHttpCacheTest,GETWithBadResponseCode)14224 TEST_P(CacheTransparencyHttpCacheTest, GETWithBadResponseCode) {
14225 MockHttpCache cache;
14226 MockTransaction transaction = kSimpleGET_Transaction;
14227 transaction.status = "HTTP/1.1 404 Not Found";
14228 const auto site_a = SchemefulSite(GURL("https://a.com/"));
14229 // The first request adds the item to the single-keyed cache.
14230 {
14231 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14232 NetworkIsolationKey(site_a, site_a),
14233 kChecksumForSimpleGET);
14234
14235 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14236 EXPECT_EQ(0, cache.disk_cache()->open_count());
14237 EXPECT_EQ(1, cache.disk_cache()->create_count());
14238 }
14239
14240 // The second request verifies that the cache entry is not re-used
14241 // but a new one is created in the split cache.
14242 {
14243 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14244 NetworkIsolationKey(site_a, site_a),
14245 kChecksumForSimpleGET);
14246
14247 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14248 EXPECT_EQ(1, cache.disk_cache()->open_count());
14249 EXPECT_EQ(2, cache.disk_cache()->create_count());
14250 }
14251 }
14252
14253 // This is identical to GETWithBadResponseCode but with a different response
14254 // code. It's not very realistic as it doesn't call DoneReading(), but it covers
14255 // the relevant code path.
TEST_P(CacheTransparencyHttpCacheTest,RedirectUnusable)14256 TEST_P(CacheTransparencyHttpCacheTest, RedirectUnusable) {
14257 MockHttpCache cache;
14258 MockTransaction transaction = kSimpleGET_Transaction;
14259 transaction.status = "HTTP/1.1 301 Moved Permanently";
14260 const auto site_a = SchemefulSite(GURL("https://a.com/"));
14261 // The first request adds the item to the single-keyed cache.
14262 {
14263 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14264 NetworkIsolationKey(site_a, site_a),
14265 kChecksumForSimpleGET);
14266
14267 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14268 EXPECT_EQ(0, cache.disk_cache()->open_count());
14269 EXPECT_EQ(1, cache.disk_cache()->create_count());
14270 }
14271
14272 // The second request verifies that the cache entry is not re-used
14273 // but a new one is created in the split cache.
14274 {
14275 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14276 NetworkIsolationKey(site_a, site_a),
14277 kChecksumForSimpleGET);
14278
14279 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14280 EXPECT_EQ(1, cache.disk_cache()->open_count());
14281 EXPECT_EQ(2, cache.disk_cache()->create_count());
14282 }
14283 }
14284
TEST_P(CacheTransparencyHttpCacheTest,GETWith206ResponseCode)14285 TEST_P(CacheTransparencyHttpCacheTest, GETWith206ResponseCode) {
14286 MockHttpCache cache;
14287 MockTransaction transaction = kSimpleGET_Transaction;
14288 // We should never get a partial response since we never send a range request,
14289 // but it behaves differently from other bad response codes.
14290 transaction.status = "HTTP/1.1 206 Partial";
14291 const auto site_a = SchemefulSite(GURL("https://a.com/"));
14292 // The response is not cached.
14293 {
14294 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14295 NetworkIsolationKey(site_a, site_a),
14296 kChecksumForSimpleGET);
14297
14298 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14299 EXPECT_EQ(0, cache.disk_cache()->open_count());
14300 EXPECT_EQ(1, cache.disk_cache()->create_count());
14301 }
14302
14303 // It is fetched from the network again.
14304 {
14305 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14306 NetworkIsolationKey(site_a, site_a),
14307 kChecksumForSimpleGET);
14308
14309 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14310 EXPECT_EQ(0, cache.disk_cache()->open_count());
14311 EXPECT_EQ(2, cache.disk_cache()->create_count());
14312 }
14313 }
14314
TEST_P(CacheTransparencyHttpCacheTest,SuccessfulRevalidation)14315 TEST_P(CacheTransparencyHttpCacheTest, SuccessfulRevalidation) {
14316 MockHttpCache cache;
14317 MockTransaction transaction = kSimpleGET_Transaction;
14318 // Add a cache control header to permit the entry to be cached, with max-age 0
14319 // to force relatidation next time. Add Etag to permit it to be revalidated.
14320 transaction.response_headers =
14321 "Etag: \"foo\"\n"
14322 "Cache-Control: max-age=0\n";
14323 {
14324 const auto site_a = SchemefulSite(GURL("https://a.com/"));
14325 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14326 NetworkIsolationKey(site_a, site_a),
14327 kChecksumForSimpleGET);
14328
14329 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14330 EXPECT_EQ(0, cache.disk_cache()->open_count());
14331 EXPECT_EQ(1, cache.disk_cache()->create_count());
14332 }
14333
14334 // The second request revalidates the existing entry.
14335 {
14336 const auto site_b = SchemefulSite(GURL("https://b.com/"));
14337 transaction.status = "HTTP/1.1 304 Not Modified";
14338 // Allow it to be reused without validation next time by increasing max-age.
14339 transaction.response_headers =
14340 "Etag: \"foo\"\n"
14341 "Cache-Control: max-age=10000\n";
14342 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14343 NetworkIsolationKey(site_b, site_b),
14344 kChecksumForSimpleGET);
14345
14346 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14347 EXPECT_EQ(1, cache.disk_cache()->open_count());
14348 EXPECT_EQ(1, cache.disk_cache()->create_count());
14349 }
14350
14351 // The third request re-uses the entry.
14352 {
14353 const auto site_c = SchemefulSite(GURL("https://c.com/"));
14354 // Load from cache again.
14355 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14356 NetworkIsolationKey(site_c, site_c),
14357 kChecksumForSimpleGET);
14358
14359 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14360 EXPECT_EQ(1, cache.disk_cache()->open_count());
14361 EXPECT_EQ(1, cache.disk_cache()->create_count());
14362 }
14363 }
14364
TEST_P(CacheTransparencyHttpCacheTest,RevalidationChangingUncheckedHeader)14365 TEST_P(CacheTransparencyHttpCacheTest, RevalidationChangingUncheckedHeader) {
14366 MockHttpCache cache;
14367 MockTransaction transaction = kSimpleGET_Transaction;
14368 // Add a cache control header to permit the entry to be cached, with max-age 0
14369 // to force relatidation next time. Add Etag to permit it to be revalidated.
14370 transaction.response_headers =
14371 "Etag: \"foo\"\n"
14372 "Cache-Control: max-age=0\n";
14373 {
14374 const auto site_a = SchemefulSite(GURL("https://a.com/"));
14375 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14376 NetworkIsolationKey(site_a, site_a),
14377 kChecksumForSimpleGET);
14378
14379 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14380 EXPECT_EQ(0, cache.disk_cache()->open_count());
14381 EXPECT_EQ(1, cache.disk_cache()->create_count());
14382 }
14383
14384 // The second request revalidates the existing entry.
14385 {
14386 const auto site_b = SchemefulSite(GURL("https://b.com/"));
14387 transaction.status = "HTTP/1.1 304 Not Modified";
14388 // Add a response header. This is the only difference from the
14389 // SuccessfulRevalidation test.
14390 transaction.response_headers =
14391 "Etag: \"foo\"\n"
14392 "Cache-Control: max-age=10000\n"
14393 "X-Unchecked-Header: 1\n";
14394 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14395 NetworkIsolationKey(site_b, site_b),
14396 kChecksumForSimpleGET);
14397
14398 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14399 EXPECT_EQ(1, cache.disk_cache()->open_count());
14400 EXPECT_EQ(1, cache.disk_cache()->create_count());
14401 }
14402
14403 // The third request re-uses the entry.
14404 {
14405 const auto site_c = SchemefulSite(GURL("https://c.com/"));
14406 // Load from cache again.
14407 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14408 NetworkIsolationKey(site_c, site_c),
14409 kChecksumForSimpleGET);
14410
14411 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14412 EXPECT_EQ(1, cache.disk_cache()->open_count());
14413 EXPECT_EQ(1, cache.disk_cache()->create_count());
14414 }
14415 }
14416
TEST_P(CacheTransparencyHttpCacheTest,RevalidationChangingCheckedHeader)14417 TEST_P(CacheTransparencyHttpCacheTest, RevalidationChangingCheckedHeader) {
14418 MockHttpCache cache;
14419 MockTransaction transaction = kSimpleGET_Transaction;
14420 // Add a cache control header to permit the entry to be cached, with max-age 0
14421 // to force relatidation next time. Add Etag to permit it to be revalidated.
14422 transaction.response_headers =
14423 "Etag: \"foo\"\n"
14424 "Cache-Control: max-age=0\n";
14425 {
14426 const auto site_a = SchemefulSite(GURL("https://a.com/"));
14427 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14428 NetworkIsolationKey(site_a, site_a),
14429 kChecksumForSimpleGET);
14430
14431 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14432 EXPECT_EQ(0, cache.disk_cache()->open_count());
14433 EXPECT_EQ(1, cache.disk_cache()->create_count());
14434 }
14435
14436 // The second request marks the single-keyed cache entry unusable because the
14437 // checksum no longer matches.
14438 {
14439 const auto site_b = SchemefulSite(GURL("https://b.com/"));
14440 transaction.status = "HTTP/1.1 304 Not Modified";
14441 // Add the "Vary" response header.
14442 transaction.response_headers =
14443 "Etag: \"foo\"\n"
14444 "Cache-Control: max-age=10000\n"
14445 "Vary: Cookie\n";
14446 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14447 NetworkIsolationKey(site_b, site_b),
14448 kChecksumForSimpleGET);
14449
14450 EXPECT_EQ(2, cache.network_layer()->transaction_count());
14451 EXPECT_EQ(1, cache.disk_cache()->open_count());
14452 EXPECT_EQ(1, cache.disk_cache()->create_count());
14453 }
14454
14455 // The third request has to go to the network because the single-keyed cache
14456 // entry is unusable. It writes a new entry to the split cache.
14457 {
14458 const auto site_c = SchemefulSite(GURL("https://c.com/"));
14459 RunTransactionTestForSingleKeyedCache(cache.http_cache(), transaction,
14460 NetworkIsolationKey(site_c, site_c),
14461 kChecksumForSimpleGET);
14462
14463 EXPECT_EQ(3, cache.network_layer()->transaction_count());
14464 EXPECT_EQ(2, cache.disk_cache()->open_count());
14465 EXPECT_EQ(2, cache.disk_cache()->create_count());
14466 }
14467 }
14468
TEST_P(CacheTransparencyHttpCacheTest,SuccessfulGETManyWriters)14469 TEST_P(CacheTransparencyHttpCacheTest, SuccessfulGETManyWriters) {
14470 MockHttpCache cache;
14471
14472 MockHttpRequest request(kSimpleGET_Transaction);
14473 request.checksum = kChecksumForSimpleGET;
14474
14475 constexpr int kNumTransactions = 2;
14476 std::vector<Context> context_list(kNumTransactions);
14477
14478 for (Context& c : context_list) {
14479 c.result = cache.CreateTransaction(&c.trans);
14480 ASSERT_THAT(c.result, IsOk());
14481
14482 c.result =
14483 c.trans->Start(&request, c.callback.callback(), NetLogWithSource());
14484 }
14485
14486 // Allow all requests to move from the Create queue to the active entry.
14487 // All would have been added to writers.
14488 base::RunLoop().RunUntilIdle();
14489 std::string cache_key = cache.http_cache()
14490 ->GenerateCacheKeyForRequest(
14491 &request, /*use_single_keyed_cache=*/true)
14492 .value();
14493 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
14494
14495 // The second transaction skipped validation, thus only one network
14496 // transaction is created.
14497 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14498 EXPECT_EQ(0, cache.disk_cache()->open_count());
14499 EXPECT_EQ(1, cache.disk_cache()->create_count());
14500
14501 // Complete the transactions.
14502 for (Context& c : context_list) {
14503 ReadAndVerifyTransaction(c.trans.get(), kSimpleGET_Transaction);
14504 }
14505
14506 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14507 EXPECT_EQ(0, cache.disk_cache()->open_count());
14508 EXPECT_EQ(1, cache.disk_cache()->create_count());
14509 }
14510
TEST_P(CacheTransparencyHttpCacheTest,BadChecksumManyWriters)14511 TEST_P(CacheTransparencyHttpCacheTest, BadChecksumManyWriters) {
14512 MockHttpCache cache;
14513
14514 MockHttpRequest request(kSimpleGET_Transaction);
14515 request.checksum =
14516 "0000000000000000000000000000000000000000000000000000000000000000";
14517
14518 constexpr int kNumTransactions = 2;
14519 std::vector<Context> context_list(kNumTransactions);
14520
14521 for (Context& c : context_list) {
14522 c.result = cache.CreateTransaction(&c.trans);
14523 ASSERT_THAT(c.result, IsOk());
14524
14525 c.result =
14526 c.trans->Start(&request, c.callback.callback(), NetLogWithSource());
14527 }
14528
14529 // Allow all requests to move from the Create queue to the active entry.
14530 // All would have been added to writers.
14531 base::RunLoop().RunUntilIdle();
14532 std::string cache_key = cache.http_cache()
14533 ->GenerateCacheKeyForRequest(
14534 &request, /*use_single_keyed_cache=*/true)
14535 .value();
14536 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
14537
14538 // The second transaction skipped validation, thus only one network
14539 // transaction is created.
14540 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14541 EXPECT_EQ(0, cache.disk_cache()->open_count());
14542 EXPECT_EQ(1, cache.disk_cache()->create_count());
14543
14544 // Complete the transactions.
14545 for (Context& c : context_list) {
14546 ReadAndVerifyTransaction(c.trans.get(), kSimpleGET_Transaction);
14547 }
14548
14549 EXPECT_EQ(1, cache.network_layer()->transaction_count());
14550 EXPECT_EQ(0, cache.disk_cache()->open_count());
14551 EXPECT_EQ(1, cache.disk_cache()->create_count());
14552 }
14553
14554 } // namespace net
14555