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

Unified 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: Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
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) {

Powered by Google App Engine
This is Rietveld 408576698