| Index: net/http/http_cache_unittest.cc
|
| diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
|
| index f6cba7a12b7317c97e97adce75f51707ee05616a..a2f8fe6eaa5740a783fbe87d9cdc1b14d780f1c2 100644
|
| --- a/net/http/http_cache_unittest.cc
|
| +++ b/net/http/http_cache_unittest.cc
|
| @@ -148,6 +148,203 @@ void ReadAndVerifyTransaction(HttpTransaction* trans,
|
| EXPECT_EQ(expected, content);
|
| }
|
|
|
| +void ReadAndVerifySharedWritersCacheRead(std::vector<Context*>& context_list,
|
| + const MockTransaction& trans_info) {
|
| + std::vector<std::string> contents(context_list.size());
|
| + int rv = ReadSharedWritersCacheRead(context_list, contents);
|
| +
|
| + EXPECT_THAT(rv, IsOk());
|
| + std::string expected(trans_info.data);
|
| + for (size_t i = 0; i < contents.size(); i++) {
|
| + EXPECT_EQ(expected, contents.at(i));
|
| + }
|
| +}
|
| +
|
| +void ReadAndVerifySharedWritersJoinedRead(const MockTransaction& trans_info,
|
| + std::vector<Context*>& context_list) {
|
| + std::vector<std::string> results(context_list.size());
|
| + int rv = ReadSharedWritersJoinedRead(context_list, results);
|
| +
|
| + EXPECT_THAT(rv, IsOk());
|
| + std::string expected(trans_info.data);
|
| + for (size_t i = 0; i < results.size(); i++) {
|
| + EXPECT_EQ(expected, results[i]);
|
| + }
|
| +}
|
| +
|
| +void ReadAndVerifySharedWritersJoinedReadDoneReading(
|
| + const MockTransaction& trans_info,
|
| + std::vector<Context*>& context_list) {
|
| + std::vector<std::string> results(context_list.size());
|
| + int rv = ReadSharedWritersJoinedReadDoneReading(context_list, results);
|
| +
|
| + EXPECT_THAT(rv, IsOk());
|
| + std::string expected(trans_info.data);
|
| + for (size_t i = 0; i < results.size(); i++) {
|
| + EXPECT_EQ(expected, results[i]);
|
| + }
|
| +}
|
| +
|
| +void ReadAndVerifySharedWritersJoinedReadDoomCurrentWriter(
|
| + const MockTransaction& trans_info,
|
| + std::vector<Context*>& context_list) {
|
| + std::vector<std::string> results(context_list.size() - 1);
|
| + int rv = ReadSharedWritersJoinedReadDoomCurrentWriter(context_list, results);
|
| +
|
| + EXPECT_THAT(rv, IsOk());
|
| + std::string expected(trans_info.data);
|
| + for (size_t i = 0; i < results.size(); i++) {
|
| + EXPECT_EQ(expected, results[i]);
|
| + }
|
| +}
|
| +
|
| +void ReadAndVerifySharedWritersDeleteWaitingWriter(
|
| + const MockTransaction& trans_info,
|
| + std::vector<Context*>& context_list) {
|
| + std::vector<std::string> results(context_list.size() - 1);
|
| + int rv =
|
| + ReadSharedWritersJoinedReadDeleteWaitingWriter(context_list, results);
|
| +
|
| + EXPECT_THAT(rv, IsOk());
|
| + std::string expected(trans_info.data);
|
| + for (size_t i = 0; i < results.size(); i++) {
|
| + EXPECT_EQ(expected, results[i]);
|
| + }
|
| +}
|
| +
|
| +void ReadAndVerifySharedWritersDeleteIdleWriter(
|
| + const MockTransaction& trans_info,
|
| + std::vector<Context*>& context_list) {
|
| + std::vector<std::string> results(context_list.size() - 1);
|
| + int rv = ReadSharedWritersJoinedReadDeleteIdleWriter(context_list, results);
|
| +
|
| + EXPECT_THAT(rv, IsOk());
|
| + std::string expected(trans_info.data);
|
| + for (size_t i = 0; i < results.size(); i++) {
|
| + EXPECT_EQ(expected, results[i]);
|
| + }
|
| +}
|
| +
|
| +int ReadSharedWritersJoinedReadCacheWriteFailure(
|
| + std::vector<Context*>& context_list,
|
| + std::vector<std::string>& results,
|
| + MockHttpCache& cache) {
|
| + int rv = 0;
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| +
|
| + // Fail the request.
|
| + cache.disk_cache()->set_soft_failures(true);
|
| + // We have to open the entry again to propagate the failure flag.
|
| + disk_cache::Entry* en;
|
| + cache.OpenBackendEntry(kSimpleGET_Transaction.url, &en);
|
| + en->Close();
|
| +
|
| + // Invoke Read for a few transactions so they become current_writer_ and
|
| + // waiting_writers_ respectively.
|
| + std::vector<scoped_refptr<IOBuffer>> buf(2);
|
| + size_t i = 0, j = 0;
|
| + do {
|
| + HttpTransaction* trans = context_list[i]->trans.get();
|
| + buf[j] = new IOBuffer(30);
|
| + rv = trans->Read(buf[j].get(), 30, context_list[i]->callback.callback());
|
| + i = context_list.size() - 1;
|
| + j++;
|
| + } while (j < buf.size());
|
| +
|
| + // current_writer_ which is transaction [0] should continue without writing
|
| + // to the cache, idle writer ([3]) should fail on its next Read call and
|
| + // waiting_writers_ ([6]) should return a failure back.
|
| + if (rv == ERR_IO_PENDING) {
|
| + Context* ct = *(context_list.begin());
|
| + rv = ct->callback.WaitForResult();
|
| + }
|
| +
|
| + // Only [0] should succeed in the Read.
|
| + results[0].append(buf[0]->data(), 30);
|
| +
|
| + // Invoke Start on 4 and 5. 4 will fail to read from the cache, doom the
|
| + // entry and go on to create a new entry. 5 will also get added to that
|
| + // entry.
|
| + for (size_t i = 4; i <= 5; i++) {
|
| + Context* c = context_list[i];
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + }
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // 3 and 6 failed, delete them.
|
| + Context* c = context_list[3];
|
| + scoped_refptr<IOBuffer> buf1 = new IOBuffer(30);
|
| + int rv_fail = c->trans->Read(buf1.get(), 30, c->callback.callback());
|
| + EXPECT_THAT(rv_fail, ERR_CACHE_WRITE_FAILURE);
|
| +
|
| + Context* c6 = context_list[6];
|
| + for (auto itr = context_list.begin(); itr != context_list.end();) {
|
| + if (*itr == c || *itr == c6) {
|
| + Context* ct = *itr;
|
| + itr = context_list.erase(itr);
|
| + delete ct;
|
| + } else {
|
| + itr++;
|
| + }
|
| + }
|
| +
|
| + cache.disk_cache()->set_soft_failures(false);
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Read for the rest of the transactions.
|
| + Context* c0 = context_list[0];
|
| + Context* c3 = context_list[3];
|
| + for (size_t i = 0; i < context_list.size(); i++) {
|
| + if (i == 1 || i == 2 || i == 4)
|
| + continue;
|
| + std::string res;
|
| + ReadTransaction(context_list[i]->trans.get(), &res);
|
| + results[i].append(res);
|
| + }
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // Delete the done transactions so that pending queue can be processed.
|
| + // The reader transactions will error out with ERR_CACHE_MISS because of cache
|
| + // failures.
|
| + Context* c1 = context_list[1];
|
| + Context* c2 = context_list[2];
|
| + auto itr = context_list.begin();
|
| + for (; itr != context_list.end();) {
|
| + Context* c = *itr;
|
| + if (c == c0 || c == c1 || c == c2 || c == c3) {
|
| + itr = context_list.erase(itr);
|
| + delete c;
|
| + } else {
|
| + itr++;
|
| + }
|
| + }
|
| +
|
| + std::string res;
|
| + ReadTransaction(context_list[0]->trans.get(), &res);
|
| + results[4].append(res);
|
| +
|
| + return OK;
|
| +}
|
| +
|
| +void ReadAndVerifySharedWritersJoinedReadCacheWriteFailure(
|
| + const MockTransaction& trans_info,
|
| + std::vector<Context*>& context_list,
|
| + MockHttpCache& cache) {
|
| + std::vector<std::string> results(context_list.size());
|
| + int rv = ReadSharedWritersJoinedReadCacheWriteFailure(context_list, results,
|
| + cache);
|
| +
|
| + EXPECT_THAT(rv, IsOk());
|
| + std::string expected(trans_info.data);
|
| + for (size_t i = 0; i < context_list.size(); i++) {
|
| + EXPECT_EQ(expected, results[i]);
|
| + }
|
| +}
|
| +
|
| void RunTransactionTestBase(HttpCache* cache,
|
| const MockTransaction& trans_info,
|
| const MockHttpRequest& request,
|
| @@ -157,24 +354,22 @@ void RunTransactionTestBase(HttpCache* cache,
|
| int64_t* sent_bytes,
|
| int64_t* received_bytes,
|
| IPEndPoint* remote_endpoint) {
|
| - TestCompletionCallback callback;
|
| -
|
| // write to the cache
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &trans);
|
| + Context* c = new Context();
|
| + int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &c->trans);
|
| EXPECT_THAT(rv, IsOk());
|
| - ASSERT_TRUE(trans.get());
|
| + ASSERT_TRUE(c->trans.get());
|
|
|
| - rv = trans->Start(&request, callback.callback(), net_log);
|
| + rv = c->trans->Start(&request, c->callback.callback(), net_log);
|
| if (rv == ERR_IO_PENDING)
|
| - rv = callback.WaitForResult();
|
| + rv = c->callback.WaitForResult();
|
| ASSERT_EQ(trans_info.return_code, rv);
|
|
|
| if (OK != rv)
|
| return;
|
|
|
| - const HttpResponseInfo* response = trans->GetResponseInfo();
|
| + const HttpResponseInfo* response = c->trans->GetResponseInfo();
|
| ASSERT_TRUE(response);
|
|
|
| if (response_info)
|
| @@ -185,18 +380,20 @@ void RunTransactionTestBase(HttpCache* cache,
|
| // ID.
|
| EXPECT_TRUE(net_log.net_log());
|
| *load_timing_info = LoadTimingInfo();
|
| - trans->GetLoadTimingInfo(load_timing_info);
|
| + c->trans->GetLoadTimingInfo(load_timing_info);
|
| }
|
|
|
| if (remote_endpoint)
|
| - ASSERT_TRUE(trans->GetRemoteEndpoint(remote_endpoint));
|
| + ASSERT_TRUE(c->trans->GetRemoteEndpoint(remote_endpoint));
|
|
|
| - ReadAndVerifyTransaction(trans.get(), trans_info);
|
| + ReadAndVerifyTransaction(c->trans.get(), trans_info);
|
|
|
| if (sent_bytes)
|
| - *sent_bytes = trans->GetTotalSentBytes();
|
| + *sent_bytes = c->trans->GetTotalSentBytes();
|
| if (received_bytes)
|
| - *received_bytes = trans->GetTotalReceivedBytes();
|
| + *received_bytes = c->trans->GetTotalReceivedBytes();
|
| +
|
| + delete c;
|
| }
|
|
|
| void RunTransactionTestWithRequest(HttpCache* cache,
|
| @@ -572,14 +769,6 @@ struct Response {
|
| const char* body;
|
| };
|
|
|
| -struct Context {
|
| - Context() : result(ERR_IO_PENDING) {}
|
| -
|
| - int result;
|
| - TestCompletionCallback callback;
|
| - std::unique_ptr<HttpTransaction> trans;
|
| -};
|
| -
|
| class FakeWebSocketHandshakeStreamCreateHelper
|
| : public WebSocketHandshakeStreamBase::CreateHelper {
|
| public:
|
| @@ -641,9 +830,10 @@ bool LogContainsEventType(const BoundTestNetLog& log,
|
| TEST(HttpCache, CreateThenDestroy) {
|
| MockHttpCache cache;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - EXPECT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| - ASSERT_TRUE(trans.get());
|
| + Context* c = new Context();
|
| + EXPECT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
| + ASSERT_TRUE(c->trans.get());
|
| + delete c;
|
| }
|
|
|
| TEST(HttpCache, GetBackend) {
|
| @@ -732,18 +922,20 @@ TEST(HttpCache, ReleaseBuffer) {
|
| RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction);
|
|
|
| MockHttpRequest request(kSimpleGET_Transaction);
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + Context* c = new Context();
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| const int kBufferSize = 10;
|
| scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
|
| ReleaseBufferCompletionCallback cb(buffer.get());
|
|
|
| - int rv = trans->Start(&request, cb.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, cb.callback(), NetLogWithSource());
|
| EXPECT_THAT(cb.GetResult(rv), IsOk());
|
|
|
| - rv = trans->Read(buffer.get(), kBufferSize, cb.callback());
|
| + rv = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
|
| EXPECT_EQ(kBufferSize, cb.GetResult(rv));
|
| +
|
| + delete c;
|
| }
|
|
|
| TEST(HttpCache, SimpleGETWithDiskFailures) {
|
| @@ -920,18 +1112,16 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Miss) {
|
| transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
|
|
|
| MockHttpRequest request(transaction);
|
| - TestCompletionCallback callback;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| if (rv == ERR_IO_PENDING)
|
| - rv = callback.WaitForResult();
|
| + rv = c->callback.WaitForResult();
|
| ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
|
|
|
| - trans.reset();
|
| -
|
| EXPECT_EQ(0, cache.network_layer()->transaction_count());
|
| EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| EXPECT_EQ(0, cache.disk_cache()->create_count());
|
| @@ -1038,20 +1228,21 @@ TEST(HttpCache, SimpleGET_CacheSignal_Failure) {
|
| AddMockTransaction(&transaction);
|
|
|
| MockHttpRequest request(transaction);
|
| - TestCompletionCallback callback;
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
|
| + Context* c = new Context();
|
| + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &c->trans);
|
| EXPECT_THAT(rv, IsOk());
|
| - ASSERT_TRUE(trans.get());
|
| - rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| - EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
|
| + ASSERT_TRUE(c->trans.get());
|
| + rv = c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + EXPECT_THAT(c->callback.GetResult(rv), IsError(ERR_FAILED));
|
|
|
| - const HttpResponseInfo* response_info = trans->GetResponseInfo();
|
| + const HttpResponseInfo* response_info = c->trans->GetResponseInfo();
|
| ASSERT_TRUE(response_info);
|
| EXPECT_TRUE(response_info->was_cached);
|
| EXPECT_EQ(2, cache.network_layer()->transaction_count());
|
|
|
| RemoveMockTransaction(&transaction);
|
| +
|
| + delete c;
|
| }
|
|
|
| // Confirm if we have an empty cache, a read is marked as network verified.
|
| @@ -1342,8 +1533,9 @@ TEST(HttpCache, SimpleGET_ManyReaders) {
|
| // Allow all requests to move from the Create queue to the active entry.
|
| base::RunLoop().RunUntilIdle();
|
|
|
| - // The first request should be a writer at this point, and the subsequent
|
| - // requests should be pending.
|
| + // At the end of Start: [0] should be in shared_writers->all_writers_,
|
| + // [3] and [4] should also be in all_writers_ since its a case of validation
|
| + // match/skip, [1] and [2] should be in pending_queue.
|
|
|
| EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| @@ -1419,11 +1611,12 @@ TEST(HttpCache, SimpleGET_RacingReaders) {
|
| c->result = c->callback.WaitForResult();
|
| ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
|
|
|
| - // Now we have 2 active readers and two queued transactions.
|
| -
|
| + // after [0] completes reading and writing, [3] and [4] should be added to
|
| + // entry->readers from shared writers and pending queue should be
|
| + // processed to add [1] and [2] to readers as well. They are all waiting for
|
| + // their consumer to invoke Read.
|
| EXPECT_EQ(LOAD_STATE_IDLE, context_list[2]->trans->GetLoadState());
|
| - EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE,
|
| - context_list[3]->trans->GetLoadState());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, context_list[3]->trans->GetLoadState());
|
|
|
| c = context_list[1];
|
| ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
|
| @@ -1437,7 +1630,9 @@ TEST(HttpCache, SimpleGET_RacingReaders) {
|
| // next request.
|
|
|
| c = context_list[2];
|
| - c->trans.reset();
|
| + if (c->trans) {
|
| + c->trans->Orphan(std::move(c->trans));
|
| + }
|
|
|
| for (int i = 3; i < kNumTransactions; ++i) {
|
| Context* c = context_list[i];
|
| @@ -1537,9 +1732,9 @@ TEST(HttpCache, FastNoStoreGET_DoneWithPending) {
|
| // The first request should be a writer at this point, and the subsequent
|
| // requests should be pending.
|
|
|
| - EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(3, cache.network_layer()->transaction_count());
|
| EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| - EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| + EXPECT_EQ(2, cache.disk_cache()->create_count());
|
|
|
| // Now, make sure that the second request asks for the entry not to be stored.
|
| request_handler.set_no_store(true);
|
| @@ -1582,7 +1777,8 @@ TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) {
|
| base::RunLoop().RunUntilIdle();
|
|
|
| // The first request should be a writer at this point, and the subsequent
|
| - // requests should be pending.
|
| + // requests should have been added to SharedWriters, skipped validation and
|
| + // completed the start state machine of HttpCache::Transaction.
|
|
|
| EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| @@ -1605,11 +1801,11 @@ TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) {
|
| ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
|
| }
|
|
|
| - // We should have had to re-open the disk entry.
|
| -
|
| - EXPECT_EQ(2, cache.network_layer()->transaction_count());
|
| + // 2nd transaction will reuse the network transaction as they are both part of
|
| + // SharedWriters. Similarly it will be part of the same entry.
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| - EXPECT_EQ(2, cache.disk_cache()->create_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
|
|
| for (int i = 1; i < kNumTransactions; ++i) {
|
| Context* c = context_list[i];
|
| @@ -1791,7 +1987,9 @@ TEST(HttpCache, SimpleGET_AbandonedCacheRead) {
|
|
|
| // Test that destroying the transaction while it is reading from the cache
|
| // works properly.
|
| - trans.reset();
|
| + if (trans) {
|
| + trans->Orphan(std::move(trans));
|
| + }
|
|
|
| // Make sure we pump any pending events, which should include a call to
|
| // HttpCache::Transaction::OnCacheReadCompleted.
|
| @@ -2960,15 +3158,13 @@ TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Miss) {
|
| MockHttpRequest request(transaction);
|
| TestCompletionCallback callback;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| - ASSERT_TRUE(trans.get());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
| + ASSERT_TRUE(c->trans.get());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| ASSERT_THAT(callback.GetResult(rv), IsError(ERR_CACHE_MISS));
|
|
|
| - trans.reset();
|
| -
|
| EXPECT_EQ(0, cache.network_layer()->transaction_count());
|
| EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| EXPECT_EQ(0, cache.disk_cache()->create_count());
|
| @@ -3215,15 +3411,13 @@ TEST(HttpCache, SimpleHEAD_LoadOnlyFromCache_Miss) {
|
| MockHttpRequest request(transaction);
|
| TestCompletionCallback callback;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| - ASSERT_TRUE(trans.get());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
| + ASSERT_TRUE(c->trans.get());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| ASSERT_THAT(callback.GetResult(rv), IsError(ERR_CACHE_MISS));
|
|
|
| - trans.reset();
|
| -
|
| EXPECT_EQ(0, cache.network_layer()->transaction_count());
|
| EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| EXPECT_EQ(0, cache.disk_cache()->create_count());
|
| @@ -5610,17 +5804,17 @@ TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) {
|
| MockHttpRequest request(transaction);
|
| TestCompletionCallback callback;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
|
| + std::unique_ptr<Context> c(new Context());
|
| + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &c->trans);
|
| EXPECT_THAT(rv, IsOk());
|
| - ASSERT_TRUE(trans.get());
|
| + ASSERT_TRUE(c->trans.get());
|
|
|
| - rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| if (rv == ERR_IO_PENDING)
|
| rv = callback.WaitForResult();
|
| ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
|
|
|
| - trans.reset();
|
| + c.reset();
|
|
|
| EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| EXPECT_EQ(1, cache.disk_cache()->open_count());
|
| @@ -5831,7 +6025,9 @@ TEST(HttpCache, SetTruncatedFlag) {
|
| MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL);
|
|
|
| // Destroy the transaction.
|
| - c->trans.reset();
|
| + if (c->trans) {
|
| + c->trans->Orphan(std::move(c->trans));
|
| + }
|
| MockHttpCache::SetTestMode(0);
|
|
|
|
|
| @@ -5841,8 +6037,10 @@ TEST(HttpCache, SetTruncatedFlag) {
|
| // notification from the transaction destructor (see http://crbug.com/31723).
|
| EXPECT_FALSE(c->callback.have_result());
|
|
|
| - // Verify that the entry is marked as incomplete.
|
| - VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0);
|
| + // Verify that the entry is not marked as incomplete since SharedWriters
|
| + // enables response writing to complete even if transaction is destroyed
|
| + // mid-way.
|
| + VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, false, 0);
|
| }
|
|
|
| // Tests that we don't mark an entry as truncated when we read everything.
|
| @@ -5869,7 +6067,9 @@ TEST(HttpCache, DontSetTruncatedFlag) {
|
| EXPECT_EQ(buf->size(), c->callback.GetResult(rv));
|
|
|
| // Destroy the transaction.
|
| - c->trans.reset();
|
| + if (c->trans) {
|
| + c->trans->Orphan(std::move(c->trans));
|
| + }
|
|
|
| // Verify that the entry is not marked as truncated.
|
| VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, false, 0);
|
| @@ -5883,21 +6083,19 @@ TEST(HttpCache, RangeGET_DontTruncate) {
|
| transaction.request_headers = "Range: bytes = 0-19\r\n" EXTRA_HEADER;
|
|
|
| std::unique_ptr<MockHttpRequest> request(new MockHttpRequest(transaction));
|
| - std::unique_ptr<HttpTransaction> trans;
|
| + std::unique_ptr<Context> c(new Context());
|
|
|
| - int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
|
| + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &c->trans);
|
| EXPECT_THAT(rv, IsOk());
|
|
|
| TestCompletionCallback cb;
|
| - rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
|
| + rv = c->trans->Start(request.get(), cb.callback(), NetLogWithSource());
|
| EXPECT_EQ(0, cb.GetResult(rv));
|
|
|
| scoped_refptr<IOBuffer> buf(new IOBuffer(10));
|
| - rv = trans->Read(buf.get(), 10, cb.callback());
|
| + rv = c->trans->Read(buf.get(), 10, cb.callback());
|
| EXPECT_EQ(10, cb.GetResult(rv));
|
|
|
| - // Should not trigger any DCHECK.
|
| - trans.reset();
|
| VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 0);
|
| }
|
|
|
| @@ -5910,21 +6108,20 @@ TEST(HttpCache, RangeGET_DontTruncate2) {
|
| transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER;
|
|
|
| std::unique_ptr<MockHttpRequest> request(new MockHttpRequest(transaction));
|
| - std::unique_ptr<HttpTransaction> trans;
|
| + std::unique_ptr<Context> c(new Context());
|
|
|
| - int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
|
| + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &c->trans);
|
| EXPECT_THAT(rv, IsOk());
|
|
|
| - TestCompletionCallback cb;
|
| - rv = trans->Start(request.get(), cb.callback(), NetLogWithSource());
|
| - EXPECT_EQ(0, cb.GetResult(rv));
|
| + rv = c->trans->Start(request.get(), c->callback.callback(),
|
| + NetLogWithSource());
|
| + EXPECT_EQ(0, c->callback.GetResult(rv));
|
|
|
| scoped_refptr<IOBuffer> buf(new IOBuffer(10));
|
| - rv = trans->Read(buf.get(), 10, cb.callback());
|
| - EXPECT_EQ(10, cb.GetResult(rv));
|
| + rv = c->trans->Read(buf.get(), 10, c->callback.callback());
|
| + EXPECT_EQ(10, c->callback.GetResult(rv));
|
|
|
| // Should not trigger any DCHECK.
|
| - trans.reset();
|
| VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 0);
|
| }
|
|
|
| @@ -6388,15 +6585,15 @@ TEST(HttpCache, CachedRedirect) {
|
|
|
| // Write to the cache.
|
| {
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| if (rv == ERR_IO_PENDING)
|
| rv = callback.WaitForResult();
|
| ASSERT_THAT(rv, IsOk());
|
|
|
| - const HttpResponseInfo* info = trans->GetResponseInfo();
|
| + const HttpResponseInfo* info = c->trans->GetResponseInfo();
|
| ASSERT_TRUE(info);
|
|
|
| EXPECT_EQ(info->headers->response_code(), 301);
|
| @@ -6406,7 +6603,7 @@ TEST(HttpCache, CachedRedirect) {
|
| EXPECT_EQ(location, "http://www.bar.com/");
|
|
|
| // Mark the transaction as completed so it is cached.
|
| - trans->DoneReading();
|
| + c->trans->DoneReading();
|
|
|
| // Destroy transaction when going out of scope. We have not actually
|
| // read the response body -- want to test that it is still getting cached.
|
| @@ -6422,15 +6619,15 @@ TEST(HttpCache, CachedRedirect) {
|
|
|
| // Read from the cache.
|
| {
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| if (rv == ERR_IO_PENDING)
|
| rv = callback.WaitForResult();
|
| ASSERT_THAT(rv, IsOk());
|
|
|
| - const HttpResponseInfo* info = trans->GetResponseInfo();
|
| + const HttpResponseInfo* info = c->trans->GetResponseInfo();
|
| ASSERT_TRUE(info);
|
|
|
| EXPECT_EQ(info->headers->response_code(), 301);
|
| @@ -6440,7 +6637,7 @@ TEST(HttpCache, CachedRedirect) {
|
| EXPECT_EQ(location, "http://www.bar.com/");
|
|
|
| // Mark the transaction as completed so it is cached.
|
| - trans->DoneReading();
|
| + c->trans->DoneReading();
|
|
|
| // Destroy transaction when going out of scope. We have not actually
|
| // read the response body -- want to test that it is still getting cached.
|
| @@ -6601,14 +6798,14 @@ TEST(HttpCache, SimpleGET_SSLError) {
|
| transaction.load_flags |= LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
|
|
|
| MockHttpRequest request(transaction);
|
| - TestCompletionCallback callback;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| if (rv == ERR_IO_PENDING)
|
| - rv = callback.WaitForResult();
|
| + rv = c->callback.WaitForResult();
|
| ASSERT_THAT(rv, IsError(ERR_CACHE_MISS));
|
| }
|
|
|
| @@ -6616,11 +6813,10 @@ TEST(HttpCache, SimpleGET_SSLError) {
|
| TEST(HttpCache, OutlivedTransactions) {
|
| MockHttpCache* cache = new MockHttpCache;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - EXPECT_THAT(cache->CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + EXPECT_THAT(cache->CreateTransaction(&c->trans), IsOk());
|
|
|
| delete cache;
|
| - trans.reset();
|
| }
|
|
|
| // Test that the disabled mode works.
|
| @@ -6899,19 +7095,19 @@ TEST(HttpCache, FilterCompletion) {
|
| TestCompletionCallback callback;
|
|
|
| {
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| MockHttpRequest request(kSimpleGET_Transaction);
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| EXPECT_THAT(callback.GetResult(rv), IsOk());
|
|
|
| scoped_refptr<IOBuffer> buf(new IOBuffer(256));
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 256, callback.callback());
|
| EXPECT_GT(callback.GetResult(rv), 0);
|
|
|
| // Now make sure that the entry is preserved.
|
| - trans->DoneReading();
|
| + c->trans->DoneReading();
|
| }
|
|
|
| // Make sure that the ActiveEntry is gone.
|
| @@ -6935,14 +7131,14 @@ TEST(HttpCache, DoneReading) {
|
| ScopedMockTransaction transaction(kSimpleGET_Transaction);
|
| transaction.data = "";
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| MockHttpRequest request(transaction);
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| EXPECT_THAT(callback.GetResult(rv), IsOk());
|
|
|
| - trans->DoneReading();
|
| + c->trans->DoneReading();
|
| // Leave the transaction around.
|
|
|
| // Make sure that the ActiveEntry is gone.
|
| @@ -6959,27 +7155,27 @@ TEST(HttpCache, DoneReading) {
|
| // Tests that we stop caching when told.
|
| TEST(HttpCache, StopCachingDeletesEntry) {
|
| MockHttpCache cache;
|
| - TestCompletionCallback callback;
|
| MockHttpRequest request(kSimpleGET_Transaction);
|
|
|
| {
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| - EXPECT_THAT(callback.GetResult(rv), IsOk());
|
| + int rv =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + EXPECT_THAT(c->callback.GetResult(rv), IsOk());
|
|
|
| scoped_refptr<IOBuffer> buf(new IOBuffer(256));
|
| - rv = trans->Read(buf.get(), 10, callback.callback());
|
| - EXPECT_EQ(10, callback.GetResult(rv));
|
| + rv = c->trans->Read(buf.get(), 10, c->callback.callback());
|
| + EXPECT_EQ(10, c->callback.GetResult(rv));
|
|
|
| - trans->StopCaching();
|
| + c->trans->StopCaching();
|
|
|
| // We should be able to keep reading.
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| - EXPECT_GT(callback.GetResult(rv), 0);
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| - EXPECT_EQ(0, callback.GetResult(rv));
|
| + rv = c->trans->Read(buf.get(), 256, c->callback.callback());
|
| + EXPECT_GT(c->callback.GetResult(rv), 0);
|
| + rv = c->trans->Read(buf.get(), 256, c->callback.callback());
|
| + EXPECT_EQ(0, c->callback.GetResult(rv));
|
| }
|
|
|
| // Make sure that the ActiveEntry is gone.
|
| @@ -7001,26 +7197,26 @@ TEST(HttpCache, StopCachingThenDoneReadingDeletesEntry) {
|
| MockHttpRequest request(kSimpleGET_Transaction);
|
|
|
| {
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| EXPECT_THAT(callback.GetResult(rv), IsOk());
|
|
|
| scoped_refptr<IOBuffer> buf(new IOBuffer(256));
|
| - rv = trans->Read(buf.get(), 10, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 10, callback.callback());
|
| EXPECT_EQ(10, callback.GetResult(rv));
|
|
|
| - trans->StopCaching();
|
| + c->trans->StopCaching();
|
|
|
| // We should be able to keep reading.
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 256, callback.callback());
|
| EXPECT_GT(callback.GetResult(rv), 0);
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 256, callback.callback());
|
| EXPECT_EQ(0, callback.GetResult(rv));
|
|
|
| // We should be able to call DoneReading.
|
| - trans->DoneReading();
|
| + c->trans->DoneReading();
|
| }
|
|
|
| // Make sure that the ActiveEntry is gone.
|
| @@ -7044,16 +7240,16 @@ TEST(HttpCache, StopCachingWithAuthDeletesEntry) {
|
| MockHttpRequest request(mock_transaction);
|
|
|
| {
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| EXPECT_THAT(callback.GetResult(rv), IsOk());
|
|
|
| - trans->StopCaching();
|
| + c->trans->StopCaching();
|
|
|
| scoped_refptr<IOBuffer> buf(new IOBuffer(256));
|
| - rv = trans->Read(buf.get(), 10, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 10, callback.callback());
|
| EXPECT_EQ(callback.GetResult(rv), 10);
|
| }
|
| RemoveMockTransaction(&mock_transaction);
|
| @@ -7076,8 +7272,8 @@ TEST(HttpCache, StopCachingSavesEntry) {
|
| MockHttpRequest request(kSimpleGET_Transaction);
|
|
|
| {
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| // Force a response that can be resumed.
|
| ScopedMockTransaction mock_transaction(kSimpleGET_Transaction);
|
| @@ -7086,19 +7282,19 @@ TEST(HttpCache, StopCachingSavesEntry) {
|
| "Content-Length: 42\n"
|
| "Etag: \"foo\"\n";
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| EXPECT_THAT(callback.GetResult(rv), IsOk());
|
|
|
| scoped_refptr<IOBuffer> buf(new IOBuffer(256));
|
| - rv = trans->Read(buf.get(), 10, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 10, callback.callback());
|
| EXPECT_EQ(callback.GetResult(rv), 10);
|
|
|
| - trans->StopCaching();
|
| + c->trans->StopCaching();
|
|
|
| // We should be able to keep reading.
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 256, callback.callback());
|
| EXPECT_GT(callback.GetResult(rv), 0);
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 256, callback.callback());
|
| EXPECT_EQ(callback.GetResult(rv), 0);
|
| }
|
|
|
| @@ -7124,25 +7320,25 @@ TEST(HttpCache, StopCachingTruncatedEntry) {
|
|
|
| {
|
| // Now make a regular request.
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.CreateTransaction(&trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context());
|
| + ASSERT_THAT(cache.CreateTransaction(&c->trans), IsOk());
|
|
|
| - int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + int rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| EXPECT_THAT(callback.GetResult(rv), IsOk());
|
|
|
| scoped_refptr<IOBuffer> buf(new IOBuffer(256));
|
| - rv = trans->Read(buf.get(), 10, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 10, callback.callback());
|
| EXPECT_EQ(callback.GetResult(rv), 10);
|
|
|
| // This is actually going to do nothing.
|
| - trans->StopCaching();
|
| + c->trans->StopCaching();
|
|
|
| // We should be able to keep reading.
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 256, callback.callback());
|
| EXPECT_GT(callback.GetResult(rv), 0);
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 256, callback.callback());
|
| EXPECT_GT(callback.GetResult(rv), 0);
|
| - rv = trans->Read(buf.get(), 256, callback.callback());
|
| + rv = c->trans->Read(buf.get(), 256, callback.callback());
|
| EXPECT_EQ(callback.GetResult(rv), 0);
|
| }
|
|
|
| @@ -7369,41 +7565,40 @@ TEST_P(HttpCacheHugeResourceTest,
|
|
|
| MockHttpRequest request(transaction);
|
| net::TestCompletionCallback callback;
|
| - std::unique_ptr<net::HttpTransaction> http_transaction;
|
| - int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY,
|
| - &http_transaction);
|
| + std::unique_ptr<Context> c(new Context());
|
| + int rv =
|
| + cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY, &c->trans);
|
| ASSERT_EQ(net::OK, rv);
|
| - ASSERT_TRUE(http_transaction.get());
|
| + ASSERT_TRUE(c->trans.get());
|
|
|
| bool network_transaction_started = false;
|
| if (stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
|
| - http_transaction->SetBeforeNetworkStartCallback(
|
| + c->trans->SetBeforeNetworkStartCallback(
|
| base::Bind(&SetFlagOnBeforeNetworkStart, &network_transaction_started));
|
| }
|
|
|
| - rv = http_transaction->Start(&request, callback.callback(),
|
| - NetLogWithSource());
|
| + rv = c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
| rv = callback.GetResult(rv);
|
| ASSERT_EQ(net::OK, rv);
|
|
|
| if (stop_caching_phase == TransactionPhase::BEFORE_FIRST_READ)
|
| - http_transaction->StopCaching();
|
| + c->trans->StopCaching();
|
|
|
| int64_t total_bytes_received = 0;
|
|
|
| EXPECT_EQ(kTotalSize,
|
| - http_transaction->GetResponseInfo()->headers->GetContentLength());
|
| + c->trans->GetResponseInfo()->headers->GetContentLength());
|
| do {
|
| // This test simulates reading gigabytes of data. Buffer size is set to 10MB
|
| // to reduce the number of reads and speed up the test.
|
| const int kBufferSize = 1024 * 1024 * 10;
|
| scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufferSize));
|
| - rv = http_transaction->Read(buf.get(), kBufferSize, callback.callback());
|
| + rv = c->trans->Read(buf.get(), kBufferSize, callback.callback());
|
| rv = callback.GetResult(rv);
|
|
|
| if (stop_caching_phase == TransactionPhase::AFTER_FIRST_READ &&
|
| total_bytes_received == 0) {
|
| - http_transaction->StopCaching();
|
| + c->trans->StopCaching();
|
| }
|
|
|
| if (rv > 0)
|
| @@ -7411,7 +7606,7 @@ TEST_P(HttpCacheHugeResourceTest,
|
|
|
| if (network_transaction_started &&
|
| stop_caching_phase == TransactionPhase::AFTER_NETWORK_READ) {
|
| - http_transaction->StopCaching();
|
| + c->trans->StopCaching();
|
| network_transaction_started = false;
|
| }
|
| } while (rv > 0);
|
| @@ -7466,11 +7661,11 @@ TEST(HttpCache, TruncatedByContentLength2) {
|
| TEST(HttpCache, SetPriority) {
|
| MockHttpCache cache;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context);
|
| + ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &c->trans), IsOk());
|
|
|
| // Shouldn't crash, but doesn't do anything either.
|
| - trans->SetPriority(LOW);
|
| + c->trans->SetPriority(LOW);
|
|
|
| EXPECT_FALSE(cache.network_layer()->last_transaction());
|
| EXPECT_EQ(DEFAULT_PRIORITY,
|
| @@ -7480,7 +7675,7 @@ TEST(HttpCache, SetPriority) {
|
| info.url = GURL(kSimpleGET_Transaction.url);
|
| TestCompletionCallback callback;
|
| EXPECT_EQ(ERR_IO_PENDING,
|
| - trans->Start(&info, callback.callback(), NetLogWithSource()));
|
| + c->trans->Start(&info, callback.callback(), NetLogWithSource()));
|
|
|
| EXPECT_TRUE(cache.network_layer()->last_transaction());
|
| if (cache.network_layer()->last_transaction()) {
|
| @@ -7488,7 +7683,7 @@ TEST(HttpCache, SetPriority) {
|
| EXPECT_EQ(LOW, cache.network_layer()->last_transaction()->priority());
|
| }
|
|
|
| - trans->SetPriority(HIGHEST);
|
| + c->trans->SetPriority(HIGHEST);
|
|
|
| if (cache.network_layer()->last_transaction()) {
|
| EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority());
|
| @@ -7504,8 +7699,8 @@ TEST(HttpCache, SetWebSocketHandshakeStreamCreateHelper) {
|
| MockHttpCache cache;
|
|
|
| FakeWebSocketHandshakeStreamCreateHelper create_helper;
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context);
|
| + ASSERT_THAT(cache.http_cache()->CreateTransaction(IDLE, &c->trans), IsOk());
|
|
|
| EXPECT_FALSE(cache.network_layer()->last_transaction());
|
|
|
| @@ -7513,12 +7708,12 @@ TEST(HttpCache, SetWebSocketHandshakeStreamCreateHelper) {
|
| info.url = GURL(kSimpleGET_Transaction.url);
|
| TestCompletionCallback callback;
|
| EXPECT_EQ(ERR_IO_PENDING,
|
| - trans->Start(&info, callback.callback(), NetLogWithSource()));
|
| + c->trans->Start(&info, callback.callback(), NetLogWithSource()));
|
|
|
| ASSERT_TRUE(cache.network_layer()->last_transaction());
|
| EXPECT_FALSE(cache.network_layer()->last_transaction()->
|
| websocket_handshake_stream_create_helper());
|
| - trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper);
|
| + c->trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper);
|
| EXPECT_EQ(&create_helper,
|
| cache.network_layer()->last_transaction()->
|
| websocket_handshake_stream_create_helper());
|
| @@ -7544,23 +7739,23 @@ TEST(HttpCache, SetPriorityNewTransaction) {
|
| transaction.request_headers = EXTRA_HEADER;
|
| transaction.data = kFullRangeData;
|
|
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - ASSERT_THAT(cache.http_cache()->CreateTransaction(MEDIUM, &trans), IsOk());
|
| + std::unique_ptr<Context> c(new Context);
|
| + ASSERT_THAT(cache.http_cache()->CreateTransaction(MEDIUM, &c->trans), IsOk());
|
| EXPECT_EQ(DEFAULT_PRIORITY,
|
| cache.network_layer()->last_create_transaction_priority());
|
|
|
| MockHttpRequest info(transaction);
|
| TestCompletionCallback callback;
|
| EXPECT_EQ(ERR_IO_PENDING,
|
| - trans->Start(&info, callback.callback(), NetLogWithSource()));
|
| + c->trans->Start(&info, callback.callback(), NetLogWithSource()));
|
| EXPECT_THAT(callback.WaitForResult(), IsOk());
|
|
|
| EXPECT_EQ(MEDIUM, cache.network_layer()->last_create_transaction_priority());
|
|
|
| - trans->SetPriority(HIGHEST);
|
| + c->trans->SetPriority(HIGHEST);
|
| // Should trigger a new network transaction and pick up the new
|
| // priority.
|
| - ReadAndVerifyTransaction(trans.get(), transaction);
|
| + ReadAndVerifyTransaction(c->trans.get(), transaction);
|
|
|
| EXPECT_EQ(HIGHEST, cache.network_layer()->last_create_transaction_priority());
|
|
|
| @@ -7939,13 +8134,13 @@ TEST(HttpCache, RangeGET_MultipleRequests) {
|
| AddMockTransaction(&transaction);
|
|
|
| TestCompletionCallback callback;
|
| - std::unique_ptr<HttpTransaction> trans;
|
| - int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans);
|
| + std::unique_ptr<Context> c(new Context);
|
| + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &c->trans);
|
| EXPECT_THAT(rv, IsOk());
|
| - ASSERT_TRUE(trans.get());
|
| + ASSERT_TRUE(c->trans.get());
|
|
|
| // Start our transaction.
|
| - trans->Start(&request, callback.callback(), NetLogWithSource());
|
| + c->trans->Start(&request, callback.callback(), NetLogWithSource());
|
|
|
| // A second transaction on a different part of the file (the default
|
| // kRangeGET_TransactionOK requests 40-49) should not be blocked by
|
| @@ -8196,4 +8391,762 @@ TEST(HttpCache, CacheEntryStatusCantConditionalize) {
|
| response_info.cache_entry_status);
|
| }
|
|
|
| +TEST(HttpCache, SimpleGET_SharedWritingCacheRead) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 5;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // The first request should be a writer at this point, and the subsequent
|
| + // requests should be pending.
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + // All requests depend on the writer, and the writer is between Start and
|
| + // Read, i.e. idle.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + if (c->result == ERR_IO_PENDING)
|
| + c->result = c->callback.WaitForResult();
|
| + }
|
| +
|
| + ReadAndVerifySharedWritersCacheRead(context_list, kSimpleGET_Transaction);
|
| +
|
| + // We should not have had to re-open the disk entry
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| +TEST(HttpCache, SimpleGET_SharedWritingJoinedRead) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 5;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // The first request should be a writer at this point, and the subsequent
|
| + // requests should be pending.
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + // All requests depend on the writer, and the writer is between Start and
|
| + // Read, i.e. idle.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + std::vector<HttpTransaction*> transactions;
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + if (c->result == ERR_IO_PENDING)
|
| + c->result = c->callback.WaitForResult();
|
| + transactions.push_back(c->trans.get());
|
| + }
|
| +
|
| + ReadAndVerifySharedWritersJoinedRead(kSimpleGET_Transaction, context_list);
|
| +
|
| + // We should not have had to re-open the disk entry
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| +TEST(HttpCache, SimpleGET_SharedWritingJoinedReadDoneReading) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 5;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // The first request should be a writer at this point, and the subsequent
|
| + // requests should be pending.
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + // All requests depend on the writer, and the writer is between Start and
|
| + // Read, i.e. idle.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + std::vector<HttpTransaction*> transactions;
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + if (c->result == ERR_IO_PENDING)
|
| + c->result = c->callback.WaitForResult();
|
| + transactions.push_back(c->trans.get());
|
| + }
|
| +
|
| + ReadAndVerifySharedWritersJoinedReadDoneReading(kSimpleGET_Transaction,
|
| + context_list);
|
| +
|
| + // We should not have had to re-open the disk entry
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + delete c;
|
| + }
|
| +}
|
| +// Tests the following:
|
| +// - A 200 will doom the entry and the transaction will continue to read from
|
| +// the network.
|
| +// - Doomed entry's SharedWriters will continue to read and write to the cache.
|
| +// - Doomed entry's SharedWriters' waiting_for_validation_ will create another
|
| +// entry.
|
| +// - The new entry will also have another SharedWriters for subsequent
|
| +// transactions.
|
| +TEST(HttpCache, SharedWritingValidation200) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| + request.load_flags |= LOAD_VALIDATE_CACHE;
|
| + MockHttpRequest reader_request(kSimpleGET_Transaction);
|
| + reader_request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
|
| + MockHttpRequest request_no_validate(kSimpleGET_Transaction);
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 6;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + MockHttpRequest* this_request = &request;
|
| + if (i == 1 || i == 2)
|
| + this_request = &reader_request;
|
| +
|
| + if (i == 5)
|
| + this_request = &request_no_validate;
|
| +
|
| + c->result = c->trans->Start(this_request, c->callback.callback(),
|
| + NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // The first [0] request should be a writer at this point, and should have
|
| + // created
|
| + // SharedWriters, [1] and [2] will be in pending_queue and [3] and [4] should
|
| + // have validated and [5] will have skipped validation and be ready to read.
|
| +
|
| + EXPECT_EQ(3, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(2, cache.disk_cache()->create_count());
|
| +
|
| + Context* c = context_list[0];
|
| + ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
|
| + c->result = c->callback.WaitForResult();
|
| +
|
| + // First request is done with the headers, now [3] will start validation.
|
| + Context* c3 = context_list[3];
|
| + ASSERT_THAT(c3->result, IsError(ERR_IO_PENDING));
|
| +
|
| + // Let [3] get a 200 , thus leading to dooming the entry, [4] and [5] will
|
| + // move to entry's pending_queue.
|
| + c3->result = c3->callback.WaitForResult();
|
| +
|
| + // [3] will complete reading the response using its own network transaction
|
| + // and not writing to the cache.
|
| + ReadAndVerifyTransaction(c3->trans.get(), kSimpleGET_Transaction);
|
| +
|
| + // [0] will complete reading the response using SharedWriter's network
|
| + // transaction and then the entry should be finalized.
|
| + ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
|
| +
|
| + // [4] should be added to a new entry and should contiue reading and writing
|
| + // to the cache (also create SharedWriters)
|
| + for (int i = 4; i <= 5; i++) {
|
| + Context* c = context_list[i];
|
| + ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
|
| + c->result = c->callback.WaitForResult();
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| + // [5] will join SharedWriters at this point when [4] completes validation.
|
| + ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
|
| + }
|
| + // [1] and [2] will become readers and read from the cache.
|
| + for (int i = 1; i <= 2; i++) {
|
| + Context* c = context_list[i];
|
| + ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
|
| + c->result = c->callback.WaitForResult();
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| + ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction);
|
| + }
|
| +
|
| + // We should not have had to re-open the disk entry
|
| + EXPECT_EQ(3, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(2, cache.disk_cache()->create_count());
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| +// Tests a validating transaction deletion while it is waiting for its callback
|
| +// to be invoked.
|
| +TEST(HttpCache, SharedWritingDeleteValidationTrans) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| + request.load_flags |= LOAD_VALIDATE_CACHE;
|
| + MockHttpRequest reader_request(kSimpleGET_Transaction);
|
| + reader_request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 5;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + MockHttpRequest* this_request = &request;
|
| + if (i == 1 || i == 2)
|
| + this_request = &reader_request;
|
| +
|
| + if (i == 3 || i == 4)
|
| + continue;
|
| +
|
| + c->result = c->trans->Start(this_request, c->callback.callback(),
|
| + NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + if (i == 3 || i == 4)
|
| + continue;
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + // Start [3], [4].
|
| + for (size_t i = 3; i <= 4; i++) {
|
| + Context* c = context_list[i];
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
|
| + }
|
| +
|
| + // Delete [3] as it is the current validating trans.
|
| + Context* c3 = context_list[3];
|
| + for (auto it = context_list.begin(); it != context_list.end(); it++) {
|
| + if (*it == c3) {
|
| + context_list.erase(it);
|
| + delete c3;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // Complete start state machine for [4].
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // [0] will complete reading the response using SharedWriter's network
|
| + // transaction and then the entry should be finalized.
|
| + Context* c0 = context_list[0];
|
| + ReadAndVerifyTransaction(c0->trans.get(), kSimpleGET_Transaction);
|
| +
|
| + // [4] (now [3]) should doom the entry and continue reading with its network
|
| + // transaction.
|
| + Context* c4 = context_list[3];
|
| + ReadAndVerifyTransaction(c4->trans.get(), kSimpleGET_Transaction);
|
| +
|
| + // 1st entry will get destroyed and [1] and [2] will being readers will get a
|
| + // ERR_CACHE_MISS.
|
| + for (int i = 1; i <= 2; i++) {
|
| + Context* c = context_list[i];
|
| + ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
|
| + c->result = c->callback.WaitForResult();
|
| + ASSERT_THAT(c->result, IsError(ERR_CACHE_MISS));
|
| + }
|
| +
|
| + // We should not have had to re-open the disk entry
|
| + EXPECT_EQ(2, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + for (auto i = context_list.begin(); i != context_list.end(); ++i) {
|
| + Context* c = *i;
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| +// Tests a transaction deletion while it is waiting for validation.
|
| +TEST(HttpCache, SharedWritingDeleteWaitingForValidation) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| + request.load_flags |= LOAD_VALIDATE_CACHE;
|
| + MockHttpRequest reader_request(kSimpleGET_Transaction);
|
| + reader_request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 5;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + MockHttpRequest* this_request = &request;
|
| + if (i == 1 || i == 2)
|
| + this_request = &reader_request;
|
| +
|
| + if (i == 3 || i == 4)
|
| + continue;
|
| +
|
| + c->result = c->trans->Start(this_request, c->callback.callback(),
|
| + NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + if (i == 3 || i == 4)
|
| + continue;
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + // Start [3], [4].
|
| + for (size_t i = 3; i <= 4; i++) {
|
| + Context* c = context_list[i];
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
|
| + }
|
| +
|
| + // Delete [4] as it is the waiting for validation trans.
|
| + Context* c4 = context_list[4];
|
| + for (auto it = context_list.begin(); it != context_list.end(); it++) {
|
| + if (*it == c4) {
|
| + context_list.erase(it);
|
| + delete c4;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // Complete start state machine for [3].
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // [0] will complete reading the response using SharedWriter's network
|
| + // transaction and then the entry should be finalized.
|
| + Context* c0 = context_list[0];
|
| + ReadAndVerifyTransaction(c0->trans.get(), kSimpleGET_Transaction);
|
| +
|
| + // [3] should doom the entry and continue reading with its network
|
| + // transaction.
|
| + Context* c3 = context_list[3];
|
| + ReadAndVerifyTransaction(c3->trans.get(), kSimpleGET_Transaction);
|
| +
|
| + // 1st entry will get destroyed and [1] and [2] will being readers will get a
|
| + // ERR_CACHE_MISS.
|
| + for (int i = 1; i <= 2; i++) {
|
| + Context* c = context_list[i];
|
| + ASSERT_THAT(c->result, IsError(ERR_IO_PENDING));
|
| + c->result = c->callback.WaitForResult();
|
| + ASSERT_THAT(c->result, IsError(ERR_CACHE_MISS));
|
| + }
|
| +
|
| + // We should not have had to re-open the disk entry
|
| + EXPECT_EQ(2, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + for (auto i = context_list.begin(); i != context_list.end(); ++i) {
|
| + Context* c = *i;
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| +// Tests the impact of cache write failure on Shared Writing.
|
| +TEST(HttpCache, SharedWritingCacheWriteFailure) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| + request.load_flags |= LOAD_VALIDATE_CACHE;
|
| + MockHttpRequest reader_request(kSimpleGET_Transaction);
|
| + reader_request.load_flags = LOAD_ONLY_FROM_CACHE | LOAD_SKIP_CACHE_VALIDATION;
|
| + MockHttpRequest request_no_validate(kSimpleGET_Transaction);
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 7;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + MockHttpRequest* this_request = &request;
|
| + if (i == 1 || i == 2)
|
| + this_request = &reader_request;
|
| +
|
| + if (i == 3 || i == 6)
|
| + this_request = &request_no_validate;
|
| +
|
| + if (i == 4 || i == 5)
|
| + continue;
|
| +
|
| + c->result = c->trans->Start(this_request, c->callback.callback(),
|
| + NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + if (i == 4 || i == 5)
|
| + continue;
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // At this point, 0,5 and 3 are idle writers, 1 and 2 are pending readers and
|
| + // 4
|
| + // will now become the validating_trans_.
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + ReadAndVerifySharedWritersJoinedReadCacheWriteFailure(kSimpleGET_Transaction,
|
| + context_list, cache);
|
| +
|
| + // We should not have had to re-open the disk entry
|
| + EXPECT_EQ(3, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(3, cache.disk_cache()->create_count());
|
| +
|
| + for (auto i = context_list.begin(); i != context_list.end(); ++i) {
|
| + Context* c = *i;
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| +TEST(HttpCache, SimpleGET_SharedWritingJoinedReadDoomCurrentWriter) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 5;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // The first request should be a writer at this point, and the subsequent
|
| + // requests should be pending.
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + // All requests depend on the writer, and the writer is between Start and
|
| + // Read, i.e. idle.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + std::vector<HttpTransaction*> transactions;
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + if (c->result == ERR_IO_PENDING)
|
| + c->result = c->callback.WaitForResult();
|
| + transactions.push_back(c->trans.get());
|
| + }
|
| +
|
| + ReadAndVerifySharedWritersJoinedReadDoomCurrentWriter(kSimpleGET_Transaction,
|
| + context_list);
|
| +
|
| + // We should not have had to re-open the disk entry
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + for (auto i = context_list.begin(); i != context_list.end(); ++i) {
|
| + Context* c = *i;
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| +TEST(HttpCache, SimpleGET_SharedWritingJoinedReadDeleteWaitingWriter) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 5;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // The first request should be a writer at this point, and the subsequent
|
| + // requests should be pending.
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + // All requests depend on the writer, and the writer is between Start and
|
| + // Read, i.e. idle.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + std::vector<HttpTransaction*> transactions;
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + if (c->result == ERR_IO_PENDING)
|
| + c->result = c->callback.WaitForResult();
|
| + transactions.push_back(c->trans.get());
|
| + }
|
| +
|
| + ReadAndVerifySharedWritersDeleteWaitingWriter(kSimpleGET_Transaction,
|
| + context_list);
|
| +
|
| + // We should not have had to re-open the disk entry
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + for (auto i = context_list.begin(); i != context_list.end(); ++i) {
|
| + Context* c = *i;
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| +TEST(HttpCache, SimpleGET_SharedWritingJoinedReadDeleteIdleWriter) {
|
| + MockHttpCache cache;
|
| +
|
| + MockHttpRequest request(kSimpleGET_Transaction);
|
| +
|
| + std::vector<Context*> context_list;
|
| + const int kNumTransactions = 5;
|
| +
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + context_list.push_back(new Context());
|
| + Context* c = context_list[i];
|
| +
|
| + c->result = cache.CreateTransaction(&c->trans);
|
| + ASSERT_THAT(c->result, IsOk());
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| +
|
| + c->result =
|
| + c->trans->Start(&request, c->callback.callback(), NetLogWithSource());
|
| + }
|
| +
|
| + // All requests are waiting for the active entry.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + // Allow all requests to move from the Create queue to the active entry.
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + // The first request should be a writer at this point, and the subsequent
|
| + // requests should be pending.
|
| +
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + // All requests depend on the writer, and the writer is between Start and
|
| + // Read, i.e. idle.
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
|
| + }
|
| +
|
| + std::vector<HttpTransaction*> transactions;
|
| + for (int i = 0; i < kNumTransactions; ++i) {
|
| + Context* c = context_list[i];
|
| + if (c->result == ERR_IO_PENDING)
|
| + c->result = c->callback.WaitForResult();
|
| + transactions.push_back(c->trans.get());
|
| + }
|
| +
|
| + ReadAndVerifySharedWritersDeleteIdleWriter(kSimpleGET_Transaction,
|
| + context_list);
|
| +
|
| + // We should not have had to re-open the disk entry
|
| + EXPECT_EQ(1, cache.network_layer()->transaction_count());
|
| + EXPECT_EQ(0, cache.disk_cache()->open_count());
|
| + EXPECT_EQ(1, cache.disk_cache()->create_count());
|
| +
|
| + for (auto i = context_list.begin(); i != context_list.end(); ++i) {
|
| + Context* c = *i;
|
| + delete c;
|
| + }
|
| +}
|
| +
|
| } // namespace net
|
|
|