Chromium Code Reviews| Index: net/http/http_cache_unittest.cc |
| diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc |
| index f490444356fb1240f22e71fc3f443d0815b3a86b..e09bdb9eb0c387cb76194593764e1f48c50cf920 100644 |
| --- a/net/http/http_cache_unittest.cc |
| +++ b/net/http/http_cache_unittest.cc |
| @@ -8,6 +8,7 @@ |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| +#include "base/format_macros.h" |
| #include "base/memory/scoped_vector.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| @@ -276,7 +277,6 @@ const MockTransaction kFastNoStoreGET_Transaction = { |
| &FastTransactionServer::FastNoStoreHandler, |
| nullptr, |
| 0, |
| - 0, |
| OK}; |
| // This class provides a handler for kRangeGET_TransactionOK so that the range |
| @@ -342,6 +342,8 @@ void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request, |
| std::string* response_status, |
| std::string* response_headers, |
| std::string* response_data) { |
| + SCOPED_TRACE(testing::Message() << "Request headers: \n" |
| + << request->extra_headers.ToString()); |
| if (request->extra_headers.IsEmpty()) { |
| response_status->assign("HTTP/1.1 416 Requested Range Not Satisfiable"); |
| response_data->clear(); |
| @@ -449,7 +451,6 @@ const MockTransaction kRangeGET_TransactionOK = { |
| &RangeTransactionServer::RangeHandler, |
| nullptr, |
| 0, |
| - 0, |
| OK}; |
| const char kFullRangeData[] = |
| @@ -6718,8 +6719,9 @@ TEST(HttpCache, DoneReading) { |
| EXPECT_EQ(1, cache.disk_cache()->create_count()); |
| } |
| -// Tests that we stop caching when told. |
| -TEST(HttpCache, StopCachingDeletesEntry) { |
| +// Tests that calling StopCaching() causes the cache entry to be deleted if the |
| +// request cannot be resumed. |
| +TEST(HttpCache, StopCachingDeletesEntryIfRequestIsNotResumable) { |
| MockHttpCache cache; |
| TestCompletionCallback callback; |
| MockHttpRequest request(kSimpleGET_Transaction); |
| @@ -6788,7 +6790,8 @@ TEST(HttpCache, StopCachingThenDoneReadingDeletesEntry) { |
| // Make sure that the ActiveEntry is gone. |
| base::MessageLoop::current()->RunUntilIdle(); |
| - // Verify that the entry is gone. |
| + // Verify that the entry is gone. The request is not resumeable, so the cache |
| + // entry should be deleted if only part of the response was cached. |
| RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); |
| EXPECT_EQ(2, cache.network_layer()->transaction_count()); |
| @@ -6832,7 +6835,9 @@ TEST(HttpCache, StopCachingWithAuthDeletesEntry) { |
| } |
| // Tests that when we are told to stop caching we don't throw away valid data. |
| -TEST(HttpCache, StopCachingSavesEntry) { |
| +// If the request is resumable (i.e. has strong validators), then the cache |
| +// should hold on to the partial response. |
| +TEST(HttpCache, StopCachingSavesEntryIfRequestIsResumable) { |
| MockHttpCache cache; |
| TestCompletionCallback callback; |
| MockHttpRequest request(kSimpleGET_Transaction); |
| @@ -6904,7 +6909,8 @@ TEST(HttpCache, StopCachingTruncatedEntry) { |
| rv = trans->Read(buf.get(), 10, callback.callback()); |
| EXPECT_EQ(callback.GetResult(rv), 10); |
| - // This is actually going to do nothing. |
| + // This prevents any further writes to the cache entry, but doesn't discard |
| + // the existing entry. |
| trans->StopCaching(); |
| // We should be able to keep reading. |
| @@ -6916,19 +6922,167 @@ TEST(HttpCache, StopCachingTruncatedEntry) { |
| EXPECT_EQ(callback.GetResult(rv), 0); |
| } |
| - // Verify that the disk entry was updated. |
| + // Verify that the disk entry was not updated. |
| disk_cache::Entry* entry; |
| ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); |
| - EXPECT_EQ(80, entry->GetDataSize(1)); |
| - bool truncated = true; |
| + EXPECT_EQ(20, entry->GetDataSize(1)); |
| + bool truncated = false; |
| HttpResponseInfo response; |
| EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); |
| - EXPECT_FALSE(truncated); |
| + EXPECT_TRUE(truncated); |
| entry->Close(); |
| RemoveMockTransaction(&kRangeGET_TransactionOK); |
| } |
| +namespace { |
| + |
| +const int64 kTotalSize = 5000000000LL; // Five beeeeeelllliooonn bytes! |
| + |
| +void ExpectByteRangeTransactionHandler(const net::HttpRequestInfo* request, |
| + std::string* response_status, |
| + std::string* response_headers, |
| + std::string* response_data) { |
| + std::string if_range; |
| + EXPECT_TRUE(request->extra_headers.GetHeader( |
| + net::HttpRequestHeaders::kIfRange, &if_range)); |
| + EXPECT_EQ("\"foo\"", if_range); |
| + |
| + std::string range_header; |
| + EXPECT_TRUE(request->extra_headers.GetHeader(net::HttpRequestHeaders::kRange, |
| + &range_header)); |
| + std::vector<net::HttpByteRange> ranges; |
| + |
| + EXPECT_TRUE(net::HttpUtil::ParseRangeHeader(range_header, &ranges)); |
| + ASSERT_EQ(1u, ranges.size()); |
| + |
| + net::HttpByteRange range = ranges[0]; |
| + EXPECT_TRUE(range.HasFirstBytePosition()); |
| + EXPECT_TRUE(range.HasLastBytePosition()); |
| + |
| + response_status->assign("HTTP/1.1 206 Partial"); |
| + response_headers->assign(base::StringPrintf( |
| + "Content-Range: bytes %" PRId64 "-%" PRId64 "/%" PRId64 |
| + "\n" |
| + "Content-Length: %" PRId64 "\n", |
| + range.first_byte_position(), range.last_byte_position(), kTotalSize, |
| + range.last_byte_position() - range.first_byte_position() + 1)); |
| +} |
| + |
| +int LargeBufferReader(int64 content_length, |
| + int64 offset, |
| + net::IOBuffer* buf, |
| + int buf_len) { |
| + EXPECT_LT(0, content_length); |
| + EXPECT_LE(offset, content_length); |
| + int num = std::min(static_cast<int64>(buf_len), content_length - offset); |
| + return num; |
| +} |
| + |
| +void SetFlagOnBeforeNetworkStart(bool* started, bool* /* defer */) { |
| + *started = true; |
| +} |
| + |
| +void StopCachingOnBeforeNetworkStart(HttpTransaction* transaction, |
| + bool* /* defer */) { |
| + transaction->StopCaching(); |
| +} |
| + |
| +enum TransactionPhases { |
| + TRANSACTION_PHASE_BEFORE_FIRST_READ, |
| + TRANSACTION_PHASE_ON_BEFORE_NETWORK_START, |
| + TRANSACTION_PHASE_AFTER_FIRST_READ, |
| + TRANSACTION_PHASE_AFTER_NETWORK_READ |
| +}; |
| + |
| +class HttpCacheTestWithPhases |
| + : public ::testing::TestWithParam<TransactionPhases> {}; |
| + |
| +INSTANTIATE_TEST_CASE_P( |
| + Phase, |
| + HttpCacheTestWithPhases, |
| + ::testing::Values(TRANSACTION_PHASE_BEFORE_FIRST_READ, |
| + TRANSACTION_PHASE_ON_BEFORE_NETWORK_START, |
| + TRANSACTION_PHASE_AFTER_FIRST_READ, |
| + TRANSACTION_PHASE_AFTER_NETWORK_READ)); |
| + |
| +} // namespace |
| + |
| +TEST_P(HttpCacheTestWithPhases, |
| + StopCachingFollowedByReadForHugeTruncatedResource) { |
| + MockHttpCache cache; |
| + MockTransaction transaction(kSimpleGET_Transaction); |
| + transaction.url = kRangeGET_TransactionOK.url; |
| + transaction.handler = &ExpectByteRangeTransactionHandler; |
| + transaction.read_handler = &LargeBufferReader; |
| + ScopedMockTransaction scoped_transaction(transaction); |
| + |
| + std::string cached_headers = base::StringPrintf( |
| + "HTTP/1.1 200 OK\n" |
| + "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" |
| + "ETag: \"foo\"\n" |
| + "Accept-Ranges: bytes\n" |
| + "Content-Length: %" PRId64 "\n", |
| + kTotalSize); |
| + CreateTruncatedEntry(cached_headers, &cache); |
| + |
| + MockHttpRequest request(transaction); |
| + net::TestCompletionCallback callback; |
| + scoped_ptr<net::HttpTransaction> http_transaction; |
| + int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY, |
| + &http_transaction); |
| + ASSERT_EQ(net::OK, rv); |
| + ASSERT_TRUE(http_transaction.get()); |
| + |
| + if (GetParam() == TRANSACTION_PHASE_ON_BEFORE_NETWORK_START) |
| + http_transaction->SetBeforeNetworkStartCallback( |
| + base::Bind(&StopCachingOnBeforeNetworkStart, http_transaction.get())); |
| + |
| + bool network_transaction_started = false; |
| + if (GetParam() == TRANSACTION_PHASE_AFTER_NETWORK_READ) |
| + http_transaction->SetBeforeNetworkStartCallback( |
| + base::Bind(&SetFlagOnBeforeNetworkStart, &network_transaction_started)); |
| + |
| + rv = http_transaction->Start(&request, callback.callback(), |
| + net::BoundNetLog()); |
| + rv = callback.GetResult(rv); |
| + ASSERT_EQ(net::OK, rv); |
| + |
| + if (GetParam() == TRANSACTION_PHASE_BEFORE_FIRST_READ) |
| + http_transaction->StopCaching(); |
| + |
| + int64 total_bytes_received = 0; |
| + |
| + EXPECT_EQ(kTotalSize, |
| + http_transaction->GetResponseInfo()->headers->GetContentLength()); |
| + do { |
| + // This test simulates reading Gigabytes of data. Buffer size is set to 1MB |
| + // to reduce the number of reads and speedup the test. |
| + const int kBufferSize = 1024 * 1024; |
| + scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize)); |
| + rv = http_transaction->Read(buf.get(), kBufferSize, callback.callback()); |
| + rv = callback.GetResult(rv); |
| + |
| + if (GetParam() == TRANSACTION_PHASE_AFTER_FIRST_READ && |
| + total_bytes_received == 0) |
| + http_transaction->StopCaching(); |
| + |
| + if (rv > 0) |
| + total_bytes_received += rv; |
| + |
| + if (network_transaction_started && |
| + GetParam() == TRANSACTION_PHASE_AFTER_NETWORK_READ) { |
| + http_transaction->StopCaching(); |
| + network_transaction_started = false; |
| + } |
| + } while (rv > 0); |
| + |
| + // The only thing we can test right now. Ideally we would also verify that |
|
hubbe
2015/07/16 15:56:12
This comment makes no sense to me.
Verify A, but c
asanka
2015/07/16 16:16:58
The comment is explaining why we aren't checking m
hubbe
2015/07/16 16:57:52
Yes, this is a much better explanation than what i
asanka
2015/07/16 17:57:00
Done.
|
| + // only a single network request was made etc. But that's not currently |
| + // possible since multiple network requests are being made. |
| + EXPECT_EQ(kTotalSize, total_bytes_received); |
| +} |
| + |
| // Tests that we detect truncated resources from the net when there is |
| // a Content-Length header. |
| TEST(HttpCache, TruncatedByContentLength) { |