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

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

Issue 2089783002: [net/cache] Avoid the cache for responses exceeding 2GB. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address mmenke's comments Created 4 years, 6 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 <memory> 10 #include <memory>
11 #include <utility> 11 #include <utility>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
16 #include "base/format_macros.h"
16 #include "base/macros.h" 17 #include "base/macros.h"
17 #include "base/memory/ptr_util.h" 18 #include "base/memory/ptr_util.h"
18 #include "base/message_loop/message_loop.h" 19 #include "base/message_loop/message_loop.h"
19 #include "base/run_loop.h" 20 #include "base/run_loop.h"
20 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
22 #include "base/test/simple_test_clock.h" 23 #include "base/test/simple_test_clock.h"
23 #include "net/base/cache_type.h" 24 #include "net/base/cache_type.h"
24 #include "net/base/elements_upload_data_stream.h" 25 #include "net/base/elements_upload_data_stream.h"
25 #include "net/base/host_port_pair.h" 26 #include "net/base/host_port_pair.h"
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 base::Time(), 297 base::Time(),
297 "", 298 "",
298 LOAD_VALIDATE_CACHE, 299 LOAD_VALIDATE_CACHE,
299 "HTTP/1.1 200 OK", 300 "HTTP/1.1 200 OK",
300 "Cache-Control: max-age=10000\n", 301 "Cache-Control: max-age=10000\n",
301 base::Time(), 302 base::Time(),
302 "<html><body>Google Blah Blah</body></html>", 303 "<html><body>Google Blah Blah</body></html>",
303 TEST_MODE_SYNC_NET_START, 304 TEST_MODE_SYNC_NET_START,
304 &FastTransactionServer::FastNoStoreHandler, 305 &FastTransactionServer::FastNoStoreHandler,
305 nullptr, 306 nullptr,
307 nullptr,
306 0, 308 0,
307 0, 309 0,
308 OK}; 310 OK};
309 311
310 // This class provides a handler for kRangeGET_TransactionOK so that the range 312 // This class provides a handler for kRangeGET_TransactionOK so that the range
311 // request can be served on demand. 313 // request can be served on demand.
312 class RangeTransactionServer { 314 class RangeTransactionServer {
313 public: 315 public:
314 RangeTransactionServer() { 316 RangeTransactionServer() {
315 not_modified_ = false; 317 not_modified_ = false;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 response_headers->replace(response_headers->find("Content-Length:"), 456 response_headers->replace(response_headers->find("Content-Length:"),
455 content_length.size(), content_length); 457 content_length.size(), content_length);
456 } 458 }
457 } else { 459 } else {
458 response_status->assign("HTTP/1.1 304 Not Modified"); 460 response_status->assign("HTTP/1.1 304 Not Modified");
459 response_data->clear(); 461 response_data->clear();
460 } 462 }
461 } 463 }
462 464
463 const MockTransaction kRangeGET_TransactionOK = { 465 const MockTransaction kRangeGET_TransactionOK = {
464 "http://www.google.com/range", 466 "http://www.google.com/range", "GET", base::Time(),
465 "GET", 467 "Range: bytes = 40-49\r\n" EXTRA_HEADER, LOAD_NORMAL,
466 base::Time(),
467 "Range: bytes = 40-49\r\n" EXTRA_HEADER,
468 LOAD_NORMAL,
469 "HTTP/1.1 206 Partial Content", 468 "HTTP/1.1 206 Partial Content",
470 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" 469 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
471 "ETag: \"foo\"\n" 470 "ETag: \"foo\"\n"
472 "Accept-Ranges: bytes\n" 471 "Accept-Ranges: bytes\n"
473 "Content-Length: 10\n", 472 "Content-Length: 10\n",
474 base::Time(), 473 base::Time(), "rg: 40-49 ", TEST_MODE_NORMAL,
475 "rg: 40-49 ", 474 &RangeTransactionServer::RangeHandler, nullptr, nullptr, 0, 0, OK};
476 TEST_MODE_NORMAL,
477 &RangeTransactionServer::RangeHandler,
478 nullptr,
479 0,
480 0,
481 OK};
482 475
483 const char kFullRangeData[] = 476 const char kFullRangeData[] =
484 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 " 477 "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 "
485 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 "; 478 "rg: 40-49 rg: 50-59 rg: 60-69 rg: 70-79 ";
486 479
487 // Verifies the response headers (|response|) match a partial content 480 // Verifies the response headers (|response|) match a partial content
488 // response for the range starting at |start| and ending at |end|. 481 // response for the range starting at |start| and ending at |end|.
489 void Verify206Response(const std::string& response, int start, int end) { 482 void Verify206Response(const std::string& response, int start, int end) {
490 std::string raw_headers( 483 std::string raw_headers(
491 HttpUtil::AssembleRawHeaders(response.data(), response.size())); 484 HttpUtil::AssembleRawHeaders(response.data(), response.size()));
(...skipping 6557 matching lines...) Expand 10 before | Expand all | Expand 10 after
7049 EXPECT_GT(callback.GetResult(rv), 0); 7042 EXPECT_GT(callback.GetResult(rv), 0);
7050 rv = trans->Read(buf.get(), 256, callback.callback()); 7043 rv = trans->Read(buf.get(), 256, callback.callback());
7051 EXPECT_EQ(callback.GetResult(rv), 0); 7044 EXPECT_EQ(callback.GetResult(rv), 0);
7052 } 7045 }
7053 7046
7054 // Verify that the disk entry was updated. 7047 // Verify that the disk entry was updated.
7055 VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 80); 7048 VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 80);
7056 RemoveMockTransaction(&kRangeGET_TransactionOK); 7049 RemoveMockTransaction(&kRangeGET_TransactionOK);
7057 } 7050 }
7058 7051
7052 namespace {
7053
7054 enum class TransactionPhase {
7055 BEFORE_FIRST_READ,
7056 AFTER_FIRST_READ,
7057 AFTER_NETWORK_READ
7058 };
7059
7060 using CacheInitializer = void (*)(MockHttpCache*);
7061 using HugeCacheTestConfiguration =
7062 std::pair<TransactionPhase, CacheInitializer>;
7063
7064 class HttpCacheHugeResourceTest
7065 : public ::testing::TestWithParam<HugeCacheTestConfiguration> {
7066 public:
7067 static std::list<HugeCacheTestConfiguration> GetTestModes();
7068 static std::list<HugeCacheTestConfiguration> kTestModes;
7069
7070 // CacheInitializer callbacks. These are used to initialize the cache
7071 // depending on the test run configuration.
7072
7073 // Initializes a cache containing a truncated entry containing the first 20
7074 // bytes of the reponse body.
7075 static void SetupTruncatedCacheEntry(MockHttpCache* cache);
7076
7077 // Initializes a cache containing a sparse entry. The first 10 bytes are
7078 // present in the cache.
7079 static void SetupPrefixSparseCacheEntry(MockHttpCache* cache);
7080
7081 // Initializes a cache containing a sparse entry. The 10 bytes at offset
7082 // 99990 are present in the cache.
7083 static void SetupInfixSparseCacheEntry(MockHttpCache* cache);
7084
7085 protected:
7086 static void LargeResourceTransactionHandler(
7087 const net::HttpRequestInfo* request,
7088 std::string* response_status,
7089 std::string* response_headers,
7090 std::string* response_data);
7091 static int LargeBufferReader(int64_t content_length,
7092 int64_t offset,
7093 net::IOBuffer* buf,
7094 int buf_len);
7095
7096 static void SetFlagOnBeforeNetworkStart(bool* started, bool* /* defer */);
7097
7098 // Size of resource to be tested.
7099 static const int64_t kTotalSize =
7100 5000000000LL; // Five beeeeeelllliooonn bytes!
gavinp 2016/06/28 14:24:43 Nit: can we write this as 5000 * 1000 * 1000 just
asanka 2016/06/28 16:55:38 Rewritten as 5'00'00'00'000LL :P
7101 };
7102
7103 const int64_t HttpCacheHugeResourceTest::kTotalSize;
gavinp 2016/06/28 14:24:43 Is this necessary?
asanka 2016/06/28 16:55:38 Apparently EXPECT_EQ(kTotalSize, ...) results in a
7104
7105 // static
7106 void HttpCacheHugeResourceTest::LargeResourceTransactionHandler(
7107 const net::HttpRequestInfo* request,
7108 std::string* response_status,
7109 std::string* response_headers,
7110 std::string* response_data) {
7111 std::string if_range;
7112 if (!request->extra_headers.GetHeader(net::HttpRequestHeaders::kIfRange,
7113 &if_range)) {
7114 // If there were no range headers in the request, we are going to just
7115 // return the entire response body.
7116 response_status->assign("HTTP/1.1 200 Success");
gavinp 2016/06/28 14:24:43 Nit: I know this was probably cut and paste, but y
asanka 2016/06/28 16:55:37 Done.
7117 response_headers->assign(base::StringPrintf("Content-Length: %" PRId64 "\n"
7118 "ETag: \"foo\"\n"
7119 "Accept-Ranges: bytes\n",
7120 kTotalSize));
7121 return;
7122 }
7123
7124 // From this point on, we should be processing a valid byte-range request.
7125 EXPECT_EQ("\"foo\"", if_range);
7126
7127 std::string range_header;
7128 EXPECT_TRUE(request->extra_headers.GetHeader(net::HttpRequestHeaders::kRange,
7129 &range_header));
7130 std::vector<net::HttpByteRange> ranges;
7131
7132 EXPECT_TRUE(net::HttpUtil::ParseRangeHeader(range_header, &ranges));
7133 ASSERT_EQ(1u, ranges.size());
7134
7135 net::HttpByteRange range = ranges[0];
7136 EXPECT_TRUE(range.HasFirstBytePosition());
7137 int64_t last_byte_position =
7138 range.HasLastBytePosition() ? range.last_byte_position() : kTotalSize - 1;
7139
7140 response_status->assign("HTTP/1.1 206 Partial");
7141 response_headers->assign(base::StringPrintf(
7142 "Content-Range: bytes %" PRId64 "-%" PRId64 "/%" PRId64
7143 "\n"
7144 "Content-Length: %" PRId64 "\n",
7145 range.first_byte_position(), last_byte_position, kTotalSize,
7146 last_byte_position - range.first_byte_position() + 1));
7147 }
7148
7149 // static
7150 int HttpCacheHugeResourceTest::LargeBufferReader(int64_t content_length,
7151 int64_t offset,
7152 net::IOBuffer* buf,
7153 int buf_len) {
7154 // This test involves reading multiple gigabytes of data. To make it run in a
7155 // reasonable amount of time, we are going to skip filling the buffer with
7156 // data. Instead the test relies on verifying that the count of bytes expected
7157 // at the end is correct.
7158 EXPECT_LT(0, content_length);
7159 EXPECT_LE(offset, content_length);
7160 int num = std::min(static_cast<int64_t>(buf_len), content_length - offset);
7161 return num;
7162 }
7163
7164 // static
7165 void HttpCacheHugeResourceTest::SetFlagOnBeforeNetworkStart(bool* started,
7166 bool* /* defer */) {
7167 *started = true;
7168 }
7169
7170 // static
7171 void HttpCacheHugeResourceTest::SetupTruncatedCacheEntry(MockHttpCache* cache) {
7172 ScopedMockTransaction scoped_transaction(kRangeGET_TransactionOK);
7173 std::string cached_headers = base::StringPrintf(
7174 "HTTP/1.1 200 OK\n"
7175 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7176 "ETag: \"foo\"\n"
7177 "Accept-Ranges: bytes\n"
7178 "Content-Length: %" PRId64 "\n",
7179 kTotalSize);
7180 CreateTruncatedEntry(cached_headers, cache);
7181 }
7182
7183 // static
7184 void HttpCacheHugeResourceTest::SetupPrefixSparseCacheEntry(
7185 MockHttpCache* cache) {
7186 MockTransaction transaction(kRangeGET_TransactionOK);
7187 transaction.handler = nullptr;
7188 transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER;
7189 transaction.response_headers =
7190 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7191 "ETag: \"foo\"\n"
7192 "Accept-Ranges: bytes\n"
7193 "Content-Range: bytes 0-9/5000000000\n"
7194 "Content-Length: 10\n";
7195 AddMockTransaction(&transaction);
7196 std::string headers;
7197 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
7198 RemoveMockTransaction(&transaction);
7199 }
7200
7201 // static
7202 void HttpCacheHugeResourceTest::SetupInfixSparseCacheEntry(
7203 MockHttpCache* cache) {
7204 MockTransaction transaction(kRangeGET_TransactionOK);
7205 transaction.handler = nullptr;
7206 transaction.request_headers = "Range: bytes = 99990-99999\r\n" EXTRA_HEADER;
7207 transaction.response_headers =
7208 "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n"
7209 "ETag: \"foo\"\n"
7210 "Accept-Ranges: bytes\n"
7211 "Content-Range: bytes 99990-99999/5000000000\n"
7212 "Content-Length: 10\n";
7213 AddMockTransaction(&transaction);
7214 std::string headers;
7215 RunTransactionTestWithResponse(cache->http_cache(), transaction, &headers);
7216 RemoveMockTransaction(&transaction);
7217 }
7218
7219 // static
7220 std::list<HugeCacheTestConfiguration>
7221 HttpCacheHugeResourceTest::GetTestModes() {
7222 std::list<HugeCacheTestConfiguration> test_modes;
7223 const TransactionPhase kTransactionPhases[] = {
7224 TransactionPhase::BEFORE_FIRST_READ, TransactionPhase::AFTER_FIRST_READ,
7225 TransactionPhase::AFTER_NETWORK_READ};
7226 const CacheInitializer kInitializers[] = {&SetupTruncatedCacheEntry,
7227 &SetupPrefixSparseCacheEntry,
7228 &SetupInfixSparseCacheEntry};
7229
7230 for (const auto phase : kTransactionPhases)
7231 for (const auto initializer : kInitializers)
7232 test_modes.push_back(std::make_pair(phase, initializer));
7233
7234 return test_modes;
7235 }
7236
7237 // static
7238 std::list<HugeCacheTestConfiguration> HttpCacheHugeResourceTest::kTestModes =
7239 HttpCacheHugeResourceTest::GetTestModes();
7240
7241 INSTANTIATE_TEST_CASE_P(
7242 _,
7243 HttpCacheHugeResourceTest,
7244 ::testing::ValuesIn(HttpCacheHugeResourceTest::kTestModes));
7245
7246 } // namespace
7247
7248 // Test what happens when StopCaching() is called while reading a huge resource
7249 // fetched via GET. Various combinations of cache state and when StopCaching()
7250 // is called is controlled by the parameter passed into the test via the
7251 // INSTANTIATE_TEST_CASE_P invocation above.
7252 TEST_P(HttpCacheHugeResourceTest,
7253 StopCachingFollowedByReadForHugeTruncatedResource) {
7254 // This test is going to be repeated for all combinations of TransactionPhase
7255 // and CacheInitializers returned by GetTestModes().
7256 const TransactionPhase stop_caching_phase = GetParam().first;
7257 const CacheInitializer cache_initializer = GetParam().second;
7258
7259 MockHttpCache cache;
7260 (*cache_initializer)(&cache);
7261
7262 MockTransaction transaction(kSimpleGET_Transaction);
7263 transaction.url = kRangeGET_TransactionOK.url;
7264 transaction.handler = &LargeResourceTransactionHandler;
7265 transaction.read_handler = &LargeBufferReader;
7266 ScopedMockTransaction scoped_transaction(transaction);
7267
7268 MockHttpRequest request(transaction);
7269 net::TestCompletionCallback callback;
7270 std::unique_ptr<net::HttpTransaction> http_transaction;
7271 int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY,
7272 &http_transaction);
7273 ASSERT_EQ(net::OK, rv);
7274 ASSERT_TRUE(http_transaction.get());
7275
7276 bool network_transaction_started = false;
7277 if (stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
7278 http_transaction->SetBeforeNetworkStartCallback(
7279 base::Bind(&SetFlagOnBeforeNetworkStart, &network_transaction_started));
7280 }
7281
7282 rv = http_transaction->Start(&request, callback.callback(),
7283 net::BoundNetLog());
7284 rv = callback.GetResult(rv);
7285 ASSERT_EQ(net::OK, rv);
7286
7287 if (stop_caching_phase == TransactionPhase::BEFORE_FIRST_READ)
7288 http_transaction->StopCaching();
7289
7290 int64_t total_bytes_received = 0;
7291
7292 EXPECT_EQ(kTotalSize,
7293 http_transaction->GetResponseInfo()->headers->GetContentLength());
7294 do {
7295 // This test simulates reading Gigabytes of data. Buffer size is set to 10MB
gavinp 2016/06/28 14:24:43 Nit: I don't believe we need to capitalise gigabyt
asanka 2016/06/28 16:55:38 Done.
7296 // to reduce the number of reads and speedup the test.
gavinp 2016/06/28 14:24:43 Nit: speedup is a noun, I believe you want "speed
asanka 2016/06/28 16:55:38 Done.
7297 const int kBufferSize = 1024 * 1024 * 10;
7298 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize));
7299 rv = http_transaction->Read(buf.get(), kBufferSize, callback.callback());
7300 rv = callback.GetResult(rv);
7301
7302 if (stop_caching_phase == TransactionPhase::AFTER_FIRST_READ &&
7303 total_bytes_received == 0) {
7304 http_transaction->StopCaching();
7305 }
7306
7307 if (rv > 0)
7308 total_bytes_received += rv;
7309
7310 if (network_transaction_started &&
7311 stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
7312 http_transaction->StopCaching();
7313 network_transaction_started = false;
7314 }
7315 } while (rv > 0);
7316
7317 // The only verification we are going to do is that the received resource has
7318 // the correct size. This is sufficient to verify that the state machine
7319 // didn't terminate abruptly due to the StopCaching() call.
7320 EXPECT_EQ(kTotalSize, total_bytes_received);
7321 }
7322
7059 // Tests that we detect truncated resources from the net when there is 7323 // Tests that we detect truncated resources from the net when there is
7060 // a Content-Length header. 7324 // a Content-Length header.
7061 TEST(HttpCache, TruncatedByContentLength) { 7325 TEST(HttpCache, TruncatedByContentLength) {
7062 MockHttpCache cache; 7326 MockHttpCache cache;
7063 TestCompletionCallback callback; 7327 TestCompletionCallback callback;
7064 7328
7065 MockTransaction transaction(kSimpleGET_Transaction); 7329 MockTransaction transaction(kSimpleGET_Transaction);
7066 AddMockTransaction(&transaction); 7330 AddMockTransaction(&transaction);
7067 transaction.response_headers = "Cache-Control: max-age=10000\n" 7331 transaction.response_headers = "Cache-Control: max-age=10000\n"
7068 "Content-Length: 100\n"; 7332 "Content-Length: 100\n";
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after
7735 EXPECT_EQ(1, cache.disk_cache()->open_count()); 7999 EXPECT_EQ(1, cache.disk_cache()->open_count());
7736 EXPECT_EQ(1, cache.disk_cache()->create_count()); 8000 EXPECT_EQ(1, cache.disk_cache()->create_count());
7737 EXPECT_TRUE(response_info.was_cached); 8001 EXPECT_TRUE(response_info.was_cached);
7738 8002
7739 // The new SSL state is reported. 8003 // The new SSL state is reported.
7740 EXPECT_EQ(status2, response_info.ssl_info.connection_status); 8004 EXPECT_EQ(status2, response_info.ssl_info.connection_status);
7741 EXPECT_TRUE(cert2->Equals(response_info.ssl_info.cert.get())); 8005 EXPECT_TRUE(cert2->Equals(response_info.ssl_info.cert.get()));
7742 } 8006 }
7743 8007
7744 } // namespace net 8008 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698