Chromium Code Reviews| Index: net/http/http_cache_writers_unittest.cc |
| diff --git a/net/http/http_cache_writers_unittest.cc b/net/http/http_cache_writers_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1d4f4e7407b62758b11a010cf5a070a50aa29bc7 |
| --- /dev/null |
| +++ b/net/http/http_cache_writers_unittest.cc |
| @@ -0,0 +1,673 @@ |
| +// Copyright (c) 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "net/http/http_cache_writers.h" |
| + |
| +#include <memory> |
| +#include <string> |
| +#include <vector> |
| + |
| +#include "base/run_loop.h" |
| +#include "net/http/http_cache.h" |
| +#include "net/http/http_cache_transaction.h" |
| +#include "net/http/http_transaction.h" |
| +#include "net/http/http_transaction_test_util.h" |
| +#include "net/http/mock_http_cache.h" |
| +#include "net/test/gtest_util.h" |
| + |
| +using net::test::IsError; |
| +using net::test::IsOk; |
| + |
| +namespace net { |
| + |
| +class HttpCache::WritersTest { |
| + public: |
| + WritersTest() {} |
| + |
| + // Since ActiveEntry and Transaction are private classes of HttpCache, |
| + // accessing those only in this class instead of in tests. |
| + |
| + void CreateWriters(const std::string& url) { |
| + HttpCache* cache = cache_.http_cache(); |
| + ActiveEntry* entry = cache->FindActiveEntry(url); |
| + writers_ = base::MakeUnique<Writers>(cache, entry->disk_entry); |
| + } |
| + |
| + std::unique_ptr<HttpTransaction> CreateNetworkTransaction() { |
| + std::unique_ptr<HttpTransaction> transaction; |
| + MockNetworkLayer* network_layer = cache_.network_layer(); |
| + network_layer->CreateTransaction(DEFAULT_PRIORITY, &transaction); |
| + return transaction; |
| + } |
| + |
| + void CreateWritersAddTransaction(MockTransaction transaction_info, |
| + bool is_exclusive = false) { |
| + MockHttpRequest request(transaction_info); |
| + std::unique_ptr<HttpTransaction> transaction; |
| + int rv = cache_.CreateTransaction(&transaction); |
| + DCHECK_EQ(rv, OK); |
| + DCHECK(transaction.get()); |
| + |
| + // Create an ActiveEntry. |
| + TestCompletionCallback callback; |
| + rv = transaction->Start(&request, callback.callback(), NetLogWithSource()); |
| + base::RunLoop().RunUntilIdle(); |
| + |
| + CreateWriters(kSimpleGET_Transaction.url); |
| + |
| + // Create and Start a mock network transaction. |
| + std::unique_ptr<HttpTransaction> network_transaction; |
| + network_transaction = CreateNetworkTransaction(); |
| + network_transaction->Start(&request, callback.callback(), |
| + NetLogWithSource()); |
| + base::RunLoop().RunUntilIdle(); |
| + |
| + DCHECK(writers_->IsEmpty()); |
| + writers_->AddTransaction((Transaction*)(transaction.get()), |
| + std::move(network_transaction), is_exclusive); |
| + transactions_.push_back(std::move(transaction)); |
| + } |
| + |
| + void AddTransactionToExistingWriters() { |
| + std::unique_ptr<HttpTransaction> transaction; |
| + int rv = cache_.CreateTransaction(&transaction); |
| + DCHECK_EQ(rv, OK); |
| + DCHECK(transaction.get()); |
| + |
| + DCHECK(writers_); |
| + writers_->AddTransaction((Transaction*)(transaction.get()), nullptr, false); |
| + transactions_.push_back(std::move(transaction)); |
| + } |
| + |
| + int Read(std::string* result) { |
| + Transaction* transaction = (Transaction*)(transactions_.begin()->get()); |
|
Randy Smith (Not in Mondays)
2017/06/22 21:45:05
DCHECK that there's at least one transaction in tr
shivanisha
2017/06/26 20:45:35
done
|
| + TestCompletionCallback callback; |
| + |
| + std::string content; |
| + int rv; |
| + do { |
| + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); |
| + rv = writers_->Read(buf.get(), 256, callback.callback(), transaction); |
| + if (rv == ERR_IO_PENDING) { |
| + rv = callback.WaitForResult(); |
| + base::RunLoop().RunUntilIdle(); |
| + } |
| + |
| + if (rv > 0) |
| + content.append(buf->data(), rv); |
| + else if (rv < 0) |
| + return rv; |
| + } while (rv > 0); |
| + |
| + result->swap(content); |
| + return OK; |
| + } |
| + |
| + int ReadAll(std::vector<std::string>& results) { |
| + int rv; |
| + do { |
| + std::vector<scoped_refptr<IOBuffer>> bufs; |
| + std::vector<TestCompletionCallback> callbacks(results.size()); |
| + |
| + // Multiple transactions should be able to read. |
| + int i = 0; |
| + for (auto& transaction : transactions_) { |
| + bufs.push_back(new IOBuffer(256)); |
| + rv = writers_->Read(bufs[i].get(), 256, callbacks[i].callback(), |
| + (Transaction*)transaction.get()); |
| + EXPECT_EQ(rv, ERR_IO_PENDING); // Since the default is asynchronous. |
| + i++; |
| + } |
| + |
| + if (rv == ERR_IO_PENDING) { |
| + int prev_rv = callbacks[0].WaitForResult(); |
| + for (size_t i = 1; i < callbacks.size(); i++) { |
| + rv = callbacks[i].WaitForResult(); |
| + EXPECT_EQ(rv, prev_rv); |
| + prev_rv = rv; |
| + } |
| + } |
| + |
| + if (rv > 0) { |
| + int i = 0; |
| + for (auto& result : results) { |
|
Randy Smith (Not in Mondays)
2017/06/22 21:45:05
suggestion-but-I'd-prefer-it: Using *both* the aut
shivanisha
2017/06/26 20:45:35
done
|
| + result.append(bufs[i]->data(), rv); |
| + i++; |
| + } |
| + } else if (rv <= 0) { |
| + return rv; |
| + } |
| + } while (rv > 0); |
| + |
| + return OK; |
| + } |
| + |
| + int ReadAllDeleteActiveTransaction(std::vector<std::string>& results) { |
| + int rv; |
| + bool first_iter = true; |
| + do { |
| + std::vector<scoped_refptr<IOBuffer>> bufs; |
| + std::vector<TestCompletionCallback> callbacks(results.size()); |
| + |
| + // Multiple transactions should be able to read. |
| + int i = 0; |
| + for (auto& transaction : transactions_) { |
| + bufs.push_back(new IOBuffer(256)); |
| + if (!first_iter && i == 0) { |
| + i++; |
| + continue; |
| + } |
| + rv = writers_->Read(bufs[i].get(), 256, callbacks[i].callback(), |
| + (Transaction*)transaction.get()); |
| + EXPECT_EQ(rv, ERR_IO_PENDING); // Since the default is asynchronous. |
| + i++; |
| + } |
| + |
| + if (rv == ERR_IO_PENDING) { |
| + if (first_iter) { |
| + // Delete active transaction. |
| + RemoveFirstTransaction(); |
| + } |
| + int prev_rv = callbacks[1].WaitForResult(); |
| + for (size_t i = 2; i < callbacks.size(); i++) { |
| + rv = callbacks[i].WaitForResult(); |
| + EXPECT_EQ(rv, prev_rv); |
| + prev_rv = rv; |
| + } |
| + } |
| + |
| + if (rv > 0) { |
| + int i = 0; |
| + for (auto& result : results) { |
| + result.append(bufs[i]->data(), rv); |
| + i++; |
| + } |
| + } else if (rv <= 0) { |
|
Randy Smith (Not in Mondays)
2017/06/22 21:45:05
suggestion: If you eliminate this conditional and
shivanisha
2017/06/26 20:45:34
done
|
| + return rv; |
| + } |
| + first_iter = false; |
| + } while (rv > 0); |
| + |
| + return OK; |
| + } |
| + |
| + int ReadAllDeleteWaitingTransaction(std::vector<std::string>& results, |
| + size_t waiting_index) { |
| + int rv; |
| + bool first_iter = true; |
| + do { |
| + std::vector<scoped_refptr<IOBuffer>> bufs; |
| + std::vector<TestCompletionCallback> callbacks(results.size()); |
| + |
| + // Multiple transactions should be able to read. |
| + size_t i = 0; |
| + for (auto& transaction : transactions_) { |
| + bufs.push_back(new IOBuffer(256)); |
| + if (!first_iter && i == waiting_index) { |
| + i++; |
| + continue; |
| + } |
| + rv = writers_->Read(bufs[i].get(), 256, callbacks[i].callback(), |
| + (Transaction*)transaction.get()); |
| + EXPECT_EQ(rv, ERR_IO_PENDING); // Since the default is asynchronous. |
| + i++; |
| + } |
| + |
| + if (rv == ERR_IO_PENDING) { |
| + if (first_iter) { |
| + // Delete waiting transaction. |
| + writers_->RemoveTransaction( |
| + (Transaction*)transactions_.at(waiting_index).get()); |
| + } |
| + for (size_t j = 0; j < callbacks.size(); j++) { |
| + if (j == waiting_index) |
| + continue; |
| + rv = callbacks[j].WaitForResult(); |
| + } |
| + } |
| + |
| + if (rv > 0) { |
| + size_t i = 0; |
| + for (auto& result : results) { |
|
Randy Smith (Not in Mondays)
2017/06/22 21:45:05
Same request as above--if the loop is going to be
shivanisha
2017/06/26 20:45:34
done
|
| + if (i == waiting_index) { |
| + i++; |
| + continue; |
| + } |
| + result.append(bufs[i]->data(), rv); |
| + i++; |
| + } |
| + } else if (rv <= 0) { |
| + return rv; |
|
Randy Smith (Not in Mondays)
2017/06/22 21:45:05
Same suggestion as above; delete this clause and r
shivanisha
2017/06/26 20:45:34
done
|
| + } |
| + first_iter = false; |
| + } while (rv > 0); |
| + |
| + return OK; |
| + } |
| + |
| + int ReadAllDeleteIdleTransaction(std::vector<std::string>& results, |
| + size_t idle_index) { |
| + int rv; |
| + bool first_iter = true; |
| + do { |
| + std::vector<scoped_refptr<IOBuffer>> bufs; |
| + std::vector<TestCompletionCallback> callbacks(results.size()); |
| + |
| + // Multiple transactions should be able to read. |
| + size_t i = 0; |
| + for (auto& transaction : transactions_) { |
| + bufs.push_back(new IOBuffer(256)); |
| + if (i == idle_index) { |
| + i++; |
| + continue; |
| + } |
| + rv = writers_->Read(bufs[i].get(), 256, callbacks[i].callback(), |
| + (Transaction*)transaction.get()); |
| + EXPECT_EQ(rv, ERR_IO_PENDING); // Since the default is asynchronous. |
| + i++; |
| + } |
| + |
| + if (rv == ERR_IO_PENDING) { |
| + if (first_iter) { |
| + // Delete idle transaction. |
| + writers_->RemoveTransaction( |
| + (Transaction*)transactions_.at(idle_index).get()); |
| + } |
| + for (size_t j = 0; j < callbacks.size(); j++) { |
| + if (j == idle_index) |
| + continue; |
| + rv = callbacks[j].WaitForResult(); |
| + } |
| + } |
| + |
| + if (rv > 0) { |
| + size_t i = 0; |
| + for (auto& result : results) { |
| + if (i == idle_index) { |
| + i++; |
| + continue; |
| + } |
| + result.append(bufs[i]->data(), rv); |
| + i++; |
| + } |
| + } else if (rv <= 0) { |
| + return rv; |
| + } |
| + first_iter = false; |
| + } while (rv > 0); |
| + |
| + return OK; |
| + } |
| + |
| + int ReadCacheWriteFailure(std::vector<std::string>& results) { |
| + int rv; |
| + bool first_iter = true; |
| + do { |
| + std::vector<scoped_refptr<IOBuffer>> bufs; |
| + std::vector<TestCompletionCallback> callbacks(results.size()); |
| + |
| + // 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(); |
| + |
| + size_t i = 0; |
| + for (auto& transaction : transactions_) { |
| + bufs.push_back(new IOBuffer(30)); |
| + |
| + if (!first_iter && i > 0) |
| + break; |
| + rv = writers_->Read(bufs[i].get(), 30, callbacks[i].callback(), |
| + (Transaction*)transaction.get()); |
| + EXPECT_EQ(rv, ERR_IO_PENDING); // Since the default is asynchronous. |
| + i++; |
| + } |
| + |
| + if (rv == ERR_IO_PENDING) { |
| + int i = 0; |
| + for (auto& callback : callbacks) { |
| + // Only active transaction should succeed. |
| + if (i == 0) { |
| + rv = callback.WaitForResult(); |
| + EXPECT_TRUE(rv >= 0); |
| + results[0].append(bufs[i]->data(), rv); |
| + if (rv == 0) |
| + return rv; |
| + } else if (first_iter) { |
| + rv = callback.WaitForResult(); |
| + EXPECT_EQ(ERR_CACHE_WRITE_FAILURE, rv); |
| + } |
| + i++; |
| + } |
| + } |
| + |
| + first_iter = false; |
| + } while (true); |
| + |
| + return OK; |
| + } |
| + |
| + int ReadNetworkFailure(std::vector<std::string>& results) { |
| + int rv; |
| + do { |
| + std::vector<scoped_refptr<IOBuffer>> bufs; |
| + std::vector<TestCompletionCallback> callbacks(results.size()); |
| + |
| + // Fail the request. |
| + MockNetworkTransaction* network_transaction = |
| + (MockNetworkTransaction*)(writers_->network_transaction()); |
| + network_transaction->SetReadError(ERR_INTERNET_DISCONNECTED); |
| + |
| + size_t i = 0; |
| + for (auto& transaction : transactions_) { |
| + bufs.push_back(new IOBuffer(30)); |
| + |
| + rv = writers_->Read(bufs[i].get(), 30, callbacks[i].callback(), |
| + (Transaction*)transaction.get()); |
| + EXPECT_EQ(rv, ERR_IO_PENDING); // Since the default is asynchronous. |
| + i++; |
| + } |
| + |
| + if (rv == ERR_IO_PENDING) { |
| + for (auto& callback : callbacks) { |
| + rv = callback.WaitForResult(); |
| + EXPECT_EQ(ERR_INTERNET_DISCONNECTED, rv); |
| + } |
| + } |
| + } while (rv > 0); |
| + |
| + return rv; |
| + } |
| + |
| + bool StopCaching() { |
| + Transaction* transaction = (Transaction*)(transactions_.begin()->get()); |
| + DCHECK(transaction); |
| + return writers_->StopCaching(transaction); |
| + } |
| + |
| + void RemoveFirstTransaction() { |
| + Transaction* transaction = (Transaction*)(transactions_.begin()->get()); |
| + DCHECK(transaction); |
| + writers_->RemoveTransaction(transaction); |
| + } |
| + |
| + MockHttpCache cache_; |
| + std::unique_ptr<Writers> writers_; |
| + std::vector<std::unique_ptr<HttpTransaction>> transactions_; |
| +}; |
| + |
| +// Tests successful addition of a transaction. |
| +TEST(HttpCacheWriters, AddTransaction) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| +} |
| + |
| +// Tests successful addition of multiple transaction. |
| +TEST(HttpCacheWriters, AddManyTransactions) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + for (int i = 0; i < 5; i++) |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + EXPECT_EQ(writersTest.writers_->CountTransactionsForTesting(), 6); |
| +} |
| + |
| +// Tests that CanAddWriters should return false if it is exclusive writing. |
| +TEST(HttpCacheWriters, AddTransactionsExclusive) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction, true); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_FALSE(writersTest.writers_->CanAddWriters()); |
| +} |
| + |
| +// Tests StopCaching should not stop caching if there are multiple writers. |
| +TEST(HttpCacheWriters, StopCachingMultipleWriters) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + EXPECT_FALSE(writersTest.StopCaching()); |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| +} |
| + |
| +// Tests StopCaching should stop caching if there is a single writer. |
| +TEST(HttpCacheWriters, StopCaching) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.StopCaching()); |
| + EXPECT_FALSE(writersTest.writers_->CanAddWriters()); |
| +} |
| + |
| +// Tests removing of an idle transaction. |
| +TEST(HttpCacheWriters, RemoveIdleTransaction) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + writersTest.RemoveFirstTransaction(); |
| + EXPECT_TRUE(writersTest.writers_->IsEmpty()); |
| +} |
| + |
| +// Tests that Read is successful. |
| +TEST(HttpCacheWriters, Read) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + std::string content; |
| + int rv = writersTest.Read(&content); |
| + |
| + EXPECT_THAT(rv, IsOk()); |
| + std::string expected(kSimpleGET_Transaction.data); |
| + EXPECT_EQ(expected, content); |
| +} |
| + |
| +// Tests that multiple transactions can read the same data simultaneously. |
| +TEST(HttpCacheWriters, ReadMultiple) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + std::vector<std::string> contents(2); |
| + int rv = writersTest.ReadAll(contents); |
| + |
| + EXPECT_THAT(rv, IsOk()); |
| + std::string expected(kSimpleGET_Transaction.data); |
| + |
| + for (auto content : contents) |
| + EXPECT_EQ(expected, content); |
| +} |
| + |
| +// Tests that ongoing Read completes even when active transaction is deleted |
| +// mid-read. Any transactions waiting should be able to get the read buffer. |
| +TEST(HttpCacheWriters, ReadMultipleDeleteActiveTransaction) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| + writersTest.AddTransactionToExistingWriters(); |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + std::vector<std::string> contents(3); |
| + int rv = writersTest.ReadAllDeleteActiveTransaction(contents); |
| + |
| + EXPECT_THAT(rv, IsOk()); |
| + std::string expected(kSimpleGET_Transaction.data); |
| + |
| + for (auto content : contents) |
| + EXPECT_EQ(expected, content); |
| +} |
| + |
| +// Tests that removing a waiting for read transaction does not impact other |
| +// transactions. |
| +TEST(HttpCacheWriters, ReadMultipleDeleteWaitingTransaction) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| + writersTest.AddTransactionToExistingWriters(); |
| + writersTest.AddTransactionToExistingWriters(); |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + std::vector<std::string> contents(4); |
| + size_t waiting_index = 1; |
| + int rv = writersTest.ReadAllDeleteWaitingTransaction(contents, waiting_index); |
| + |
| + EXPECT_THAT(rv, IsOk()); |
| + std::string expected(kSimpleGET_Transaction.data); |
| + |
| + size_t i = 0; |
| + for (auto content : contents) { |
| + if (i == waiting_index) |
| + EXPECT_EQ("", content); |
| + else |
| + EXPECT_EQ(expected, content); |
| + i++; |
| + } |
| +} |
| + |
| +// Tests that removing an idle transaction does not impact other transactions. |
| +TEST(HttpCacheWriters, ReadMultipleDeleteIdleTransaction) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| + writersTest.AddTransactionToExistingWriters(); |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + std::vector<std::string> contents(3); |
| + size_t idle_index = 1; |
| + int rv = writersTest.ReadAllDeleteIdleTransaction(contents, idle_index); |
| + |
| + EXPECT_THAT(rv, IsOk()); |
| + std::string expected(kSimpleGET_Transaction.data); |
| + |
| + size_t i = 0; |
| + for (auto content : contents) { |
| + if (i == idle_index) { |
| + i++; |
| + continue; |
| + } |
| + EXPECT_EQ(expected, content); |
| + i++; |
| + } |
| +} |
| + |
| +// Tests cache write failure. |
| +TEST(HttpCacheWriters, ReadMultipleCacheWriteFailed) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| + writersTest.AddTransactionToExistingWriters(); |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + std::vector<std::string> contents(3); |
| + int rv = writersTest.ReadCacheWriteFailure(contents); |
| + |
| + EXPECT_THAT(rv, IsOk()); |
| + std::string expected(kSimpleGET_Transaction.data); |
| + |
| + // Only active_transaction_ should succeed. |
| + EXPECT_EQ(expected, contents.at(0)); |
| + |
| + // No new transactions should now be added. |
| + EXPECT_FALSE(writersTest.writers_->CanAddWriters()); |
| +} |
| + |
| +// Tests that network read failure fails all transactions: active, waiting and |
| +// idle. |
| +TEST(HttpCacheWriters, ReadMultipleNetworkReadFailed) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| + writersTest.AddTransactionToExistingWriters(); |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + std::vector<std::string> contents(3); |
| + int rv = writersTest.ReadNetworkFailure(contents); |
| + |
| + EXPECT_EQ(rv, ERR_INTERNET_DISCONNECTED); |
| +} |
| + |
| +// Tests moving idle writers to readers. |
| +TEST(HttpCacheWriters, MoveIdleWritersToReaders) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_TRUE(writersTest.writers_->CanAddWriters()); |
| + writersTest.AddTransactionToExistingWriters(); |
| + writersTest.AddTransactionToExistingWriters(); |
| + |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + writersTest.writers_->RemoveAllIdleWriters(); |
| + EXPECT_TRUE(writersTest.writers_->IsEmpty()); |
| +} |
| + |
| +// Tests GetWriterLoadState. |
| +TEST(HttpCacheWriters, GetWriterLoadState) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + EXPECT_EQ(LOAD_STATE_IDLE, writersTest.writers_->GetWriterLoadState()); |
| +} |
| + |
| +// Tests truncating the entry via Writers. |
| +TEST(HttpCacheWriters, TruncateEntry) { |
| + HttpCache::WritersTest writersTest; |
| + |
| + writersTest.CreateWritersAddTransaction(kSimpleGET_Transaction); |
| + EXPECT_FALSE(writersTest.writers_->IsEmpty()); |
| + |
| + std::string content; |
| + int rv = writersTest.Read(&content); |
| + |
| + EXPECT_THAT(rv, IsOk()); |
| + std::string expected(kSimpleGET_Transaction.data); |
| + EXPECT_EQ(expected, content); |
| + |
| + writersTest.writers_->TruncateEntry(); |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(writersTest.writers_->IsTruncatedForTesting()); |
| +} |
| + |
| +} // namespace net |