Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: net/http/http_cache_unittest.cc

Issue 1230113012: [net] Better StopCaching() handling for HttpCache::Transaction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add missing MockTransaction initializers Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_cache.h" 5 #include "net/http/http_cache.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <list>
10 11
11 #include "base/bind.h" 12 #include "base/bind.h"
12 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/format_macros.h"
13 #include "base/memory/scoped_vector.h" 15 #include "base/memory/scoped_vector.h"
14 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h" 17 #include "base/run_loop.h"
16 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
18 #include "base/test/simple_test_clock.h" 20 #include "base/test/simple_test_clock.h"
19 #include "net/base/cache_type.h" 21 #include "net/base/cache_type.h"
20 #include "net/base/elements_upload_data_stream.h" 22 #include "net/base/elements_upload_data_stream.h"
21 #include "net/base/host_port_pair.h" 23 #include "net/base/host_port_pair.h"
22 #include "net/base/load_flags.h" 24 #include "net/base/load_flags.h"
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 base::Time(), 275 base::Time(),
274 "", 276 "",
275 LOAD_VALIDATE_CACHE, 277 LOAD_VALIDATE_CACHE,
276 "HTTP/1.1 200 OK", 278 "HTTP/1.1 200 OK",
277 "Cache-Control: max-age=10000\n", 279 "Cache-Control: max-age=10000\n",
278 base::Time(), 280 base::Time(),
279 "<html><body>Google Blah Blah</body></html>", 281 "<html><body>Google Blah Blah</body></html>",
280 TEST_MODE_SYNC_NET_START, 282 TEST_MODE_SYNC_NET_START,
281 &FastTransactionServer::FastNoStoreHandler, 283 &FastTransactionServer::FastNoStoreHandler,
282 nullptr, 284 nullptr,
285 nullptr,
283 0, 286 0,
284 0, 287 0,
285 OK}; 288 OK};
286 289
287 // This class provides a handler for kRangeGET_TransactionOK so that the range 290 // This class provides a handler for kRangeGET_TransactionOK so that the range
288 // request can be served on demand. 291 // request can be served on demand.
289 class RangeTransactionServer { 292 class RangeTransactionServer {
290 public: 293 public:
291 RangeTransactionServer() { 294 RangeTransactionServer() {
292 not_modified_ = false; 295 not_modified_ = false;
(...skipping 13 matching lines...) Expand all
306 void set_modified(bool value) { modified_ = value; } 309 void set_modified(bool value) { modified_ = value; }
307 310
308 // Returns 200 instead of 206 (a malformed response overall). 311 // Returns 200 instead of 206 (a malformed response overall).
309 void set_bad_200(bool value) { bad_200_ = value; } 312 void set_bad_200(bool value) { bad_200_ = value; }
310 313
311 // Other than regular range related behavior (and the flags mentioned above), 314 // Other than regular range related behavior (and the flags mentioned above),
312 // the server reacts to requests headers like so: 315 // the server reacts to requests headers like so:
313 // X-Require-Mock-Auth -> return 401. 316 // X-Require-Mock-Auth -> return 401.
314 // X-Require-Mock-Auth-Alt -> return 401. 317 // X-Require-Mock-Auth-Alt -> return 401.
315 // X-Return-Default-Range -> assume 40-49 was requested. 318 // X-Return-Default-Range -> assume 40-49 was requested.
319 // X-No-Ranges -> Returns "Not a range" if the request is not a valid range
320 // request.
316 // The -Alt variant doesn't cause the MockNetworkTransaction to 321 // The -Alt variant doesn't cause the MockNetworkTransaction to
317 // report that it IsReadyToRestartForAuth(). 322 // report that it IsReadyToRestartForAuth().
318 static void RangeHandler(const HttpRequestInfo* request, 323 static void RangeHandler(const HttpRequestInfo* request,
319 std::string* response_status, 324 std::string* response_status,
320 std::string* response_headers, 325 std::string* response_headers,
321 std::string* response_data); 326 std::string* response_data);
322 327
323 private: 328 private:
324 static bool not_modified_; 329 static bool not_modified_;
325 static bool modified_; 330 static bool modified_;
326 static bool bad_200_; 331 static bool bad_200_;
327 DISALLOW_COPY_AND_ASSIGN(RangeTransactionServer); 332 DISALLOW_COPY_AND_ASSIGN(RangeTransactionServer);
328 }; 333 };
329 bool RangeTransactionServer::not_modified_ = false; 334 bool RangeTransactionServer::not_modified_ = false;
330 bool RangeTransactionServer::modified_ = false; 335 bool RangeTransactionServer::modified_ = false;
331 bool RangeTransactionServer::bad_200_ = false; 336 bool RangeTransactionServer::bad_200_ = false;
332 337
333 // A dummy extra header that must be preserved on a given request. 338 // A dummy extra header that must be preserved on a given request.
334 339
335 // EXTRA_HEADER_LINE doesn't include a line terminator because it 340 // EXTRA_HEADER_LINE doesn't include a line terminator because it
336 // will be passed to AddHeaderFromString() which doesn't accept them. 341 // will be passed to AddHeaderFromString() which doesn't accept them.
337 #define EXTRA_HEADER_LINE "Extra: header" 342 #define EXTRA_HEADER_LINE "Extra: header"
338 343
339 // EXTRA_HEADER contains a line terminator, as expected by 344 // EXTRA_HEADER contains a line terminator, as expected by
340 // AddHeadersFromString() (_not_ AddHeaderFromString()). 345 // AddHeadersFromString() (_not_ AddHeaderFromString()).
341 #define EXTRA_HEADER EXTRA_HEADER_LINE "\r\n" 346 #define EXTRA_HEADER EXTRA_HEADER_LINE "\r\n"
342 347
343 static const char kExtraHeaderKey[] = "Extra"; 348 #define RETURN_DEFAULT_RANGE_HEADER "X-Return-Default-Range: 1\r\n"
349
350 #define INDICATE_NO_RANGES_HEADER "X-No-Ranges: 1\r\n"
351
352 const char kExtraHeaderKey[] = "Extra";
353
354 const char kFullRangeData[] =
355 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 "
356 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 ";
344 357
345 // Static. 358 // Static.
346 void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request, 359 void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request,
347 std::string* response_status, 360 std::string* response_status,
348 std::string* response_headers, 361 std::string* response_headers,
349 std::string* response_data) { 362 std::string* response_data) {
363 SCOPED_TRACE(testing::Message() << "Request headers: \n"
364 << request->extra_headers.ToString());
350 if (request->extra_headers.IsEmpty()) { 365 if (request->extra_headers.IsEmpty()) {
351 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable"); 366 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
352 response_data->clear(); 367 response_data->clear();
353 return; 368 return;
354 } 369 }
355 370
356 // We want to make sure we don't delete extra headers. 371 // We want to make sure we don't delete extra headers.
357 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey)); 372 EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey));
358 373
359 bool require_auth = 374 bool require_auth =
(...skipping 13 matching lines...) Expand all
373 } 388 }
374 389
375 std::vector<HttpByteRange> ranges; 390 std::vector<HttpByteRange> ranges;
376 std::string range_header; 391 std::string range_header;
377 if (!request->extra_headers.GetHeader(HttpRequestHeaders::kRange, 392 if (!request->extra_headers.GetHeader(HttpRequestHeaders::kRange,
378 &range_header) || 393 &range_header) ||
379 !HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ || 394 !HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ ||
380 ranges.size() != 1) { 395 ranges.size() != 1) {
381 // This is not a byte range request. We return 200. 396 // This is not a byte range request. We return 200.
382 response_status->assign("HTTP/1.1 200 OK"); 397 response_status->assign("HTTP/1.1 200 OK");
383 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT"); 398 response_headers->assign("Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
384 response_data->assign("Not a range"); 399 if (request->extra_headers.HasHeader("X-No-Ranges")) {
400 response_data->assign("Not a range");
401 return;
402 }
403 response_headers->append(
404 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
405 "ETag: \"foo\"\n"
406 "Accept-Ranges: bytes\n"
407 "Content-Length: 80\n");
408 response_data->assign(kFullRangeData);
385 return; 409 return;
386 } 410 }
387 411
388 // We can handle this range request. 412 // We can handle this range request.
389 HttpByteRange byte_range = ranges[0]; 413 HttpByteRange byte_range = ranges[0];
390 414
391 if (request->extra_headers.HasHeader("X-Return-Default-Range")) { 415 if (request->extra_headers.HasHeader("X-Return-Default-Range")) {
392 byte_range.set_first_byte_position(40); 416 byte_range.set_first_byte_position(40);
393 byte_range.set_last_byte_position(49); 417 byte_range.set_last_byte_position(49);
394 } 418 }
395 419
396 if (byte_range.first_byte_position() > 79) { 420 if (byte_range.first_byte_position() > 79) {
397 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable"); 421 response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable");
398 response_data->clear(); 422 response_data->clear();
399 return; 423 return;
400 } 424 }
425 response_status->assign("HTTP/1.1 206 Partial");
401 426
402 EXPECT_TRUE(byte_range.ComputeBounds(80)); 427 EXPECT_TRUE(byte_range.ComputeBounds(80));
403 int start = static_cast<int>(byte_range.first_byte_position()); 428 int start = static_cast<int>(byte_range.first_byte_position());
404 int end = static_cast<int>(byte_range.last_byte_position()); 429 int end = static_cast<int>(byte_range.last_byte_position());
405 430
406 EXPECT_LT(end, 80); 431 EXPECT_LT(end, 80);
407 432
408 std::string content_range = base::StringPrintf( 433 std::string content_range = base::StringPrintf(
409 "Content-Range: bytes %d-%d/80\n", start, end); 434 "Content-Range: bytes %d-%d/80\n", start, end);
410 response_headers->append(content_range); 435 response_headers->append(content_range);
(...skipping 20 matching lines...) Expand all
431 response_headers->replace(response_headers->find("Content-Length:"), 456 response_headers->replace(response_headers->find("Content-Length:"),
432 content_length.size(), content_length); 457 content_length.size(), content_length);
433 } 458 }
434 } else { 459 } else {
435 response_status->assign("HTTP/1.1 304 Not Modified"); 460 response_status->assign("HTTP/1.1 304 Not Modified");
436 response_data->clear(); 461 response_data->clear();
437 } 462 }
438 } 463 }
439 464
440 const MockTransaction kRangeGET_TransactionOK = { 465 const MockTransaction kRangeGET_TransactionOK = {
441 "http://www.google.com/range", 466 "http://www.google.com/range", "GET", base::Time(),
442 "GET", 467 "Range: bytes = 40-49\r\n" EXTRA_HEADER, LOAD_NORMAL,
443 base::Time(),
444 "Range: bytes = 40-49\r\n" EXTRA_HEADER,
445 LOAD_NORMAL,
446 "HTTP/1.1 206 Partial Content", 468 "HTTP/1.1 206 Partial Content",
447 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" 469 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
448 "ETag: \"foo\"\n" 470 "ETag: \"foo\"\n"
449 "Accept-Ranges: bytes\n" 471 "Accept-Ranges: bytes\n"
450 "Content-Length: 10\n", 472 "Content-Length: 10\n",
451 base::Time(), 473 base::Time(), "rg: 40-49 ", TEST_MODE_NORMAL,
452 "rg: 40-49 ", 474 &RangeTransactionServer::RangeHandler, nullptr, nullptr, 0, 0, OK};
453 TEST_MODE_NORMAL,
454 &RangeTransactionServer::RangeHandler,
455 nullptr,
456 0,
457 0,
458 OK};
459 475
460 const char kFullRangeData[] = 476 const MockTransaction kResumableGET_Transaction = {
461 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 " 477 kRangeGET_TransactionOK.url, "GET", base::Time(), EXTRA_HEADER, LOAD_NORMAL,
462 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 "; 478 "HTTP/1.1 200 OK",
479 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
480 "Date: Sat, 18 Apr 2015 01:10:43 GMT\n"
481 "ETag: \"foo\"\n"
482 "Accept-Ranges: bytes\n"
483 "Content-Length: 80\n",
484 base::Time(), kFullRangeData, TEST_MODE_NORMAL,
485 &RangeTransactionServer::RangeHandler, nullptr, nullptr, 0, 0, OK};
463 486
464 // Verifies the response headers (|response|) match a partial content 487 // Verifies the response headers (|response|) match a partial content
465 // response for the range starting at |start| and ending at |end|. 488 // response for the range starting at |start| and ending at |end|.
466 void Verify206Response(std::string response, int start, int end) { 489 void Verify206Response(std::string response, int start, int end) {
467 std::string raw_headers( 490 std::string raw_headers(
468 HttpUtil::AssembleRawHeaders(response.data(), response.size())); 491 HttpUtil::AssembleRawHeaders(response.data(), response.size()));
469 scoped_refptr<HttpResponseHeaders> headers( 492 scoped_refptr<HttpResponseHeaders> headers(
470 new HttpResponseHeaders(raw_headers)); 493 new HttpResponseHeaders(raw_headers));
471 494
472 ASSERT_EQ(206, headers->response_code()); 495 ASSERT_EQ(206, headers->response_code());
(...skipping 1625 matching lines...) Expand 10 before | Expand all | Expand 10 after
2098 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n" 2121 "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n"
2099 "Cache-Control: max-age=0\n" 2122 "Cache-Control: max-age=0\n"
2100 "Vary: Foo\n"; 2123 "Vary: Foo\n";
2101 AddMockTransaction(&transaction); 2124 AddMockTransaction(&transaction);
2102 RunTransactionTest(cache.http_cache(), transaction); 2125 RunTransactionTest(cache.http_cache(), transaction);
2103 2126
2104 // Read from the cache and don't revalidate the entry. 2127 // Read from the cache and don't revalidate the entry.
2105 RevalidationServer server; 2128 RevalidationServer server;
2106 transaction.handler = server.Handler; 2129 transaction.handler = server.Handler;
2107 transaction.request_headers = "Foo: none\r\n"; 2130 transaction.request_headers = "Foo: none\r\n";
2131
2108 BoundTestNetLog log; 2132 BoundTestNetLog log;
2109 LoadTimingInfo load_timing_info; 2133 LoadTimingInfo load_timing_info;
2110 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(), 2134 RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
2111 &load_timing_info); 2135 &load_timing_info);
2112 2136
2113 EXPECT_FALSE(server.EtagUsed()); 2137 EXPECT_FALSE(server.EtagUsed());
2114 EXPECT_FALSE(server.LastModifiedUsed()); 2138 EXPECT_FALSE(server.LastModifiedUsed());
2115 EXPECT_EQ(2, cache.network_layer()->transaction_count()); 2139 EXPECT_EQ(2, cache.network_layer()->transaction_count());
2116 EXPECT_EQ(1, cache.disk_cache()->open_count()); 2140 EXPECT_EQ(1, cache.disk_cache()->open_count());
2117 EXPECT_EQ(1, cache.disk_cache()->create_count()); 2141 EXPECT_EQ(1, cache.disk_cache()->create_count());
(...skipping 1778 matching lines...) Expand 10 before | Expand all | Expand 10 after
3896 3920
3897 Verify206Response(headers, 40, 49); 3921 Verify206Response(headers, 40, 49);
3898 EXPECT_EQ(1, cache.network_layer()->transaction_count()); 3922 EXPECT_EQ(1, cache.network_layer()->transaction_count());
3899 EXPECT_EQ(0, cache.disk_cache()->open_count()); 3923 EXPECT_EQ(0, cache.disk_cache()->open_count());
3900 EXPECT_EQ(1, cache.disk_cache()->create_count()); 3924 EXPECT_EQ(1, cache.disk_cache()->create_count());
3901 3925
3902 // Now verify that the cached data is not used. 3926 // Now verify that the cached data is not used.
3903 // Don't ask for a range. The cache will attempt to use the cached data but 3927 // Don't ask for a range. The cache will attempt to use the cached data but
3904 // should discard it as it cannot be validated. A regular request should go 3928 // should discard it as it cannot be validated. A regular request should go
3905 // to the server and a new entry should be created. 3929 // to the server and a new entry should be created.
3906 transaction.request_headers = EXTRA_HEADER; 3930 transaction.request_headers = INDICATE_NO_RANGES_HEADER EXTRA_HEADER;
3907 transaction.data = "Not a range"; 3931 transaction.data = "Not a range";
3908 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); 3932 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
3909 3933
3910 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n")); 3934 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
3911 EXPECT_EQ(2, cache.network_layer()->transaction_count()); 3935 EXPECT_EQ(2, cache.network_layer()->transaction_count());
3912 EXPECT_EQ(1, cache.disk_cache()->open_count()); 3936 EXPECT_EQ(1, cache.disk_cache()->open_count());
3913 EXPECT_EQ(2, cache.disk_cache()->create_count()); 3937 EXPECT_EQ(2, cache.disk_cache()->create_count());
3914 3938
3915 // The last response was saved. 3939 // The last response was saved.
3916 RunTransactionTest(cache.http_cache(), transaction); 3940 RunTransactionTest(cache.http_cache(), transaction);
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
4364 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER; 4388 transaction.request_headers = "Range: bytes = 70-79\r\n" EXTRA_HEADER;
4365 transaction.data = "rg: 70-79 "; 4389 transaction.data = "rg: 70-79 ";
4366 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); 4390 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4367 Verify206Response(headers, 70, 79); 4391 Verify206Response(headers, 70, 79);
4368 4392
4369 // Don't ask for a range. The cache will ask the server for 0-69. 4393 // Don't ask for a range. The cache will ask the server for 0-69.
4370 // The server returns 40-49. The cache should consider the server confused and 4394 // The server returns 40-49. The cache should consider the server confused and
4371 // abort caching, restarting the request. 4395 // abort caching, restarting the request.
4372 // The second network request should not be a byte range request so the server 4396 // The second network request should not be a byte range request so the server
4373 // should return 200 + "Not a range" 4397 // should return 200 + "Not a range"
4374 transaction.request_headers = "X-Return-Default-Range:\r\n" EXTRA_HEADER; 4398 transaction.request_headers =
4399 RETURN_DEFAULT_RANGE_HEADER INDICATE_NO_RANGES_HEADER EXTRA_HEADER;
4375 transaction.data = "Not a range"; 4400 transaction.data = "Not a range";
4376 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); 4401 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
4377 4402
4378 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n")); 4403 EXPECT_EQ(0U, headers.find("HTTP/1.1 200 OK\n"));
4379 EXPECT_EQ(3, cache.network_layer()->transaction_count()); 4404 EXPECT_EQ(3, cache.network_layer()->transaction_count());
4380 EXPECT_EQ(1, cache.disk_cache()->open_count()); 4405 EXPECT_EQ(1, cache.disk_cache()->open_count());
4381 EXPECT_EQ(1, cache.disk_cache()->create_count()); 4406 EXPECT_EQ(1, cache.disk_cache()->create_count());
4382 4407
4383 // The entry was deleted. 4408 // The entry was deleted.
4384 RunTransactionTest(cache.http_cache(), transaction); 4409 RunTransactionTest(cache.http_cache(), transaction);
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
4756 Verify206Response(headers, 0, 9); 4781 Verify206Response(headers, 0, 9);
4757 EXPECT_EQ(1, cache.network_layer()->transaction_count()); 4782 EXPECT_EQ(1, cache.network_layer()->transaction_count());
4758 EXPECT_EQ(0, cache.disk_cache()->open_count()); 4783 EXPECT_EQ(0, cache.disk_cache()->open_count());
4759 EXPECT_EQ(1, cache.disk_cache()->create_count()); 4784 EXPECT_EQ(1, cache.disk_cache()->create_count());
4760 4785
4761 // Now we'll issue a request without any range that should result first in a 4786 // Now we'll issue a request without any range that should result first in a
4762 // 206 (when revalidating), and then in a weird standard answer: the test 4787 // 206 (when revalidating), and then in a weird standard answer: the test
4763 // server will not modify the response so we'll get the default range... a 4788 // server will not modify the response so we'll get the default range... a
4764 // real server will answer with 200. 4789 // real server will answer with 200.
4765 MockTransaction transaction2(kRangeGET_TransactionOK); 4790 MockTransaction transaction2(kRangeGET_TransactionOK);
4766 transaction2.request_headers = EXTRA_HEADER; 4791 transaction2.request_headers = INDICATE_NO_RANGES_HEADER EXTRA_HEADER;
4767 transaction2.load_flags |= LOAD_VALIDATE_CACHE; 4792 transaction2.load_flags |= LOAD_VALIDATE_CACHE;
4768 transaction2.data = "Not a range"; 4793 transaction2.data = "Not a range";
4769 RangeTransactionServer handler; 4794 RangeTransactionServer handler;
4770 handler.set_modified(true); 4795 handler.set_modified(true);
4771 BoundTestNetLog log; 4796 BoundTestNetLog log;
4772 LoadTimingInfo load_timing_info; 4797 LoadTimingInfo load_timing_info;
4773 RunTransactionTestWithResponseAndGetTiming( 4798 RunTransactionTestWithResponseAndGetTiming(
4774 cache.http_cache(), transaction2, &headers, log.bound(), 4799 cache.http_cache(), transaction2, &headers, log.bound(),
4775 &load_timing_info); 4800 &load_timing_info);
4776 4801
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
5366 5391
5367 RemoveMockTransaction(&kRangeGET_TransactionOK); 5392 RemoveMockTransaction(&kRangeGET_TransactionOK);
5368 } 5393 }
5369 5394
5370 // Tests that we don't crash when after reading from the cache we issue a 5395 // Tests that we don't crash when after reading from the cache we issue a
5371 // request for the next range and the server gives us a 200 synchronously. 5396 // request for the next range and the server gives us a 200 synchronously.
5372 TEST(HttpCache, RangeGET_FastFlakyServer) { 5397 TEST(HttpCache, RangeGET_FastFlakyServer) {
5373 MockHttpCache cache; 5398 MockHttpCache cache;
5374 5399
5375 ScopedMockTransaction transaction(kRangeGET_TransactionOK); 5400 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
5376 transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER; 5401 transaction.request_headers =
5402 "Range: bytes = 40-\r\n" INDICATE_NO_RANGES_HEADER EXTRA_HEADER;
5377 transaction.test_mode = TEST_MODE_SYNC_NET_START; 5403 transaction.test_mode = TEST_MODE_SYNC_NET_START;
5378 transaction.load_flags |= LOAD_VALIDATE_CACHE; 5404 transaction.load_flags |= LOAD_VALIDATE_CACHE;
5379 5405
5380 // Write to the cache. 5406 // Write to the cache.
5381 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); 5407 RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK);
5382 5408
5383 // And now read from the cache and the network. 5409 // And now read from the cache and the network.
5384 RangeTransactionServer handler; 5410 RangeTransactionServer handler;
5385 handler.set_bad_200(true); 5411 handler.set_bad_200(true);
5386 transaction.data = "Not a range"; 5412 transaction.data = "Not a range";
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
5941 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" 5967 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
5942 "ETag: \"foo\"\n" 5968 "ETag: \"foo\"\n"
5943 "Accept-Ranges: bytes\n" 5969 "Accept-Ranges: bytes\n"
5944 "Content-Length: 50\n"); 5970 "Content-Length: 50\n");
5945 CreateTruncatedEntry(raw_headers, &cache); 5971 CreateTruncatedEntry(raw_headers, &cache);
5946 5972
5947 // Now make a regular request. We expect the code to fail the validation and 5973 // Now make a regular request. We expect the code to fail the validation and
5948 // retry the request without using byte ranges. 5974 // retry the request without using byte ranges.
5949 std::string headers; 5975 std::string headers;
5950 MockTransaction transaction(kRangeGET_TransactionOK); 5976 MockTransaction transaction(kRangeGET_TransactionOK);
5951 transaction.request_headers = EXTRA_HEADER; 5977 transaction.request_headers = INDICATE_NO_RANGES_HEADER EXTRA_HEADER;
5952 transaction.data = "Not a range"; 5978 transaction.data = "Not a range";
5953 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); 5979 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
5954 5980
5955 // The server will return 200 instead of a byte range. 5981 // The server will return 200 instead of a byte range.
5956 std::string expected_headers( 5982 std::string expected_headers(
5957 "HTTP/1.1 200 OK\n" 5983 "HTTP/1.1 200 OK\n"
5958 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"); 5984 "Date: Wed, 28 Nov 2007 09:40:09 GMT\n");
5959 5985
5960 EXPECT_EQ(expected_headers, headers); 5986 EXPECT_EQ(expected_headers, headers);
5961 EXPECT_EQ(2, cache.network_layer()->transaction_count()); 5987 EXPECT_EQ(2, cache.network_layer()->transaction_count());
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
6095 6121
6096 std::string raw_headers("HTTP/1.1 200 OK\n" 6122 std::string raw_headers("HTTP/1.1 200 OK\n"
6097 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n" 6123 "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n"
6098 "ETag: \"foo\"\n" 6124 "ETag: \"foo\"\n"
6099 "Accept-Ranges: bytes\n" 6125 "Accept-Ranges: bytes\n"
6100 "Content-Length: 80\n"); 6126 "Content-Length: 80\n");
6101 CreateTruncatedEntry(raw_headers, &cache); 6127 CreateTruncatedEntry(raw_headers, &cache);
6102 6128
6103 // Now make a regular request. 6129 // Now make a regular request.
6104 std::string headers; 6130 std::string headers;
6105 transaction.request_headers = EXTRA_HEADER; 6131 transaction.request_headers = INDICATE_NO_RANGES_HEADER EXTRA_HEADER;
6106 transaction.data = "Not a range"; 6132 transaction.data = "Not a range";
6107 RangeTransactionServer handler; 6133 RangeTransactionServer handler;
6108 handler.set_bad_200(true); 6134 handler.set_bad_200(true);
6109 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); 6135 RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
6110 6136
6111 EXPECT_EQ(1, cache.network_layer()->transaction_count()); 6137 EXPECT_EQ(1, cache.network_layer()->transaction_count());
6112 EXPECT_EQ(1, cache.disk_cache()->open_count()); 6138 EXPECT_EQ(1, cache.disk_cache()->open_count());
6113 EXPECT_EQ(1, cache.disk_cache()->create_count()); 6139 EXPECT_EQ(1, cache.disk_cache()->create_count());
6114 6140
6115 // Verify that the disk entry was updated. 6141 // Verify that the disk entry was updated.
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
6250 6276
6251 MockHttpRequest request(kTestTransaction); 6277 MockHttpRequest request(kTestTransaction);
6252 TestCompletionCallback callback; 6278 TestCompletionCallback callback;
6253 6279
6254 // Write to the cache. 6280 // Write to the cache.
6255 { 6281 {
6256 scoped_ptr<HttpTransaction> trans; 6282 scoped_ptr<HttpTransaction> trans;
6257 ASSERT_EQ(OK, cache.CreateTransaction(&trans)); 6283 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6258 6284
6259 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6285 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6260 if (rv == ERR_IO_PENDING) 6286 ASSERT_EQ(OK, callback.GetResult(rv));
6261 rv = callback.WaitForResult();
6262 ASSERT_EQ(OK, rv);
6263 6287
6264 const HttpResponseInfo* info = trans->GetResponseInfo(); 6288 const HttpResponseInfo* info = trans->GetResponseInfo();
6265 ASSERT_TRUE(info); 6289 ASSERT_TRUE(info);
6266 6290
6267 EXPECT_EQ(info->headers->response_code(), 301); 6291 EXPECT_EQ(info->headers->response_code(), 301);
6268 6292
6269 std::string location; 6293 std::string location;
6270 info->headers->EnumerateHeader(NULL, "Location", &location); 6294 info->headers->EnumerateHeader(NULL, "Location", &location);
6271 EXPECT_EQ(location, "http://www.bar.com/"); 6295 EXPECT_EQ(location, "http://www.bar.com/");
6272 6296
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after
6929 VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0); 6953 VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0);
6930 } 6954 }
6931 6955
6932 // Tests that we handle truncated enries when StopCaching is called. 6956 // Tests that we handle truncated enries when StopCaching is called.
6933 TEST(HttpCache, StopCachingTruncatedEntry) { 6957 TEST(HttpCache, StopCachingTruncatedEntry) {
6934 MockHttpCache cache; 6958 MockHttpCache cache;
6935 TestCompletionCallback callback; 6959 TestCompletionCallback callback;
6936 MockHttpRequest request(kRangeGET_TransactionOK); 6960 MockHttpRequest request(kRangeGET_TransactionOK);
6937 request.extra_headers.Clear(); 6961 request.extra_headers.Clear();
6938 request.extra_headers.AddHeaderFromString(EXTRA_HEADER_LINE); 6962 request.extra_headers.AddHeaderFromString(EXTRA_HEADER_LINE);
6939 AddMockTransaction(&kRangeGET_TransactionOK); 6963 ScopedMockTransaction transaction(kRangeGET_TransactionOK);
6940 6964
6941 std::string raw_headers("HTTP/1.1 200 OK\n" 6965 std::string raw_headers("HTTP/1.1 200 OK\n"
6942 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" 6966 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
6943 "ETag: \"foo\"\n" 6967 "ETag: \"foo\"\n"
6944 "Accept-Ranges: bytes\n" 6968 "Accept-Ranges: bytes\n"
6945 "Content-Length: 80\n"); 6969 "Content-Length: 80\n");
6946 CreateTruncatedEntry(raw_headers, &cache); 6970 CreateTruncatedEntry(raw_headers, &cache);
6947 6971
6948 { 6972 {
6949 // Now make a regular request. 6973 // Now make a regular request.
6950 scoped_ptr<HttpTransaction> trans; 6974 scoped_ptr<HttpTransaction> trans;
6951 ASSERT_EQ(OK, cache.CreateTransaction(&trans)); 6975 ASSERT_EQ(OK, cache.CreateTransaction(&trans));
6952 6976
6953 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6977 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6954 EXPECT_EQ(OK, callback.GetResult(rv)); 6978 EXPECT_EQ(OK, callback.GetResult(rv));
6955 6979
6956 scoped_refptr<IOBuffer> buf(new IOBuffer(256)); 6980 scoped_refptr<IOBuffer> buf(new IOBuffer(256));
6957 rv = trans->Read(buf.get(), 10, callback.callback()); 6981 rv = trans->Read(buf.get(), 10, callback.callback());
6958 EXPECT_EQ(callback.GetResult(rv), 10); 6982 EXPECT_EQ(callback.GetResult(rv), 10);
6959 6983
6960 // This is actually going to do nothing.
6961 trans->StopCaching(); 6984 trans->StopCaching();
6962 6985
6963 // We should be able to keep reading. 6986 // We should be able to keep reading.
6964 rv = trans->Read(buf.get(), 256, callback.callback()); 6987 rv = trans->Read(buf.get(), 256, callback.callback());
6965 EXPECT_GT(callback.GetResult(rv), 0); 6988 EXPECT_EQ(70, callback.GetResult(rv));
6966 rv = trans->Read(buf.get(), 256, callback.callback()); 6989 rv = trans->Read(buf.get(), 256, callback.callback());
6967 EXPECT_GT(callback.GetResult(rv), 0); 6990 EXPECT_EQ(0, callback.GetResult(rv));
6968 rv = trans->Read(buf.get(), 256, callback.callback());
6969 EXPECT_EQ(callback.GetResult(rv), 0);
6970 } 6991 }
6971 6992
6972 // Verify that the disk entry was updated. 6993 // Verify that the disk entry is still intact and contains the truncated data
6973 VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 80); 6994 // from before the request.
6974 RemoveMockTransaction(&kRangeGET_TransactionOK); 6995 VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, true, 20);
6996 }
6997
6998 TEST(HttpCache, StopCachingKeepsSparseEntry) {
6999 MockHttpCache cache;
7000 TestCompletionCallback callback;
7001
7002 // Create a sparse entry which contains 10 bytes at offset 20 out of an 80
7003 // byte resource.
7004 MockTransaction mock_transaction(kRangeGET_TransactionOK);
7005 mock_transaction.handler = nullptr;
7006 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
7007 mock_transaction.response_headers =
7008 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7009 "ETag: \"foo\"\n"
7010 "Accept-Ranges: bytes\n"
7011 "Content-Range: bytes 20-29/80\n"
7012 "Content-Length: 10\n";
7013 mock_transaction.data = "rg: 20-29 ";
7014 AddMockTransaction(&mock_transaction);
7015 std::string headers;
7016 RunTransactionTestWithResponse(cache.http_cache(), mock_transaction,
7017 &headers);
7018
7019 // Verify our assumptions. There should be sparse entry here.
7020 disk_cache::Entry* cache_entry;
7021 ASSERT_TRUE(cache.OpenBackendEntry(mock_transaction.url, &cache_entry));
7022 EXPECT_TRUE(cache_entry->CouldBeSparse());
7023 cache_entry->Close();
7024 RemoveMockTransaction(&mock_transaction);
7025
7026 cache.ResetCounts();
7027
7028 // Prepare a request to read the entire contents of the resource. This should
7029 // usually hope between network -> cache -> network. But not today.
7030 mock_transaction.request_headers = EXTRA_HEADER;
7031 mock_transaction.handler = kRangeGET_TransactionOK.handler;
7032 mock_transaction.response_headers =
7033 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7034 "ETag: \"foo\"\n"
7035 "Accept-Ranges: bytes\n"
7036 "Content-Length: 80\n";
7037 AddMockTransaction(&mock_transaction);
7038 MockHttpRequest request(mock_transaction);
7039
7040 scoped_ptr<HttpTransaction> transaction;
7041 ASSERT_EQ(OK, cache.CreateTransaction(&transaction));
7042 int rv = transaction->Start(&request, callback.callback(), BoundNetLog());
7043 ASSERT_EQ(OK, callback.GetResult(rv));
7044
7045 const size_t kBufferSize = 256;
7046 scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
7047
7048 rv = transaction->Read(buffer.get(), 10, callback.callback());
7049 EXPECT_EQ(10, callback.GetResult(rv));
7050
7051 // This should've caused a network read of 10 bytes.
7052 EXPECT_EQ(1, cache.network_layer()->transaction_count());
7053
7054 // StopCaching() should cause the transaction to switch entirely to the
7055 // network for the remainder of the response. Since the existing network
7056 // transaction doesn't cover the entirety of the resource, the cache creates a
7057 // new network transaction.
7058 transaction->StopCaching();
7059
7060 // Since it's coming from a single network request, we can slurp the remainder
7061 // of the resource in one request.
7062 rv = transaction->Read(buffer.get(), kBufferSize, callback.callback());
7063 EXPECT_EQ(70, callback.GetResult(rv));
7064
7065 // And we hit EOF.
7066 rv = transaction->Read(buffer.get(), kBufferSize, callback.callback());
7067 EXPECT_EQ(0, callback.GetResult(rv));
7068
7069 // Another network transaction is issued for the remainder of the resource
7070 // following the StopCaching call.
7071 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7072
7073 // And the sparse entry is still here.
7074 ASSERT_TRUE(cache.OpenBackendEntry(mock_transaction.url, &cache_entry));
7075 cache_entry->Close();
7076 RemoveMockTransaction(&mock_transaction);
7077 }
7078
7079 // If StopCaching() is called while serving the entire request out of cache, the
7080 // transaction is expected to ignore the StopCaching() call and continue serving
7081 // the remainder of the resource out of the cache.
7082 TEST(HttpCache, StopCachingKeepsFullEntry) {
7083 MockHttpCache cache;
7084 TestCompletionCallback callback;
7085
7086 MockTransaction mock_transaction(kRangeGET_TransactionOK);
7087 mock_transaction.handler = nullptr;
7088 mock_transaction.request_headers = EXTRA_HEADER;
7089 mock_transaction.status = "HTTP/1.1 200 OK";
7090 mock_transaction.response_headers =
7091 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7092 "ETag: \"foo\"\n"
7093 "Content-Length: 80\n";
7094 mock_transaction.data = kFullRangeData;
7095 AddMockTransaction(&mock_transaction);
7096 std::string headers;
7097 RunTransactionTestWithResponse(cache.http_cache(), mock_transaction,
7098 &headers);
7099
7100 cache.ResetCounts();
7101
7102 mock_transaction.request_headers = EXTRA_HEADER;
7103 mock_transaction.handler = kRangeGET_TransactionOK.handler;
7104 mock_transaction.response_headers =
7105 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7106 "ETag: \"foo\"\n"
7107 "Accept-Ranges: bytes\n"
7108 "Content-Length: 80\n";
7109 AddMockTransaction(&mock_transaction);
7110 MockHttpRequest request(mock_transaction);
7111
7112 scoped_ptr<HttpTransaction> transaction;
7113 ASSERT_EQ(OK, cache.CreateTransaction(&transaction));
7114 int rv = transaction->Start(&request, callback.callback(), BoundNetLog());
7115 ASSERT_EQ(OK, callback.GetResult(rv));
7116
7117 const size_t kBufferSize = 256;
7118 scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
7119
7120 rv = transaction->Read(buffer.get(), 10, callback.callback());
7121 EXPECT_EQ(10, callback.GetResult(rv));
7122
7123 // This should've caused a cache read of 10 bytes. No new network transactions
7124 // are expected.
7125 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7126
7127 // StopCaching() doesn't do anything because the entire resource is cached
7128 // already. We proceed with the cache read.
7129 transaction->StopCaching();
7130
7131 // Since it's all coming from a single network request, we can slurp the
7132 // remainder of the resource in one request.
7133 rv = transaction->Read(buffer.get(), kBufferSize, callback.callback());
7134 EXPECT_EQ(70, callback.GetResult(rv));
7135
7136 // And we hit EOF.
7137 rv = transaction->Read(buffer.get(), kBufferSize, callback.callback());
7138 EXPECT_EQ(0, callback.GetResult(rv));
7139
7140 // We should've only seen one network transactions at this point.
7141 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7142
7143 // And the entry is still here.
7144 EXPECT_EQ(1, cache.disk_cache()->open_count());
7145 EXPECT_EQ(0, cache.disk_cache()->create_count());
7146 disk_cache::Entry* cache_entry;
7147 ASSERT_TRUE(cache.OpenBackendEntry(mock_transaction.url, &cache_entry));
7148 cache_entry->Close();
7149
7150 RemoveMockTransaction(&mock_transaction);
7151 }
7152
7153 TEST(HttpCache, StopCachingReleasesCacheLockForNewCacheEntry) {
7154 MockHttpCache cache;
7155 TestCompletionCallback callback;
7156 ScopedMockTransaction mock_transaction(kResumableGET_Transaction);
7157 MockHttpRequest mock_request(mock_transaction);
7158
7159 scoped_ptr<HttpTransaction> first_transaction;
7160 ASSERT_EQ(OK, cache.CreateTransaction(&first_transaction));
7161
7162 int rv = first_transaction->Start(&mock_request, callback.callback(),
7163 BoundNetLog());
7164 ASSERT_EQ(OK, callback.GetResult(rv));
7165
7166 const size_t kBufferSize = 1024;
7167 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize));
7168 rv = first_transaction->Read(buf.get(), 10, callback.callback());
7169 EXPECT_EQ(10, callback.GetResult(rv));
7170
7171 first_transaction->StopCaching();
7172
7173 rv = first_transaction->Read(buf.get(), 10, callback.callback());
7174 EXPECT_EQ(10, callback.GetResult(rv));
7175
7176 // Since the cache entry is no longer locked by |first_transaction|, we can
7177 // start another transaction without blocking. The test should time out if
7178 // this is not the case (i.e. the Start() call has to wait indefinitely[*]
7179 // for the previous transaction to release the lock).
7180 //
7181 // [*]: The wait isn't really indefinite since the Start() call times out
7182 // (currently after 20 seconds) and proceeds without the cache entry. Failure
7183 // to release the cahe entry is accounted for by the previous
7184 // disk_cache()->GetEntryCount() expectation.
7185 scoped_ptr<HttpTransaction> second_transaction;
7186 ASSERT_EQ(OK, cache.CreateTransaction(&second_transaction));
7187 rv = second_transaction->Start(&mock_request, callback.callback(),
7188 BoundNetLog());
7189 ASSERT_EQ(OK, callback.GetResult(rv));
7190
7191 rv = second_transaction->Read(buf.get(), 10, callback.callback());
7192 EXPECT_EQ(10, callback.GetResult(rv));
7193
7194 // First transaction creates a cache entry which the second transaction opens.
7195 EXPECT_EQ(1, cache.disk_cache()->create_count());
7196 EXPECT_EQ(1, cache.disk_cache()->open_count());
7197
7198 // One network request for each cache transaction.
7199 EXPECT_EQ(2, cache.network_layer()->transaction_count());
7200
7201 first_transaction.reset();
7202 second_transaction.reset();
7203
7204 // The cache entry is still around. It should be truncated and contain the 10
7205 // bytes that were written before the first StopCaching() call was made.
7206 VerifyTruncatedFlag(&cache, kResumableGET_Transaction.url, true, 10);
7207 }
7208
7209 TEST(HttpCache, StopCachingReleasesCacheLockForTruncatedEntry) {
7210 MockHttpCache cache;
7211 TestCompletionCallback callback;
7212 ScopedMockTransaction mock_transaction(kResumableGET_Transaction);
7213 MockHttpRequest mock_request(kResumableGET_Transaction);
7214 std::string raw_headers(
7215 "HTTP/1.1 200 OK\n"
7216 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7217 "Date: Sat, 18 Apr 2015 01:10:43 GMT\n"
7218 "ETag: \"foo\"\n"
7219 "Accept-Ranges: bytes\n"
7220 "Content-Length: 80\n");
7221 CreateTruncatedEntry(raw_headers, &cache);
7222 cache.ResetCounts();
7223
7224 scoped_ptr<HttpTransaction> first_transaction;
7225 int rv = cache.CreateTransaction(&first_transaction);
7226 ASSERT_EQ(OK, rv);
7227 ASSERT_TRUE(first_transaction.get());
7228
7229 rv = first_transaction->Start(&mock_request, callback.callback(),
7230 BoundNetLog());
7231 ASSERT_EQ(OK, callback.GetResult(rv));
7232
7233 first_transaction->StopCaching();
7234
7235 const int kBufferSize = 1024;
7236 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize));
7237 rv = first_transaction->Read(buf.get(), 10, callback.callback());
7238 EXPECT_EQ(10, callback.GetResult(rv));
7239
7240 // Now that the cache lock is released, another transaction can begin. The
7241 // Start() call should complete without delay. The test should timeout if this
7242 // is not the case (i.e. the Start() call has to wait indefinitely[*] for the
7243 // previous transaction to release the lock).
7244 //
7245 // [*]: The wait isn't really indefinite since the Start() call times out
7246 // (currently after 20 seconds) and proceeds without the cache entry. This
7247 // case is accounted for by the network_layer()->transaction_count()
7248 // expectation below.
7249 scoped_ptr<HttpTransaction> second_transaction;
7250 rv = cache.CreateTransaction(&second_transaction);
7251 ASSERT_EQ(OK, rv);
7252 ASSERT_TRUE(second_transaction);
7253 rv = second_transaction->Start(&mock_request, callback.callback(),
7254 BoundNetLog());
7255 ASSERT_EQ(OK, callback.GetResult(rv));
7256
7257 rv = second_transaction->Read(buf.get(), 10, callback.callback());
7258 EXPECT_EQ(10, callback.GetResult(rv));
7259
7260 // first_transaction:
7261 // 1 open cache entry.
7262 // 1 network fetch for validation.
7263 // 1 network fetch for switching to the network.
7264 // second_transaction:
7265 // 1 open cache entry.
7266 // 1 network fetch for validation.
7267 EXPECT_EQ(0, cache.disk_cache()->create_count());
7268 EXPECT_EQ(2, cache.disk_cache()->open_count());
7269 EXPECT_EQ(3, cache.network_layer()->transaction_count());
7270
7271 first_transaction.reset();
7272 second_transaction.reset();
7273 VerifyTruncatedFlag(&cache, kResumableGET_Transaction.url, true, 20);
7274 }
7275
7276 TEST(HttpCache, StopCachingReleasesCacheLockForSparseEntry) {
7277 MockHttpCache cache;
7278 TestCompletionCallback callback;
7279
7280 // Create a sparse entry which contains 10 bytes at offset 20 out of an 80
7281 // byte resource.
7282 MockTransaction mock_transaction(kRangeGET_TransactionOK);
7283 mock_transaction.handler = nullptr;
7284 mock_transaction.request_headers = "Range: bytes = 20-29\r\n" EXTRA_HEADER;
7285 mock_transaction.response_headers =
7286 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7287 "ETag: \"foo\"\n"
7288 "Accept-Ranges: bytes\n"
7289 "Content-Range: bytes 20-29/80\n"
7290 "Content-Length: 10\n";
7291 mock_transaction.data = "rg: 20-29 ";
7292 AddMockTransaction(&mock_transaction);
7293 std::string headers;
7294 RunTransactionTestWithResponse(cache.http_cache(), mock_transaction,
7295 &headers);
7296
7297 // Verify our assumptions. There should be sparse entry here.
7298 disk_cache::Entry* cache_entry;
7299 ASSERT_TRUE(cache.OpenBackendEntry(mock_transaction.url, &cache_entry));
7300 EXPECT_TRUE(cache_entry->CouldBeSparse());
7301 cache_entry->Close();
7302 RemoveMockTransaction(&mock_transaction);
7303
7304 cache.ResetCounts();
7305
7306 // Prepare a request to read the entire contents of the resource. This should
7307 // usually hope between network -> cache -> network. But not today.
7308 mock_transaction.request_headers = EXTRA_HEADER;
7309 mock_transaction.handler = kRangeGET_TransactionOK.handler;
7310 mock_transaction.response_headers =
7311 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7312 "ETag: \"foo\"\n"
7313 "Accept-Ranges: bytes\n"
7314 "Content-Length: 10\n";
7315 AddMockTransaction(&mock_transaction);
7316 MockHttpRequest request(mock_transaction);
7317
7318 scoped_ptr<HttpTransaction> first_transaction;
7319 ASSERT_EQ(OK, cache.CreateTransaction(&first_transaction));
7320 int rv =
7321 first_transaction->Start(&request, callback.callback(), BoundNetLog());
7322 ASSERT_EQ(OK, callback.GetResult(rv));
7323
7324 const size_t kBufferSize = 256;
7325 scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
7326
7327 rv = first_transaction->Read(buffer.get(), 10, callback.callback());
7328 EXPECT_EQ(10, callback.GetResult(rv));
7329
7330 // Create another cache transaction. This one is blocked on the first
7331 // transaction's cache lock.
7332 scoped_ptr<HttpTransaction> second_transaction;
7333 TestCompletionCallback second_callback;
7334 ASSERT_EQ(OK, cache.CreateTransaction(&second_transaction));
7335 rv = second_transaction->Start(&request, second_callback.callback(),
7336 BoundNetLog());
7337 ASSERT_EQ(ERR_IO_PENDING, rv);
7338
7339 // StopCaching() should cause the transaction to switch entirely to the
7340 // network for the remainder of the response. Since the existing network
7341 // transaction doesn't cover the entirety of the resource, the cache creates a
7342 // new network transaction.
7343 first_transaction->StopCaching();
7344
7345 // Since it's coming from a single network request, we can slurp the remaining
7346 // 70 bytes of the resource in one request. Let's leave a little bit on the
7347 // pipe so that the stream doesn't hit EOF.
7348 rv = first_transaction->Read(buffer.get(), 60, callback.callback());
7349 EXPECT_EQ(60, callback.GetResult(rv));
7350
7351 // The second transaction should become unblocked at this point.
7352 EXPECT_EQ(OK, second_callback.GetResult(ERR_IO_PENDING));
7353
7354 // And it can read the entire resource too, but needs to alternate between
7355 // cache and network..
7356 // 0-9 from cache (due to the first Read() on first_transaction).
7357 EXPECT_EQ(10, second_callback.GetResult(second_transaction->Read(
7358 buffer.get(), kBufferSize, second_callback.callback())));
7359
7360 // 10-19 From network:
7361 EXPECT_EQ(10, second_callback.GetResult(second_transaction->Read(
7362 buffer.get(), kBufferSize, second_callback.callback())));
7363
7364 // 20-29 From cache (due to test setup):
7365 EXPECT_EQ(10, second_callback.GetResult(second_transaction->Read(
7366 buffer.get(), kBufferSize, second_callback.callback())));
7367
7368 // 30-79 From network again:
7369 EXPECT_EQ(50, second_callback.GetResult(second_transaction->Read(
7370 buffer.get(), kBufferSize, second_callback.callback())));
7371 EXPECT_EQ(0, second_callback.GetResult(second_transaction->Read(
7372 buffer.get(), kBufferSize, second_callback.callback())));
7373
7374 // Now drain first_transaction as well.
7375 EXPECT_EQ(10, callback.GetResult(first_transaction->Read(
7376 buffer.get(), kBufferSize, callback.callback())));
7377 EXPECT_EQ(0, callback.GetResult(first_transaction->Read(
7378 buffer.get(), kBufferSize, callback.callback())));
7379
7380 // first_transaction:
7381 // 1 open cache entry.
7382 // 2 network fetches (0-19 and 10-79).
7383 // second_transaction:
7384 // 1 open cache entry.
7385 // 2 network fetches (10-19 and 30-79).
7386 EXPECT_EQ(0, cache.disk_cache()->create_count());
7387 EXPECT_EQ(4, cache.network_layer()->transaction_count());
7388
7389 // Even though there are two HttpCache::OpenEntry() calls, there's only one
7390 // DiskCache::OpenEntry call because HttpCache already has an active entry.
7391 EXPECT_EQ(1, cache.disk_cache()->open_count());
7392
7393 // And the sparse entry is still here.
7394 ASSERT_TRUE(cache.OpenBackendEntry(mock_transaction.url, &cache_entry));
7395 cache_entry->Close();
7396 RemoveMockTransaction(&mock_transaction);
7397 }
7398
7399 TEST(HttpCache, StopCachingAfterStartForLoadPreferringCacheWithInvalidation) {
7400 MockHttpCache cache;
7401 TestCompletionCallback callback;
7402 MockTransaction transaction(kSimpleGET_Transaction);
7403
7404 AddMockTransaction(&transaction);
7405 RunTransactionTest(cache.http_cache(), transaction);
7406 RemoveMockTransaction(&transaction);
7407 cache.ResetCounts();
7408
7409 transaction.load_flags |= LOAD_PREFERRING_CACHE;
7410 AddMockTransaction(&transaction);
7411
7412 scoped_ptr<HttpTransaction> http_transaction;
7413
7414 int rv = cache.CreateTransaction(&http_transaction);
7415 ASSERT_EQ(OK, rv);
7416
7417 MockHttpRequest request(transaction);
7418 rv = http_transaction->Start(&request, callback.callback(), BoundNetLog());
7419 ASSERT_EQ(OK, callback.GetResult(rv));
7420
7421 http_transaction->StopCaching();
7422
7423 ReadAndVerifyTransaction(http_transaction.get(), transaction);
7424 RemoveMockTransaction(&transaction);
7425
7426 EXPECT_EQ(0, cache.network_layer()->transaction_count());
7427 EXPECT_EQ(1, cache.disk_cache()->open_count());
7428 EXPECT_EQ(0, cache.disk_cache()->create_count());
7429 }
7430
7431 namespace {
7432
7433 enum class TransactionPhase {
7434 BEFORE_FIRST_READ,
7435 AFTER_FIRST_READ,
7436 AFTER_NETWORK_READ
7437 };
7438
7439 using CacheInitializer = void (*)(MockHttpCache*);
7440 using HugeCacheTestConfiguration =
7441 std::pair<TransactionPhase, CacheInitializer>;
7442
7443 class HttpCacheHugeResourceTest
7444 : public ::testing::TestWithParam<HugeCacheTestConfiguration> {
7445 public:
7446 static std::list<HugeCacheTestConfiguration> GetTestModes();
7447 static std::list<HugeCacheTestConfiguration> kTestModes;
7448
7449 // CacheInitializer callbacks. These are used to initialize the cache
7450 // depending on the test run configuration.
7451
7452 // Initializes a cache containing a truncated entry containing the first 20
7453 // bytes of the reponse body.
7454 static void SetupTruncatedCacheEntry(MockHttpCache* cache);
7455
7456 // Initializes a cache containing a sparse entry. The first 10 bytes are
7457 // present in the cache.
7458 static void SetupPrefixSparseCacheEntry(MockHttpCache* cache);
7459
7460 // Initializes a cache containing a sparse entry. The 10 bytes at offset
7461 // 99999990 are present in the cache.
7462 static void SetupInfixSparseCacheEntry(MockHttpCache* cache);
7463
7464 protected:
7465 static void ExpectByteRangeTransactionHandler(
7466 const net::HttpRequestInfo* request,
7467 std::string* response_status,
7468 std::string* response_headers,
7469 std::string* response_data);
7470 static int LargeBufferReader(int64 content_length,
7471 int64 offset,
7472 net::IOBuffer* buf,
7473 int buf_len);
7474
7475 static void SetFlagOnBeforeNetworkStart(bool* started, bool* /* defer */);
7476
7477 // Size of resource to be tested.
7478 static const int64 kTotalSize =
7479 5000000000LL; // Five beeeeeelllliooonn bytes!
7480 };
7481
7482 const int64 HttpCacheHugeResourceTest::kTotalSize;
7483
7484 // static
7485 void HttpCacheHugeResourceTest::ExpectByteRangeTransactionHandler(
7486 const net::HttpRequestInfo* request,
7487 std::string* response_status,
7488 std::string* response_headers,
7489 std::string* response_data) {
7490 std::string if_range;
7491 EXPECT_TRUE(request->extra_headers.GetHeader(
7492 net::HttpRequestHeaders::kIfRange, &if_range));
7493 EXPECT_EQ("\"foo\"", if_range);
7494
7495 std::string range_header;
7496 EXPECT_TRUE(request->extra_headers.GetHeader(net::HttpRequestHeaders::kRange,
7497 &range_header));
7498 std::vector<net::HttpByteRange> ranges;
7499
7500 EXPECT_TRUE(net::HttpUtil::ParseRangeHeader(range_header, &ranges));
7501 ASSERT_EQ(1u, ranges.size());
7502
7503 net::HttpByteRange range = ranges[0];
7504 EXPECT_TRUE(range.HasFirstBytePosition());
7505 int64 last_byte_position =
7506 range.HasLastBytePosition() ? range.last_byte_position() : kTotalSize - 1;
7507
7508 response_status->assign("HTTP/1.1 206 Partial");
7509 response_headers->assign(base::StringPrintf(
7510 "Content-Range: bytes %" PRId64 "-%" PRId64 "/%" PRId64
7511 "\n"
7512 "Content-Length: %" PRId64 "\n",
7513 range.first_byte_position(), last_byte_position, kTotalSize,
7514 last_byte_position - range.first_byte_position() + 1));
7515 }
7516
7517 // static
7518 int HttpCacheHugeResourceTest::LargeBufferReader(int64 content_length,
7519 int64 offset,
7520 net::IOBuffer* buf,
7521 int buf_len) {
7522 // This test involves reading multiple gigabytes of data. To make it run in a
7523 // reasonable amount of time, we are going to skip filling the buffer with
7524 // data. Instead the test relies on verifying that the count of bytes expected
7525 // at the end is correct.
7526 EXPECT_LT(0, content_length);
7527 EXPECT_LE(offset, content_length);
7528 int num = std::min(static_cast<int64>(buf_len), content_length - offset);
7529 return num;
7530 }
7531
7532 // static
7533 void HttpCacheHugeResourceTest::SetFlagOnBeforeNetworkStart(bool* started,
7534 bool* /* defer */) {
7535 *started = true;
7536 }
7537
7538 // static
7539 void HttpCacheHugeResourceTest::SetupTruncatedCacheEntry(MockHttpCache* cache) {
7540 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
7541 std::string cached_headers = base::StringPrintf(
7542 "HTTP/1.1 200 OK\n"
7543 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7544 "ETag: \"foo\"\n"
7545 "Accept-Ranges: bytes\n"
7546 "Content-Length: %" PRId64 "\n",
7547 kTotalSize);
7548 CreateTruncatedEntry(cached_headers, cache);
7549 }
7550
7551 // static
7552 void HttpCacheHugeResourceTest::SetupPrefixSparseCacheEntry(
7553 MockHttpCache* cache) {
7554 MockTransaction transaction(kRangeGET_TransactionOK);
7555 transaction.handler = nullptr;
7556 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
7557 transaction.response_headers =
7558 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7559 "ETag: \"foo\"\n"
7560 "Accept-Ranges: bytes\n"
7561 "Content-Range: bytes 0-9/5000000000\n"
7562 "Content-Length: 10\n";
7563 AddMockTransaction(&transaction);
7564 std::string headers;
7565 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
7566 RemoveMockTransaction(&transaction);
7567 }
7568
7569 // static
7570 void HttpCacheHugeResourceTest::SetupInfixSparseCacheEntry(
7571 MockHttpCache* cache) {
7572 MockTransaction transaction(kRangeGET_TransactionOK);
7573 transaction.handler = nullptr;
7574 transaction.request_headers =
7575 "Range: bytes = 99999990-99999999\r\n" EXTRA_HEADER;
7576 transaction.response_headers =
7577 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7578 "ETag: \"foo\"\n"
7579 "Accept-Ranges: bytes\n"
7580 "Content-Range: bytes 99999990-99999999/5000000000\n"
7581 "Content-Length: 10\n";
7582 AddMockTransaction(&transaction);
7583 std::string headers;
7584 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
7585 RemoveMockTransaction(&transaction);
7586 }
7587
7588 // static
7589 std::list<HugeCacheTestConfiguration>
7590 HttpCacheHugeResourceTest::GetTestModes() {
7591 std::list<HugeCacheTestConfiguration> test_modes;
7592 const TransactionPhase kTransactionPhases[] = {
7593 TransactionPhase::BEFORE_FIRST_READ, TransactionPhase::AFTER_FIRST_READ,
7594 TransactionPhase::AFTER_NETWORK_READ};
7595 const CacheInitializer kInitializers[] = {&SetupTruncatedCacheEntry,
7596 &SetupPrefixSparseCacheEntry,
7597 &SetupInfixSparseCacheEntry};
7598
7599 for (const auto phase : kTransactionPhases)
7600 for (const auto initializer : kInitializers)
7601 test_modes.push_back(std::make_pair(phase, initializer));
7602
7603 return test_modes;
7604 }
7605
7606 // static
7607 std::list<HugeCacheTestConfiguration> HttpCacheHugeResourceTest::kTestModes =
7608 HttpCacheHugeResourceTest::GetTestModes();
7609
7610 INSTANTIATE_TEST_CASE_P(
7611 _,
7612 HttpCacheHugeResourceTest,
7613 ::testing::ValuesIn(HttpCacheHugeResourceTest::kTestModes));
7614
7615 } // namespace
7616
7617 // Test what happens when StopCaching() is called while reading a huge resource
7618 // fetched via GET. Various combinations of cache state and when StopCaching()
7619 // is called is controlled by the parameter passed into the test via the
7620 // INSTANTIATE_TEST_CASE_P invocation above.
7621 TEST_P(HttpCacheHugeResourceTest,
7622 StopCachingFollowedByReadForHugeTruncatedResource) {
7623 // This test is going to be repeated for all combinations of TransactionPhase
7624 // and CacheInitializers returned by GetTestModes().
7625 const TransactionPhase stop_caching_phase = GetParam().first;
7626 const CacheInitializer cache_initializer = GetParam().second;
7627
7628 MockHttpCache cache;
7629 (*cache_initializer)(&cache);
7630
7631 MockTransaction transaction(kSimpleGET_Transaction);
7632 transaction.url = kRangeGET_TransactionOK.url;
7633 transaction.handler = &ExpectByteRangeTransactionHandler;
7634 transaction.read_handler = &LargeBufferReader;
7635 ScopedMockTransaction scoped_transaction(transaction);
7636
7637 MockHttpRequest request(transaction);
7638 net::TestCompletionCallback callback;
7639 scoped_ptr<net::HttpTransaction> http_transaction;
7640 int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY,
7641 &http_transaction);
7642 ASSERT_EQ(net::OK, rv);
7643 ASSERT_TRUE(http_transaction.get());
7644
7645 bool network_transaction_started = false;
7646 if (stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
7647 http_transaction->SetBeforeNetworkStartCallback(
7648 base::Bind(&SetFlagOnBeforeNetworkStart, &network_transaction_started));
7649 }
7650
7651 rv = http_transaction->Start(&request, callback.callback(),
7652 net::BoundNetLog());
7653 rv = callback.GetResult(rv);
7654 ASSERT_EQ(net::OK, rv);
7655
7656 if (stop_caching_phase == TransactionPhase::BEFORE_FIRST_READ)
7657 http_transaction->StopCaching();
7658
7659 int64 total_bytes_received = 0;
7660
7661 EXPECT_EQ(kTotalSize,
7662 http_transaction->GetResponseInfo()->headers->GetContentLength());
7663 do {
7664 // This test simulates reading Gigabytes of data. Buffer size is set to 1MB
7665 // to reduce the number of reads and speedup the test.
7666 const int kBufferSize = 1024 * 1024;
7667 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize));
7668 rv = http_transaction->Read(buf.get(), kBufferSize, callback.callback());
7669 rv = callback.GetResult(rv);
7670
7671 if (stop_caching_phase == TransactionPhase::AFTER_FIRST_READ &&
7672 total_bytes_received == 0) {
7673 http_transaction->StopCaching();
7674 }
7675
7676 if (rv > 0)
7677 total_bytes_received += rv;
7678
7679 if (network_transaction_started &&
7680 stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
7681 http_transaction->StopCaching();
7682 network_transaction_started = false;
7683 }
7684 } while (rv > 0);
7685
7686 // The only verification we are going to do is that the received resource has
7687 // the correct size. This is sufficient to verify that the state machine
7688 // didn't terminate abruptly due to the StopCaching() call.
7689 EXPECT_EQ(kTotalSize, total_bytes_received);
6975 } 7690 }
6976 7691
6977 // Tests that we detect truncated resources from the net when there is 7692 // Tests that we detect truncated resources from the net when there is
6978 // a Content-Length header. 7693 // a Content-Length header.
6979 TEST(HttpCache, TruncatedByContentLength) { 7694 TEST(HttpCache, TruncatedByContentLength) {
6980 MockHttpCache cache; 7695 MockHttpCache cache;
6981 TestCompletionCallback callback; 7696 TestCompletionCallback callback;
6982 7697
6983 MockTransaction transaction(kSimpleGET_Transaction); 7698 MockTransaction transaction(kSimpleGET_Transaction);
6984 AddMockTransaction(&transaction); 7699 AddMockTransaction(&transaction);
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
7653 EXPECT_EQ(1, cache.disk_cache()->open_count()); 8368 EXPECT_EQ(1, cache.disk_cache()->open_count());
7654 EXPECT_EQ(1, cache.disk_cache()->create_count()); 8369 EXPECT_EQ(1, cache.disk_cache()->create_count());
7655 EXPECT_TRUE(response_info.was_cached); 8370 EXPECT_TRUE(response_info.was_cached);
7656 8371
7657 // The new SSL state is reported. 8372 // The new SSL state is reported.
7658 EXPECT_EQ(status2, response_info.ssl_info.connection_status); 8373 EXPECT_EQ(status2, response_info.ssl_info.connection_status);
7659 EXPECT_TRUE(cert2->Equals(response_info.ssl_info.cert.get())); 8374 EXPECT_TRUE(cert2->Equals(response_info.ssl_info.cert.get()));
7660 } 8375 }
7661 8376
7662 } // namespace net 8377 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698