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 <optional>
12 #include <set>
13 #include <utility>
14 #include <vector>
15
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/format_macros.h"
18 #include "base/functional/bind.h"
19 #include "base/functional/callback_helpers.h"
20 #include "base/memory/ptr_util.h"
21 #include "base/memory/raw_ptr.h"
22 #include "base/run_loop.h"
23 #include "base/strings/strcat.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_util.h"
26 #include "base/strings/stringprintf.h"
27 #include "base/test/bind.h"
28 #include "base/test/metrics/histogram_tester.h"
29 #include "base/test/scoped_feature_list.h"
30 #include "base/test/simple_test_clock.h"
31 #include "base/time/time.h"
32 #include "base/trace_event/memory_allocator_dump.h"
33 #include "base/trace_event/memory_dump_request_args.h"
34 #include "base/trace_event/process_memory_dump.h"
35 #include "net/base/cache_type.h"
36 #include "net/base/completion_repeating_callback.h"
37 #include "net/base/elements_upload_data_stream.h"
38 #include "net/base/features.h"
39 #include "net/base/host_port_pair.h"
40 #include "net/base/ip_address.h"
41 #include "net/base/ip_endpoint.h"
42 #include "net/base/load_flags.h"
43 #include "net/base/load_timing_info.h"
44 #include "net/base/load_timing_info_test_util.h"
45 #include "net/base/net_errors.h"
46 #include "net/base/schemeful_site.h"
47 #include "net/base/tracing.h"
48 #include "net/base/upload_bytes_element_reader.h"
49 #include "net/cert/cert_status_flags.h"
50 #include "net/cert/x509_certificate.h"
51 #include "net/disk_cache/disk_cache.h"
52 #include "net/http/http_byte_range.h"
53 #include "net/http/http_cache_transaction.h"
54 #include "net/http/http_request_headers.h"
55 #include "net/http/http_request_info.h"
56 #include "net/http/http_response_headers.h"
57 #include "net/http/http_response_headers_test_util.h"
58 #include "net/http/http_response_info.h"
59 #include "net/http/http_transaction.h"
60 #include "net/http/http_transaction_test_util.h"
61 #include "net/http/http_util.h"
62 #include "net/http/mock_http_cache.h"
63 #include "net/log/net_log_event_type.h"
64 #include "net/log/net_log_source.h"
65 #include "net/log/net_log_with_source.h"
66 #include "net/log/test_net_log.h"
67 #include "net/log/test_net_log_util.h"
68 #include "net/socket/client_socket_handle.h"
69 #include "net/ssl/ssl_cert_request_info.h"
70 #include "net/ssl/ssl_connection_status_flags.h"
71 #include "net/test/cert_test_util.h"
72 #include "net/test/gtest_util.h"
73 #include "net/test/test_data_directory.h"
74 #include "net/test/test_with_task_environment.h"
75 #include "net/websockets/websocket_handshake_stream_base.h"
76 #include "testing/gmock/include/gmock/gmock.h"
77 #include "testing/gtest/include/gtest/gtest.h"
78 #include "url/origin.h"
79
80 using net::test::IsError;
81 using net::test::IsOk;
82 using testing::AllOf;
83 using testing::ByRef;
84 using testing::Contains;
85 using testing::ElementsAre;
86 using testing::Eq;
87 using testing::Field;
88 using testing::Gt;
89 using testing::IsEmpty;
90 using testing::NotNull;
91
92 using base::Time;
93
94 namespace net {
95
96 using CacheEntryStatus = HttpResponseInfo::CacheEntryStatus;
97
98 class WebSocketEndpointLockManager;
99
100 namespace {
101
102 constexpr auto ToSimpleString = test::HttpResponseHeadersToSimpleString;
103
104 // Tests the load timing values of a request that goes through a
105 // MockNetworkTransaction.
TestLoadTimingNetworkRequest(const LoadTimingInfo & load_timing_info)106 void TestLoadTimingNetworkRequest(const LoadTimingInfo& load_timing_info) {
107 EXPECT_FALSE(load_timing_info.socket_reused);
108 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
109
110 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
111 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
112
113 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
114 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
115 EXPECT_LE(load_timing_info.connect_timing.connect_end,
116 load_timing_info.send_start);
117
118 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
119
120 // Set by URLRequest / URLRequestHttpJob, at a higher level.
121 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
122 EXPECT_TRUE(load_timing_info.request_start.is_null());
123 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
124 }
125
126 // Tests the load timing values of a request that receives a cached response.
TestLoadTimingCachedResponse(const LoadTimingInfo & load_timing_info)127 void TestLoadTimingCachedResponse(const LoadTimingInfo& load_timing_info) {
128 EXPECT_FALSE(load_timing_info.socket_reused);
129 EXPECT_EQ(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
130
131 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
132 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
133
134 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
135
136 // Only the send start / end times should be sent, and they should have the
137 // same value.
138 EXPECT_FALSE(load_timing_info.send_start.is_null());
139 EXPECT_EQ(load_timing_info.send_start, load_timing_info.send_end);
140
141 // Set by URLRequest / URLRequestHttpJob, at a higher level.
142 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
143 EXPECT_TRUE(load_timing_info.request_start.is_null());
144 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
145 }
146
DeferCallback(bool * defer)147 void DeferCallback(bool* defer) {
148 *defer = true;
149 }
150
151 class DeleteCacheCompletionCallback : public TestCompletionCallbackBase {
152 public:
DeleteCacheCompletionCallback(std::unique_ptr<MockHttpCache> cache)153 explicit DeleteCacheCompletionCallback(std::unique_ptr<MockHttpCache> cache)
154 : cache_(std::move(cache)) {}
155
156 DeleteCacheCompletionCallback(const DeleteCacheCompletionCallback&) = delete;
157 DeleteCacheCompletionCallback& operator=(
158 const DeleteCacheCompletionCallback&) = delete;
159
callback()160 CompletionOnceCallback callback() {
161 return base::BindOnce(&DeleteCacheCompletionCallback::OnComplete,
162 base::Unretained(this));
163 }
164
165 private:
OnComplete(int result)166 void OnComplete(int result) {
167 cache_.reset();
168 SetResult(result);
169 }
170
171 std::unique_ptr<MockHttpCache> cache_;
172 };
173
174 //-----------------------------------------------------------------------------
175 // helpers
176
ReadAndVerifyTransaction(HttpTransaction * trans,const MockTransaction & trans_info)177 void ReadAndVerifyTransaction(HttpTransaction* trans,
178 const MockTransaction& trans_info) {
179 std::string content;
180 int rv = ReadTransaction(trans, &content);
181
182 EXPECT_THAT(rv, IsOk());
183 std::string expected(trans_info.data);
184 EXPECT_EQ(expected, content);
185 }
186
ReadRemainingAndVerifyTransaction(HttpTransaction * trans,const std::string & already_read,const MockTransaction & trans_info)187 void ReadRemainingAndVerifyTransaction(HttpTransaction* trans,
188 const std::string& already_read,
189 const MockTransaction& trans_info) {
190 std::string content;
191 int rv = ReadTransaction(trans, &content);
192 EXPECT_THAT(rv, IsOk());
193
194 std::string expected(trans_info.data);
195 EXPECT_EQ(expected, already_read + content);
196 }
197
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)198 void RunTransactionTestBase(HttpCache* cache,
199 const MockTransaction& trans_info,
200 const MockHttpRequest& request,
201 HttpResponseInfo* response_info,
202 const NetLogWithSource& net_log,
203 LoadTimingInfo* load_timing_info,
204 int64_t* sent_bytes,
205 int64_t* received_bytes,
206 IPEndPoint* remote_endpoint) {
207 TestCompletionCallback callback;
208
209 // write to the cache
210
211 std::unique_ptr<HttpTransaction> trans;
212 int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &trans);
213 EXPECT_THAT(rv, IsOk());
214 ASSERT_TRUE(trans.get());
215
216 rv = trans->Start(&request, callback.callback(), net_log);
217 if (rv == ERR_IO_PENDING) {
218 rv = callback.WaitForResult();
219 }
220 ASSERT_EQ(trans_info.start_return_code, rv);
221
222 if (OK != rv) {
223 return;
224 }
225
226 const HttpResponseInfo* response = trans->GetResponseInfo();
227 ASSERT_TRUE(response);
228
229 if (response_info) {
230 *response_info = *response;
231 }
232
233 if (load_timing_info) {
234 // If a fake network connection is used, need a NetLog to get a fake socket
235 // ID.
236 EXPECT_TRUE(net_log.net_log());
237 *load_timing_info = LoadTimingInfo();
238 trans->GetLoadTimingInfo(load_timing_info);
239 }
240
241 if (remote_endpoint) {
242 ASSERT_TRUE(trans->GetRemoteEndpoint(remote_endpoint));
243 }
244
245 ReadAndVerifyTransaction(trans.get(), trans_info);
246
247 if (sent_bytes) {
248 *sent_bytes = trans->GetTotalSentBytes();
249 }
250 if (received_bytes) {
251 *received_bytes = trans->GetTotalReceivedBytes();
252 }
253 }
254
RunTransactionTestWithRequest(HttpCache * cache,const MockTransaction & trans_info,const MockHttpRequest & request,HttpResponseInfo * response_info)255 void RunTransactionTestWithRequest(HttpCache* cache,
256 const MockTransaction& trans_info,
257 const MockHttpRequest& request,
258 HttpResponseInfo* response_info) {
259 RunTransactionTestBase(cache, trans_info, request, response_info,
260 NetLogWithSource(), nullptr, nullptr, nullptr,
261 nullptr);
262 }
263
RunTransactionTestAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)264 void RunTransactionTestAndGetTiming(HttpCache* cache,
265 const MockTransaction& trans_info,
266 const NetLogWithSource& log,
267 LoadTimingInfo* load_timing_info) {
268 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
269 nullptr, log, load_timing_info, nullptr, nullptr,
270 nullptr);
271 }
272
RunTransactionTestAndGetTimingAndConnectedSocketAddress(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log,LoadTimingInfo * load_timing_info,IPEndPoint * remote_endpoint)273 void RunTransactionTestAndGetTimingAndConnectedSocketAddress(
274 HttpCache* cache,
275 const MockTransaction& trans_info,
276 const NetLogWithSource& log,
277 LoadTimingInfo* load_timing_info,
278 IPEndPoint* remote_endpoint) {
279 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
280 nullptr, log, load_timing_info, nullptr, nullptr,
281 remote_endpoint);
282 }
283
RunTransactionTest(HttpCache * cache,const MockTransaction & trans_info)284 void RunTransactionTest(HttpCache* cache, const MockTransaction& trans_info) {
285 RunTransactionTestAndGetTiming(cache, trans_info, NetLogWithSource(),
286 nullptr);
287 }
288
RunTransactionTestWithLog(HttpCache * cache,const MockTransaction & trans_info,const NetLogWithSource & log)289 void RunTransactionTestWithLog(HttpCache* cache,
290 const MockTransaction& trans_info,
291 const NetLogWithSource& log) {
292 RunTransactionTestAndGetTiming(cache, trans_info, log, nullptr);
293 }
294
RunTransactionTestWithResponseInfo(HttpCache * cache,const MockTransaction & trans_info,HttpResponseInfo * response)295 void RunTransactionTestWithResponseInfo(HttpCache* cache,
296 const MockTransaction& trans_info,
297 HttpResponseInfo* response) {
298 RunTransactionTestWithRequest(cache, trans_info, MockHttpRequest(trans_info),
299 response);
300 }
301
RunTransactionTestWithResponseInfoAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,HttpResponseInfo * response,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)302 void RunTransactionTestWithResponseInfoAndGetTiming(
303 HttpCache* cache,
304 const MockTransaction& trans_info,
305 HttpResponseInfo* response,
306 const NetLogWithSource& log,
307 LoadTimingInfo* load_timing_info) {
308 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
309 response, log, load_timing_info, nullptr, nullptr,
310 nullptr);
311 }
312
RunTransactionTestWithResponse(HttpCache * cache,const MockTransaction & trans_info,std::string * response_headers)313 void RunTransactionTestWithResponse(HttpCache* cache,
314 const MockTransaction& trans_info,
315 std::string* response_headers) {
316 HttpResponseInfo response;
317 RunTransactionTestWithResponseInfo(cache, trans_info, &response);
318 *response_headers = ToSimpleString(response.headers);
319 }
320
RunTransactionTestWithResponseAndGetTiming(HttpCache * cache,const MockTransaction & trans_info,std::string * response_headers,const NetLogWithSource & log,LoadTimingInfo * load_timing_info)321 void RunTransactionTestWithResponseAndGetTiming(
322 HttpCache* cache,
323 const MockTransaction& trans_info,
324 std::string* response_headers,
325 const NetLogWithSource& log,
326 LoadTimingInfo* load_timing_info) {
327 HttpResponseInfo response;
328 RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
329 &response, log, load_timing_info, nullptr, nullptr,
330 nullptr);
331 *response_headers = ToSimpleString(response.headers);
332 }
333
334 // This class provides a handler for kFastNoStoreGET_Transaction so that the
335 // no-store header can be included on demand.
336 class FastTransactionServer {
337 public:
FastTransactionServer()338 FastTransactionServer() { no_store = false; }
339
340 FastTransactionServer(const FastTransactionServer&) = delete;
341 FastTransactionServer& operator=(const FastTransactionServer&) = delete;
342
343 ~FastTransactionServer() = default;
344
set_no_store(bool value)345 void set_no_store(bool value) { no_store = value; }
346
FastNoStoreHandler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)347 static void FastNoStoreHandler(const HttpRequestInfo* request,
348 std::string* response_status,
349 std::string* response_headers,
350 std::string* response_data) {
351 if (no_store) {
352 *response_headers = "Cache-Control: no-store\n";
353 }
354 }
355
356 private:
357 static bool no_store;
358 };
359 bool FastTransactionServer::no_store;
360
361 const MockTransaction kFastNoStoreGET_Transaction = {
362 "http://www.google.com/nostore",
363 "GET",
364 base::Time(),
365 "",
366 LOAD_VALIDATE_CACHE,
367 DefaultTransportInfo(),
368 "HTTP/1.1 200 OK",
369 "Cache-Control: max-age=10000\n",
370 base::Time(),
371 "<html><body>Google Blah Blah</body></html>",
372 {},
373 std::nullopt,
374 std::nullopt,
375 TEST_MODE_SYNC_NET_START,
376 base::BindRepeating(&FastTransactionServer::FastNoStoreHandler),
377 MockTransactionReadHandler(),
378 nullptr,
379 0,
380 0,
381 OK,
382 };
383
384 // This class provides a handler for kRangeGET_TransactionOK so that the range
385 // request can be served on demand.
386 class RangeTransactionServer {
387 public:
RangeTransactionServer()388 RangeTransactionServer() {
389 not_modified_ = false;
390 modified_ = false;
391 bad_200_ = false;
392 redirect_ = false;
393 length_ = 80;
394 }
395
396 RangeTransactionServer(const RangeTransactionServer&) = delete;
397 RangeTransactionServer& operator=(const RangeTransactionServer&) = delete;
398
~RangeTransactionServer()399 ~RangeTransactionServer() {
400 not_modified_ = false;
401 modified_ = false;
402 bad_200_ = false;
403 redirect_ = false;
404 length_ = 80;
405 }
406
407 // Returns only 416 or 304 when set.
set_not_modified(bool value)408 void set_not_modified(bool value) { not_modified_ = value; }
409
410 // Returns 206 when revalidating a range (instead of 304).
set_modified(bool value)411 void set_modified(bool value) { modified_ = value; }
412
413 // Returns 200 instead of 206 (a malformed response overall).
set_bad_200(bool value)414 void set_bad_200(bool value) { bad_200_ = value; }
415
416 // Sets how long the resource is. (Default is 80)
set_length(int64_t length)417 void set_length(int64_t length) { length_ = length; }
418
419 // Sets whether to return a 301 instead of normal return.
set_redirect(bool redirect)420 void set_redirect(bool redirect) { redirect_ = redirect; }
421
422 // Other than regular range related behavior (and the flags mentioned above),
423 // the server reacts to requests headers like so:
424 // X-Require-Mock-Auth -> return 401.
425 // X-Require-Mock-Auth-Alt -> return 401.
426 // X-Return-Default-Range -> assume 40-49 was requested.
427 // The -Alt variant doesn't cause the MockNetworkTransaction to
428 // report that it IsReadyToRestartForAuth().
429 static void RangeHandler(const HttpRequestInfo* request,
430 std::string* response_status,
431 std::string* response_headers,
432 std::string* response_data);
433
434 private:
435 static bool not_modified_;
436 static bool modified_;
437 static bool bad_200_;
438 static bool redirect_;
439 static int64_t length_;
440 };
441 bool RangeTransactionServer::not_modified_ = false;
442 bool RangeTransactionServer::modified_ = false;
443 bool RangeTransactionServer::bad_200_ = false;
444 bool RangeTransactionServer::redirect_ = false;
445 int64_t RangeTransactionServer::length_ = 80;
446
447 // A dummy extra header that must be preserved on a given request.
448
449 // EXTRA_HEADER_LINE doesn't include a line terminator because it
450 // will be passed to AddHeaderFromString() which doesn't accept them.
451 #define EXTRA_HEADER_LINE "Extra: header"
452
453 // EXTRA_HEADER contains a line terminator, as expected by
454 // AddHeadersFromString() (_not_ AddHeaderFromString()).
455 #define EXTRA_HEADER EXTRA_HEADER_LINE "\r\n"
456
457 static const char kExtraHeaderKey[] = "Extra";
458
459 // Static.
RangeHandler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)460 void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request,
461 std::string* response_status,
462 std::string* response_headers,
463 std::string* response_data) {
464 if (request->extra_headers.IsEmpty()) {
465 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
466 response_data->clear();
467 return;
468 }
469
470 // We want to make sure we don't delete extra headers.
471 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
472
473 bool require_auth =
474 request->extra_headers.HasHeader("X-Require-Mock-Auth") ||
475 request->extra_headers.HasHeader("X-Require-Mock-Auth-Alt");
476
477 if (require_auth && !request->extra_headers.HasHeader("Authorization")) {
478 response_status->assign("HTTP/1.1 401 Unauthorized");
479 response_data->assign("WWW-Authenticate: Foo\n");
480 return;
481 }
482
483 if (redirect_) {
484 response_status->assign("HTTP/1.1 301 Moved Permanently");
485 response_headers->assign("Location: /elsewhere\nContent-Length: 5");
486 response_data->assign("12345");
487 return;
488 }
489
490 if (not_modified_) {
491 response_status->assign("HTTP/1.1 304 Not Modified");
492 response_data->clear();
493 return;
494 }
495
496 std::vector<HttpByteRange> ranges;
497 std::string range_header;
498 if (!request->extra_headers.GetHeader(HttpRequestHeaders::kRange,
499 &range_header) ||
500 !HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ ||
501 ranges.size() != 1 ||
502 (modified_ && request->extra_headers.HasHeader("If-Range"))) {
503 // This is not a byte range request, or a failed If-Range. We return 200.
504 response_status->assign("HTTP/1.1 200 OK");
505 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT");
506 response_data->assign("Not a range");
507 return;
508 }
509
510 // We can handle this range request.
511 HttpByteRange byte_range = ranges[0];
512
513 if (request->extra_headers.HasHeader("X-Return-Default-Range")) {
514 byte_range.set_first_byte_position(40);
515 byte_range.set_last_byte_position(49);
516 }
517
518 if (byte_range.first_byte_position() >= length_) {
519 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
520 response_data->clear();
521 return;
522 }
523
524 EXPECT_TRUE(byte_range.ComputeBounds(length_));
525 int64_t start = byte_range.first_byte_position();
526 int64_t end = byte_range.last_byte_position();
527
528 EXPECT_LT(end, length_);
529
530 std::string content_range = base::StringPrintf("Content-Range: bytes %" PRId64
531 "-%" PRId64 "/%" PRId64 "\n",
532 start, end, length_);
533 response_headers->append(content_range);
534
535 if (!request->extra_headers.HasHeader("If-None-Match") || modified_) {
536 std::string data;
537 if (end == start) {
538 EXPECT_EQ(0, end % 10);
539 data = "r";
540 } else {
541 EXPECT_EQ(9, (end - start) % 10);
542 for (int64_t block_start = start; block_start < end; block_start += 10) {
543 base::StringAppendF(&data, "rg: %02" PRId64 "-%02" PRId64 " ",
544 block_start % 100, (block_start + 9) % 100);
545 }
546 }
547 *response_data = data;
548
549 if (end - start != 9) {
550 // We also have to fix content-length.
551 int64_t len = end - start + 1;
552 std::string content_length =
553 base::StringPrintf("Content-Length: %" PRId64 "\n", len);
554 response_headers->replace(response_headers->find("Content-Length:"),
555 content_length.size(), content_length);
556 }
557 } else {
558 response_status->assign("HTTP/1.1 304 Not Modified");
559 response_data->clear();
560 }
561 }
562
563 const MockTransaction kRangeGET_TransactionOK = {
564 "http://www.google.com/range",
565 "GET",
566 base::Time(),
567 "Range: bytes = 40-49\r\n" EXTRA_HEADER,
568 LOAD_NORMAL,
569 DefaultTransportInfo(),
570 "HTTP/1.1 206 Partial Content",
571 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
572 "ETag: \"foo\"\n"
573 "Accept-Ranges: bytes\n"
574 "Content-Length: 10\n",
575 base::Time(),
576 "rg: 40-49 ",
577 {},
578 std::nullopt,
579 std::nullopt,
580 TEST_MODE_NORMAL,
581 base::BindRepeating(&RangeTransactionServer::RangeHandler),
582 MockTransactionReadHandler(),
583 nullptr,
584 0,
585 0,
586 OK,
587 };
588
589 const char kFullRangeData[] =
590 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 "
591 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 ";
592
593 // Verifies the response headers (|response|) match a partial content
594 // response for the range starting at |start| and ending at |end|.
Verify206Response(const std::string & response,int start,int end)595 void Verify206Response(const std::string& response, int start, int end) {
596 auto headers = base::MakeRefCounted<HttpResponseHeaders>(
597 HttpUtil::AssembleRawHeaders(response));
598
599 ASSERT_EQ(206, headers->response_code());
600
601 int64_t range_start, range_end, object_size;
602 ASSERT_TRUE(
603 headers->GetContentRangeFor206(&range_start, &range_end, &object_size));
604 int64_t content_length = headers->GetContentLength();
605
606 int length = end - start + 1;
607 ASSERT_EQ(length, content_length);
608 ASSERT_EQ(start, range_start);
609 ASSERT_EQ(end, range_end);
610 }
611
612 // Creates a truncated entry that can be resumed using byte ranges.
CreateTruncatedEntry(std::string raw_headers,MockHttpCache * cache)613 void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) {
614 // Create a disk cache entry that stores an incomplete resource.
615 disk_cache::Entry* entry;
616 MockHttpRequest request(kRangeGET_TransactionOK);
617 ASSERT_TRUE(cache->CreateBackendEntry(request.CacheKey(), &entry, nullptr));
618
619 HttpResponseInfo response;
620 response.response_time = base::Time::Now();
621 response.request_time = base::Time::Now();
622 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
623 HttpUtil::AssembleRawHeaders(raw_headers));
624 // Set the last argument for this to be an incomplete request.
625 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
626
627 auto buf = base::MakeRefCounted<IOBufferWithSize>(100);
628 int len =
629 static_cast<int>(base::strlcpy(buf->data(), "rg: 00-09 rg: 10-19 ", 100));
630 TestCompletionCallback cb;
631 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
632 EXPECT_EQ(len, cb.GetResult(rv));
633 entry->Close();
634 }
635
636 // Verifies that there's an entry with this |key| with the truncated flag set to
637 // |flag_value|, and with an optional |data_size| (if not zero).
VerifyTruncatedFlag(MockHttpCache * cache,const std::string & key,bool flag_value,int data_size)638 void VerifyTruncatedFlag(MockHttpCache* cache,
639 const std::string& key,
640 bool flag_value,
641 int data_size) {
642 disk_cache::Entry* entry;
643 ASSERT_TRUE(cache->OpenBackendEntry(key, &entry));
644 disk_cache::ScopedEntryPtr closer(entry);
645
646 HttpResponseInfo response;
647 bool truncated = !flag_value;
648 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
649 EXPECT_EQ(flag_value, truncated);
650 if (data_size) {
651 EXPECT_EQ(data_size, entry->GetDataSize(1));
652 }
653 }
654
655 // Helper to represent a network HTTP response.
656 struct Response {
657 // Set this response into |trans|.
AssignTonet::__anone6acdaec0111::Response658 void AssignTo(MockTransaction* trans) const {
659 trans->status = status;
660 trans->response_headers = headers;
661 trans->data = body;
662 }
663
status_and_headersnet::__anone6acdaec0111::Response664 std::string status_and_headers() const {
665 return std::string(status) + "\n" + std::string(headers);
666 }
667
668 const char* status;
669 const char* headers;
670 const char* body;
671 };
672
673 struct Context {
674 Context() = default;
675
676 int result = ERR_IO_PENDING;
677 TestCompletionCallback callback;
678 std::unique_ptr<HttpTransaction> trans;
679 };
680
681 class FakeWebSocketHandshakeStreamCreateHelper
682 : public WebSocketHandshakeStreamBase::CreateHelper {
683 public:
684 ~FakeWebSocketHandshakeStreamCreateHelper() override = default;
CreateBasicStream(std::unique_ptr<ClientSocketHandle> connect,bool using_proxy,WebSocketEndpointLockManager * websocket_endpoint_lock_manager)685 std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream(
686 std::unique_ptr<ClientSocketHandle> connect,
687 bool using_proxy,
688 WebSocketEndpointLockManager* websocket_endpoint_lock_manager) override {
689 return nullptr;
690 }
CreateHttp2Stream(base::WeakPtr<SpdySession> session,std::set<std::string> dns_aliases)691 std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream(
692 base::WeakPtr<SpdySession> session,
693 std::set<std::string> dns_aliases) override {
694 NOTREACHED();
695 return nullptr;
696 }
CreateHttp3Stream(std::unique_ptr<QuicChromiumClientSession::Handle> session,std::set<std::string> dns_aliases)697 std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp3Stream(
698 std::unique_ptr<QuicChromiumClientSession::Handle> session,
699 std::set<std::string> dns_aliases) override {
700 NOTREACHED();
701 return nullptr;
702 }
703 };
704
705 // Returns true if |entry| is not one of the log types paid attention to in this
706 // test. Note that HTTP_CACHE_WRITE_INFO and HTTP_CACHE_*_DATA are
707 // ignored.
ShouldIgnoreLogEntry(const NetLogEntry & entry)708 bool ShouldIgnoreLogEntry(const NetLogEntry& entry) {
709 switch (entry.type) {
710 case NetLogEventType::HTTP_CACHE_GET_BACKEND:
711 case NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY:
712 case NetLogEventType::HTTP_CACHE_OPEN_ENTRY:
713 case NetLogEventType::HTTP_CACHE_CREATE_ENTRY:
714 case NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY:
715 case NetLogEventType::HTTP_CACHE_DOOM_ENTRY:
716 case NetLogEventType::HTTP_CACHE_READ_INFO:
717 return false;
718 default:
719 return true;
720 }
721 }
722
723 // Gets the entries from |net_log| created by the cache layer and asserted on in
724 // these tests.
GetFilteredNetLogEntries(const RecordingNetLogObserver & net_log_observer)725 std::vector<NetLogEntry> GetFilteredNetLogEntries(
726 const RecordingNetLogObserver& net_log_observer) {
727 auto entries = net_log_observer.GetEntries();
728 std::erase_if(entries, ShouldIgnoreLogEntry);
729 return entries;
730 }
731
LogContainsEventType(const RecordingNetLogObserver & net_log_observer,NetLogEventType expected)732 bool LogContainsEventType(const RecordingNetLogObserver& net_log_observer,
733 NetLogEventType expected) {
734 return !net_log_observer.GetEntriesWithType(expected).empty();
735 }
736
737 // Returns a TransportInfo distinct from the default for mock transactions,
738 // with the given port number.
TestTransportInfoWithPort(uint16_t port)739 TransportInfo TestTransportInfoWithPort(uint16_t port) {
740 TransportInfo result;
741 result.endpoint = IPEndPoint(IPAddress(42, 0, 1, 2), port);
742 return result;
743 }
744
745 // Returns a TransportInfo distinct from the default for mock transactions.
TestTransportInfo()746 TransportInfo TestTransportInfo() {
747 return TestTransportInfoWithPort(1337);
748 }
749
CachedTestTransportInfo()750 TransportInfo CachedTestTransportInfo() {
751 TransportInfo result = TestTransportInfo();
752 result.type = TransportType::kCached;
753 return result;
754 }
755
756 // Helper function, generating valid HTTP cache key from `url`.
757 // See also: HttpCache::GenerateCacheKey(..)
GenerateCacheKey(const std::string & url)758 std::string GenerateCacheKey(const std::string& url) {
759 return "1/0/" + url;
760 }
761
762 } // namespace
763
764 using HttpCacheTest = TestWithTaskEnvironment;
765
766 class HttpCacheIOCallbackTest : public HttpCacheTest {
767 public:
768 HttpCacheIOCallbackTest() = default;
769 ~HttpCacheIOCallbackTest() override = default;
770
771 // HttpCache::ActiveEntry is private, doing this allows tests to use it
772 using ActiveEntry = HttpCache::ActiveEntry;
773 using Transaction = HttpCache::Transaction;
774
775 // The below functions are forwarding calls to the HttpCache class.
OpenEntry(HttpCache * cache,const std::string & url,scoped_refptr<ActiveEntry> * entry,HttpCache::Transaction * trans)776 int OpenEntry(HttpCache* cache,
777 const std::string& url,
778 scoped_refptr<ActiveEntry>* entry,
779 HttpCache::Transaction* trans) {
780 return cache->OpenEntry(GenerateCacheKey(url), entry, trans);
781 }
782
OpenOrCreateEntry(HttpCache * cache,const std::string & url,scoped_refptr<ActiveEntry> * entry,HttpCache::Transaction * trans)783 int OpenOrCreateEntry(HttpCache* cache,
784 const std::string& url,
785 scoped_refptr<ActiveEntry>* entry,
786 HttpCache::Transaction* trans) {
787 return cache->OpenOrCreateEntry(GenerateCacheKey(url), entry, trans);
788 }
789
CreateEntry(HttpCache * cache,const std::string & url,scoped_refptr<ActiveEntry> * entry,HttpCache::Transaction * trans)790 int CreateEntry(HttpCache* cache,
791 const std::string& url,
792 scoped_refptr<ActiveEntry>* entry,
793 HttpCache::Transaction* trans) {
794 return cache->CreateEntry(GenerateCacheKey(url), entry, trans);
795 }
796
DoomEntry(HttpCache * cache,const std::string & url,HttpCache::Transaction * trans)797 int DoomEntry(HttpCache* cache,
798 const std::string& url,
799 HttpCache::Transaction* trans) {
800 return cache->DoomEntry(GenerateCacheKey(url), trans);
801 }
802 };
803
804 class HttpSplitCacheKeyTest : public HttpCacheTest {
805 public:
806 HttpSplitCacheKeyTest() = default;
807 ~HttpSplitCacheKeyTest() override = default;
808
ComputeCacheKey(const std::string & url_string)809 std::string ComputeCacheKey(const std::string& url_string) {
810 GURL url(url_string);
811 SchemefulSite site(url);
812 net::HttpRequestInfo request_info;
813 request_info.url = url;
814 request_info.method = "GET";
815 request_info.network_isolation_key = net::NetworkIsolationKey(site, site);
816 request_info.network_anonymization_key =
817 net::NetworkAnonymizationKey::CreateSameSite(site);
818 MockHttpCache cache;
819 return *cache.http_cache()->GenerateCacheKeyForRequest(&request_info);
820 }
821 };
822
823 //-----------------------------------------------------------------------------
824 // Tests.
825
TEST_F(HttpCacheTest,CreateThenDestroy)826 TEST_F(HttpCacheTest, CreateThenDestroy) {
827 MockHttpCache cache;
828
829 std::unique_ptr<HttpTransaction> trans;
830 EXPECT_THAT(cache.CreateTransaction(&trans), IsOk());
831 ASSERT_TRUE(trans.get());
832 }
833
TEST_F(HttpCacheTest,GetBackend)834 TEST_F(HttpCacheTest, GetBackend) {
835 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(0));
836
837 disk_cache::Backend* backend;
838 TestCompletionCallback cb;
839 // This will lazily initialize the backend.
840 int rv = cache.http_cache()->GetBackend(&backend, cb.callback());
841 EXPECT_THAT(cb.GetResult(rv), IsOk());
842 }
843
TEST_F(HttpCacheTest,SimpleGET)844 TEST_F(HttpCacheTest, SimpleGET) {
845 MockHttpCache cache;
846 LoadTimingInfo load_timing_info;
847
848 // Write to the cache.
849 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
850 NetLogWithSource::Make(NetLogSourceType::NONE),
851 &load_timing_info);
852
853 EXPECT_EQ(1, cache.network_layer()->transaction_count());
854 EXPECT_EQ(0, cache.disk_cache()->open_count());
855 EXPECT_EQ(1, cache.disk_cache()->create_count());
856 TestLoadTimingNetworkRequest(load_timing_info);
857 }
858
859 // This test verifies that the callback passed to SetConnectedCallback() is
860 // called once for simple GET calls that traverse the cache.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallback)861 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallback) {
862 MockHttpCache cache;
863
864 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
865 mock_transaction.transport_info = TestTransportInfo();
866 MockHttpRequest request(mock_transaction);
867
868 ConnectedHandler connected_handler;
869
870 std::unique_ptr<HttpTransaction> transaction;
871 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
872 ASSERT_THAT(transaction, NotNull());
873
874 transaction->SetConnectedCallback(connected_handler.Callback());
875
876 TestCompletionCallback callback;
877 ASSERT_THAT(
878 transaction->Start(&request, callback.callback(), NetLogWithSource()),
879 IsError(ERR_IO_PENDING));
880 EXPECT_THAT(callback.WaitForResult(), IsOk());
881
882 EXPECT_THAT(connected_handler.transports(), ElementsAre(TestTransportInfo()));
883 }
884
885 // This test verifies that when the callback passed to SetConnectedCallback()
886 // returns an error, the transaction fails with that error.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackReturnError)887 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackReturnError) {
888 MockHttpCache cache;
889 MockHttpRequest request(kSimpleGET_Transaction);
890 ConnectedHandler connected_handler;
891
892 std::unique_ptr<HttpTransaction> transaction;
893 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
894 ASSERT_THAT(transaction, NotNull());
895
896 // The exact error code does not matter. We only care that it is passed to
897 // the transaction's completion callback unmodified.
898 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
899 transaction->SetConnectedCallback(connected_handler.Callback());
900
901 TestCompletionCallback callback;
902 ASSERT_THAT(
903 transaction->Start(&request, callback.callback(), NetLogWithSource()),
904 IsError(ERR_IO_PENDING));
905 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));
906 }
907
908 // This test verifies that the callback passed to SetConnectedCallback() is
909 // called once for requests that hit the cache.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHit)910 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHit) {
911 MockHttpCache cache;
912
913 {
914 // Populate the cache.
915 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
916 mock_transaction.transport_info = TestTransportInfo();
917 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
918 }
919
920 // Establish a baseline.
921 EXPECT_EQ(1, cache.network_layer()->transaction_count());
922
923 // Load from the cache (only), observe the callback being called.
924
925 ConnectedHandler connected_handler;
926 MockHttpRequest request(kSimpleGET_Transaction);
927
928 std::unique_ptr<HttpTransaction> transaction;
929 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
930 ASSERT_THAT(transaction, NotNull());
931
932 transaction->SetConnectedCallback(connected_handler.Callback());
933
934 TestCompletionCallback callback;
935 ASSERT_THAT(
936 transaction->Start(&request, callback.callback(), NetLogWithSource()),
937 IsError(ERR_IO_PENDING));
938 EXPECT_THAT(callback.WaitForResult(), IsOk());
939
940 // Still only 1 transaction for the previous request. The connected callback
941 // was not called by a second network transaction.
942 EXPECT_EQ(1, cache.network_layer()->transaction_count());
943
944 EXPECT_THAT(connected_handler.transports(),
945 ElementsAre(CachedTestTransportInfo()));
946 }
947
948 // This test verifies that when the callback passed to SetConnectedCallback()
949 // is called for a request that hit the cache and returns an error, the cache
950 // entry is reusable.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnError)951 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHitReturnError) {
952 MockHttpCache cache;
953
954 {
955 // Populate the cache.
956 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
957 mock_transaction.transport_info = TestTransportInfo();
958 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
959 }
960
961 MockHttpRequest request(kSimpleGET_Transaction);
962
963 {
964 // Attempt to read from cache entry, but abort transaction due to a
965 // connected callback error.
966 ConnectedHandler connected_handler;
967 connected_handler.set_result(ERR_FAILED);
968
969 std::unique_ptr<HttpTransaction> transaction;
970 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
971 ASSERT_THAT(transaction, NotNull());
972
973 transaction->SetConnectedCallback(connected_handler.Callback());
974
975 TestCompletionCallback callback;
976 ASSERT_THAT(
977 transaction->Start(&request, callback.callback(), NetLogWithSource()),
978 IsError(ERR_IO_PENDING));
979 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));
980
981 // Used the cache entry only.
982 EXPECT_THAT(connected_handler.transports(),
983 ElementsAre(CachedTestTransportInfo()));
984 }
985
986 {
987 // Request the same resource once more, observe that it is read from cache.
988 ConnectedHandler connected_handler;
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(), IsOk());
1001
1002 // Used the cache entry only.
1003 EXPECT_THAT(connected_handler.transports(),
1004 ElementsAre(CachedTestTransportInfo()));
1005 }
1006 }
1007
1008 // This test verifies that when the callback passed to SetConnectedCallback()
1009 // returns `ERR_INCONSISTENT_IP_ADDRESS_SPACE`, the cache entry is invalidated.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnInconsistentIpError)1010 TEST_F(HttpCacheTest,
1011 SimpleGET_ConnectedCallbackOnCacheHitReturnInconsistentIpError) {
1012 MockHttpCache cache;
1013
1014 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1015 mock_transaction.transport_info = TestTransportInfo();
1016
1017 // Populate the cache.
1018 RunTransactionTest(cache.http_cache(), mock_transaction);
1019
1020 MockHttpRequest request(kSimpleGET_Transaction);
1021
1022 {
1023 // Attempt to read from cache entry, but abort transaction due to a
1024 // connected callback error.
1025 ConnectedHandler connected_handler;
1026 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
1027
1028 std::unique_ptr<HttpTransaction> transaction;
1029 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1030 ASSERT_THAT(transaction, NotNull());
1031
1032 transaction->SetConnectedCallback(connected_handler.Callback());
1033
1034 TestCompletionCallback callback;
1035 ASSERT_THAT(
1036 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1037 IsError(ERR_IO_PENDING));
1038 EXPECT_THAT(callback.WaitForResult(),
1039 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
1040
1041 // Used the cache entry only.
1042 EXPECT_THAT(connected_handler.transports(),
1043 ElementsAre(CachedTestTransportInfo()));
1044 }
1045
1046 {
1047 // Request the same resource once more, observe that it is not read from
1048 // cache.
1049 ConnectedHandler connected_handler;
1050
1051 std::unique_ptr<HttpTransaction> transaction;
1052 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1053 ASSERT_THAT(transaction, NotNull());
1054
1055 transaction->SetConnectedCallback(connected_handler.Callback());
1056
1057 TestCompletionCallback callback;
1058 ASSERT_THAT(
1059 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1060 IsError(ERR_IO_PENDING));
1061 EXPECT_THAT(callback.WaitForResult(), IsOk());
1062
1063 // Used the network only.
1064 EXPECT_THAT(connected_handler.transports(),
1065 ElementsAre(TestTransportInfo()));
1066 }
1067 }
1068
1069 // This test verifies that when the callback passed to SetConnectedCallback()
1070 // returns
1071 // `ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY`, the
1072 // cache entry is invalidated, and we'll retry the connection from the network.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitReturnPrivateNetworkAccessBlockedError)1073 TEST_F(
1074 HttpCacheTest,
1075 SimpleGET_ConnectedCallbackOnCacheHitReturnPrivateNetworkAccessBlockedError) {
1076 MockHttpCache cache;
1077
1078 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1079 mock_transaction.transport_info = TestTransportInfo();
1080
1081 // Populate the cache.
1082 RunTransactionTest(cache.http_cache(), mock_transaction);
1083
1084 MockHttpRequest request(kSimpleGET_Transaction);
1085
1086 {
1087 // Attempt to read from cache entry, but abort transaction due to a
1088 // connected callback error.
1089 ConnectedHandler connected_handler;
1090 connected_handler.set_result(
1091 ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY);
1092
1093 std::unique_ptr<HttpTransaction> transaction;
1094 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1095 ASSERT_THAT(transaction, NotNull());
1096
1097 transaction->SetConnectedCallback(connected_handler.Callback());
1098
1099 TestCompletionCallback callback;
1100 ASSERT_THAT(
1101 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1102 IsError(ERR_IO_PENDING));
1103 EXPECT_THAT(
1104 callback.WaitForResult(),
1105 IsError(
1106 ERR_CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY));
1107
1108 // Used the cache entry only.
1109 EXPECT_THAT(connected_handler.transports(),
1110 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
1111 }
1112
1113 {
1114 // Request the same resource once more, observe that it is not read from
1115 // cache.
1116 ConnectedHandler connected_handler;
1117
1118 std::unique_ptr<HttpTransaction> transaction;
1119 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1120 ASSERT_THAT(transaction, NotNull());
1121
1122 transaction->SetConnectedCallback(connected_handler.Callback());
1123
1124 TestCompletionCallback callback;
1125 ASSERT_THAT(
1126 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1127 IsError(ERR_IO_PENDING));
1128 EXPECT_THAT(callback.WaitForResult(), IsOk());
1129
1130 // Used the network only.
1131 EXPECT_THAT(connected_handler.transports(),
1132 ElementsAre(TestTransportInfo()));
1133 }
1134 }
1135
1136 // This test verifies that the callback passed to SetConnectedCallback() is
1137 // called with the right transport type when the cached entry was originally
1138 // fetched via proxy.
TEST_F(HttpCacheTest,SimpleGET_ConnectedCallbackOnCacheHitFromProxy)1139 TEST_F(HttpCacheTest, SimpleGET_ConnectedCallbackOnCacheHitFromProxy) {
1140 MockHttpCache cache;
1141
1142 TransportInfo proxied_transport_info = TestTransportInfo();
1143 proxied_transport_info.type = TransportType::kProxied;
1144
1145 {
1146 // Populate the cache.
1147 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
1148 mock_transaction.transport_info = proxied_transport_info;
1149 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1150 }
1151
1152 // Establish a baseline.
1153 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1154
1155 // Load from the cache (only), observe the callback being called.
1156
1157 ConnectedHandler connected_handler;
1158 MockHttpRequest request(kSimpleGET_Transaction);
1159
1160 std::unique_ptr<HttpTransaction> transaction;
1161 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
1162 ASSERT_THAT(transaction, NotNull());
1163
1164 transaction->SetConnectedCallback(connected_handler.Callback());
1165
1166 TestCompletionCallback callback;
1167 ASSERT_THAT(
1168 transaction->Start(&request, callback.callback(), NetLogWithSource()),
1169 IsError(ERR_IO_PENDING));
1170 EXPECT_THAT(callback.WaitForResult(), IsOk());
1171
1172 // Still only 1 transaction for the previous request. The connected callback
1173 // was not called by a second network transaction.
1174 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1175
1176 // The transport info mentions both the cache and the original proxy.
1177 TransportInfo expected_transport_info = TestTransportInfo();
1178 expected_transport_info.type = TransportType::kCachedFromProxy;
1179
1180 EXPECT_THAT(connected_handler.transports(),
1181 ElementsAre(expected_transport_info));
1182 }
1183
TEST_F(HttpCacheTest,SimpleGET_DelayedCacheLock)1184 TEST_F(HttpCacheTest, SimpleGET_DelayedCacheLock) {
1185 MockHttpCache cache;
1186 LoadTimingInfo load_timing_info;
1187
1188 // Configure the cache to delay the response for AddTransactionToEntry so it
1189 // gets sequenced behind any other tasks that get generated when starting the
1190 // transaction (i.e. network activity when run in parallel with the cache
1191 // lock).
1192 cache.http_cache()->DelayAddTransactionToEntryForTesting();
1193
1194 // Write to the cache.
1195 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
1196 NetLogWithSource::Make(NetLogSourceType::NONE),
1197 &load_timing_info);
1198
1199 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1200 EXPECT_EQ(0, cache.disk_cache()->open_count());
1201 EXPECT_EQ(1, cache.disk_cache()->create_count());
1202 TestLoadTimingNetworkRequest(load_timing_info);
1203 }
1204
1205 enum class SplitCacheTestCase {
1206 kSplitCacheDisabled,
1207 kSplitCacheNikFrameSiteEnabled,
1208 kSplitCacheNikCrossSiteFlagEnabled,
1209 kSplitCacheNikFrameSiteSharedOpaqueEnabled,
1210 };
1211
InitializeSplitCacheScopedFeatureList(base::test::ScopedFeatureList & scoped_feature_list,SplitCacheTestCase test_case)1212 void InitializeSplitCacheScopedFeatureList(
1213 base::test::ScopedFeatureList& scoped_feature_list,
1214 SplitCacheTestCase test_case) {
1215 std::vector<base::test::FeatureRef> enabled_features;
1216 std::vector<base::test::FeatureRef> disabled_features;
1217
1218 if (test_case == SplitCacheTestCase::kSplitCacheDisabled) {
1219 disabled_features.push_back(
1220 net::features::kSplitCacheByNetworkIsolationKey);
1221 } else {
1222 enabled_features.push_back(net::features::kSplitCacheByNetworkIsolationKey);
1223 }
1224
1225 if (test_case == SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled) {
1226 enabled_features.push_back(
1227 net::features::kEnableCrossSiteFlagNetworkIsolationKey);
1228 } else {
1229 disabled_features.push_back(
1230 net::features::kEnableCrossSiteFlagNetworkIsolationKey);
1231 }
1232
1233 if (test_case ==
1234 SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled) {
1235 enabled_features.push_back(
1236 net::features::kEnableFrameSiteSharedOpaqueNetworkIsolationKey);
1237 } else {
1238 disabled_features.push_back(
1239 net::features::kEnableFrameSiteSharedOpaqueNetworkIsolationKey);
1240 }
1241 scoped_feature_list.InitWithFeatures(enabled_features, disabled_features);
1242 }
1243
1244 class HttpCacheTest_SplitCacheFeature
1245 : public HttpCacheTest,
1246 public ::testing::WithParamInterface<SplitCacheTestCase> {
1247 public:
HttpCacheTest_SplitCacheFeature()1248 HttpCacheTest_SplitCacheFeature() {
1249 InitializeSplitCacheScopedFeatureList(feature_list_, GetParam());
1250 }
1251
IsSplitCacheEnabled() const1252 bool IsSplitCacheEnabled() const {
1253 return GetParam() != SplitCacheTestCase::kSplitCacheDisabled;
1254 }
1255
1256 private:
1257 base::test::ScopedFeatureList feature_list_;
1258 };
1259
TEST_P(HttpCacheTest_SplitCacheFeature,SimpleGETVerifyGoogleFontMetrics)1260 TEST_P(HttpCacheTest_SplitCacheFeature, SimpleGETVerifyGoogleFontMetrics) {
1261 SchemefulSite site_a(GURL("http://www.a.com"));
1262
1263 MockHttpCache cache;
1264
1265 ScopedMockTransaction transaction(
1266 kSimpleGET_Transaction,
1267 "http://themes.googleusercontent.com/static/fonts/roboto");
1268 MockHttpRequest request(transaction);
1269 request.network_isolation_key = NetworkIsolationKey(site_a, site_a);
1270 request.network_anonymization_key =
1271 net::NetworkAnonymizationKey::CreateSameSite(site_a);
1272
1273 // Attempt to populate the cache.
1274 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
1275 nullptr);
1276
1277 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
1278 nullptr);
1279 }
1280
1281 INSTANTIATE_TEST_SUITE_P(
1282 All,
1283 HttpCacheTest_SplitCacheFeature,
1284 testing::ValuesIn(
1285 {SplitCacheTestCase::kSplitCacheDisabled,
1286 SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled,
1287 SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled,
1288 SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled}),
__anone6acdaec0202(const testing::TestParamInfo<SplitCacheTestCase>& info) 1289 [](const testing::TestParamInfo<SplitCacheTestCase>& info) {
1290 switch (info.param) {
1291 case (SplitCacheTestCase::kSplitCacheDisabled):
1292 return "SplitCacheDisabled";
1293 case (SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled):
1294 return "SplitCacheNikFrameSiteEnabled";
1295 case (SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled):
1296 return "SplitCacheNikCrossSiteFlagEnabled";
1297 case (SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled):
1298 return "SplitCacheNikFrameSiteSharedOpaqueEnabled";
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(
1315 {SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled,
1316 SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled,
1317 SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled}),
__anone6acdaec0302(const testing::TestParamInfo<SplitCacheTestCase>& info) 1318 [](const testing::TestParamInfo<SplitCacheTestCase>& info) {
1319 switch (info.param) {
1320 case (SplitCacheTestCase::kSplitCacheDisabled):
1321 return "NotUsedForThisTestSuite";
1322 case (SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled):
1323 return "SplitCacheNikFrameSiteEnabled";
1324 case (SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled):
1325 return "SplitCacheNikCrossSiteFlagEnabled";
1326 case (SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled):
1327 return "SplitCacheNikFrameSiteSharedOpaqueEnabled";
1328 }
1329 });
1330
TEST_F(HttpCacheTest,SimpleGETNoDiskCache)1331 TEST_F(HttpCacheTest, SimpleGETNoDiskCache) {
1332 MockHttpCache cache;
1333
1334 cache.disk_cache()->set_fail_requests(true);
1335
1336 RecordingNetLogObserver net_log_observer;
1337 LoadTimingInfo load_timing_info;
1338
1339 // Read from the network, and don't use the cache.
1340 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
1341 NetLogWithSource::Make(NetLogSourceType::NONE),
1342 &load_timing_info);
1343
1344 // Check that the NetLog was filled as expected.
1345 // (We attempted to OpenOrCreate entries, but fail).
1346 auto entries = GetFilteredNetLogEntries(net_log_observer);
1347
1348 EXPECT_EQ(4u, entries.size());
1349 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1350 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1351 EXPECT_TRUE(
1352 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1353 EXPECT_TRUE(LogContainsBeginEvent(
1354 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1355 EXPECT_TRUE(LogContainsEndEvent(
1356 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1357
1358 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1359 EXPECT_EQ(0, cache.disk_cache()->open_count());
1360 EXPECT_EQ(0, cache.disk_cache()->create_count());
1361 TestLoadTimingNetworkRequest(load_timing_info);
1362 }
1363
TEST_F(HttpCacheTest,SimpleGETNoDiskCache2)1364 TEST_F(HttpCacheTest, SimpleGETNoDiskCache2) {
1365 // This will initialize a cache object with NULL backend.
1366 auto factory = std::make_unique<MockBlockingBackendFactory>();
1367 factory->set_fail(true);
1368 factory->FinishCreation(); // We'll complete synchronously.
1369 MockHttpCache cache(std::move(factory));
1370
1371 // Read from the network, and don't use the cache.
1372 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1373
1374 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1375 EXPECT_FALSE(cache.http_cache()->GetCurrentBackend());
1376 }
1377
1378 // Tests that IOBuffers are not referenced after IO completes.
TEST_F(HttpCacheTest,ReleaseBuffer)1379 TEST_F(HttpCacheTest, ReleaseBuffer) {
1380 MockHttpCache cache;
1381
1382 // Write to the cache.
1383 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1384
1385 MockHttpRequest request(kSimpleGET_Transaction);
1386 std::unique_ptr<HttpTransaction> trans;
1387 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
1388
1389 const int kBufferSize = 10;
1390 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
1391 ReleaseBufferCompletionCallback cb(buffer.get());
1392
1393 int rv = trans->Start(&request, cb.callback(), NetLogWithSource());
1394 EXPECT_THAT(cb.GetResult(rv), IsOk());
1395
1396 rv = trans->Read(buffer.get(), kBufferSize, cb.callback());
1397 EXPECT_EQ(kBufferSize, cb.GetResult(rv));
1398 }
1399
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures)1400 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures) {
1401 MockHttpCache cache;
1402
1403 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1404
1405 // Read from the network, and fail to write to the cache.
1406 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1407
1408 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1409 EXPECT_EQ(0, cache.disk_cache()->open_count());
1410 EXPECT_EQ(1, cache.disk_cache()->create_count());
1411
1412 // This one should see an empty cache again.
1413 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1414
1415 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1416 EXPECT_EQ(0, cache.disk_cache()->open_count());
1417 EXPECT_EQ(2, cache.disk_cache()->create_count());
1418 }
1419
1420 // Tests that disk failures after the transaction has started don't cause the
1421 // request to fail.
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures2)1422 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures2) {
1423 MockHttpCache cache;
1424
1425 MockHttpRequest request(kSimpleGET_Transaction);
1426
1427 auto c = std::make_unique<Context>();
1428 int rv = cache.CreateTransaction(&c->trans);
1429 ASSERT_THAT(rv, IsOk());
1430
1431 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
1432 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1433 rv = c->callback.WaitForResult();
1434
1435 // Start failing request now.
1436 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1437
1438 // We have to open the entry again to propagate the failure flag.
1439 disk_cache::Entry* en;
1440 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &en));
1441 en->Close();
1442
1443 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
1444 c.reset();
1445
1446 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1447 EXPECT_EQ(1, cache.disk_cache()->open_count());
1448 EXPECT_EQ(1, cache.disk_cache()->create_count());
1449
1450 // This one should see an empty cache again.
1451 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1452
1453 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1454 EXPECT_EQ(1, cache.disk_cache()->open_count());
1455 EXPECT_EQ(2, cache.disk_cache()->create_count());
1456 }
1457
1458 // Tests that we handle failures to read from the cache.
TEST_F(HttpCacheTest,SimpleGETWithDiskFailures3)1459 TEST_F(HttpCacheTest, SimpleGETWithDiskFailures3) {
1460 MockHttpCache cache;
1461
1462 // Read from the network, and write to the cache.
1463 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1464
1465 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1466 EXPECT_EQ(0, cache.disk_cache()->open_count());
1467 EXPECT_EQ(1, cache.disk_cache()->create_count());
1468
1469 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
1470
1471 MockHttpRequest request(kSimpleGET_Transaction);
1472
1473 // Now fail to read from the cache.
1474 auto c = std::make_unique<Context>();
1475 int rv = cache.CreateTransaction(&c->trans);
1476 ASSERT_THAT(rv, IsOk());
1477
1478 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
1479 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
1480
1481 // Now verify that the entry was removed from the cache.
1482 cache.disk_cache()->set_soft_failures_mask(0);
1483
1484 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1485 EXPECT_EQ(1, cache.disk_cache()->open_count());
1486 EXPECT_EQ(2, cache.disk_cache()->create_count());
1487
1488 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1489
1490 EXPECT_EQ(3, cache.network_layer()->transaction_count());
1491 EXPECT_EQ(1, cache.disk_cache()->open_count());
1492 EXPECT_EQ(3, cache.disk_cache()->create_count());
1493 }
1494
TEST_F(HttpCacheTest,SimpleGET_LoadOnlyFromCache_Hit)1495 TEST_F(HttpCacheTest, SimpleGET_LoadOnlyFromCache_Hit) {
1496 MockHttpCache cache;
1497
1498 RecordingNetLogObserver net_log_observer;
1499 NetLogWithSource net_log_with_source =
1500 NetLogWithSource::Make(NetLogSourceType::NONE);
1501 LoadTimingInfo load_timing_info;
1502
1503 // Write to the cache.
1504 RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction,
1505 net_log_with_source, &load_timing_info);
1506
1507 // Check that the NetLog was filled as expected.
1508 auto entries = GetFilteredNetLogEntries(net_log_observer);
1509
1510 EXPECT_EQ(6u, entries.size());
1511 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1512 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1513 EXPECT_TRUE(
1514 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1515 EXPECT_TRUE(LogContainsBeginEvent(
1516 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1517 EXPECT_TRUE(LogContainsEndEvent(
1518 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1519 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1520 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1521 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1522 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1523
1524 TestLoadTimingNetworkRequest(load_timing_info);
1525
1526 // Force this transaction to read from the cache.
1527 MockTransaction transaction(kSimpleGET_Transaction);
1528 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
1529
1530 net_log_observer.Clear();
1531
1532 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1533 net_log_with_source, &load_timing_info);
1534
1535 // Check that the NetLog was filled as expected.
1536 entries = GetFilteredNetLogEntries(net_log_observer);
1537
1538 EXPECT_EQ(8u, entries.size());
1539 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1540 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1541 EXPECT_TRUE(
1542 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1543 EXPECT_TRUE(LogContainsBeginEvent(
1544 entries, 2, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1545 EXPECT_TRUE(LogContainsEndEvent(
1546 entries, 3, NetLogEventType::HTTP_CACHE_OPEN_OR_CREATE_ENTRY));
1547 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1548 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1549 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1550 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1551 EXPECT_TRUE(
1552 LogContainsBeginEvent(entries, 6, NetLogEventType::HTTP_CACHE_READ_INFO));
1553 EXPECT_TRUE(
1554 LogContainsEndEvent(entries, 7, NetLogEventType::HTTP_CACHE_READ_INFO));
1555
1556 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1557 EXPECT_EQ(1, cache.disk_cache()->open_count());
1558 EXPECT_EQ(1, cache.disk_cache()->create_count());
1559 TestLoadTimingCachedResponse(load_timing_info);
1560 }
1561
TEST_F(HttpCacheTest,SimpleGET_LoadOnlyFromCache_Miss)1562 TEST_F(HttpCacheTest, SimpleGET_LoadOnlyFromCache_Miss) {
1563 MockHttpCache cache;
1564
1565 // force this transaction to read from the cache
1566 MockTransaction transaction(kSimpleGET_Transaction);
1567 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
1568
1569 MockHttpRequest request(transaction);
1570 TestCompletionCallback callback;
1571
1572 std::unique_ptr<HttpTransaction> trans;
1573 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
1574
1575 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1576 if (rv == ERR_IO_PENDING) {
1577 rv = callback.WaitForResult();
1578 }
1579 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
1580
1581 trans.reset();
1582
1583 EXPECT_EQ(0, cache.network_layer()->transaction_count());
1584 EXPECT_EQ(0, cache.disk_cache()->open_count());
1585 EXPECT_EQ(0, cache.disk_cache()->create_count());
1586 }
1587
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_Hit)1588 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_Hit) {
1589 MockHttpCache cache;
1590
1591 // write to the cache
1592 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1593
1594 // force this transaction to read from the cache if valid
1595 MockTransaction transaction(kSimpleGET_Transaction);
1596 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1597
1598 RunTransactionTest(cache.http_cache(), transaction);
1599
1600 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1601 EXPECT_EQ(1, cache.disk_cache()->open_count());
1602 EXPECT_EQ(1, cache.disk_cache()->create_count());
1603 }
1604
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_Miss)1605 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_Miss) {
1606 MockHttpCache cache;
1607
1608 // force this transaction to read from the cache if valid
1609 MockTransaction transaction(kSimpleGET_Transaction);
1610 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1611
1612 RunTransactionTest(cache.http_cache(), transaction);
1613
1614 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1615 EXPECT_EQ(0, cache.disk_cache()->open_count());
1616 EXPECT_EQ(1, cache.disk_cache()->create_count());
1617 }
1618
1619 // Tests LOAD_SKIP_CACHE_VALIDATION in the presence of vary headers.
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_VaryMatch)1620 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_VaryMatch) {
1621 MockHttpCache cache;
1622
1623 // Write to the cache.
1624 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1625 transaction.request_headers = "Foo: bar\r\n";
1626 transaction.response_headers =
1627 "Cache-Control: max-age=10000\n"
1628 "Vary: Foo\n";
1629 RunTransactionTest(cache.http_cache(), transaction);
1630
1631 // Read from the cache.
1632 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1633 RunTransactionTest(cache.http_cache(), transaction);
1634
1635 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1636 EXPECT_EQ(1, cache.disk_cache()->open_count());
1637 EXPECT_EQ(1, cache.disk_cache()->create_count());
1638 }
1639
1640 // Tests LOAD_SKIP_CACHE_VALIDATION in the presence of vary headers.
TEST_F(HttpCacheTest,SimpleGET_LoadPreferringCache_VaryMismatch)1641 TEST_F(HttpCacheTest, SimpleGET_LoadPreferringCache_VaryMismatch) {
1642 MockHttpCache cache;
1643
1644 // Write to the cache.
1645 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1646 transaction.request_headers = "Foo: bar\r\n";
1647 transaction.response_headers =
1648 "Cache-Control: max-age=10000\n"
1649 "Vary: Foo\n";
1650 RunTransactionTest(cache.http_cache(), transaction);
1651
1652 // Attempt to read from the cache... this is a vary mismatch that must reach
1653 // the network again.
1654 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1655 transaction.request_headers = "Foo: none\r\n";
1656 LoadTimingInfo load_timing_info;
1657 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1658 NetLogWithSource::Make(NetLogSourceType::NONE),
1659 &load_timing_info);
1660
1661 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1662 EXPECT_EQ(1, cache.disk_cache()->open_count());
1663 EXPECT_EQ(1, cache.disk_cache()->create_count());
1664 TestLoadTimingNetworkRequest(load_timing_info);
1665 }
1666
1667 // Tests that we honor Vary: * with LOAD_SKIP_CACHE_VALIDATION (crbug/778681)
TEST_F(HttpCacheTest,SimpleGET_LoadSkipCacheValidation_VaryStar)1668 TEST_F(HttpCacheTest, SimpleGET_LoadSkipCacheValidation_VaryStar) {
1669 MockHttpCache cache;
1670
1671 // Write to the cache.
1672 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1673 transaction.response_headers =
1674 "Cache-Control: max-age=10000\n"
1675 "Vary: *\n";
1676 RunTransactionTest(cache.http_cache(), transaction);
1677
1678 // Attempt to read from the cache... we will still load it from network,
1679 // since Vary: * doesn't match.
1680 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
1681 LoadTimingInfo load_timing_info;
1682 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1683 NetLogWithSource::Make(NetLogSourceType::NONE),
1684 &load_timing_info);
1685
1686 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1687 EXPECT_EQ(1, cache.disk_cache()->open_count());
1688 EXPECT_EQ(1, cache.disk_cache()->create_count());
1689 }
1690
1691 // Tests that was_cached was set properly on a failure, even if the cached
1692 // response wasn't returned.
TEST_F(HttpCacheTest,SimpleGET_CacheSignal_Failure)1693 TEST_F(HttpCacheTest, SimpleGET_CacheSignal_Failure) {
1694 for (bool use_memory_entry_data : {false, true}) {
1695 MockHttpCache cache;
1696 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
1697
1698 // Prime cache.
1699 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1700 transaction.response_headers = "Cache-Control: no-cache\n";
1701
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
1707 // Network failure with error; should fail but have was_cached set.
1708 transaction.start_return_code = ERR_FAILED;
1709
1710 MockHttpRequest request(transaction);
1711 TestCompletionCallback callback;
1712 std::unique_ptr<HttpTransaction> trans;
1713 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
1714 EXPECT_THAT(rv, IsOk());
1715 ASSERT_TRUE(trans.get());
1716 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1717 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
1718
1719 const HttpResponseInfo* response_info = trans->GetResponseInfo();
1720 ASSERT_TRUE(response_info);
1721 // If use_memory_entry_data is true, we will not bother opening the entry,
1722 // and just kick it out, so was_cached will end up false.
1723 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1724 if (use_memory_entry_data) {
1725 EXPECT_EQ(false, response_info->was_cached);
1726 EXPECT_EQ(2, cache.disk_cache()->create_count());
1727 EXPECT_EQ(0, cache.disk_cache()->open_count());
1728 } else {
1729 EXPECT_EQ(true, response_info->was_cached);
1730 EXPECT_EQ(1, cache.disk_cache()->create_count());
1731 EXPECT_EQ(1, cache.disk_cache()->open_count());
1732 }
1733 }
1734 }
1735
1736 // Tests that if the transaction is destroyed right after setting the
1737 // cache_entry_status_ as CANT_CONDITIONALIZE, then RecordHistograms should not
1738 // hit a dcheck.
TEST_F(HttpCacheTest,RecordHistogramsCantConditionalize)1739 TEST_F(HttpCacheTest, RecordHistogramsCantConditionalize) {
1740 MockHttpCache cache;
1741 cache.disk_cache()->set_support_in_memory_entry_data(true);
1742
1743 {
1744 // Prime cache.
1745 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1746 transaction.response_headers = "Cache-Control: no-cache\n";
1747 RunTransactionTest(cache.http_cache(), transaction);
1748 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1749 EXPECT_EQ(1, cache.disk_cache()->create_count());
1750 EXPECT_EQ(0, cache.disk_cache()->open_count());
1751 }
1752
1753 {
1754 ScopedMockTransaction transaction(kSimpleGET_Transaction);
1755 MockHttpRequest request(transaction);
1756 TestCompletionCallback callback;
1757 std::unique_ptr<HttpTransaction> trans;
1758 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
1759 EXPECT_THAT(rv, IsOk());
1760 ASSERT_TRUE(trans.get());
1761 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
1762 // Now destroy the transaction so that RecordHistograms gets invoked.
1763 trans.reset();
1764 }
1765 }
1766
1767 // Confirm if we have an empty cache, a read is marked as network verified.
TEST_F(HttpCacheTest,SimpleGET_NetworkAccessed_Network)1768 TEST_F(HttpCacheTest, SimpleGET_NetworkAccessed_Network) {
1769 MockHttpCache cache;
1770
1771 // write to the cache
1772 HttpResponseInfo response_info;
1773 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
1774 &response_info);
1775
1776 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1777 EXPECT_EQ(0, cache.disk_cache()->open_count());
1778 EXPECT_EQ(1, cache.disk_cache()->create_count());
1779 EXPECT_TRUE(response_info.network_accessed);
1780 EXPECT_EQ(CacheEntryStatus::ENTRY_NOT_IN_CACHE,
1781 response_info.cache_entry_status);
1782 }
1783
1784 // Confirm if we have a fresh entry in cache, it isn't marked as
1785 // network verified.
TEST_F(HttpCacheTest,SimpleGET_NetworkAccessed_Cache)1786 TEST_F(HttpCacheTest, SimpleGET_NetworkAccessed_Cache) {
1787 MockHttpCache cache;
1788
1789 // Prime cache.
1790 MockTransaction transaction(kSimpleGET_Transaction);
1791
1792 RunTransactionTest(cache.http_cache(), transaction);
1793 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1794 EXPECT_EQ(1, cache.disk_cache()->create_count());
1795
1796 // Re-run transaction; make sure we don't mark the network as accessed.
1797 HttpResponseInfo response_info;
1798 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
1799 &response_info);
1800
1801 EXPECT_EQ(1, cache.network_layer()->transaction_count());
1802 EXPECT_FALSE(response_info.network_accessed);
1803 EXPECT_EQ(CacheEntryStatus::ENTRY_USED, response_info.cache_entry_status);
1804 }
1805
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache)1806 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache) {
1807 MockHttpCache cache;
1808
1809 // Write to the cache.
1810 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1811
1812 // Force this transaction to write to the cache again.
1813 MockTransaction transaction(kSimpleGET_Transaction);
1814 transaction.load_flags |= LOAD_BYPASS_CACHE;
1815
1816 RecordingNetLogObserver net_log_observer;
1817 LoadTimingInfo load_timing_info;
1818
1819 // Write to the cache.
1820 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
1821 NetLogWithSource::Make(NetLogSourceType::NONE),
1822 &load_timing_info);
1823
1824 // Check that the NetLog was filled as expected.
1825 auto entries = GetFilteredNetLogEntries(net_log_observer);
1826
1827 EXPECT_EQ(8u, entries.size());
1828 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
1829 NetLogEventType::HTTP_CACHE_GET_BACKEND));
1830 EXPECT_TRUE(
1831 LogContainsEndEvent(entries, 1, NetLogEventType::HTTP_CACHE_GET_BACKEND));
1832 EXPECT_TRUE(LogContainsBeginEvent(entries, 2,
1833 NetLogEventType::HTTP_CACHE_DOOM_ENTRY));
1834 EXPECT_TRUE(
1835 LogContainsEndEvent(entries, 3, NetLogEventType::HTTP_CACHE_DOOM_ENTRY));
1836 EXPECT_TRUE(LogContainsBeginEvent(entries, 4,
1837 NetLogEventType::HTTP_CACHE_CREATE_ENTRY));
1838 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
1839 NetLogEventType::HTTP_CACHE_CREATE_ENTRY));
1840 EXPECT_TRUE(LogContainsBeginEvent(entries, 6,
1841 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1842 EXPECT_TRUE(LogContainsEndEvent(entries, 7,
1843 NetLogEventType::HTTP_CACHE_ADD_TO_ENTRY));
1844
1845 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1846 EXPECT_EQ(0, cache.disk_cache()->open_count());
1847 EXPECT_EQ(2, cache.disk_cache()->create_count());
1848 TestLoadTimingNetworkRequest(load_timing_info);
1849 }
1850
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache_Implicit)1851 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache_Implicit) {
1852 MockHttpCache cache;
1853
1854 // write to the cache
1855 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1856
1857 // force this transaction to write to the cache again
1858 MockTransaction transaction(kSimpleGET_Transaction);
1859 transaction.request_headers = "pragma: no-cache\r\n";
1860
1861 RunTransactionTest(cache.http_cache(), transaction);
1862
1863 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1864 EXPECT_EQ(0, cache.disk_cache()->open_count());
1865 EXPECT_EQ(2, cache.disk_cache()->create_count());
1866 }
1867
TEST_F(HttpCacheTest,SimpleGET_LoadBypassCache_Implicit2)1868 TEST_F(HttpCacheTest, SimpleGET_LoadBypassCache_Implicit2) {
1869 MockHttpCache cache;
1870
1871 // write to the cache
1872 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1873
1874 // force this transaction to write to the cache again
1875 MockTransaction transaction(kSimpleGET_Transaction);
1876 transaction.request_headers = "cache-control: no-cache\r\n";
1877
1878 RunTransactionTest(cache.http_cache(), transaction);
1879
1880 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1881 EXPECT_EQ(0, cache.disk_cache()->open_count());
1882 EXPECT_EQ(2, cache.disk_cache()->create_count());
1883 }
1884
TEST_F(HttpCacheTest,SimpleGET_LoadValidateCache)1885 TEST_F(HttpCacheTest, SimpleGET_LoadValidateCache) {
1886 MockHttpCache cache;
1887
1888 // Write to the cache.
1889 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1890
1891 // Read from the cache.
1892 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1893
1894 // Force this transaction to validate the cache.
1895 MockTransaction transaction(kSimpleGET_Transaction);
1896 transaction.load_flags |= LOAD_VALIDATE_CACHE;
1897
1898 HttpResponseInfo response_info;
1899 LoadTimingInfo load_timing_info;
1900 RunTransactionTestWithResponseInfoAndGetTiming(
1901 cache.http_cache(), transaction, &response_info,
1902 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
1903
1904 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1905 EXPECT_EQ(1, cache.disk_cache()->open_count());
1906 EXPECT_EQ(1, cache.disk_cache()->create_count());
1907 EXPECT_TRUE(response_info.network_accessed);
1908 TestLoadTimingNetworkRequest(load_timing_info);
1909 }
1910
TEST_F(HttpCacheTest,SimpleGET_LoadValidateCache_Implicit)1911 TEST_F(HttpCacheTest, SimpleGET_LoadValidateCache_Implicit) {
1912 MockHttpCache cache;
1913
1914 // write to the cache
1915 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1916
1917 // read from the cache
1918 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
1919
1920 // force this transaction to validate the cache
1921 MockTransaction transaction(kSimpleGET_Transaction);
1922 transaction.request_headers = "cache-control: max-age=0\r\n";
1923
1924 RunTransactionTest(cache.http_cache(), transaction);
1925
1926 EXPECT_EQ(2, cache.network_layer()->transaction_count());
1927 EXPECT_EQ(1, cache.disk_cache()->open_count());
1928 EXPECT_EQ(1, cache.disk_cache()->create_count());
1929 }
1930
1931 // Tests that |unused_since_prefetch| is updated accordingly (e.g. it is set to
1932 // true after a prefetch and set back to false when the prefetch is used).
TEST_F(HttpCacheTest,SimpleGET_UnusedSincePrefetch)1933 TEST_F(HttpCacheTest, SimpleGET_UnusedSincePrefetch) {
1934 MockHttpCache cache;
1935 HttpResponseInfo response_info;
1936
1937 // A normal load does not have |unused_since_prefetch| set.
1938 RunTransactionTestWithResponseInfoAndGetTiming(
1939 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1940 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1941 EXPECT_FALSE(response_info.unused_since_prefetch);
1942 EXPECT_FALSE(response_info.was_cached);
1943
1944 // The prefetch itself does not have |unused_since_prefetch| set.
1945 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
1946 prefetch_transaction.load_flags |= LOAD_PREFETCH;
1947 RunTransactionTestWithResponseInfoAndGetTiming(
1948 cache.http_cache(), prefetch_transaction, &response_info,
1949 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1950 EXPECT_FALSE(response_info.unused_since_prefetch);
1951 EXPECT_TRUE(response_info.was_cached);
1952
1953 // A duplicated prefetch has |unused_since_prefetch| set.
1954 RunTransactionTestWithResponseInfoAndGetTiming(
1955 cache.http_cache(), prefetch_transaction, &response_info,
1956 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1957 EXPECT_TRUE(response_info.unused_since_prefetch);
1958 EXPECT_TRUE(response_info.was_cached);
1959
1960 // |unused_since_prefetch| is still true after two prefetches in a row.
1961 RunTransactionTestWithResponseInfoAndGetTiming(
1962 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1963 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1964 EXPECT_TRUE(response_info.unused_since_prefetch);
1965 EXPECT_TRUE(response_info.was_cached);
1966
1967 // The resource has now been used, back to normal behavior.
1968 RunTransactionTestWithResponseInfoAndGetTiming(
1969 cache.http_cache(), kSimpleGET_Transaction, &response_info,
1970 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1971 EXPECT_FALSE(response_info.unused_since_prefetch);
1972 EXPECT_TRUE(response_info.was_cached);
1973 }
1974
1975 // Tests that requests made with the LOAD_RESTRICTED_PREFETCH load flag result
1976 // in HttpResponseInfo entries with the |restricted_prefetch| flag set. Also
1977 // tests that responses with |restricted_prefetch| flag set can only be used by
1978 // requests that have the LOAD_CAN_USE_RESTRICTED_PREFETCH load flag.
TEST_F(HttpCacheTest,SimpleGET_RestrictedPrefetchIsRestrictedUntilReuse)1979 TEST_F(HttpCacheTest, SimpleGET_RestrictedPrefetchIsRestrictedUntilReuse) {
1980 MockHttpCache cache;
1981 HttpResponseInfo response_info;
1982
1983 // A normal load does not have |restricted_prefetch| set.
1984 RunTransactionTestWithResponseInfoAndGetTiming(
1985 cache.http_cache(), kTypicalGET_Transaction, &response_info,
1986 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1987 EXPECT_FALSE(response_info.restricted_prefetch);
1988 EXPECT_FALSE(response_info.was_cached);
1989 EXPECT_TRUE(response_info.network_accessed);
1990
1991 // A restricted prefetch is marked as |restricted_prefetch|.
1992 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
1993 prefetch_transaction.load_flags |= LOAD_PREFETCH;
1994 prefetch_transaction.load_flags |= LOAD_RESTRICTED_PREFETCH;
1995 RunTransactionTestWithResponseInfoAndGetTiming(
1996 cache.http_cache(), prefetch_transaction, &response_info,
1997 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
1998 EXPECT_TRUE(response_info.restricted_prefetch);
1999 EXPECT_FALSE(response_info.was_cached);
2000 EXPECT_TRUE(response_info.network_accessed);
2001
2002 // Requests that are marked as able to reuse restricted prefetches can do so
2003 // correctly. Once it is reused, it is no longer considered as or marked
2004 // restricted.
2005 MockTransaction can_use_restricted_prefetch_transaction(
2006 kSimpleGET_Transaction);
2007 can_use_restricted_prefetch_transaction.load_flags |=
2008 LOAD_CAN_USE_RESTRICTED_PREFETCH;
2009 RunTransactionTestWithResponseInfoAndGetTiming(
2010 cache.http_cache(), can_use_restricted_prefetch_transaction,
2011 &response_info, NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2012 EXPECT_TRUE(response_info.restricted_prefetch);
2013 EXPECT_TRUE(response_info.was_cached);
2014 EXPECT_FALSE(response_info.network_accessed);
2015
2016 // Later reuse is still no longer marked restricted.
2017 RunTransactionTestWithResponseInfoAndGetTiming(
2018 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2019 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2020 EXPECT_FALSE(response_info.restricted_prefetch);
2021 EXPECT_TRUE(response_info.was_cached);
2022 EXPECT_FALSE(response_info.network_accessed);
2023 }
2024
TEST_F(HttpCacheTest,SimpleGET_RestrictedPrefetchReuseIsLimited)2025 TEST_F(HttpCacheTest, SimpleGET_RestrictedPrefetchReuseIsLimited) {
2026 MockHttpCache cache;
2027 HttpResponseInfo response_info;
2028
2029 // A restricted prefetch is marked as |restricted_prefetch|.
2030 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
2031 prefetch_transaction.load_flags |= LOAD_PREFETCH;
2032 prefetch_transaction.load_flags |= LOAD_RESTRICTED_PREFETCH;
2033 RunTransactionTestWithResponseInfoAndGetTiming(
2034 cache.http_cache(), prefetch_transaction, &response_info,
2035 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2036 EXPECT_TRUE(response_info.restricted_prefetch);
2037 EXPECT_FALSE(response_info.was_cached);
2038 EXPECT_TRUE(response_info.network_accessed);
2039
2040 // Requests that cannot reuse restricted prefetches fail to do so. The network
2041 // is accessed and the resulting response is not marked as
2042 // |restricted_prefetch|.
2043 RunTransactionTestWithResponseInfoAndGetTiming(
2044 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2045 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2046 EXPECT_FALSE(response_info.restricted_prefetch);
2047 EXPECT_FALSE(response_info.was_cached);
2048 EXPECT_TRUE(response_info.network_accessed);
2049
2050 // Future requests that are not marked as able to reuse restricted prefetches
2051 // can use the entry in the cache now, since it has been evicted in favor of
2052 // an unrestricted one.
2053 RunTransactionTestWithResponseInfoAndGetTiming(
2054 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2055 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2056 EXPECT_FALSE(response_info.restricted_prefetch);
2057 EXPECT_TRUE(response_info.was_cached);
2058 EXPECT_FALSE(response_info.network_accessed);
2059 }
2060
TEST_F(HttpCacheTest,SimpleGET_UnusedSincePrefetchWriteError)2061 TEST_F(HttpCacheTest, SimpleGET_UnusedSincePrefetchWriteError) {
2062 MockHttpCache cache;
2063 HttpResponseInfo response_info;
2064
2065 // Do a prefetch.
2066 MockTransaction prefetch_transaction(kSimpleGET_Transaction);
2067 prefetch_transaction.load_flags |= LOAD_PREFETCH;
2068 RunTransactionTestWithResponseInfoAndGetTiming(
2069 cache.http_cache(), prefetch_transaction, &response_info,
2070 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2071 EXPECT_TRUE(response_info.unused_since_prefetch);
2072 EXPECT_FALSE(response_info.was_cached);
2073
2074 // Try to use it while injecting a failure on write.
2075 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_WRITE);
2076 RunTransactionTestWithResponseInfoAndGetTiming(
2077 cache.http_cache(), kSimpleGET_Transaction, &response_info,
2078 NetLogWithSource::Make(NetLogSourceType::NONE), nullptr);
2079 }
2080
2081 // Make sure that if a prefetch entry is truncated, then an attempt to re-use it
2082 // gets aborted in connected handler that truncated bit is not lost.
TEST_F(HttpCacheTest,PrefetchTruncateCancelInConnectedCallback)2083 TEST_F(HttpCacheTest, PrefetchTruncateCancelInConnectedCallback) {
2084 MockHttpCache cache;
2085
2086 ScopedMockTransaction transaction(kSimpleGET_Transaction);
2087 transaction.response_headers =
2088 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2089 "Content-Length: 20\n"
2090 "Etag: \"foopy\"\n";
2091 transaction.data = "01234567890123456789";
2092 transaction.load_flags |= LOAD_PREFETCH | LOAD_CAN_USE_RESTRICTED_PREFETCH;
2093
2094 // Do a truncated read of a prefetch request.
2095 {
2096 MockHttpRequest request(transaction);
2097 Context c;
2098
2099 int rv = cache.CreateTransaction(&c.trans);
2100 ASSERT_THAT(rv, IsOk());
2101
2102 rv = c.callback.GetResult(
2103 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2104 ASSERT_THAT(rv, IsOk());
2105
2106 // Read less than the whole thing.
2107 scoped_refptr<IOBufferWithSize> buf =
2108 base::MakeRefCounted<IOBufferWithSize>(10);
2109 rv = c.callback.GetResult(
2110 c.trans->Read(buf.get(), buf->size(), c.callback.callback()));
2111 EXPECT_EQ(buf->size(), rv);
2112
2113 // Destroy the transaction.
2114 c.trans.reset();
2115 base::RunLoop().RunUntilIdle();
2116
2117 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2118 /*data_size=*/10);
2119 }
2120
2121 // Do a fetch that can use prefetch that aborts in connected handler.
2122 transaction.load_flags &= ~LOAD_PREFETCH;
2123 {
2124 MockHttpRequest request(transaction);
2125 Context c;
2126
2127 int rv = cache.CreateTransaction(&c.trans);
2128 ASSERT_THAT(rv, IsOk());
2129 c.trans->SetConnectedCallback(base::BindRepeating(
2130 [](const TransportInfo& info, CompletionOnceCallback callback) -> int {
2131 return net::ERR_ABORTED;
2132 }));
2133 rv = c.callback.GetResult(
2134 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2135 EXPECT_EQ(net::ERR_ABORTED, rv);
2136
2137 // Destroy the transaction.
2138 c.trans.reset();
2139 base::RunLoop().RunUntilIdle();
2140
2141 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2142 /*data_size=*/10);
2143 }
2144
2145 // Now try again without abort.
2146 {
2147 MockHttpRequest request(transaction);
2148 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
2149 /*response_info=*/nullptr);
2150 base::RunLoop().RunUntilIdle();
2151
2152 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/false,
2153 /*data_size=*/20);
2154 }
2155 }
2156
2157 // Make sure that if a stale-while-revalidate entry is truncated, then an
2158 // attempt to re-use it gets aborted in connected handler that truncated bit is
2159 // not lost.
TEST_F(HttpCacheTest,StaleWhiteRevalidateTruncateCancelInConnectedCallback)2160 TEST_F(HttpCacheTest, StaleWhiteRevalidateTruncateCancelInConnectedCallback) {
2161 MockHttpCache cache;
2162
2163 ScopedMockTransaction transaction(kSimpleGET_Transaction);
2164 transaction.response_headers =
2165 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2166 "Content-Length: 20\n"
2167 "Cache-Control: max-age=0, stale-while-revalidate=60\n"
2168 "Etag: \"foopy\"\n";
2169 transaction.data = "01234567890123456789";
2170 transaction.load_flags |= LOAD_SUPPORT_ASYNC_REVALIDATION;
2171
2172 // Do a truncated read of a stale-while-revalidate resource.
2173 {
2174 MockHttpRequest request(transaction);
2175 Context c;
2176
2177 int rv = cache.CreateTransaction(&c.trans);
2178 ASSERT_THAT(rv, IsOk());
2179
2180 rv = c.callback.GetResult(
2181 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2182 ASSERT_THAT(rv, IsOk());
2183
2184 // Read less than the whole thing.
2185 scoped_refptr<IOBufferWithSize> buf =
2186 base::MakeRefCounted<IOBufferWithSize>(10);
2187 rv = c.callback.GetResult(
2188 c.trans->Read(buf.get(), buf->size(), c.callback.callback()));
2189 EXPECT_EQ(buf->size(), rv);
2190
2191 // Destroy the transaction.
2192 c.trans.reset();
2193 base::RunLoop().RunUntilIdle();
2194
2195 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2196 /*data_size=*/10);
2197 }
2198
2199 // Do a fetch that uses that resource that aborts in connected handler.
2200 {
2201 MockHttpRequest request(transaction);
2202 Context c;
2203
2204 int rv = cache.CreateTransaction(&c.trans);
2205 ASSERT_THAT(rv, IsOk());
2206 c.trans->SetConnectedCallback(base::BindRepeating(
2207 [](const TransportInfo& info, CompletionOnceCallback callback) -> int {
2208 return net::ERR_ABORTED;
2209 }));
2210 rv = c.callback.GetResult(
2211 c.trans->Start(&request, c.callback.callback(), NetLogWithSource()));
2212 EXPECT_EQ(net::ERR_ABORTED, rv);
2213
2214 // Destroy the transaction.
2215 c.trans.reset();
2216 base::RunLoop().RunUntilIdle();
2217
2218 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/true,
2219 /*data_size=*/10);
2220 }
2221
2222 // Now try again without abort.
2223 {
2224 MockHttpRequest request(transaction);
2225 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
2226 /*response_info=*/nullptr);
2227 base::RunLoop().RunUntilIdle();
2228
2229 VerifyTruncatedFlag(&cache, request.CacheKey(), /*flag_value=*/false,
2230 /*data_size=*/20);
2231 }
2232 }
2233
2234 static const auto kPreserveRequestHeaders =
2235 base::BindRepeating([](const net::HttpRequestInfo* request,
2236 std::string* response_status,
2237 std::string* response_headers,
__anone6acdaec0602(const net::HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) 2238 std::string* response_data) {
2239 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
2240 });
2241
2242 // Tests that we don't remove extra headers for simple requests.
TEST_F(HttpCacheTest,SimpleGET_PreserveRequestHeaders)2243 TEST_F(HttpCacheTest, SimpleGET_PreserveRequestHeaders) {
2244 for (bool use_memory_entry_data : {false, true}) {
2245 MockHttpCache cache;
2246 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
2247
2248 ScopedMockTransaction transaction(kSimpleGET_Transaction);
2249 transaction.handler = kPreserveRequestHeaders;
2250 transaction.request_headers = EXTRA_HEADER;
2251 transaction.response_headers = "Cache-Control: max-age=0\n";
2252
2253 // Write, then revalidate the entry.
2254 RunTransactionTest(cache.http_cache(), transaction);
2255 RunTransactionTest(cache.http_cache(), transaction);
2256
2257 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2258
2259 // If the backend supports memory entry data, we can figure out that the
2260 // entry has caching-hostile headers w/o opening it.
2261 if (use_memory_entry_data) {
2262 EXPECT_EQ(0, cache.disk_cache()->open_count());
2263 EXPECT_EQ(2, cache.disk_cache()->create_count());
2264 } else {
2265 EXPECT_EQ(1, cache.disk_cache()->open_count());
2266 EXPECT_EQ(1, cache.disk_cache()->create_count());
2267 }
2268 }
2269 }
2270
2271 // Tests that we don't remove extra headers for conditionalized requests.
TEST_F(HttpCacheTest,ConditionalizedGET_PreserveRequestHeaders)2272 TEST_F(HttpCacheTest, ConditionalizedGET_PreserveRequestHeaders) {
2273 for (bool use_memory_entry_data : {false, true}) {
2274 MockHttpCache cache;
2275 // Unlike in SimpleGET_PreserveRequestHeaders, this entry can be
2276 // conditionalized, so memory hints don't affect behavior.
2277 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
2278
2279 // Write to the cache.
2280 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
2281
2282 ScopedMockTransaction transaction(kETagGET_Transaction);
2283 transaction.handler = kPreserveRequestHeaders;
2284 transaction.request_headers = "If-None-Match: \"foopy\"\r\n" EXTRA_HEADER;
2285
2286 RunTransactionTest(cache.http_cache(), transaction);
2287
2288 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2289 EXPECT_EQ(1, cache.disk_cache()->open_count());
2290 EXPECT_EQ(1, cache.disk_cache()->create_count());
2291 }
2292 }
2293
TEST_F(HttpCacheTest,SimpleGET_ManyReaders)2294 TEST_F(HttpCacheTest, SimpleGET_ManyReaders) {
2295 MockHttpCache cache;
2296
2297 MockHttpRequest request(kSimpleGET_Transaction);
2298
2299 std::vector<std::unique_ptr<Context>> context_list;
2300 const int kNumTransactions = 5;
2301
2302 for (int i = 0; i < kNumTransactions; ++i) {
2303 context_list.push_back(std::make_unique<Context>());
2304 auto& c = context_list[i];
2305
2306 c->result = cache.CreateTransaction(&c->trans);
2307 ASSERT_THAT(c->result, IsOk());
2308 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2309
2310 c->result =
2311 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2312 }
2313
2314 // All requests are waiting for the active entry.
2315 for (auto& context : context_list) {
2316 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
2317 }
2318
2319 // Allow all requests to move from the Create queue to the active entry.
2320 base::RunLoop().RunUntilIdle();
2321
2322 // All requests are added to writers.
2323 std::string cache_key = request.CacheKey();
2324 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
2325
2326 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2327 EXPECT_EQ(0, cache.disk_cache()->open_count());
2328 EXPECT_EQ(1, cache.disk_cache()->create_count());
2329
2330 // All requests are between Start and Read, i.e. idle.
2331 for (auto& context : context_list) {
2332 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
2333 }
2334
2335 for (int i = 0; i < kNumTransactions; ++i) {
2336 auto& c = context_list[i];
2337 if (c->result == ERR_IO_PENDING) {
2338 c->result = c->callback.WaitForResult();
2339 }
2340
2341 // After the 1st transaction has completed the response, all transactions
2342 // get added to readers.
2343 if (i > 0) {
2344 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
2345 EXPECT_EQ(kNumTransactions - i, cache.GetCountReaders(cache_key));
2346 }
2347
2348 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
2349 }
2350
2351 // We should not have had to re-open the disk entry
2352 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2353 EXPECT_EQ(0, cache.disk_cache()->open_count());
2354 EXPECT_EQ(1, cache.disk_cache()->create_count());
2355 }
2356
TEST_F(HttpCacheTest,RangeGET_FullAfterPartial)2357 TEST_F(HttpCacheTest, RangeGET_FullAfterPartial) {
2358 MockHttpCache cache;
2359
2360 // Request a prefix.
2361 {
2362 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2363 transaction_pre.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
2364 transaction_pre.data = "rg: 00-09 ";
2365 MockHttpRequest request_pre(transaction_pre);
2366
2367 HttpResponseInfo response_pre;
2368 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2369 request_pre, &response_pre);
2370 ASSERT_TRUE(response_pre.headers != nullptr);
2371 EXPECT_EQ(206, response_pre.headers->response_code());
2372 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2373 EXPECT_EQ(0, cache.disk_cache()->open_count());
2374 EXPECT_EQ(1, cache.disk_cache()->create_count());
2375 }
2376
2377 {
2378 // Now request the full thing, but set validation to fail. This would
2379 // previously fail in the middle of data and truncate it; current behavior
2380 // restarts it, somewhat wastefully but gets the data back.
2381 RangeTransactionServer handler;
2382 handler.set_modified(true);
2383
2384 ScopedMockTransaction transaction_all(kRangeGET_TransactionOK);
2385 transaction_all.request_headers = EXTRA_HEADER;
2386 transaction_all.data = "Not a range";
2387 MockHttpRequest request_all(transaction_all);
2388
2389 HttpResponseInfo response_all;
2390 RunTransactionTestWithRequest(cache.http_cache(), transaction_all,
2391 request_all, &response_all);
2392 ASSERT_TRUE(response_all.headers != nullptr);
2393 EXPECT_EQ(200, response_all.headers->response_code());
2394 // 1 from previous test, failed validation, and re-try.
2395 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2396 EXPECT_EQ(1, cache.disk_cache()->open_count());
2397 EXPECT_EQ(1, cache.disk_cache()->create_count());
2398 }
2399 }
2400
2401 // Tests that when a range request transaction becomes a writer for the first
2402 // range and then fails conditionalization for the next range and decides to
2403 // doom the entry, then there should not be a dcheck assertion hit.
TEST_F(HttpCacheTest,RangeGET_OverlappingRangesCouldntConditionalize)2404 TEST_F(HttpCacheTest, RangeGET_OverlappingRangesCouldntConditionalize) {
2405 MockHttpCache cache;
2406
2407 {
2408 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2409 transaction_pre.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2410 transaction_pre.data = "rg: 10-19 ";
2411 MockHttpRequest request_pre(transaction_pre);
2412
2413 HttpResponseInfo response_pre;
2414 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2415 request_pre, &response_pre);
2416 ASSERT_TRUE(response_pre.headers != nullptr);
2417 EXPECT_EQ(206, response_pre.headers->response_code());
2418 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2419 EXPECT_EQ(0, cache.disk_cache()->open_count());
2420 EXPECT_EQ(1, cache.disk_cache()->create_count());
2421 }
2422
2423 {
2424 // First range skips validation because the response is fresh while the
2425 // second range requires validation since that range is not present in the
2426 // cache and during validation it fails conditionalization.
2427 cache.FailConditionalizations();
2428 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2429 transaction_pre.request_headers = "Range: bytes = 10-29\r\n" EXTRA_HEADER;
2430
2431 // TODO(crbug.com/992521): Fix this scenario to not return the cached bytes
2432 // repeatedly.
2433 transaction_pre.data = "rg: 10-19 rg: 10-19 rg: 20-29 ";
2434 MockHttpRequest request_pre(transaction_pre);
2435 HttpResponseInfo response_pre;
2436 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2437 request_pre, &response_pre);
2438 ASSERT_TRUE(response_pre.headers != nullptr);
2439 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2440 EXPECT_EQ(1, cache.disk_cache()->open_count());
2441 EXPECT_EQ(2, cache.disk_cache()->create_count());
2442 }
2443 }
2444
TEST_F(HttpCacheTest,RangeGET_FullAfterPartialReuse)2445 TEST_F(HttpCacheTest, RangeGET_FullAfterPartialReuse) {
2446 MockHttpCache cache;
2447
2448 // Request a prefix.
2449 {
2450 ScopedMockTransaction transaction_pre(kRangeGET_TransactionOK);
2451 transaction_pre.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
2452 transaction_pre.data = "rg: 00-09 ";
2453 MockHttpRequest request_pre(transaction_pre);
2454
2455 HttpResponseInfo response_pre;
2456 RunTransactionTestWithRequest(cache.http_cache(), transaction_pre,
2457 request_pre, &response_pre);
2458 ASSERT_TRUE(response_pre.headers != nullptr);
2459 EXPECT_EQ(206, response_pre.headers->response_code());
2460 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2461 EXPECT_EQ(0, cache.disk_cache()->open_count());
2462 EXPECT_EQ(1, cache.disk_cache()->create_count());
2463 }
2464
2465 {
2466 // Now request the full thing, revalidating successfully, so the full
2467 // file gets stored via a sparse-entry.
2468 ScopedMockTransaction transaction_all(kRangeGET_TransactionOK);
2469 transaction_all.request_headers = EXTRA_HEADER;
2470 transaction_all.data =
2471 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49"
2472 " rg: 50-59 rg: 60-69 rg: 70-79 ";
2473 MockHttpRequest request_all(transaction_all);
2474
2475 HttpResponseInfo response_all;
2476 RunTransactionTestWithRequest(cache.http_cache(), transaction_all,
2477 request_all, &response_all);
2478 ASSERT_TRUE(response_all.headers != nullptr);
2479 EXPECT_EQ(200, response_all.headers->response_code());
2480 // 1 from previous test, validation, and second chunk
2481 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2482 EXPECT_EQ(1, cache.disk_cache()->open_count());
2483 EXPECT_EQ(1, cache.disk_cache()->create_count());
2484 }
2485
2486 {
2487 // Grab it again, should not need re-validation.
2488 ScopedMockTransaction transaction_all2(kRangeGET_TransactionOK);
2489 transaction_all2.request_headers = EXTRA_HEADER;
2490 transaction_all2.data =
2491 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 rg: 40-49"
2492 " rg: 50-59 rg: 60-69 rg: 70-79 ";
2493 MockHttpRequest request_all2(transaction_all2);
2494
2495 HttpResponseInfo response_all2;
2496 RunTransactionTestWithRequest(cache.http_cache(), transaction_all2,
2497 request_all2, &response_all2);
2498 ASSERT_TRUE(response_all2.headers != nullptr);
2499 EXPECT_EQ(200, response_all2.headers->response_code());
2500
2501 // Only one more cache open, no new network traffic.
2502 EXPECT_EQ(3, cache.network_layer()->transaction_count());
2503 EXPECT_EQ(2, cache.disk_cache()->open_count());
2504 EXPECT_EQ(1, cache.disk_cache()->create_count());
2505 }
2506 }
2507
2508 // This test verifies that the ConnectedCallback passed to a cache transaction
2509 // is called once per subrange in the case of a range request with a partial
2510 // cache hit.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackCalledForEachRange)2511 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackCalledForEachRange) {
2512 MockHttpCache cache;
2513
2514 // Request an infix range and populate the cache with it.
2515 {
2516 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2517 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2518 mock_transaction.data = "rg: 20-29 ";
2519 mock_transaction.transport_info = TestTransportInfo();
2520
2521 RunTransactionTest(cache.http_cache(), mock_transaction);
2522 }
2523
2524 // Request a surrounding range and observe that the callback is called once
2525 // per subrange, as split up by cache hits.
2526 {
2527 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2528 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2529 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2530 mock_transaction.transport_info = TestTransportInfo();
2531 MockHttpRequest request(mock_transaction);
2532
2533 ConnectedHandler connected_handler;
2534
2535 std::unique_ptr<HttpTransaction> transaction;
2536 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2537 ASSERT_THAT(transaction, NotNull());
2538
2539 transaction->SetConnectedCallback(connected_handler.Callback());
2540
2541 TestCompletionCallback callback;
2542 ASSERT_THAT(
2543 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2544 IsError(ERR_IO_PENDING));
2545 EXPECT_THAT(callback.WaitForResult(), IsOk());
2546
2547 // 1 call for the first range's network transaction.
2548 EXPECT_THAT(connected_handler.transports(),
2549 ElementsAre(TestTransportInfo()));
2550
2551 // Switch the endpoint for the next network transaction to observe.
2552 // For ease, we just switch the port number.
2553 //
2554 // NOTE: This works because only the mock transaction struct's address is
2555 // registered with the mocking framework - the pointee data is consulted
2556 // each time it is read.
2557 mock_transaction.transport_info = TestTransportInfoWithPort(123);
2558
2559 ReadAndVerifyTransaction(transaction.get(), mock_transaction);
2560
2561 // A second call for the cached range, reported as coming from the original
2562 // endpoint it was cached from. A third call for the last range's network
2563 // transaction.
2564 EXPECT_THAT(connected_handler.transports(),
2565 ElementsAre(TestTransportInfo(), CachedTestTransportInfo(),
2566 TestTransportInfoWithPort(123)));
2567 }
2568 }
2569
2570 // This test verifies that when the ConnectedCallback passed to a cache range
2571 // transaction returns an `ERR_INCONSISTENT_IP_ADDRESS_SPACE` error during a
2572 // partial read from cache, then the cache entry is invalidated.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnInconsistentIpError)2573 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackReturnInconsistentIpError) {
2574 MockHttpCache cache;
2575
2576 // Request an infix range and populate the cache with it.
2577 {
2578 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2579 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2580 mock_transaction.data = "rg: 20-29 ";
2581 mock_transaction.transport_info = TestTransportInfo();
2582
2583 RunTransactionTest(cache.http_cache(), mock_transaction);
2584 }
2585
2586 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2587 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2588 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2589 mock_transaction.transport_info = TestTransportInfo();
2590 MockHttpRequest request(mock_transaction);
2591
2592 // Request a surrounding range. This *should* be read in three parts:
2593 //
2594 // 1. for the prefix: from the network
2595 // 2. for the cached infix: from the cache
2596 // 3. for the suffix: from the network
2597 //
2598 // The connected callback returns OK for 1), but fails during 2). As a result,
2599 // the transaction fails partway and 3) is never created. The cache entry is
2600 // invalidated as a result of the specific error code.
2601 {
2602 ConnectedHandler connected_handler;
2603
2604 std::unique_ptr<HttpTransaction> transaction;
2605 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2606 ASSERT_THAT(transaction, NotNull());
2607
2608 transaction->SetConnectedCallback(connected_handler.Callback());
2609
2610 TestCompletionCallback callback;
2611 ASSERT_THAT(
2612 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2613 IsError(ERR_IO_PENDING));
2614 EXPECT_THAT(callback.WaitForResult(), IsOk());
2615
2616 // 1 call for the first range's network transaction.
2617 EXPECT_THAT(connected_handler.transports(),
2618 ElementsAre(TestTransportInfo()));
2619
2620 // Set the callback to return an error the next time it is called.
2621 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
2622
2623 std::string content;
2624 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2625 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
2626
2627 // A second call that failed.
2628 EXPECT_THAT(connected_handler.transports(),
2629 ElementsAre(TestTransportInfo(), CachedTestTransportInfo()));
2630 }
2631
2632 // Request the same range again, observe that nothing is read from cache.
2633 {
2634 ConnectedHandler connected_handler;
2635
2636 std::unique_ptr<HttpTransaction> transaction;
2637 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2638 ASSERT_THAT(transaction, NotNull());
2639
2640 transaction->SetConnectedCallback(connected_handler.Callback());
2641
2642 TestCompletionCallback callback;
2643 ASSERT_THAT(
2644 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2645 IsError(ERR_IO_PENDING));
2646 EXPECT_THAT(callback.WaitForResult(), IsOk());
2647
2648 std::string content;
2649 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2650 EXPECT_EQ(content, mock_transaction.data);
2651
2652 // 1 call for the network transaction from which the whole response was
2653 // read. The first 20 bytes were cached by the previous two requests, but
2654 // the cache entry was doomed during the last transaction so they are not
2655 // used here.
2656 EXPECT_THAT(connected_handler.transports(),
2657 ElementsAre(TestTransportInfo()));
2658 }
2659 }
2660
2661 // This test verifies that when the ConnectedCallback passed to a cache range
2662 // transaction returns an `ERR_INCONSISTENT_IP_ADDRESS_SPACE` error during a
2663 // network transaction, then the cache entry is invalidated.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnInconsistentIpErrorForNetwork)2664 TEST_F(HttpCacheTest,
2665 RangeGET_ConnectedCallbackReturnInconsistentIpErrorForNetwork) {
2666 MockHttpCache cache;
2667
2668 // Request a prefix range and populate the cache with it.
2669 {
2670 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2671 mock_transaction.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2672 mock_transaction.data = "rg: 10-19 ";
2673 mock_transaction.transport_info = TestTransportInfo();
2674
2675 RunTransactionTest(cache.http_cache(), mock_transaction);
2676 }
2677
2678 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2679 mock_transaction.request_headers = "Range: bytes = 10-29\r\n" EXTRA_HEADER;
2680 mock_transaction.data = "rg: 10-19 rg: 20-29 ";
2681 mock_transaction.transport_info = TestTransportInfo();
2682 MockHttpRequest request(mock_transaction);
2683
2684 // Request a longer range. This *should* be read in two parts:
2685 //
2686 // 1. for the prefix: from the cache
2687 // 2. for the suffix: from the network
2688 {
2689 ConnectedHandler connected_handler;
2690
2691 std::unique_ptr<HttpTransaction> transaction;
2692 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2693 ASSERT_THAT(transaction, NotNull());
2694
2695 transaction->SetConnectedCallback(connected_handler.Callback());
2696
2697 TestCompletionCallback callback;
2698 ASSERT_THAT(
2699 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2700 IsError(ERR_IO_PENDING));
2701 EXPECT_THAT(callback.WaitForResult(), IsOk());
2702
2703 // 1 call for the first range's network transaction.
2704 EXPECT_THAT(connected_handler.transports(),
2705 ElementsAre(CachedTestTransportInfo()));
2706
2707 // Set the callback to return an error the next time it is called.
2708 connected_handler.set_result(ERR_INCONSISTENT_IP_ADDRESS_SPACE);
2709
2710 std::string content;
2711 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2712 IsError(ERR_INCONSISTENT_IP_ADDRESS_SPACE));
2713
2714 // A second call that failed.
2715 EXPECT_THAT(connected_handler.transports(),
2716 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
2717 }
2718
2719 // Request the same range again, observe that nothing is read from cache.
2720 {
2721 ConnectedHandler connected_handler;
2722
2723 std::unique_ptr<HttpTransaction> transaction;
2724 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2725 ASSERT_THAT(transaction, NotNull());
2726
2727 transaction->SetConnectedCallback(connected_handler.Callback());
2728
2729 TestCompletionCallback callback;
2730 ASSERT_THAT(
2731 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2732 IsError(ERR_IO_PENDING));
2733 EXPECT_THAT(callback.WaitForResult(), IsOk());
2734
2735 std::string content;
2736 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2737 EXPECT_EQ(content, mock_transaction.data);
2738
2739 // 1 call for the network transaction from which the whole response was
2740 // read. The first 20 bytes were cached by the previous two requests, but
2741 // the cache entry was doomed during the last transaction so they are not
2742 // used here.
2743 EXPECT_THAT(connected_handler.transports(),
2744 ElementsAre(TestTransportInfo()));
2745 }
2746 }
2747
2748 // This test verifies that when the ConnectedCallback passed to a cache
2749 // transaction returns an error for the second (or third) subrange transaction,
2750 // the overall cache transaction fails with that error. The cache entry is still
2751 // usable after that.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackReturnErrorSecondTime)2752 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackReturnErrorSecondTime) {
2753 MockHttpCache cache;
2754
2755 // Request an infix range and populate the cache with it.
2756 {
2757 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2758 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
2759 mock_transaction.data = "rg: 20-29 ";
2760 mock_transaction.transport_info = TestTransportInfo();
2761
2762 RunTransactionTest(cache.http_cache(), mock_transaction);
2763 }
2764
2765 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2766 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2767 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2768 mock_transaction.transport_info = TestTransportInfo();
2769 MockHttpRequest request(mock_transaction);
2770
2771 // Request a surrounding range. This *should* be read in three parts:
2772 //
2773 // 1. for the prefix: from the network
2774 // 2. for the cached infix: from the cache
2775 // 3. for the suffix: from the network
2776 //
2777 // The connected callback returns OK for 1), but fails during 2). As a result,
2778 // the transaction fails partway and 3) is never created. The prefix is still
2779 // cached, such that the cache entry ends up with both the prefix and infix.
2780 {
2781 ConnectedHandler connected_handler;
2782
2783 std::unique_ptr<HttpTransaction> transaction;
2784 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2785 ASSERT_THAT(transaction, NotNull());
2786
2787 transaction->SetConnectedCallback(connected_handler.Callback());
2788
2789 TestCompletionCallback callback;
2790 ASSERT_THAT(
2791 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2792 IsError(ERR_IO_PENDING));
2793 EXPECT_THAT(callback.WaitForResult(), IsOk());
2794
2795 // 1 call for the first range's network transaction.
2796 EXPECT_THAT(connected_handler.transports(),
2797 ElementsAre(TestTransportInfo()));
2798
2799 // Set the callback to return an error the next time it is called. The exact
2800 // error code is irrelevant, what matters is that it is reflected in the
2801 // overall status of the transaction.
2802 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
2803
2804 std::string content;
2805 EXPECT_THAT(ReadTransaction(transaction.get(), &content),
2806 IsError(ERR_NOT_IMPLEMENTED));
2807
2808 // A second call that failed.
2809 EXPECT_THAT(connected_handler.transports(),
2810 ElementsAre(TestTransportInfo(), CachedTestTransportInfo()));
2811 }
2812
2813 // Request the same range again, observe that the prefix and infix are both
2814 // read from cache. Only the suffix is fetched from the network.
2815 {
2816 ConnectedHandler connected_handler;
2817
2818 std::unique_ptr<HttpTransaction> transaction;
2819 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2820 ASSERT_THAT(transaction, NotNull());
2821
2822 transaction->SetConnectedCallback(connected_handler.Callback());
2823
2824 TestCompletionCallback callback;
2825 ASSERT_THAT(
2826 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2827 IsError(ERR_IO_PENDING));
2828 EXPECT_THAT(callback.WaitForResult(), IsOk());
2829
2830 // 1 call for the first range's cache transaction: the first 20 bytes were
2831 // cached by the previous two requests.
2832 EXPECT_THAT(connected_handler.transports(),
2833 ElementsAre(CachedTestTransportInfo()));
2834
2835 std::string content;
2836 EXPECT_THAT(ReadTransaction(transaction.get(), &content), IsOk());
2837 EXPECT_EQ(content, mock_transaction.data);
2838
2839 // A second call from the network transaction for the last 10 bytes.
2840 EXPECT_THAT(connected_handler.transports(),
2841 ElementsAre(CachedTestTransportInfo(), TestTransportInfo()));
2842 }
2843 }
2844
2845 // This test verifies that the ConnectedCallback passed to a cache transaction
2846 // is called once per subrange in the case of a range request with a partial
2847 // cache hit, even when a prefix of the range is cached.
TEST_F(HttpCacheTest,RangeGET_ConnectedCallbackCalledForEachRangeWithPrefix)2848 TEST_F(HttpCacheTest, RangeGET_ConnectedCallbackCalledForEachRangeWithPrefix) {
2849 MockHttpCache cache;
2850
2851 // Request a prefix range and populate the cache with it.
2852 {
2853 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2854 mock_transaction.request_headers = "Range: bytes = 10-19\r\n" EXTRA_HEADER;
2855 mock_transaction.data = "rg: 10-19 ";
2856 mock_transaction.transport_info = TestTransportInfo();
2857
2858 RunTransactionTest(cache.http_cache(), mock_transaction);
2859 }
2860
2861 // Request a surrounding range and observe that the callback is called once
2862 // per subrange, as split up by cache hits.
2863 {
2864 ScopedMockTransaction mock_transaction(kRangeGET_TransactionOK);
2865 mock_transaction.request_headers = "Range: bytes = 10-39\r\n" EXTRA_HEADER;
2866 mock_transaction.data = "rg: 10-19 rg: 20-29 rg: 30-39 ";
2867 mock_transaction.transport_info = TestTransportInfoWithPort(123);
2868 MockHttpRequest request(mock_transaction);
2869
2870 ConnectedHandler connected_handler;
2871
2872 std::unique_ptr<HttpTransaction> transaction;
2873 EXPECT_THAT(cache.CreateTransaction(&transaction), IsOk());
2874 ASSERT_THAT(transaction, NotNull());
2875
2876 transaction->SetConnectedCallback(connected_handler.Callback());
2877
2878 TestCompletionCallback callback;
2879 ASSERT_THAT(
2880 transaction->Start(&request, callback.callback(), NetLogWithSource()),
2881 IsError(ERR_IO_PENDING));
2882 EXPECT_THAT(callback.WaitForResult(), IsOk());
2883
2884 // 1 call for the first range from the cache, reported as coming from the
2885 // endpoint which initially served the cached range.
2886 EXPECT_THAT(connected_handler.transports(),
2887 ElementsAre(CachedTestTransportInfo()));
2888
2889 ReadAndVerifyTransaction(transaction.get(), mock_transaction);
2890
2891 // A second call for the last range's network transaction.
2892 EXPECT_THAT(
2893 connected_handler.transports(),
2894 ElementsAre(CachedTestTransportInfo(), TestTransportInfoWithPort(123)));
2895 }
2896 }
2897
2898 // Tests that a range transaction is still usable even if it's unable to access
2899 // the cache.
TEST_F(HttpCacheTest,RangeGET_FailedCacheAccess)2900 TEST_F(HttpCacheTest, RangeGET_FailedCacheAccess) {
2901 MockHttpCache cache;
2902
2903 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
2904 MockHttpRequest request(transaction);
2905
2906 auto c = std::make_unique<Context>();
2907 c->result = cache.CreateTransaction(&c->trans);
2908 ASSERT_THAT(c->result, IsOk());
2909 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2910
2911 cache.disk_cache()->set_fail_requests(true);
2912
2913 c->result =
2914 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2915
2916 base::RunLoop().RunUntilIdle();
2917
2918 EXPECT_FALSE(cache.IsWriterPresent(kRangeGET_TransactionOK.url));
2919
2920 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2921 EXPECT_EQ(0, cache.disk_cache()->open_count());
2922 EXPECT_EQ(0, cache.disk_cache()->create_count());
2923
2924 c->result = c->callback.WaitForResult();
2925
2926 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
2927
2928 EXPECT_EQ(1, cache.network_layer()->transaction_count());
2929 EXPECT_EQ(0, cache.disk_cache()->open_count());
2930 EXPECT_EQ(0, cache.disk_cache()->create_count());
2931 }
2932
2933 // Tests that we can have parallel validation on range requests.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatch)2934 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatch) {
2935 MockHttpCache cache;
2936
2937 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
2938 MockHttpRequest request(transaction);
2939
2940 std::vector<std::unique_ptr<Context>> context_list;
2941 const int kNumTransactions = 5;
2942
2943 for (int i = 0; i < kNumTransactions; ++i) {
2944 context_list.push_back(std::make_unique<Context>());
2945 auto& c = context_list[i];
2946
2947 c->result = cache.CreateTransaction(&c->trans);
2948 ASSERT_THAT(c->result, IsOk());
2949 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
2950
2951 c->result =
2952 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
2953 }
2954
2955 // All requests are waiting for the active entry.
2956 for (auto& context : context_list) {
2957 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
2958 }
2959
2960 // Allow all requests to move from the Create queue to the active entry.
2961 base::RunLoop().RunUntilIdle();
2962
2963 // First entry created is doomed due to 2nd transaction's validation leading
2964 // to restarting of the queued transactions.
2965 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
2966
2967 // TODO(shivanisha): The restarted transactions race for creating the entry
2968 // and thus instead of all 4 succeeding, 2 of them succeed. This is very
2969 // implementation specific and happens because the queued transactions get
2970 // restarted synchronously and get to the queue of creating the entry before
2971 // the transaction that is restarting them. Fix the test to make it less
2972 // vulnerable to any scheduling changes in the code.
2973 EXPECT_EQ(5, cache.network_layer()->transaction_count());
2974 EXPECT_EQ(0, cache.disk_cache()->open_count());
2975 EXPECT_EQ(3, cache.disk_cache()->create_count());
2976
2977 for (auto& context : context_list) {
2978 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
2979 }
2980
2981 for (int i = 0; i < kNumTransactions; ++i) {
2982 auto& c = context_list[i];
2983 if (c->result == ERR_IO_PENDING) {
2984 c->result = c->callback.WaitForResult();
2985 }
2986
2987 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
2988 }
2989
2990 EXPECT_EQ(5, cache.network_layer()->transaction_count());
2991 EXPECT_EQ(0, cache.disk_cache()->open_count());
2992 EXPECT_EQ(3, cache.disk_cache()->create_count());
2993 }
2994
2995 // Tests that if a transaction is dooming the entry and the entry was doomed by
2996 // another transaction that was not part of the entry and created a new entry,
2997 // the new entry should not be incorrectly doomed. (crbug.com/736993)
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatchDoomEntry)2998 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatchDoomEntry) {
2999 MockHttpCache cache;
3000
3001 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3002 MockHttpRequest request(transaction);
3003
3004 MockTransaction dooming_transaction(kRangeGET_TransactionOK);
3005 dooming_transaction.load_flags |= LOAD_BYPASS_CACHE;
3006 MockHttpRequest dooming_request(dooming_transaction);
3007
3008 std::vector<std::unique_ptr<Context>> context_list;
3009 const int kNumTransactions = 3;
3010
3011 scoped_refptr<MockDiskEntry> first_entry;
3012 scoped_refptr<MockDiskEntry> second_entry;
3013 for (int i = 0; i < kNumTransactions; ++i) {
3014 context_list.push_back(std::make_unique<Context>());
3015 auto& c = context_list[i];
3016
3017 c->result = cache.CreateTransaction(&c->trans);
3018 ASSERT_THAT(c->result, IsOk());
3019 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3020
3021 MockHttpRequest* this_request = &request;
3022
3023 if (i == 2) {
3024 this_request = &dooming_request;
3025 }
3026
3027 if (i == 1) {
3028 ASSERT_TRUE(first_entry);
3029 first_entry->SetDefer(MockDiskEntry::DEFER_READ);
3030 }
3031
3032 c->result = c->trans->Start(this_request, c->callback.callback(),
3033 NetLogWithSource());
3034
3035 // Continue the transactions. 2nd will pause at the cache reading state and
3036 // 3rd transaction will doom the entry.
3037 base::RunLoop().RunUntilIdle();
3038
3039 std::string cache_key = request.CacheKey();
3040 // Check status of the first and second entries after every transaction.
3041 switch (i) {
3042 case 0:
3043 first_entry = cache.disk_cache()->GetDiskEntryRef(cache_key);
3044 break;
3045 case 1:
3046 EXPECT_FALSE(first_entry->is_doomed());
3047 break;
3048 case 2:
3049 EXPECT_TRUE(first_entry->is_doomed());
3050 second_entry = cache.disk_cache()->GetDiskEntryRef(cache_key);
3051 EXPECT_FALSE(second_entry->is_doomed());
3052 break;
3053 }
3054 }
3055 // Resume cache read by 1st transaction which will lead to dooming the entry
3056 // as well since the entry cannot be validated. This double dooming should not
3057 // lead to an assertion.
3058 first_entry->ResumeDiskEntryOperation();
3059 base::RunLoop().RunUntilIdle();
3060
3061 // Since second_entry is already created, when 1st transaction goes on to
3062 // create an entry, it will get ERR_CACHE_RACE leading to dooming of
3063 // second_entry and creation of a third entry.
3064 EXPECT_TRUE(second_entry->is_doomed());
3065
3066 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3067 EXPECT_EQ(0, cache.disk_cache()->open_count());
3068 EXPECT_EQ(3, cache.disk_cache()->create_count());
3069
3070 for (auto& context : context_list) {
3071 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3072 }
3073
3074 for (auto& c : context_list) {
3075 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
3076 }
3077
3078 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3079 EXPECT_EQ(0, cache.disk_cache()->open_count());
3080 EXPECT_EQ(3, cache.disk_cache()->create_count());
3081 }
3082
3083 // Same as above but tests that the 2nd transaction does not do anything if
3084 // there is nothing to doom. (crbug.com/736993)
TEST_F(HttpCacheTest,RangeGET_ParallelValidationNoMatchDoomEntry1)3085 TEST_F(HttpCacheTest, RangeGET_ParallelValidationNoMatchDoomEntry1) {
3086 MockHttpCache cache;
3087
3088 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3089 MockHttpRequest request(transaction);
3090
3091 MockTransaction dooming_transaction(kRangeGET_TransactionOK);
3092 dooming_transaction.load_flags |= LOAD_BYPASS_CACHE;
3093 MockHttpRequest dooming_request(dooming_transaction);
3094
3095 std::vector<std::unique_ptr<Context>> context_list;
3096 const int kNumTransactions = 3;
3097
3098 scoped_refptr<MockDiskEntry> first_entry;
3099 for (int i = 0; i < kNumTransactions; ++i) {
3100 context_list.push_back(std::make_unique<Context>());
3101 auto& c = context_list[i];
3102
3103 c->result = cache.CreateTransaction(&c->trans);
3104 ASSERT_THAT(c->result, IsOk());
3105 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3106
3107 MockHttpRequest* this_request = &request;
3108
3109 if (i == 2) {
3110 this_request = &dooming_request;
3111 cache.disk_cache()->SetDefer(MockDiskEntry::DEFER_CREATE);
3112 }
3113
3114 if (i == 1) {
3115 ASSERT_TRUE(first_entry);
3116 first_entry->SetDefer(MockDiskEntry::DEFER_READ);
3117 }
3118
3119 c->result = c->trans->Start(this_request, c->callback.callback(),
3120 NetLogWithSource());
3121
3122 // Continue the transactions. 2nd will pause at the cache reading state and
3123 // 3rd transaction will doom the entry and pause before creating a new
3124 // entry.
3125 base::RunLoop().RunUntilIdle();
3126
3127 // Check status of the entry after every transaction.
3128 switch (i) {
3129 case 0:
3130 first_entry = cache.disk_cache()->GetDiskEntryRef(request.CacheKey());
3131 break;
3132 case 1:
3133 EXPECT_FALSE(first_entry->is_doomed());
3134 break;
3135 case 2:
3136 EXPECT_TRUE(first_entry->is_doomed());
3137 break;
3138 }
3139 }
3140 // Resume cache read by 2nd transaction which will lead to dooming the entry
3141 // as well since the entry cannot be validated. This double dooming should not
3142 // lead to an assertion.
3143 first_entry->ResumeDiskEntryOperation();
3144 base::RunLoop().RunUntilIdle();
3145
3146 // Resume creation of entry by 3rd transaction.
3147 cache.disk_cache()->ResumeCacheOperation();
3148 base::RunLoop().RunUntilIdle();
3149
3150 // Note that since 3rd transaction's entry is already created but its
3151 // callback is deferred, MockDiskCache's implementation returns
3152 // ERR_CACHE_CREATE_FAILURE when 2nd transaction tries to create an entry
3153 // during that time, leading to it switching over to pass-through mode.
3154 // Thus the number of entries is 2 below.
3155 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3156 EXPECT_EQ(0, cache.disk_cache()->open_count());
3157 EXPECT_EQ(2, cache.disk_cache()->create_count());
3158
3159 for (auto& context : context_list) {
3160 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3161 }
3162
3163 for (auto& c : context_list) {
3164 ReadAndVerifyTransaction(c->trans.get(), kRangeGET_TransactionOK);
3165 }
3166
3167 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3168 EXPECT_EQ(0, cache.disk_cache()->open_count());
3169 EXPECT_EQ(2, cache.disk_cache()->create_count());
3170 }
3171
3172 // Tests parallel validation on range requests with non-overlapping ranges.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationDifferentRanges)3173 TEST_F(HttpCacheTest, RangeGET_ParallelValidationDifferentRanges) {
3174 MockHttpCache cache;
3175
3176 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3177
3178 std::vector<std::unique_ptr<Context>> context_list;
3179 const int kNumTransactions = 2;
3180
3181 for (int i = 0; i < kNumTransactions; ++i) {
3182 context_list.push_back(std::make_unique<Context>());
3183 }
3184
3185 // Let 1st transaction complete headers phase for ranges 40-49.
3186 std::string first_read;
3187 MockHttpRequest request1(transaction);
3188 {
3189 auto& c = context_list[0];
3190 c->result = cache.CreateTransaction(&c->trans);
3191 ASSERT_THAT(c->result, IsOk());
3192 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3193
3194 c->result =
3195 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3196 base::RunLoop().RunUntilIdle();
3197
3198 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3199 // true.
3200 const int kBufferSize = 5;
3201 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3202 ReleaseBufferCompletionCallback cb(buffer.get());
3203 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3204 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3205
3206 std::string data_read(buffer->data(), kBufferSize);
3207 first_read = data_read;
3208
3209 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3210 }
3211
3212 // 2nd transaction requests ranges 30-39.
3213 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
3214 MockHttpRequest request2(transaction);
3215 {
3216 auto& c = context_list[1];
3217 c->result = cache.CreateTransaction(&c->trans);
3218 ASSERT_THAT(c->result, IsOk());
3219 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3220
3221 c->result =
3222 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3223 base::RunLoop().RunUntilIdle();
3224
3225 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3226 }
3227
3228 std::string cache_key = request2.CacheKey();
3229 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3230 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3231
3232 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3233 EXPECT_EQ(0, cache.disk_cache()->open_count());
3234 EXPECT_EQ(1, cache.disk_cache()->create_count());
3235
3236 for (int i = 0; i < kNumTransactions; ++i) {
3237 auto& c = context_list[i];
3238 if (c->result == ERR_IO_PENDING) {
3239 c->result = c->callback.WaitForResult();
3240 }
3241
3242 if (i == 0) {
3243 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3244 transaction);
3245 continue;
3246 }
3247
3248 transaction.data = "rg: 30-39 ";
3249 ReadAndVerifyTransaction(c->trans.get(), transaction);
3250 }
3251
3252 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3253 EXPECT_EQ(0, cache.disk_cache()->open_count());
3254 EXPECT_EQ(1, cache.disk_cache()->create_count());
3255
3256 // Fetch from the cache to check that ranges 30-49 have been successfully
3257 // cached.
3258 {
3259 MockTransaction range_transaction(kRangeGET_TransactionOK);
3260 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3261 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3262 std::string headers;
3263 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3264 &headers);
3265 Verify206Response(headers, 30, 49);
3266 }
3267
3268 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3269 EXPECT_EQ(1, cache.disk_cache()->open_count());
3270 EXPECT_EQ(1, cache.disk_cache()->create_count());
3271
3272 context_list.clear();
3273 }
3274
3275 // Tests that a request does not create Writers when readers is not empty.
TEST_F(HttpCacheTest,RangeGET_DoNotCreateWritersWhenReaderExists)3276 TEST_F(HttpCacheTest, RangeGET_DoNotCreateWritersWhenReaderExists) {
3277 MockHttpCache cache;
3278
3279 // Save a request in the cache so that the next request can become a
3280 // reader.
3281 ScopedMockTransaction transaction(kRangeGET_Transaction);
3282 transaction.request_headers = EXTRA_HEADER;
3283 RunTransactionTest(cache.http_cache(), transaction);
3284
3285 // Let this request be a reader since it doesn't need validation as per its
3286 // load flag.
3287 transaction.load_flags |= LOAD_SKIP_CACHE_VALIDATION;
3288 MockHttpRequest request(transaction);
3289 Context context;
3290 context.result = cache.CreateTransaction(&context.trans);
3291 ASSERT_THAT(context.result, IsOk());
3292 context.result = context.trans->Start(&request, context.callback.callback(),
3293 NetLogWithSource());
3294 base::RunLoop().RunUntilIdle();
3295 std::string cache_key = request.CacheKey();
3296 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
3297
3298 // A range request should now "not" create Writers while readers is still
3299 // non-empty.
3300 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
3301 MockHttpRequest range_request(transaction);
3302 Context range_context;
3303 range_context.result = cache.CreateTransaction(&range_context.trans);
3304 ASSERT_THAT(range_context.result, IsOk());
3305 range_context.result = range_context.trans->Start(
3306 &range_request, range_context.callback.callback(), NetLogWithSource());
3307 base::RunLoop().RunUntilIdle();
3308
3309 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
3310 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
3311 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3312 }
3313
3314 // Tests parallel validation on range requests can be successfully restarted
3315 // when there is a cache lock timeout.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCacheLockTimeout)3316 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCacheLockTimeout) {
3317 MockHttpCache cache;
3318
3319 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3320
3321 std::vector<std::unique_ptr<Context>> context_list;
3322 const int kNumTransactions = 2;
3323
3324 for (int i = 0; i < kNumTransactions; ++i) {
3325 context_list.push_back(std::make_unique<Context>());
3326 }
3327
3328 // Let 1st transaction complete headers phase for ranges 40-49.
3329 std::string first_read;
3330 MockHttpRequest request1(transaction);
3331 {
3332 auto& c = context_list[0];
3333 c->result = cache.CreateTransaction(&c->trans);
3334 ASSERT_THAT(c->result, IsOk());
3335 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3336
3337 c->result =
3338 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3339 base::RunLoop().RunUntilIdle();
3340
3341 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3342 // true.
3343 const int kBufferSize = 5;
3344 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3345 ReleaseBufferCompletionCallback cb(buffer.get());
3346 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3347 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3348
3349 std::string data_read(buffer->data(), kBufferSize);
3350 first_read = data_read;
3351
3352 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3353 }
3354
3355 // Cache lock timeout will lead to dooming the entry since the transaction may
3356 // have already written the headers.
3357 cache.SimulateCacheLockTimeoutAfterHeaders();
3358
3359 // 2nd transaction requests ranges 30-39.
3360 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
3361 MockHttpRequest request2(transaction);
3362 {
3363 auto& c = context_list[1];
3364 c->result = cache.CreateTransaction(&c->trans);
3365 ASSERT_THAT(c->result, IsOk());
3366 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3367
3368 c->result =
3369 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3370 base::RunLoop().RunUntilIdle();
3371
3372 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3373 }
3374
3375 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(request1.CacheKey()));
3376
3377 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3378 EXPECT_EQ(0, cache.disk_cache()->open_count());
3379 EXPECT_EQ(1, cache.disk_cache()->create_count());
3380
3381 for (int i = 0; i < kNumTransactions; ++i) {
3382 auto& c = context_list[i];
3383 if (c->result == ERR_IO_PENDING) {
3384 c->result = c->callback.WaitForResult();
3385 }
3386
3387 if (i == 0) {
3388 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3389 transaction);
3390 continue;
3391 }
3392
3393 transaction.data = "rg: 30-39 ";
3394 ReadAndVerifyTransaction(c->trans.get(), transaction);
3395 }
3396
3397 EXPECT_EQ(3, cache.network_layer()->transaction_count());
3398 EXPECT_EQ(0, cache.disk_cache()->open_count());
3399 EXPECT_EQ(1, cache.disk_cache()->create_count());
3400 }
3401
3402 // Tests a full request and a simultaneous range request and the range request
3403 // dooms the entry created by the full request due to not being able to
3404 // conditionalize.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCouldntConditionalize)3405 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCouldntConditionalize) {
3406 MockHttpCache cache;
3407
3408 MockTransaction mock_transaction(kSimpleGET_Transaction);
3409 mock_transaction.url = kRangeGET_TransactionOK.url;
3410 // Remove the cache-control and other headers so that the response cannot be
3411 // conditionalized.
3412 mock_transaction.response_headers = "";
3413 MockHttpRequest request1(mock_transaction);
3414
3415 std::vector<std::unique_ptr<Context>> context_list;
3416 const int kNumTransactions = 2;
3417
3418 for (int i = 0; i < kNumTransactions; ++i) {
3419 context_list.push_back(std::make_unique<Context>());
3420 }
3421
3422 // Let 1st transaction complete headers phase for no range and read some part
3423 // of the response and write in the cache.
3424 std::string first_read;
3425 {
3426 ScopedMockTransaction transaction(mock_transaction);
3427 request1.url = GURL(kRangeGET_TransactionOK.url);
3428 auto& c = context_list[0];
3429 c->result = cache.CreateTransaction(&c->trans);
3430 ASSERT_THAT(c->result, IsOk());
3431 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3432
3433 c->result =
3434 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3435 base::RunLoop().RunUntilIdle();
3436
3437 const int kBufferSize = 5;
3438 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3439 ReleaseBufferCompletionCallback cb(buffer.get());
3440 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3441 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3442
3443 std::string data_read(buffer->data(), kBufferSize);
3444 first_read = data_read;
3445
3446 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3447 }
3448
3449 // 2nd transaction requests a range.
3450 ScopedMockTransaction range_transaction(kRangeGET_TransactionOK);
3451 range_transaction.request_headers = "Range: bytes = 0-29\r\n" EXTRA_HEADER;
3452 MockHttpRequest request2(range_transaction);
3453 {
3454 auto& c = context_list[1];
3455 c->result = cache.CreateTransaction(&c->trans);
3456 ASSERT_THAT(c->result, IsOk());
3457 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3458
3459 c->result =
3460 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3461 base::RunLoop().RunUntilIdle();
3462
3463 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3464 }
3465
3466 // The second request would have doomed the 1st entry and created a new entry.
3467 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3468 EXPECT_EQ(0, cache.disk_cache()->open_count());
3469 EXPECT_EQ(2, cache.disk_cache()->create_count());
3470
3471 for (int i = 0; i < kNumTransactions; ++i) {
3472 auto& c = context_list[i];
3473 if (c->result == ERR_IO_PENDING) {
3474 c->result = c->callback.WaitForResult();
3475 }
3476
3477 if (i == 0) {
3478 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3479 mock_transaction);
3480 continue;
3481 }
3482 range_transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 ";
3483 ReadAndVerifyTransaction(c->trans.get(), range_transaction);
3484 }
3485 context_list.clear();
3486 }
3487
3488 // Tests a 200 request and a simultaneous range request where conditionalization
3489 // is possible.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationCouldConditionalize)3490 TEST_F(HttpCacheTest, RangeGET_ParallelValidationCouldConditionalize) {
3491 MockHttpCache cache;
3492
3493 MockTransaction mock_transaction(kSimpleGET_Transaction);
3494 mock_transaction.url = kRangeGET_TransactionOK.url;
3495 mock_transaction.data = kFullRangeData;
3496 std::string response_headers_str = base::StrCat(
3497 {"ETag: StrongOne\n",
3498 "Content-Length:", base::NumberToString(strlen(kFullRangeData)), "\n"});
3499 mock_transaction.response_headers = response_headers_str.c_str();
3500
3501 std::vector<std::unique_ptr<Context>> context_list;
3502 const int kNumTransactions = 2;
3503
3504 for (int i = 0; i < kNumTransactions; ++i) {
3505 context_list.push_back(std::make_unique<Context>());
3506 }
3507
3508 // Let 1st transaction complete headers phase for no range and read some part
3509 // of the response and write in the cache.
3510 std::string first_read;
3511 MockHttpRequest request1(mock_transaction);
3512 {
3513 ScopedMockTransaction transaction(mock_transaction);
3514 request1.url = GURL(kRangeGET_TransactionOK.url);
3515 auto& c = context_list[0];
3516 c->result = cache.CreateTransaction(&c->trans);
3517 ASSERT_THAT(c->result, IsOk());
3518 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3519
3520 c->result =
3521 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3522 base::RunLoop().RunUntilIdle();
3523
3524 const int kBufferSize = 5;
3525 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3526 ReleaseBufferCompletionCallback cb(buffer.get());
3527 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3528 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3529
3530 std::string data_read(buffer->data(), kBufferSize);
3531 first_read = data_read;
3532
3533 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3534 }
3535
3536 // 2nd transaction requests a range.
3537 ScopedMockTransaction range_transaction(kRangeGET_TransactionOK);
3538 range_transaction.request_headers = "Range: bytes = 0-29\r\n" EXTRA_HEADER;
3539 MockHttpRequest request2(range_transaction);
3540 {
3541 auto& c = context_list[1];
3542 c->result = cache.CreateTransaction(&c->trans);
3543 ASSERT_THAT(c->result, IsOk());
3544 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3545
3546 c->result =
3547 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3548 base::RunLoop().RunUntilIdle();
3549
3550 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3551 }
3552
3553 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3554 EXPECT_EQ(0, cache.disk_cache()->open_count());
3555 EXPECT_EQ(1, cache.disk_cache()->create_count());
3556
3557 // Finish and verify the first request.
3558 auto& c0 = context_list[0];
3559 c0->result = c0->callback.WaitForResult();
3560 ReadRemainingAndVerifyTransaction(c0->trans.get(), first_read,
3561 mock_transaction);
3562
3563 // And the second.
3564 auto& c1 = context_list[1];
3565 c1->result = c1->callback.WaitForResult();
3566
3567 range_transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 ";
3568 ReadAndVerifyTransaction(c1->trans.get(), range_transaction);
3569 context_list.clear();
3570 }
3571
3572 // Tests parallel validation on range requests with overlapping ranges.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationOverlappingRanges)3573 TEST_F(HttpCacheTest, RangeGET_ParallelValidationOverlappingRanges) {
3574 MockHttpCache cache;
3575
3576 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3577
3578 std::vector<std::unique_ptr<Context>> context_list;
3579 const int kNumTransactions = 2;
3580
3581 for (int i = 0; i < kNumTransactions; ++i) {
3582 context_list.push_back(std::make_unique<Context>());
3583 }
3584
3585 // Let 1st transaction complete headers phase for ranges 40-49.
3586 std::string first_read;
3587 MockHttpRequest request1(transaction);
3588 {
3589 auto& c = context_list[0];
3590 c->result = cache.CreateTransaction(&c->trans);
3591 ASSERT_THAT(c->result, IsOk());
3592 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3593
3594 c->result =
3595 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3596 base::RunLoop().RunUntilIdle();
3597
3598 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3599 // true.
3600 const int kBufferSize = 5;
3601 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3602 ReleaseBufferCompletionCallback cb(buffer.get());
3603 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3604 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3605
3606 std::string data_read(buffer->data(), kBufferSize);
3607 first_read = data_read;
3608
3609 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3610 }
3611
3612 // 2nd transaction requests ranges 30-49.
3613 transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3614 MockHttpRequest request2(transaction);
3615 {
3616 auto& c = context_list[1];
3617 c->result = cache.CreateTransaction(&c->trans);
3618 ASSERT_THAT(c->result, IsOk());
3619 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3620
3621 c->result =
3622 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3623 base::RunLoop().RunUntilIdle();
3624
3625 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3626 }
3627
3628 std::string cache_key = request1.CacheKey();
3629 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3630 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3631
3632 // Should have created another transaction for the uncached range.
3633 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3634 EXPECT_EQ(0, cache.disk_cache()->open_count());
3635 EXPECT_EQ(1, cache.disk_cache()->create_count());
3636
3637 for (int i = 0; i < kNumTransactions; ++i) {
3638 auto& c = context_list[i];
3639 if (c->result == ERR_IO_PENDING) {
3640 c->result = c->callback.WaitForResult();
3641 }
3642
3643 if (i == 0) {
3644 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read,
3645 transaction);
3646 continue;
3647 }
3648
3649 transaction.data = "rg: 30-39 rg: 40-49 ";
3650 ReadAndVerifyTransaction(c->trans.get(), transaction);
3651 }
3652
3653 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3654 EXPECT_EQ(0, cache.disk_cache()->open_count());
3655 EXPECT_EQ(1, cache.disk_cache()->create_count());
3656
3657 // Fetch from the cache to check that ranges 30-49 have been successfully
3658 // cached.
3659 {
3660 MockTransaction range_transaction(kRangeGET_TransactionOK);
3661 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3662 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3663 std::string headers;
3664 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3665 &headers);
3666 Verify206Response(headers, 30, 49);
3667 }
3668
3669 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3670 EXPECT_EQ(0, cache.disk_cache()->open_count());
3671 EXPECT_EQ(1, cache.disk_cache()->create_count());
3672 }
3673
3674 // Tests parallel validation on range requests with overlapping ranges and the
3675 // impact of deleting the writer on transactions that have validated.
TEST_F(HttpCacheTest,RangeGET_ParallelValidationRestartDoneHeaders)3676 TEST_F(HttpCacheTest, RangeGET_ParallelValidationRestartDoneHeaders) {
3677 MockHttpCache cache;
3678
3679 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3680
3681 std::vector<std::unique_ptr<Context>> context_list;
3682 const int kNumTransactions = 2;
3683
3684 for (int i = 0; i < kNumTransactions; ++i) {
3685 context_list.push_back(std::make_unique<Context>());
3686 }
3687
3688 // Let 1st transaction complete headers phase for ranges 40-59.
3689 std::string first_read;
3690 transaction.request_headers = "Range: bytes = 40-59\r\n" EXTRA_HEADER;
3691 MockHttpRequest request1(transaction);
3692 {
3693 auto& c = context_list[0];
3694 c->result = cache.CreateTransaction(&c->trans);
3695 ASSERT_THAT(c->result, IsOk());
3696 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3697
3698 c->result =
3699 c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
3700 base::RunLoop().RunUntilIdle();
3701
3702 // Start writing to the cache so that MockDiskEntry::CouldBeSparse() returns
3703 // true.
3704 const int kBufferSize = 10;
3705 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
3706 ReleaseBufferCompletionCallback cb(buffer.get());
3707 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
3708 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
3709
3710 std::string data_read(buffer->data(), kBufferSize);
3711 first_read = data_read;
3712
3713 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3714 }
3715
3716 // 2nd transaction requests ranges 30-59.
3717 transaction.request_headers = "Range: bytes = 30-59\r\n" EXTRA_HEADER;
3718 MockHttpRequest request2(transaction);
3719 {
3720 auto& c = context_list[1];
3721 c->result = cache.CreateTransaction(&c->trans);
3722 ASSERT_THAT(c->result, IsOk());
3723 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3724
3725 c->result =
3726 c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
3727 base::RunLoop().RunUntilIdle();
3728
3729 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3730 }
3731
3732 std::string cache_key = request1.CacheKey();
3733 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
3734 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
3735
3736 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3737 EXPECT_EQ(0, cache.disk_cache()->open_count());
3738 EXPECT_EQ(1, cache.disk_cache()->create_count());
3739
3740 // Delete the writer transaction.
3741 context_list[0].reset();
3742
3743 base::RunLoop().RunUntilIdle();
3744
3745 transaction.data = "rg: 30-39 rg: 40-49 rg: 50-59 ";
3746 ReadAndVerifyTransaction(context_list[1]->trans.get(), transaction);
3747
3748 // Create another network transaction since the 2nd transaction is restarted.
3749 // 30-39 will be read from network, 40-49 from the cache and 50-59 from the
3750 // network.
3751 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3752 EXPECT_EQ(0, cache.disk_cache()->open_count());
3753 EXPECT_EQ(1, cache.disk_cache()->create_count());
3754
3755 // Fetch from the cache to check that ranges 30-49 have been successfully
3756 // cached.
3757 {
3758 MockTransaction range_transaction(kRangeGET_TransactionOK);
3759 range_transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
3760 range_transaction.data = "rg: 30-39 rg: 40-49 ";
3761 std::string headers;
3762 RunTransactionTestWithResponse(cache.http_cache(), range_transaction,
3763 &headers);
3764 Verify206Response(headers, 30, 49);
3765 }
3766
3767 EXPECT_EQ(4, cache.network_layer()->transaction_count());
3768 EXPECT_EQ(1, cache.disk_cache()->open_count());
3769 EXPECT_EQ(1, cache.disk_cache()->create_count());
3770 }
3771
3772 // A test of doing a range request to a cached 301 response
TEST_F(HttpCacheTest,RangeGET_CachedRedirect)3773 TEST_F(HttpCacheTest, RangeGET_CachedRedirect) {
3774 RangeTransactionServer handler;
3775 handler.set_redirect(true);
3776
3777 MockHttpCache cache;
3778 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
3779 transaction.request_headers = "Range: bytes = 0-\r\n" EXTRA_HEADER;
3780 transaction.status = "HTTP/1.1 301 Moved Permanently";
3781 transaction.response_headers = "Location: /elsewhere\nContent-Length:5";
3782 transaction.data = "12345";
3783 MockHttpRequest request(transaction);
3784
3785 TestCompletionCallback callback;
3786
3787 // Write to the cache.
3788 {
3789 std::unique_ptr<HttpTransaction> trans;
3790 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3791
3792 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3793 if (rv == ERR_IO_PENDING) {
3794 rv = callback.WaitForResult();
3795 }
3796 ASSERT_THAT(rv, IsOk());
3797
3798 const HttpResponseInfo* info = trans->GetResponseInfo();
3799 ASSERT_TRUE(info);
3800
3801 EXPECT_EQ(info->headers->response_code(), 301);
3802
3803 std::string location;
3804 info->headers->EnumerateHeader(nullptr, "Location", &location);
3805 EXPECT_EQ(location, "/elsewhere");
3806
3807 ReadAndVerifyTransaction(trans.get(), transaction);
3808 }
3809 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3810 EXPECT_EQ(0, cache.disk_cache()->open_count());
3811 EXPECT_EQ(1, cache.disk_cache()->create_count());
3812
3813 // Active entries in the cache are not retired synchronously. Make
3814 // sure the next run hits the MockHttpCache and open_count is
3815 // correct.
3816 base::RunLoop().RunUntilIdle();
3817
3818 // Read from the cache.
3819 {
3820 std::unique_ptr<HttpTransaction> trans;
3821 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3822
3823 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3824 if (rv == ERR_IO_PENDING) {
3825 rv = callback.WaitForResult();
3826 }
3827 ASSERT_THAT(rv, IsOk());
3828
3829 const HttpResponseInfo* info = trans->GetResponseInfo();
3830 ASSERT_TRUE(info);
3831
3832 EXPECT_EQ(info->headers->response_code(), 301);
3833
3834 std::string location;
3835 info->headers->EnumerateHeader(nullptr, "Location", &location);
3836 EXPECT_EQ(location, "/elsewhere");
3837
3838 trans->DoneReading();
3839 }
3840 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3841 EXPECT_EQ(1, cache.disk_cache()->open_count());
3842 EXPECT_EQ(1, cache.disk_cache()->create_count());
3843
3844 // Now read the full body. This normally would not be done for a 301 by
3845 // higher layers, but e.g. a 500 could hit a further bug here.
3846 {
3847 std::unique_ptr<HttpTransaction> trans;
3848 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
3849
3850 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
3851 if (rv == ERR_IO_PENDING) {
3852 rv = callback.WaitForResult();
3853 }
3854 ASSERT_THAT(rv, IsOk());
3855
3856 const HttpResponseInfo* info = trans->GetResponseInfo();
3857 ASSERT_TRUE(info);
3858
3859 EXPECT_EQ(info->headers->response_code(), 301);
3860
3861 std::string location;
3862 info->headers->EnumerateHeader(nullptr, "Location", &location);
3863 EXPECT_EQ(location, "/elsewhere");
3864
3865 ReadAndVerifyTransaction(trans.get(), transaction);
3866 }
3867 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3868 // No extra open since it picks up a previous ActiveEntry.
3869 EXPECT_EQ(1, cache.disk_cache()->open_count());
3870 EXPECT_EQ(1, cache.disk_cache()->create_count());
3871 }
3872
3873 // A transaction that fails to validate an entry, while attempting to write
3874 // the response, should still get data to its consumer even if the attempt to
3875 // create a new entry fails.
TEST_F(HttpCacheTest,SimpleGET_ValidationFailureWithCreateFailure)3876 TEST_F(HttpCacheTest, SimpleGET_ValidationFailureWithCreateFailure) {
3877 MockHttpCache cache;
3878 MockHttpRequest request(kSimpleGET_Transaction);
3879 request.load_flags |= LOAD_VALIDATE_CACHE;
3880 std::vector<std::unique_ptr<Context>> context_list;
3881
3882 // Create and run the first, successful, transaction to prime the cache.
3883 context_list.push_back(std::make_unique<Context>());
3884 auto& c1 = context_list.back();
3885 c1->result = cache.CreateTransaction(&c1->trans);
3886 ASSERT_THAT(c1->result, IsOk());
3887 EXPECT_EQ(LOAD_STATE_IDLE, c1->trans->GetLoadState());
3888 c1->result =
3889 c1->trans->Start(&request, c1->callback.callback(), NetLogWithSource());
3890 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c1->trans->GetLoadState());
3891 base::RunLoop().RunUntilIdle();
3892
3893 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
3894 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3895 EXPECT_EQ(0, cache.disk_cache()->open_count());
3896 EXPECT_EQ(1, cache.disk_cache()->create_count());
3897
3898 // Create and start the second transaction, which will fail its validation
3899 // during the call to RunUntilIdle().
3900 context_list.push_back(std::make_unique<Context>());
3901 auto& c2 = context_list.back();
3902 c2->result = cache.CreateTransaction(&c2->trans);
3903 ASSERT_THAT(c2->result, IsOk());
3904 EXPECT_EQ(LOAD_STATE_IDLE, c2->trans->GetLoadState());
3905 c2->result =
3906 c2->trans->Start(&request, c2->callback.callback(), NetLogWithSource());
3907 // Expect idle at this point because we should be able to find and use the
3908 // Active Entry that c1 created instead of waiting on the cache to open the
3909 // entry.
3910 EXPECT_EQ(LOAD_STATE_IDLE, c2->trans->GetLoadState());
3911
3912 cache.disk_cache()->set_fail_requests(true);
3913 // The transaction, c2, should now attempt to validate the entry, fail when it
3914 // receives a 200 OK response, attempt to create a new entry, fail to create,
3915 // and then continue onward without an entry.
3916 base::RunLoop().RunUntilIdle();
3917
3918 // All requests depend on the writer, and the writer is between Start and
3919 // Read, i.e. idle.
3920 for (auto& context : context_list) {
3921 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3922 }
3923
3924 // Confirm that both transactions correctly Read() the data.
3925 for (auto& context : context_list) {
3926 if (context->result == ERR_IO_PENDING) {
3927 context->result = context->callback.WaitForResult();
3928 }
3929 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
3930 }
3931
3932 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3933 EXPECT_EQ(0, cache.disk_cache()->open_count());
3934 EXPECT_EQ(1, cache.disk_cache()->create_count());
3935 }
3936
3937 // Parallel validation results in 200.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationNoMatch)3938 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationNoMatch) {
3939 MockHttpCache cache;
3940 MockHttpRequest request(kSimpleGET_Transaction);
3941 request.load_flags |= LOAD_VALIDATE_CACHE;
3942 std::vector<std::unique_ptr<Context>> context_list;
3943 const int kNumTransactions = 5;
3944 for (int i = 0; i < kNumTransactions; ++i) {
3945 context_list.push_back(std::make_unique<Context>());
3946 auto& c = context_list[i];
3947 c->result = cache.CreateTransaction(&c->trans);
3948 ASSERT_THAT(c->result, IsOk());
3949 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
3950 c->result =
3951 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
3952 }
3953
3954 // All requests are waiting for the active entry.
3955 for (auto& context : context_list) {
3956 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
3957 }
3958
3959 // Allow all requests to move from the Create queue to the active entry.
3960 base::RunLoop().RunUntilIdle();
3961
3962 // The first request should be a writer at this point, and the subsequent
3963 // requests should have passed the validation phase and created their own
3964 // entries since none of them matched the headers of the earlier one.
3965 EXPECT_TRUE(cache.IsWriterPresent(request.CacheKey()));
3966
3967 EXPECT_EQ(5, cache.network_layer()->transaction_count());
3968 EXPECT_EQ(0, cache.disk_cache()->open_count());
3969 EXPECT_EQ(5, cache.disk_cache()->create_count());
3970
3971 // All requests depend on the writer, and the writer is between Start and
3972 // Read, i.e. idle.
3973 for (auto& context : context_list) {
3974 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
3975 }
3976
3977 for (auto& context : context_list) {
3978 if (context->result == ERR_IO_PENDING) {
3979 context->result = context->callback.WaitForResult();
3980 }
3981 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
3982 }
3983
3984 EXPECT_EQ(5, cache.network_layer()->transaction_count());
3985 EXPECT_EQ(0, cache.disk_cache()->open_count());
3986 EXPECT_EQ(5, cache.disk_cache()->create_count());
3987 }
3988
TEST_F(HttpCacheTest,RangeGET_Enormous)3989 TEST_F(HttpCacheTest, RangeGET_Enormous) {
3990 // Test for how blockfile's limit on range namespace interacts with
3991 // HttpCache::Transaction.
3992 // See https://crbug.com/770694
3993 base::ScopedTempDir temp_dir;
3994 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
3995
3996 auto backend_factory = std::make_unique<HttpCache::DefaultBackend>(
3997 DISK_CACHE, CACHE_BACKEND_BLOCKFILE,
3998 /*file_operations_factory=*/nullptr, temp_dir.GetPath(), 1024 * 1024,
3999 false);
4000 MockHttpCache cache(std::move(backend_factory));
4001
4002 RangeTransactionServer handler;
4003 handler.set_length(2305843009213693962);
4004
4005 // Prime with a range it can store.
4006 {
4007 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4008 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
4009 transaction.data = "rg: 00-09 ";
4010 MockHttpRequest request(transaction);
4011
4012 HttpResponseInfo response;
4013 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4014 &response);
4015 ASSERT_TRUE(response.headers != nullptr);
4016 EXPECT_EQ(206, response.headers->response_code());
4017 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4018 }
4019
4020 // Try with a range it can't. Should still work.
4021 {
4022 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4023 transaction.request_headers =
4024 "Range: bytes = "
4025 "2305843009213693952-2305843009213693961\r\n" EXTRA_HEADER;
4026 transaction.data = "rg: 52-61 ";
4027 MockHttpRequest request(transaction);
4028
4029 HttpResponseInfo response;
4030 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4031 &response);
4032 ASSERT_TRUE(response.headers != nullptr);
4033 EXPECT_EQ(206, response.headers->response_code());
4034 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4035 }
4036
4037 // Can't actually cache it due to backend limitations. If the network
4038 // transaction count is 2, this test isn't covering what it needs to.
4039 {
4040 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
4041 transaction.request_headers =
4042 "Range: bytes = "
4043 "2305843009213693952-2305843009213693961\r\n" EXTRA_HEADER;
4044 transaction.data = "rg: 52-61 ";
4045 MockHttpRequest request(transaction);
4046
4047 HttpResponseInfo response;
4048 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
4049 &response);
4050 ASSERT_TRUE(response.headers != nullptr);
4051 EXPECT_EQ(206, response.headers->response_code());
4052 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4053 }
4054 }
4055
4056 // Parallel validation results in 200 for 1 transaction and validation matches
4057 // for subsequent transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationNoMatch1)4058 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationNoMatch1) {
4059 MockHttpCache cache;
4060 MockHttpRequest request(kSimpleGET_Transaction);
4061
4062 MockTransaction transaction(kSimpleGET_Transaction);
4063 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4064 MockHttpRequest validate_request(transaction);
4065 std::vector<std::unique_ptr<Context>> context_list;
4066 const int kNumTransactions = 5;
4067 for (int i = 0; i < kNumTransactions; ++i) {
4068 context_list.push_back(std::make_unique<Context>());
4069 auto& c = context_list[i];
4070 c->result = cache.CreateTransaction(&c->trans);
4071 ASSERT_THAT(c->result, IsOk());
4072 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
4073
4074 MockHttpRequest* this_request = &request;
4075 if (i == 1) {
4076 this_request = &validate_request;
4077 }
4078
4079 c->result = c->trans->Start(this_request, c->callback.callback(),
4080 NetLogWithSource());
4081 }
4082
4083 // All requests are waiting for the active entry.
4084 for (auto& context : context_list) {
4085 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
4086 }
4087
4088 // Allow all requests to move from the Create queue to the active entry.
4089 base::RunLoop().RunUntilIdle();
4090
4091 // The new entry will have all the transactions except the first one which
4092 // will continue in the doomed entry.
4093 EXPECT_EQ(kNumTransactions - 1,
4094 cache.GetCountWriterTransactions(validate_request.CacheKey()));
4095
4096 EXPECT_EQ(1, cache.disk_cache()->doomed_count());
4097
4098 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4099 EXPECT_EQ(0, cache.disk_cache()->open_count());
4100 EXPECT_EQ(2, cache.disk_cache()->create_count());
4101
4102 for (auto& context : context_list) {
4103 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
4104 }
4105
4106 for (auto& context : context_list) {
4107 if (context->result == ERR_IO_PENDING) {
4108 context->result = context->callback.WaitForResult();
4109 }
4110
4111 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4112 }
4113
4114 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4115 EXPECT_EQ(0, cache.disk_cache()->open_count());
4116 EXPECT_EQ(2, cache.disk_cache()->create_count());
4117 }
4118
4119 // Tests that a GET followed by a DELETE results in DELETE immediately starting
4120 // the headers phase and the entry is doomed.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationDelete)4121 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationDelete) {
4122 MockHttpCache cache;
4123
4124 MockHttpRequest request(kSimpleGET_Transaction);
4125 request.load_flags |= LOAD_VALIDATE_CACHE;
4126
4127 MockHttpRequest delete_request(kSimpleGET_Transaction);
4128 delete_request.method = "DELETE";
4129
4130 std::vector<std::unique_ptr<Context>> context_list;
4131 const int kNumTransactions = 2;
4132
4133 for (int i = 0; i < kNumTransactions; ++i) {
4134 context_list.push_back(std::make_unique<Context>());
4135 auto& c = context_list[i];
4136
4137 MockHttpRequest* this_request = &request;
4138 if (i == 1) {
4139 this_request = &delete_request;
4140 }
4141
4142 c->result = cache.CreateTransaction(&c->trans);
4143 ASSERT_THAT(c->result, IsOk());
4144 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
4145
4146 c->result = c->trans->Start(this_request, c->callback.callback(),
4147 NetLogWithSource());
4148 }
4149
4150 // All requests are waiting for the active entry.
4151 for (auto& context : context_list) {
4152 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
4153 }
4154
4155 // Allow all requests to move from the Create queue to the active entry.
4156 base::RunLoop().RunUntilIdle();
4157
4158 // The first request should be a writer at this point, and the subsequent
4159 // request should have passed the validation phase and doomed the existing
4160 // entry.
4161 EXPECT_TRUE(cache.disk_cache()->IsDiskEntryDoomed(request.CacheKey()));
4162
4163 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4164 EXPECT_EQ(0, cache.disk_cache()->open_count());
4165 EXPECT_EQ(1, cache.disk_cache()->create_count());
4166
4167 // All requests depend on the writer, and the writer is between Start and
4168 // Read, i.e. idle.
4169 for (auto& context : context_list) {
4170 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
4171 }
4172
4173 for (auto& context : context_list) {
4174 if (context->result == ERR_IO_PENDING) {
4175 context->result = context->callback.WaitForResult();
4176 }
4177 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4178 }
4179
4180 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4181 EXPECT_EQ(0, cache.disk_cache()->open_count());
4182 EXPECT_EQ(1, cache.disk_cache()->create_count());
4183 }
4184
4185 // Tests that a transaction which is in validated queue can be destroyed without
4186 // any impact to other transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelValidated)4187 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelValidated) {
4188 MockHttpCache cache;
4189
4190 MockHttpRequest request(kSimpleGET_Transaction);
4191
4192 MockTransaction transaction(kSimpleGET_Transaction);
4193 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4194 MockHttpRequest read_only_request(transaction);
4195
4196 std::vector<std::unique_ptr<Context>> context_list;
4197 const int kNumTransactions = 2;
4198
4199 for (int i = 0; i < kNumTransactions; ++i) {
4200 context_list.push_back(std::make_unique<Context>());
4201 auto& c = context_list[i];
4202
4203 c->result = cache.CreateTransaction(&c->trans);
4204 ASSERT_THAT(c->result, IsOk());
4205
4206 MockHttpRequest* current_request = i == 1 ? &read_only_request : &request;
4207
4208 c->result = c->trans->Start(current_request, c->callback.callback(),
4209 NetLogWithSource());
4210 }
4211
4212 // Allow all requests to move from the Create queue to the active entry.
4213 base::RunLoop().RunUntilIdle();
4214
4215 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4216 EXPECT_EQ(0, cache.disk_cache()->open_count());
4217 EXPECT_EQ(1, cache.disk_cache()->create_count());
4218
4219 std::string cache_key = request.CacheKey();
4220 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4221 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4222
4223 context_list[1].reset();
4224
4225 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4226
4227 // Complete the rest of the transactions.
4228 for (auto& context : context_list) {
4229 if (!context) {
4230 continue;
4231 }
4232 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4233 }
4234
4235 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4236 EXPECT_EQ(0, cache.disk_cache()->open_count());
4237 EXPECT_EQ(1, cache.disk_cache()->create_count());
4238 }
4239
4240 // Tests that an idle writer transaction can be deleted without impacting the
4241 // existing writers.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingCancelIdleTransaction)4242 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingCancelIdleTransaction) {
4243 MockHttpCache cache;
4244
4245 MockHttpRequest request(kSimpleGET_Transaction);
4246
4247 std::vector<std::unique_ptr<Context>> context_list;
4248 const int kNumTransactions = 2;
4249
4250 for (int i = 0; i < kNumTransactions; ++i) {
4251 context_list.push_back(std::make_unique<Context>());
4252 auto& c = context_list[i];
4253
4254 c->result = cache.CreateTransaction(&c->trans);
4255 ASSERT_THAT(c->result, IsOk());
4256
4257 c->result =
4258 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4259 }
4260
4261 // Allow all requests to move from the Create queue to the active entry.
4262 base::RunLoop().RunUntilIdle();
4263
4264 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4265 EXPECT_EQ(0, cache.disk_cache()->open_count());
4266 EXPECT_EQ(1, cache.disk_cache()->create_count());
4267
4268 // Both transactions would be added to writers.
4269 std::string cache_key = request.CacheKey();
4270 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
4271
4272 context_list[1].reset();
4273
4274 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
4275
4276 // Complete the rest of the transactions.
4277 for (auto& context : context_list) {
4278 if (!context) {
4279 continue;
4280 }
4281 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4282 }
4283
4284 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4285 EXPECT_EQ(0, cache.disk_cache()->open_count());
4286 EXPECT_EQ(1, cache.disk_cache()->create_count());
4287 }
4288
4289 // Tests that a transaction which is in validated queue can timeout and start
4290 // the headers phase again.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationValidatedTimeout)4291 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationValidatedTimeout) {
4292 MockHttpCache cache;
4293
4294 MockHttpRequest request(kSimpleGET_Transaction);
4295
4296 MockTransaction transaction(kSimpleGET_Transaction);
4297 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4298 MockHttpRequest read_only_request(transaction);
4299
4300 std::vector<std::unique_ptr<Context>> context_list;
4301 const int kNumTransactions = 2;
4302
4303 for (int i = 0; i < kNumTransactions; ++i) {
4304 context_list.push_back(std::make_unique<Context>());
4305 auto& c = context_list[i];
4306
4307 MockHttpRequest* this_request = &request;
4308 if (i == 1) {
4309 this_request = &read_only_request;
4310 cache.SimulateCacheLockTimeoutAfterHeaders();
4311 }
4312
4313 c->result = cache.CreateTransaction(&c->trans);
4314 ASSERT_THAT(c->result, IsOk());
4315
4316 c->result = c->trans->Start(this_request, c->callback.callback(),
4317 NetLogWithSource());
4318 }
4319
4320 // Allow all requests to move from the Create queue to the active entry.
4321 base::RunLoop().RunUntilIdle();
4322
4323 // The first request should be a writer at this point, and the subsequent
4324 // requests should have completed validation, timed out and restarted.
4325 // Since it is a read only request, it will error out.
4326
4327 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4328 EXPECT_EQ(0, cache.disk_cache()->open_count());
4329 EXPECT_EQ(1, cache.disk_cache()->create_count());
4330
4331 std::string cache_key = request.CacheKey();
4332 EXPECT_TRUE(cache.IsWriterPresent(cache_key));
4333 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4334
4335 base::RunLoop().RunUntilIdle();
4336
4337 int rv = context_list[1]->callback.WaitForResult();
4338 EXPECT_EQ(ERR_CACHE_MISS, rv);
4339
4340 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4341 kSimpleGET_Transaction);
4342 }
4343
4344 // Tests that a transaction which is in readers can be destroyed without
4345 // any impact to other transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelReader)4346 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelReader) {
4347 MockHttpCache cache;
4348
4349 MockHttpRequest request(kSimpleGET_Transaction);
4350
4351 MockTransaction transaction(kSimpleGET_Transaction);
4352 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4353 MockHttpRequest validate_request(transaction);
4354
4355 int kNumTransactions = 4;
4356 std::vector<std::unique_ptr<Context>> context_list;
4357
4358 for (int i = 0; i < kNumTransactions; ++i) {
4359 context_list.push_back(std::make_unique<Context>());
4360 auto& c = context_list[i];
4361
4362 c->result = cache.CreateTransaction(&c->trans);
4363 ASSERT_THAT(c->result, IsOk());
4364
4365 MockHttpRequest* this_request = &request;
4366 if (i == 3) {
4367 this_request = &validate_request;
4368 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
4369 }
4370
4371 c->result = c->trans->Start(this_request, c->callback.callback(),
4372 NetLogWithSource());
4373 }
4374
4375 // Allow all requests to move from the Create queue to the active entry.
4376 base::RunLoop().RunUntilIdle();
4377
4378 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4379 EXPECT_EQ(0, cache.disk_cache()->open_count());
4380 EXPECT_EQ(1, cache.disk_cache()->create_count());
4381
4382 std::string cache_key = request.CacheKey();
4383
4384 EXPECT_EQ(kNumTransactions - 1, cache.GetCountWriterTransactions(cache_key));
4385 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4386
4387 // Complete the response body.
4388 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4389 kSimpleGET_Transaction);
4390
4391 // Rest of the transactions should move to readers.
4392 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
4393 EXPECT_EQ(kNumTransactions - 2, cache.GetCountReaders(cache_key));
4394 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4395 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4396
4397 // Add 2 new transactions.
4398 kNumTransactions = 6;
4399
4400 for (int i = 4; i < kNumTransactions; ++i) {
4401 context_list.push_back(std::make_unique<Context>());
4402 auto& c = context_list[i];
4403
4404 c->result = cache.CreateTransaction(&c->trans);
4405 ASSERT_THAT(c->result, IsOk());
4406
4407 c->result =
4408 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4409 }
4410
4411 EXPECT_EQ(2, cache.GetCountAddToEntryQueue(cache_key));
4412
4413 // Delete a reader.
4414 context_list[1].reset();
4415
4416 // Deleting the reader did not impact any other transaction.
4417 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
4418 EXPECT_EQ(2, cache.GetCountAddToEntryQueue(cache_key));
4419 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4420
4421 // Resume network start for headers_transaction. It will doom the entry as it
4422 // will be a 200 and will go to network for the response body.
4423 context_list[3]->trans->ResumeNetworkStart();
4424
4425 // The pending transactions will be added to a new entry as writers.
4426 base::RunLoop().RunUntilIdle();
4427
4428 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4429
4430 // Complete the rest of the transactions.
4431 for (int i = 2; i < kNumTransactions; ++i) {
4432 ReadAndVerifyTransaction(context_list[i]->trans.get(),
4433 kSimpleGET_Transaction);
4434 }
4435
4436 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4437 EXPECT_EQ(0, cache.disk_cache()->open_count());
4438 EXPECT_EQ(2, cache.disk_cache()->create_count());
4439 }
4440
4441 // Tests that when the only writer goes away, it immediately cleans up rather
4442 // than wait for the network request to finish. See https://crbug.com/804868.
TEST_F(HttpCacheTest,SimpleGET_HangingCacheWriteCleanup)4443 TEST_F(HttpCacheTest, SimpleGET_HangingCacheWriteCleanup) {
4444 MockHttpCache mock_cache;
4445 MockHttpRequest request(kSimpleGET_Transaction);
4446
4447 std::unique_ptr<HttpTransaction> transaction;
4448 mock_cache.CreateTransaction(&transaction);
4449 TestCompletionCallback callback;
4450 int result =
4451 transaction->Start(&request, callback.callback(), NetLogWithSource());
4452
4453 // Get the transaction ready to read.
4454 result = callback.GetResult(result);
4455
4456 // Read the first byte.
4457 auto buffer = base::MakeRefCounted<IOBufferWithSize>(1);
4458 ReleaseBufferCompletionCallback buffer_callback(buffer.get());
4459 result = transaction->Read(buffer.get(), 1, buffer_callback.callback());
4460 EXPECT_EQ(1, buffer_callback.GetResult(result));
4461
4462 // Read the second byte, but leave the cache write hanging.
4463 std::string cache_key = request.CacheKey();
4464 scoped_refptr<MockDiskEntry> entry =
4465 mock_cache.disk_cache()->GetDiskEntryRef(cache_key);
4466 entry->SetDefer(MockDiskEntry::DEFER_WRITE);
4467
4468 auto buffer2 = base::MakeRefCounted<IOBufferWithSize>(1);
4469 ReleaseBufferCompletionCallback buffer_callback2(buffer2.get());
4470 result = transaction->Read(buffer2.get(), 1, buffer_callback2.callback());
4471 EXPECT_EQ(ERR_IO_PENDING, result);
4472 base::RunLoop().RunUntilIdle();
4473 EXPECT_TRUE(mock_cache.IsWriterPresent(cache_key));
4474
4475 // At this point the next byte should have been read from the network but is
4476 // waiting to be written to the cache. Destroy the transaction and make sure
4477 // that everything has been cleaned up.
4478 transaction = nullptr;
4479 EXPECT_FALSE(mock_cache.IsWriterPresent(cache_key));
4480 EXPECT_FALSE(mock_cache.network_layer()->last_transaction());
4481 }
4482
4483 // Tests that a transaction writer can be destroyed mid-read.
4484 // A waiting for read transaction should be able to read the data that was
4485 // driven by the Read started by the cancelled writer.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingCancelWriter)4486 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingCancelWriter) {
4487 MockHttpCache cache;
4488
4489 MockHttpRequest request(kSimpleGET_Transaction);
4490
4491 MockTransaction transaction(kSimpleGET_Transaction);
4492 transaction.load_flags |= LOAD_VALIDATE_CACHE;
4493 MockHttpRequest validate_request(transaction);
4494
4495 const int kNumTransactions = 3;
4496 std::vector<std::unique_ptr<Context>> context_list;
4497
4498 for (int i = 0; i < kNumTransactions; ++i) {
4499 context_list.push_back(std::make_unique<Context>());
4500 auto& c = context_list[i];
4501
4502 c->result = cache.CreateTransaction(&c->trans);
4503 ASSERT_THAT(c->result, IsOk());
4504
4505 MockHttpRequest* this_request = &request;
4506 if (i == 2) {
4507 this_request = &validate_request;
4508 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
4509 }
4510
4511 c->result = c->trans->Start(this_request, c->callback.callback(),
4512 NetLogWithSource());
4513 }
4514
4515 // Allow all requests to move from the Create queue to the active entry.
4516 base::RunLoop().RunUntilIdle();
4517
4518 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4519 EXPECT_EQ(0, cache.disk_cache()->open_count());
4520 EXPECT_EQ(1, cache.disk_cache()->create_count());
4521
4522 std::string cache_key = validate_request.CacheKey();
4523 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
4524 EXPECT_EQ(2, cache.GetCountWriterTransactions(cache_key));
4525
4526 // Initiate Read from both writers and kill 1 of them mid-read.
4527 std::string first_read;
4528 for (int i = 0; i < 2; i++) {
4529 auto& c = context_list[i];
4530 const int kBufferSize = 5;
4531 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
4532 ReleaseBufferCompletionCallback cb(buffer.get());
4533 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
4534 EXPECT_EQ(ERR_IO_PENDING, c->result);
4535 // Deleting one writer at this point will not impact other transactions
4536 // since writers contain more transactions.
4537 if (i == 1) {
4538 context_list[0].reset();
4539 base::RunLoop().RunUntilIdle();
4540 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
4541 std::string data_read(buffer->data(), kBufferSize);
4542 first_read = data_read;
4543 }
4544 }
4545
4546 // Resume network start for headers_transaction. It will doom the existing
4547 // entry and create a new entry due to validation returning a 200.
4548 auto& c = context_list[2];
4549 c->trans->ResumeNetworkStart();
4550
4551 base::RunLoop().RunUntilIdle();
4552
4553 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4554
4555 // Complete the rest of the transactions.
4556 for (int i = 0; i < kNumTransactions; i++) {
4557 auto& context = context_list[i];
4558 if (!context) {
4559 continue;
4560 }
4561 if (i == 1) {
4562 ReadRemainingAndVerifyTransaction(context->trans.get(), first_read,
4563 kSimpleGET_Transaction);
4564 } else {
4565 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
4566 }
4567 }
4568
4569 EXPECT_EQ(2, cache.network_layer()->transaction_count());
4570 EXPECT_EQ(0, cache.disk_cache()->open_count());
4571 EXPECT_EQ(2, cache.disk_cache()->create_count());
4572 }
4573
4574 // Tests the case when network read failure happens. Idle and waiting
4575 // transactions should fail and headers transaction should be restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingNetworkReadFailed)4576 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingNetworkReadFailed) {
4577 MockHttpCache cache;
4578
4579 ScopedMockTransaction fail_transaction(kSimpleGET_Transaction);
4580 fail_transaction.read_return_code = ERR_INTERNET_DISCONNECTED;
4581 MockHttpRequest failing_request(fail_transaction);
4582
4583 MockHttpRequest request(kSimpleGET_Transaction);
4584
4585 MockTransaction transaction(kSimpleGET_Transaction);
4586 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4587 MockHttpRequest read_request(transaction);
4588
4589 const int kNumTransactions = 4;
4590 std::vector<std::unique_ptr<Context>> context_list;
4591
4592 for (int i = 0; i < kNumTransactions; ++i) {
4593 context_list.push_back(std::make_unique<Context>());
4594 auto& c = context_list[i];
4595
4596 c->result = cache.CreateTransaction(&c->trans);
4597 ASSERT_THAT(c->result, IsOk());
4598
4599 MockHttpRequest* this_request = &request;
4600 if (i == 0) {
4601 this_request = &failing_request;
4602 }
4603 if (i == 3) {
4604 this_request = &read_request;
4605 }
4606
4607 c->result = c->trans->Start(this_request, c->callback.callback(),
4608 NetLogWithSource());
4609 }
4610
4611 // Allow all requests to move from the Create queue to the active entry.
4612 base::RunLoop().RunUntilIdle();
4613
4614 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4615 EXPECT_EQ(0, cache.disk_cache()->open_count());
4616 EXPECT_EQ(1, cache.disk_cache()->create_count());
4617
4618 std::string cache_key = read_request.CacheKey();
4619 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4620 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4621
4622 // Initiate Read from two writers and let the first get a network failure.
4623 for (int i = 0; i < 2; i++) {
4624 auto& c = context_list[i];
4625 const int kBufferSize = 5;
4626 auto buffer = base::MakeRefCounted<IOBufferWithSize>(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 auto buffer = base::MakeRefCounted<IOBufferWithSize>(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
4681 c->result = c->trans->Start(this_request, c->callback.callback(),
4682 NetLogWithSource());
4683 }
4684
4685 // Allow all requests to move from the Create queue to the active entry.
4686 base::RunLoop().RunUntilIdle();
4687
4688 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4689 EXPECT_EQ(0, cache.disk_cache()->open_count());
4690 EXPECT_EQ(1, cache.disk_cache()->create_count());
4691
4692 std::string cache_key = read_request.CacheKey();
4693 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4694 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4695
4696 // Initiate Read from two writers and let the first get a cache write failure.
4697 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
4698 // We have to open the entry again to propagate the failure flag.
4699 disk_cache::Entry* en;
4700 cache.OpenBackendEntry(cache_key, &en);
4701 en->Close();
4702 const int kBufferSize = 5;
4703 std::vector<scoped_refptr<IOBuffer>> buffer(
4704 3, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
4705 for (int i = 0; i < 2; i++) {
4706 auto& c = context_list[i];
4707 c->result =
4708 c->trans->Read(buffer[i].get(), kBufferSize, c->callback.callback());
4709 EXPECT_EQ(ERR_IO_PENDING, c->result);
4710 }
4711
4712 std::string first_read;
4713 base::RunLoop().RunUntilIdle();
4714 for (int i = 0; i < 2; i++) {
4715 auto& c = context_list[i];
4716 c->result = c->callback.WaitForResult();
4717 if (i == 0) {
4718 EXPECT_EQ(5, c->result);
4719 std::string data_read(buffer[i]->data(), kBufferSize);
4720 first_read = data_read;
4721 } else {
4722 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, c->result);
4723 }
4724 }
4725
4726 // The entry should have been doomed and destroyed and the headers transaction
4727 // restarted. Since headers transaction is read-only it will error out.
4728 auto& read_only = context_list[3];
4729 read_only->result = read_only->callback.WaitForResult();
4730 EXPECT_EQ(ERR_CACHE_MISS, read_only->result);
4731
4732 EXPECT_FALSE(cache.IsWriterPresent(cache_key));
4733
4734 // Invoke Read on the 3rd transaction and it should get the error code back.
4735 auto& c = context_list[2];
4736 c->result =
4737 c->trans->Read(buffer[2].get(), kBufferSize, c->callback.callback());
4738 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, c->result);
4739
4740 // The first transaction should be able to continue to read from the network
4741 // without writing to the cache.
4742 auto& succ_read = context_list[0];
4743 ReadRemainingAndVerifyTransaction(succ_read->trans.get(), first_read,
4744 kSimpleGET_Transaction);
4745 }
4746
4747 // Tests that POST requests do not join existing transactions for parallel
4748 // writing to the cache. Note that two POSTs only map to the same entry if their
4749 // upload data identifier is same and that should happen for back-forward case
4750 // (LOAD_ONLY_FROM_CACHE). But this test tests without LOAD_ONLY_FROM_CACHE
4751 // because read-only transactions anyways do not join parallel writing.
4752 // TODO(shivanisha) Testing this because it is allowed by the code but looks
4753 // like the code should disallow two POSTs without LOAD_ONLY_FROM_CACHE with the
4754 // same upload data identifier to map to the same entry.
TEST_F(HttpCacheTest,SimplePOST_ParallelWritingDisallowed)4755 TEST_F(HttpCacheTest, SimplePOST_ParallelWritingDisallowed) {
4756 MockHttpCache cache;
4757
4758 MockTransaction transaction(kSimplePOST_Transaction);
4759
4760 const int64_t kUploadId = 1; // Just a dummy value.
4761
4762 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
4763 element_readers.push_back(
4764 std::make_unique<UploadBytesElementReader>("hello", 5));
4765 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
4766 kUploadId);
4767
4768 // Note that both transactions should have the same upload_data_stream
4769 // identifier to map to the same entry.
4770 transaction.load_flags = LOAD_SKIP_CACHE_VALIDATION;
4771 MockHttpRequest request(transaction);
4772 request.upload_data_stream = &upload_data_stream;
4773
4774 const int kNumTransactions = 2;
4775 std::vector<std::unique_ptr<Context>> context_list;
4776
4777 for (int i = 0; i < kNumTransactions; ++i) {
4778 context_list.push_back(std::make_unique<Context>());
4779 auto& c = context_list[i];
4780
4781 c->result = cache.CreateTransaction(&c->trans);
4782 ASSERT_THAT(c->result, IsOk());
4783
4784 c->result =
4785 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
4786
4787 // Complete the headers phase request.
4788 base::RunLoop().RunUntilIdle();
4789 }
4790
4791 std::string cache_key = request.CacheKey();
4792 // Only the 1st transaction gets added to writers.
4793 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4794 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4795
4796 // Read the 1st transaction.
4797 ReadAndVerifyTransaction(context_list[0]->trans.get(),
4798 kSimplePOST_Transaction);
4799
4800 // 2nd transaction should now become a reader.
4801 base::RunLoop().RunUntilIdle();
4802 EXPECT_EQ(1, cache.GetCountReaders(cache_key));
4803 EXPECT_EQ(0, cache.GetCountDoneHeadersQueue(cache_key));
4804 ReadAndVerifyTransaction(context_list[1]->trans.get(),
4805 kSimplePOST_Transaction);
4806
4807 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4808 EXPECT_EQ(0, cache.disk_cache()->open_count());
4809 EXPECT_EQ(1, cache.disk_cache()->create_count());
4810
4811 context_list.clear();
4812 }
4813
4814 // Tests the case when parallel writing succeeds. Tests both idle and waiting
4815 // transactions.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingSuccess)4816 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingSuccess) {
4817 MockHttpCache cache;
4818
4819 MockHttpRequest request(kSimpleGET_Transaction);
4820
4821 MockTransaction transaction(kSimpleGET_Transaction);
4822 transaction.load_flags |= LOAD_ONLY_FROM_CACHE;
4823 MockHttpRequest read_request(transaction);
4824
4825 const int kNumTransactions = 4;
4826 std::vector<std::unique_ptr<Context>> context_list;
4827
4828 for (int i = 0; i < kNumTransactions; ++i) {
4829 context_list.push_back(std::make_unique<Context>());
4830 auto& c = context_list[i];
4831
4832 c->result = cache.CreateTransaction(&c->trans);
4833 ASSERT_THAT(c->result, IsOk());
4834
4835 MockHttpRequest* this_request = &request;
4836 if (i == 3) {
4837 this_request = &read_request;
4838 }
4839
4840 c->result = c->trans->Start(this_request, c->callback.callback(),
4841 NetLogWithSource());
4842 }
4843
4844 // Allow all requests to move from the Create queue to the active entry.
4845 base::RunLoop().RunUntilIdle();
4846
4847 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4848 EXPECT_EQ(0, cache.disk_cache()->open_count());
4849 EXPECT_EQ(1, cache.disk_cache()->create_count());
4850
4851 std::string cache_key = request.CacheKey();
4852 EXPECT_EQ(3, cache.GetCountWriterTransactions(cache_key));
4853 EXPECT_EQ(1, cache.GetCountDoneHeadersQueue(cache_key));
4854
4855 // Initiate Read from two writers.
4856 const int kBufferSize = 5;
4857 std::vector<scoped_refptr<IOBuffer>> buffer(
4858 3, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
4859 for (int i = 0; i < 2; i++) {
4860 auto& c = context_list[i];
4861 c->result =
4862 c->trans->Read(buffer[i].get(), kBufferSize, c->callback.callback());
4863 EXPECT_EQ(ERR_IO_PENDING, c->result);
4864 }
4865
4866 std::vector<std::string> first_read(2);
4867 base::RunLoop().RunUntilIdle();
4868 for (int i = 0; i < 2; i++) {
4869 auto& c = context_list[i];
4870 c->result = c->callback.WaitForResult();
4871 EXPECT_EQ(5, c->result);
4872 std::string data_read(buffer[i]->data(), kBufferSize);
4873 first_read[i] = data_read;
4874 }
4875 EXPECT_EQ(first_read[0], first_read[1]);
4876
4877 // The first transaction should be able to continue to read from the network
4878 // without writing to the cache.
4879 for (int i = 0; i < 2; i++) {
4880 auto& c = context_list[i];
4881 ReadRemainingAndVerifyTransaction(c->trans.get(), first_read[i],
4882 kSimpleGET_Transaction);
4883 if (i == 0) {
4884 // Remaining transactions should now be readers.
4885 EXPECT_EQ(3, cache.GetCountReaders(cache_key));
4886 }
4887 }
4888
4889 // Verify the rest of the transactions.
4890 for (int i = 2; i < kNumTransactions; i++) {
4891 auto& c = context_list[i];
4892 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
4893 }
4894
4895 context_list.clear();
4896 }
4897
4898 // Tests the case when parallel writing involves things bigger than what cache
4899 // can store. In this case, the best we can do is re-fetch it.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritingHuge)4900 TEST_F(HttpCacheTest, SimpleGET_ParallelWritingHuge) {
4901 MockHttpCache cache;
4902 cache.disk_cache()->set_max_file_size(10);
4903
4904 ScopedMockTransaction transaction(kSimpleGET_Transaction);
4905 std::string response_headers = base::StrCat(
4906 {kSimpleGET_Transaction.response_headers, "Content-Length: ",
4907 base::NumberToString(strlen(kSimpleGET_Transaction.data)), "\n"});
4908 transaction.response_headers = response_headers.c_str();
4909 MockHttpRequest request(transaction);
4910
4911 const int kNumTransactions = 4;
4912 std::vector<std::unique_ptr<Context>> context_list;
4913
4914 for (int i = 0; i < kNumTransactions; ++i) {
4915 context_list.push_back(std::make_unique<Context>());
4916 auto& c = context_list[i];
4917
4918 c->result = cache.CreateTransaction(&c->trans);
4919 ASSERT_THAT(c->result, IsOk());
4920
4921 MockHttpRequest* this_request = &request;
4922 c->result = c->trans->Start(this_request, c->callback.callback(),
4923 NetLogWithSource());
4924 }
4925
4926 // Start them up.
4927 base::RunLoop().RunUntilIdle();
4928
4929 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4930 EXPECT_EQ(0, cache.disk_cache()->open_count());
4931 EXPECT_EQ(1, cache.disk_cache()->create_count());
4932
4933 std::string cache_key = request.CacheKey();
4934 EXPECT_EQ(1, cache.GetCountWriterTransactions(cache_key));
4935 EXPECT_EQ(kNumTransactions - 1, cache.GetCountDoneHeadersQueue(cache_key));
4936
4937 // Initiate Read from first transaction.
4938 const int kBufferSize = 5;
4939 std::vector<scoped_refptr<IOBuffer>> buffer(
4940 kNumTransactions, base::MakeRefCounted<IOBufferWithSize>(kBufferSize));
4941 auto& c = context_list[0];
4942 c->result =
4943 c->trans->Read(buffer[0].get(), kBufferSize, c->callback.callback());
4944 EXPECT_EQ(ERR_IO_PENDING, c->result);
4945
4946 // ... and complete it.
4947 std::vector<std::string> first_read(kNumTransactions);
4948 base::RunLoop().RunUntilIdle();
4949 c->result = c->callback.WaitForResult();
4950 EXPECT_EQ(kBufferSize, c->result);
4951 std::string data_read(buffer[0]->data(), kBufferSize);
4952 first_read[0] = data_read;
4953 EXPECT_EQ("<html", first_read[0]);
4954
4955 // Complete all of them.
4956 for (int i = 0; i < kNumTransactions; i++) {
4957 ReadRemainingAndVerifyTransaction(context_list[i]->trans.get(),
4958 first_read[i], kSimpleGET_Transaction);
4959 }
4960
4961 // Sadly all of them have to hit the network
4962 EXPECT_EQ(kNumTransactions, cache.network_layer()->transaction_count());
4963
4964 context_list.clear();
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 auto buffer = base::MakeRefCounted<IOBufferWithSize>(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 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
5095 ReleaseBufferCompletionCallback cb(buffer.get());
5096 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
5097 EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
5098 }
5099
5100 // Deleting the active transaction at this point will not impact the other
5101 // transactions since there are other transactions in writers.
5102 context_list[0].reset();
5103
5104 base::RunLoop().RunUntilIdle();
5105
5106 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5107 EXPECT_EQ(0, cache.disk_cache()->open_count());
5108 EXPECT_EQ(1, cache.disk_cache()->create_count());
5109
5110 // Complete the rest of the transactions.
5111 for (auto& context : context_list) {
5112 if (!context) {
5113 continue;
5114 }
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 }
5233 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
5234 }
5235
5236 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5237 EXPECT_EQ(0, cache.disk_cache()->open_count());
5238 EXPECT_EQ(2, cache.disk_cache()->create_count());
5239 }
5240
5241 // Tests that a transaction is currently in headers phase and is destroyed
5242 // leading to destroying the entry.
TEST_F(HttpCacheTest,SimpleGET_ParallelValidationCancelHeaders)5243 TEST_F(HttpCacheTest, SimpleGET_ParallelValidationCancelHeaders) {
5244 MockHttpCache cache;
5245
5246 MockHttpRequest request(kSimpleGET_Transaction);
5247
5248 const int kNumTransactions = 2;
5249 std::vector<std::unique_ptr<Context>> context_list;
5250
5251 for (int i = 0; i < kNumTransactions; ++i) {
5252 context_list.push_back(std::make_unique<Context>());
5253 auto& c = context_list[i];
5254
5255 c->result = cache.CreateTransaction(&c->trans);
5256 ASSERT_THAT(c->result, IsOk());
5257
5258 if (i == 0) {
5259 c->trans->SetBeforeNetworkStartCallback(base::BindOnce(&DeferCallback));
5260 }
5261
5262 c->result =
5263 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5264 }
5265
5266 base::RunLoop().RunUntilIdle();
5267
5268 std::string cache_key = request.CacheKey();
5269 EXPECT_TRUE(cache.IsHeadersTransactionPresent(cache_key));
5270 EXPECT_EQ(1, cache.GetCountAddToEntryQueue(cache_key));
5271
5272 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5273 EXPECT_EQ(0, cache.disk_cache()->open_count());
5274 EXPECT_EQ(1, cache.disk_cache()->create_count());
5275
5276 // Delete the headers transaction.
5277 context_list[0].reset();
5278
5279 base::RunLoop().RunUntilIdle();
5280
5281 // Complete the rest of the transactions.
5282 for (auto& context : context_list) {
5283 if (!context) {
5284 continue;
5285 }
5286 ReadAndVerifyTransaction(context->trans.get(), kSimpleGET_Transaction);
5287 }
5288
5289 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5290 EXPECT_EQ(0, cache.disk_cache()->open_count());
5291 EXPECT_EQ(2, cache.disk_cache()->create_count());
5292 }
5293
5294 // Similar to the above test, except here cache write fails and the
5295 // validated transactions should be restarted.
TEST_F(HttpCacheTest,SimpleGET_ParallelWritersFailWrite)5296 TEST_F(HttpCacheTest, SimpleGET_ParallelWritersFailWrite) {
5297 MockHttpCache cache;
5298
5299 MockHttpRequest request(kSimpleGET_Transaction);
5300
5301 const int kNumTransactions = 5;
5302 std::vector<std::unique_ptr<Context>> context_list;
5303
5304 for (int i = 0; i < kNumTransactions; ++i) {
5305 context_list.push_back(std::make_unique<Context>());
5306 auto& c = context_list[i];
5307
5308 c->result = cache.CreateTransaction(&c->trans);
5309 ASSERT_THAT(c->result, IsOk());
5310 EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
5311
5312 c->result =
5313 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5314 }
5315
5316 // All requests are waiting for the active entry.
5317 for (auto& context : context_list) {
5318 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context->trans->GetLoadState());
5319 }
5320
5321 // Allow all requests to move from the Create queue to the active entry.
5322 base::RunLoop().RunUntilIdle();
5323
5324 // All transactions become writers.
5325 std::string cache_key = request.CacheKey();
5326 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
5327
5328 // All requests depend on the writer, and the writer is between Start and
5329 // Read, i.e. idle.
5330 for (auto& context : context_list) {
5331 EXPECT_EQ(LOAD_STATE_IDLE, context->trans->GetLoadState());
5332 }
5333
5334 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5335 EXPECT_EQ(0, cache.disk_cache()->open_count());
5336 EXPECT_EQ(1, cache.disk_cache()->create_count());
5337
5338 // Fail the request.
5339 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_ALL);
5340 // We have to open the entry again to propagate the failure flag.
5341 disk_cache::Entry* en;
5342 cache.OpenBackendEntry(cache_key, &en);
5343 en->Close();
5344
5345 for (int i = 0; i < kNumTransactions; ++i) {
5346 auto& c = context_list[i];
5347 if (c->result == ERR_IO_PENDING) {
5348 c->result = c->callback.WaitForResult();
5349 }
5350 if (i == 1) {
5351 // The earlier entry must be destroyed and its disk entry doomed.
5352 EXPECT_TRUE(cache.disk_cache()->IsDiskEntryDoomed(cache_key));
5353 }
5354
5355 if (i == 0) {
5356 // Consumer gets the response even if cache write failed.
5357 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5358 } else {
5359 // Read should lead to a failure being returned.
5360 const int kBufferSize = 5;
5361 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBufferSize);
5362 ReleaseBufferCompletionCallback cb(buffer.get());
5363 c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
5364 EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, cb.GetResult(c->result));
5365 }
5366 }
5367 }
5368
5369 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4769.
5370 // If cancelling a request is racing with another request for the same resource
5371 // finishing, we have to make sure that we remove both transactions from the
5372 // entry.
TEST_F(HttpCacheTest,SimpleGET_RacingReaders)5373 TEST_F(HttpCacheTest, SimpleGET_RacingReaders) {
5374 MockHttpCache cache;
5375
5376 MockHttpRequest request(kSimpleGET_Transaction);
5377 MockHttpRequest reader_request(kSimpleGET_Transaction);
5378 reader_request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
5379
5380 std::vector<std::unique_ptr<Context>> context_list;
5381 const int kNumTransactions = 5;
5382
5383 for (int i = 0; i < kNumTransactions; ++i) {
5384 context_list.push_back(std::make_unique<Context>());
5385 Context* c = context_list[i].get();
5386
5387 c->result = cache.CreateTransaction(&c->trans);
5388 ASSERT_THAT(c->result, IsOk());
5389
5390 MockHttpRequest* this_request = &request;
5391 if (i == 1 || i == 2) {
5392 this_request = &reader_request;
5393 }
5394
5395 c->result = c->trans->Start(this_request, c->callback.callback(),
5396 NetLogWithSource());
5397 }
5398
5399 // Allow all requests to move from the Create queue to the active entry.
5400 base::RunLoop().RunUntilIdle();
5401
5402 // The first request should be a writer at this point, and the subsequent
5403 // requests should be pending.
5404
5405 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5406 EXPECT_EQ(0, cache.disk_cache()->open_count());
5407 EXPECT_EQ(1, cache.disk_cache()->create_count());
5408
5409 Context* c = context_list[0].get();
5410 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5411 c->result = c->callback.WaitForResult();
5412 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5413
5414 // Now all transactions should be waiting for read to be invoked. Two readers
5415 // are because of the load flags and remaining two transactions were converted
5416 // to readers after skipping validation. Note that the remaining two went on
5417 // to process the headers in parallel with readers present on the entry.
5418 EXPECT_EQ(LOAD_STATE_IDLE, context_list[2]->trans->GetLoadState());
5419 EXPECT_EQ(LOAD_STATE_IDLE, context_list[3]->trans->GetLoadState());
5420
5421 c = context_list[1].get();
5422 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5423 c->result = c->callback.WaitForResult();
5424 if (c->result == OK) {
5425 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5426 }
5427
5428 // At this point we have one reader, two pending transactions and a task on
5429 // the queue to move to the next transaction. Now we cancel the request that
5430 // is the current reader, and expect the queued task to be able to start the
5431 // next request.
5432
5433 c = context_list[2].get();
5434 c->trans.reset();
5435
5436 for (int i = 3; i < kNumTransactions; ++i) {
5437 c = context_list[i].get();
5438 if (c->result == ERR_IO_PENDING) {
5439 c->result = c->callback.WaitForResult();
5440 }
5441 if (c->result == OK) {
5442 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5443 }
5444 }
5445
5446 // We should not have had to re-open the disk entry.
5447
5448 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5449 EXPECT_EQ(0, cache.disk_cache()->open_count());
5450 EXPECT_EQ(1, cache.disk_cache()->create_count());
5451 }
5452
5453 // Tests that we can doom an entry with pending transactions and delete one of
5454 // the pending transactions before the first one completes.
5455 // See http://code.google.com/p/chromium/issues/detail?id=25588
TEST_F(HttpCacheTest,SimpleGET_DoomWithPending)5456 TEST_F(HttpCacheTest, SimpleGET_DoomWithPending) {
5457 // We need simultaneous doomed / not_doomed entries so let's use a real cache.
5458 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
5459
5460 MockHttpRequest request(kSimpleGET_Transaction);
5461 MockHttpRequest writer_request(kSimpleGET_Transaction);
5462 writer_request.load_flags = LOAD_BYPASS_CACHE;
5463
5464 std::vector<std::unique_ptr<Context>> context_list;
5465 const int kNumTransactions = 4;
5466
5467 for (int i = 0; i < kNumTransactions; ++i) {
5468 context_list.push_back(std::make_unique<Context>());
5469 Context* c = context_list[i].get();
5470
5471 c->result = cache.CreateTransaction(&c->trans);
5472 ASSERT_THAT(c->result, IsOk());
5473
5474 MockHttpRequest* this_request = &request;
5475 if (i == 3) {
5476 this_request = &writer_request;
5477 }
5478
5479 c->result = c->trans->Start(this_request, c->callback.callback(),
5480 NetLogWithSource());
5481 }
5482
5483 base::RunLoop().RunUntilIdle();
5484
5485 // The first request should be a writer at this point, and the two subsequent
5486 // requests should be pending. The last request doomed the first entry.
5487
5488 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5489
5490 // Cancel the second transaction. Note that this and the 3rd transactions
5491 // would have completed their headers phase and would be waiting in the
5492 // done_headers_queue when the 2nd transaction is cancelled.
5493 context_list[1].reset();
5494
5495 for (int i = 0; i < kNumTransactions; ++i) {
5496 if (i == 1) {
5497 continue;
5498 }
5499 Context* c = context_list[i].get();
5500 ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
5501 c->result = c->callback.WaitForResult();
5502 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5503 }
5504 }
5505
TEST_F(HttpCacheTest,DoomDoesNotSetHints)5506 TEST_F(HttpCacheTest, DoomDoesNotSetHints) {
5507 // Test that a doomed writer doesn't set in-memory index hints.
5508 MockHttpCache cache;
5509 cache.disk_cache()->set_support_in_memory_entry_data(true);
5510
5511 // Request 1 is a normal one to a no-cache/no-etag resource, to potentially
5512 // set a "this is unvalidatable" hint in the cache. We also need it to
5513 // actually write out to the doomed entry after request 2 does its thing,
5514 // so its transaction is paused.
5515 ScopedMockTransaction transaction(kSimpleGET_Transaction);
5516 transaction.response_headers = "Cache-Control: no-cache\n";
5517 MockHttpRequest request1(transaction);
5518
5519 Context c1;
5520 c1.result = cache.CreateTransaction(&c1.trans);
5521 ASSERT_THAT(c1.result, IsOk());
5522 c1.trans->SetBeforeNetworkStartCallback(
5523 base::BindOnce([](bool* defer) { *defer = true; }));
5524 c1.result =
5525 c1.trans->Start(&request1, c1.callback.callback(), NetLogWithSource());
5526 ASSERT_THAT(c1.result, IsError(ERR_IO_PENDING));
5527
5528 // It starts, copies over headers info, but doesn't get to proceed.
5529 base::RunLoop().RunUntilIdle();
5530
5531 // Request 2 sets LOAD_BYPASS_CACHE to force the first one to be doomed ---
5532 // it'll want to be a writer.
5533 transaction.response_headers = kSimpleGET_Transaction.response_headers;
5534 MockHttpRequest request2(transaction);
5535 request2.load_flags = LOAD_BYPASS_CACHE;
5536
5537 Context c2;
5538 c2.result = cache.CreateTransaction(&c2.trans);
5539 ASSERT_THAT(c2.result, IsOk());
5540 c2.result =
5541 c2.trans->Start(&request2, c2.callback.callback(), NetLogWithSource());
5542 ASSERT_THAT(c2.result, IsError(ERR_IO_PENDING));
5543
5544 // Run Request2, then let the first one wrap up.
5545 base::RunLoop().RunUntilIdle();
5546 c2.callback.WaitForResult();
5547 ReadAndVerifyTransaction(c2.trans.get(), kSimpleGET_Transaction);
5548
5549 c1.trans->ResumeNetworkStart();
5550 c1.callback.WaitForResult();
5551 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
5552
5553 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5554 EXPECT_EQ(0, cache.disk_cache()->open_count());
5555 EXPECT_EQ(2, cache.disk_cache()->create_count());
5556
5557 // Request 3 tries to read from cache, and it should successfully do so. It's
5558 // run after the previous two transactions finish so it doesn't try to
5559 // cooperate with them, and is entirely driven by the state of the cache.
5560 MockHttpRequest request3(kSimpleGET_Transaction);
5561 Context context3;
5562 context3.result = cache.CreateTransaction(&context3.trans);
5563 ASSERT_THAT(context3.result, IsOk());
5564 context3.result = context3.trans->Start(
5565 &request3, context3.callback.callback(), NetLogWithSource());
5566 base::RunLoop().RunUntilIdle();
5567 ASSERT_THAT(context3.result, IsError(ERR_IO_PENDING));
5568 context3.result = context3.callback.WaitForResult();
5569 ReadAndVerifyTransaction(context3.trans.get(), kSimpleGET_Transaction);
5570
5571 EXPECT_EQ(2, cache.network_layer()->transaction_count());
5572 EXPECT_EQ(1, cache.disk_cache()->open_count());
5573 EXPECT_EQ(2, cache.disk_cache()->create_count());
5574 }
5575
5576 // This is a test for http://code.google.com/p/chromium/issues/detail?id=4731.
5577 // We may attempt to delete an entry synchronously with the act of adding a new
5578 // transaction to said entry.
TEST_F(HttpCacheTest,FastNoStoreGET_DoneWithPending)5579 TEST_F(HttpCacheTest, FastNoStoreGET_DoneWithPending) {
5580 MockHttpCache cache;
5581
5582 ScopedMockTransaction transaction(kFastNoStoreGET_Transaction);
5583 // The headers will be served right from the call to Start() the request.
5584 MockHttpRequest request(transaction);
5585 FastTransactionServer request_handler;
5586
5587 std::vector<std::unique_ptr<Context>> context_list;
5588 const int kNumTransactions = 3;
5589
5590 for (int i = 0; i < kNumTransactions; ++i) {
5591 context_list.push_back(std::make_unique<Context>());
5592 Context* c = context_list[i].get();
5593
5594 c->result = cache.CreateTransaction(&c->trans);
5595 ASSERT_THAT(c->result, IsOk());
5596
5597 c->result =
5598 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5599 }
5600
5601 // Allow all requests to move from the Create queue to the active entry.
5602 base::RunLoop().RunUntilIdle();
5603
5604 // The first request should be a writer at this point, and the subsequent
5605 // requests should have completed validation. Since the validation does not
5606 // result in a match, a new entry would be created.
5607
5608 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5609 EXPECT_EQ(0, cache.disk_cache()->open_count());
5610 EXPECT_EQ(3, cache.disk_cache()->create_count());
5611
5612 // Now, make sure that the second request asks for the entry not to be stored.
5613 request_handler.set_no_store(true);
5614
5615 for (int i = 0; i < kNumTransactions; ++i) {
5616 Context* c = context_list[i].get();
5617 if (c->result == ERR_IO_PENDING) {
5618 c->result = c->callback.WaitForResult();
5619 }
5620 ReadAndVerifyTransaction(c->trans.get(), transaction);
5621 context_list[i].reset();
5622 }
5623
5624 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5625 EXPECT_EQ(0, cache.disk_cache()->open_count());
5626 EXPECT_EQ(3, cache.disk_cache()->create_count());
5627 }
5628
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_CancelFirst)5629 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_CancelFirst) {
5630 MockHttpCache cache;
5631
5632 MockHttpRequest request(kSimpleGET_Transaction);
5633
5634 std::vector<std::unique_ptr<Context>> context_list;
5635 const int kNumTransactions = 2;
5636
5637 for (int i = 0; i < kNumTransactions; ++i) {
5638 context_list.push_back(std::make_unique<Context>());
5639 Context* c = context_list[i].get();
5640
5641 c->result = cache.CreateTransaction(&c->trans);
5642 ASSERT_THAT(c->result, IsOk());
5643
5644 c->result =
5645 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5646 }
5647
5648 // Allow all requests to move from the Create queue to the active entry.
5649 // All would have been added to writers.
5650 base::RunLoop().RunUntilIdle();
5651 std::string cache_key =
5652 *cache.http_cache()->GenerateCacheKeyForRequest(&request);
5653 EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
5654
5655 // The second transaction skipped validation, thus only one network
5656 // transaction is created.
5657 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5658 EXPECT_EQ(0, cache.disk_cache()->open_count());
5659 EXPECT_EQ(1, cache.disk_cache()->create_count());
5660
5661 for (int i = 0; i < kNumTransactions; ++i) {
5662 Context* c = context_list[i].get();
5663 if (c->result == ERR_IO_PENDING) {
5664 c->result = c->callback.WaitForResult();
5665 }
5666 // Destroy only the first transaction.
5667 // This should not impact the other writer transaction and the network
5668 // transaction will continue to be used by that transaction.
5669 if (i == 0) {
5670 context_list[i].reset();
5671 }
5672 }
5673
5674 // Complete the rest of the transactions.
5675 for (int i = 1; i < kNumTransactions; ++i) {
5676 Context* c = context_list[i].get();
5677 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5678 }
5679
5680 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5681 EXPECT_EQ(0, cache.disk_cache()->open_count());
5682 EXPECT_EQ(1, cache.disk_cache()->create_count());
5683 }
5684
5685 // Tests that we can cancel requests that are queued waiting to open the disk
5686 // cache entry.
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_CancelCreate)5687 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_CancelCreate) {
5688 MockHttpCache cache;
5689
5690 MockHttpRequest request(kSimpleGET_Transaction);
5691
5692 std::vector<std::unique_ptr<Context>> context_list;
5693 const int kNumTransactions = 5;
5694
5695 for (int i = 0; i < kNumTransactions; i++) {
5696 context_list.push_back(std::make_unique<Context>());
5697 Context* c = context_list[i].get();
5698
5699 c->result = cache.CreateTransaction(&c->trans);
5700 ASSERT_THAT(c->result, IsOk());
5701
5702 c->result =
5703 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5704 }
5705
5706 // The first request should be creating the disk cache entry and the others
5707 // should be pending.
5708
5709 EXPECT_EQ(0, cache.network_layer()->transaction_count());
5710 EXPECT_EQ(0, cache.disk_cache()->open_count());
5711 EXPECT_EQ(1, cache.disk_cache()->create_count());
5712
5713 // Cancel a request from the pending queue.
5714 context_list[3].reset();
5715
5716 // Cancel the request that is creating the entry. This will force the pending
5717 // operations to restart.
5718 context_list[0].reset();
5719
5720 // Complete the rest of the transactions.
5721 for (int i = 1; i < kNumTransactions; i++) {
5722 Context* c = context_list[i].get();
5723 if (c) {
5724 c->result = c->callback.GetResult(c->result);
5725 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5726 }
5727 }
5728
5729 // We should have had to re-create the disk entry.
5730
5731 EXPECT_EQ(1, cache.network_layer()->transaction_count());
5732 EXPECT_EQ(0, cache.disk_cache()->open_count());
5733 EXPECT_EQ(2, cache.disk_cache()->create_count());
5734 }
5735
5736 // Tests that we can cancel a single request to open a disk cache entry.
TEST_F(HttpCacheTest,SimpleGET_CancelCreate)5737 TEST_F(HttpCacheTest, SimpleGET_CancelCreate) {
5738 MockHttpCache cache;
5739
5740 MockHttpRequest request(kSimpleGET_Transaction);
5741
5742 auto c = std::make_unique<Context>();
5743
5744 c->result = cache.CreateTransaction(&c->trans);
5745 ASSERT_THAT(c->result, IsOk());
5746
5747 c->result =
5748 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5749 EXPECT_THAT(c->result, IsError(ERR_IO_PENDING));
5750
5751 // Release the reference that the mock disk cache keeps for this entry, so
5752 // that we test that the http cache handles the cancellation correctly.
5753 cache.disk_cache()->ReleaseAll();
5754 c.reset();
5755
5756 base::RunLoop().RunUntilIdle();
5757 EXPECT_EQ(1, cache.disk_cache()->create_count());
5758 }
5759
5760 // Tests that we delete/create entries even if multiple requests are queued.
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_BypassCache)5761 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_BypassCache) {
5762 MockHttpCache cache;
5763
5764 MockHttpRequest request(kSimpleGET_Transaction);
5765 request.load_flags = LOAD_BYPASS_CACHE;
5766
5767 std::vector<std::unique_ptr<Context>> context_list;
5768 const int kNumTransactions = 5;
5769
5770 for (int i = 0; i < kNumTransactions; i++) {
5771 context_list.push_back(std::make_unique<Context>());
5772 Context* c = context_list[i].get();
5773
5774 c->result = cache.CreateTransaction(&c->trans);
5775 ASSERT_THAT(c->result, IsOk());
5776
5777 c->result =
5778 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5779 }
5780
5781 // The first request should be deleting the disk cache entry and the others
5782 // should be pending.
5783
5784 EXPECT_EQ(0, cache.network_layer()->transaction_count());
5785 EXPECT_EQ(0, cache.disk_cache()->open_count());
5786 EXPECT_EQ(0, cache.disk_cache()->create_count());
5787
5788 // Complete the transactions.
5789 for (int i = 0; i < kNumTransactions; i++) {
5790 Context* c = context_list[i].get();
5791 c->result = c->callback.GetResult(c->result);
5792 ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
5793 }
5794
5795 // We should have had to re-create the disk entry multiple times.
5796
5797 EXPECT_EQ(5, cache.network_layer()->transaction_count());
5798 EXPECT_EQ(0, cache.disk_cache()->open_count());
5799 EXPECT_EQ(5, cache.disk_cache()->create_count());
5800 }
5801
5802 // Tests that a (simulated) timeout allows transactions waiting on the cache
5803 // lock to continue.
TEST_F(HttpCacheTest,SimpleGET_WriterTimeout)5804 TEST_F(HttpCacheTest, SimpleGET_WriterTimeout) {
5805 MockHttpCache cache;
5806 cache.SimulateCacheLockTimeout();
5807
5808 MockHttpRequest request(kSimpleGET_Transaction);
5809 Context c1, c2;
5810 ASSERT_THAT(cache.CreateTransaction(&c1.trans), IsOk());
5811 ASSERT_EQ(ERR_IO_PENDING, c1.trans->Start(&request, c1.callback.callback(),
5812 NetLogWithSource()));
5813 ASSERT_THAT(cache.CreateTransaction(&c2.trans), IsOk());
5814 ASSERT_EQ(ERR_IO_PENDING, c2.trans->Start(&request, c2.callback.callback(),
5815 NetLogWithSource()));
5816
5817 // The second request is queued after the first one.
5818
5819 c2.callback.WaitForResult();
5820 ReadAndVerifyTransaction(c2.trans.get(), kSimpleGET_Transaction);
5821
5822 // Complete the first transaction.
5823 c1.callback.WaitForResult();
5824 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
5825 }
5826
5827 // Tests that a (simulated) timeout allows transactions waiting on the cache
5828 // lock to continue but read only transactions to error out.
TEST_F(HttpCacheTest,SimpleGET_WriterTimeoutReadOnlyError)5829 TEST_F(HttpCacheTest, SimpleGET_WriterTimeoutReadOnlyError) {
5830 MockHttpCache cache;
5831
5832 // Simulate timeout.
5833 cache.SimulateCacheLockTimeout();
5834
5835 MockHttpRequest request(kSimpleGET_Transaction);
5836 Context c1, c2;
5837 ASSERT_THAT(cache.CreateTransaction(&c1.trans), IsOk());
5838 ASSERT_EQ(ERR_IO_PENDING, c1.trans->Start(&request, c1.callback.callback(),
5839 NetLogWithSource()));
5840
5841 request.load_flags = LOAD_ONLY_FROM_CACHE;
5842 ASSERT_THAT(cache.CreateTransaction(&c2.trans), IsOk());
5843 ASSERT_EQ(ERR_IO_PENDING, c2.trans->Start(&request, c2.callback.callback(),
5844 NetLogWithSource()));
5845
5846 // The second request is queued after the first one.
5847 int res = c2.callback.WaitForResult();
5848 ASSERT_EQ(ERR_CACHE_MISS, res);
5849
5850 // Complete the first transaction.
5851 c1.callback.WaitForResult();
5852 ReadAndVerifyTransaction(c1.trans.get(), kSimpleGET_Transaction);
5853 }
5854
TEST_F(HttpCacheTest,SimpleGET_AbandonedCacheRead)5855 TEST_F(HttpCacheTest, SimpleGET_AbandonedCacheRead) {
5856 MockHttpCache cache;
5857
5858 // write to the cache
5859 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
5860
5861 MockHttpRequest request(kSimpleGET_Transaction);
5862 TestCompletionCallback callback;
5863
5864 std::unique_ptr<HttpTransaction> trans;
5865 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
5866 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5867 if (rv == ERR_IO_PENDING) {
5868 rv = callback.WaitForResult();
5869 }
5870 ASSERT_THAT(rv, IsOk());
5871
5872 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
5873 rv = trans->Read(buf.get(), 256, callback.callback());
5874 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5875
5876 // Test that destroying the transaction while it is reading from the cache
5877 // works properly.
5878 trans.reset();
5879
5880 // Make sure we pump any pending events, which should include a call to
5881 // HttpCache::Transaction::OnCacheReadCompleted.
5882 base::RunLoop().RunUntilIdle();
5883 }
5884
5885 // Tests that we can delete the HttpCache and deal with queued transactions
5886 // ("waiting for the backend" as opposed to Active or Doomed entries).
TEST_F(HttpCacheTest,SimpleGET_ManyWriters_DeleteCache)5887 TEST_F(HttpCacheTest, SimpleGET_ManyWriters_DeleteCache) {
5888 auto cache = std::make_unique<MockHttpCache>(
5889 std::make_unique<MockBackendNoCbFactory>());
5890
5891 MockHttpRequest request(kSimpleGET_Transaction);
5892
5893 std::vector<std::unique_ptr<Context>> context_list;
5894 const int kNumTransactions = 5;
5895
5896 for (int i = 0; i < kNumTransactions; i++) {
5897 context_list.push_back(std::make_unique<Context>());
5898 Context* c = context_list[i].get();
5899
5900 c->result = cache->CreateTransaction(&c->trans);
5901 ASSERT_THAT(c->result, IsOk());
5902
5903 c->result =
5904 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
5905 }
5906
5907 // The first request should be creating the disk cache entry and the others
5908 // should be pending.
5909
5910 EXPECT_EQ(0, cache->network_layer()->transaction_count());
5911 EXPECT_EQ(0, cache->disk_cache()->open_count());
5912 EXPECT_EQ(0, cache->disk_cache()->create_count());
5913
5914 cache.reset();
5915 }
5916
5917 // Tests that we queue requests when initializing the backend.
TEST_F(HttpCacheTest,SimpleGET_WaitForBackend)5918 TEST_F(HttpCacheTest, SimpleGET_WaitForBackend) {
5919 auto factory = std::make_unique<MockBlockingBackendFactory>();
5920 MockBlockingBackendFactory* factory_ptr = factory.get();
5921 MockHttpCache cache(std::move(factory));
5922
5923 MockHttpRequest request0(kSimpleGET_Transaction);
5924 MockHttpRequest request1(kTypicalGET_Transaction);
5925 MockHttpRequest request2(kETagGET_Transaction);
5926
5927 std::vector<std::unique_ptr<Context>> context_list;
5928 const int kNumTransactions = 3;
5929
5930 for (int i = 0; i < kNumTransactions; i++) {
5931 context_list.push_back(std::make_unique<Context>());
5932 Context* c = context_list[i].get();
5933
5934 c->result = cache.CreateTransaction(&c->trans);
5935 ASSERT_THAT(c->result, IsOk());
5936 }
5937
5938 context_list[0]->result = context_list[0]->trans->Start(
5939 &request0, context_list[0]->callback.callback(), NetLogWithSource());
5940 context_list[1]->result = context_list[1]->trans->Start(
5941 &request1, context_list[1]->callback.callback(), NetLogWithSource());
5942 context_list[2]->result = context_list[2]->trans->Start(
5943 &request2, context_list[2]->callback.callback(), NetLogWithSource());
5944
5945 // Just to make sure that everything is still pending.
5946 base::RunLoop().RunUntilIdle();
5947
5948 // The first request should be creating the disk cache.
5949 EXPECT_FALSE(context_list[0]->callback.have_result());
5950
5951 factory_ptr->FinishCreation();
5952
5953 base::RunLoop().RunUntilIdle();
5954 EXPECT_EQ(3, cache.network_layer()->transaction_count());
5955 EXPECT_EQ(3, cache.disk_cache()->create_count());
5956
5957 for (int i = 0; i < kNumTransactions; ++i) {
5958 EXPECT_TRUE(context_list[i]->callback.have_result());
5959 context_list[i].reset();
5960 }
5961 }
5962
5963 // Tests that we can cancel requests that are queued waiting for the backend
5964 // to be initialized.
TEST_F(HttpCacheTest,SimpleGET_WaitForBackend_CancelCreate)5965 TEST_F(HttpCacheTest, SimpleGET_WaitForBackend_CancelCreate) {
5966 auto factory = std::make_unique<MockBlockingBackendFactory>();
5967 MockBlockingBackendFactory* factory_ptr = factory.get();
5968 MockHttpCache cache(std::move(factory));
5969
5970 MockHttpRequest request0(kSimpleGET_Transaction);
5971 MockHttpRequest request1(kTypicalGET_Transaction);
5972 MockHttpRequest request2(kETagGET_Transaction);
5973
5974 std::vector<std::unique_ptr<Context>> context_list;
5975 const int kNumTransactions = 3;
5976
5977 for (int i = 0; i < kNumTransactions; i++) {
5978 context_list.push_back(std::make_unique<Context>());
5979 Context* c = context_list[i].get();
5980
5981 c->result = cache.CreateTransaction(&c->trans);
5982 ASSERT_THAT(c->result, IsOk());
5983 }
5984
5985 context_list[0]->result = context_list[0]->trans->Start(
5986 &request0, context_list[0]->callback.callback(), NetLogWithSource());
5987 context_list[1]->result = context_list[1]->trans->Start(
5988 &request1, context_list[1]->callback.callback(), NetLogWithSource());
5989 context_list[2]->result = context_list[2]->trans->Start(
5990 &request2, context_list[2]->callback.callback(), NetLogWithSource());
5991
5992 // Just to make sure that everything is still pending.
5993 base::RunLoop().RunUntilIdle();
5994
5995 // The first request should be creating the disk cache.
5996 EXPECT_FALSE(context_list[0]->callback.have_result());
5997
5998 // Cancel a request from the pending queue.
5999 context_list[1].reset();
6000
6001 // Cancel the request that is creating the entry.
6002 context_list[0].reset();
6003
6004 // Complete the last transaction.
6005 factory_ptr->FinishCreation();
6006
6007 context_list[2]->result =
6008 context_list[2]->callback.GetResult(context_list[2]->result);
6009 ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction);
6010
6011 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6012 EXPECT_EQ(1, cache.disk_cache()->create_count());
6013 }
6014
6015 // Tests that we can delete the HttpCache while creating the backend.
TEST_F(HttpCacheTest,DeleteCacheWaitingForBackend)6016 TEST_F(HttpCacheTest, DeleteCacheWaitingForBackend) {
6017 auto factory = std::make_unique<MockBlockingBackendFactory>();
6018 MockBlockingBackendFactory* factory_ptr = factory.get();
6019 auto cache = std::make_unique<MockHttpCache>(std::move(factory));
6020
6021 MockHttpRequest request(kSimpleGET_Transaction);
6022
6023 auto c = std::make_unique<Context>();
6024 c->result = cache->CreateTransaction(&c->trans);
6025 ASSERT_THAT(c->result, IsOk());
6026
6027 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
6028
6029 // Just to make sure that everything is still pending.
6030 base::RunLoop().RunUntilIdle();
6031
6032 // The request should be creating the disk cache.
6033 EXPECT_FALSE(c->callback.have_result());
6034
6035 // Manually arrange for completion to happen after ~HttpCache.
6036 // This can't be done via FinishCreation() since that's in `factory`, and
6037 // that's owned by `cache`.
6038 disk_cache::BackendResultCallback callback = factory_ptr->ReleaseCallback();
6039
6040 cache.reset();
6041 base::RunLoop().RunUntilIdle();
6042
6043 // Simulate the backend completion callback running now the HttpCache is gone.
6044 std::move(callback).Run(disk_cache::BackendResult::MakeError(ERR_ABORTED));
6045 }
6046
6047 // Tests that we can delete the cache while creating the backend, from within
6048 // one of the callbacks.
TEST_F(HttpCacheTest,DeleteCacheWaitingForBackend2)6049 TEST_F(HttpCacheTest, DeleteCacheWaitingForBackend2) {
6050 auto factory = std::make_unique<MockBlockingBackendFactory>();
6051 MockBlockingBackendFactory* factory_ptr = factory.get();
6052 auto cache = std::make_unique<MockHttpCache>(std::move(factory));
6053 auto* cache_ptr = cache.get();
6054
6055 DeleteCacheCompletionCallback cb(std::move(cache));
6056 disk_cache::Backend* backend;
6057 int rv = cache_ptr->http_cache()->GetBackend(&backend, cb.callback());
6058 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6059
6060 // Now let's queue a regular transaction
6061 MockHttpRequest request(kSimpleGET_Transaction);
6062
6063 auto c = std::make_unique<Context>();
6064 c->result = cache_ptr->CreateTransaction(&c->trans);
6065 ASSERT_THAT(c->result, IsOk());
6066
6067 c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
6068
6069 // And another direct backend request.
6070 TestCompletionCallback cb2;
6071 rv = cache_ptr->http_cache()->GetBackend(&backend, cb2.callback());
6072 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6073
6074 // Just to make sure that everything is still pending.
6075 base::RunLoop().RunUntilIdle();
6076
6077 // The request should be queued.
6078 EXPECT_FALSE(c->callback.have_result());
6079
6080 // Generate the callback.
6081 factory_ptr->FinishCreation();
6082 rv = cb.WaitForResult();
6083
6084 // The cache should be gone by now.
6085 base::RunLoop().RunUntilIdle();
6086 EXPECT_THAT(c->callback.GetResult(c->result), IsOk());
6087 EXPECT_FALSE(cb2.have_result());
6088 }
6089
TEST_F(HttpCacheTest,TypicalGET_ConditionalRequest)6090 TEST_F(HttpCacheTest, TypicalGET_ConditionalRequest) {
6091 MockHttpCache cache;
6092
6093 // write to the cache
6094 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
6095
6096 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6097 EXPECT_EQ(0, cache.disk_cache()->open_count());
6098 EXPECT_EQ(1, cache.disk_cache()->create_count());
6099
6100 // Get the same URL again, but this time we expect it to result
6101 // in a conditional request.
6102 LoadTimingInfo load_timing_info;
6103 RunTransactionTestAndGetTiming(cache.http_cache(), kTypicalGET_Transaction,
6104 NetLogWithSource::Make(NetLogSourceType::NONE),
6105 &load_timing_info);
6106
6107 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6108 EXPECT_EQ(1, cache.disk_cache()->open_count());
6109 EXPECT_EQ(1, cache.disk_cache()->create_count());
6110 TestLoadTimingNetworkRequest(load_timing_info);
6111 }
6112
6113 static const auto kETagGetConditionalRequestHandler =
6114 base::BindRepeating([](const HttpRequestInfo* request,
6115 std::string* response_status,
6116 std::string* response_headers,
__anone6acdaec0802(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) 6117 std::string* response_data) {
6118 EXPECT_TRUE(
6119 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6120 response_status->assign("HTTP/1.1 304 Not Modified");
6121 response_headers->assign(kETagGET_Transaction.response_headers);
6122 response_data->clear();
6123 });
6124
TEST_F(HttpCacheTest,ETagGET_ConditionalRequest_304)6125 TEST_F(HttpCacheTest, ETagGET_ConditionalRequest_304) {
6126 MockHttpCache cache;
6127
6128 ScopedMockTransaction transaction(kETagGET_Transaction);
6129
6130 // write to the cache
6131 RunTransactionTest(cache.http_cache(), transaction);
6132
6133 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6134 EXPECT_EQ(0, cache.disk_cache()->open_count());
6135 EXPECT_EQ(1, cache.disk_cache()->create_count());
6136
6137 // Get the same URL again, but this time we expect it to result
6138 // in a conditional request.
6139 transaction.load_flags = LOAD_VALIDATE_CACHE;
6140 transaction.handler = kETagGetConditionalRequestHandler;
6141 LoadTimingInfo load_timing_info;
6142 IPEndPoint remote_endpoint;
6143 RunTransactionTestAndGetTimingAndConnectedSocketAddress(
6144 cache.http_cache(), transaction,
6145 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info,
6146 &remote_endpoint);
6147
6148 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6149 EXPECT_EQ(1, cache.disk_cache()->open_count());
6150 EXPECT_EQ(1, cache.disk_cache()->create_count());
6151 TestLoadTimingNetworkRequest(load_timing_info);
6152
6153 EXPECT_FALSE(remote_endpoint.address().empty());
6154 }
6155
6156 class RevalidationServer {
6157 public:
6158 RevalidationServer() = default;
6159
EtagUsed()6160 bool EtagUsed() { return etag_used_; }
LastModifiedUsed()6161 bool LastModifiedUsed() { return last_modified_used_; }
6162
GetHandlerCallback()6163 MockTransactionHandler GetHandlerCallback() {
6164 return base::BindLambdaForTesting([this](const HttpRequestInfo* request,
6165 std::string* response_status,
6166 std::string* response_headers,
6167 std::string* response_data) {
6168 if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch)) {
6169 etag_used_ = true;
6170 }
6171
6172 if (request->extra_headers.HasHeader(
6173 HttpRequestHeaders::kIfModifiedSince)) {
6174 last_modified_used_ = true;
6175 }
6176
6177 if (etag_used_ || last_modified_used_) {
6178 response_status->assign("HTTP/1.1 304 Not Modified");
6179 response_headers->assign(kTypicalGET_Transaction.response_headers);
6180 response_data->clear();
6181 } else {
6182 response_status->assign(kTypicalGET_Transaction.status);
6183 response_headers->assign(kTypicalGET_Transaction.response_headers);
6184 response_data->assign(kTypicalGET_Transaction.data);
6185 }
6186 });
6187 }
6188
6189 private:
6190 bool etag_used_ = false;
6191 bool last_modified_used_ = false;
6192 };
6193
6194 // Tests revalidation after a vary match.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch)6195 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch) {
6196 MockHttpCache cache;
6197
6198 // Write to the cache.
6199 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6200 transaction.request_headers = "Foo: bar\r\n";
6201 transaction.response_headers =
6202 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6203 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6204 "Etag: \"foopy\"\n"
6205 "Cache-Control: max-age=0\n"
6206 "Vary: Foo\n";
6207 RunTransactionTest(cache.http_cache(), transaction);
6208
6209 // Read from the cache.
6210 RevalidationServer server;
6211 transaction.handler = server.GetHandlerCallback();
6212 LoadTimingInfo load_timing_info;
6213 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6214 NetLogWithSource::Make(NetLogSourceType::NONE),
6215 &load_timing_info);
6216
6217 EXPECT_TRUE(server.EtagUsed());
6218 EXPECT_TRUE(server.LastModifiedUsed());
6219 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6220 EXPECT_EQ(1, cache.disk_cache()->open_count());
6221 EXPECT_EQ(1, cache.disk_cache()->create_count());
6222 TestLoadTimingNetworkRequest(load_timing_info);
6223 }
6224
6225 // Tests revalidation after a vary mismatch if etag is present.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch)6226 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch) {
6227 MockHttpCache cache;
6228
6229 // Write to the cache.
6230 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6231 transaction.request_headers = "Foo: bar\r\n";
6232 transaction.response_headers =
6233 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6234 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6235 "Etag: \"foopy\"\n"
6236 "Cache-Control: max-age=0\n"
6237 "Vary: Foo\n";
6238 RunTransactionTest(cache.http_cache(), transaction);
6239
6240 // Read from the cache and revalidate the entry.
6241 RevalidationServer server;
6242 transaction.handler = server.GetHandlerCallback();
6243 transaction.request_headers = "Foo: none\r\n";
6244 LoadTimingInfo load_timing_info;
6245 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6246 NetLogWithSource::Make(NetLogSourceType::NONE),
6247 &load_timing_info);
6248
6249 EXPECT_TRUE(server.EtagUsed());
6250 EXPECT_FALSE(server.LastModifiedUsed());
6251 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6252 EXPECT_EQ(1, cache.disk_cache()->open_count());
6253 EXPECT_EQ(1, cache.disk_cache()->create_count());
6254 TestLoadTimingNetworkRequest(load_timing_info);
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 ScopedMockTransaction 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 RunTransactionTest(cache.http_cache(), transaction);
6270
6271 // Read from the cache and revalidate the entry.
6272 RevalidationServer server;
6273 transaction.handler = server.GetHandlerCallback();
6274 LoadTimingInfo load_timing_info;
6275 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6276 NetLogWithSource::Make(NetLogSourceType::NONE),
6277 &load_timing_info);
6278
6279 EXPECT_TRUE(server.EtagUsed());
6280 EXPECT_FALSE(server.LastModifiedUsed());
6281 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6282 EXPECT_EQ(1, cache.disk_cache()->open_count());
6283 EXPECT_EQ(1, cache.disk_cache()->create_count());
6284 TestLoadTimingNetworkRequest(load_timing_info);
6285 }
6286
6287 // Tests lack of revalidation after a vary mismatch and no etag.
TEST_F(HttpCacheTest,GET_DontValidateCache_VaryMismatch)6288 TEST_F(HttpCacheTest, GET_DontValidateCache_VaryMismatch) {
6289 MockHttpCache cache;
6290
6291 // Write to the cache.
6292 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6293 transaction.request_headers = "Foo: bar\r\n";
6294 transaction.response_headers =
6295 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
6296 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
6297 "Cache-Control: max-age=0\n"
6298 "Vary: Foo\n";
6299 RunTransactionTest(cache.http_cache(), transaction);
6300
6301 // Read from the cache and don't revalidate the entry.
6302 RevalidationServer server;
6303 transaction.handler = server.GetHandlerCallback();
6304 transaction.request_headers = "Foo: none\r\n";
6305 LoadTimingInfo load_timing_info;
6306 RunTransactionTestAndGetTiming(cache.http_cache(), transaction,
6307 NetLogWithSource::Make(NetLogSourceType::NONE),
6308 &load_timing_info);
6309
6310 EXPECT_FALSE(server.EtagUsed());
6311 EXPECT_FALSE(server.LastModifiedUsed());
6312 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6313 EXPECT_EQ(1, cache.disk_cache()->open_count());
6314 EXPECT_EQ(1, cache.disk_cache()->create_count());
6315 TestLoadTimingNetworkRequest(load_timing_info);
6316 }
6317
6318 // Tests that a new vary header provided when revalidating an entry is saved.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch_UpdateVary)6319 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch_UpdateVary) {
6320 MockHttpCache cache;
6321
6322 // Write to the cache.
6323 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6324 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
6325 transaction.response_headers =
6326 "Etag: \"foopy\"\n"
6327 "Cache-Control: max-age=0\n"
6328 "Vary: Foo\n";
6329 RunTransactionTest(cache.http_cache(), transaction);
6330
6331 // Validate the entry and change the vary field in the response.
6332 transaction.request_headers = "Foo: bar\r\n Name: none\r\n";
6333 transaction.status = "HTTP/1.1 304 Not Modified";
6334 transaction.response_headers =
6335 "Etag: \"foopy\"\n"
6336 "Cache-Control: max-age=3600\n"
6337 "Vary: Name\n";
6338 RunTransactionTest(cache.http_cache(), transaction);
6339
6340 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6341 EXPECT_EQ(1, cache.disk_cache()->open_count());
6342 EXPECT_EQ(1, cache.disk_cache()->create_count());
6343
6344 // Make sure that the ActiveEntry is gone.
6345 base::RunLoop().RunUntilIdle();
6346
6347 // Generate a vary mismatch.
6348 transaction.request_headers = "Foo: bar\r\n Name: bar\r\n";
6349 RunTransactionTest(cache.http_cache(), transaction);
6350
6351 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6352 EXPECT_EQ(2, cache.disk_cache()->open_count());
6353 EXPECT_EQ(1, cache.disk_cache()->create_count());
6354 }
6355
6356 // Tests that new request headers causing a vary mismatch are paired with the
6357 // new response when the server says the old response can be used.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch_UpdateRequestHeader)6358 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch_UpdateRequestHeader) {
6359 MockHttpCache cache;
6360
6361 // Write to the cache.
6362 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6363 transaction.request_headers = "Foo: bar\r\n";
6364 transaction.response_headers =
6365 "Etag: \"foopy\"\n"
6366 "Cache-Control: max-age=3600\n"
6367 "Vary: Foo\n";
6368 RunTransactionTest(cache.http_cache(), transaction);
6369
6370 // Vary-mismatch validation receives 304.
6371 transaction.request_headers = "Foo: none\r\n";
6372 transaction.status = "HTTP/1.1 304 Not Modified";
6373 RunTransactionTest(cache.http_cache(), transaction);
6374
6375 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6376 EXPECT_EQ(1, cache.disk_cache()->open_count());
6377 EXPECT_EQ(1, cache.disk_cache()->create_count());
6378
6379 // Make sure that the ActiveEntry is gone.
6380 base::RunLoop().RunUntilIdle();
6381
6382 // Generate a vary mismatch.
6383 transaction.request_headers = "Foo: bar\r\n";
6384 RunTransactionTest(cache.http_cache(), transaction);
6385
6386 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6387 EXPECT_EQ(2, cache.disk_cache()->open_count());
6388 EXPECT_EQ(1, cache.disk_cache()->create_count());
6389 }
6390
6391 // Tests that a 304 without vary headers doesn't delete the previously stored
6392 // vary data after a vary match revalidation.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMatch_DontDeleteVary)6393 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMatch_DontDeleteVary) {
6394 MockHttpCache cache;
6395
6396 // Write to the cache.
6397 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6398 transaction.request_headers = "Foo: bar\r\n";
6399 transaction.response_headers =
6400 "Etag: \"foopy\"\n"
6401 "Cache-Control: max-age=0\n"
6402 "Vary: Foo\n";
6403 RunTransactionTest(cache.http_cache(), transaction);
6404
6405 // Validate the entry and remove the vary field in the response.
6406 transaction.status = "HTTP/1.1 304 Not Modified";
6407 transaction.response_headers =
6408 "Etag: \"foopy\"\n"
6409 "Cache-Control: max-age=3600\n";
6410 RunTransactionTest(cache.http_cache(), transaction);
6411
6412 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6413 EXPECT_EQ(1, cache.disk_cache()->open_count());
6414 EXPECT_EQ(1, cache.disk_cache()->create_count());
6415
6416 // Make sure that the ActiveEntry is gone.
6417 base::RunLoop().RunUntilIdle();
6418
6419 // Generate a vary mismatch.
6420 transaction.request_headers = "Foo: none\r\n";
6421 RunTransactionTest(cache.http_cache(), transaction);
6422
6423 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6424 EXPECT_EQ(2, cache.disk_cache()->open_count());
6425 EXPECT_EQ(1, cache.disk_cache()->create_count());
6426 }
6427
6428 // Tests that a 304 without vary headers doesn't delete the previously stored
6429 // vary data after a vary mismatch.
TEST_F(HttpCacheTest,GET_ValidateCache_VaryMismatch_DontDeleteVary)6430 TEST_F(HttpCacheTest, GET_ValidateCache_VaryMismatch_DontDeleteVary) {
6431 MockHttpCache cache;
6432
6433 // Write to the cache.
6434 ScopedMockTransaction transaction(kTypicalGET_Transaction);
6435 transaction.request_headers = "Foo: bar\r\n";
6436 transaction.response_headers =
6437 "Etag: \"foopy\"\n"
6438 "Cache-Control: max-age=3600\n"
6439 "Vary: Foo\n";
6440 RunTransactionTest(cache.http_cache(), transaction);
6441
6442 // Vary-mismatch validation receives 304 and no vary header.
6443 transaction.request_headers = "Foo: none\r\n";
6444 transaction.status = "HTTP/1.1 304 Not Modified";
6445 transaction.response_headers =
6446 "Etag: \"foopy\"\n"
6447 "Cache-Control: max-age=3600\n";
6448 RunTransactionTest(cache.http_cache(), transaction);
6449
6450 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6451 EXPECT_EQ(1, cache.disk_cache()->open_count());
6452 EXPECT_EQ(1, cache.disk_cache()->create_count());
6453
6454 // Make sure that the ActiveEntry is gone.
6455 base::RunLoop().RunUntilIdle();
6456
6457 // Generate a vary mismatch.
6458 transaction.request_headers = "Foo: bar\r\n";
6459 RunTransactionTest(cache.http_cache(), transaction);
6460
6461 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6462 EXPECT_EQ(2, cache.disk_cache()->open_count());
6463 EXPECT_EQ(1, cache.disk_cache()->create_count());
6464 }
6465
ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)6466 static void ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo* request,
6467 std::string* response_status,
6468 std::string* response_headers,
6469 std::string* response_data) {
6470 EXPECT_FALSE(
6471 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6472 }
6473
TEST_F(HttpCacheTest,ETagGET_Http10)6474 TEST_F(HttpCacheTest, ETagGET_Http10) {
6475 MockHttpCache cache;
6476
6477 ScopedMockTransaction transaction(kETagGET_Transaction);
6478 transaction.status = "HTTP/1.0 200 OK";
6479
6480 // Write to the cache.
6481 RunTransactionTest(cache.http_cache(), transaction);
6482
6483 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6484 EXPECT_EQ(0, cache.disk_cache()->open_count());
6485 EXPECT_EQ(1, cache.disk_cache()->create_count());
6486
6487 // Get the same URL again, without generating a conditional request.
6488 transaction.load_flags = LOAD_VALIDATE_CACHE;
6489 transaction.handler =
6490 base::BindRepeating(&ETagGet_UnconditionalRequest_Handler);
6491 RunTransactionTest(cache.http_cache(), transaction);
6492
6493 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6494 EXPECT_EQ(1, cache.disk_cache()->open_count());
6495 EXPECT_EQ(1, cache.disk_cache()->create_count());
6496 }
6497
TEST_F(HttpCacheTest,ETagGET_Http10_Range)6498 TEST_F(HttpCacheTest, ETagGET_Http10_Range) {
6499 MockHttpCache cache;
6500
6501 ScopedMockTransaction transaction(kETagGET_Transaction);
6502 transaction.status = "HTTP/1.0 200 OK";
6503
6504 // Write to the cache.
6505 RunTransactionTest(cache.http_cache(), transaction);
6506
6507 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6508 EXPECT_EQ(0, cache.disk_cache()->open_count());
6509 EXPECT_EQ(1, cache.disk_cache()->create_count());
6510
6511 // Get the same URL again, but use a byte range request.
6512 transaction.load_flags = LOAD_VALIDATE_CACHE;
6513 transaction.handler =
6514 base::BindRepeating(&ETagGet_UnconditionalRequest_Handler);
6515 transaction.request_headers = "Range: bytes = 5-\r\n";
6516 RunTransactionTest(cache.http_cache(), transaction);
6517
6518 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6519 EXPECT_EQ(1, cache.disk_cache()->open_count());
6520 EXPECT_EQ(2, cache.disk_cache()->create_count());
6521 }
6522
ETagGet_ConditionalRequest_NoStore_Handler(const HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)6523 static void ETagGet_ConditionalRequest_NoStore_Handler(
6524 const HttpRequestInfo* request,
6525 std::string* response_status,
6526 std::string* response_headers,
6527 std::string* response_data) {
6528 EXPECT_TRUE(
6529 request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch));
6530 response_status->assign("HTTP/1.1 304 Not Modified");
6531 response_headers->assign("Cache-Control: no-store\n");
6532 response_data->clear();
6533 }
6534
TEST_F(HttpCacheTest,ETagGET_ConditionalRequest_304_NoStore)6535 TEST_F(HttpCacheTest, ETagGET_ConditionalRequest_304_NoStore) {
6536 MockHttpCache cache;
6537
6538 ScopedMockTransaction transaction(kETagGET_Transaction);
6539
6540 // Write to the cache.
6541 RunTransactionTest(cache.http_cache(), transaction);
6542
6543 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6544 EXPECT_EQ(0, cache.disk_cache()->open_count());
6545 EXPECT_EQ(1, cache.disk_cache()->create_count());
6546
6547 // Get the same URL again, but this time we expect it to result
6548 // in a conditional request.
6549 transaction.load_flags = LOAD_VALIDATE_CACHE;
6550 transaction.handler =
6551 base::BindRepeating(&ETagGet_ConditionalRequest_NoStore_Handler);
6552 RunTransactionTest(cache.http_cache(), transaction);
6553
6554 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6555 EXPECT_EQ(1, cache.disk_cache()->open_count());
6556 EXPECT_EQ(1, cache.disk_cache()->create_count());
6557
6558 // Reset transaction
6559 transaction.load_flags = kETagGET_Transaction.load_flags;
6560 transaction.handler = kETagGET_Transaction.handler;
6561
6562 // Write to the cache again. This should create a new entry.
6563 RunTransactionTest(cache.http_cache(), transaction);
6564
6565 EXPECT_EQ(3, cache.network_layer()->transaction_count());
6566 EXPECT_EQ(1, cache.disk_cache()->open_count());
6567 EXPECT_EQ(2, cache.disk_cache()->create_count());
6568 }
6569
6570 // Helper that does 4 requests using HttpCache:
6571 //
6572 // (1) loads |kUrl| -- expects |net_response_1| to be returned.
6573 // (2) loads |kUrl| from cache only -- expects |net_response_1| to be returned.
6574 // (3) loads |kUrl| using |extra_request_headers| -- expects |net_response_2| to
6575 // be returned.
6576 // (4) loads |kUrl| from cache only -- expects |cached_response_2| to be
6577 // returned.
6578 // The entry will be created once and will be opened for the 3 subsequent
6579 // requests.
ConditionalizedRequestUpdatesCacheHelper(const Response & net_response_1,const Response & net_response_2,const Response & cached_response_2,const char * extra_request_headers)6580 static void ConditionalizedRequestUpdatesCacheHelper(
6581 const Response& net_response_1,
6582 const Response& net_response_2,
6583 const Response& cached_response_2,
6584 const char* extra_request_headers) {
6585 MockHttpCache cache;
6586
6587 // The URL we will be requesting.
6588 const char kUrl[] = "http://foobar.com/main.css";
6589
6590 // Junk network response.
6591 static const Response kUnexpectedResponse = {"HTTP/1.1 500 Unexpected",
6592 "Server: unexpected_header",
6593 "unexpected body"};
6594
6595 // We will control the network layer's responses for |kUrl| using
6596 // |mock_network_response|.
6597 ScopedMockTransaction mock_network_response(kUrl);
6598
6599 // Request |kUrl| for the first time. It should hit the network and
6600 // receive |kNetResponse1|, which it saves into the HTTP cache.
6601
6602 MockTransaction request = {nullptr};
6603 request.url = kUrl;
6604 request.method = "GET";
6605 request.request_headers = "";
6606
6607 net_response_1.AssignTo(&mock_network_response); // Network mock.
6608 net_response_1.AssignTo(&request); // Expected result.
6609
6610 std::string response_headers;
6611 RunTransactionTestWithResponse(cache.http_cache(), request,
6612 &response_headers);
6613
6614 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
6615 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6616 EXPECT_EQ(0, cache.disk_cache()->open_count());
6617 EXPECT_EQ(1, cache.disk_cache()->create_count());
6618
6619 // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP
6620 // cache, so we don't hit the network.
6621
6622 request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
6623
6624 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
6625 net_response_1.AssignTo(&request); // Expected result.
6626
6627 RunTransactionTestWithResponse(cache.http_cache(), request,
6628 &response_headers);
6629
6630 EXPECT_EQ(net_response_1.status_and_headers(), response_headers);
6631 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6632 EXPECT_EQ(1, cache.disk_cache()->open_count());
6633 EXPECT_EQ(1, cache.disk_cache()->create_count());
6634
6635 // Request |kUrl| yet again, but this time give the request an
6636 // "If-Modified-Since" header. This will cause the request to re-hit the
6637 // network. However now the network response is going to be
6638 // different -- this simulates a change made to the CSS file.
6639
6640 request.request_headers = extra_request_headers;
6641 request.load_flags = LOAD_NORMAL;
6642
6643 net_response_2.AssignTo(&mock_network_response); // Network mock.
6644 net_response_2.AssignTo(&request); // Expected result.
6645
6646 RunTransactionTestWithResponse(cache.http_cache(), request,
6647 &response_headers);
6648
6649 EXPECT_EQ(net_response_2.status_and_headers(), response_headers);
6650 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6651 EXPECT_EQ(1, cache.disk_cache()->open_count());
6652 EXPECT_EQ(1, cache.disk_cache()->create_count());
6653
6654 // Finally, request |kUrl| again. This request should be serviced from
6655 // the cache. Moreover, the value in the cache should be |kNetResponse2|
6656 // and NOT |kNetResponse1|. The previous step should have replaced the
6657 // value in the cache with the modified response.
6658
6659 request.request_headers = "";
6660 request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
6661
6662 kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock.
6663 cached_response_2.AssignTo(&request); // Expected result.
6664
6665 RunTransactionTestWithResponse(cache.http_cache(), request,
6666 &response_headers);
6667
6668 EXPECT_EQ(cached_response_2.status_and_headers(), response_headers);
6669 EXPECT_EQ(2, cache.network_layer()->transaction_count());
6670 EXPECT_EQ(2, cache.disk_cache()->open_count());
6671 EXPECT_EQ(1, cache.disk_cache()->create_count());
6672 }
6673
6674 // Check that when an "if-modified-since" header is attached
6675 // to the request, the result still updates the cached entry.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache1)6676 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache1) {
6677 // First network response for |kUrl|.
6678 static const Response kNetResponse1 = {
6679 "HTTP/1.1 200 OK",
6680 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6681 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6682 "body1"};
6683
6684 // Second network response for |kUrl|.
6685 static const Response kNetResponse2 = {
6686 "HTTP/1.1 200 OK",
6687 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6688 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6689 "body2"};
6690
6691 const char extra_headers[] =
6692 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6693
6694 ConditionalizedRequestUpdatesCacheHelper(kNetResponse1, kNetResponse2,
6695 kNetResponse2, extra_headers);
6696 }
6697
6698 // Check that when an "if-none-match" header is attached
6699 // to the request, the result updates the cached entry.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache2)6700 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache2) {
6701 // First network response for |kUrl|.
6702 static const Response kNetResponse1 = {
6703 "HTTP/1.1 200 OK",
6704 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6705 "Etag: \"ETAG1\"\n"
6706 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
6707 "body1"};
6708
6709 // Second network response for |kUrl|.
6710 static const Response kNetResponse2 = {
6711 "HTTP/1.1 200 OK",
6712 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6713 "Etag: \"ETAG2\"\n"
6714 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n", // Should never expire.
6715 "body2"};
6716
6717 const char extra_headers[] = "If-None-Match: \"ETAG1\"\r\n";
6718
6719 ConditionalizedRequestUpdatesCacheHelper(kNetResponse1, kNetResponse2,
6720 kNetResponse2, extra_headers);
6721 }
6722
6723 // Check that when an "if-modified-since" header is attached
6724 // to a request, the 304 (not modified result) result updates the cached
6725 // headers, and the 304 response is returned rather than the cached response.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache3)6726 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache3) {
6727 // First network response for |kUrl|.
6728 static const Response kNetResponse1 = {
6729 "HTTP/1.1 200 OK",
6730 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6731 "Server: server1\n"
6732 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6733 "body1"};
6734
6735 // Second network response for |kUrl|.
6736 static const Response kNetResponse2 = {
6737 "HTTP/1.1 304 Not Modified",
6738 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6739 "Server: server2\n"
6740 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6741 ""};
6742
6743 static const Response kCachedResponse2 = {
6744 "HTTP/1.1 200 OK",
6745 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6746 "Server: server2\n"
6747 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6748 "body1"};
6749
6750 const char extra_headers[] =
6751 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6752
6753 ConditionalizedRequestUpdatesCacheHelper(kNetResponse1, kNetResponse2,
6754 kCachedResponse2, extra_headers);
6755 }
6756
6757 // Test that when doing an externally conditionalized if-modified-since
6758 // and there is no corresponding cache entry, a new cache entry is NOT
6759 // created (304 response).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache4)6760 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache4) {
6761 MockHttpCache cache;
6762
6763 const char kUrl[] = "http://foobar.com/main.css";
6764
6765 static const Response kNetResponse = {
6766 "HTTP/1.1 304 Not Modified",
6767 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6768 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6769 ""};
6770
6771 const char kExtraRequestHeaders[] =
6772 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6773
6774 // We will control the network layer's responses for |kUrl| using
6775 // |mock_network_response|.
6776 ScopedMockTransaction mock_network_response(kUrl);
6777
6778 MockTransaction request = {nullptr};
6779 request.url = kUrl;
6780 request.method = "GET";
6781 request.request_headers = kExtraRequestHeaders;
6782
6783 kNetResponse.AssignTo(&mock_network_response); // Network mock.
6784 kNetResponse.AssignTo(&request); // Expected result.
6785
6786 std::string response_headers;
6787 RunTransactionTestWithResponse(cache.http_cache(), request,
6788 &response_headers);
6789
6790 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
6791 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6792 EXPECT_EQ(0, cache.disk_cache()->open_count());
6793 EXPECT_EQ(0, cache.disk_cache()->create_count());
6794 }
6795
6796 // Test that when doing an externally conditionalized if-modified-since
6797 // and there is no corresponding cache entry, a new cache entry is NOT
6798 // created (200 response).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache5)6799 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache5) {
6800 MockHttpCache cache;
6801
6802 const char kUrl[] = "http://foobar.com/main.css";
6803
6804 static const Response kNetResponse = {
6805 "HTTP/1.1 200 OK",
6806 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6807 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6808 "foobar!!!"};
6809
6810 const char kExtraRequestHeaders[] =
6811 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
6812
6813 // We will control the network layer's responses for |kUrl| using
6814 // |mock_network_response|.
6815 ScopedMockTransaction mock_network_response(kUrl);
6816
6817 MockTransaction request = {nullptr};
6818 request.url = kUrl;
6819 request.method = "GET";
6820 request.request_headers = kExtraRequestHeaders;
6821
6822 kNetResponse.AssignTo(&mock_network_response); // Network mock.
6823 kNetResponse.AssignTo(&request); // Expected result.
6824
6825 std::string response_headers;
6826 RunTransactionTestWithResponse(cache.http_cache(), request,
6827 &response_headers);
6828
6829 EXPECT_EQ(kNetResponse.status_and_headers(), response_headers);
6830 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6831 EXPECT_EQ(0, cache.disk_cache()->open_count());
6832 EXPECT_EQ(0, cache.disk_cache()->create_count());
6833 }
6834
6835 // Test that when doing an externally conditionalized if-modified-since
6836 // if the date does not match the cache entry's last-modified date,
6837 // then we do NOT use the response (304) to update the cache.
6838 // (the if-modified-since date is 2 days AFTER the cache's modification date).
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache6)6839 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache6) {
6840 static const Response kNetResponse1 = {
6841 "HTTP/1.1 200 OK",
6842 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6843 "Server: server1\n"
6844 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6845 "body1"};
6846
6847 // Second network response for |kUrl|.
6848 static const Response kNetResponse2 = {
6849 "HTTP/1.1 304 Not Modified",
6850 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6851 "Server: server2\n"
6852 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6853 ""};
6854
6855 // This is two days in the future from the original response's last-modified
6856 // date!
6857 const char kExtraRequestHeaders[] =
6858 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n";
6859
6860 ConditionalizedRequestUpdatesCacheHelper(kNetResponse1, kNetResponse2,
6861 kNetResponse1, kExtraRequestHeaders);
6862 }
6863
6864 // Test that when doing an externally conditionalized if-none-match
6865 // if the etag does not match the cache entry's etag, then we do not use the
6866 // response (304) to update the cache.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache7)6867 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache7) {
6868 static const Response kNetResponse1 = {
6869 "HTTP/1.1 200 OK",
6870 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6871 "Etag: \"Foo1\"\n"
6872 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6873 "body1"};
6874
6875 // Second network response for |kUrl|.
6876 static const Response kNetResponse2 = {
6877 "HTTP/1.1 304 Not Modified",
6878 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6879 "Etag: \"Foo2\"\n"
6880 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6881 ""};
6882
6883 // Different etag from original response.
6884 const char kExtraRequestHeaders[] = "If-None-Match: \"Foo2\"\r\n";
6885
6886 ConditionalizedRequestUpdatesCacheHelper(kNetResponse1, kNetResponse2,
6887 kNetResponse1, kExtraRequestHeaders);
6888 }
6889
6890 // Test that doing an externally conditionalized request with both if-none-match
6891 // and if-modified-since updates the cache.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache8)6892 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache8) {
6893 static const Response kNetResponse1 = {
6894 "HTTP/1.1 200 OK",
6895 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6896 "Etag: \"Foo1\"\n"
6897 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6898 "body1"};
6899
6900 // Second network response for |kUrl|.
6901 static const Response kNetResponse2 = {
6902 "HTTP/1.1 200 OK",
6903 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6904 "Etag: \"Foo2\"\n"
6905 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6906 "body2"};
6907
6908 const char kExtraRequestHeaders[] =
6909 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
6910 "If-None-Match: \"Foo1\"\r\n";
6911
6912 ConditionalizedRequestUpdatesCacheHelper(kNetResponse1, kNetResponse2,
6913 kNetResponse2, kExtraRequestHeaders);
6914 }
6915
6916 // Test that doing an externally conditionalized request with both if-none-match
6917 // and if-modified-since does not update the cache with only one match.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache9)6918 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache9) {
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 // Second network response for |kUrl|.
6927 static const Response kNetResponse2 = {
6928 "HTTP/1.1 200 OK",
6929 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6930 "Etag: \"Foo2\"\n"
6931 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6932 "body2"};
6933
6934 // The etag doesn't match what we have stored.
6935 const char kExtraRequestHeaders[] =
6936 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"
6937 "If-None-Match: \"Foo2\"\r\n";
6938
6939 ConditionalizedRequestUpdatesCacheHelper(kNetResponse1, kNetResponse2,
6940 kNetResponse1, kExtraRequestHeaders);
6941 }
6942
6943 // Test that doing an externally conditionalized request with both if-none-match
6944 // and if-modified-since does not update the cache with only one match.
TEST_F(HttpCacheTest,ConditionalizedRequestUpdatesCache10)6945 TEST_F(HttpCacheTest, ConditionalizedRequestUpdatesCache10) {
6946 static const Response kNetResponse1 = {
6947 "HTTP/1.1 200 OK",
6948 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
6949 "Etag: \"Foo1\"\n"
6950 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
6951 "body1"};
6952
6953 // Second network response for |kUrl|.
6954 static const Response kNetResponse2 = {
6955 "HTTP/1.1 200 OK",
6956 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
6957 "Etag: \"Foo2\"\n"
6958 "Last-Modified: Fri, 03 Jul 2009 02:14:27 GMT\n",
6959 "body2"};
6960
6961 // The modification date doesn't match what we have stored.
6962 const char kExtraRequestHeaders[] =
6963 "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n"
6964 "If-None-Match: \"Foo1\"\r\n";
6965
6966 ConditionalizedRequestUpdatesCacheHelper(kNetResponse1, kNetResponse2,
6967 kNetResponse1, kExtraRequestHeaders);
6968 }
6969
TEST_F(HttpCacheTest,UrlContainingHash)6970 TEST_F(HttpCacheTest, UrlContainingHash) {
6971 MockHttpCache cache;
6972
6973 // Do a typical GET request -- should write an entry into our cache.
6974 MockTransaction trans(kTypicalGET_Transaction);
6975 RunTransactionTest(cache.http_cache(), trans);
6976
6977 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6978 EXPECT_EQ(0, cache.disk_cache()->open_count());
6979 EXPECT_EQ(1, cache.disk_cache()->create_count());
6980
6981 // Request the same URL, but this time with a reference section (hash).
6982 // Since the cache key strips the hash sections, this should be a cache hit.
6983 std::string url_with_hash = std::string(trans.url) + "#multiple#hashes";
6984 trans.url = url_with_hash.c_str();
6985 trans.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
6986
6987 RunTransactionTest(cache.http_cache(), trans);
6988
6989 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6990 EXPECT_EQ(1, cache.disk_cache()->open_count());
6991 EXPECT_EQ(1, cache.disk_cache()->create_count());
6992 }
6993
6994 // Tests that we skip the cache for POST requests that do not have an upload
6995 // identifier.
TEST_F(HttpCacheTest,SimplePOST_SkipsCache)6996 TEST_F(HttpCacheTest, SimplePOST_SkipsCache) {
6997 MockHttpCache cache;
6998
6999 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
7000
7001 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7002 EXPECT_EQ(0, cache.disk_cache()->open_count());
7003 EXPECT_EQ(0, cache.disk_cache()->create_count());
7004 }
7005
7006 // Tests POST handling with a disabled cache (no DCHECK).
TEST_F(HttpCacheTest,SimplePOST_DisabledCache)7007 TEST_F(HttpCacheTest, SimplePOST_DisabledCache) {
7008 MockHttpCache cache;
7009 cache.http_cache()->set_mode(HttpCache::Mode::DISABLE);
7010
7011 RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction);
7012
7013 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7014 EXPECT_EQ(0, cache.disk_cache()->open_count());
7015 EXPECT_EQ(0, cache.disk_cache()->create_count());
7016 }
7017
TEST_F(HttpCacheTest,SimplePOST_LoadOnlyFromCache_Miss)7018 TEST_F(HttpCacheTest, SimplePOST_LoadOnlyFromCache_Miss) {
7019 MockHttpCache cache;
7020
7021 MockTransaction transaction(kSimplePOST_Transaction);
7022 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7023
7024 MockHttpRequest request(transaction);
7025 TestCompletionCallback callback;
7026
7027 std::unique_ptr<HttpTransaction> trans;
7028 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
7029 ASSERT_TRUE(trans.get());
7030
7031 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
7032 ASSERT_THAT(callback.GetResult(rv), IsError(ERR_CACHE_MISS));
7033
7034 trans.reset();
7035
7036 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7037 EXPECT_EQ(0, cache.disk_cache()->open_count());
7038 EXPECT_EQ(0, cache.disk_cache()->create_count());
7039 }
7040
TEST_F(HttpCacheTest,SimplePOST_LoadOnlyFromCache_Hit)7041 TEST_F(HttpCacheTest, SimplePOST_LoadOnlyFromCache_Hit) {
7042 MockHttpCache cache;
7043
7044 // Test that we hit the cache for POST requests.
7045
7046 MockTransaction transaction(kSimplePOST_Transaction);
7047
7048 const int64_t kUploadId = 1; // Just a dummy value.
7049
7050 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7051 element_readers.push_back(
7052 std::make_unique<UploadBytesElementReader>("hello", 5));
7053 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
7054 kUploadId);
7055 MockHttpRequest request(transaction);
7056 request.upload_data_stream = &upload_data_stream;
7057
7058 // Populate the cache.
7059 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7060 nullptr);
7061
7062 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7063 EXPECT_EQ(0, cache.disk_cache()->open_count());
7064 EXPECT_EQ(1, cache.disk_cache()->create_count());
7065
7066 // Load from cache.
7067 request.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7068 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7069 nullptr);
7070
7071 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7072 EXPECT_EQ(1, cache.disk_cache()->open_count());
7073 EXPECT_EQ(1, cache.disk_cache()->create_count());
7074 }
7075
7076 // Test that we don't hit the cache for POST requests if there is a byte range.
TEST_F(HttpCacheTest,SimplePOST_WithRanges)7077 TEST_F(HttpCacheTest, SimplePOST_WithRanges) {
7078 MockHttpCache cache;
7079
7080 MockTransaction transaction(kSimplePOST_Transaction);
7081 transaction.request_headers = "Range: bytes = 0-4\r\n";
7082
7083 const int64_t kUploadId = 1; // Just a dummy value.
7084
7085 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7086 element_readers.push_back(
7087 std::make_unique<UploadBytesElementReader>("hello", 5));
7088 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
7089 kUploadId);
7090
7091 MockHttpRequest request(transaction);
7092 request.upload_data_stream = &upload_data_stream;
7093
7094 // Attempt to populate the cache.
7095 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7096 nullptr);
7097
7098 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7099 EXPECT_EQ(0, cache.disk_cache()->open_count());
7100 EXPECT_EQ(0, cache.disk_cache()->create_count());
7101 }
7102
7103 // Tests that a POST is cached separately from a GET.
TEST_F(HttpCacheTest,SimplePOST_SeparateCache)7104 TEST_F(HttpCacheTest, SimplePOST_SeparateCache) {
7105 MockHttpCache cache;
7106
7107 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7108 element_readers.push_back(
7109 std::make_unique<UploadBytesElementReader>("hello", 5));
7110 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7111
7112 MockTransaction transaction(kSimplePOST_Transaction);
7113 MockHttpRequest req1(transaction);
7114 req1.upload_data_stream = &upload_data_stream;
7115
7116 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7117
7118 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7119 EXPECT_EQ(0, cache.disk_cache()->open_count());
7120 EXPECT_EQ(1, cache.disk_cache()->create_count());
7121
7122 transaction.method = "GET";
7123 MockHttpRequest req2(transaction);
7124
7125 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7126
7127 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7128 EXPECT_EQ(0, cache.disk_cache()->open_count());
7129 EXPECT_EQ(2, cache.disk_cache()->create_count());
7130 }
7131
7132 // Tests that a successful POST invalidates a previously cached GET.
TEST_F(HttpCacheTest,SimplePOST_Invalidate_205)7133 TEST_F(HttpCacheTest, SimplePOST_Invalidate_205) {
7134 MockHttpCache cache;
7135
7136 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7137 MockHttpRequest req1(transaction);
7138
7139 // Attempt to populate the cache.
7140 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7141
7142 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7143 EXPECT_EQ(0, cache.disk_cache()->open_count());
7144 EXPECT_EQ(1, cache.disk_cache()->create_count());
7145
7146 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7147 element_readers.push_back(
7148 std::make_unique<UploadBytesElementReader>("hello", 5));
7149 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7150
7151 transaction.method = "POST";
7152 transaction.status = "HTTP/1.1 205 No Content";
7153 MockHttpRequest req2(transaction);
7154 req2.upload_data_stream = &upload_data_stream;
7155
7156 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7157
7158 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7159 EXPECT_EQ(0, cache.disk_cache()->open_count());
7160 EXPECT_EQ(2, cache.disk_cache()->create_count());
7161
7162 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7163
7164 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7165 EXPECT_EQ(0, cache.disk_cache()->open_count());
7166 EXPECT_EQ(3, cache.disk_cache()->create_count());
7167 }
7168
7169 // Tests that a successful POST invalidates a previously cached GET,
7170 // with cache split by top-frame origin.
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SimplePOST_Invalidate_205_SplitCache)7171 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
7172 SimplePOST_Invalidate_205_SplitCache) {
7173 SchemefulSite site_a(GURL("http://a.com"));
7174 SchemefulSite site_b(GURL("http://b.com"));
7175
7176 MockHttpCache cache;
7177
7178 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7179 MockHttpRequest req1(transaction);
7180 req1.network_isolation_key = NetworkIsolationKey(site_a, site_a);
7181 req1.network_anonymization_key =
7182 net::NetworkAnonymizationKey::CreateSameSite(site_a);
7183
7184 // Attempt to populate the cache.
7185 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7186
7187 // Same for a different origin.
7188 MockHttpRequest req1b(transaction);
7189 req1b.network_isolation_key = NetworkIsolationKey(site_b, site_b);
7190 req1b.network_anonymization_key =
7191 net::NetworkAnonymizationKey::CreateSameSite(site_b);
7192 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1b,
7193 nullptr);
7194
7195 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7196 EXPECT_EQ(0, cache.disk_cache()->open_count());
7197 EXPECT_EQ(2, cache.disk_cache()->create_count());
7198
7199 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7200 element_readers.push_back(
7201 std::make_unique<UploadBytesElementReader>("hello", 5));
7202 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7203
7204 transaction.method = "POST";
7205 transaction.status = "HTTP/1.1 205 No Content";
7206 MockHttpRequest req2(transaction);
7207 req2.upload_data_stream = &upload_data_stream;
7208 req2.network_isolation_key = NetworkIsolationKey(site_a, site_a);
7209 req2.network_anonymization_key =
7210 net::NetworkAnonymizationKey::CreateSameSite(site_a);
7211
7212 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7213
7214 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7215 EXPECT_EQ(0, cache.disk_cache()->open_count());
7216 EXPECT_EQ(3, cache.disk_cache()->create_count());
7217
7218 // req1b should still be cached, since it has a different top-level frame
7219 // origin.
7220 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1b,
7221 nullptr);
7222 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7223 EXPECT_EQ(1, cache.disk_cache()->open_count());
7224 EXPECT_EQ(3, cache.disk_cache()->create_count());
7225
7226 // req1 should not be cached after the POST.
7227 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7228 EXPECT_EQ(4, cache.network_layer()->transaction_count());
7229 EXPECT_EQ(1, cache.disk_cache()->open_count());
7230 EXPECT_EQ(4, cache.disk_cache()->create_count());
7231 }
7232
7233 // Tests that a successful POST invalidates a previously cached GET, even when
7234 // there is no upload identifier.
TEST_F(HttpCacheTest,SimplePOST_NoUploadId_Invalidate_205)7235 TEST_F(HttpCacheTest, SimplePOST_NoUploadId_Invalidate_205) {
7236 MockHttpCache cache;
7237
7238 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7239 MockHttpRequest req1(transaction);
7240
7241 // Attempt to populate the cache.
7242 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7243
7244 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7245 EXPECT_EQ(0, cache.disk_cache()->open_count());
7246 EXPECT_EQ(1, cache.disk_cache()->create_count());
7247
7248 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7249 element_readers.push_back(
7250 std::make_unique<UploadBytesElementReader>("hello", 5));
7251 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7252
7253 transaction.method = "POST";
7254 transaction.status = "HTTP/1.1 205 No Content";
7255 MockHttpRequest req2(transaction);
7256 req2.upload_data_stream = &upload_data_stream;
7257
7258 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7259
7260 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7261 EXPECT_EQ(0, cache.disk_cache()->open_count());
7262 EXPECT_EQ(1, cache.disk_cache()->create_count());
7263
7264 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7265
7266 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7267 EXPECT_EQ(0, cache.disk_cache()->open_count());
7268 EXPECT_EQ(2, cache.disk_cache()->create_count());
7269 }
7270
7271 // Tests that processing a POST before creating the backend doesn't crash.
TEST_F(HttpCacheTest,SimplePOST_NoUploadId_NoBackend)7272 TEST_F(HttpCacheTest, SimplePOST_NoUploadId_NoBackend) {
7273 // This will initialize a cache object with NULL backend.
7274 auto factory = std::make_unique<MockBlockingBackendFactory>();
7275 factory->set_fail(true);
7276 factory->FinishCreation();
7277 MockHttpCache cache(std::move(factory));
7278
7279 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7280 element_readers.push_back(
7281 std::make_unique<UploadBytesElementReader>("hello", 5));
7282 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7283
7284 ScopedMockTransaction transaction(kSimplePOST_Transaction);
7285 MockHttpRequest req(transaction);
7286 req.upload_data_stream = &upload_data_stream;
7287
7288 RunTransactionTestWithRequest(cache.http_cache(), transaction, req, nullptr);
7289 }
7290
7291 // Tests that we don't invalidate entries as a result of a failed POST.
TEST_F(HttpCacheTest,SimplePOST_DontInvalidate_100)7292 TEST_F(HttpCacheTest, SimplePOST_DontInvalidate_100) {
7293 MockHttpCache cache;
7294
7295 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7296 MockHttpRequest req1(transaction);
7297
7298 // Attempt to populate the cache.
7299 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7300
7301 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7302 EXPECT_EQ(0, cache.disk_cache()->open_count());
7303 EXPECT_EQ(1, cache.disk_cache()->create_count());
7304
7305 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7306 element_readers.push_back(
7307 std::make_unique<UploadBytesElementReader>("hello", 5));
7308 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 1);
7309
7310 transaction.method = "POST";
7311 transaction.status = "HTTP/1.1 100 Continue";
7312 MockHttpRequest req2(transaction);
7313 req2.upload_data_stream = &upload_data_stream;
7314
7315 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7316
7317 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7318 EXPECT_EQ(0, cache.disk_cache()->open_count());
7319 EXPECT_EQ(2, cache.disk_cache()->create_count());
7320
7321 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7322
7323 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7324 EXPECT_EQ(1, cache.disk_cache()->open_count());
7325 EXPECT_EQ(2, cache.disk_cache()->create_count());
7326 }
7327
7328 // Tests that a HEAD request is not cached by itself.
TEST_F(HttpCacheTest,SimpleHEAD_LoadOnlyFromCache_Miss)7329 TEST_F(HttpCacheTest, SimpleHEAD_LoadOnlyFromCache_Miss) {
7330 MockHttpCache cache;
7331 ScopedMockTransaction transaction(kSimplePOST_Transaction);
7332 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7333 transaction.method = "HEAD";
7334
7335 MockHttpRequest request(transaction);
7336 TestCompletionCallback callback;
7337
7338 std::unique_ptr<HttpTransaction> trans;
7339 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
7340 ASSERT_TRUE(trans.get());
7341
7342 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
7343 ASSERT_THAT(callback.GetResult(rv), IsError(ERR_CACHE_MISS));
7344
7345 trans.reset();
7346
7347 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7348 EXPECT_EQ(0, cache.disk_cache()->open_count());
7349 EXPECT_EQ(0, cache.disk_cache()->create_count());
7350 }
7351
7352 // Tests that a HEAD request is served from a cached GET.
TEST_F(HttpCacheTest,SimpleHEAD_LoadOnlyFromCache_Hit)7353 TEST_F(HttpCacheTest, SimpleHEAD_LoadOnlyFromCache_Hit) {
7354 MockHttpCache cache;
7355 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7356
7357 // Populate the cache.
7358 RunTransactionTest(cache.http_cache(), transaction);
7359
7360 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7361 EXPECT_EQ(0, cache.disk_cache()->open_count());
7362 EXPECT_EQ(1, cache.disk_cache()->create_count());
7363
7364 // Load from cache.
7365 transaction.method = "HEAD";
7366 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7367 transaction.data = "";
7368 RunTransactionTest(cache.http_cache(), transaction);
7369
7370 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7371 EXPECT_EQ(1, cache.disk_cache()->open_count());
7372 EXPECT_EQ(1, cache.disk_cache()->create_count());
7373 }
7374
7375 // Tests that a read-only request served from the cache preserves CL.
TEST_F(HttpCacheTest,SimpleHEAD_ContentLengthOnHit_Read)7376 TEST_F(HttpCacheTest, SimpleHEAD_ContentLengthOnHit_Read) {
7377 MockHttpCache cache;
7378 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7379 transaction.response_headers = "Content-Length: 42\n";
7380
7381 // Populate the cache.
7382 RunTransactionTest(cache.http_cache(), transaction);
7383
7384 // Load from cache.
7385 transaction.method = "HEAD";
7386 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7387 transaction.data = "";
7388 std::string headers;
7389
7390 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7391
7392 EXPECT_EQ("HTTP/1.1 200 OK\nContent-Length: 42\n", headers);
7393 }
7394
7395 // Tests that a read-write request served from the cache preserves CL.
TEST_F(HttpCacheTest,ETagHEAD_ContentLengthOnHit_ReadWrite)7396 TEST_F(HttpCacheTest, ETagHEAD_ContentLengthOnHit_ReadWrite) {
7397 MockHttpCache cache;
7398 ScopedMockTransaction transaction(kETagGET_Transaction);
7399 std::string server_headers(kETagGET_Transaction.response_headers);
7400 server_headers.append("Content-Length: 42\n");
7401 transaction.response_headers = server_headers.data();
7402
7403 // Populate the cache.
7404 RunTransactionTest(cache.http_cache(), transaction);
7405
7406 // Load from cache.
7407 transaction.method = "HEAD";
7408 transaction.data = "";
7409 std::string headers;
7410
7411 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7412
7413 EXPECT_NE(std::string::npos, headers.find("Content-Length: 42\n"));
7414 }
7415
7416 // Tests that a HEAD request that includes byte ranges bypasses the cache.
TEST_F(HttpCacheTest,SimpleHEAD_WithRanges)7417 TEST_F(HttpCacheTest, SimpleHEAD_WithRanges) {
7418 MockHttpCache cache;
7419 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7420
7421 // Populate the cache.
7422 RunTransactionTest(cache.http_cache(), transaction);
7423
7424 // Load from cache.
7425 transaction.method = "HEAD";
7426 transaction.request_headers = "Range: bytes = 0-4\r\n";
7427 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7428 transaction.start_return_code = ERR_CACHE_MISS;
7429 RunTransactionTest(cache.http_cache(), transaction);
7430
7431 EXPECT_EQ(0, cache.disk_cache()->open_count());
7432 EXPECT_EQ(1, cache.disk_cache()->create_count());
7433 }
7434
7435 // Tests that a HEAD request can be served from a partially cached resource.
TEST_F(HttpCacheTest,SimpleHEAD_WithCachedRanges)7436 TEST_F(HttpCacheTest, SimpleHEAD_WithCachedRanges) {
7437 MockHttpCache cache;
7438 {
7439 ScopedMockTransaction scoped_mock_transaction(kRangeGET_TransactionOK);
7440 // Write to the cache (40-49).
7441 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
7442 }
7443
7444 ScopedMockTransaction transaction(kSimpleGET_Transaction,
7445 kRangeGET_TransactionOK.url);
7446 transaction.method = "HEAD";
7447 transaction.data = "";
7448 std::string headers;
7449
7450 // Load from cache.
7451 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7452
7453 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7454 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
7455 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
7456 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7457 EXPECT_EQ(1, cache.disk_cache()->open_count());
7458 EXPECT_EQ(1, cache.disk_cache()->create_count());
7459 }
7460
7461 // Tests that a HEAD request can be served from a truncated resource.
TEST_F(HttpCacheTest,SimpleHEAD_WithTruncatedEntry)7462 TEST_F(HttpCacheTest, SimpleHEAD_WithTruncatedEntry) {
7463 MockHttpCache cache;
7464 {
7465 ScopedMockTransaction scoped_mock_transaction(kRangeGET_TransactionOK);
7466 std::string raw_headers(
7467 "HTTP/1.1 200 OK\n"
7468 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7469 "ETag: \"foo\"\n"
7470 "Accept-Ranges: bytes\n"
7471 "Content-Length: 80\n");
7472 CreateTruncatedEntry(raw_headers, &cache);
7473 }
7474
7475 ScopedMockTransaction transaction(kSimpleGET_Transaction,
7476 kRangeGET_TransactionOK.url);
7477 transaction.method = "HEAD";
7478 transaction.data = "";
7479 std::string headers;
7480
7481 // Load from cache.
7482 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7483
7484 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7485 EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
7486 EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
7487 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7488 EXPECT_EQ(1, cache.disk_cache()->open_count());
7489 EXPECT_EQ(1, cache.disk_cache()->create_count());
7490 }
7491
7492 // Tests that a HEAD request updates the cached response.
TEST_F(HttpCacheTest,TypicalHEAD_UpdatesResponse)7493 TEST_F(HttpCacheTest, TypicalHEAD_UpdatesResponse) {
7494 MockHttpCache cache;
7495 std::string headers;
7496 {
7497 ScopedMockTransaction transaction(kTypicalGET_Transaction);
7498
7499 // Populate the cache.
7500 RunTransactionTest(cache.http_cache(), transaction);
7501
7502 // Update the cache.
7503 transaction.method = "HEAD";
7504 transaction.response_headers = "Foo: bar\n";
7505 transaction.data = "";
7506 transaction.status = "HTTP/1.1 304 Not Modified\n";
7507 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7508 }
7509
7510 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
7511 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7512
7513 ScopedMockTransaction transaction2(kTypicalGET_Transaction);
7514
7515 // Make sure we are done with the previous transaction.
7516 base::RunLoop().RunUntilIdle();
7517
7518 // Load from the cache.
7519 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7520 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
7521
7522 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
7523 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7524 EXPECT_EQ(2, cache.disk_cache()->open_count());
7525 EXPECT_EQ(1, cache.disk_cache()->create_count());
7526 }
7527
7528 // Tests that an externally conditionalized HEAD request updates the cache.
TEST_F(HttpCacheTest,TypicalHEAD_ConditionalizedRequestUpdatesResponse)7529 TEST_F(HttpCacheTest, TypicalHEAD_ConditionalizedRequestUpdatesResponse) {
7530 MockHttpCache cache;
7531 std::string headers;
7532
7533 {
7534 ScopedMockTransaction transaction(kTypicalGET_Transaction);
7535
7536 // Populate the cache.
7537 RunTransactionTest(cache.http_cache(), transaction);
7538
7539 // Update the cache.
7540 transaction.method = "HEAD";
7541 transaction.request_headers =
7542 "If-Modified-Since: Wed, 28 Nov 2007 00:40:09 GMT\r\n";
7543 transaction.response_headers = "Foo: bar\n";
7544 transaction.data = "";
7545 transaction.status = "HTTP/1.1 304 Not Modified\n";
7546 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
7547
7548 EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 304 Not Modified\n"));
7549 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7550
7551 // Make sure we are done with the previous transaction.
7552 base::RunLoop().RunUntilIdle();
7553 }
7554 {
7555 ScopedMockTransaction transaction2(kTypicalGET_Transaction);
7556
7557 // Load from the cache.
7558 transaction2.load_flags |=
7559 LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7560 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
7561
7562 EXPECT_NE(std::string::npos, headers.find("Foo: bar\n"));
7563 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7564 EXPECT_EQ(2, cache.disk_cache()->open_count());
7565 EXPECT_EQ(1, cache.disk_cache()->create_count());
7566 }
7567 }
7568
7569 // Tests that a HEAD request invalidates an old cached entry.
TEST_F(HttpCacheTest,SimpleHEAD_InvalidatesEntry)7570 TEST_F(HttpCacheTest, SimpleHEAD_InvalidatesEntry) {
7571 MockHttpCache cache;
7572 ScopedMockTransaction transaction(kTypicalGET_Transaction);
7573
7574 // Populate the cache.
7575 RunTransactionTest(cache.http_cache(), transaction);
7576
7577 // Update the cache.
7578 transaction.method = "HEAD";
7579 transaction.data = "";
7580 RunTransactionTest(cache.http_cache(), transaction);
7581 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7582
7583 // Load from the cache.
7584 transaction.method = "GET";
7585 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7586 transaction.start_return_code = ERR_CACHE_MISS;
7587 RunTransactionTest(cache.http_cache(), transaction);
7588 }
7589
7590 // Tests that we do not cache the response of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Miss)7591 TEST_F(HttpCacheTest, SimplePUT_Miss) {
7592 MockHttpCache cache;
7593
7594 MockTransaction transaction(kSimplePOST_Transaction);
7595 transaction.method = "PUT";
7596
7597 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7598 element_readers.push_back(
7599 std::make_unique<UploadBytesElementReader>("hello", 5));
7600 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7601
7602 MockHttpRequest request(transaction);
7603 request.upload_data_stream = &upload_data_stream;
7604
7605 // Attempt to populate the cache.
7606 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7607 nullptr);
7608
7609 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7610 EXPECT_EQ(0, cache.disk_cache()->open_count());
7611 EXPECT_EQ(0, cache.disk_cache()->create_count());
7612 }
7613
7614 // Tests that we invalidate entries as a result of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Invalidate)7615 TEST_F(HttpCacheTest, SimplePUT_Invalidate) {
7616 MockHttpCache cache;
7617
7618 MockTransaction transaction(kSimpleGET_Transaction);
7619 MockHttpRequest req1(transaction);
7620
7621 // Attempt to populate the cache.
7622 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7623
7624 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7625 EXPECT_EQ(0, cache.disk_cache()->open_count());
7626 EXPECT_EQ(1, cache.disk_cache()->create_count());
7627
7628 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7629 element_readers.push_back(
7630 std::make_unique<UploadBytesElementReader>("hello", 5));
7631 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7632
7633 transaction.method = "PUT";
7634 MockHttpRequest req2(transaction);
7635 req2.upload_data_stream = &upload_data_stream;
7636
7637 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7638
7639 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7640 EXPECT_EQ(1, cache.disk_cache()->open_count());
7641 EXPECT_EQ(1, cache.disk_cache()->create_count());
7642
7643 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7644
7645 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7646 EXPECT_EQ(1, cache.disk_cache()->open_count());
7647 EXPECT_EQ(2, cache.disk_cache()->create_count());
7648 }
7649
7650 // Tests that we invalidate entries as a result of a PUT.
TEST_F(HttpCacheTest,SimplePUT_Invalidate_305)7651 TEST_F(HttpCacheTest, SimplePUT_Invalidate_305) {
7652 MockHttpCache cache;
7653
7654 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7655 MockHttpRequest req1(transaction);
7656
7657 // Attempt to populate the cache.
7658 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7659
7660 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7661 EXPECT_EQ(0, cache.disk_cache()->open_count());
7662 EXPECT_EQ(1, cache.disk_cache()->create_count());
7663
7664 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7665 element_readers.push_back(
7666 std::make_unique<UploadBytesElementReader>("hello", 5));
7667 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7668
7669 transaction.method = "PUT";
7670 transaction.status = "HTTP/1.1 305 Use Proxy";
7671 MockHttpRequest req2(transaction);
7672 req2.upload_data_stream = &upload_data_stream;
7673
7674 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7675
7676 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7677 EXPECT_EQ(1, cache.disk_cache()->open_count());
7678 EXPECT_EQ(1, cache.disk_cache()->create_count());
7679
7680 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7681
7682 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7683 EXPECT_EQ(1, cache.disk_cache()->open_count());
7684 EXPECT_EQ(2, cache.disk_cache()->create_count());
7685 }
7686
7687 // Tests that we don't invalidate entries as a result of a failed PUT.
TEST_F(HttpCacheTest,SimplePUT_DontInvalidate_404)7688 TEST_F(HttpCacheTest, SimplePUT_DontInvalidate_404) {
7689 MockHttpCache cache;
7690
7691 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7692 MockHttpRequest req1(transaction);
7693
7694 // Attempt to populate the cache.
7695 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7696
7697 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7698 EXPECT_EQ(0, cache.disk_cache()->open_count());
7699 EXPECT_EQ(1, cache.disk_cache()->create_count());
7700
7701 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7702 element_readers.push_back(
7703 std::make_unique<UploadBytesElementReader>("hello", 5));
7704 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7705
7706 transaction.method = "PUT";
7707 transaction.status = "HTTP/1.1 404 Not Found";
7708 MockHttpRequest req2(transaction);
7709 req2.upload_data_stream = &upload_data_stream;
7710
7711 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7712
7713 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7714 EXPECT_EQ(1, cache.disk_cache()->open_count());
7715 EXPECT_EQ(1, cache.disk_cache()->create_count());
7716
7717 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7718
7719 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7720 EXPECT_EQ(2, cache.disk_cache()->open_count());
7721 EXPECT_EQ(1, cache.disk_cache()->create_count());
7722 }
7723
7724 // Tests that we do not cache the response of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Miss)7725 TEST_F(HttpCacheTest, SimpleDELETE_Miss) {
7726 MockHttpCache cache;
7727
7728 MockTransaction transaction(kSimplePOST_Transaction);
7729 transaction.method = "DELETE";
7730
7731 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7732 element_readers.push_back(
7733 std::make_unique<UploadBytesElementReader>("hello", 5));
7734 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7735
7736 MockHttpRequest request(transaction);
7737 request.upload_data_stream = &upload_data_stream;
7738
7739 // Attempt to populate the cache.
7740 RunTransactionTestWithRequest(cache.http_cache(), transaction, request,
7741 nullptr);
7742
7743 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7744 EXPECT_EQ(0, cache.disk_cache()->open_count());
7745 EXPECT_EQ(0, cache.disk_cache()->create_count());
7746 }
7747
7748 // Tests that we invalidate entries as a result of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Invalidate)7749 TEST_F(HttpCacheTest, SimpleDELETE_Invalidate) {
7750 MockHttpCache cache;
7751
7752 MockTransaction transaction(kSimpleGET_Transaction);
7753 MockHttpRequest req1(transaction);
7754
7755 // Attempt to populate the cache.
7756 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7757
7758 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7759 EXPECT_EQ(0, cache.disk_cache()->open_count());
7760 EXPECT_EQ(1, cache.disk_cache()->create_count());
7761
7762 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7763 element_readers.push_back(
7764 std::make_unique<UploadBytesElementReader>("hello", 5));
7765 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7766
7767 transaction.method = "DELETE";
7768 MockHttpRequest req2(transaction);
7769 req2.upload_data_stream = &upload_data_stream;
7770
7771 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
7772
7773 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7774 EXPECT_EQ(1, cache.disk_cache()->open_count());
7775 EXPECT_EQ(1, cache.disk_cache()->create_count());
7776
7777 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7778
7779 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7780 EXPECT_EQ(1, cache.disk_cache()->open_count());
7781 EXPECT_EQ(2, cache.disk_cache()->create_count());
7782 }
7783
7784 // Tests that we invalidate entries as a result of a DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_Invalidate_301)7785 TEST_F(HttpCacheTest, SimpleDELETE_Invalidate_301) {
7786 MockHttpCache cache;
7787
7788 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7789
7790 // Attempt to populate the cache.
7791 RunTransactionTest(cache.http_cache(), transaction);
7792
7793 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7794 EXPECT_EQ(0, cache.disk_cache()->open_count());
7795 EXPECT_EQ(1, cache.disk_cache()->create_count());
7796
7797 transaction.method = "DELETE";
7798 transaction.status = "HTTP/1.1 301 Moved Permanently ";
7799
7800 RunTransactionTest(cache.http_cache(), transaction);
7801
7802 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7803 EXPECT_EQ(1, cache.disk_cache()->open_count());
7804 EXPECT_EQ(1, cache.disk_cache()->create_count());
7805
7806 transaction.method = "GET";
7807 RunTransactionTest(cache.http_cache(), transaction);
7808
7809 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7810 EXPECT_EQ(1, cache.disk_cache()->open_count());
7811 EXPECT_EQ(2, cache.disk_cache()->create_count());
7812 }
7813
7814 // Tests that we don't invalidate entries as a result of a failed DELETE.
TEST_F(HttpCacheTest,SimpleDELETE_DontInvalidate_416)7815 TEST_F(HttpCacheTest, SimpleDELETE_DontInvalidate_416) {
7816 MockHttpCache cache;
7817
7818 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7819
7820 // Attempt to populate the cache.
7821 RunTransactionTest(cache.http_cache(), transaction);
7822
7823 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7824 EXPECT_EQ(0, cache.disk_cache()->open_count());
7825 EXPECT_EQ(1, cache.disk_cache()->create_count());
7826
7827 transaction.method = "DELETE";
7828 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
7829
7830 RunTransactionTest(cache.http_cache(), transaction);
7831
7832 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7833 EXPECT_EQ(1, cache.disk_cache()->open_count());
7834 EXPECT_EQ(1, cache.disk_cache()->create_count());
7835
7836 transaction.method = "GET";
7837 transaction.status = "HTTP/1.1 200 OK";
7838 RunTransactionTest(cache.http_cache(), transaction);
7839
7840 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7841 EXPECT_EQ(2, cache.disk_cache()->open_count());
7842 EXPECT_EQ(1, cache.disk_cache()->create_count());
7843 }
7844
7845 // Tests that we invalidate entries as a result of a PATCH.
TEST_F(HttpCacheTest,SimplePATCH_Invalidate)7846 TEST_F(HttpCacheTest, SimplePATCH_Invalidate) {
7847 MockHttpCache cache;
7848
7849 MockTransaction transaction(kSimpleGET_Transaction);
7850 MockHttpRequest req1(transaction);
7851
7852 // Attempt to populate the cache.
7853 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7854
7855 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7856 EXPECT_EQ(0, cache.disk_cache()->open_count());
7857 EXPECT_EQ(1, cache.disk_cache()->create_count());
7858
7859 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
7860 element_readers.push_back(
7861 std::make_unique<UploadBytesElementReader>("hello", 5));
7862 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
7863
7864 transaction.method = "PATCH";
7865 MockHttpRequest req2(transaction);
7866 req2.upload_data_stream = &upload_data_stream;
7867
7868 RunTransactionTestWithRequest(cache.http_cache(), transaction, req2, nullptr);
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 RunTransactionTestWithRequest(cache.http_cache(), transaction, req1, nullptr);
7875
7876 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7877 EXPECT_EQ(1, cache.disk_cache()->open_count());
7878 EXPECT_EQ(2, cache.disk_cache()->create_count());
7879 }
7880
7881 // Tests that we invalidate entries as a result of a PATCH.
TEST_F(HttpCacheTest,SimplePATCH_Invalidate_301)7882 TEST_F(HttpCacheTest, SimplePATCH_Invalidate_301) {
7883 MockHttpCache cache;
7884
7885 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7886
7887 // Attempt to populate the cache.
7888 RunTransactionTest(cache.http_cache(), transaction);
7889
7890 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7891 EXPECT_EQ(0, cache.disk_cache()->open_count());
7892 EXPECT_EQ(1, cache.disk_cache()->create_count());
7893
7894 transaction.method = "PATCH";
7895 transaction.status = "HTTP/1.1 301 Moved Permanently ";
7896
7897 RunTransactionTest(cache.http_cache(), transaction);
7898
7899 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7900 EXPECT_EQ(1, cache.disk_cache()->open_count());
7901 EXPECT_EQ(1, cache.disk_cache()->create_count());
7902
7903 transaction.method = "GET";
7904 RunTransactionTest(cache.http_cache(), transaction);
7905
7906 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7907 EXPECT_EQ(1, cache.disk_cache()->open_count());
7908 EXPECT_EQ(2, cache.disk_cache()->create_count());
7909 }
7910
7911 // Tests that we don't invalidate entries as a result of a failed PATCH.
TEST_F(HttpCacheTest,SimplePATCH_DontInvalidate_416)7912 TEST_F(HttpCacheTest, SimplePATCH_DontInvalidate_416) {
7913 MockHttpCache cache;
7914
7915 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7916
7917 // Attempt to populate the cache.
7918 RunTransactionTest(cache.http_cache(), transaction);
7919
7920 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7921 EXPECT_EQ(0, cache.disk_cache()->open_count());
7922 EXPECT_EQ(1, cache.disk_cache()->create_count());
7923
7924 transaction.method = "PATCH";
7925 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
7926
7927 RunTransactionTest(cache.http_cache(), transaction);
7928
7929 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7930 EXPECT_EQ(1, cache.disk_cache()->open_count());
7931 EXPECT_EQ(1, cache.disk_cache()->create_count());
7932
7933 transaction.method = "GET";
7934 transaction.status = "HTTP/1.1 200 OK";
7935 RunTransactionTest(cache.http_cache(), transaction);
7936
7937 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7938 EXPECT_EQ(2, cache.disk_cache()->open_count());
7939 EXPECT_EQ(1, cache.disk_cache()->create_count());
7940 }
7941
7942 // Tests that we don't invalidate entries after a failed network transaction.
TEST_F(HttpCacheTest,SimpleGET_DontInvalidateOnFailure)7943 TEST_F(HttpCacheTest, SimpleGET_DontInvalidateOnFailure) {
7944 MockHttpCache cache;
7945
7946 // Populate the cache.
7947 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
7948 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7949
7950 // Fail the network request.
7951 ScopedMockTransaction transaction(kSimpleGET_Transaction);
7952 transaction.start_return_code = ERR_FAILED;
7953 transaction.load_flags |= LOAD_VALIDATE_CACHE;
7954
7955 RunTransactionTest(cache.http_cache(), transaction);
7956 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7957
7958 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
7959 transaction.start_return_code = OK;
7960 RunTransactionTest(cache.http_cache(), transaction);
7961
7962 // Make sure the transaction didn't reach the network.
7963 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7964 }
7965
TEST_F(HttpCacheTest,RangeGET_SkipsCache)7966 TEST_F(HttpCacheTest, RangeGET_SkipsCache) {
7967 MockHttpCache cache;
7968
7969 // Test that we skip the cache for range GET requests. Eventually, we will
7970 // want to cache these, but we'll still have cases where skipping the cache
7971 // makes sense, so we want to make sure that it works properly.
7972
7973 RunTransactionTest(cache.http_cache(), kRangeGET_Transaction);
7974
7975 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7976 EXPECT_EQ(0, cache.disk_cache()->open_count());
7977 EXPECT_EQ(0, cache.disk_cache()->create_count());
7978
7979 MockTransaction transaction(kSimpleGET_Transaction);
7980 transaction.request_headers = "If-None-Match: foo\r\n";
7981 RunTransactionTest(cache.http_cache(), transaction);
7982
7983 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7984 EXPECT_EQ(0, cache.disk_cache()->open_count());
7985 EXPECT_EQ(0, cache.disk_cache()->create_count());
7986
7987 transaction.request_headers =
7988 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n";
7989 RunTransactionTest(cache.http_cache(), transaction);
7990
7991 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7992 EXPECT_EQ(0, cache.disk_cache()->open_count());
7993 EXPECT_EQ(0, cache.disk_cache()->create_count());
7994 }
7995
7996 // Test that we skip the cache for range requests that include a validation
7997 // header.
TEST_F(HttpCacheTest,RangeGET_SkipsCache2)7998 TEST_F(HttpCacheTest, RangeGET_SkipsCache2) {
7999 MockHttpCache cache;
8000
8001 MockTransaction transaction(kRangeGET_Transaction);
8002 transaction.request_headers =
8003 "If-None-Match: foo\r\n" EXTRA_HEADER "Range: bytes = 40-49\r\n";
8004 RunTransactionTest(cache.http_cache(), transaction);
8005
8006 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8007 EXPECT_EQ(0, cache.disk_cache()->open_count());
8008 EXPECT_EQ(0, cache.disk_cache()->create_count());
8009
8010 transaction.request_headers =
8011 "If-Modified-Since: Wed, 28 Nov 2007 00:45:20 GMT\r\n" EXTRA_HEADER
8012 "Range: bytes = 40-49\r\n";
8013 RunTransactionTest(cache.http_cache(), transaction);
8014
8015 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8016 EXPECT_EQ(0, cache.disk_cache()->open_count());
8017 EXPECT_EQ(0, cache.disk_cache()->create_count());
8018
8019 transaction.request_headers =
8020 "If-Range: bla\r\n" EXTRA_HEADER "Range: bytes = 40-49\r\n";
8021 RunTransactionTest(cache.http_cache(), transaction);
8022
8023 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8024 EXPECT_EQ(0, cache.disk_cache()->open_count());
8025 EXPECT_EQ(0, cache.disk_cache()->create_count());
8026 }
8027
TEST_F(HttpCacheTest,SimpleGET_DoesntLogHeaders)8028 TEST_F(HttpCacheTest, SimpleGET_DoesntLogHeaders) {
8029 MockHttpCache cache;
8030
8031 RecordingNetLogObserver net_log_observer;
8032 RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction,
8033 NetLogWithSource::Make(NetLogSourceType::NONE));
8034
8035 EXPECT_FALSE(LogContainsEventType(
8036 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8037 }
8038
TEST_F(HttpCacheTest,RangeGET_LogsHeaders)8039 TEST_F(HttpCacheTest, RangeGET_LogsHeaders) {
8040 MockHttpCache cache;
8041
8042 RecordingNetLogObserver net_log_observer;
8043 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_Transaction,
8044 NetLogWithSource::Make(NetLogSourceType::NONE));
8045
8046 EXPECT_TRUE(LogContainsEventType(
8047 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8048 }
8049
TEST_F(HttpCacheTest,ExternalValidation_LogsHeaders)8050 TEST_F(HttpCacheTest, ExternalValidation_LogsHeaders) {
8051 MockHttpCache cache;
8052
8053 RecordingNetLogObserver net_log_observer;
8054 MockTransaction transaction(kSimpleGET_Transaction);
8055 transaction.request_headers = "If-None-Match: foo\r\n" EXTRA_HEADER;
8056 RunTransactionTestWithLog(cache.http_cache(), transaction,
8057 NetLogWithSource::Make(NetLogSourceType::NONE));
8058
8059 EXPECT_TRUE(LogContainsEventType(
8060 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8061 }
8062
TEST_F(HttpCacheTest,SpecialHeaders_LogsHeaders)8063 TEST_F(HttpCacheTest, SpecialHeaders_LogsHeaders) {
8064 MockHttpCache cache;
8065
8066 RecordingNetLogObserver net_log_observer;
8067 MockTransaction transaction(kSimpleGET_Transaction);
8068 transaction.request_headers = "cache-control: no-cache\r\n" EXTRA_HEADER;
8069 RunTransactionTestWithLog(cache.http_cache(), transaction,
8070 NetLogWithSource::Make(NetLogSourceType::NONE));
8071
8072 EXPECT_TRUE(LogContainsEventType(
8073 net_log_observer, NetLogEventType::HTTP_CACHE_CALLER_REQUEST_HEADERS));
8074 }
8075
8076 // Tests that receiving 206 for a regular request is handled correctly.
TEST_F(HttpCacheTest,GET_Crazy206)8077 TEST_F(HttpCacheTest, GET_Crazy206) {
8078 MockHttpCache cache;
8079
8080 // Write to the cache.
8081 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8082 transaction.request_headers = EXTRA_HEADER;
8083 transaction.handler = MockTransactionHandler();
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(1, cache.disk_cache()->create_count());
8089
8090 // This should read again from the net.
8091 RunTransactionTest(cache.http_cache(), transaction);
8092
8093 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8094 EXPECT_EQ(0, cache.disk_cache()->open_count());
8095 EXPECT_EQ(2, cache.disk_cache()->create_count());
8096 }
8097
8098 // Tests that receiving 416 for a regular request is handled correctly.
TEST_F(HttpCacheTest,GET_Crazy416)8099 TEST_F(HttpCacheTest, GET_Crazy416) {
8100 MockHttpCache cache;
8101
8102 // Write to the cache.
8103 ScopedMockTransaction transaction(kSimpleGET_Transaction);
8104 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
8105 RunTransactionTest(cache.http_cache(), transaction);
8106
8107 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8108 EXPECT_EQ(0, cache.disk_cache()->open_count());
8109 EXPECT_EQ(1, cache.disk_cache()->create_count());
8110 }
8111
8112 // Tests that we don't store partial responses that can't be validated.
TEST_F(HttpCacheTest,RangeGET_NoStrongValidators)8113 TEST_F(HttpCacheTest, RangeGET_NoStrongValidators) {
8114 MockHttpCache cache;
8115 std::string headers;
8116
8117 // Attempt to write to the cache (40-49).
8118 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8119 transaction.response_headers =
8120 "Content-Length: 10\n"
8121 "Cache-Control: max-age=3600\n"
8122 "ETag: w/\"foo\"\n";
8123 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8124
8125 Verify206Response(headers, 40, 49);
8126 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8127 EXPECT_EQ(0, cache.disk_cache()->open_count());
8128 EXPECT_EQ(1, cache.disk_cache()->create_count());
8129
8130 // Now verify that there's no cached data.
8131 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8132 &headers);
8133
8134 Verify206Response(headers, 40, 49);
8135 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8136 EXPECT_EQ(0, cache.disk_cache()->open_count());
8137 EXPECT_EQ(2, cache.disk_cache()->create_count());
8138 }
8139
8140 // Tests failures to conditionalize byte range requests.
TEST_F(HttpCacheTest,RangeGET_NoConditionalization)8141 TEST_F(HttpCacheTest, RangeGET_NoConditionalization) {
8142 MockHttpCache cache;
8143 cache.FailConditionalizations();
8144 std::string headers;
8145
8146 // Write to the cache (40-49).
8147 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8148 transaction.response_headers =
8149 "Content-Length: 10\n"
8150 "ETag: \"foo\"\n";
8151 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8152
8153 Verify206Response(headers, 40, 49);
8154 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8155 EXPECT_EQ(0, cache.disk_cache()->open_count());
8156 EXPECT_EQ(1, cache.disk_cache()->create_count());
8157
8158 // Now verify that the cached data is not used.
8159 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8160 &headers);
8161
8162 Verify206Response(headers, 40, 49);
8163 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8164 EXPECT_EQ(1, cache.disk_cache()->open_count());
8165 EXPECT_EQ(2, cache.disk_cache()->create_count());
8166 }
8167
8168 // Tests that restarting a partial request when the cached data cannot be
8169 // revalidated logs an event.
TEST_F(HttpCacheTest,RangeGET_NoValidation_LogsRestart)8170 TEST_F(HttpCacheTest, RangeGET_NoValidation_LogsRestart) {
8171 MockHttpCache cache;
8172 cache.FailConditionalizations();
8173
8174 // Write to the cache (40-49).
8175 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8176 transaction.response_headers =
8177 "Content-Length: 10\n"
8178 "ETag: \"foo\"\n";
8179 RunTransactionTest(cache.http_cache(), transaction);
8180
8181 // Now verify that the cached data is not used.
8182 RecordingNetLogObserver net_log_observer;
8183 RunTransactionTestWithLog(cache.http_cache(), kRangeGET_TransactionOK,
8184 NetLogWithSource::Make(NetLogSourceType::NONE));
8185
8186 EXPECT_TRUE(LogContainsEventType(
8187 net_log_observer, NetLogEventType::HTTP_CACHE_RESTART_PARTIAL_REQUEST));
8188 }
8189
8190 // Tests that a failure to conditionalize a regular request (no range) with a
8191 // sparse entry results in a full response.
TEST_F(HttpCacheTest,GET_NoConditionalization)8192 TEST_F(HttpCacheTest, GET_NoConditionalization) {
8193 for (bool use_memory_entry_data : {false, true}) {
8194 MockHttpCache cache;
8195 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
8196 cache.FailConditionalizations();
8197 std::string headers;
8198
8199 // Write to the cache (40-49).
8200 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8201 transaction.response_headers =
8202 "Content-Length: 10\n"
8203 "ETag: \"foo\"\n";
8204 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8205
8206 Verify206Response(headers, 40, 49);
8207 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8208 EXPECT_EQ(0, cache.disk_cache()->open_count());
8209 EXPECT_EQ(1, cache.disk_cache()->create_count());
8210
8211 // Now verify that the cached data is not used.
8212 // Don't ask for a range. The cache will attempt to use the cached data but
8213 // should discard it as it cannot be validated. A regular request should go
8214 // to the server and a new entry should be created.
8215 transaction.request_headers = EXTRA_HEADER;
8216 transaction.data = "Not a range";
8217 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8218
8219 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
8220 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8221 EXPECT_EQ(1, cache.disk_cache()->open_count());
8222 EXPECT_EQ(2, cache.disk_cache()->create_count());
8223
8224 // The last response was saved.
8225 RunTransactionTest(cache.http_cache(), transaction);
8226 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8227 if (use_memory_entry_data) {
8228 // The cache entry isn't really useful, since when
8229 // &RangeTransactionServer::RangeHandler gets a non-range request,
8230 // (the network transaction #2) it returns headers without ETag,
8231 // Last-Modified or caching headers, with a Date in 2007 (so no heuristic
8232 // freshness), so it's both expired and not conditionalizable --- so in
8233 // this branch we avoid opening it.
8234 EXPECT_EQ(1, cache.disk_cache()->open_count());
8235 EXPECT_EQ(3, cache.disk_cache()->create_count());
8236 } else {
8237 EXPECT_EQ(2, cache.disk_cache()->open_count());
8238 EXPECT_EQ(2, cache.disk_cache()->create_count());
8239 }
8240 }
8241 }
8242
8243 // Verifies that conditionalization failures when asking for a range that would
8244 // require the cache to modify the range to ask, result in a network request
8245 // that matches the user's one.
TEST_F(HttpCacheTest,RangeGET_NoConditionalization2)8246 TEST_F(HttpCacheTest, RangeGET_NoConditionalization2) {
8247 MockHttpCache cache;
8248 cache.FailConditionalizations();
8249 std::string headers;
8250
8251 // Write to the cache (40-49).
8252 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8253 transaction.response_headers =
8254 "Content-Length: 10\n"
8255 "ETag: \"foo\"\n";
8256 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8257
8258 Verify206Response(headers, 40, 49);
8259 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8260 EXPECT_EQ(0, cache.disk_cache()->open_count());
8261 EXPECT_EQ(1, cache.disk_cache()->create_count());
8262
8263 // Now verify that the cached data is not used.
8264 // Ask for a range that extends before and after the cached data so that the
8265 // cache would normally mix data from three sources. After deleting the entry,
8266 // the response will come from a single network request.
8267 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8268 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8269 transaction.response_headers = kRangeGET_TransactionOK.response_headers;
8270 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8271
8272 Verify206Response(headers, 20, 59);
8273 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8274 EXPECT_EQ(1, cache.disk_cache()->open_count());
8275 EXPECT_EQ(2, cache.disk_cache()->create_count());
8276
8277 // The last response was saved.
8278 RunTransactionTest(cache.http_cache(), transaction);
8279 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8280 EXPECT_EQ(2, cache.disk_cache()->open_count());
8281 EXPECT_EQ(2, cache.disk_cache()->create_count());
8282 }
8283
8284 // Tests that we cache partial responses that lack content-length.
TEST_F(HttpCacheTest,RangeGET_NoContentLength)8285 TEST_F(HttpCacheTest, RangeGET_NoContentLength) {
8286 MockHttpCache cache;
8287 std::string headers;
8288
8289 // Attempt to write to the cache (40-49).
8290 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8291 transaction.response_headers =
8292 "ETag: \"foo\"\n"
8293 "Accept-Ranges: bytes\n"
8294 "Content-Range: bytes 40-49/80\n";
8295 transaction.handler = MockTransactionHandler();
8296 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8297
8298 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8299 EXPECT_EQ(0, cache.disk_cache()->open_count());
8300 EXPECT_EQ(1, cache.disk_cache()->create_count());
8301
8302 // Now verify that there's no cached data.
8303 transaction.handler =
8304 base::BindRepeating(&RangeTransactionServer::RangeHandler);
8305 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8306 &headers);
8307
8308 Verify206Response(headers, 40, 49);
8309 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8310 EXPECT_EQ(1, cache.disk_cache()->open_count());
8311 EXPECT_EQ(1, cache.disk_cache()->create_count());
8312 }
8313
8314 // Tests that we can cache range requests and fetch random blocks from the
8315 // cache and the network.
TEST_F(HttpCacheTest,RangeGET_OK)8316 TEST_F(HttpCacheTest, RangeGET_OK) {
8317 MockHttpCache cache;
8318 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
8319 std::string headers;
8320
8321 // Write to the cache (40-49).
8322 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8323 &headers);
8324
8325 Verify206Response(headers, 40, 49);
8326 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8327 EXPECT_EQ(0, cache.disk_cache()->open_count());
8328 EXPECT_EQ(1, cache.disk_cache()->create_count());
8329
8330 // Read from the cache (40-49).
8331 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8332 &headers);
8333
8334 Verify206Response(headers, 40, 49);
8335 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8336 EXPECT_EQ(1, cache.disk_cache()->open_count());
8337 EXPECT_EQ(1, cache.disk_cache()->create_count());
8338
8339 // Make sure we are done with the previous transaction.
8340 base::RunLoop().RunUntilIdle();
8341
8342 // Write to the cache (30-39).
8343 MockTransaction transaction(kRangeGET_TransactionOK);
8344 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
8345 transaction.data = "rg: 30-39 ";
8346 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8347
8348 Verify206Response(headers, 30, 39);
8349 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8350 EXPECT_EQ(2, cache.disk_cache()->open_count());
8351 EXPECT_EQ(1, cache.disk_cache()->create_count());
8352
8353 // Make sure we are done with the previous transaction.
8354 base::RunLoop().RunUntilIdle();
8355
8356 // Write and read from the cache (20-59).
8357 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8358 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8359 LoadTimingInfo load_timing_info;
8360 RunTransactionTestWithResponseAndGetTiming(
8361 cache.http_cache(), transaction, &headers,
8362 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
8363
8364 Verify206Response(headers, 20, 59);
8365 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8366 EXPECT_EQ(3, cache.disk_cache()->open_count());
8367 EXPECT_EQ(1, cache.disk_cache()->create_count());
8368 TestLoadTimingNetworkRequest(load_timing_info);
8369 }
8370
TEST_F(HttpCacheTest,RangeGET_CacheReadError)8371 TEST_F(HttpCacheTest, RangeGET_CacheReadError) {
8372 // Tests recovery on cache read error on range request.
8373 MockHttpCache cache;
8374 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8375 std::string headers;
8376
8377 // Write to the cache (40-49).
8378 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8379 &headers);
8380
8381 Verify206Response(headers, 40, 49);
8382 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8383 EXPECT_EQ(0, cache.disk_cache()->open_count());
8384 EXPECT_EQ(1, cache.disk_cache()->create_count());
8385
8386 cache.disk_cache()->set_soft_failures_one_instance(MockDiskEntry::FAIL_ALL);
8387
8388 // Try to read from the cache (40-49), which will fail quickly enough to
8389 // restart, due to the failure injected above. This should still be a range
8390 // request. (https://crbug.com/891212)
8391 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
8392 &headers);
8393
8394 Verify206Response(headers, 40, 49);
8395 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8396 EXPECT_EQ(1, cache.disk_cache()->open_count());
8397 EXPECT_EQ(2, cache.disk_cache()->create_count());
8398 }
8399
8400 // Tests that range requests with no-store get correct content-length
8401 // (https://crbug.com/700197).
TEST_F(HttpCacheTest,RangeGET_NoStore)8402 TEST_F(HttpCacheTest, RangeGET_NoStore) {
8403 MockHttpCache cache;
8404
8405 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8406 std::string response_headers = base::StrCat(
8407 {kRangeGET_TransactionOK.response_headers, "Cache-Control: no-store\n"});
8408 transaction.response_headers = response_headers.c_str();
8409
8410 std::string headers;
8411 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8412
8413 Verify206Response(headers, 40, 49);
8414 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8415 EXPECT_EQ(0, cache.disk_cache()->open_count());
8416 EXPECT_EQ(1, cache.disk_cache()->create_count());
8417 }
8418
8419 // Tests a 304 setting no-store on existing 206 entry.
TEST_F(HttpCacheTest,RangeGET_NoStore304)8420 TEST_F(HttpCacheTest, RangeGET_NoStore304) {
8421 MockHttpCache cache;
8422
8423 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8424 std::string response_headers = base::StrCat(
8425 {kRangeGET_TransactionOK.response_headers, "Cache-Control: max-age=0\n"});
8426 transaction.response_headers = response_headers.c_str();
8427
8428 std::string headers;
8429 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8430
8431 Verify206Response(headers, 40, 49);
8432 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8433 EXPECT_EQ(0, cache.disk_cache()->open_count());
8434 EXPECT_EQ(1, cache.disk_cache()->create_count());
8435
8436 response_headers = base::StrCat(
8437 {kRangeGET_TransactionOK.response_headers, "Cache-Control: no-store\n"});
8438 transaction.response_headers = response_headers.c_str();
8439 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8440 Verify206Response(headers, 40, 49);
8441
8442 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8443 EXPECT_EQ(1, cache.disk_cache()->open_count());
8444 EXPECT_EQ(1, cache.disk_cache()->create_count());
8445
8446 // Fetch again, this one should be from newly created cache entry, due to
8447 // earlier no-store.
8448 transaction.response_headers = kRangeGET_TransactionOK.response_headers;
8449 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8450 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8451 EXPECT_EQ(1, cache.disk_cache()->open_count());
8452 EXPECT_EQ(2, cache.disk_cache()->create_count());
8453 Verify206Response(headers, 40, 49);
8454 }
8455
8456 // Tests that we can cache range requests and fetch random blocks from the
8457 // cache and the network, with synchronous responses.
TEST_F(HttpCacheTest,RangeGET_SyncOK)8458 TEST_F(HttpCacheTest, RangeGET_SyncOK) {
8459 MockHttpCache cache;
8460
8461 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8462 transaction.test_mode = TEST_MODE_SYNC_ALL;
8463
8464 // Write to the cache (40-49).
8465 std::string headers;
8466 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8467
8468 Verify206Response(headers, 40, 49);
8469 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8470 EXPECT_EQ(0, cache.disk_cache()->open_count());
8471 EXPECT_EQ(1, cache.disk_cache()->create_count());
8472
8473 // Read from the cache (40-49).
8474 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8475
8476 Verify206Response(headers, 40, 49);
8477 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8478 EXPECT_EQ(0, cache.disk_cache()->open_count());
8479 EXPECT_EQ(1, cache.disk_cache()->create_count());
8480
8481 // Make sure we are done with the previous transaction.
8482 base::RunLoop().RunUntilIdle();
8483
8484 // Write to the cache (30-39).
8485 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
8486 transaction.data = "rg: 30-39 ";
8487 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8488
8489 Verify206Response(headers, 30, 39);
8490 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8491 EXPECT_EQ(1, cache.disk_cache()->open_count());
8492 EXPECT_EQ(1, cache.disk_cache()->create_count());
8493
8494 // Make sure we are done with the previous transaction.
8495 base::RunLoop().RunUntilIdle();
8496
8497 // Write and read from the cache (20-59).
8498 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
8499 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
8500 LoadTimingInfo load_timing_info;
8501 RunTransactionTestWithResponseAndGetTiming(
8502 cache.http_cache(), transaction, &headers,
8503 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
8504
8505 Verify206Response(headers, 20, 59);
8506 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8507 EXPECT_EQ(2, cache.disk_cache()->open_count());
8508 EXPECT_EQ(1, cache.disk_cache()->create_count());
8509 TestLoadTimingNetworkRequest(load_timing_info);
8510 }
8511
8512 // Tests that if the previous transaction is cancelled while busy (doing sparse
8513 // IO), a new transaction (that reuses that same ActiveEntry) waits until the
8514 // entry is ready again.
TEST_F(HttpCacheTest,Sparse_WaitForEntry)8515 TEST_F(HttpCacheTest, Sparse_WaitForEntry) {
8516 MockHttpCache cache;
8517
8518 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8519
8520 // Create a sparse entry.
8521 RunTransactionTest(cache.http_cache(), transaction);
8522
8523 // Simulate a previous transaction being cancelled.
8524 disk_cache::Entry* entry;
8525 MockHttpRequest request(transaction);
8526 std::string cache_key =
8527 *cache.http_cache()->GenerateCacheKeyForRequest(&request);
8528 ASSERT_TRUE(cache.OpenBackendEntry(cache_key, &entry));
8529 entry->CancelSparseIO();
8530
8531 // Test with a range request.
8532 RunTransactionTest(cache.http_cache(), transaction);
8533
8534 // Now test with a regular request.
8535 entry->CancelSparseIO();
8536 transaction.request_headers = EXTRA_HEADER;
8537 transaction.data = kFullRangeData;
8538 RunTransactionTest(cache.http_cache(), transaction);
8539
8540 entry->Close();
8541 }
8542
8543 // Tests that we don't revalidate an entry unless we are required to do so.
TEST_F(HttpCacheTest,RangeGET_Revalidate1)8544 TEST_F(HttpCacheTest, RangeGET_Revalidate1) {
8545 MockHttpCache cache;
8546 std::string headers;
8547
8548 // Write to the cache (40-49).
8549 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8550 transaction.response_headers =
8551 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
8552 "Expires: Wed, 7 Sep 2033 21:46:42 GMT\n" // Should never expire.
8553 "ETag: \"foo\"\n"
8554 "Accept-Ranges: bytes\n"
8555 "Content-Length: 10\n";
8556 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8557
8558 Verify206Response(headers, 40, 49);
8559 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8560 EXPECT_EQ(0, cache.disk_cache()->open_count());
8561 EXPECT_EQ(1, cache.disk_cache()->create_count());
8562
8563 // Read from the cache (40-49).
8564 NetLogWithSource net_log_with_source =
8565 NetLogWithSource::Make(NetLogSourceType::NONE);
8566 LoadTimingInfo load_timing_info;
8567 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
8568 &headers, net_log_with_source,
8569 &load_timing_info);
8570
8571 Verify206Response(headers, 40, 49);
8572 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8573 EXPECT_EQ(1, cache.disk_cache()->open_count());
8574 EXPECT_EQ(1, cache.disk_cache()->create_count());
8575 TestLoadTimingCachedResponse(load_timing_info);
8576
8577 // Read again forcing the revalidation.
8578 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8579 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
8580 &headers, net_log_with_source,
8581 &load_timing_info);
8582
8583 Verify206Response(headers, 40, 49);
8584 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8585 EXPECT_EQ(1, cache.disk_cache()->open_count());
8586 EXPECT_EQ(1, cache.disk_cache()->create_count());
8587 TestLoadTimingNetworkRequest(load_timing_info);
8588 }
8589
8590 // Checks that we revalidate an entry when the headers say so.
TEST_F(HttpCacheTest,RangeGET_Revalidate2)8591 TEST_F(HttpCacheTest, RangeGET_Revalidate2) {
8592 MockHttpCache cache;
8593 std::string headers;
8594
8595 // Write to the cache (40-49).
8596 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8597 transaction.response_headers =
8598 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
8599 "Expires: Sat, 18 Apr 2009 01:10:43 GMT\n" // Expired.
8600 "ETag: \"foo\"\n"
8601 "Accept-Ranges: bytes\n"
8602 "Content-Length: 10\n";
8603 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8604
8605 Verify206Response(headers, 40, 49);
8606 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8607 EXPECT_EQ(0, cache.disk_cache()->open_count());
8608 EXPECT_EQ(1, cache.disk_cache()->create_count());
8609
8610 // Read from the cache (40-49).
8611 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8612 Verify206Response(headers, 40, 49);
8613
8614 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8615 EXPECT_EQ(1, cache.disk_cache()->open_count());
8616 EXPECT_EQ(1, cache.disk_cache()->create_count());
8617 }
8618
8619 // Tests that we deal with 304s for range requests.
TEST_F(HttpCacheTest,RangeGET_304)8620 TEST_F(HttpCacheTest, RangeGET_304) {
8621 MockHttpCache cache;
8622 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
8623 std::string headers;
8624
8625 // Write to the cache (40-49).
8626 RunTransactionTestWithResponse(cache.http_cache(), scoped_transaction,
8627 &headers);
8628
8629 Verify206Response(headers, 40, 49);
8630 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8631 EXPECT_EQ(0, cache.disk_cache()->open_count());
8632 EXPECT_EQ(1, cache.disk_cache()->create_count());
8633
8634 // Read from the cache (40-49).
8635 RangeTransactionServer handler;
8636 handler.set_not_modified(true);
8637 MockTransaction transaction(kRangeGET_TransactionOK);
8638 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8639 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8640
8641 Verify206Response(headers, 40, 49);
8642 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8643 EXPECT_EQ(1, cache.disk_cache()->open_count());
8644 EXPECT_EQ(1, cache.disk_cache()->create_count());
8645 }
8646
8647 // Tests that we deal with 206s when revalidating range requests.
TEST_F(HttpCacheTest,RangeGET_ModifiedResult)8648 TEST_F(HttpCacheTest, RangeGET_ModifiedResult) {
8649 MockHttpCache cache;
8650 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
8651 std::string headers;
8652
8653 // Write to the cache (40-49).
8654 RunTransactionTestWithResponse(cache.http_cache(), scoped_transaction,
8655 &headers);
8656
8657 Verify206Response(headers, 40, 49);
8658 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8659 EXPECT_EQ(0, cache.disk_cache()->open_count());
8660 EXPECT_EQ(1, cache.disk_cache()->create_count());
8661
8662 // Attempt to read from the cache (40-49).
8663 RangeTransactionServer handler;
8664 handler.set_modified(true);
8665 MockTransaction transaction(kRangeGET_TransactionOK);
8666 transaction.load_flags |= LOAD_VALIDATE_CACHE;
8667 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8668
8669 Verify206Response(headers, 40, 49);
8670 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8671 EXPECT_EQ(1, cache.disk_cache()->open_count());
8672 EXPECT_EQ(1, cache.disk_cache()->create_count());
8673
8674 // And the entry should be gone.
8675 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
8676 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8677 EXPECT_EQ(1, cache.disk_cache()->open_count());
8678 EXPECT_EQ(2, cache.disk_cache()->create_count());
8679 }
8680
8681 // Tests that when a server returns 206 with a sub-range of the requested range,
8682 // and there is nothing stored in the cache, the returned response is passed to
8683 // the caller as is. In this context, a subrange means a response that starts
8684 // with the same byte that was requested, but that is not the whole range that
8685 // was requested.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSubrangeRange_NoCachedContent)8686 TEST_F(HttpCacheTest, RangeGET_206ReturnsSubrangeRange_NoCachedContent) {
8687 MockHttpCache cache;
8688 std::string headers;
8689
8690 // Request a large range (40-59). The server sends 40-49.
8691 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8692 transaction.request_headers = "Range: bytes = 40-59\r\n" EXTRA_HEADER;
8693 transaction.response_headers =
8694 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8695 "ETag: \"foo\"\n"
8696 "Accept-Ranges: bytes\n"
8697 "Content-Length: 10\n"
8698 "Content-Range: bytes 40-49/80\n";
8699 transaction.handler = MockTransactionHandler();
8700 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8701
8702 Verify206Response(headers, 40, 49);
8703 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8704 EXPECT_EQ(0, cache.disk_cache()->open_count());
8705 EXPECT_EQ(1, cache.disk_cache()->create_count());
8706 }
8707
8708 // Tests that when a server returns 206 with a sub-range of the requested range,
8709 // and there was an entry stored in the cache, the cache gets out of the way.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSubrangeRange_CachedContent)8710 TEST_F(HttpCacheTest, RangeGET_206ReturnsSubrangeRange_CachedContent) {
8711 MockHttpCache cache;
8712 std::string headers;
8713
8714 // Write to the cache (70-79).
8715 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8716 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8717 transaction.data = "rg: 70-79 ";
8718 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8719 Verify206Response(headers, 70, 79);
8720
8721 // Request a large range (40-79). The cache will ask the server for 40-59.
8722 // The server returns 40-49. The cache should consider the server confused and
8723 // abort caching, restarting the request without caching.
8724 transaction.request_headers = "Range: bytes = 40-79\r\n" EXTRA_HEADER;
8725 transaction.response_headers =
8726 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8727 "ETag: \"foo\"\n"
8728 "Accept-Ranges: bytes\n"
8729 "Content-Length: 10\n"
8730 "Content-Range: bytes 40-49/80\n";
8731 transaction.handler = MockTransactionHandler();
8732 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8733
8734 // Two new network requests were issued, one from the cache and another after
8735 // deleting the entry.
8736 Verify206Response(headers, 40, 49);
8737 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8738 EXPECT_EQ(1, cache.disk_cache()->open_count());
8739 EXPECT_EQ(1, cache.disk_cache()->create_count());
8740
8741 // The entry was deleted.
8742 RunTransactionTest(cache.http_cache(), transaction);
8743 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8744 EXPECT_EQ(1, cache.disk_cache()->open_count());
8745 EXPECT_EQ(2, cache.disk_cache()->create_count());
8746 }
8747
8748 // Tests that when a server returns 206 with a sub-range of the requested range,
8749 // and there was an entry stored in the cache, the cache gets out of the way,
8750 // when the caller is not using ranges.
TEST_F(HttpCacheTest,GET_206ReturnsSubrangeRange_CachedContent)8751 TEST_F(HttpCacheTest, GET_206ReturnsSubrangeRange_CachedContent) {
8752 MockHttpCache cache;
8753 std::string headers;
8754
8755 // Write to the cache (70-79).
8756 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8757 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8758 transaction.data = "rg: 70-79 ";
8759 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8760 Verify206Response(headers, 70, 79);
8761
8762 // Don't ask for a range. The cache will ask the server for 0-69.
8763 // The server returns 40-49. The cache should consider the server confused and
8764 // abort caching, restarting the request.
8765 // The second network request should not be a byte range request so the server
8766 // should return 200 + "Not a range"
8767 transaction.request_headers = "X-Return-Default-Range:\r\n" EXTRA_HEADER;
8768 transaction.data = "Not a range";
8769 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8770
8771 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
8772 EXPECT_EQ(3, cache.network_layer()->transaction_count());
8773 EXPECT_EQ(1, cache.disk_cache()->open_count());
8774 EXPECT_EQ(1, cache.disk_cache()->create_count());
8775
8776 // The entry was deleted.
8777 RunTransactionTest(cache.http_cache(), transaction);
8778 EXPECT_EQ(4, cache.network_layer()->transaction_count());
8779 EXPECT_EQ(1, cache.disk_cache()->open_count());
8780 EXPECT_EQ(2, cache.disk_cache()->create_count());
8781 }
8782
8783 // Tests that when a server returns 206 with a random range and there is
8784 // nothing stored in the cache, the returned response is passed to the caller
8785 // as is. In this context, a WrongRange means that the returned range may or may
8786 // not have any relationship with the requested range (may or may not be
8787 // contained). The important part is that the first byte doesn't match the first
8788 // requested byte.
TEST_F(HttpCacheTest,RangeGET_206ReturnsWrongRange_NoCachedContent)8789 TEST_F(HttpCacheTest, RangeGET_206ReturnsWrongRange_NoCachedContent) {
8790 MockHttpCache cache;
8791 std::string headers;
8792
8793 // Request a large range (30-59). The server sends (40-49).
8794 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8795 transaction.request_headers = "Range: bytes = 30-59\r\n" EXTRA_HEADER;
8796 transaction.response_headers =
8797 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8798 "ETag: \"foo\"\n"
8799 "Accept-Ranges: bytes\n"
8800 "Content-Length: 10\n"
8801 "Content-Range: bytes 40-49/80\n";
8802 transaction.handler = MockTransactionHandler();
8803 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8804
8805 Verify206Response(headers, 40, 49);
8806 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8807 EXPECT_EQ(0, cache.disk_cache()->open_count());
8808 EXPECT_EQ(1, cache.disk_cache()->create_count());
8809
8810 // The entry was deleted.
8811 RunTransactionTest(cache.http_cache(), transaction);
8812 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8813 EXPECT_EQ(0, cache.disk_cache()->open_count());
8814 EXPECT_EQ(2, cache.disk_cache()->create_count());
8815 }
8816
8817 // Tests that when a server returns 206 with a random range and there is
8818 // an entry stored in the cache, the cache gets out of the way.
TEST_F(HttpCacheTest,RangeGET_206ReturnsWrongRange_CachedContent)8819 TEST_F(HttpCacheTest, RangeGET_206ReturnsWrongRange_CachedContent) {
8820 MockHttpCache cache;
8821 std::string headers;
8822
8823 // Write to the cache (70-79).
8824 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8825 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
8826 transaction.data = "rg: 70-79 ";
8827 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8828 Verify206Response(headers, 70, 79);
8829
8830 // Request a large range (30-79). The cache will ask the server for 30-69.
8831 // The server returns 40-49. The cache should consider the server confused and
8832 // abort caching, returning the weird range to the caller.
8833 transaction.request_headers = "Range: bytes = 30-79\r\n" EXTRA_HEADER;
8834 transaction.response_headers =
8835 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
8836 "ETag: \"foo\"\n"
8837 "Accept-Ranges: bytes\n"
8838 "Content-Length: 10\n"
8839 "Content-Range: bytes 40-49/80\n";
8840 transaction.handler = MockTransactionHandler();
8841 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8842
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 caller asks for a range beyond EOF, with an empty cache,
8856 // the response matches the one provided by the server.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSmallerFile_NoCachedContent)8857 TEST_F(HttpCacheTest, RangeGET_206ReturnsSmallerFile_NoCachedContent) {
8858 MockHttpCache cache;
8859 std::string headers;
8860
8861 // Request a large range (70-99). The server sends 70-79.
8862 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8863 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
8864 transaction.data = "rg: 70-79 ";
8865 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8866
8867 Verify206Response(headers, 70, 79);
8868 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8869 EXPECT_EQ(0, cache.disk_cache()->open_count());
8870 EXPECT_EQ(1, cache.disk_cache()->create_count());
8871
8872 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
8873 EXPECT_EQ(1, cache.disk_cache()->open_count());
8874 }
8875
8876 // Tests that when a caller asks for a range beyond EOF, with a cached entry,
8877 // the cache automatically fixes the request.
TEST_F(HttpCacheTest,RangeGET_206ReturnsSmallerFile_CachedContent)8878 TEST_F(HttpCacheTest, RangeGET_206ReturnsSmallerFile_CachedContent) {
8879 MockHttpCache cache;
8880 std::string headers;
8881
8882 // Write to the cache (40-49).
8883 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8884 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8885
8886 // Request a large range (70-99). The server sends 70-79.
8887 transaction.request_headers = "Range: bytes = 70-99\r\n" EXTRA_HEADER;
8888 transaction.data = "rg: 70-79 ";
8889 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8890
8891 Verify206Response(headers, 70, 79);
8892 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8893 EXPECT_EQ(1, cache.disk_cache()->open_count());
8894 EXPECT_EQ(1, cache.disk_cache()->create_count());
8895
8896 // The entry was not deleted (the range was automatically fixed).
8897 RunTransactionTest(cache.http_cache(), transaction);
8898 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8899 EXPECT_EQ(2, cache.disk_cache()->open_count());
8900 EXPECT_EQ(1, cache.disk_cache()->create_count());
8901 }
8902
8903 // Tests that when a caller asks for a not-satisfiable range, the server's
8904 // response is forwarded to the caller.
TEST_F(HttpCacheTest,RangeGET_416_NoCachedContent)8905 TEST_F(HttpCacheTest, RangeGET_416_NoCachedContent) {
8906 MockHttpCache cache;
8907 std::string headers;
8908
8909 // Request a range beyond EOF (80-99).
8910 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8911 transaction.request_headers = "Range: bytes = 80-99\r\n" EXTRA_HEADER;
8912 transaction.data = "";
8913 transaction.status = "HTTP/1.1 416 Requested Range Not Satisfiable";
8914 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8915
8916 EXPECT_EQ(0U, headers.find(transaction.status));
8917 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8918 EXPECT_EQ(0, cache.disk_cache()->open_count());
8919 EXPECT_EQ(1, cache.disk_cache()->create_count());
8920
8921 // The entry was deleted.
8922 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
8923 EXPECT_EQ(2, cache.disk_cache()->create_count());
8924 }
8925
8926 // Tests that we cache 301s for range requests.
TEST_F(HttpCacheTest,RangeGET_301)8927 TEST_F(HttpCacheTest, RangeGET_301) {
8928 MockHttpCache cache;
8929 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8930 transaction.status = "HTTP/1.1 301 Moved Permanently";
8931 transaction.response_headers = "Location: http://www.bar.com/\n";
8932 transaction.data = "";
8933 transaction.handler = MockTransactionHandler();
8934
8935 // Write to the cache.
8936 RunTransactionTest(cache.http_cache(), transaction);
8937 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8938 EXPECT_EQ(0, cache.disk_cache()->open_count());
8939 EXPECT_EQ(1, cache.disk_cache()->create_count());
8940
8941 // Read from the cache.
8942 RunTransactionTest(cache.http_cache(), transaction);
8943 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8944 EXPECT_EQ(1, cache.disk_cache()->open_count());
8945 EXPECT_EQ(1, cache.disk_cache()->create_count());
8946 }
8947
8948 // Tests that we can cache range requests when the start or end is unknown.
8949 // We start with one suffix request, followed by a request from a given point.
TEST_F(HttpCacheTest,UnknownRangeGET_1)8950 TEST_F(HttpCacheTest, UnknownRangeGET_1) {
8951 MockHttpCache cache;
8952 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
8953 std::string headers;
8954
8955 // Write to the cache (70-79).
8956 MockTransaction transaction(kRangeGET_TransactionOK);
8957 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
8958 transaction.data = "rg: 70-79 ";
8959 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8960
8961 Verify206Response(headers, 70, 79);
8962 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8963 EXPECT_EQ(0, cache.disk_cache()->open_count());
8964 EXPECT_EQ(1, cache.disk_cache()->create_count());
8965
8966 // Make sure we are done with the previous transaction.
8967 base::RunLoop().RunUntilIdle();
8968
8969 // Write and read from the cache (60-79).
8970 transaction.request_headers = "Range: bytes = 60-\r\n" EXTRA_HEADER;
8971 transaction.data = "rg: 60-69 rg: 70-79 ";
8972 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8973
8974 Verify206Response(headers, 60, 79);
8975 EXPECT_EQ(2, cache.network_layer()->transaction_count());
8976 EXPECT_EQ(1, cache.disk_cache()->open_count());
8977 EXPECT_EQ(1, cache.disk_cache()->create_count());
8978 }
8979
8980 // Tests that we can cache range requests when the start or end is unknown.
8981 // We start with one request from a given point, followed by a suffix request.
8982 // We'll also verify that synchronous cache responses work as intended.
TEST_F(HttpCacheTest,UnknownRangeGET_2)8983 TEST_F(HttpCacheTest, UnknownRangeGET_2) {
8984 MockHttpCache cache;
8985 std::string headers;
8986
8987 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
8988 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
8989 TEST_MODE_SYNC_CACHE_READ |
8990 TEST_MODE_SYNC_CACHE_WRITE;
8991
8992 // Write to the cache (70-79).
8993 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
8994 transaction.data = "rg: 70-79 ";
8995 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
8996
8997 Verify206Response(headers, 70, 79);
8998 EXPECT_EQ(1, cache.network_layer()->transaction_count());
8999 EXPECT_EQ(0, cache.disk_cache()->open_count());
9000 EXPECT_EQ(1, cache.disk_cache()->create_count());
9001
9002 // Make sure we are done with the previous transaction.
9003 base::RunLoop().RunUntilIdle();
9004
9005 // Write and read from the cache (60-79).
9006 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
9007 transaction.data = "rg: 60-69 rg: 70-79 ";
9008 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9009
9010 Verify206Response(headers, 60, 79);
9011 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9012 EXPECT_EQ(1, cache.disk_cache()->open_count());
9013 EXPECT_EQ(1, cache.disk_cache()->create_count());
9014 }
9015
9016 // Similar to UnknownRangeGET_2, except that the resource size is empty.
9017 // Regression test for crbug.com/813061, and probably https://crbug.com/1375128
TEST_F(HttpCacheTest,UnknownRangeGET_3)9018 TEST_F(HttpCacheTest, UnknownRangeGET_3) {
9019 MockHttpCache cache;
9020 std::string headers;
9021
9022 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9023 transaction.response_headers =
9024 "Cache-Control: max-age=10000\n"
9025 "Content-Length: 0\n",
9026 transaction.data = "";
9027 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9028 TEST_MODE_SYNC_CACHE_READ |
9029 TEST_MODE_SYNC_CACHE_WRITE;
9030
9031 // Write the empty resource to the cache.
9032 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9033
9034 EXPECT_EQ(
9035 "HTTP/1.1 200 OK\nCache-Control: max-age=10000\nContent-Length: 0\n",
9036 headers);
9037 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9038 EXPECT_EQ(0, cache.disk_cache()->open_count());
9039 EXPECT_EQ(1, cache.disk_cache()->create_count());
9040
9041 // Make sure we are done with the previous transaction.
9042 base::RunLoop().RunUntilIdle();
9043
9044 // Write and read from the cache. This used to trigger a DCHECK
9045 // (or loop infinitely with it off).
9046 transaction.request_headers = "Range: bytes = -20\r\n" EXTRA_HEADER;
9047 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9048
9049 EXPECT_EQ(
9050 "HTTP/1.1 200 OK\nCache-Control: max-age=10000\nContent-Length: 0\n",
9051 headers);
9052 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9053 EXPECT_EQ(1, cache.disk_cache()->open_count());
9054 EXPECT_EQ(1, cache.disk_cache()->create_count());
9055 }
9056
9057 // Testcase for https://crbug.com/1433305, validation of range request to a
9058 // cache 302, which is notably bodiless.
TEST_F(HttpCacheTest,UnknownRangeGET_302)9059 TEST_F(HttpCacheTest, UnknownRangeGET_302) {
9060 MockHttpCache cache;
9061 std::string headers;
9062
9063 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9064 transaction.status = "HTTP/1.1 302 Found";
9065 transaction.response_headers =
9066 "Cache-Control: max-age=0\n"
9067 "Content-Length: 0\n"
9068 "Location: https://example.org/\n",
9069
9070 transaction.data = "";
9071 transaction.request_headers = "Range: bytes = 0-\r\n" EXTRA_HEADER;
9072 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9073 TEST_MODE_SYNC_CACHE_READ |
9074 TEST_MODE_SYNC_CACHE_WRITE;
9075
9076 // Write the empty resource to the cache.
9077 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9078
9079 EXPECT_EQ(
9080 "HTTP/1.1 302 Found\n"
9081 "Cache-Control: max-age=0\n"
9082 "Content-Length: 0\n"
9083 "Location: https://example.org/\n",
9084 headers);
9085 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9086 EXPECT_EQ(0, cache.disk_cache()->open_count());
9087 EXPECT_EQ(1, cache.disk_cache()->create_count());
9088
9089 // Make sure we are done with the previous transaction.
9090 base::RunLoop().RunUntilIdle();
9091
9092 // Try to read from the cache. This should send a network request to
9093 // validate it, and get a different redirect.
9094 transaction.response_headers =
9095 "Cache-Control: max-age=0\n"
9096 "Content-Length: 0\n"
9097 "Location: https://example.com/\n",
9098 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9099
9100 EXPECT_EQ(
9101 "HTTP/1.1 302 Found\n"
9102 "Cache-Control: max-age=0\n"
9103 "Content-Length: 0\n"
9104 "Location: https://example.com/\n",
9105 headers);
9106 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9107 EXPECT_EQ(1, cache.disk_cache()->open_count());
9108 // A new entry is created since this one isn't conditionalizable.
9109 EXPECT_EQ(2, cache.disk_cache()->create_count());
9110 }
9111
9112 // Testcase for https://crbug.com/1433305, validation of range request to a
9113 // cache 302, which is notably bodiless, where the 302 is replaced with an
9114 // actual body.
TEST_F(HttpCacheTest,UnknownRangeGET_302_Replaced)9115 TEST_F(HttpCacheTest, UnknownRangeGET_302_Replaced) {
9116 MockHttpCache cache;
9117 std::string headers;
9118
9119 ScopedMockTransaction transaction(kSimpleGET_Transaction);
9120 transaction.status = "HTTP/1.1 302 Found";
9121 transaction.response_headers =
9122 "Cache-Control: max-age=0\n"
9123 "Content-Length: 0\n"
9124 "Location: https://example.org/\n",
9125
9126 transaction.data = "";
9127 transaction.test_mode = TEST_MODE_SYNC_CACHE_START |
9128 TEST_MODE_SYNC_CACHE_READ |
9129 TEST_MODE_SYNC_CACHE_WRITE;
9130
9131 // Write the empty resource to the cache.
9132 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9133
9134 EXPECT_EQ(
9135 "HTTP/1.1 302 Found\n"
9136 "Cache-Control: max-age=0\n"
9137 "Content-Length: 0\n"
9138 "Location: https://example.org/\n",
9139 headers);
9140 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9141 EXPECT_EQ(0, cache.disk_cache()->open_count());
9142 EXPECT_EQ(1, cache.disk_cache()->create_count());
9143
9144 // Make sure we are done with the previous transaction.
9145 base::RunLoop().RunUntilIdle();
9146
9147 // Try to read from the cache. This should send a network request to
9148 // validate it, and get a different response.
9149 transaction.handler =
9150 base::BindRepeating(&RangeTransactionServer::RangeHandler);
9151 transaction.request_headers = "Range: bytes = -30\r\n" EXTRA_HEADER;
9152 // Tail 30 bytes out of 80
9153 transaction.data = "rg: 50-59 rg: 60-69 rg: 70-79 ";
9154 transaction.status = "HTTP/1.1 206 Partial Content";
9155 transaction.response_headers = "Content-Length: 10\n";
9156 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9157
9158 EXPECT_EQ(
9159 "HTTP/1.1 206 Partial Content\n"
9160 "Content-Range: bytes 50-79/80\n"
9161 "Content-Length: 30\n",
9162 headers);
9163 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9164 EXPECT_EQ(1, cache.disk_cache()->open_count());
9165 // A new entry is created since this one isn't conditionalizable.
9166 EXPECT_EQ(2, cache.disk_cache()->create_count());
9167 }
9168
9169 // Tests that receiving Not Modified when asking for an open range doesn't mess
9170 // up things.
TEST_F(HttpCacheTest,UnknownRangeGET_304)9171 TEST_F(HttpCacheTest, UnknownRangeGET_304) {
9172 MockHttpCache cache;
9173 std::string headers;
9174
9175 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9176
9177 RangeTransactionServer handler;
9178 handler.set_not_modified(true);
9179
9180 // Ask for the end of the file, without knowing the length.
9181 transaction.request_headers = "Range: bytes = 70-\r\n" EXTRA_HEADER;
9182 transaction.data = "";
9183 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9184
9185 // We just bypass the cache.
9186 EXPECT_EQ(0U, headers.find("HTTP/1.1 304 Not Modified\n"));
9187 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9188 EXPECT_EQ(0, cache.disk_cache()->open_count());
9189 EXPECT_EQ(1, cache.disk_cache()->create_count());
9190
9191 RunTransactionTest(cache.http_cache(), transaction);
9192 EXPECT_EQ(2, cache.disk_cache()->create_count());
9193 }
9194
9195 // Tests that we can handle non-range requests when we have cached a range.
TEST_F(HttpCacheTest,GET_Previous206)9196 TEST_F(HttpCacheTest, GET_Previous206) {
9197 MockHttpCache cache;
9198 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9199 std::string headers;
9200 NetLogWithSource net_log_with_source =
9201 NetLogWithSource::Make(NetLogSourceType::NONE);
9202 LoadTimingInfo load_timing_info;
9203
9204 // Write to the cache (40-49).
9205 RunTransactionTestWithResponseAndGetTiming(
9206 cache.http_cache(), kRangeGET_TransactionOK, &headers,
9207 net_log_with_source, &load_timing_info);
9208
9209 Verify206Response(headers, 40, 49);
9210 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9211 EXPECT_EQ(0, cache.disk_cache()->open_count());
9212 EXPECT_EQ(1, cache.disk_cache()->create_count());
9213 TestLoadTimingNetworkRequest(load_timing_info);
9214
9215 // Write and read from the cache (0-79), when not asked for a range.
9216 MockTransaction transaction(kRangeGET_TransactionOK);
9217 transaction.request_headers = EXTRA_HEADER;
9218 transaction.data = kFullRangeData;
9219 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9220 &headers, net_log_with_source,
9221 &load_timing_info);
9222
9223 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9224 EXPECT_EQ(3, cache.network_layer()->transaction_count());
9225 EXPECT_EQ(1, cache.disk_cache()->open_count());
9226 EXPECT_EQ(1, cache.disk_cache()->create_count());
9227 TestLoadTimingNetworkRequest(load_timing_info);
9228 }
9229
9230 // Tests that we can handle non-range requests when we have cached the first
9231 // part of the object and the server replies with 304 (Not Modified).
TEST_F(HttpCacheTest,GET_Previous206_NotModified)9232 TEST_F(HttpCacheTest, GET_Previous206_NotModified) {
9233 MockHttpCache cache;
9234
9235 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9236 std::string headers;
9237 NetLogWithSource net_log_with_source =
9238 NetLogWithSource::Make(NetLogSourceType::NONE);
9239
9240 LoadTimingInfo load_timing_info;
9241
9242 // Write to the cache (0-9).
9243 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
9244 transaction.data = "rg: 00-09 ";
9245 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9246 &headers, net_log_with_source,
9247 &load_timing_info);
9248 Verify206Response(headers, 0, 9);
9249 TestLoadTimingNetworkRequest(load_timing_info);
9250
9251 // Write to the cache (70-79).
9252 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
9253 transaction.data = "rg: 70-79 ";
9254 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9255 &headers, net_log_with_source,
9256 &load_timing_info);
9257 Verify206Response(headers, 70, 79);
9258
9259 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9260 EXPECT_EQ(1, cache.disk_cache()->open_count());
9261 EXPECT_EQ(1, cache.disk_cache()->create_count());
9262 TestLoadTimingNetworkRequest(load_timing_info);
9263
9264 // Read from the cache (0-9), write and read from cache (10 - 79).
9265 transaction.load_flags |= LOAD_VALIDATE_CACHE;
9266 transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER;
9267 transaction.data = kFullRangeData;
9268 RunTransactionTestWithResponseAndGetTiming(cache.http_cache(), transaction,
9269 &headers, net_log_with_source,
9270 &load_timing_info);
9271
9272 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9273 EXPECT_EQ(4, cache.network_layer()->transaction_count());
9274 EXPECT_EQ(2, cache.disk_cache()->open_count());
9275 EXPECT_EQ(1, cache.disk_cache()->create_count());
9276 TestLoadTimingNetworkRequest(load_timing_info);
9277 }
9278
9279 // Tests that we can handle a regular request to a sparse entry, that results in
9280 // new content provided by the server (206).
TEST_F(HttpCacheTest,GET_Previous206_NewContent)9281 TEST_F(HttpCacheTest, GET_Previous206_NewContent) {
9282 MockHttpCache cache;
9283 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9284 std::string headers;
9285
9286 // Write to the cache (0-9).
9287 MockTransaction transaction(kRangeGET_TransactionOK);
9288 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
9289 transaction.data = "rg: 00-09 ";
9290 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9291
9292 Verify206Response(headers, 0, 9);
9293 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9294 EXPECT_EQ(0, cache.disk_cache()->open_count());
9295 EXPECT_EQ(1, cache.disk_cache()->create_count());
9296
9297 // Now we'll issue a request without any range that should result first in a
9298 // 206 (when revalidating), and then in a weird standard answer: the test
9299 // server will not modify the response so we'll get the default range... a
9300 // real server will answer with 200.
9301 MockTransaction transaction2(kRangeGET_TransactionOK);
9302 transaction2.request_headers = EXTRA_HEADER;
9303 transaction2.load_flags |= LOAD_VALIDATE_CACHE;
9304 transaction2.data = "Not a range";
9305 RangeTransactionServer handler;
9306 handler.set_modified(true);
9307 LoadTimingInfo load_timing_info;
9308 RunTransactionTestWithResponseAndGetTiming(
9309 cache.http_cache(), transaction2, &headers,
9310 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
9311
9312 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
9313 EXPECT_EQ(3, cache.network_layer()->transaction_count());
9314 EXPECT_EQ(1, cache.disk_cache()->open_count());
9315 EXPECT_EQ(1, cache.disk_cache()->create_count());
9316 TestLoadTimingNetworkRequest(load_timing_info);
9317
9318 // Verify that the previous request deleted the entry.
9319 RunTransactionTest(cache.http_cache(), transaction);
9320 EXPECT_EQ(2, cache.disk_cache()->create_count());
9321 }
9322
9323 // Tests that we can handle cached 206 responses that are not sparse.
TEST_F(HttpCacheTest,GET_Previous206_NotSparse)9324 TEST_F(HttpCacheTest, GET_Previous206_NotSparse) {
9325 MockHttpCache cache;
9326
9327 MockHttpRequest request(kSimpleGET_Transaction);
9328 // Create a disk cache entry that stores 206 headers while not being sparse.
9329 disk_cache::Entry* entry;
9330 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9331
9332 std::string raw_headers(kRangeGET_TransactionOK.status);
9333 raw_headers.append("\n");
9334 raw_headers.append(kRangeGET_TransactionOK.response_headers);
9335
9336 HttpResponseInfo response;
9337 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9338 HttpUtil::AssembleRawHeaders(raw_headers));
9339 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9340
9341 auto buf(base::MakeRefCounted<IOBufferWithSize>(500));
9342 int len = static_cast<int>(
9343 base::strlcpy(buf->data(), kRangeGET_TransactionOK.data, 500));
9344 TestCompletionCallback cb;
9345 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9346 EXPECT_EQ(len, cb.GetResult(rv));
9347 entry->Close();
9348
9349 // Now see that we don't use the stored entry.
9350 std::string headers;
9351 LoadTimingInfo load_timing_info;
9352 RunTransactionTestWithResponseAndGetTiming(
9353 cache.http_cache(), kSimpleGET_Transaction, &headers,
9354 NetLogWithSource::Make(NetLogSourceType::NONE), &load_timing_info);
9355
9356 // We are expecting a 200.
9357 std::string expected_headers(kSimpleGET_Transaction.status);
9358 expected_headers.append("\n");
9359 expected_headers.append(kSimpleGET_Transaction.response_headers);
9360 EXPECT_EQ(expected_headers, headers);
9361 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9362 EXPECT_EQ(1, cache.disk_cache()->open_count());
9363 EXPECT_EQ(2, cache.disk_cache()->create_count());
9364 TestLoadTimingNetworkRequest(load_timing_info);
9365 }
9366
9367 // Tests that we can handle cached 206 responses that are not sparse. This time
9368 // we issue a range request and expect to receive a range.
TEST_F(HttpCacheTest,RangeGET_Previous206_NotSparse_2)9369 TEST_F(HttpCacheTest, RangeGET_Previous206_NotSparse_2) {
9370 MockHttpCache cache;
9371 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9372
9373 // Create a disk cache entry that stores 206 headers while not being sparse.
9374 MockHttpRequest request(kRangeGET_TransactionOK);
9375 disk_cache::Entry* entry;
9376 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9377
9378 std::string raw_headers(kRangeGET_TransactionOK.status);
9379 raw_headers.append("\n");
9380 raw_headers.append(kRangeGET_TransactionOK.response_headers);
9381
9382 HttpResponseInfo response;
9383 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9384 HttpUtil::AssembleRawHeaders(raw_headers));
9385 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9386
9387 auto buf = base::MakeRefCounted<IOBufferWithSize>(500);
9388 int len = static_cast<int>(
9389 base::strlcpy(buf->data(), kRangeGET_TransactionOK.data, 500));
9390 TestCompletionCallback cb;
9391 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9392 EXPECT_EQ(len, cb.GetResult(rv));
9393 entry->Close();
9394
9395 // Now see that we don't use the stored entry.
9396 std::string headers;
9397 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9398 &headers);
9399
9400 // We are expecting a 206.
9401 Verify206Response(headers, 40, 49);
9402 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9403 EXPECT_EQ(1, cache.disk_cache()->open_count());
9404 EXPECT_EQ(2, cache.disk_cache()->create_count());
9405 }
9406
9407 // Tests that we can handle cached 206 responses that can't be validated.
TEST_F(HttpCacheTest,GET_Previous206_NotValidation)9408 TEST_F(HttpCacheTest, GET_Previous206_NotValidation) {
9409 MockHttpCache cache;
9410
9411 MockHttpRequest request(kSimpleGET_Transaction);
9412 // Create a disk cache entry that stores 206 headers.
9413 disk_cache::Entry* entry;
9414 ASSERT_TRUE(cache.CreateBackendEntry(request.CacheKey(), &entry, nullptr));
9415
9416 // Make sure that the headers cannot be validated with the server.
9417 std::string raw_headers(kRangeGET_TransactionOK.status);
9418 raw_headers.append("\n");
9419 raw_headers.append("Content-Length: 80\n");
9420
9421 HttpResponseInfo response;
9422 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
9423 HttpUtil::AssembleRawHeaders(raw_headers));
9424 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
9425
9426 auto buf = base::MakeRefCounted<IOBufferWithSize>(500);
9427 int len = static_cast<int>(
9428 base::strlcpy(buf->data(), kRangeGET_TransactionOK.data, 500));
9429 TestCompletionCallback cb;
9430 int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true);
9431 EXPECT_EQ(len, cb.GetResult(rv));
9432 entry->Close();
9433
9434 // Now see that we don't use the stored entry.
9435 std::string headers;
9436 RunTransactionTestWithResponse(cache.http_cache(), kSimpleGET_Transaction,
9437 &headers);
9438
9439 // We are expecting a 200.
9440 std::string expected_headers(kSimpleGET_Transaction.status);
9441 expected_headers.append("\n");
9442 expected_headers.append(kSimpleGET_Transaction.response_headers);
9443 EXPECT_EQ(expected_headers, headers);
9444 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9445 EXPECT_EQ(1, cache.disk_cache()->open_count());
9446 EXPECT_EQ(2, cache.disk_cache()->create_count());
9447 }
9448
9449 // Tests that we can handle range requests with cached 200 responses.
TEST_F(HttpCacheTest,RangeGET_Previous200)9450 TEST_F(HttpCacheTest, RangeGET_Previous200) {
9451 MockHttpCache cache;
9452
9453 {
9454 // Store the whole thing with status 200.
9455 ScopedMockTransaction transaction(kTypicalGET_Transaction,
9456 kRangeGET_TransactionOK.url);
9457 transaction.data = kFullRangeData;
9458 RunTransactionTest(cache.http_cache(), transaction);
9459 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9460 EXPECT_EQ(0, cache.disk_cache()->open_count());
9461 EXPECT_EQ(1, cache.disk_cache()->create_count());
9462 }
9463
9464 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9465 // Now see that we use the stored entry.
9466 std::string headers;
9467 MockTransaction transaction2(kRangeGET_TransactionOK);
9468 RangeTransactionServer handler;
9469 handler.set_not_modified(true);
9470 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9471
9472 // We are expecting a 206.
9473 Verify206Response(headers, 40, 49);
9474 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9475 EXPECT_EQ(1, cache.disk_cache()->open_count());
9476 EXPECT_EQ(1, cache.disk_cache()->create_count());
9477
9478 // The last transaction has finished so make sure the entry is deactivated.
9479 base::RunLoop().RunUntilIdle();
9480
9481 // Make a request for an invalid range.
9482 MockTransaction transaction3(kRangeGET_TransactionOK);
9483 transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER;
9484 transaction3.data = kFullRangeData;
9485 transaction3.load_flags = LOAD_SKIP_CACHE_VALIDATION;
9486 RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers);
9487 EXPECT_EQ(2, cache.disk_cache()->open_count());
9488 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 "));
9489 EXPECT_EQ(std::string::npos, headers.find("Content-Range:"));
9490 EXPECT_EQ(std::string::npos, headers.find("Content-Length: 80"));
9491
9492 // Make sure the entry is deactivated.
9493 base::RunLoop().RunUntilIdle();
9494
9495 // Even though the request was invalid, we should have the entry.
9496 RunTransactionTest(cache.http_cache(), transaction2);
9497 EXPECT_EQ(3, cache.disk_cache()->open_count());
9498
9499 // Make sure the entry is deactivated.
9500 base::RunLoop().RunUntilIdle();
9501
9502 // Now we should receive a range from the server and drop the stored entry.
9503 handler.set_not_modified(false);
9504 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
9505 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9506 Verify206Response(headers, 40, 49);
9507 EXPECT_EQ(4, cache.network_layer()->transaction_count());
9508 EXPECT_EQ(4, cache.disk_cache()->open_count());
9509 EXPECT_EQ(1, cache.disk_cache()->create_count());
9510
9511 RunTransactionTest(cache.http_cache(), transaction2);
9512 EXPECT_EQ(2, cache.disk_cache()->create_count());
9513 }
9514
9515 // Tests that we can handle a 200 response when dealing with sparse entries.
TEST_F(HttpCacheTest,RangeRequestResultsIn200)9516 TEST_F(HttpCacheTest, RangeRequestResultsIn200) {
9517 MockHttpCache cache;
9518 std::string headers;
9519
9520 {
9521 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9522 // Write to the cache (70-79).
9523 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
9524 transaction.data = "rg: 70-79 ";
9525 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9526
9527 Verify206Response(headers, 70, 79);
9528 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9529 EXPECT_EQ(0, cache.disk_cache()->open_count());
9530 EXPECT_EQ(1, cache.disk_cache()->create_count());
9531 }
9532 // Now we'll issue a request that results in a plain 200 response, but to
9533 // the to the same URL that we used to store sparse data, and making sure
9534 // that we ask for a range.
9535 ScopedMockTransaction transaction2(kSimpleGET_Transaction,
9536 kRangeGET_TransactionOK.url);
9537 transaction2.request_headers = kRangeGET_TransactionOK.request_headers;
9538
9539 RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers);
9540
9541 std::string expected_headers(kSimpleGET_Transaction.status);
9542 expected_headers.append("\n");
9543 expected_headers.append(kSimpleGET_Transaction.response_headers);
9544 EXPECT_EQ(expected_headers, headers);
9545 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9546 EXPECT_EQ(1, cache.disk_cache()->open_count());
9547 EXPECT_EQ(1, cache.disk_cache()->create_count());
9548 }
9549
9550 // Tests that a range request that falls outside of the size that we know about
9551 // only deletes the entry if the resource has indeed changed.
TEST_F(HttpCacheTest,RangeGET_MoreThanCurrentSize)9552 TEST_F(HttpCacheTest, RangeGET_MoreThanCurrentSize) {
9553 MockHttpCache cache;
9554 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9555 std::string headers;
9556
9557 // Write to the cache (40-49).
9558 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9559 &headers);
9560
9561 Verify206Response(headers, 40, 49);
9562 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9563 EXPECT_EQ(0, cache.disk_cache()->open_count());
9564 EXPECT_EQ(1, cache.disk_cache()->create_count());
9565
9566 // A weird request should not delete this entry. Ask for bytes 120-.
9567 MockTransaction transaction(kRangeGET_TransactionOK);
9568 transaction.request_headers = "Range: bytes = 120-\r\n" EXTRA_HEADER;
9569 transaction.data = "";
9570 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9571
9572 EXPECT_EQ(0U, headers.find("HTTP/1.1 416 "));
9573 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9574 EXPECT_EQ(1, cache.disk_cache()->open_count());
9575 EXPECT_EQ(1, cache.disk_cache()->create_count());
9576
9577 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9578 EXPECT_EQ(2, cache.disk_cache()->open_count());
9579 EXPECT_EQ(1, cache.disk_cache()->create_count());
9580 }
9581
9582 // Tests that we don't delete a sparse entry when we cancel a request.
TEST_F(HttpCacheTest,RangeGET_Cancel)9583 TEST_F(HttpCacheTest, RangeGET_Cancel) {
9584 MockHttpCache cache;
9585 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9586
9587 MockHttpRequest request(kRangeGET_TransactionOK);
9588
9589 auto c = std::make_unique<Context>();
9590 int rv = cache.CreateTransaction(&c->trans);
9591 ASSERT_THAT(rv, IsOk());
9592
9593 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9594 if (rv == ERR_IO_PENDING) {
9595 rv = c->callback.WaitForResult();
9596 }
9597
9598 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9599 EXPECT_EQ(0, cache.disk_cache()->open_count());
9600 EXPECT_EQ(1, cache.disk_cache()->create_count());
9601
9602 // Make sure that the entry has some data stored.
9603 scoped_refptr<IOBufferWithSize> buf =
9604 base::MakeRefCounted<IOBufferWithSize>(10);
9605 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9606 if (rv == ERR_IO_PENDING) {
9607 rv = c->callback.WaitForResult();
9608 }
9609 EXPECT_EQ(buf->size(), rv);
9610
9611 // Destroy the transaction.
9612 c.reset();
9613
9614 // Verify that the entry has not been deleted.
9615 disk_cache::Entry* entry;
9616 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9617 entry->Close();
9618 }
9619
9620 // Tests that we don't mark an entry as truncated if it is partial and not
9621 // already truncated.
TEST_F(HttpCacheTest,RangeGET_CancelWhileReading)9622 TEST_F(HttpCacheTest, RangeGET_CancelWhileReading) {
9623 MockHttpCache cache;
9624 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9625
9626 MockHttpRequest request(kRangeGET_TransactionOK);
9627
9628 auto context = std::make_unique<Context>();
9629 int rv = cache.CreateTransaction(&context->trans);
9630 ASSERT_THAT(rv, IsOk());
9631
9632 rv = context->trans->Start(&request, context->callback.callback(),
9633 NetLogWithSource());
9634 if (rv == ERR_IO_PENDING) {
9635 rv = context->callback.WaitForResult();
9636 }
9637
9638 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9639 EXPECT_EQ(0, cache.disk_cache()->open_count());
9640 EXPECT_EQ(1, cache.disk_cache()->create_count());
9641
9642 // Start Read.
9643 scoped_refptr<IOBufferWithSize> buf =
9644 base::MakeRefCounted<IOBufferWithSize>(5);
9645 rv = context->trans->Read(buf.get(), buf->size(),
9646 context->callback.callback());
9647 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9648
9649 // Destroy the transaction.
9650 context.reset();
9651
9652 // Complete Read.
9653 base::RunLoop().RunUntilIdle();
9654
9655 // Verify that the entry has not been marked as truncated.
9656 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 0);
9657 }
9658
9659 // Tests that we don't delete a sparse entry when we start a new request after
9660 // cancelling the previous one.
TEST_F(HttpCacheTest,RangeGET_Cancel2)9661 TEST_F(HttpCacheTest, RangeGET_Cancel2) {
9662 MockHttpCache cache;
9663 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9664
9665 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9666 MockHttpRequest request(kRangeGET_TransactionOK);
9667 request.load_flags |= LOAD_VALIDATE_CACHE;
9668
9669 auto c = std::make_unique<Context>();
9670 int rv = cache.CreateTransaction(&c->trans);
9671 ASSERT_THAT(rv, IsOk());
9672
9673 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9674 if (rv == ERR_IO_PENDING) {
9675 rv = c->callback.WaitForResult();
9676 }
9677
9678 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9679 EXPECT_EQ(1, cache.disk_cache()->open_count());
9680 EXPECT_EQ(1, cache.disk_cache()->create_count());
9681
9682 // Make sure that we revalidate the entry and read from the cache (a single
9683 // read will return while waiting for the network).
9684 scoped_refptr<IOBufferWithSize> buf =
9685 base::MakeRefCounted<IOBufferWithSize>(5);
9686 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9687 EXPECT_EQ(5, c->callback.GetResult(rv));
9688 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9689 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9690
9691 // Destroy the transaction before completing the read.
9692 c.reset();
9693
9694 // We have the read and the delete (OnProcessPendingQueue) waiting on the
9695 // message loop. This means that a new transaction will just reuse the same
9696 // active entry (no open or create).
9697
9698 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9699
9700 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9701 EXPECT_EQ(1, cache.disk_cache()->open_count());
9702 EXPECT_EQ(1, cache.disk_cache()->create_count());
9703 }
9704
9705 // A slight variation of the previous test, this time we cancel two requests in
9706 // a row, making sure that the second is waiting for the entry to be ready.
TEST_F(HttpCacheTest,RangeGET_Cancel3)9707 TEST_F(HttpCacheTest, RangeGET_Cancel3) {
9708 MockHttpCache cache;
9709 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
9710
9711 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9712 MockHttpRequest request(kRangeGET_TransactionOK);
9713 request.load_flags |= LOAD_VALIDATE_CACHE;
9714
9715 auto c = std::make_unique<Context>();
9716 int rv = cache.CreateTransaction(&c->trans);
9717 ASSERT_THAT(rv, IsOk());
9718
9719 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9720 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9721 rv = c->callback.WaitForResult();
9722
9723 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9724 EXPECT_EQ(1, cache.disk_cache()->open_count());
9725 EXPECT_EQ(1, cache.disk_cache()->create_count());
9726
9727 // Make sure that we revalidate the entry and read from the cache (a single
9728 // read will return while waiting for the network).
9729 scoped_refptr<IOBufferWithSize> buf =
9730 base::MakeRefCounted<IOBufferWithSize>(5);
9731 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9732 EXPECT_EQ(5, c->callback.GetResult(rv));
9733 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
9734 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9735
9736 // Destroy the previous transaction before completing the read.
9737 c.reset();
9738
9739 // We have the read and the delete (OnProcessPendingQueue) waiting on the
9740 // message loop. This means that a new transaction will just reuse the same
9741 // active entry (no open or create).
9742
9743 c = std::make_unique<Context>();
9744 rv = cache.CreateTransaction(&c->trans);
9745 ASSERT_THAT(rv, IsOk());
9746
9747 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
9748 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9749
9750 MockDiskEntry::IgnoreCallbacks(true);
9751 base::RunLoop().RunUntilIdle();
9752 MockDiskEntry::IgnoreCallbacks(false);
9753
9754 // The new transaction is waiting for the query range callback.
9755 c.reset();
9756
9757 // And we should not crash when the callback is delivered.
9758 base::RunLoop().RunUntilIdle();
9759
9760 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9761 EXPECT_EQ(1, cache.disk_cache()->open_count());
9762 EXPECT_EQ(1, cache.disk_cache()->create_count());
9763 }
9764
9765 // Tests that an invalid range response results in no cached entry.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse1)9766 TEST_F(HttpCacheTest, RangeGET_InvalidResponse1) {
9767 MockHttpCache cache;
9768 std::string headers;
9769
9770 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9771 transaction.handler = MockTransactionHandler();
9772 transaction.response_headers =
9773 "Content-Range: bytes 40-49/45\n"
9774 "Content-Length: 10\n";
9775 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9776
9777 std::string expected(transaction.status);
9778 expected.append("\n");
9779 expected.append(transaction.response_headers);
9780 EXPECT_EQ(expected, headers);
9781
9782 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9783 EXPECT_EQ(0, cache.disk_cache()->open_count());
9784 EXPECT_EQ(1, cache.disk_cache()->create_count());
9785
9786 // Verify that we don't have a cached entry.
9787 disk_cache::Entry* entry;
9788 MockHttpRequest request(transaction);
9789 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9790 }
9791
9792 // Tests that we reject a range that doesn't match the content-length.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse2)9793 TEST_F(HttpCacheTest, RangeGET_InvalidResponse2) {
9794 MockHttpCache cache;
9795 std::string headers;
9796
9797 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9798 transaction.handler = MockTransactionHandler();
9799 transaction.response_headers =
9800 "Content-Range: bytes 40-49/80\n"
9801 "Content-Length: 20\n";
9802 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9803
9804 std::string expected(transaction.status);
9805 expected.append("\n");
9806 expected.append(transaction.response_headers);
9807 EXPECT_EQ(expected, headers);
9808
9809 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9810 EXPECT_EQ(0, cache.disk_cache()->open_count());
9811 EXPECT_EQ(1, cache.disk_cache()->create_count());
9812
9813 // Verify that we don't have a cached entry.
9814 disk_cache::Entry* entry;
9815 MockHttpRequest request(transaction);
9816 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
9817 }
9818
9819 // Tests that if a server tells us conflicting information about a resource we
9820 // drop the entry.
TEST_F(HttpCacheTest,RangeGET_InvalidResponse3)9821 TEST_F(HttpCacheTest, RangeGET_InvalidResponse3) {
9822 MockHttpCache cache;
9823 std::string headers;
9824 {
9825 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9826 transaction.handler = MockTransactionHandler();
9827 transaction.request_headers = "Range: bytes = 50-59\r\n" EXTRA_HEADER;
9828 std::string response_headers(transaction.response_headers);
9829 response_headers.append("Content-Range: bytes 50-59/160\n");
9830 transaction.response_headers = response_headers.c_str();
9831 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9832
9833 Verify206Response(headers, 50, 59);
9834 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9835 EXPECT_EQ(0, cache.disk_cache()->open_count());
9836 EXPECT_EQ(1, cache.disk_cache()->create_count());
9837 }
9838 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9839
9840 // This transaction will report a resource size of 80 bytes, and we think it's
9841 // 160 so we should ignore the response.
9842 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
9843 &headers);
9844
9845 Verify206Response(headers, 40, 49);
9846 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9847 EXPECT_EQ(1, cache.disk_cache()->open_count());
9848 EXPECT_EQ(1, cache.disk_cache()->create_count());
9849
9850 // Verify that the entry is gone.
9851 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9852 EXPECT_EQ(1, cache.disk_cache()->open_count());
9853 EXPECT_EQ(2, cache.disk_cache()->create_count());
9854 }
9855
9856 // Tests that we handle large range values properly.
TEST_F(HttpCacheTest,RangeGET_LargeValues)9857 TEST_F(HttpCacheTest, RangeGET_LargeValues) {
9858 // We need a real sparse cache for this test.
9859 MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024));
9860 std::string headers;
9861
9862 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9863 transaction.handler = MockTransactionHandler();
9864 transaction.request_headers =
9865 "Range: bytes = 4294967288-4294967297\r\n" EXTRA_HEADER;
9866 transaction.response_headers =
9867 "ETag: \"foo\"\n"
9868 "Content-Range: bytes 4294967288-4294967297/4294967299\n"
9869 "Content-Length: 10\n";
9870 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9871
9872 std::string expected(transaction.status);
9873 expected.append("\n");
9874 expected.append(transaction.response_headers);
9875 EXPECT_EQ(expected, headers);
9876
9877 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9878
9879 // Verify that we have a cached entry.
9880 disk_cache::Entry* en;
9881 MockHttpRequest request(transaction);
9882 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &en));
9883 en->Close();
9884 }
9885
9886 // Tests that we don't crash with a range request if the disk cache was not
9887 // initialized properly.
TEST_F(HttpCacheTest,RangeGET_NoDiskCache)9888 TEST_F(HttpCacheTest, RangeGET_NoDiskCache) {
9889 auto factory = std::make_unique<MockBlockingBackendFactory>();
9890 factory->set_fail(true);
9891 factory->FinishCreation(); // We'll complete synchronously.
9892 MockHttpCache cache(std::move(factory));
9893
9894 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9895
9896 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9897 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9898 }
9899
9900 // Tests that we handle byte range requests that skip the cache.
TEST_F(HttpCacheTest,RangeHEAD)9901 TEST_F(HttpCacheTest, RangeHEAD) {
9902 MockHttpCache cache;
9903 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9904 transaction.request_headers = "Range: bytes = -10\r\n" EXTRA_HEADER;
9905 transaction.method = "HEAD";
9906 transaction.data = "rg: 70-79 ";
9907
9908 std::string headers;
9909 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
9910
9911 Verify206Response(headers, 70, 79);
9912 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9913 EXPECT_EQ(0, cache.disk_cache()->open_count());
9914 EXPECT_EQ(0, cache.disk_cache()->create_count());
9915 }
9916
9917 // Tests that we don't crash when after reading from the cache we issue a
9918 // request for the next range and the server gives us a 200 synchronously.
TEST_F(HttpCacheTest,RangeGET_FastFlakyServer)9919 TEST_F(HttpCacheTest, RangeGET_FastFlakyServer) {
9920 MockHttpCache cache;
9921
9922 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9923 transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER;
9924 transaction.test_mode = TEST_MODE_SYNC_NET_START;
9925 transaction.load_flags |= LOAD_VALIDATE_CACHE;
9926
9927 // Write to the cache.
9928 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9929
9930 // And now read from the cache and the network.
9931 RangeTransactionServer handler;
9932 handler.set_bad_200(true);
9933 transaction.data = "Not a range";
9934 RecordingNetLogObserver net_log_observer;
9935 RunTransactionTestWithLog(cache.http_cache(), transaction,
9936 NetLogWithSource::Make(NetLogSourceType::NONE));
9937
9938 EXPECT_EQ(3, cache.network_layer()->transaction_count());
9939 EXPECT_EQ(1, cache.disk_cache()->open_count());
9940 EXPECT_EQ(1, cache.disk_cache()->create_count());
9941 EXPECT_TRUE(LogContainsEventType(
9942 net_log_observer, NetLogEventType::HTTP_CACHE_RE_SEND_PARTIAL_REQUEST));
9943 }
9944
9945 // Tests that when the server gives us less data than expected, we don't keep
9946 // asking for more data.
TEST_F(HttpCacheTest,RangeGET_FastFlakyServer2)9947 TEST_F(HttpCacheTest, RangeGET_FastFlakyServer2) {
9948 MockHttpCache cache;
9949
9950 // First, check with an empty cache (WRITE mode).
9951 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9952 transaction.request_headers = "Range: bytes = 40-49\r\n" EXTRA_HEADER;
9953 transaction.data = "rg: 40-"; // Less than expected.
9954 transaction.handler = MockTransactionHandler();
9955 std::string headers(transaction.response_headers);
9956 headers.append("Content-Range: bytes 40-49/80\n");
9957 transaction.response_headers = headers.c_str();
9958
9959 // Write to the cache.
9960 RunTransactionTest(cache.http_cache(), transaction);
9961
9962 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9963 EXPECT_EQ(0, cache.disk_cache()->open_count());
9964 EXPECT_EQ(1, cache.disk_cache()->create_count());
9965
9966 // Now verify that even in READ_WRITE mode, we forward the bad response to
9967 // the caller.
9968 transaction.request_headers = "Range: bytes = 60-69\r\n" EXTRA_HEADER;
9969 transaction.data = "rg: 60-"; // Less than expected.
9970 headers = kRangeGET_TransactionOK.response_headers;
9971 headers.append("Content-Range: bytes 60-69/80\n");
9972 transaction.response_headers = headers.c_str();
9973
9974 RunTransactionTest(cache.http_cache(), transaction);
9975
9976 EXPECT_EQ(2, cache.network_layer()->transaction_count());
9977 EXPECT_EQ(1, cache.disk_cache()->open_count());
9978 EXPECT_EQ(1, cache.disk_cache()->create_count());
9979 }
9980
TEST_F(HttpCacheTest,RangeGET_OK_LoadOnlyFromCache)9981 TEST_F(HttpCacheTest, RangeGET_OK_LoadOnlyFromCache) {
9982 MockHttpCache cache;
9983 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
9984
9985 // Write to the cache (40-49).
9986 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
9987 EXPECT_EQ(1, cache.network_layer()->transaction_count());
9988 EXPECT_EQ(0, cache.disk_cache()->open_count());
9989 EXPECT_EQ(1, cache.disk_cache()->create_count());
9990
9991 // Force this transaction to read from the cache.
9992 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
9993
9994 MockHttpRequest request(transaction);
9995 TestCompletionCallback callback;
9996
9997 std::unique_ptr<HttpTransaction> trans;
9998 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
9999 EXPECT_THAT(rv, IsOk());
10000 ASSERT_TRUE(trans.get());
10001
10002 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
10003 if (rv == ERR_IO_PENDING) {
10004 rv = callback.WaitForResult();
10005 }
10006 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
10007
10008 trans.reset();
10009
10010 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10011 EXPECT_EQ(1, cache.disk_cache()->open_count());
10012 EXPECT_EQ(1, cache.disk_cache()->create_count());
10013 }
10014
10015 // Tests the handling of the "truncation" flag.
TEST_F(HttpCacheTest,WriteResponseInfo_Truncated)10016 TEST_F(HttpCacheTest, WriteResponseInfo_Truncated) {
10017 MockHttpCache cache;
10018 disk_cache::Entry* entry;
10019 ASSERT_TRUE(cache.CreateBackendEntry(
10020 GenerateCacheKey("http://www.google.com"), &entry, nullptr));
10021
10022 HttpResponseInfo response;
10023 response.headers = base::MakeRefCounted<HttpResponseHeaders>(
10024 HttpUtil::AssembleRawHeaders("HTTP/1.1 200 OK"));
10025
10026 // Set the last argument for this to be an incomplete request.
10027 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true));
10028 bool truncated = false;
10029 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
10030 EXPECT_TRUE(truncated);
10031
10032 // And now test the opposite case.
10033 EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false));
10034 truncated = true;
10035 EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated));
10036 EXPECT_FALSE(truncated);
10037 entry->Close();
10038 }
10039
10040 // Tests basic pickling/unpickling of HttpResponseInfo.
TEST_F(HttpCacheTest,PersistHttpResponseInfo)10041 TEST_F(HttpCacheTest, PersistHttpResponseInfo) {
10042 const IPEndPoint expected_endpoint = IPEndPoint(IPAddress(1, 2, 3, 4), 80);
10043 // Set some fields (add more if needed.)
10044 HttpResponseInfo response1;
10045 response1.was_cached = false;
10046 response1.remote_endpoint = expected_endpoint;
10047 response1.headers =
10048 base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
10049
10050 // Pickle.
10051 base::Pickle pickle;
10052 response1.Persist(&pickle, false, false);
10053
10054 // Unpickle.
10055 HttpResponseInfo response2;
10056 bool response_truncated;
10057 EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated));
10058 EXPECT_FALSE(response_truncated);
10059
10060 // Verify fields.
10061 EXPECT_TRUE(response2.was_cached); // InitFromPickle sets this flag.
10062 EXPECT_EQ(expected_endpoint, response2.remote_endpoint);
10063 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
10064 }
10065
10066 // Tests that we delete an entry when the request is cancelled before starting
10067 // to read from the network.
TEST_F(HttpCacheTest,DoomOnDestruction)10068 TEST_F(HttpCacheTest, DoomOnDestruction) {
10069 MockHttpCache cache;
10070
10071 MockHttpRequest request(kSimpleGET_Transaction);
10072
10073 auto c = std::make_unique<Context>();
10074 int rv = cache.CreateTransaction(&c->trans);
10075 ASSERT_THAT(rv, IsOk());
10076
10077 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10078 if (rv == ERR_IO_PENDING) {
10079 c->result = c->callback.WaitForResult();
10080 }
10081
10082 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10083 EXPECT_EQ(0, cache.disk_cache()->open_count());
10084 EXPECT_EQ(1, cache.disk_cache()->create_count());
10085
10086 // Destroy the transaction. We only have the headers so we should delete this
10087 // entry.
10088 c.reset();
10089
10090 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10091
10092 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10093 EXPECT_EQ(0, cache.disk_cache()->open_count());
10094 EXPECT_EQ(2, cache.disk_cache()->create_count());
10095 }
10096
10097 // Tests that we delete an entry when the request is cancelled if the response
10098 // does not have content-length and strong validators.
TEST_F(HttpCacheTest,DoomOnDestruction2)10099 TEST_F(HttpCacheTest, DoomOnDestruction2) {
10100 MockHttpCache cache;
10101
10102 MockHttpRequest request(kSimpleGET_Transaction);
10103
10104 auto c = std::make_unique<Context>();
10105 int rv = cache.CreateTransaction(&c->trans);
10106 ASSERT_THAT(rv, IsOk());
10107
10108 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10109 if (rv == ERR_IO_PENDING) {
10110 rv = c->callback.WaitForResult();
10111 }
10112
10113 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10114 EXPECT_EQ(0, cache.disk_cache()->open_count());
10115 EXPECT_EQ(1, cache.disk_cache()->create_count());
10116
10117 // Make sure that the entry has some data stored.
10118 scoped_refptr<IOBufferWithSize> buf =
10119 base::MakeRefCounted<IOBufferWithSize>(10);
10120 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10121 if (rv == ERR_IO_PENDING) {
10122 rv = c->callback.WaitForResult();
10123 }
10124 EXPECT_EQ(buf->size(), rv);
10125
10126 // Destroy the transaction.
10127 c.reset();
10128
10129 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10130
10131 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10132 EXPECT_EQ(0, cache.disk_cache()->open_count());
10133 EXPECT_EQ(2, cache.disk_cache()->create_count());
10134 }
10135
10136 // Tests that we delete an entry when the request is cancelled if the response
10137 // has an "Accept-Ranges: none" header.
TEST_F(HttpCacheTest,DoomOnDestruction3)10138 TEST_F(HttpCacheTest, DoomOnDestruction3) {
10139 MockHttpCache cache;
10140
10141 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10142 transaction.response_headers =
10143 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10144 "Content-Length: 22\n"
10145 "Accept-Ranges: none\n"
10146 "Etag: \"foopy\"\n";
10147 MockHttpRequest request(transaction);
10148
10149 auto c = std::make_unique<Context>();
10150 int rv = cache.CreateTransaction(&c->trans);
10151 ASSERT_THAT(rv, IsOk());
10152
10153 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10154 if (rv == ERR_IO_PENDING) {
10155 rv = c->callback.WaitForResult();
10156 }
10157
10158 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10159 EXPECT_EQ(0, cache.disk_cache()->open_count());
10160 EXPECT_EQ(1, cache.disk_cache()->create_count());
10161
10162 // Make sure that the entry has some data stored.
10163 scoped_refptr<IOBufferWithSize> buf =
10164 base::MakeRefCounted<IOBufferWithSize>(10);
10165 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10166 if (rv == ERR_IO_PENDING) {
10167 rv = c->callback.WaitForResult();
10168 }
10169 EXPECT_EQ(buf->size(), rv);
10170
10171 // Destroy the transaction.
10172 c.reset();
10173
10174 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
10175
10176 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10177 EXPECT_EQ(0, cache.disk_cache()->open_count());
10178 EXPECT_EQ(2, cache.disk_cache()->create_count());
10179 }
10180
10181 // Tests that we mark an entry as incomplete when the request is cancelled.
TEST_F(HttpCacheTest,SetTruncatedFlag)10182 TEST_F(HttpCacheTest, SetTruncatedFlag) {
10183 MockHttpCache cache;
10184
10185 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10186 transaction.response_headers =
10187 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10188 "Content-Length: 22\n"
10189 "Etag: \"foopy\"\n";
10190 MockHttpRequest request(transaction);
10191
10192 auto c = std::make_unique<Context>();
10193
10194 int rv = cache.CreateTransaction(&c->trans);
10195 ASSERT_THAT(rv, IsOk());
10196
10197 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10198 if (rv == ERR_IO_PENDING) {
10199 rv = c->callback.WaitForResult();
10200 }
10201
10202 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10203 EXPECT_EQ(0, cache.disk_cache()->open_count());
10204 EXPECT_EQ(1, cache.disk_cache()->create_count());
10205
10206 // Make sure that the entry has some data stored.
10207 scoped_refptr<IOBufferWithSize> buf =
10208 base::MakeRefCounted<IOBufferWithSize>(10);
10209 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10210 if (rv == ERR_IO_PENDING) {
10211 rv = c->callback.WaitForResult();
10212 }
10213 EXPECT_EQ(buf->size(), rv);
10214
10215 // We want to cancel the request when the transaction is busy.
10216 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10217 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10218 EXPECT_FALSE(c->callback.have_result());
10219
10220 // Destroy the transaction.
10221 c->trans.reset();
10222
10223 // Make sure that we don't invoke the callback. We may have an issue if the
10224 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
10225 // could end up with the transaction being deleted twice if we send any
10226 // notification from the transaction destructor (see http://crbug.com/31723).
10227 EXPECT_FALSE(c->callback.have_result());
10228
10229 base::RunLoop().RunUntilIdle();
10230 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 0);
10231 }
10232
10233 // Tests that we do not mark an entry as truncated when the request is
10234 // cancelled.
TEST_F(HttpCacheTest,DontSetTruncatedFlagForGarbledResponseCode)10235 TEST_F(HttpCacheTest, DontSetTruncatedFlagForGarbledResponseCode) {
10236 MockHttpCache cache;
10237
10238 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10239 transaction.response_headers =
10240 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10241 "Content-Length: 22\n"
10242 "Etag: \"foopy\"\n";
10243 transaction.status = "HTTP/1.1 2";
10244 MockHttpRequest request(transaction);
10245
10246 auto c = std::make_unique<Context>();
10247
10248 int rv = cache.CreateTransaction(&c->trans);
10249 ASSERT_THAT(rv, IsOk());
10250
10251 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10252 if (rv == ERR_IO_PENDING) {
10253 rv = c->callback.WaitForResult();
10254 }
10255
10256 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10257 EXPECT_EQ(0, cache.disk_cache()->open_count());
10258 EXPECT_EQ(1, cache.disk_cache()->create_count());
10259
10260 // Make sure that the entry has some data stored.
10261 scoped_refptr<IOBufferWithSize> buf =
10262 base::MakeRefCounted<IOBufferWithSize>(10);
10263 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10264 if (rv == ERR_IO_PENDING) {
10265 rv = c->callback.WaitForResult();
10266 }
10267 EXPECT_EQ(buf->size(), rv);
10268
10269 // We want to cancel the request when the transaction is busy.
10270 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10271 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10272 EXPECT_FALSE(c->callback.have_result());
10273
10274 MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL);
10275
10276 // Destroy the transaction.
10277 c->trans.reset();
10278 MockHttpCache::SetTestMode(0);
10279
10280 // Make sure that we don't invoke the callback. We may have an issue if the
10281 // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we
10282 // could end up with the transaction being deleted twice if we send any
10283 // notification from the transaction destructor (see http://crbug.com/31723).
10284 EXPECT_FALSE(c->callback.have_result());
10285
10286 // Verify that the entry is deleted as well, since the response status is
10287 // garbled. Note that the entry will be deleted after the pending Read is
10288 // complete.
10289 base::RunLoop().RunUntilIdle();
10290 disk_cache::Entry* entry;
10291 ASSERT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10292 }
10293
10294 // Tests that we don't mark an entry as truncated when we read everything.
TEST_F(HttpCacheTest,DontSetTruncatedFlag)10295 TEST_F(HttpCacheTest, DontSetTruncatedFlag) {
10296 MockHttpCache cache;
10297
10298 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10299 transaction.response_headers =
10300 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
10301 "Content-Length: 22\n"
10302 "Etag: \"foopy\"\n";
10303 MockHttpRequest request(transaction);
10304
10305 auto c = std::make_unique<Context>();
10306 int rv = cache.CreateTransaction(&c->trans);
10307 ASSERT_THAT(rv, IsOk());
10308
10309 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10310 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10311
10312 // Read everything.
10313 scoped_refptr<IOBufferWithSize> buf =
10314 base::MakeRefCounted<IOBufferWithSize>(22);
10315 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10316 EXPECT_EQ(buf->size(), c->callback.GetResult(rv));
10317
10318 // Destroy the transaction.
10319 c->trans.reset();
10320
10321 // Verify that the entry is not marked as truncated.
10322 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 0);
10323 }
10324
10325 // Tests that sparse entries don't set the truncate flag.
TEST_F(HttpCacheTest,RangeGET_DontTruncate)10326 TEST_F(HttpCacheTest, RangeGET_DontTruncate) {
10327 MockHttpCache cache;
10328
10329 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10330 transaction.request_headers = "Range: bytes = 0-19\r\n" EXTRA_HEADER;
10331
10332 auto request = std::make_unique<MockHttpRequest>(transaction);
10333 std::unique_ptr<HttpTransaction> trans;
10334
10335 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
10336 EXPECT_THAT(rv, IsOk());
10337
10338 TestCompletionCallback cb;
10339 rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
10340 EXPECT_EQ(0, cb.GetResult(rv));
10341
10342 auto buf = base::MakeRefCounted<IOBufferWithSize>(10);
10343 rv = trans->Read(buf.get(), 10, cb.callback());
10344 EXPECT_EQ(10, cb.GetResult(rv));
10345
10346 // Should not trigger any DCHECK.
10347 trans.reset();
10348 VerifyTruncatedFlag(&cache, request->CacheKey(), false, 0);
10349 }
10350
10351 // Tests that sparse entries don't set the truncate flag (when the byte range
10352 // starts after 0).
TEST_F(HttpCacheTest,RangeGET_DontTruncate2)10353 TEST_F(HttpCacheTest, RangeGET_DontTruncate2) {
10354 MockHttpCache cache;
10355
10356 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10357 transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
10358
10359 auto request = std::make_unique<MockHttpRequest>(transaction);
10360 std::unique_ptr<HttpTransaction> trans;
10361
10362 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
10363 EXPECT_THAT(rv, IsOk());
10364
10365 TestCompletionCallback cb;
10366 rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
10367 EXPECT_EQ(0, cb.GetResult(rv));
10368
10369 auto buf = base::MakeRefCounted<IOBufferWithSize>(10);
10370 rv = trans->Read(buf.get(), 10, cb.callback());
10371 EXPECT_EQ(10, cb.GetResult(rv));
10372
10373 // Should not trigger any DCHECK.
10374 trans.reset();
10375 VerifyTruncatedFlag(&cache, request->CacheKey(), false, 0);
10376 }
10377
10378 // Tests that we can continue with a request that was interrupted.
TEST_F(HttpCacheTest,GET_IncompleteResource)10379 TEST_F(HttpCacheTest, GET_IncompleteResource) {
10380 MockHttpCache cache;
10381 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10382
10383 std::string raw_headers(
10384 "HTTP/1.1 200 OK\n"
10385 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10386 "ETag: \"foo\"\n"
10387 "Accept-Ranges: bytes\n"
10388 "Content-Length: 80\n");
10389 CreateTruncatedEntry(raw_headers, &cache);
10390
10391 // Now make a regular request.
10392 std::string headers;
10393 transaction.request_headers = EXTRA_HEADER;
10394 transaction.data = kFullRangeData;
10395 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10396
10397 // We update the headers with the ones received while revalidating.
10398 std::string expected_headers(
10399 "HTTP/1.1 200 OK\n"
10400 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10401 "Accept-Ranges: bytes\n"
10402 "ETag: \"foo\"\n"
10403 "Content-Length: 80\n");
10404
10405 EXPECT_EQ(expected_headers, headers);
10406 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10407 EXPECT_EQ(1, cache.disk_cache()->open_count());
10408 EXPECT_EQ(1, cache.disk_cache()->create_count());
10409
10410 // Verify that the disk entry was updated.
10411 MockHttpRequest request(transaction);
10412 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 80);
10413 }
10414
10415 // Tests the handling of no-store when revalidating a truncated entry.
TEST_F(HttpCacheTest,GET_IncompleteResource_NoStore)10416 TEST_F(HttpCacheTest, GET_IncompleteResource_NoStore) {
10417 MockHttpCache cache;
10418 {
10419 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
10420
10421 std::string raw_headers(
10422 "HTTP/1.1 200 OK\n"
10423 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10424 "ETag: \"foo\"\n"
10425 "Accept-Ranges: bytes\n"
10426 "Content-Length: 80\n");
10427 CreateTruncatedEntry(raw_headers, &cache);
10428 }
10429
10430 // Now make a regular request.
10431 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10432 transaction.request_headers = EXTRA_HEADER;
10433 std::string response_headers(transaction.response_headers);
10434 response_headers += ("Cache-Control: no-store\n");
10435 transaction.response_headers = response_headers.c_str();
10436 transaction.data = kFullRangeData;
10437
10438 std::string headers;
10439 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10440
10441 // We update the headers with the ones received while revalidating.
10442 std::string expected_headers(
10443 "HTTP/1.1 200 OK\n"
10444 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10445 "Accept-Ranges: bytes\n"
10446 "Cache-Control: no-store\n"
10447 "ETag: \"foo\"\n"
10448 "Content-Length: 80\n");
10449
10450 EXPECT_EQ(expected_headers, headers);
10451 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10452 EXPECT_EQ(1, cache.disk_cache()->open_count());
10453 EXPECT_EQ(1, cache.disk_cache()->create_count());
10454
10455 // Verify that the disk entry was deleted.
10456 disk_cache::Entry* entry;
10457 MockHttpRequest request(transaction);
10458 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10459 }
10460
10461 // Tests cancelling a request after the server sent no-store.
TEST_F(HttpCacheTest,GET_IncompleteResource_Cancel)10462 TEST_F(HttpCacheTest, GET_IncompleteResource_Cancel) {
10463 MockHttpCache cache;
10464 {
10465 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
10466 std::string raw_headers(
10467 "HTTP/1.1 200 OK\n"
10468 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10469 "ETag: \"foo\"\n"
10470 "Accept-Ranges: bytes\n"
10471 "Content-Length: 80\n");
10472 CreateTruncatedEntry(raw_headers, &cache);
10473 }
10474
10475 // Now make a regular request.
10476 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10477 transaction.request_headers = EXTRA_HEADER;
10478 std::string response_headers(transaction.response_headers);
10479 response_headers += ("Cache-Control: no-store\n");
10480 transaction.response_headers = response_headers.c_str();
10481 transaction.data = kFullRangeData;
10482
10483 MockHttpRequest request(transaction);
10484 auto c = std::make_unique<Context>();
10485
10486 int rv = cache.CreateTransaction(&c->trans);
10487 ASSERT_THAT(rv, IsOk());
10488
10489 // Queue another request to this transaction. We have to start this request
10490 // before the first one gets the response from the server and dooms the entry,
10491 // otherwise it will just create a new entry without being queued to the first
10492 // request.
10493 auto pending = std::make_unique<Context>();
10494 ASSERT_THAT(cache.CreateTransaction(&pending->trans), IsOk());
10495
10496 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10497 EXPECT_EQ(ERR_IO_PENDING,
10498 pending->trans->Start(&request, pending->callback.callback(),
10499 NetLogWithSource()));
10500 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10501
10502 // Make sure that the entry has some data stored.
10503 scoped_refptr<IOBufferWithSize> buf =
10504 base::MakeRefCounted<IOBufferWithSize>(5);
10505 rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback());
10506 EXPECT_EQ(5, c->callback.GetResult(rv));
10507
10508 // Since |pending| is currently validating the already written headers
10509 // it will be restarted as well.
10510 c.reset();
10511 pending.reset();
10512
10513 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10514 EXPECT_EQ(1, cache.disk_cache()->open_count());
10515 EXPECT_EQ(1, cache.disk_cache()->create_count());
10516
10517 base::RunLoop().RunUntilIdle();
10518 }
10519
10520 // Tests that we delete truncated entries if the server changes its mind midway.
TEST_F(HttpCacheTest,GET_IncompleteResource2)10521 TEST_F(HttpCacheTest, GET_IncompleteResource2) {
10522 MockHttpCache cache;
10523 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
10524 // Content-length will be intentionally bad.
10525 std::string raw_headers(
10526 "HTTP/1.1 200 OK\n"
10527 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10528 "ETag: \"foo\"\n"
10529 "Accept-Ranges: bytes\n"
10530 "Content-Length: 50\n");
10531 CreateTruncatedEntry(raw_headers, &cache);
10532
10533 // Now make a regular request. We expect the code to fail the validation and
10534 // retry the request without using byte ranges.
10535 std::string headers;
10536 MockTransaction transaction(kRangeGET_TransactionOK);
10537 transaction.request_headers = EXTRA_HEADER;
10538 transaction.data = "Not a range";
10539 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10540
10541 // The server will return 200 instead of a byte range.
10542 std::string expected_headers(
10543 "HTTP/1.1 200 OK\n"
10544 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
10545
10546 EXPECT_EQ(expected_headers, headers);
10547 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10548 EXPECT_EQ(1, cache.disk_cache()->open_count());
10549 EXPECT_EQ(1, cache.disk_cache()->create_count());
10550
10551 // Verify that the disk entry was deleted.
10552 disk_cache::Entry* entry;
10553 MockHttpRequest request(transaction);
10554 ASSERT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10555 }
10556
10557 // Tests that we always validate a truncated request.
TEST_F(HttpCacheTest,GET_IncompleteResource3)10558 TEST_F(HttpCacheTest, GET_IncompleteResource3) {
10559 MockHttpCache cache;
10560 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
10561
10562 // This should not require validation for 10 hours.
10563 std::string raw_headers(
10564 "HTTP/1.1 200 OK\n"
10565 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10566 "ETag: \"foo\"\n"
10567 "Cache-Control: max-age= 36000\n"
10568 "Accept-Ranges: bytes\n"
10569 "Content-Length: 80\n");
10570 CreateTruncatedEntry(raw_headers, &cache);
10571
10572 // Now make a regular request.
10573 std::string headers;
10574 MockTransaction transaction(kRangeGET_TransactionOK);
10575 transaction.request_headers = EXTRA_HEADER;
10576 transaction.data = kFullRangeData;
10577
10578 auto c = std::make_unique<Context>();
10579 int rv = cache.CreateTransaction(&c->trans);
10580 ASSERT_THAT(rv, IsOk());
10581
10582 MockHttpRequest request(transaction);
10583 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10584 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10585
10586 // We should have checked with the server before finishing Start().
10587 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10588 EXPECT_EQ(1, cache.disk_cache()->open_count());
10589 EXPECT_EQ(1, cache.disk_cache()->create_count());
10590 }
10591
10592 // Tests that we handle 401s for truncated resources.
TEST_F(HttpCacheTest,GET_IncompleteResourceWithAuth)10593 TEST_F(HttpCacheTest, GET_IncompleteResourceWithAuth) {
10594 MockHttpCache cache;
10595 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
10596
10597 std::string raw_headers(
10598 "HTTP/1.1 200 OK\n"
10599 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
10600 "ETag: \"foo\"\n"
10601 "Accept-Ranges: bytes\n"
10602 "Content-Length: 80\n");
10603 CreateTruncatedEntry(raw_headers, &cache);
10604
10605 // Now make a regular request.
10606 MockTransaction transaction(kRangeGET_TransactionOK);
10607 transaction.request_headers = "X-Require-Mock-Auth: dummy\r\n" EXTRA_HEADER;
10608 transaction.data = kFullRangeData;
10609 RangeTransactionServer handler;
10610
10611 auto c = std::make_unique<Context>();
10612 int rv = cache.CreateTransaction(&c->trans);
10613 ASSERT_THAT(rv, IsOk());
10614
10615 MockHttpRequest request(transaction);
10616 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10617 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10618
10619 const HttpResponseInfo* response = c->trans->GetResponseInfo();
10620 ASSERT_TRUE(response);
10621 ASSERT_EQ(401, response->headers->response_code());
10622 rv = c->trans->RestartWithAuth(AuthCredentials(), c->callback.callback());
10623 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10624 response = c->trans->GetResponseInfo();
10625 ASSERT_TRUE(response);
10626 ASSERT_EQ(200, response->headers->response_code());
10627
10628 ReadAndVerifyTransaction(c->trans.get(), transaction);
10629 c.reset(); // The destructor could delete the entry.
10630 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10631
10632 // Verify that the entry was deleted.
10633 disk_cache::Entry* entry;
10634 ASSERT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10635 entry->Close();
10636 }
10637
10638 // Test that the transaction won't retry failed partial requests
10639 // after it starts reading data. http://crbug.com/474835
TEST_F(HttpCacheTest,TransactionRetryLimit)10640 TEST_F(HttpCacheTest, TransactionRetryLimit) {
10641 MockHttpCache cache;
10642
10643 // Cache 0-9, so that we have data to read before failing.
10644 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10645 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
10646 transaction.data = "rg: 00-09 ";
10647
10648 // Write to the cache.
10649 RunTransactionTest(cache.http_cache(), transaction);
10650 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10651
10652 // And now read from the cache and the network. 10-19 will get a
10653 // 401, but will have already returned 0-9.
10654 // We do not set X-Require-Mock-Auth because that causes the mock
10655 // network transaction to become IsReadyToRestartForAuth().
10656 transaction.request_headers =
10657 "Range: bytes = 0-79\r\n"
10658 "X-Require-Mock-Auth-Alt: dummy\r\n" EXTRA_HEADER;
10659
10660 auto c = std::make_unique<Context>();
10661 int rv = cache.CreateTransaction(&c->trans);
10662 ASSERT_THAT(rv, IsOk());
10663
10664 MockHttpRequest request(transaction);
10665
10666 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10667 if (rv == ERR_IO_PENDING) {
10668 rv = c->callback.WaitForResult();
10669 }
10670 std::string content;
10671 rv = ReadTransaction(c->trans.get(), &content);
10672 EXPECT_THAT(rv, IsError(ERR_CACHE_AUTH_FAILURE_AFTER_READ));
10673 }
10674
10675 // Tests that we cache a 200 response to the validation request.
TEST_F(HttpCacheTest,GET_IncompleteResource4)10676 TEST_F(HttpCacheTest, GET_IncompleteResource4) {
10677 MockHttpCache cache;
10678 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10679
10680 std::string raw_headers(
10681 "HTTP/1.1 200 OK\n"
10682 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10683 "ETag: \"foo\"\n"
10684 "Accept-Ranges: bytes\n"
10685 "Content-Length: 80\n");
10686 CreateTruncatedEntry(raw_headers, &cache);
10687
10688 // Now make a regular request.
10689 std::string headers;
10690 transaction.request_headers = EXTRA_HEADER;
10691 transaction.data = "Not a range";
10692 RangeTransactionServer handler;
10693 handler.set_bad_200(true);
10694 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
10695
10696 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10697 EXPECT_EQ(1, cache.disk_cache()->open_count());
10698 EXPECT_EQ(1, cache.disk_cache()->create_count());
10699
10700 // Verify that the disk entry was updated.
10701 MockHttpRequest request(transaction);
10702 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 11);
10703 }
10704
10705 // Tests that when we cancel a request that was interrupted, we mark it again
10706 // as truncated.
TEST_F(HttpCacheTest,GET_CancelIncompleteResource)10707 TEST_F(HttpCacheTest, GET_CancelIncompleteResource) {
10708 MockHttpCache cache;
10709 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
10710
10711 std::string raw_headers(
10712 "HTTP/1.1 200 OK\n"
10713 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
10714 "ETag: \"foo\"\n"
10715 "Accept-Ranges: bytes\n"
10716 "Content-Length: 80\n");
10717 CreateTruncatedEntry(raw_headers, &cache);
10718
10719 // Now make a regular request.
10720 transaction.request_headers = EXTRA_HEADER;
10721
10722 MockHttpRequest request(transaction);
10723 auto c = std::make_unique<Context>();
10724 int rv = cache.CreateTransaction(&c->trans);
10725 ASSERT_THAT(rv, IsOk());
10726
10727 rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
10728 EXPECT_THAT(c->callback.GetResult(rv), IsOk());
10729
10730 // Read 20 bytes from the cache, and 10 from the net.
10731 auto buf = base::MakeRefCounted<IOBufferWithSize>(100);
10732 rv = c->trans->Read(buf.get(), 20, c->callback.callback());
10733 EXPECT_EQ(20, c->callback.GetResult(rv));
10734 rv = c->trans->Read(buf.get(), 10, c->callback.callback());
10735 EXPECT_EQ(10, c->callback.GetResult(rv));
10736
10737 // At this point, we are already reading so canceling the request should leave
10738 // a truncated one.
10739 c.reset();
10740
10741 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10742 EXPECT_EQ(1, cache.disk_cache()->open_count());
10743 EXPECT_EQ(1, cache.disk_cache()->create_count());
10744
10745 // Verify that the disk entry was updated: now we have 30 bytes.
10746 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 30);
10747 }
10748
10749 // Tests that we can handle range requests when we have a truncated entry.
TEST_F(HttpCacheTest,RangeGET_IncompleteResource)10750 TEST_F(HttpCacheTest, RangeGET_IncompleteResource) {
10751 MockHttpCache cache;
10752 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
10753
10754 // Content-length will be intentionally bogus.
10755 std::string raw_headers(
10756 "HTTP/1.1 200 OK\n"
10757 "Last-Modified: something\n"
10758 "ETag: \"foo\"\n"
10759 "Accept-Ranges: bytes\n"
10760 "Content-Length: 10\n");
10761 CreateTruncatedEntry(raw_headers, &cache);
10762
10763 // Now make a range request.
10764 std::string headers;
10765 RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
10766 &headers);
10767
10768 Verify206Response(headers, 40, 49);
10769 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10770 EXPECT_EQ(1, cache.disk_cache()->open_count());
10771 EXPECT_EQ(2, cache.disk_cache()->create_count());
10772 }
10773
TEST_F(HttpCacheTest,SyncRead)10774 TEST_F(HttpCacheTest, SyncRead) {
10775 MockHttpCache cache;
10776
10777 // This test ensures that a read that completes synchronously does not cause
10778 // any problems.
10779
10780 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10781 transaction.test_mode |=
10782 (TEST_MODE_SYNC_CACHE_START | TEST_MODE_SYNC_CACHE_READ |
10783 TEST_MODE_SYNC_CACHE_WRITE);
10784
10785 MockHttpRequest r1(transaction), r2(transaction), r3(transaction);
10786
10787 TestTransactionConsumer c1(DEFAULT_PRIORITY, cache.http_cache()),
10788 c2(DEFAULT_PRIORITY, cache.http_cache()),
10789 c3(DEFAULT_PRIORITY, cache.http_cache());
10790
10791 c1.Start(&r1, NetLogWithSource());
10792
10793 r2.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
10794 c2.Start(&r2, NetLogWithSource());
10795
10796 r3.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
10797 c3.Start(&r3, NetLogWithSource());
10798
10799 EXPECT_TRUE(c1.is_done());
10800 EXPECT_TRUE(c2.is_done());
10801 EXPECT_TRUE(c3.is_done());
10802
10803 EXPECT_THAT(c1.error(), IsOk());
10804 EXPECT_THAT(c2.error(), IsOk());
10805 EXPECT_THAT(c3.error(), IsOk());
10806 }
10807
TEST_F(HttpCacheTest,ValidationResultsIn200)10808 TEST_F(HttpCacheTest, ValidationResultsIn200) {
10809 MockHttpCache cache;
10810
10811 // This test ensures that a conditional request, which results in a 200
10812 // instead of a 304, properly truncates the existing response data.
10813
10814 // write to the cache
10815 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
10816
10817 // force this transaction to validate the cache
10818 MockTransaction transaction(kETagGET_Transaction);
10819 transaction.load_flags |= LOAD_VALIDATE_CACHE;
10820 RunTransactionTest(cache.http_cache(), transaction);
10821
10822 // read from the cache
10823 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
10824 }
10825
TEST_F(HttpCacheTest,CachedRedirect)10826 TEST_F(HttpCacheTest, CachedRedirect) {
10827 MockHttpCache cache;
10828
10829 ScopedMockTransaction kTestTransaction(kSimpleGET_Transaction);
10830 kTestTransaction.status = "HTTP/1.1 301 Moved Permanently";
10831 kTestTransaction.response_headers = "Location: http://www.bar.com/\n";
10832
10833 MockHttpRequest request(kTestTransaction);
10834 TestCompletionCallback callback;
10835
10836 // Write to the cache.
10837 {
10838 std::unique_ptr<HttpTransaction> trans;
10839 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
10840
10841 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
10842 if (rv == ERR_IO_PENDING) {
10843 rv = callback.WaitForResult();
10844 }
10845 ASSERT_THAT(rv, IsOk());
10846
10847 const HttpResponseInfo* info = trans->GetResponseInfo();
10848 ASSERT_TRUE(info);
10849
10850 EXPECT_EQ(info->headers->response_code(), 301);
10851
10852 std::string location;
10853 info->headers->EnumerateHeader(nullptr, "Location", &location);
10854 EXPECT_EQ(location, "http://www.bar.com/");
10855
10856 // Mark the transaction as completed so it is cached.
10857 trans->DoneReading();
10858
10859 // Destroy transaction when going out of scope. We have not actually
10860 // read the response body -- want to test that it is still getting cached.
10861 }
10862 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10863 EXPECT_EQ(0, cache.disk_cache()->open_count());
10864 EXPECT_EQ(1, cache.disk_cache()->create_count());
10865
10866 // Active entries in the cache are not retired synchronously. Make
10867 // sure the next run hits the MockHttpCache and open_count is
10868 // correct.
10869 base::RunLoop().RunUntilIdle();
10870
10871 // Read from the cache.
10872 {
10873 std::unique_ptr<HttpTransaction> trans;
10874 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
10875
10876 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
10877 if (rv == ERR_IO_PENDING) {
10878 rv = callback.WaitForResult();
10879 }
10880 ASSERT_THAT(rv, IsOk());
10881
10882 const HttpResponseInfo* info = trans->GetResponseInfo();
10883 ASSERT_TRUE(info);
10884
10885 EXPECT_EQ(info->headers->response_code(), 301);
10886
10887 std::string location;
10888 info->headers->EnumerateHeader(nullptr, "Location", &location);
10889 EXPECT_EQ(location, "http://www.bar.com/");
10890
10891 // Mark the transaction as completed so it is cached.
10892 trans->DoneReading();
10893
10894 // Destroy transaction when going out of scope. We have not actually
10895 // read the response body -- want to test that it is still getting cached.
10896 }
10897 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10898 EXPECT_EQ(1, cache.disk_cache()->open_count());
10899 EXPECT_EQ(1, cache.disk_cache()->create_count());
10900 }
10901
10902 // Verify that no-cache resources are stored in cache, but are not fetched from
10903 // cache during normal loads.
TEST_F(HttpCacheTest,CacheControlNoCacheNormalLoad)10904 TEST_F(HttpCacheTest, CacheControlNoCacheNormalLoad) {
10905 for (bool use_memory_entry_data : {false, true}) {
10906 MockHttpCache cache;
10907 cache.disk_cache()->set_support_in_memory_entry_data(use_memory_entry_data);
10908
10909 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10910 transaction.response_headers = "cache-control: no-cache\n";
10911
10912 // Initial load.
10913 RunTransactionTest(cache.http_cache(), transaction);
10914
10915 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10916 EXPECT_EQ(0, cache.disk_cache()->open_count());
10917 EXPECT_EQ(1, cache.disk_cache()->create_count());
10918
10919 // Try loading again; it should result in a network fetch.
10920 RunTransactionTest(cache.http_cache(), transaction);
10921
10922 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10923 if (use_memory_entry_data) {
10924 EXPECT_EQ(0, cache.disk_cache()->open_count());
10925 EXPECT_EQ(2, cache.disk_cache()->create_count());
10926 } else {
10927 EXPECT_EQ(1, cache.disk_cache()->open_count());
10928 EXPECT_EQ(1, cache.disk_cache()->create_count());
10929 }
10930
10931 disk_cache::Entry* entry;
10932 MockHttpRequest request(transaction);
10933 EXPECT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10934 entry->Close();
10935 }
10936 }
10937
10938 // Verify that no-cache resources are stored in cache and fetched from cache
10939 // when the LOAD_SKIP_CACHE_VALIDATION flag is set.
TEST_F(HttpCacheTest,CacheControlNoCacheHistoryLoad)10940 TEST_F(HttpCacheTest, CacheControlNoCacheHistoryLoad) {
10941 MockHttpCache cache;
10942
10943 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10944 transaction.response_headers = "cache-control: no-cache\n";
10945
10946 // Initial load.
10947 RunTransactionTest(cache.http_cache(), transaction);
10948
10949 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10950 EXPECT_EQ(0, cache.disk_cache()->open_count());
10951 EXPECT_EQ(1, cache.disk_cache()->create_count());
10952
10953 // Try loading again with LOAD_SKIP_CACHE_VALIDATION.
10954 transaction.load_flags = LOAD_SKIP_CACHE_VALIDATION;
10955 RunTransactionTest(cache.http_cache(), transaction);
10956
10957 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10958 EXPECT_EQ(1, cache.disk_cache()->open_count());
10959 EXPECT_EQ(1, cache.disk_cache()->create_count());
10960
10961 disk_cache::Entry* entry;
10962 MockHttpRequest request(transaction);
10963 EXPECT_TRUE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10964 entry->Close();
10965 }
10966
TEST_F(HttpCacheTest,CacheControlNoStore)10967 TEST_F(HttpCacheTest, CacheControlNoStore) {
10968 MockHttpCache cache;
10969
10970 ScopedMockTransaction transaction(kSimpleGET_Transaction);
10971 transaction.response_headers = "cache-control: no-store\n";
10972
10973 // initial load
10974 RunTransactionTest(cache.http_cache(), transaction);
10975
10976 EXPECT_EQ(1, cache.network_layer()->transaction_count());
10977 EXPECT_EQ(0, cache.disk_cache()->open_count());
10978 EXPECT_EQ(1, cache.disk_cache()->create_count());
10979
10980 // try loading again; it should result in a network fetch
10981 RunTransactionTest(cache.http_cache(), transaction);
10982
10983 EXPECT_EQ(2, cache.network_layer()->transaction_count());
10984 EXPECT_EQ(0, cache.disk_cache()->open_count());
10985 EXPECT_EQ(2, cache.disk_cache()->create_count());
10986
10987 disk_cache::Entry* entry;
10988 MockHttpRequest request(transaction);
10989 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
10990 }
10991
TEST_F(HttpCacheTest,CacheControlNoStore2)10992 TEST_F(HttpCacheTest, CacheControlNoStore2) {
10993 // this test is similar to the above test, except that the initial response
10994 // is cachable, but when it is validated, no-store is received causing the
10995 // cached document to be deleted.
10996 MockHttpCache cache;
10997
10998 ScopedMockTransaction transaction(kETagGET_Transaction);
10999
11000 // initial load
11001 RunTransactionTest(cache.http_cache(), transaction);
11002
11003 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11004 EXPECT_EQ(0, cache.disk_cache()->open_count());
11005 EXPECT_EQ(1, cache.disk_cache()->create_count());
11006
11007 // try loading again; it should result in a network fetch
11008 transaction.load_flags = LOAD_VALIDATE_CACHE;
11009 transaction.response_headers = "cache-control: no-store\n";
11010 RunTransactionTest(cache.http_cache(), transaction);
11011
11012 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11013 EXPECT_EQ(1, cache.disk_cache()->open_count());
11014 EXPECT_EQ(1, cache.disk_cache()->create_count());
11015
11016 disk_cache::Entry* entry;
11017 MockHttpRequest request(transaction);
11018 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11019 }
11020
TEST_F(HttpCacheTest,CacheControlNoStore3)11021 TEST_F(HttpCacheTest, CacheControlNoStore3) {
11022 // this test is similar to the above test, except that the response is a 304
11023 // instead of a 200. this should never happen in practice, but it seems like
11024 // a good thing to verify that we still destroy the cache entry.
11025 MockHttpCache cache;
11026
11027 ScopedMockTransaction transaction(kETagGET_Transaction);
11028
11029 // initial load
11030 RunTransactionTest(cache.http_cache(), transaction);
11031
11032 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11033 EXPECT_EQ(0, cache.disk_cache()->open_count());
11034 EXPECT_EQ(1, cache.disk_cache()->create_count());
11035
11036 // try loading again; it should result in a network fetch
11037 transaction.load_flags = LOAD_VALIDATE_CACHE;
11038 transaction.response_headers = "cache-control: no-store\n";
11039 transaction.status = "HTTP/1.1 304 Not Modified";
11040 RunTransactionTest(cache.http_cache(), transaction);
11041
11042 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11043 EXPECT_EQ(1, cache.disk_cache()->open_count());
11044 EXPECT_EQ(1, cache.disk_cache()->create_count());
11045
11046 disk_cache::Entry* entry;
11047 MockHttpRequest request(transaction);
11048 EXPECT_FALSE(cache.OpenBackendEntry(request.CacheKey(), &entry));
11049 }
11050
11051 // Ensure that we don't cache requests served over bad HTTPS.
TEST_F(HttpCacheTest,SimpleGET_SSLError)11052 TEST_F(HttpCacheTest, SimpleGET_SSLError) {
11053 MockHttpCache cache;
11054
11055 MockTransaction transaction = kSimpleGET_Transaction;
11056 transaction.cert_status = CERT_STATUS_REVOKED;
11057 ScopedMockTransaction scoped_transaction(transaction);
11058
11059 // write to the cache
11060 RunTransactionTest(cache.http_cache(), transaction);
11061
11062 // Test that it was not cached.
11063 transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
11064
11065 MockHttpRequest request(transaction);
11066 TestCompletionCallback callback;
11067
11068 std::unique_ptr<HttpTransaction> trans;
11069 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11070
11071 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11072 if (rv == ERR_IO_PENDING) {
11073 rv = callback.WaitForResult();
11074 }
11075 ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
11076 }
11077
11078 // Ensure that we don't crash by if left-behind transactions.
TEST_F(HttpCacheTest,OutlivedTransactions)11079 TEST_F(HttpCacheTest, OutlivedTransactions) {
11080 auto cache = std::make_unique<MockHttpCache>();
11081
11082 std::unique_ptr<HttpTransaction> trans;
11083 EXPECT_THAT(cache->CreateTransaction(&trans), IsOk());
11084
11085 cache.reset();
11086 trans.reset();
11087 }
11088
11089 // Test that the disabled mode works.
TEST_F(HttpCacheTest,CacheDisabledMode)11090 TEST_F(HttpCacheTest, CacheDisabledMode) {
11091 MockHttpCache cache;
11092
11093 // write to the cache
11094 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11095
11096 // go into disabled mode
11097 cache.http_cache()->set_mode(HttpCache::DISABLE);
11098
11099 // force this transaction to write to the cache again
11100 MockTransaction transaction(kSimpleGET_Transaction);
11101
11102 RunTransactionTest(cache.http_cache(), transaction);
11103
11104 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11105 EXPECT_EQ(0, cache.disk_cache()->open_count());
11106 EXPECT_EQ(1, cache.disk_cache()->create_count());
11107 }
11108
11109 // Other tests check that the response headers of the cached response
11110 // get updated on 304. Here we specifically check that the
11111 // HttpResponseHeaders::request_time and HttpResponseHeaders::response_time
11112 // fields also gets updated.
11113 // http://crbug.com/20594.
TEST_F(HttpCacheTest,UpdatesRequestResponseTimeOn304)11114 TEST_F(HttpCacheTest, UpdatesRequestResponseTimeOn304) {
11115 MockHttpCache cache;
11116
11117 const char kUrl[] = "http://foobar";
11118 const char kData[] = "body";
11119
11120 ScopedMockTransaction mock_network_response(kUrl);
11121
11122 // Request |kUrl|, causing |kNetResponse1| to be written to the cache.
11123
11124 MockTransaction request = {nullptr};
11125 request.url = kUrl;
11126 request.method = "GET";
11127 request.request_headers = "\r\n";
11128 request.data = kData;
11129
11130 static const Response kNetResponse1 = {
11131 "HTTP/1.1 200 OK",
11132 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
11133 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
11134 kData};
11135
11136 kNetResponse1.AssignTo(&mock_network_response);
11137
11138 RunTransactionTest(cache.http_cache(), request);
11139
11140 // Request |kUrl| again, this time validating the cache and getting
11141 // a 304 back.
11142
11143 request.load_flags = LOAD_VALIDATE_CACHE;
11144
11145 static const Response kNetResponse2 = {
11146 "HTTP/1.1 304 Not Modified", "Date: Wed, 22 Jul 2009 03:15:26 GMT\n", ""};
11147
11148 kNetResponse2.AssignTo(&mock_network_response);
11149
11150 base::Time request_time = base::Time() + base::Hours(1234);
11151 base::Time response_time = base::Time() + base::Hours(1235);
11152
11153 mock_network_response.request_time = request_time;
11154 mock_network_response.response_time = response_time;
11155
11156 HttpResponseInfo response;
11157 RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response);
11158
11159 // The request and response times should have been updated.
11160 EXPECT_EQ(request_time.ToInternalValue(),
11161 response.request_time.ToInternalValue());
11162 EXPECT_EQ(response_time.ToInternalValue(),
11163 response.response_time.ToInternalValue());
11164
11165 EXPECT_EQ(
11166 "HTTP/1.1 200 OK\n"
11167 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
11168 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
11169 ToSimpleString(response.headers));
11170 }
11171
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCacheWithNetworkIsolationKey)11172 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
11173 SplitCacheWithNetworkIsolationKey) {
11174 MockHttpCache cache;
11175 HttpResponseInfo response;
11176
11177 SchemefulSite site_a(GURL("http://a.com"));
11178 SchemefulSite site_b(GURL("http://b.com"));
11179 SchemefulSite site_data(GURL("data:text/html,<body>Hello World</body>"));
11180
11181 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11182 // Request with a.com as the top frame and subframe origins. This should
11183 // result in a cache miss.
11184 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11185 trans_info.network_anonymization_key =
11186 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11187 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11188 trans_info, &response);
11189 EXPECT_FALSE(response.was_cached);
11190
11191 // The second request should result in a cache hit.
11192 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11193 trans_info, &response);
11194 EXPECT_TRUE(response.was_cached);
11195
11196 // Now request with b.com as the subframe origin. It should result in a cache
11197 // miss.
11198 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_b);
11199 trans_info.network_anonymization_key =
11200 net::NetworkAnonymizationKey::CreateCrossSite(site_a);
11201 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11202 trans_info, &response);
11203 EXPECT_FALSE(response.was_cached);
11204
11205 // The second request should result in a cache hit.
11206 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11207 trans_info, &response);
11208 EXPECT_TRUE(response.was_cached);
11209
11210 // Another request with a.com as the top frame and subframe origin should
11211 // still result in a cache hit.
11212 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11213 trans_info.network_anonymization_key =
11214 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11215 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11216 trans_info, &response);
11217 EXPECT_TRUE(response.was_cached);
11218
11219 // Now make a request with an opaque subframe site. It shouldn't cause
11220 // anything to be added to the cache when the NIK makes use of the frame site.
11221 // Note that we will use `site_b` as the top-level site so that this resource
11222 // won't be in the cache at first regardless of the NIK partitioning scheme.
11223 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_data);
11224 trans_info.network_anonymization_key =
11225 net::NetworkAnonymizationKey::CreateCrossSite(site_b);
11226 switch (GetParam()) {
11227 case SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled:
11228 EXPECT_EQ(std::nullopt,
11229 trans_info.network_isolation_key.ToCacheKeyString());
11230 break;
11231 case SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled:
11232 EXPECT_EQ("http://b.com _1",
11233 trans_info.network_isolation_key.ToCacheKeyString().value());
11234 break;
11235 case SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled:
11236 EXPECT_EQ("http://b.com _opaque",
11237 trans_info.network_isolation_key.ToCacheKeyString().value());
11238 break;
11239 case SplitCacheTestCase::kSplitCacheDisabled:
11240 NOTREACHED_NORETURN();
11241 }
11242
11243 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11244 trans_info, &response);
11245 EXPECT_FALSE(response.was_cached);
11246
11247 // On the second request, expect a cache miss if the NIK uses the frame site.
11248 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11249 trans_info, &response);
11250 switch (GetParam()) {
11251 case SplitCacheTestCase::kSplitCacheNikFrameSiteEnabled:
11252 EXPECT_FALSE(response.was_cached);
11253 break;
11254 case SplitCacheTestCase::kSplitCacheNikCrossSiteFlagEnabled:
11255 case SplitCacheTestCase::kSplitCacheNikFrameSiteSharedOpaqueEnabled:
11256 EXPECT_TRUE(response.was_cached);
11257 break;
11258 case SplitCacheTestCase::kSplitCacheDisabled:
11259 NOTREACHED_NORETURN();
11260 }
11261
11262 // Verify that a post transaction with a data stream uses a separate key.
11263 const int64_t kUploadId = 1; // Just a dummy value.
11264
11265 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11266 element_readers.push_back(
11267 std::make_unique<UploadBytesElementReader>("hello", 5));
11268 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
11269 kUploadId);
11270
11271 MockHttpRequest post_info = MockHttpRequest(kSimplePOST_Transaction);
11272 post_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11273 post_info.network_anonymization_key =
11274 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11275 post_info.upload_data_stream = &upload_data_stream;
11276
11277 RunTransactionTestWithRequest(cache.http_cache(), kSimplePOST_Transaction,
11278 post_info, &response);
11279 EXPECT_FALSE(response.was_cached);
11280 }
11281
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyCSS)11282 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyCSS) {
11283 base::HistogramTester histograms;
11284 MockHttpCache cache;
11285 HttpResponseInfo response;
11286
11287 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11288 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11289 SchemefulSite site_a(origin_a);
11290 SchemefulSite site_b(origin_b);
11291
11292 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11293 transaction.response_headers = "Content-Type: text/css\n";
11294
11295 MockHttpRequest trans_info = MockHttpRequest(transaction);
11296
11297 // Requesting with the same top-frame site should not count as third-party
11298 // but should still be recorded as CSS
11299 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11300 trans_info.network_anonymization_key =
11301 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11302 trans_info.possibly_top_frame_origin = origin_a;
11303
11304 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11305 &response);
11306
11307 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11308 histograms.ExpectTotalCount("HttpCache.Pattern.CSS", 1);
11309 histograms.ExpectTotalCount("HttpCache.Pattern.CSSThirdParty", 0);
11310
11311 // Requesting with a different top-frame site should count as third-party
11312 // and recorded as CSS
11313 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11314 trans_info.network_anonymization_key =
11315 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11316 trans_info.possibly_top_frame_origin = origin_b;
11317
11318 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11319 &response);
11320 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11321 histograms.ExpectTotalCount("HttpCache.Pattern.CSS", 2);
11322 histograms.ExpectTotalCount("HttpCache.Pattern.CSSThirdParty", 1);
11323 }
11324
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyJavaScript)11325 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyJavaScript) {
11326 base::HistogramTester histograms;
11327 MockHttpCache cache;
11328 HttpResponseInfo response;
11329
11330 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11331 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11332 SchemefulSite site_a(origin_a);
11333 SchemefulSite site_b(origin_b);
11334
11335 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11336 transaction.response_headers = "Content-Type: application/javascript\n";
11337
11338 MockHttpRequest trans_info = MockHttpRequest(transaction);
11339
11340 // Requesting with the same top-frame site should not count as third-party
11341 // but should still be recorded as JavaScript
11342 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11343 trans_info.network_anonymization_key =
11344 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11345 trans_info.possibly_top_frame_origin = origin_a;
11346
11347 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11348 &response);
11349
11350 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11351 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScript", 1);
11352 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScriptThirdParty", 0);
11353
11354 // Requesting with a different top-frame site should count as third-party
11355 // and recorded as JavaScript
11356 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11357 trans_info.network_anonymization_key =
11358 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11359 trans_info.possibly_top_frame_origin = origin_b;
11360
11361 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11362 &response);
11363 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11364 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScript", 2);
11365 histograms.ExpectTotalCount("HttpCache.Pattern.JavaScriptThirdParty", 1);
11366 }
11367
TEST_F(HttpCacheTest,HttpCacheProfileThirdPartyFont)11368 TEST_F(HttpCacheTest, HttpCacheProfileThirdPartyFont) {
11369 base::HistogramTester histograms;
11370 MockHttpCache cache;
11371 HttpResponseInfo response;
11372
11373 url::Origin origin_a = url::Origin::Create(GURL(kSimpleGET_Transaction.url));
11374 url::Origin origin_b = url::Origin::Create(GURL("http://b.com"));
11375 SchemefulSite site_a(origin_a);
11376 SchemefulSite site_b(origin_b);
11377
11378 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11379 transaction.response_headers = "Content-Type: font/otf\n";
11380
11381 MockHttpRequest trans_info = MockHttpRequest(transaction);
11382
11383 // Requesting with the same top-frame site should not count as third-party
11384 // but should still be recorded as a font
11385 trans_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11386 trans_info.network_anonymization_key =
11387 net::NetworkAnonymizationKey::CreateSameSite(site_a);
11388 trans_info.possibly_top_frame_origin = origin_a;
11389
11390 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11391 &response);
11392
11393 histograms.ExpectTotalCount("HttpCache.Pattern", 1);
11394 histograms.ExpectTotalCount("HttpCache.Pattern.Font", 1);
11395 histograms.ExpectTotalCount("HttpCache.Pattern.FontThirdParty", 0);
11396
11397 // Requesting with a different top-frame site should count as third-party
11398 // and recorded as a font
11399 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11400 trans_info.network_anonymization_key =
11401 net::NetworkAnonymizationKey::CreateSameSite(site_b);
11402 trans_info.possibly_top_frame_origin = origin_b;
11403
11404 RunTransactionTestWithRequest(cache.http_cache(), transaction, trans_info,
11405 &response);
11406 histograms.ExpectTotalCount("HttpCache.Pattern", 2);
11407 histograms.ExpectTotalCount("HttpCache.Pattern.Font", 2);
11408 histograms.ExpectTotalCount("HttpCache.Pattern.FontThirdParty", 1);
11409 }
11410
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCache)11411 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled, SplitCache) {
11412 MockHttpCache cache;
11413 HttpResponseInfo response;
11414
11415 SchemefulSite site_a(GURL("http://a.com"));
11416 SchemefulSite site_b(GURL("http://b.com"));
11417 SchemefulSite site_data(GURL("data:text/html,<body>Hello World</body>"));
11418
11419 // A request without a top frame origin shouldn't result in anything being
11420 // added to the cache.
11421 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11422 trans_info.network_isolation_key = net::NetworkIsolationKey();
11423 trans_info.network_anonymization_key = net::NetworkAnonymizationKey();
11424 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11425 trans_info, &response);
11426 EXPECT_FALSE(response.was_cached);
11427
11428 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11429 trans_info, &response);
11430 EXPECT_FALSE(response.was_cached);
11431
11432 // Now request with a.com as the top frame origin. This should initially
11433 // result in a cache miss since the cached resource has a different top frame
11434 // origin.
11435 net::NetworkIsolationKey key_a(site_a, site_a);
11436 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11437 trans_info.network_isolation_key = key_a;
11438 trans_info.network_anonymization_key = nak_a;
11439 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11440 trans_info, &response);
11441 EXPECT_FALSE(response.was_cached);
11442
11443 // The second request should result in a cache hit.
11444 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11445 trans_info, &response);
11446 EXPECT_TRUE(response.was_cached);
11447
11448 // If the same resource with the same NIK is for a subframe document resource,
11449 // it should not be a cache hit.
11450 MockHttpRequest subframe_document_trans_info = trans_info;
11451 subframe_document_trans_info.is_subframe_document_resource = true;
11452 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11453 subframe_document_trans_info, &response);
11454 EXPECT_FALSE(response.was_cached);
11455
11456 // Same request again should be a cache hit.
11457 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11458 subframe_document_trans_info, &response);
11459 EXPECT_TRUE(response.was_cached);
11460
11461 // Now request with b.com as the top frame origin. It should be a cache miss.
11462 trans_info.network_isolation_key = NetworkIsolationKey(site_b, site_b);
11463 trans_info.network_anonymization_key =
11464 NetworkAnonymizationKey::CreateSameSite(site_b);
11465 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11466 trans_info, &response);
11467 EXPECT_FALSE(response.was_cached);
11468
11469 // The second request should be a cache hit.
11470 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11471 trans_info, &response);
11472 EXPECT_TRUE(response.was_cached);
11473
11474 // Another request for a.com should still result in a cache hit.
11475 trans_info.network_isolation_key = key_a;
11476 trans_info.network_anonymization_key = nak_a;
11477 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11478 trans_info, &response);
11479 EXPECT_TRUE(response.was_cached);
11480
11481 // Now make a request with an opaque top frame origin. It shouldn't result in
11482 // a cache hit.
11483 trans_info.network_isolation_key = NetworkIsolationKey(site_data, site_data);
11484 trans_info.network_anonymization_key =
11485 NetworkAnonymizationKey::CreateSameSite(site_data);
11486 EXPECT_EQ(std::nullopt, trans_info.network_isolation_key.ToCacheKeyString());
11487 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11488 trans_info, &response);
11489 EXPECT_FALSE(response.was_cached);
11490
11491 // On the second request, it still shouldn't result in a cache hit.
11492 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11493 trans_info, &response);
11494 EXPECT_FALSE(response.was_cached);
11495
11496 // Verify that a post transaction with a data stream uses a separate key.
11497 const int64_t kUploadId = 1; // Just a dummy value.
11498
11499 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
11500 element_readers.push_back(
11501 std::make_unique<UploadBytesElementReader>("hello", 5));
11502 ElementsUploadDataStream upload_data_stream(std::move(element_readers),
11503 kUploadId);
11504
11505 MockHttpRequest post_info = MockHttpRequest(kSimplePOST_Transaction);
11506 post_info.network_isolation_key = NetworkIsolationKey(site_a, site_a);
11507 post_info.network_anonymization_key =
11508 NetworkAnonymizationKey::CreateSameSite(site_a);
11509 post_info.upload_data_stream = &upload_data_stream;
11510
11511 RunTransactionTestWithRequest(cache.http_cache(), kSimplePOST_Transaction,
11512 post_info, &response);
11513 EXPECT_FALSE(response.was_cached);
11514 }
11515
TEST_F(HttpCacheTest,SplitCacheEnabledByDefault)11516 TEST_F(HttpCacheTest, SplitCacheEnabledByDefault) {
11517 HttpCache::ClearGlobalsForTesting();
11518 HttpCache::SplitCacheFeatureEnableByDefault();
11519 EXPECT_TRUE(HttpCache::IsSplitCacheEnabled());
11520
11521 MockHttpCache cache;
11522 HttpResponseInfo response;
11523
11524 SchemefulSite site_a(GURL("http://a.com"));
11525 SchemefulSite site_b(GURL("http://b.com"));
11526 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11527 net::NetworkIsolationKey key_a(site_a, site_a);
11528 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11529 trans_info.network_isolation_key = key_a;
11530 trans_info.network_anonymization_key = nak_a;
11531 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11532 trans_info, &response);
11533 EXPECT_FALSE(response.was_cached);
11534
11535 // Subsequent requests with the same NIK and different NIK will be a cache hit
11536 // and miss respectively.
11537 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11538 trans_info, &response);
11539 EXPECT_TRUE(response.was_cached);
11540
11541 net::NetworkIsolationKey key_b(site_b, site_b);
11542 auto nak_b = net::NetworkAnonymizationKey::CreateSameSite(site_b);
11543 trans_info.network_isolation_key = key_b;
11544 trans_info.network_anonymization_key = nak_b;
11545 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11546 trans_info, &response);
11547 EXPECT_FALSE(response.was_cached);
11548 }
11549
TEST_F(HttpCacheTest,SplitCacheEnabledByDefaultButOverridden)11550 TEST_F(HttpCacheTest, SplitCacheEnabledByDefaultButOverridden) {
11551 HttpCache::ClearGlobalsForTesting();
11552 base::test::ScopedFeatureList feature_list;
11553 feature_list.InitAndDisableFeature(
11554 net::features::kSplitCacheByNetworkIsolationKey);
11555
11556 // Enabling it here should have no effect as it is already overridden.
11557 HttpCache::SplitCacheFeatureEnableByDefault();
11558 EXPECT_FALSE(HttpCache::IsSplitCacheEnabled());
11559 }
11560
TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,SplitCacheUsesRegistrableDomain)11561 TEST_P(HttpCacheTest_SplitCacheFeatureEnabled,
11562 SplitCacheUsesRegistrableDomain) {
11563 MockHttpCache cache;
11564 HttpResponseInfo response;
11565 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11566
11567 SchemefulSite site_a(GURL("http://a.foo.com"));
11568 SchemefulSite site_b(GURL("http://b.foo.com"));
11569
11570 net::NetworkIsolationKey key_a(site_a, site_a);
11571 auto nak_a = net::NetworkAnonymizationKey::CreateSameSite(site_a);
11572 trans_info.network_isolation_key = key_a;
11573 trans_info.network_anonymization_key = nak_a;
11574 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11575 trans_info, &response);
11576 EXPECT_FALSE(response.was_cached);
11577
11578 // The second request with a different origin but the same registrable domain
11579 // should be a cache hit.
11580 net::NetworkIsolationKey key_b(site_b, site_b);
11581 auto nak_b = net::NetworkAnonymizationKey::CreateSameSite(site_b);
11582 trans_info.network_isolation_key = key_b;
11583 trans_info.network_anonymization_key = nak_b;
11584 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11585 trans_info, &response);
11586 EXPECT_TRUE(response.was_cached);
11587
11588 // Request with a different registrable domain. It should be a cache miss.
11589 SchemefulSite new_site_a(GURL("http://a.bar.com"));
11590 net::NetworkIsolationKey new_key_a(new_site_a, new_site_a);
11591 auto new_nak_a = net::NetworkAnonymizationKey::CreateSameSite(new_site_a);
11592 trans_info.network_isolation_key = new_key_a;
11593 trans_info.network_anonymization_key = new_nak_a;
11594 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11595 trans_info, &response);
11596 EXPECT_FALSE(response.was_cached);
11597 }
11598
TEST_F(HttpCacheTest,NonSplitCache)11599 TEST_F(HttpCacheTest, NonSplitCache) {
11600 base::test::ScopedFeatureList feature_list;
11601 feature_list.InitAndDisableFeature(
11602 net::features::kSplitCacheByNetworkIsolationKey);
11603
11604 MockHttpCache cache;
11605 HttpResponseInfo response;
11606
11607 // A request without a top frame is added to the cache normally.
11608 MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction);
11609 trans_info.network_isolation_key = NetworkIsolationKey();
11610 trans_info.network_anonymization_key = NetworkAnonymizationKey();
11611 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11612 trans_info, &response);
11613 EXPECT_FALSE(response.was_cached);
11614
11615 // The second request should result in a cache hit.
11616 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11617 trans_info, &response);
11618 EXPECT_TRUE(response.was_cached);
11619
11620 // Now request with a.com as the top frame origin. The same cached object
11621 // should be used.
11622 const SchemefulSite kSiteA(GURL("http://a.com/"));
11623 trans_info.network_isolation_key = NetworkIsolationKey(kSiteA, kSiteA);
11624 trans_info.network_anonymization_key =
11625 NetworkAnonymizationKey::CreateSameSite(kSiteA);
11626 RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction,
11627 trans_info, &response);
11628 EXPECT_TRUE(response.was_cached);
11629 }
11630
TEST_F(HttpCacheTest,SkipVaryCheck)11631 TEST_F(HttpCacheTest, SkipVaryCheck) {
11632 MockHttpCache cache;
11633
11634 // Write a simple vary transaction to the cache.
11635 HttpResponseInfo response;
11636 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11637 transaction.request_headers = "accept-encoding: gzip\r\n";
11638 transaction.response_headers =
11639 "Vary: accept-encoding\n"
11640 "Cache-Control: max-age=10000\n";
11641 RunTransactionTest(cache.http_cache(), transaction);
11642
11643 // Change the request headers so that the request doesn't match due to vary.
11644 // The request should fail.
11645 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11646 transaction.request_headers = "accept-encoding: foo\r\n";
11647 transaction.start_return_code = ERR_CACHE_MISS;
11648 RunTransactionTest(cache.http_cache(), transaction);
11649
11650 // Change the load flags to ignore vary checks, the request should now hit.
11651 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_VARY_CHECK;
11652 transaction.start_return_code = OK;
11653 RunTransactionTest(cache.http_cache(), transaction);
11654 }
11655
TEST_F(HttpCacheTest,SkipVaryCheckStar)11656 TEST_F(HttpCacheTest, SkipVaryCheckStar) {
11657 MockHttpCache cache;
11658
11659 // Write a simple vary:* transaction to the cache.
11660 HttpResponseInfo response;
11661 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11662 transaction.request_headers = "accept-encoding: gzip\r\n";
11663 transaction.response_headers =
11664 "Vary: *\n"
11665 "Cache-Control: max-age=10000\n";
11666 RunTransactionTest(cache.http_cache(), transaction);
11667
11668 // The request shouldn't match even with the same request headers due to the
11669 // Vary: *. The request should fail.
11670 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11671 transaction.start_return_code = ERR_CACHE_MISS;
11672 RunTransactionTest(cache.http_cache(), transaction);
11673
11674 // Change the load flags to ignore vary checks, the request should now hit.
11675 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_VARY_CHECK;
11676 transaction.start_return_code = OK;
11677 RunTransactionTest(cache.http_cache(), transaction);
11678 }
11679
11680 // Tests that we only return valid entries with LOAD_ONLY_FROM_CACHE
11681 // transactions unless LOAD_SKIP_CACHE_VALIDATION is set.
TEST_F(HttpCacheTest,ValidLoadOnlyFromCache)11682 TEST_F(HttpCacheTest, ValidLoadOnlyFromCache) {
11683 MockHttpCache cache;
11684 base::SimpleTestClock clock;
11685 cache.http_cache()->SetClockForTesting(&clock);
11686 cache.network_layer()->SetClock(&clock);
11687
11688 // Write a resource that will expire in 100 seconds.
11689 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11690 transaction.response_headers = "Cache-Control: max-age=100\n";
11691 RunTransactionTest(cache.http_cache(), transaction);
11692
11693 // Move forward in time such that the cached response is no longer valid.
11694 clock.Advance(base::Seconds(101));
11695
11696 // Skipping cache validation should still return a response.
11697 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
11698 RunTransactionTest(cache.http_cache(), transaction);
11699
11700 // If the cache entry is checked for validitiy, it should fail.
11701 transaction.load_flags = LOAD_ONLY_FROM_CACHE;
11702 transaction.start_return_code = ERR_CACHE_MISS;
11703 RunTransactionTest(cache.http_cache(), transaction);
11704 }
11705
TEST_F(HttpCacheTest,InvalidLoadFlagCombination)11706 TEST_F(HttpCacheTest, InvalidLoadFlagCombination) {
11707 MockHttpCache cache;
11708
11709 // Put the resource in the cache.
11710 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11711
11712 // Now try to fetch it again, but with a flag combination disallowing both
11713 // cache and network access.
11714 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11715 // DevTools relies on this combination of flags for "disable cache" mode
11716 // when a resource is only supposed to be loaded from cache.
11717 transaction.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_BYPASS_CACHE;
11718 transaction.start_return_code = ERR_CACHE_MISS;
11719 RunTransactionTest(cache.http_cache(), transaction);
11720 }
11721
11722 // Tests that we don't mark entries as truncated when a filter detects the end
11723 // of the stream.
TEST_F(HttpCacheTest,FilterCompletion)11724 TEST_F(HttpCacheTest, FilterCompletion) {
11725 MockHttpCache cache;
11726 TestCompletionCallback callback;
11727
11728 {
11729 MockHttpRequest request(kSimpleGET_Transaction);
11730 std::unique_ptr<HttpTransaction> trans;
11731 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11732
11733 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11734 EXPECT_THAT(callback.GetResult(rv), IsOk());
11735
11736 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
11737 rv = trans->Read(buf.get(), 256, callback.callback());
11738 EXPECT_GT(callback.GetResult(rv), 0);
11739
11740 // Now make sure that the entry is preserved.
11741 trans->DoneReading();
11742 }
11743
11744 // Make sure that the ActiveEntry is gone.
11745 base::RunLoop().RunUntilIdle();
11746
11747 // Read from the cache.
11748 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11749
11750 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11751 EXPECT_EQ(1, cache.disk_cache()->open_count());
11752 EXPECT_EQ(1, cache.disk_cache()->create_count());
11753 }
11754
11755 // Tests that we don't mark entries as truncated and release the cache
11756 // entry when DoneReading() is called before any Read() calls, such as
11757 // for a redirect.
TEST_F(HttpCacheTest,DoneReading)11758 TEST_F(HttpCacheTest, DoneReading) {
11759 MockHttpCache cache;
11760 TestCompletionCallback callback;
11761
11762 ScopedMockTransaction transaction(kSimpleGET_Transaction);
11763 transaction.data = "";
11764 MockHttpRequest request(transaction);
11765
11766 std::unique_ptr<HttpTransaction> trans;
11767 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11768
11769 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11770 EXPECT_THAT(callback.GetResult(rv), IsOk());
11771
11772 trans->DoneReading();
11773 // Leave the transaction around.
11774
11775 // Make sure that the ActiveEntry is gone.
11776 base::RunLoop().RunUntilIdle();
11777
11778 // Read from the cache. This should not deadlock.
11779 RunTransactionTest(cache.http_cache(), transaction);
11780
11781 EXPECT_EQ(1, cache.network_layer()->transaction_count());
11782 EXPECT_EQ(1, cache.disk_cache()->open_count());
11783 EXPECT_EQ(1, cache.disk_cache()->create_count());
11784 }
11785
11786 // Tests that we stop caching when told.
TEST_F(HttpCacheTest,StopCachingDeletesEntry)11787 TEST_F(HttpCacheTest, StopCachingDeletesEntry) {
11788 MockHttpCache cache;
11789 TestCompletionCallback callback;
11790 MockHttpRequest request(kSimpleGET_Transaction);
11791
11792 {
11793 std::unique_ptr<HttpTransaction> trans;
11794 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11795
11796 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11797 EXPECT_THAT(callback.GetResult(rv), IsOk());
11798
11799 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
11800 rv = trans->Read(buf.get(), 10, callback.callback());
11801 EXPECT_EQ(10, callback.GetResult(rv));
11802
11803 trans->StopCaching();
11804
11805 // We should be able to keep reading.
11806 rv = trans->Read(buf.get(), 256, callback.callback());
11807 EXPECT_GT(callback.GetResult(rv), 0);
11808 rv = trans->Read(buf.get(), 256, callback.callback());
11809 EXPECT_EQ(0, callback.GetResult(rv));
11810 }
11811
11812 // Make sure that the ActiveEntry is gone.
11813 base::RunLoop().RunUntilIdle();
11814
11815 // Verify that the entry is gone.
11816 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11817
11818 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11819 EXPECT_EQ(0, cache.disk_cache()->open_count());
11820 EXPECT_EQ(2, cache.disk_cache()->create_count());
11821 }
11822
11823 // Tests that we stop caching when told, even if DoneReading is called
11824 // after StopCaching.
TEST_F(HttpCacheTest,StopCachingThenDoneReadingDeletesEntry)11825 TEST_F(HttpCacheTest, StopCachingThenDoneReadingDeletesEntry) {
11826 MockHttpCache cache;
11827 TestCompletionCallback callback;
11828 MockHttpRequest request(kSimpleGET_Transaction);
11829
11830 {
11831 std::unique_ptr<HttpTransaction> trans;
11832 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11833
11834 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11835 EXPECT_THAT(callback.GetResult(rv), IsOk());
11836
11837 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
11838 rv = trans->Read(buf.get(), 10, callback.callback());
11839 EXPECT_EQ(10, callback.GetResult(rv));
11840
11841 trans->StopCaching();
11842
11843 // We should be able to keep reading.
11844 rv = trans->Read(buf.get(), 256, callback.callback());
11845 EXPECT_GT(callback.GetResult(rv), 0);
11846 rv = trans->Read(buf.get(), 256, callback.callback());
11847 EXPECT_EQ(0, callback.GetResult(rv));
11848
11849 // We should be able to call DoneReading.
11850 trans->DoneReading();
11851 }
11852
11853 // Make sure that the ActiveEntry is gone.
11854 base::RunLoop().RunUntilIdle();
11855
11856 // Verify that the entry is gone.
11857 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11858
11859 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11860 EXPECT_EQ(0, cache.disk_cache()->open_count());
11861 EXPECT_EQ(2, cache.disk_cache()->create_count());
11862 }
11863
11864 // Tests that we stop caching when told, when using auth.
TEST_F(HttpCacheTest,StopCachingWithAuthDeletesEntry)11865 TEST_F(HttpCacheTest, StopCachingWithAuthDeletesEntry) {
11866 MockHttpCache cache;
11867 TestCompletionCallback callback;
11868 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
11869 mock_transaction.status = "HTTP/1.1 401 Unauthorized";
11870 MockHttpRequest request(mock_transaction);
11871
11872 {
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 trans->StopCaching();
11880 }
11881
11882 // Make sure that the ActiveEntry is gone.
11883 base::RunLoop().RunUntilIdle();
11884
11885 // Verify that the entry is gone.
11886 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
11887
11888 EXPECT_EQ(2, cache.network_layer()->transaction_count());
11889 EXPECT_EQ(0, cache.disk_cache()->open_count());
11890 EXPECT_EQ(2, cache.disk_cache()->create_count());
11891 }
11892
11893 // Tests that when we are told to stop caching we don't throw away valid data.
TEST_F(HttpCacheTest,StopCachingSavesEntry)11894 TEST_F(HttpCacheTest, StopCachingSavesEntry) {
11895 MockHttpCache cache;
11896 TestCompletionCallback callback;
11897 MockHttpRequest request(kSimpleGET_Transaction);
11898
11899 {
11900 std::unique_ptr<HttpTransaction> trans;
11901 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11902
11903 // Force a response that can be resumed.
11904 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
11905 mock_transaction.response_headers =
11906 "Cache-Control: max-age=10000\n"
11907 "Content-Length: 42\n"
11908 "Etag: \"foo\"\n";
11909
11910 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11911 EXPECT_THAT(callback.GetResult(rv), IsOk());
11912
11913 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
11914 rv = trans->Read(buf.get(), 10, callback.callback());
11915 EXPECT_EQ(callback.GetResult(rv), 10);
11916
11917 trans->StopCaching();
11918
11919 // We should be able to keep reading.
11920 rv = trans->Read(buf.get(), 256, callback.callback());
11921 EXPECT_GT(callback.GetResult(rv), 0);
11922 rv = trans->Read(buf.get(), 256, callback.callback());
11923 EXPECT_EQ(callback.GetResult(rv), 0);
11924 }
11925
11926 // Verify that the entry is marked as incomplete.
11927 // VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0);
11928 // Verify that the entry is doomed.
11929 cache.disk_cache()->IsDiskEntryDoomed(request.CacheKey());
11930 }
11931
11932 // Tests that we handle truncated enries when StopCaching is called.
TEST_F(HttpCacheTest,StopCachingTruncatedEntry)11933 TEST_F(HttpCacheTest, StopCachingTruncatedEntry) {
11934 MockHttpCache cache;
11935 TestCompletionCallback callback;
11936 MockHttpRequest request(kRangeGET_TransactionOK);
11937 request.extra_headers.Clear();
11938 request.extra_headers.AddHeaderFromString(EXTRA_HEADER_LINE);
11939 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
11940
11941 std::string raw_headers(
11942 "HTTP/1.1 200 OK\n"
11943 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
11944 "ETag: \"foo\"\n"
11945 "Accept-Ranges: bytes\n"
11946 "Content-Length: 80\n");
11947 CreateTruncatedEntry(raw_headers, &cache);
11948
11949 {
11950 // Now make a regular request.
11951 std::unique_ptr<HttpTransaction> trans;
11952 ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
11953
11954 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
11955 EXPECT_THAT(callback.GetResult(rv), IsOk());
11956
11957 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
11958 rv = trans->Read(buf.get(), 10, callback.callback());
11959 EXPECT_EQ(callback.GetResult(rv), 10);
11960
11961 // This is actually going to do nothing.
11962 trans->StopCaching();
11963
11964 // We should be able to keep reading.
11965 rv = trans->Read(buf.get(), 256, callback.callback());
11966 EXPECT_GT(callback.GetResult(rv), 0);
11967 rv = trans->Read(buf.get(), 256, callback.callback());
11968 EXPECT_GT(callback.GetResult(rv), 0);
11969 rv = trans->Read(buf.get(), 256, callback.callback());
11970 EXPECT_EQ(callback.GetResult(rv), 0);
11971 }
11972
11973 // Verify that the disk entry was updated.
11974 VerifyTruncatedFlag(&cache, request.CacheKey(), false, 80);
11975 }
11976
11977 namespace {
11978
11979 enum class TransactionPhase {
11980 BEFORE_FIRST_READ,
11981 AFTER_FIRST_READ,
11982 AFTER_NETWORK_READ
11983 };
11984
11985 using CacheInitializer = void (*)(MockHttpCache*);
11986 using HugeCacheTestConfiguration =
11987 std::pair<TransactionPhase, CacheInitializer>;
11988
11989 class HttpCacheHugeResourceTest
11990 : public ::testing::TestWithParam<HugeCacheTestConfiguration>,
11991 public WithTaskEnvironment {
11992 public:
11993 static std::list<HugeCacheTestConfiguration> GetTestModes();
11994 static std::list<HugeCacheTestConfiguration> kTestModes;
11995
11996 // CacheInitializer callbacks. These are used to initialize the cache
11997 // depending on the test run configuration.
11998
11999 // Initializes a cache containing a truncated entry containing the first 20
12000 // bytes of the reponse body.
12001 static void SetupTruncatedCacheEntry(MockHttpCache* cache);
12002
12003 // Initializes a cache containing a sparse entry. The first 10 bytes are
12004 // present in the cache.
12005 static void SetupPrefixSparseCacheEntry(MockHttpCache* cache);
12006
12007 // Initializes a cache containing a sparse entry. The 10 bytes at offset
12008 // 99990 are present in the cache.
12009 static void SetupInfixSparseCacheEntry(MockHttpCache* cache);
12010
12011 protected:
12012 static void LargeResourceTransactionHandler(
12013 const net::HttpRequestInfo* request,
12014 std::string* response_status,
12015 std::string* response_headers,
12016 std::string* response_data);
12017 static int LargeBufferReader(int64_t content_length,
12018 int64_t offset,
12019 net::IOBuffer* buf,
12020 int buf_len);
12021
12022 static void SetFlagOnBeforeNetworkStart(bool* started, bool* /* defer */);
12023
12024 // Size of resource to be tested.
12025 static const int64_t kTotalSize = 5000LL * 1000 * 1000;
12026 };
12027
12028 const int64_t HttpCacheHugeResourceTest::kTotalSize;
12029
12030 // static
LargeResourceTransactionHandler(const net::HttpRequestInfo * request,std::string * response_status,std::string * response_headers,std::string * response_data)12031 void HttpCacheHugeResourceTest::LargeResourceTransactionHandler(
12032 const net::HttpRequestInfo* request,
12033 std::string* response_status,
12034 std::string* response_headers,
12035 std::string* response_data) {
12036 std::string if_range;
12037 if (!request->extra_headers.GetHeader(net::HttpRequestHeaders::kIfRange,
12038 &if_range)) {
12039 // If there were no range headers in the request, we are going to just
12040 // return the entire response body.
12041 *response_status = "HTTP/1.1 200 Success";
12042 *response_headers = base::StringPrintf("Content-Length: %" PRId64
12043 "\n"
12044 "ETag: \"foo\"\n"
12045 "Accept-Ranges: bytes\n",
12046 kTotalSize);
12047 return;
12048 }
12049
12050 // From this point on, we should be processing a valid byte-range request.
12051 EXPECT_EQ("\"foo\"", if_range);
12052
12053 std::string range_header;
12054 EXPECT_TRUE(request->extra_headers.GetHeader(net::HttpRequestHeaders::kRange,
12055 &range_header));
12056 std::vector<net::HttpByteRange> ranges;
12057
12058 EXPECT_TRUE(net::HttpUtil::ParseRangeHeader(range_header, &ranges));
12059 ASSERT_EQ(1u, ranges.size());
12060
12061 net::HttpByteRange range = ranges[0];
12062 EXPECT_TRUE(range.HasFirstBytePosition());
12063 int64_t last_byte_position =
12064 range.HasLastBytePosition() ? range.last_byte_position() : kTotalSize - 1;
12065
12066 *response_status = "HTTP/1.1 206 Partial";
12067 *response_headers = base::StringPrintf(
12068 "Content-Range: bytes %" PRId64 "-%" PRId64 "/%" PRId64
12069 "\n"
12070 "Content-Length: %" PRId64 "\n",
12071 range.first_byte_position(), last_byte_position, kTotalSize,
12072 last_byte_position - range.first_byte_position() + 1);
12073 }
12074
12075 // static
LargeBufferReader(int64_t content_length,int64_t offset,net::IOBuffer * buf,int buf_len)12076 int HttpCacheHugeResourceTest::LargeBufferReader(int64_t content_length,
12077 int64_t offset,
12078 net::IOBuffer* buf,
12079 int buf_len) {
12080 // This test involves reading multiple gigabytes of data. To make it run in a
12081 // reasonable amount of time, we are going to skip filling the buffer with
12082 // data. Instead the test relies on verifying that the count of bytes expected
12083 // at the end is correct.
12084 EXPECT_LT(0, content_length);
12085 EXPECT_LE(offset, content_length);
12086 int num = std::min(static_cast<int64_t>(buf_len), content_length - offset);
12087 return num;
12088 }
12089
12090 // static
SetFlagOnBeforeNetworkStart(bool * started,bool *)12091 void HttpCacheHugeResourceTest::SetFlagOnBeforeNetworkStart(bool* started,
12092 bool* /* defer */) {
12093 *started = true;
12094 }
12095
12096 // static
SetupTruncatedCacheEntry(MockHttpCache * cache)12097 void HttpCacheHugeResourceTest::SetupTruncatedCacheEntry(MockHttpCache* cache) {
12098 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
12099 std::string cached_headers = base::StringPrintf(
12100 "HTTP/1.1 200 OK\n"
12101 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12102 "ETag: \"foo\"\n"
12103 "Accept-Ranges: bytes\n"
12104 "Content-Length: %" PRId64 "\n",
12105 kTotalSize);
12106 CreateTruncatedEntry(cached_headers, cache);
12107 }
12108
12109 // static
SetupPrefixSparseCacheEntry(MockHttpCache * cache)12110 void HttpCacheHugeResourceTest::SetupPrefixSparseCacheEntry(
12111 MockHttpCache* cache) {
12112 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
12113 transaction.handler = MockTransactionHandler();
12114 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
12115 transaction.response_headers =
12116 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12117 "ETag: \"foo\"\n"
12118 "Accept-Ranges: bytes\n"
12119 "Content-Range: bytes 0-9/5000000000\n"
12120 "Content-Length: 10\n";
12121 std::string headers;
12122 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
12123 }
12124
12125 // static
SetupInfixSparseCacheEntry(MockHttpCache * cache)12126 void HttpCacheHugeResourceTest::SetupInfixSparseCacheEntry(
12127 MockHttpCache* cache) {
12128 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
12129 transaction.handler = MockTransactionHandler();
12130 transaction.request_headers = "Range: bytes = 99990-99999\r\n" EXTRA_HEADER;
12131 transaction.response_headers =
12132 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12133 "ETag: \"foo\"\n"
12134 "Accept-Ranges: bytes\n"
12135 "Content-Range: bytes 99990-99999/5000000000\n"
12136 "Content-Length: 10\n";
12137 std::string headers;
12138 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
12139 }
12140
12141 // static
12142 std::list<HugeCacheTestConfiguration>
GetTestModes()12143 HttpCacheHugeResourceTest::GetTestModes() {
12144 std::list<HugeCacheTestConfiguration> test_modes;
12145 const TransactionPhase kTransactionPhases[] = {
12146 TransactionPhase::BEFORE_FIRST_READ, TransactionPhase::AFTER_FIRST_READ,
12147 TransactionPhase::AFTER_NETWORK_READ};
12148 const CacheInitializer kInitializers[] = {&SetupTruncatedCacheEntry,
12149 &SetupPrefixSparseCacheEntry,
12150 &SetupInfixSparseCacheEntry};
12151
12152 for (const auto phase : kTransactionPhases) {
12153 for (const auto initializer : kInitializers) {
12154 test_modes.emplace_back(phase, initializer);
12155 }
12156 }
12157
12158 return test_modes;
12159 }
12160
12161 // static
12162 std::list<HugeCacheTestConfiguration> HttpCacheHugeResourceTest::kTestModes =
12163 HttpCacheHugeResourceTest::GetTestModes();
12164
12165 INSTANTIATE_TEST_SUITE_P(
12166 _,
12167 HttpCacheHugeResourceTest,
12168 ::testing::ValuesIn(HttpCacheHugeResourceTest::kTestModes));
12169
12170 } // namespace
12171
12172 // Test what happens when StopCaching() is called while reading a huge resource
12173 // fetched via GET. Various combinations of cache state and when StopCaching()
12174 // is called is controlled by the parameter passed into the test via the
12175 // INSTANTIATE_TEST_SUITE_P invocation above.
TEST_P(HttpCacheHugeResourceTest,StopCachingFollowedByReadForHugeTruncatedResource)12176 TEST_P(HttpCacheHugeResourceTest,
12177 StopCachingFollowedByReadForHugeTruncatedResource) {
12178 // This test is going to be repeated for all combinations of TransactionPhase
12179 // and CacheInitializers returned by GetTestModes().
12180 const TransactionPhase stop_caching_phase = GetParam().first;
12181 const CacheInitializer cache_initializer = GetParam().second;
12182
12183 MockHttpCache cache;
12184 (*cache_initializer)(&cache);
12185
12186 MockTransaction transaction(kSimpleGET_Transaction);
12187 transaction.url = kRangeGET_TransactionOK.url;
12188 transaction.handler = base::BindRepeating(&LargeResourceTransactionHandler);
12189 transaction.read_handler = base::BindRepeating(&LargeBufferReader);
12190 ScopedMockTransaction scoped_transaction(transaction);
12191
12192 MockHttpRequest request(transaction);
12193 net::TestCompletionCallback callback;
12194 std::unique_ptr<net::HttpTransaction> http_transaction;
12195 int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY,
12196 &http_transaction);
12197 ASSERT_EQ(net::OK, rv);
12198 ASSERT_TRUE(http_transaction.get());
12199
12200 bool network_transaction_started = false;
12201 if (stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
12202 http_transaction->SetBeforeNetworkStartCallback(base::BindOnce(
12203 &SetFlagOnBeforeNetworkStart, &network_transaction_started));
12204 }
12205
12206 rv = http_transaction->Start(&request, callback.callback(),
12207 NetLogWithSource());
12208 rv = callback.GetResult(rv);
12209 ASSERT_EQ(net::OK, rv);
12210
12211 if (stop_caching_phase == TransactionPhase::BEFORE_FIRST_READ) {
12212 http_transaction->StopCaching();
12213 }
12214
12215 int64_t total_bytes_received = 0;
12216
12217 EXPECT_EQ(kTotalSize,
12218 http_transaction->GetResponseInfo()->headers->GetContentLength());
12219 do {
12220 // This test simulates reading gigabytes of data. Buffer size is set to 10MB
12221 // to reduce the number of reads and speed up the test.
12222 const int kBufferSize = 1024 * 1024 * 10;
12223 scoped_refptr<net::IOBuffer> buf =
12224 base::MakeRefCounted<net::IOBufferWithSize>(kBufferSize);
12225 rv = http_transaction->Read(buf.get(), kBufferSize, callback.callback());
12226 rv = callback.GetResult(rv);
12227
12228 if (stop_caching_phase == TransactionPhase::AFTER_FIRST_READ &&
12229 total_bytes_received == 0) {
12230 http_transaction->StopCaching();
12231 }
12232
12233 if (rv > 0) {
12234 total_bytes_received += rv;
12235 }
12236
12237 if (network_transaction_started &&
12238 stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
12239 http_transaction->StopCaching();
12240 network_transaction_started = false;
12241 }
12242 } while (rv > 0);
12243
12244 // The only verification we are going to do is that the received resource has
12245 // the correct size. This is sufficient to verify that the state machine
12246 // didn't terminate abruptly due to the StopCaching() call.
12247 EXPECT_EQ(kTotalSize, total_bytes_received);
12248 }
12249
12250 // Tests that we detect truncated resources from the net when there is
12251 // a Content-Length header.
TEST_F(HttpCacheTest,TruncatedByContentLength)12252 TEST_F(HttpCacheTest, TruncatedByContentLength) {
12253 MockHttpCache cache;
12254 TestCompletionCallback callback;
12255
12256 {
12257 ScopedMockTransaction transaction(kSimpleGET_Transaction);
12258 transaction.response_headers =
12259 "Cache-Control: max-age=10000\n"
12260 "Content-Length: 100\n";
12261 RunTransactionTest(cache.http_cache(), transaction);
12262 }
12263
12264 // Read from the cache.
12265 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
12266
12267 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12268 EXPECT_EQ(0, cache.disk_cache()->open_count());
12269 EXPECT_EQ(2, cache.disk_cache()->create_count());
12270 }
12271
12272 // Tests that we actually flag entries as truncated when we detect an error
12273 // from the net.
TEST_F(HttpCacheTest,TruncatedByContentLength2)12274 TEST_F(HttpCacheTest, TruncatedByContentLength2) {
12275 MockHttpCache cache;
12276 TestCompletionCallback callback;
12277
12278 {
12279 ScopedMockTransaction transaction(kSimpleGET_Transaction);
12280 transaction.response_headers =
12281 "Cache-Control: max-age=10000\n"
12282 "Content-Length: 100\n"
12283 "Etag: \"foo\"\n";
12284 RunTransactionTest(cache.http_cache(), transaction);
12285 }
12286
12287 // Verify that the entry is marked as incomplete.
12288 MockHttpRequest request(kSimpleGET_Transaction);
12289 VerifyTruncatedFlag(&cache, request.CacheKey(), true, 0);
12290 }
12291
12292 // Make sure that calling SetPriority on a cache transaction passes on
12293 // its priority updates to its underlying network transaction.
TEST_F(HttpCacheTest,SetPriority)12294 TEST_F(HttpCacheTest, SetPriority) {
12295 MockHttpCache cache;
12296
12297 HttpRequestInfo info;
12298 std::unique_ptr<HttpTransaction> trans;
12299 ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk());
12300
12301 // Shouldn't crash, but doesn't do anything either.
12302 trans->SetPriority(LOW);
12303
12304 EXPECT_FALSE(cache.network_layer()->last_transaction());
12305 EXPECT_EQ(DEFAULT_PRIORITY,
12306 cache.network_layer()->last_create_transaction_priority());
12307
12308 info.url = GURL(kSimpleGET_Transaction.url);
12309 TestCompletionCallback callback;
12310 EXPECT_EQ(ERR_IO_PENDING,
12311 trans->Start(&info, callback.callback(), NetLogWithSource()));
12312
12313 EXPECT_TRUE(cache.network_layer()->last_transaction());
12314 if (cache.network_layer()->last_transaction()) {
12315 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
12316 EXPECT_EQ(LOW, cache.network_layer()->last_transaction()->priority());
12317 }
12318
12319 trans->SetPriority(HIGHEST);
12320
12321 if (cache.network_layer()->last_transaction()) {
12322 EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
12323 EXPECT_EQ(HIGHEST, cache.network_layer()->last_transaction()->priority());
12324 }
12325
12326 EXPECT_THAT(callback.WaitForResult(), IsOk());
12327 }
12328
12329 // Make sure that calling SetWebSocketHandshakeStreamCreateHelper on a cache
12330 // transaction passes on its argument to the underlying network transaction.
TEST_F(HttpCacheTest,SetWebSocketHandshakeStreamCreateHelper)12331 TEST_F(HttpCacheTest, SetWebSocketHandshakeStreamCreateHelper) {
12332 MockHttpCache cache;
12333 HttpRequestInfo info;
12334
12335 FakeWebSocketHandshakeStreamCreateHelper create_helper;
12336 std::unique_ptr<HttpTransaction> trans;
12337 ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk());
12338
12339 EXPECT_FALSE(cache.network_layer()->last_transaction());
12340
12341 info.url = GURL(kSimpleGET_Transaction.url);
12342 TestCompletionCallback callback;
12343 EXPECT_EQ(ERR_IO_PENDING,
12344 trans->Start(&info, callback.callback(), NetLogWithSource()));
12345
12346 ASSERT_TRUE(cache.network_layer()->last_transaction());
12347 EXPECT_FALSE(cache.network_layer()
12348 ->last_transaction()
12349 ->websocket_handshake_stream_create_helper());
12350 trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper);
12351 EXPECT_EQ(&create_helper, cache.network_layer()
12352 ->last_transaction()
12353 ->websocket_handshake_stream_create_helper());
12354 EXPECT_THAT(callback.WaitForResult(), IsOk());
12355 }
12356
12357 // Make sure that a cache transaction passes on its priority to
12358 // newly-created network transactions.
TEST_F(HttpCacheTest,SetPriorityNewTransaction)12359 TEST_F(HttpCacheTest, SetPriorityNewTransaction) {
12360 MockHttpCache cache;
12361 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
12362
12363 std::string raw_headers(
12364 "HTTP/1.1 200 OK\n"
12365 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12366 "ETag: \"foo\"\n"
12367 "Accept-Ranges: bytes\n"
12368 "Content-Length: 80\n");
12369 CreateTruncatedEntry(raw_headers, &cache);
12370
12371 // Now make a regular request.
12372 std::string headers;
12373 MockTransaction transaction(kRangeGET_TransactionOK);
12374 transaction.request_headers = EXTRA_HEADER;
12375 transaction.data = kFullRangeData;
12376
12377 std::unique_ptr<HttpTransaction> trans;
12378 ASSERT_THAT(cache.http_cache()->CreateTransaction(MEDIUM, &trans), IsOk());
12379 EXPECT_EQ(DEFAULT_PRIORITY,
12380 cache.network_layer()->last_create_transaction_priority());
12381
12382 MockHttpRequest info(transaction);
12383 TestCompletionCallback callback;
12384 EXPECT_EQ(ERR_IO_PENDING,
12385 trans->Start(&info, callback.callback(), NetLogWithSource()));
12386 EXPECT_THAT(callback.WaitForResult(), IsOk());
12387
12388 EXPECT_EQ(MEDIUM, cache.network_layer()->last_create_transaction_priority());
12389
12390 trans->SetPriority(HIGHEST);
12391 // Should trigger a new network transaction and pick up the new
12392 // priority.
12393 ReadAndVerifyTransaction(trans.get(), transaction);
12394
12395 EXPECT_EQ(HIGHEST, cache.network_layer()->last_create_transaction_priority());
12396 }
12397
12398 namespace {
12399
RunTransactionAndGetNetworkBytes(MockHttpCache * cache,const MockTransaction & trans_info,int64_t * sent_bytes,int64_t * received_bytes)12400 void RunTransactionAndGetNetworkBytes(MockHttpCache* cache,
12401 const MockTransaction& trans_info,
12402 int64_t* sent_bytes,
12403 int64_t* received_bytes) {
12404 RunTransactionTestBase(
12405 cache->http_cache(), trans_info, MockHttpRequest(trans_info), nullptr,
12406 NetLogWithSource(), nullptr, sent_bytes, received_bytes, nullptr);
12407 }
12408
12409 } // namespace
12410
TEST_F(HttpCacheTest,NetworkBytesCacheMissAndThenHit)12411 TEST_F(HttpCacheTest, NetworkBytesCacheMissAndThenHit) {
12412 MockHttpCache cache;
12413
12414 MockTransaction transaction(kSimpleGET_Transaction);
12415 int64_t sent, received;
12416 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12417 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12418 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12419
12420 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12421 EXPECT_EQ(0, sent);
12422 EXPECT_EQ(0, received);
12423 }
12424
TEST_F(HttpCacheTest,NetworkBytesConditionalRequest304)12425 TEST_F(HttpCacheTest, NetworkBytesConditionalRequest304) {
12426 MockHttpCache cache;
12427
12428 ScopedMockTransaction transaction(kETagGET_Transaction);
12429 int64_t sent, received;
12430 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12431 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12432 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12433
12434 transaction.load_flags = LOAD_VALIDATE_CACHE;
12435 transaction.handler = kETagGetConditionalRequestHandler;
12436 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12437 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12438 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12439 }
12440
TEST_F(HttpCacheTest,NetworkBytesConditionalRequest200)12441 TEST_F(HttpCacheTest, NetworkBytesConditionalRequest200) {
12442 MockHttpCache cache;
12443
12444 ScopedMockTransaction transaction(kTypicalGET_Transaction);
12445 transaction.request_headers = "Foo: bar\r\n";
12446 transaction.response_headers =
12447 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
12448 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
12449 "Etag: \"foopy\"\n"
12450 "Cache-Control: max-age=0\n"
12451 "Vary: Foo\n";
12452 int64_t sent, received;
12453 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12454 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12455 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12456
12457 RevalidationServer server;
12458 transaction.handler = server.GetHandlerCallback();
12459
12460 transaction.request_headers = "Foo: none\r\n";
12461 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12462 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12463 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12464 }
12465
TEST_F(HttpCacheTest,NetworkBytesRange)12466 TEST_F(HttpCacheTest, NetworkBytesRange) {
12467 MockHttpCache cache;
12468 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
12469
12470 // Read bytes 40-49 from the network.
12471 int64_t sent, received;
12472 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12473 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12474 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12475
12476 // Read bytes 40-49 from the cache.
12477 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12478 EXPECT_EQ(0, sent);
12479 EXPECT_EQ(0, received);
12480 base::RunLoop().RunUntilIdle();
12481
12482 // Read bytes 30-39 from the network.
12483 transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER;
12484 transaction.data = "rg: 30-39 ";
12485 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12486 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent);
12487 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received);
12488 base::RunLoop().RunUntilIdle();
12489
12490 // Read bytes 20-29 and 50-59 from the network, bytes 30-49 from the cache.
12491 transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER;
12492 transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 ";
12493 RunTransactionAndGetNetworkBytes(&cache, transaction, &sent, &received);
12494 EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes * 2, sent);
12495 EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes * 2, received);
12496 }
12497
12498 class HttpCachePrefetchValidationTest : public TestWithTaskEnvironment {
12499 protected:
12500 static const int kNumSecondsPerMinute = 60;
12501 static const int kMaxAgeSecs = 100;
12502 static const int kRequireValidationSecs = kMaxAgeSecs + 1;
12503
HttpCachePrefetchValidationTest()12504 HttpCachePrefetchValidationTest() : transaction_(kSimpleGET_Transaction) {
12505 DCHECK_LT(kMaxAgeSecs, prefetch_reuse_mins() * kNumSecondsPerMinute);
12506
12507 cache_.http_cache()->SetClockForTesting(&clock_);
12508 cache_.network_layer()->SetClock(&clock_);
12509
12510 transaction_.response_headers = "Cache-Control: max-age=100\n";
12511 }
12512
TransactionRequiredNetwork(int load_flags)12513 bool TransactionRequiredNetwork(int load_flags) {
12514 int pre_transaction_count = transaction_count();
12515 transaction_.load_flags = load_flags;
12516 RunTransactionTest(cache_.http_cache(), transaction_);
12517 return pre_transaction_count != transaction_count();
12518 }
12519
AdvanceTime(int seconds)12520 void AdvanceTime(int seconds) { clock_.Advance(base::Seconds(seconds)); }
12521
prefetch_reuse_mins()12522 int prefetch_reuse_mins() { return HttpCache::kPrefetchReuseMins; }
12523
12524 // How many times this test has sent requests to the (fake) origin
12525 // server. Every test case needs to make at least one request to initialise
12526 // the cache.
transaction_count()12527 int transaction_count() {
12528 return cache_.network_layer()->transaction_count();
12529 }
12530
12531 MockHttpCache cache_;
12532 ScopedMockTransaction transaction_;
12533 std::string response_headers_;
12534 base::SimpleTestClock clock_;
12535 };
12536
TEST_F(HttpCachePrefetchValidationTest,SkipValidationShortlyAfterPrefetch)12537 TEST_F(HttpCachePrefetchValidationTest, SkipValidationShortlyAfterPrefetch) {
12538 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12539 AdvanceTime(kRequireValidationSecs);
12540 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12541 }
12542
TEST_F(HttpCachePrefetchValidationTest,ValidateLongAfterPrefetch)12543 TEST_F(HttpCachePrefetchValidationTest, ValidateLongAfterPrefetch) {
12544 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12545 AdvanceTime(prefetch_reuse_mins() * kNumSecondsPerMinute);
12546 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12547 }
12548
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnceOnly)12549 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceOnly) {
12550 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12551 AdvanceTime(kRequireValidationSecs);
12552 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12553 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12554 }
12555
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnceReadOnly)12556 TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceReadOnly) {
12557 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12558 AdvanceTime(kRequireValidationSecs);
12559 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_ONLY_FROM_CACHE |
12560 LOAD_SKIP_CACHE_VALIDATION));
12561 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12562 }
12563
TEST_F(HttpCachePrefetchValidationTest,BypassCacheOverwritesPrefetch)12564 TEST_F(HttpCachePrefetchValidationTest, BypassCacheOverwritesPrefetch) {
12565 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12566 AdvanceTime(kRequireValidationSecs);
12567 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_BYPASS_CACHE));
12568 AdvanceTime(kRequireValidationSecs);
12569 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12570 }
12571
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnExistingEntryThatNeedsValidation)12572 TEST_F(HttpCachePrefetchValidationTest,
12573 SkipValidationOnExistingEntryThatNeedsValidation) {
12574 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12575 AdvanceTime(kRequireValidationSecs);
12576 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12577 AdvanceTime(kRequireValidationSecs);
12578 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12579 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12580 }
12581
TEST_F(HttpCachePrefetchValidationTest,SkipValidationOnExistingEntryThatDoesNotNeedValidation)12582 TEST_F(HttpCachePrefetchValidationTest,
12583 SkipValidationOnExistingEntryThatDoesNotNeedValidation) {
12584 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12585 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
12586 AdvanceTime(kRequireValidationSecs);
12587 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12588 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL));
12589 }
12590
TEST_F(HttpCachePrefetchValidationTest,PrefetchMultipleTimes)12591 TEST_F(HttpCachePrefetchValidationTest, PrefetchMultipleTimes) {
12592 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12593 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH));
12594 AdvanceTime(kRequireValidationSecs);
12595 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12596 }
12597
TEST_F(HttpCachePrefetchValidationTest,ValidateOnDelayedSecondPrefetch)12598 TEST_F(HttpCachePrefetchValidationTest, ValidateOnDelayedSecondPrefetch) {
12599 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12600 AdvanceTime(kRequireValidationSecs);
12601 EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH));
12602 AdvanceTime(kRequireValidationSecs);
12603 EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL));
12604 }
12605
TEST_F(HttpCacheTest,StaleContentNotUsedWhenLoadFlagNotSet)12606 TEST_F(HttpCacheTest, StaleContentNotUsedWhenLoadFlagNotSet) {
12607 MockHttpCache cache;
12608
12609 ScopedMockTransaction stale_while_revalidate_transaction(
12610 kSimpleGET_Transaction);
12611
12612 stale_while_revalidate_transaction.response_headers =
12613 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12614 "Age: 10801\n"
12615 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12616
12617 // Write to the cache.
12618 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12619
12620 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12621
12622 // Send the request again and check that it is sent to the network again.
12623 HttpResponseInfo response_info;
12624 RunTransactionTestWithResponseInfo(
12625 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12626
12627 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12628 EXPECT_FALSE(response_info.async_revalidation_requested);
12629 }
12630
TEST_F(HttpCacheTest,StaleContentUsedWhenLoadFlagSetAndUsableThenTimesout)12631 TEST_F(HttpCacheTest, StaleContentUsedWhenLoadFlagSetAndUsableThenTimesout) {
12632 MockHttpCache cache;
12633 base::SimpleTestClock clock;
12634 cache.http_cache()->SetClockForTesting(&clock);
12635 cache.network_layer()->SetClock(&clock);
12636 clock.Advance(base::Seconds(10));
12637
12638 ScopedMockTransaction stale_while_revalidate_transaction(
12639 kSimpleGET_Transaction);
12640 stale_while_revalidate_transaction.load_flags |=
12641 LOAD_SUPPORT_ASYNC_REVALIDATION;
12642 stale_while_revalidate_transaction.response_headers =
12643 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12644 "Age: 10801\n"
12645 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12646
12647 // Write to the cache.
12648 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12649
12650 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12651
12652 // Send the request again and check that it is not sent to the network again.
12653 HttpResponseInfo response_info;
12654 RunTransactionTestWithResponseInfo(
12655 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12656
12657 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12658 EXPECT_TRUE(response_info.async_revalidation_requested);
12659 EXPECT_FALSE(response_info.stale_revalidate_timeout.is_null());
12660
12661 // Move forward in time such that the stale response is no longer valid.
12662 clock.SetNow(response_info.stale_revalidate_timeout);
12663 clock.Advance(base::Seconds(1));
12664
12665 RunTransactionTestWithResponseInfo(
12666 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12667
12668 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12669 EXPECT_FALSE(response_info.async_revalidation_requested);
12670 }
12671
TEST_F(HttpCacheTest,StaleContentUsedWhenLoadFlagSetAndUsable)12672 TEST_F(HttpCacheTest, StaleContentUsedWhenLoadFlagSetAndUsable) {
12673 MockHttpCache cache;
12674 base::SimpleTestClock clock;
12675 cache.http_cache()->SetClockForTesting(&clock);
12676 cache.network_layer()->SetClock(&clock);
12677 clock.Advance(base::Seconds(10));
12678
12679 ScopedMockTransaction stale_while_revalidate_transaction(
12680 kSimpleGET_Transaction);
12681 stale_while_revalidate_transaction.load_flags |=
12682 LOAD_SUPPORT_ASYNC_REVALIDATION;
12683 stale_while_revalidate_transaction.response_headers =
12684 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12685 "Age: 10801\n"
12686 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12687
12688 // Write to the cache.
12689 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12690
12691 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12692
12693 // Send the request again and check that it is not sent to the network again.
12694 HttpResponseInfo response_info;
12695 RunTransactionTestWithResponseInfo(
12696 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12697
12698 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12699 EXPECT_TRUE(response_info.async_revalidation_requested);
12700 EXPECT_FALSE(response_info.stale_revalidate_timeout.is_null());
12701 base::Time revalidation_timeout = response_info.stale_revalidate_timeout;
12702 clock.Advance(base::Seconds(1));
12703 EXPECT_TRUE(clock.Now() < revalidation_timeout);
12704
12705 // Fetch the resource again inside the revalidation timeout window.
12706 RunTransactionTestWithResponseInfo(
12707 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12708
12709 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12710 EXPECT_TRUE(response_info.async_revalidation_requested);
12711 EXPECT_FALSE(response_info.stale_revalidate_timeout.is_null());
12712 // Expect that the original revalidation timeout hasn't changed.
12713 EXPECT_TRUE(revalidation_timeout == response_info.stale_revalidate_timeout);
12714
12715 // mask of async revalidation flag.
12716 stale_while_revalidate_transaction.load_flags &=
12717 ~LOAD_SUPPORT_ASYNC_REVALIDATION;
12718 stale_while_revalidate_transaction.status = "HTTP/1.1 304 Not Modified";
12719 // Write 304 to the cache.
12720 RunTransactionTestWithResponseInfo(
12721 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12722
12723 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12724 EXPECT_FALSE(response_info.async_revalidation_requested);
12725 EXPECT_TRUE(response_info.stale_revalidate_timeout.is_null());
12726 }
12727
TEST_F(HttpCacheTest,StaleContentNotUsedWhenUnusable)12728 TEST_F(HttpCacheTest, StaleContentNotUsedWhenUnusable) {
12729 MockHttpCache cache;
12730
12731 ScopedMockTransaction stale_while_revalidate_transaction(
12732 kSimpleGET_Transaction);
12733 stale_while_revalidate_transaction.load_flags |=
12734 LOAD_SUPPORT_ASYNC_REVALIDATION;
12735 stale_while_revalidate_transaction.response_headers =
12736 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12737 "Age: 10801\n"
12738 "Cache-Control: max-age=0,stale-while-revalidate=1800\n";
12739
12740 // Write to the cache.
12741 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12742
12743 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12744
12745 // Send the request again and check that it is sent to the network again.
12746 HttpResponseInfo response_info;
12747 RunTransactionTestWithResponseInfo(
12748 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12749
12750 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12751 EXPECT_FALSE(response_info.async_revalidation_requested);
12752 }
12753
TEST_F(HttpCacheTest,StaleContentWriteError)12754 TEST_F(HttpCacheTest, StaleContentWriteError) {
12755 MockHttpCache cache;
12756 base::SimpleTestClock clock;
12757 cache.http_cache()->SetClockForTesting(&clock);
12758 cache.network_layer()->SetClock(&clock);
12759 clock.Advance(base::Seconds(10));
12760
12761 ScopedMockTransaction stale_while_revalidate_transaction(
12762 kSimpleGET_Transaction);
12763 stale_while_revalidate_transaction.load_flags |=
12764 LOAD_SUPPORT_ASYNC_REVALIDATION;
12765 stale_while_revalidate_transaction.response_headers =
12766 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
12767 "Age: 10801\n"
12768 "Cache-Control: max-age=0,stale-while-revalidate=86400\n";
12769
12770 // Write to the cache.
12771 RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction);
12772
12773 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12774
12775 // Send the request again but inject a write fault. Should still work
12776 // (and not dereference any null pointers).
12777 cache.disk_cache()->set_soft_failures_mask(MockDiskEntry::FAIL_WRITE);
12778 HttpResponseInfo response_info;
12779 RunTransactionTestWithResponseInfo(
12780 cache.http_cache(), stale_while_revalidate_transaction, &response_info);
12781
12782 EXPECT_EQ(2, cache.network_layer()->transaction_count());
12783 }
12784
12785 // Tests that we allow multiple simultaneous, non-overlapping transactions to
12786 // take place on a sparse entry.
TEST_F(HttpCacheTest,RangeGET_MultipleRequests)12787 TEST_F(HttpCacheTest, RangeGET_MultipleRequests) {
12788 MockHttpCache cache;
12789
12790 // Create a transaction for bytes 0-9.
12791 MockHttpRequest request(kRangeGET_TransactionOK);
12792 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
12793 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
12794 transaction.data = "rg: 00-09 ";
12795
12796 TestCompletionCallback callback;
12797 std::unique_ptr<HttpTransaction> trans;
12798 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
12799 EXPECT_THAT(rv, IsOk());
12800 ASSERT_TRUE(trans.get());
12801
12802 // Start our transaction.
12803 trans->Start(&request, callback.callback(), NetLogWithSource());
12804
12805 // A second transaction on a different part of the file (the default
12806 // kRangeGET_TransactionOK requests 40-49) should not be blocked by
12807 // the already pending transaction.
12808 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
12809
12810 // Let the first transaction complete.
12811 callback.WaitForResult();
12812 }
12813
12814 // Verify that a range request can be satisfied from a completely cached
12815 // resource with the LOAD_ONLY_FROM_CACHE flag set. Currently it's not
12816 // implemented so it returns ERR_CACHE_MISS. See also
12817 // HttpCacheTest.RangeGET_OK_LoadOnlyFromCache.
12818 // TODO(ricea): Update this test if it is implemented in future.
TEST_F(HttpCacheTest,RangeGET_Previous200_LoadOnlyFromCache)12819 TEST_F(HttpCacheTest, RangeGET_Previous200_LoadOnlyFromCache) {
12820 MockHttpCache cache;
12821
12822 // Store the whole thing with status 200.
12823 {
12824 MockTransaction transaction(kETagGET_Transaction);
12825 transaction.url = kRangeGET_TransactionOK.url;
12826 transaction.data = kFullRangeData;
12827 ScopedMockTransaction scoped_transaction(transaction);
12828 RunTransactionTest(cache.http_cache(), transaction);
12829 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12830 EXPECT_EQ(0, cache.disk_cache()->open_count());
12831 EXPECT_EQ(1, cache.disk_cache()->create_count());
12832 }
12833
12834 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
12835
12836 // Now see that we use the stored entry.
12837 MockTransaction transaction2(kRangeGET_TransactionOK);
12838 transaction2.load_flags |= LOAD_ONLY_FROM_CACHE;
12839 MockHttpRequest request(transaction2);
12840 TestCompletionCallback callback;
12841
12842 std::unique_ptr<HttpTransaction> trans;
12843 int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
12844 EXPECT_THAT(rv, IsOk());
12845 ASSERT_TRUE(trans);
12846
12847 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12848 if (rv == ERR_IO_PENDING) {
12849 rv = callback.WaitForResult();
12850 }
12851 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
12852
12853 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12854 EXPECT_EQ(1, cache.disk_cache()->open_count());
12855 EXPECT_EQ(1, cache.disk_cache()->create_count());
12856 }
12857
12858 // Makes sure that a request stops using the cache when the response headers
12859 // with "Cache-Control: no-store" arrives. That means that another request for
12860 // the same URL can be processed before the response body of the original
12861 // request arrives.
TEST_F(HttpCacheTest,NoStoreResponseShouldNotBlockFollowingRequests)12862 TEST_F(HttpCacheTest, NoStoreResponseShouldNotBlockFollowingRequests) {
12863 MockHttpCache cache;
12864 ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
12865 mock_transaction.response_headers = "Cache-Control: no-store\n";
12866 MockHttpRequest request(mock_transaction);
12867
12868 auto first = std::make_unique<Context>();
12869 first->result = cache.CreateTransaction(&first->trans);
12870 ASSERT_THAT(first->result, IsOk());
12871 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
12872 first->result = first->trans->Start(&request, first->callback.callback(),
12873 NetLogWithSource());
12874 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, first->trans->GetLoadState());
12875
12876 base::RunLoop().RunUntilIdle();
12877 EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState());
12878 ASSERT_TRUE(first->trans->GetResponseInfo());
12879 EXPECT_TRUE(first->trans->GetResponseInfo()->headers->HasHeaderValue(
12880 "Cache-Control", "no-store"));
12881 // Here we have read the response header but not read the response body yet.
12882
12883 // Let us create the second (read) transaction.
12884 auto second = std::make_unique<Context>();
12885 second->result = cache.CreateTransaction(&second->trans);
12886 ASSERT_THAT(second->result, IsOk());
12887 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
12888 second->result = second->trans->Start(&request, second->callback.callback(),
12889 NetLogWithSource());
12890
12891 // Here the second transaction proceeds without reading the first body.
12892 EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, second->trans->GetLoadState());
12893 base::RunLoop().RunUntilIdle();
12894 EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState());
12895 ASSERT_TRUE(second->trans->GetResponseInfo());
12896 EXPECT_TRUE(second->trans->GetResponseInfo()->headers->HasHeaderValue(
12897 "Cache-Control", "no-store"));
12898 ReadAndVerifyTransaction(second->trans.get(), kSimpleGET_Transaction);
12899 }
12900
12901 // Tests that serving a response entirely from cache replays the previous
12902 // SSLInfo.
TEST_F(HttpCacheTest,CachePreservesSSLInfo)12903 TEST_F(HttpCacheTest, CachePreservesSSLInfo) {
12904 static const uint16_t kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f;
12905 int status = 0;
12906 SSLConnectionStatusSetCipherSuite(kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
12907 &status);
12908 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2, &status);
12909
12910 scoped_refptr<X509Certificate> cert =
12911 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12912
12913 MockHttpCache cache;
12914
12915 ScopedMockTransaction transaction(kSimpleGET_Transaction);
12916 transaction.cert = cert;
12917 transaction.ssl_connection_status = status;
12918
12919 // Fetch the resource.
12920 HttpResponseInfo response_info;
12921 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
12922 &response_info);
12923
12924 // The request should have hit the network and a cache entry created.
12925 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12926 EXPECT_EQ(0, cache.disk_cache()->open_count());
12927 EXPECT_EQ(1, cache.disk_cache()->create_count());
12928
12929 // The expected SSL state was reported.
12930 EXPECT_EQ(transaction.ssl_connection_status,
12931 response_info.ssl_info.connection_status);
12932 EXPECT_TRUE(cert->EqualsIncludingChain(response_info.ssl_info.cert.get()));
12933
12934 // Fetch the resource again.
12935 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
12936 &response_info);
12937
12938 // The request should have been reused without hitting the network.
12939 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12940 EXPECT_EQ(1, cache.disk_cache()->open_count());
12941 EXPECT_EQ(1, cache.disk_cache()->create_count());
12942
12943 // The SSL state was preserved.
12944 EXPECT_EQ(status, response_info.ssl_info.connection_status);
12945 EXPECT_TRUE(cert->EqualsIncludingChain(response_info.ssl_info.cert.get()));
12946 }
12947
12948 // Tests that SSLInfo gets updated when revalidating a cached response.
TEST_F(HttpCacheTest,RevalidationUpdatesSSLInfo)12949 TEST_F(HttpCacheTest, RevalidationUpdatesSSLInfo) {
12950 static const uint16_t kTLS_RSA_WITH_RC4_128_MD5 = 0x0004;
12951 static const uint16_t kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f;
12952
12953 int status1 = 0;
12954 SSLConnectionStatusSetCipherSuite(kTLS_RSA_WITH_RC4_128_MD5, &status1);
12955 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1, &status1);
12956 int status2 = 0;
12957 SSLConnectionStatusSetCipherSuite(kTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
12958 &status2);
12959 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2, &status2);
12960
12961 scoped_refptr<X509Certificate> cert1 =
12962 ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
12963 scoped_refptr<X509Certificate> cert2 =
12964 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12965
12966 MockHttpCache cache;
12967
12968 ScopedMockTransaction transaction(kTypicalGET_Transaction);
12969 transaction.cert = cert1;
12970 transaction.ssl_connection_status = status1;
12971
12972 // Fetch the resource.
12973 HttpResponseInfo response_info;
12974 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
12975 &response_info);
12976
12977 // The request should have hit the network and a cache entry created.
12978 EXPECT_EQ(1, cache.network_layer()->transaction_count());
12979 EXPECT_EQ(0, cache.disk_cache()->open_count());
12980 EXPECT_EQ(1, cache.disk_cache()->create_count());
12981 EXPECT_FALSE(response_info.was_cached);
12982
12983 // The expected SSL state was reported.
12984 EXPECT_EQ(status1, response_info.ssl_info.connection_status);
12985 EXPECT_TRUE(cert1->EqualsIncludingChain(response_info.ssl_info.cert.get()));
12986
12987 // The server deploys a more modern configuration but reports 304 on the
12988 // revalidation attempt.
12989 transaction.status = "HTTP/1.1 304 Not Modified";
12990 transaction.cert = cert2;
12991 transaction.ssl_connection_status = status2;
12992
12993 // Fetch the resource again, forcing a revalidation.
12994 transaction.request_headers = "Cache-Control: max-age=0\r\n";
12995 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
12996 &response_info);
12997
12998 // The request should have been successfully revalidated.
12999 EXPECT_EQ(2, cache.network_layer()->transaction_count());
13000 EXPECT_EQ(1, cache.disk_cache()->open_count());
13001 EXPECT_EQ(1, cache.disk_cache()->create_count());
13002 EXPECT_TRUE(response_info.was_cached);
13003
13004 // The new SSL state is reported.
13005 EXPECT_EQ(status2, response_info.ssl_info.connection_status);
13006 EXPECT_TRUE(cert2->EqualsIncludingChain(response_info.ssl_info.cert.get()));
13007 }
13008
TEST_F(HttpCacheTest,CacheEntryStatusOther)13009 TEST_F(HttpCacheTest, CacheEntryStatusOther) {
13010 MockHttpCache cache;
13011
13012 HttpResponseInfo response_info;
13013 RunTransactionTestWithResponseInfo(cache.http_cache(), kRangeGET_Transaction,
13014 &response_info);
13015
13016 EXPECT_FALSE(response_info.was_cached);
13017 EXPECT_TRUE(response_info.network_accessed);
13018 EXPECT_EQ(CacheEntryStatus::ENTRY_OTHER, response_info.cache_entry_status);
13019 }
13020
TEST_F(HttpCacheTest,CacheEntryStatusNotInCache)13021 TEST_F(HttpCacheTest, CacheEntryStatusNotInCache) {
13022 MockHttpCache cache;
13023
13024 HttpResponseInfo response_info;
13025 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
13026 &response_info);
13027
13028 EXPECT_FALSE(response_info.was_cached);
13029 EXPECT_TRUE(response_info.network_accessed);
13030 EXPECT_EQ(CacheEntryStatus::ENTRY_NOT_IN_CACHE,
13031 response_info.cache_entry_status);
13032 }
13033
TEST_F(HttpCacheTest,CacheEntryStatusUsed)13034 TEST_F(HttpCacheTest, CacheEntryStatusUsed) {
13035 MockHttpCache cache;
13036 RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
13037
13038 HttpResponseInfo response_info;
13039 RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction,
13040 &response_info);
13041
13042 EXPECT_TRUE(response_info.was_cached);
13043 EXPECT_FALSE(response_info.network_accessed);
13044 EXPECT_EQ(CacheEntryStatus::ENTRY_USED, response_info.cache_entry_status);
13045 }
13046
TEST_F(HttpCacheTest,CacheEntryStatusValidated)13047 TEST_F(HttpCacheTest, CacheEntryStatusValidated) {
13048 MockHttpCache cache;
13049 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
13050
13051 ScopedMockTransaction still_valid(kETagGET_Transaction);
13052 still_valid.load_flags = LOAD_VALIDATE_CACHE; // Force a validation.
13053 still_valid.handler = kETagGetConditionalRequestHandler;
13054
13055 HttpResponseInfo response_info;
13056 RunTransactionTestWithResponseInfo(cache.http_cache(), still_valid,
13057 &response_info);
13058
13059 EXPECT_TRUE(response_info.was_cached);
13060 EXPECT_TRUE(response_info.network_accessed);
13061 EXPECT_EQ(CacheEntryStatus::ENTRY_VALIDATED,
13062 response_info.cache_entry_status);
13063 }
13064
TEST_F(HttpCacheTest,CacheEntryStatusUpdated)13065 TEST_F(HttpCacheTest, CacheEntryStatusUpdated) {
13066 MockHttpCache cache;
13067 RunTransactionTest(cache.http_cache(), kETagGET_Transaction);
13068
13069 ScopedMockTransaction update(kETagGET_Transaction);
13070 update.load_flags = LOAD_VALIDATE_CACHE; // Force a validation.
13071
13072 HttpResponseInfo response_info;
13073 RunTransactionTestWithResponseInfo(cache.http_cache(), update,
13074 &response_info);
13075
13076 EXPECT_FALSE(response_info.was_cached);
13077 EXPECT_TRUE(response_info.network_accessed);
13078 EXPECT_EQ(CacheEntryStatus::ENTRY_UPDATED, response_info.cache_entry_status);
13079 }
13080
TEST_F(HttpCacheTest,CacheEntryStatusCantConditionalize)13081 TEST_F(HttpCacheTest, CacheEntryStatusCantConditionalize) {
13082 MockHttpCache cache;
13083 cache.FailConditionalizations();
13084 RunTransactionTest(cache.http_cache(), kTypicalGET_Transaction);
13085
13086 HttpResponseInfo response_info;
13087 RunTransactionTestWithResponseInfo(cache.http_cache(),
13088 kTypicalGET_Transaction, &response_info);
13089
13090 EXPECT_FALSE(response_info.was_cached);
13091 EXPECT_TRUE(response_info.network_accessed);
13092 EXPECT_EQ(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE,
13093 response_info.cache_entry_status);
13094 }
13095
TEST_F(HttpSplitCacheKeyTest,GetResourceURLFromHttpCacheKey)13096 TEST_F(HttpSplitCacheKeyTest, GetResourceURLFromHttpCacheKey) {
13097 base::test::ScopedFeatureList feature_list;
13098 feature_list.InitAndEnableFeature(
13099 net::features::kSplitCacheByNetworkIsolationKey);
13100 MockHttpCache cache;
13101 std::string urls[] = {"http://www.a.com/", "https://b.com/example.html",
13102 "http://example.com/Some Path/Some Leaf?some query"};
13103
13104 for (const std::string& url : urls) {
13105 std::string key = ComputeCacheKey(url);
13106 EXPECT_EQ(GURL(url).spec(), HttpCache::GetResourceURLFromHttpCacheKey(key));
13107 }
13108 }
13109
TEST_F(HttpCacheTest,GetResourceURLFromHttpCacheKey)13110 TEST_F(HttpCacheTest, GetResourceURLFromHttpCacheKey) {
13111 const struct {
13112 std::string input;
13113 std::string output;
13114 } kTestCase[] = {
13115 // Valid input:
13116 {"0/0/https://a.com/", "https://a.com/"},
13117 {"0/0/https://a.com/path", "https://a.com/path"},
13118 {"0/0/https://a.com/?query", "https://a.com/?query"},
13119 {"0/0/https://a.com/#fragment", "https://a.com/#fragment"},
13120 {"0/0/_dk_s_ https://a.com/", "https://a.com/"},
13121 {"0/0/_dk_https://a.com https://b.com https://c.com/", "https://c.com/"},
13122 {"0/0/_dk_shttps://a.com https://b.com https://c.com/", "https://c.com/"},
13123
13124 // Invalid input, producing garbage, without crashing.
13125 {"", ""},
13126 {"0/a.com", "0/a.com"},
13127 {"https://a.com/", "a.com/"},
13128 {"0/https://a.com/", "/a.com/"},
13129 };
13130
13131 for (const auto& test : kTestCase) {
13132 EXPECT_EQ(test.output,
13133 HttpCache::GetResourceURLFromHttpCacheKey(test.input));
13134 }
13135 }
13136
13137 class TestCompletionCallbackForHttpCache : public TestCompletionCallbackBase {
13138 public:
13139 TestCompletionCallbackForHttpCache() = default;
13140 ~TestCompletionCallbackForHttpCache() override = default;
13141
callback()13142 CompletionRepeatingCallback callback() {
13143 return base::BindRepeating(&TestCompletionCallbackForHttpCache::SetResult,
13144 base::Unretained(this));
13145 }
13146
results()13147 const std::vector<int>& results() { return results_; }
13148
13149 private:
13150 std::vector<int> results_;
13151
13152 protected:
SetResult(int result)13153 void SetResult(int result) override {
13154 results_.push_back(result);
13155 DidSetResult();
13156 }
13157 };
13158
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByOpen)13159 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByOpen) {
13160 MockHttpCache cache;
13161 TestCompletionCallbackForHttpCache cb;
13162 std::unique_ptr<Transaction> transaction =
13163 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13164
13165 transaction->SetIOCallBackForTest(cb.callback());
13166 transaction->SetCacheIOCallBackForTest(cb.callback());
13167
13168 // Create the backend here as our direct calls to DoomEntry and OpenEntry
13169 // below require that it exists.
13170 cache.backend();
13171
13172 // Need a mock transaction in order to use some of MockHttpCache's
13173 // functions.
13174 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13175
13176 scoped_refptr<ActiveEntry> entry1 = nullptr;
13177
13178 cache.disk_cache()->set_force_fail_callback_later(true);
13179
13180 // Queue up our operations.
13181 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13182 ASSERT_EQ(rv, ERR_IO_PENDING);
13183 cache.disk_cache()->set_force_fail_callback_later(false);
13184 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13185 transaction.get());
13186 ASSERT_EQ(rv, ERR_IO_PENDING);
13187
13188 // Wait for all the results to arrive.
13189 cb.GetResult(rv);
13190 ASSERT_EQ(cb.results().size(), 2u);
13191
13192 // Verify that DoomEntry failed correctly.
13193 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13194 // Verify that OpenEntry fails with the same code.
13195 ASSERT_EQ(cb.results()[1], ERR_CACHE_DOOM_FAILURE);
13196 ASSERT_EQ(entry1, nullptr);
13197 }
13198
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByCreate)13199 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByCreate) {
13200 MockHttpCache cache;
13201 TestCompletionCallbackForHttpCache cb;
13202 std::unique_ptr<Transaction> transaction =
13203 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13204
13205 transaction->SetIOCallBackForTest(cb.callback());
13206 transaction->SetCacheIOCallBackForTest(cb.callback());
13207
13208 // Create the backend here as our direct calls to DoomEntry and CreateEntry
13209 // below require that it exists.
13210 cache.backend();
13211
13212 // Need a mock transaction in order to use some of MockHttpCache's
13213 // functions.
13214 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13215
13216 scoped_refptr<ActiveEntry> entry1 = nullptr;
13217
13218 cache.disk_cache()->set_force_fail_callback_later(true);
13219
13220 // Queue up our operations.
13221 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13222 ASSERT_EQ(rv, ERR_IO_PENDING);
13223 cache.disk_cache()->set_force_fail_callback_later(false);
13224 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13225 transaction.get());
13226 ASSERT_EQ(rv, ERR_IO_PENDING);
13227
13228 // Wait for all the results to arrive.
13229 cb.GetResult(rv);
13230 ASSERT_EQ(cb.results().size(), 2u);
13231
13232 // Verify that DoomEntry failed correctly.
13233 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13234 // Verify that CreateEntry requests a restart (CACHE_RACE).
13235 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13236 ASSERT_EQ(entry1, nullptr);
13237 }
13238
TEST_F(HttpCacheIOCallbackTest,FailedDoomFollowedByDoom)13239 TEST_F(HttpCacheIOCallbackTest, FailedDoomFollowedByDoom) {
13240 MockHttpCache cache;
13241 TestCompletionCallbackForHttpCache cb;
13242 std::unique_ptr<Transaction> transaction =
13243 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13244
13245 transaction->SetIOCallBackForTest(cb.callback());
13246 transaction->SetCacheIOCallBackForTest(cb.callback());
13247
13248 // Create the backend here as our direct calls to DoomEntry below require that
13249 // it exists.
13250 cache.backend();
13251
13252 // Need a mock transaction in order to use some of MockHttpCache's
13253 // functions.
13254 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13255
13256 cache.disk_cache()->set_force_fail_callback_later(true);
13257
13258 // Queue up our operations.
13259 int rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13260 ASSERT_EQ(rv, ERR_IO_PENDING);
13261 cache.disk_cache()->set_force_fail_callback_later(false);
13262 rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13263 ASSERT_EQ(rv, ERR_IO_PENDING);
13264
13265 // Wait for all the results to arrive.
13266 cb.GetResult(rv);
13267 ASSERT_EQ(cb.results().size(), 2u);
13268
13269 // Verify that DoomEntry failed correctly.
13270 ASSERT_EQ(cb.results()[0], ERR_CACHE_DOOM_FAILURE);
13271 // Verify that the second DoomEntry requests a restart (CACHE_RACE).
13272 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13273 }
13274
TEST_F(HttpCacheIOCallbackTest,FailedOpenFollowedByCreate)13275 TEST_F(HttpCacheIOCallbackTest, FailedOpenFollowedByCreate) {
13276 MockHttpCache cache;
13277 TestCompletionCallbackForHttpCache cb;
13278 std::unique_ptr<Transaction> transaction =
13279 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13280
13281 transaction->SetIOCallBackForTest(cb.callback());
13282 transaction->SetCacheIOCallBackForTest(cb.callback());
13283
13284 // Create the backend here as our direct calls to OpenEntry and CreateEntry
13285 // below require that it exists.
13286 cache.backend();
13287
13288 // Need a mock transaction in order to use some of MockHttpCache's
13289 // functions.
13290 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13291
13292 scoped_refptr<ActiveEntry> entry1 = nullptr;
13293 scoped_refptr<ActiveEntry> entry2 = nullptr;
13294
13295 cache.disk_cache()->set_force_fail_callback_later(true);
13296
13297 // Queue up our operations.
13298 int rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13299 transaction.get());
13300 ASSERT_EQ(rv, ERR_IO_PENDING);
13301 cache.disk_cache()->set_force_fail_callback_later(false);
13302 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13303 transaction.get());
13304 ASSERT_EQ(rv, ERR_IO_PENDING);
13305
13306 // Wait for all the results to arrive.
13307 cb.GetResult(rv);
13308 ASSERT_EQ(cb.results().size(), 2u);
13309
13310 // Verify that OpenEntry failed correctly.
13311 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_FAILURE);
13312 ASSERT_EQ(entry1, nullptr);
13313 // Verify that the CreateEntry requests a restart (CACHE_RACE).
13314 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13315 ASSERT_EQ(entry2, nullptr);
13316 }
13317
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByOpen)13318 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByOpen) {
13319 MockHttpCache cache;
13320 TestCompletionCallbackForHttpCache cb;
13321 std::unique_ptr<Transaction> transaction =
13322 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13323
13324 transaction->SetIOCallBackForTest(cb.callback());
13325 transaction->SetCacheIOCallBackForTest(cb.callback());
13326
13327 // Create the backend here as our direct calls to CreateEntry and OpenEntry
13328 // below require that it exists.
13329 cache.backend();
13330
13331 // Need a mock transaction in order to use some of MockHttpCache's
13332 // functions.
13333 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13334
13335 scoped_refptr<ActiveEntry> entry1 = nullptr;
13336 scoped_refptr<ActiveEntry> entry2 = nullptr;
13337
13338 cache.disk_cache()->set_force_fail_callback_later(true);
13339
13340 // Queue up our operations.
13341 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13342 transaction.get());
13343 ASSERT_EQ(rv, ERR_IO_PENDING);
13344 cache.disk_cache()->set_force_fail_callback_later(false);
13345 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry2,
13346 transaction.get());
13347 ASSERT_EQ(rv, ERR_IO_PENDING);
13348
13349 // Wait for all the results to arrive.
13350 cb.GetResult(rv);
13351 ASSERT_EQ(cb.results().size(), 2u);
13352
13353 // Verify that CreateEntry failed correctly.
13354 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13355 ASSERT_EQ(entry1, nullptr);
13356 // Verify that the OpenEntry requests a restart (CACHE_RACE).
13357 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13358 ASSERT_EQ(entry2, nullptr);
13359 }
13360
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByCreate)13361 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByCreate) {
13362 MockHttpCache cache;
13363 TestCompletionCallbackForHttpCache cb;
13364 std::unique_ptr<Transaction> transaction =
13365 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13366
13367 transaction->SetIOCallBackForTest(cb.callback());
13368 transaction->SetCacheIOCallBackForTest(cb.callback());
13369
13370 // Create the backend here as our direct calls to CreateEntry below require
13371 // that it exists.
13372 cache.backend();
13373
13374 // Need a mock transaction in order to use some of MockHttpCache's
13375 // functions.
13376 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13377
13378 scoped_refptr<ActiveEntry> entry1 = nullptr;
13379 scoped_refptr<ActiveEntry> entry2 = nullptr;
13380
13381 cache.disk_cache()->set_force_fail_callback_later(true);
13382
13383 // Queue up our operations.
13384 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13385 transaction.get());
13386 ASSERT_EQ(rv, ERR_IO_PENDING);
13387 cache.disk_cache()->set_force_fail_callback_later(false);
13388 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13389 transaction.get());
13390 ASSERT_EQ(rv, ERR_IO_PENDING);
13391
13392 // Wait for all the results to arrive.
13393 cb.GetResult(rv);
13394 ASSERT_EQ(cb.results().size(), 2u);
13395
13396 // Verify the CreateEntry(s) failed.
13397 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13398 ASSERT_EQ(entry1, nullptr);
13399 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13400 ASSERT_EQ(entry2, nullptr);
13401 }
13402
TEST_F(HttpCacheIOCallbackTest,CreateFollowedByCreate)13403 TEST_F(HttpCacheIOCallbackTest, CreateFollowedByCreate) {
13404 MockHttpCache cache;
13405 TestCompletionCallbackForHttpCache cb;
13406 std::unique_ptr<Transaction> transaction =
13407 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13408
13409 transaction->SetIOCallBackForTest(cb.callback());
13410 transaction->SetCacheIOCallBackForTest(cb.callback());
13411
13412 // Create the backend here as our direct calls to CreateEntry below require
13413 // that it exists.
13414 cache.backend();
13415
13416 // Need a mock transaction in order to use some of MockHttpCache's
13417 // functions.
13418 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13419
13420 scoped_refptr<ActiveEntry> entry1 = nullptr;
13421 scoped_refptr<ActiveEntry> entry2 = nullptr;
13422
13423 // Queue up our operations.
13424 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13425 transaction.get());
13426 ASSERT_EQ(rv, ERR_IO_PENDING);
13427 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13428 transaction.get());
13429 ASSERT_EQ(rv, ERR_IO_PENDING);
13430
13431 // Wait for all the results to arrive.
13432 cb.GetResult(rv);
13433 ASSERT_EQ(cb.results().size(), 2u);
13434
13435 // Verify that the first CreateEntry succeeded.
13436 ASSERT_EQ(cb.results()[0], OK);
13437 ASSERT_NE(entry1, nullptr);
13438 // Verify that the second CreateEntry failed.
13439 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13440 ASSERT_EQ(entry2, nullptr);
13441 }
13442
TEST_F(HttpCacheIOCallbackTest,OperationFollowedByDoom)13443 TEST_F(HttpCacheIOCallbackTest, OperationFollowedByDoom) {
13444 MockHttpCache cache;
13445 TestCompletionCallbackForHttpCache cb;
13446 std::unique_ptr<Transaction> transaction =
13447 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13448
13449 transaction->SetIOCallBackForTest(cb.callback());
13450 transaction->SetCacheIOCallBackForTest(cb.callback());
13451
13452 // Create the backend here as our direct calls to CreateEntry and DoomEntry
13453 // below require that it exists.
13454 cache.backend();
13455
13456 // Need a mock transaction in order to use some of MockHttpCache's
13457 // functions.
13458 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13459
13460 scoped_refptr<ActiveEntry> entry1 = nullptr;
13461
13462 // Queue up our operations.
13463 // For this test all we need is some operation followed by a doom, a create
13464 // fulfills that requirement.
13465 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13466 transaction.get());
13467 ASSERT_EQ(rv, ERR_IO_PENDING);
13468 rv = DoomEntry(cache.http_cache(), m_transaction.url, transaction.get());
13469 ASSERT_EQ(rv, ERR_IO_PENDING);
13470
13471 // Wait for all the results to arrive.
13472 cb.GetResult(rv);
13473 ASSERT_EQ(cb.results().size(), 2u);
13474
13475 // Verify that the CreateEntry succeeded.
13476 ASSERT_EQ(cb.results()[0], OK);
13477 // Verify that the DoomEntry requests a restart (CACHE_RACE).
13478 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13479 }
13480
TEST_F(HttpCacheIOCallbackTest,CreateFollowedByOpenOrCreate)13481 TEST_F(HttpCacheIOCallbackTest, CreateFollowedByOpenOrCreate) {
13482 MockHttpCache cache;
13483 TestCompletionCallbackForHttpCache cb;
13484 std::unique_ptr<Transaction> transaction =
13485 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13486
13487 transaction->SetIOCallBackForTest(cb.callback());
13488 transaction->SetCacheIOCallBackForTest(cb.callback());
13489
13490 // Create the backend here as our direct calls to CreateEntry and
13491 // OpenOrCreateEntry below require that it exists.
13492 cache.backend();
13493
13494 // Need a mock transaction in order to use some of MockHttpCache's
13495 // functions.
13496 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13497
13498 scoped_refptr<ActiveEntry> entry1 = nullptr;
13499 scoped_refptr<ActiveEntry> entry2 = nullptr;
13500
13501 // Queue up our operations.
13502 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13503 transaction.get());
13504 ASSERT_EQ(rv, ERR_IO_PENDING);
13505 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13506 transaction.get());
13507 ASSERT_EQ(rv, ERR_IO_PENDING);
13508
13509 // Wait for all the results to arrive.
13510 cb.GetResult(rv);
13511 ASSERT_EQ(cb.results().size(), 2u);
13512
13513 // Verify that the CreateEntry succeeded.
13514 ASSERT_EQ(cb.results()[0], OK);
13515 ASSERT_NE(entry1, nullptr);
13516 // Verify that OpenOrCreateEntry succeeded.
13517 ASSERT_EQ(cb.results()[1], OK);
13518 ASSERT_NE(entry2, nullptr);
13519 ASSERT_EQ(entry1->GetEntry(), entry2->GetEntry());
13520 }
13521
TEST_F(HttpCacheIOCallbackTest,FailedCreateFollowedByOpenOrCreate)13522 TEST_F(HttpCacheIOCallbackTest, FailedCreateFollowedByOpenOrCreate) {
13523 MockHttpCache cache;
13524 TestCompletionCallbackForHttpCache cb;
13525 std::unique_ptr<Transaction> transaction =
13526 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13527
13528 transaction->SetIOCallBackForTest(cb.callback());
13529 transaction->SetCacheIOCallBackForTest(cb.callback());
13530
13531 // Create the backend here as our direct calls to CreateEntry and
13532 // OpenOrCreateEntry below require that it exists.
13533 cache.backend();
13534
13535 // Need a mock transaction in order to use some of MockHttpCache's
13536 // functions.
13537 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13538
13539 scoped_refptr<ActiveEntry> entry1 = nullptr;
13540 scoped_refptr<ActiveEntry> entry2 = nullptr;
13541
13542 cache.disk_cache()->set_force_fail_callback_later(true);
13543
13544 // Queue up our operations.
13545 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13546 transaction.get());
13547 ASSERT_EQ(rv, ERR_IO_PENDING);
13548 cache.disk_cache()->set_force_fail_callback_later(false);
13549 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13550 transaction.get());
13551 ASSERT_EQ(rv, ERR_IO_PENDING);
13552
13553 // Wait for all the results to arrive.
13554 cb.GetResult(rv);
13555 ASSERT_EQ(cb.results().size(), 2u);
13556
13557 // Verify that CreateEntry failed correctly.
13558 ASSERT_EQ(cb.results()[0], ERR_CACHE_CREATE_FAILURE);
13559 ASSERT_EQ(entry1, nullptr);
13560 // Verify that the OpenOrCreateEntry requests a restart (CACHE_RACE).
13561 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13562 ASSERT_EQ(entry2, nullptr);
13563 }
13564
TEST_F(HttpCacheIOCallbackTest,OpenFollowedByOpenOrCreate)13565 TEST_F(HttpCacheIOCallbackTest, OpenFollowedByOpenOrCreate) {
13566 MockHttpCache cache;
13567 TestCompletionCallbackForHttpCache cb;
13568 std::unique_ptr<Transaction> transaction =
13569 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13570
13571 transaction->SetIOCallBackForTest(cb.callback());
13572 transaction->SetCacheIOCallBackForTest(cb.callback());
13573
13574 // Create the backend here as our direct calls to OpenEntry and
13575 // OpenOrCreateEntry below require that it exists.
13576 cache.backend();
13577
13578 // Need a mock transaction in order to use some of MockHttpCache's
13579 // functions.
13580 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13581
13582 scoped_refptr<ActiveEntry> entry0 = nullptr;
13583 scoped_refptr<ActiveEntry> entry1 = nullptr;
13584 scoped_refptr<ActiveEntry> entry2 = nullptr;
13585
13586 // First need to create and entry so we can open it.
13587 int rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry0,
13588 transaction.get());
13589 ASSERT_EQ(rv, ERR_IO_PENDING);
13590 cb.GetResult(rv);
13591 ASSERT_EQ(cb.results().size(), static_cast<size_t>(1));
13592 ASSERT_EQ(cb.results()[0], OK);
13593 ASSERT_NE(entry0, nullptr);
13594 // Manually Deactivate() `entry0` because OpenEntry() fails if there is an
13595 // existing active entry.
13596 entry0.reset();
13597
13598 // Queue up our operations.
13599 rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13600 transaction.get());
13601 ASSERT_EQ(rv, ERR_IO_PENDING);
13602 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13603 transaction.get());
13604 ASSERT_EQ(rv, ERR_IO_PENDING);
13605
13606 // Wait for all the results to arrive.
13607 cb.GetResult(rv);
13608 ASSERT_EQ(cb.results().size(), 3u);
13609
13610 // Verify that the OpenEntry succeeded.
13611 ASSERT_EQ(cb.results()[1], OK);
13612 ASSERT_NE(entry1, nullptr);
13613 // Verify that OpenOrCreateEntry succeeded.
13614 ASSERT_EQ(cb.results()[2], OK);
13615 ASSERT_NE(entry2, nullptr);
13616 ASSERT_EQ(entry1->GetEntry(), entry2->GetEntry());
13617 }
13618
TEST_F(HttpCacheIOCallbackTest,FailedOpenFollowedByOpenOrCreate)13619 TEST_F(HttpCacheIOCallbackTest, FailedOpenFollowedByOpenOrCreate) {
13620 MockHttpCache cache;
13621 TestCompletionCallbackForHttpCache cb;
13622 std::unique_ptr<Transaction> transaction =
13623 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13624
13625 transaction->SetIOCallBackForTest(cb.callback());
13626 transaction->SetCacheIOCallBackForTest(cb.callback());
13627
13628 // Create the backend here as our direct calls to OpenEntry and
13629 // OpenOrCreateEntry below require that it exists.
13630 cache.backend();
13631
13632 // Need a mock transaction in order to use some of MockHttpCache's
13633 // functions.
13634 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13635
13636 scoped_refptr<ActiveEntry> entry1 = nullptr;
13637 scoped_refptr<ActiveEntry> entry2 = nullptr;
13638
13639 cache.disk_cache()->set_force_fail_callback_later(true);
13640
13641 // Queue up our operations.
13642 int rv = OpenEntry(cache.http_cache(), m_transaction.url, &entry1,
13643 transaction.get());
13644 ASSERT_EQ(rv, ERR_IO_PENDING);
13645 cache.disk_cache()->set_force_fail_callback_later(false);
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 OpenEntry failed correctly.
13655 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_FAILURE);
13656 ASSERT_EQ(entry1, nullptr);
13657 // Verify that the OpenOrCreateEntry requests a restart (CACHE_RACE).
13658 ASSERT_EQ(cb.results()[1], ERR_CACHE_RACE);
13659 ASSERT_EQ(entry2, nullptr);
13660 }
13661
TEST_F(HttpCacheIOCallbackTest,OpenOrCreateFollowedByCreate)13662 TEST_F(HttpCacheIOCallbackTest, OpenOrCreateFollowedByCreate) {
13663 MockHttpCache cache;
13664 TestCompletionCallbackForHttpCache cb;
13665 std::unique_ptr<Transaction> transaction =
13666 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13667
13668 transaction->SetIOCallBackForTest(cb.callback());
13669 transaction->SetCacheIOCallBackForTest(cb.callback());
13670
13671 // Create the backend here as our direct calls to OpenOrCreateEntry and
13672 // CreateEntry 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 scoped_refptr<ActiveEntry> entry1 = nullptr;
13680 scoped_refptr<ActiveEntry> entry2 = nullptr;
13681
13682 // Queue up our operations.
13683 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13684 transaction.get());
13685 ASSERT_EQ(rv, ERR_IO_PENDING);
13686 rv = CreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13687 transaction.get());
13688 ASSERT_EQ(rv, ERR_IO_PENDING);
13689
13690 // Wait for all the results to arrive.
13691 cb.GetResult(rv);
13692 ASSERT_EQ(cb.results().size(), 2u);
13693
13694 // Verify that the OpenOrCreateEntry succeeded.
13695 ASSERT_EQ(cb.results()[0], OK);
13696 ASSERT_NE(entry1, nullptr);
13697 // Verify that CreateEntry failed.
13698 ASSERT_EQ(cb.results()[1], ERR_CACHE_CREATE_FAILURE);
13699 ASSERT_EQ(entry2, nullptr);
13700 }
13701
TEST_F(HttpCacheIOCallbackTest,OpenOrCreateFollowedByOpenOrCreate)13702 TEST_F(HttpCacheIOCallbackTest, OpenOrCreateFollowedByOpenOrCreate) {
13703 MockHttpCache cache;
13704 TestCompletionCallbackForHttpCache cb;
13705 std::unique_ptr<Transaction> transaction =
13706 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13707
13708 transaction->SetIOCallBackForTest(cb.callback());
13709 transaction->SetCacheIOCallBackForTest(cb.callback());
13710
13711 // Create the backend here as our direct calls to OpenOrCreateEntry below
13712 // require that it exists.
13713 cache.backend();
13714
13715 // Need a mock transaction in order to use some of MockHttpCache's
13716 // functions.
13717 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13718
13719 scoped_refptr<ActiveEntry> entry1 = nullptr;
13720 scoped_refptr<ActiveEntry> entry2 = nullptr;
13721
13722 // Queue up our operations.
13723 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13724 transaction.get());
13725 ASSERT_EQ(rv, ERR_IO_PENDING);
13726 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13727 transaction.get());
13728 ASSERT_EQ(rv, ERR_IO_PENDING);
13729
13730 // Wait for all the results to arrive.
13731 cb.GetResult(rv);
13732 ASSERT_EQ(cb.results().size(), 2u);
13733
13734 // Verify that the OpenOrCreateEntry succeeded.
13735 ASSERT_EQ(cb.results()[0], OK);
13736 ASSERT_NE(entry1, nullptr);
13737 // Verify that the other succeeded.
13738 ASSERT_EQ(cb.results()[1], OK);
13739 ASSERT_NE(entry2, nullptr);
13740 }
13741
TEST_F(HttpCacheIOCallbackTest,FailedOpenOrCreateFollowedByOpenOrCreate)13742 TEST_F(HttpCacheIOCallbackTest, FailedOpenOrCreateFollowedByOpenOrCreate) {
13743 MockHttpCache cache;
13744 TestCompletionCallbackForHttpCache cb;
13745 std::unique_ptr<Transaction> transaction =
13746 std::make_unique<Transaction>(DEFAULT_PRIORITY, cache.http_cache());
13747
13748 transaction->SetIOCallBackForTest(cb.callback());
13749 transaction->SetCacheIOCallBackForTest(cb.callback());
13750
13751 // Create the backend here as our direct calls to OpenOrCreateEntry below
13752 // require that it exists.
13753 cache.backend();
13754
13755 // Need a mock transaction in order to use some of MockHttpCache's
13756 // functions.
13757 ScopedMockTransaction m_transaction(kSimpleGET_Transaction);
13758
13759 scoped_refptr<ActiveEntry> entry1 = nullptr;
13760 scoped_refptr<ActiveEntry> entry2 = nullptr;
13761
13762 cache.disk_cache()->set_force_fail_callback_later(true);
13763
13764 // Queue up our operations.
13765 int rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry1,
13766 transaction.get());
13767 ASSERT_EQ(rv, ERR_IO_PENDING);
13768 cache.disk_cache()->set_force_fail_callback_later(false);
13769 rv = OpenOrCreateEntry(cache.http_cache(), m_transaction.url, &entry2,
13770 transaction.get());
13771 ASSERT_EQ(rv, ERR_IO_PENDING);
13772
13773 // Wait for all the results to arrive.
13774 cb.GetResult(rv);
13775 ASSERT_EQ(cb.results().size(), 2u);
13776
13777 // Verify that the OpenOrCreateEntry failed.
13778 ASSERT_EQ(cb.results()[0], ERR_CACHE_OPEN_OR_CREATE_FAILURE);
13779 ASSERT_EQ(entry1, nullptr);
13780 // Verify that the other failed.
13781 ASSERT_EQ(cb.results()[1], ERR_CACHE_OPEN_OR_CREATE_FAILURE);
13782 ASSERT_EQ(entry2, nullptr);
13783 }
13784
TEST_F(HttpCacheTest,DnsAliasesNoRevalidation)13785 TEST_F(HttpCacheTest, DnsAliasesNoRevalidation) {
13786 MockHttpCache cache;
13787 HttpResponseInfo response;
13788 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13789 transaction.dns_aliases = {"alias1", "alias2"};
13790
13791 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13792 &response);
13793 EXPECT_FALSE(response.was_cached);
13794 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
13795
13796 // The second request result in a cache hit and the response used without
13797 // revalidation. Set the transaction alias list to empty to verify that the
13798 // cached aliases are being used.
13799 transaction.dns_aliases = {};
13800 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13801 &response);
13802 EXPECT_TRUE(response.was_cached);
13803 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
13804 }
13805
TEST_F(HttpCacheTest,NoDnsAliasesNoRevalidation)13806 TEST_F(HttpCacheTest, NoDnsAliasesNoRevalidation) {
13807 MockHttpCache cache;
13808 HttpResponseInfo response;
13809 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13810 transaction.dns_aliases = {};
13811
13812 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13813 &response);
13814 EXPECT_FALSE(response.was_cached);
13815 EXPECT_TRUE(response.dns_aliases.empty());
13816
13817 // The second request should result in a cache hit and the response used
13818 // without revalidation. Set the transaction alias list to nonempty to verify
13819 // that the cached aliases are being used.
13820 transaction.dns_aliases = {"alias"};
13821 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13822 &response);
13823 EXPECT_TRUE(response.was_cached);
13824 EXPECT_TRUE(response.dns_aliases.empty());
13825 }
13826
TEST_F(HttpCacheTest,DnsAliasesRevalidation)13827 TEST_F(HttpCacheTest, DnsAliasesRevalidation) {
13828 MockHttpCache cache;
13829 HttpResponseInfo response;
13830 ScopedMockTransaction transaction(kTypicalGET_Transaction);
13831 transaction.response_headers =
13832 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
13833 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
13834 "Cache-Control: max-age=0\n";
13835 transaction.dns_aliases = {"alias1", "alias2"};
13836
13837 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13838 &response);
13839 EXPECT_FALSE(response.was_cached);
13840 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias1", "alias2"));
13841
13842 // On the second request, the cache should be revalidated. Change the aliases
13843 // to be sure that the new aliases are being used, and have the response be
13844 // cached for next time.
13845 transaction.response_headers = "Cache-Control: max-age=10000\n";
13846 transaction.dns_aliases = {"alias3", "alias4"};
13847 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13848 &response);
13849 EXPECT_FALSE(response.was_cached);
13850 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias3", "alias4"));
13851
13852 transaction.dns_aliases = {"alias5", "alias6"};
13853 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13854 &response);
13855 EXPECT_TRUE(response.was_cached);
13856 EXPECT_THAT(response.dns_aliases, testing::ElementsAre("alias3", "alias4"));
13857 }
13858
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldBypass_NoId)13859 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldBypass_NoId) {
13860 MockHttpCache cache;
13861 HttpResponseInfo response;
13862 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13863
13864 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13865 &response);
13866 EXPECT_FALSE(response.was_cached);
13867
13868 transaction.fps_cache_filter = {5};
13869 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13870 &response);
13871 EXPECT_FALSE(response.was_cached);
13872 }
13873
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldBypass_IdTooSmall)13874 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldBypass_IdTooSmall) {
13875 MockHttpCache cache;
13876 HttpResponseInfo response;
13877 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13878 const int64_t kBrowserRunId = 4;
13879 transaction.browser_run_id = {kBrowserRunId};
13880 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13881 &response);
13882 EXPECT_FALSE(response.was_cached);
13883 EXPECT_TRUE(response.browser_run_id.has_value());
13884 EXPECT_EQ(kBrowserRunId, response.browser_run_id.value());
13885
13886 transaction.fps_cache_filter = {5};
13887 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13888 &response);
13889 EXPECT_FALSE(response.was_cached);
13890 }
13891
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldNotBypass)13892 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldNotBypass) {
13893 MockHttpCache cache;
13894 HttpResponseInfo response;
13895 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13896 const int64_t kBrowserRunId = 5;
13897 transaction.browser_run_id = {kBrowserRunId};
13898 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13899 &response);
13900 EXPECT_FALSE(response.was_cached);
13901 EXPECT_TRUE(response.browser_run_id.has_value());
13902 EXPECT_EQ(kBrowserRunId, response.browser_run_id.value());
13903
13904 transaction.fps_cache_filter = {5};
13905 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13906 &response);
13907 EXPECT_TRUE(response.was_cached);
13908 }
13909
TEST_F(HttpCacheTest,FirstPartySetsBypassCache_ShouldNotBypass_NoFilter)13910 TEST_F(HttpCacheTest, FirstPartySetsBypassCache_ShouldNotBypass_NoFilter) {
13911 MockHttpCache cache;
13912 HttpResponseInfo response;
13913 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13914
13915 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13916 &response);
13917 EXPECT_FALSE(response.was_cached);
13918
13919 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13920 &response);
13921 EXPECT_TRUE(response.was_cached);
13922 }
13923
TEST_F(HttpCacheTest,SecurityHeadersAreCopiedToConditionalizedResponse)13924 TEST_F(HttpCacheTest, SecurityHeadersAreCopiedToConditionalizedResponse) {
13925 MockHttpCache cache;
13926 HttpResponseInfo response;
13927 ScopedMockTransaction transaction(kSimpleGET_Transaction);
13928
13929 static const Response kNetResponse1 = {
13930 "HTTP/1.1 200 OK",
13931 "Date: Fri, 12 Jun 2009 21:46:42 GMT\n"
13932 "Server: server1\n"
13933 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n"
13934 "Cross-Origin-Resource-Policy: cross-origin\n",
13935 "body1"};
13936
13937 static const Response kNetResponse2 = {
13938 "HTTP/1.1 304 Not Modified",
13939 "Date: Wed, 22 Jul 2009 03:15:26 GMT\n"
13940 "Server: server2\n"
13941 "Last-Modified: Wed, 06 Feb 2008 22:38:21 GMT\n",
13942 ""};
13943
13944 kNetResponse1.AssignTo(&transaction);
13945 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13946 &response);
13947
13948 // On the second request, the cache is revalidated.
13949 const char kExtraRequestHeaders[] =
13950 "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n";
13951 transaction.request_headers = kExtraRequestHeaders;
13952 kNetResponse2.AssignTo(&transaction);
13953 RunTransactionTestWithResponseInfo(cache.http_cache(), transaction,
13954 &response);
13955
13956 // Verify that the CORP header was carried over to the response.
13957 std::string response_corp_header;
13958 response.headers->GetNormalizedHeader("Cross-Origin-Resource-Policy",
13959 &response_corp_header);
13960
13961 EXPECT_EQ(304, response.headers->response_code());
13962 EXPECT_EQ("cross-origin", response_corp_header);
13963 }
13964
13965 } // namespace net
13966