| Index: chrome/browser/browsing_data/storage_partition_http_cache_data_remover_browsertest.cc
|
| diff --git a/chrome/browser/browsing_data/storage_partition_http_cache_data_remover_browsertest.cc b/chrome/browser/browsing_data/storage_partition_http_cache_data_remover_browsertest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..df7b04cef4d1b6bc39b0eba615c11d57a230a04f
|
| --- /dev/null
|
| +++ b/chrome/browser/browsing_data/storage_partition_http_cache_data_remover_browsertest.cc
|
| @@ -0,0 +1,445 @@
|
| +// Copyright (c) 2015 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 "base/run_loop.h"
|
| +#include "base/threading/platform_thread.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/ui/browser.h"
|
| +#include "chrome/test/base/in_process_browser_test.h"
|
| +#include "components/browsing_data/storage_partition_http_cache_data_remover.h"
|
| +#include "content/public/browser/browser_context.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "content/public/browser/storage_partition.h"
|
| +#include "net/disk_cache/disk_cache.h"
|
| +#include "net/http/http_cache.h"
|
| +#include "net/url_request/url_request_context.h"
|
| +#include "net/url_request/url_request_context_getter.h"
|
| +
|
| +using browsing_data::StoragePartitionHttpCacheDataRemover;
|
| +using content::BrowserThread;
|
| +
|
| +class StoragePartitionHttpCacheDataRemoverBrowserTest
|
| + : public InProcessBrowserTest {
|
| + public:
|
| + // Initialization ------------------------------------------------------------
|
| +
|
| + void SetUpOnMainThread() override {
|
| + result_callback_ = base::Bind(
|
| + &StoragePartitionHttpCacheDataRemoverBrowserTest::ResultCallback,
|
| + base::Unretained(this));
|
| + removal_callback_ = base::Bind(
|
| + &StoragePartitionHttpCacheDataRemoverBrowserTest::RemovalCallback,
|
| + base::Unretained(this));
|
| + done_callback_ = base::Bind(
|
| + &StoragePartitionHttpCacheDataRemoverBrowserTest::DoneCallback,
|
| + base::Unretained(this));
|
| + remaining_tasks_ = 0;
|
| + next_key_ = 0;
|
| +
|
| + partition_ = content::BrowserContext::GetDefaultStoragePartition(
|
| + browser()->profile());
|
| +
|
| + // Get the cache backends.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + InitializeCountingTest,
|
| + base::Unretained(this)));
|
| + WaitForTasksOnIOThread();
|
| + DCHECK(main_backend_);
|
| + DCHECK(media_backend_);
|
| + }
|
| +
|
| + void InitializeCountingTest() {
|
| + net::URLRequestContextGetter* main_context;
|
| + net::URLRequestContextGetter* media_context;
|
| +
|
| + main_context = partition_->GetURLRequestContext();
|
| + media_context = partition_->GetMediaURLRequestContext();
|
| +
|
| + net::HttpCache* main_cache = main_context->GetURLRequestContext()->
|
| + http_transaction_factory()->GetCache();
|
| + net::HttpCache* media_cache = media_context->GetURLRequestContext()->
|
| + http_transaction_factory()->GetCache();
|
| +
|
| + SetNumberOfWaitedTasks(2);
|
| + WaitForCompletion(main_cache->GetBackend(&main_backend_, done_callback_));
|
| + WaitForCompletion(media_cache->GetBackend(&media_backend_, done_callback_));
|
| + }
|
| +
|
| + // Get a new remover instance.
|
| + StoragePartitionHttpCacheDataRemover* GetNewRemover() {
|
| + return GetNewRemoverForRange(base::Time(), base::Time::Max());
|
| + }
|
| +
|
| + StoragePartitionHttpCacheDataRemover* GetNewRemoverForRange(
|
| + base::Time begin, base::Time end) {
|
| + return StoragePartitionHttpCacheDataRemover::CreateForRange(
|
| + partition_, begin, end);
|
| + }
|
| +
|
| + // Waiting for the calculation and retrieving results on the UI thread,
|
| + // or cache cleaning. --------------------------------------------------------
|
| +
|
| + void WaitForResultOrRemoval() {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + loop_.reset(new base::RunLoop());
|
| + loop_->Run();
|
| + }
|
| +
|
| + void ResultCallback(int64 result) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + if (loop_)
|
| + loop_->Quit();
|
| + result_ = result;
|
| + }
|
| +
|
| + void RemovalCallback() {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + if (loop_)
|
| + loop_->Quit();
|
| + }
|
| +
|
| + net::Int64CompletionCallback GetResultCallback() {
|
| + return result_callback_;
|
| + }
|
| +
|
| + base::Closure GetRemovalCallback() {
|
| + return removal_callback_;
|
| + }
|
| +
|
| + int64 GetResult() {
|
| + return result_;
|
| + }
|
| +
|
| + // Waiting for tasks to be done on IO thread. --------------------------------
|
| +
|
| + void WaitForTasksOnIOThread() {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + io_thread_loop_.reset(new base::RunLoop());
|
| + io_thread_loop_->Run();
|
| + }
|
| +
|
| + void SetNumberOfWaitedTasks(int count) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + remaining_tasks_ = count;
|
| + }
|
| +
|
| + void WaitForCompletion(int value) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + if (value >= 0) {
|
| + // We got the result immediately.
|
| + DoneCallback(value);
|
| + } else if (value == net::ERR_IO_PENDING) {
|
| + // We need to wait for the callback.
|
| + } else {
|
| + // An error has occurred.
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + void DoneCallback(int value) {
|
| + DCHECK_GE(value, 0); // Negative values represent error codes.
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + if (--remaining_tasks_ > 0)
|
| + return;
|
| +
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&base::RunLoop::Quit,
|
| + base::Unretained(io_thread_loop_.get())));
|
| + }
|
| +
|
| + // Helpers. ------------------------------------------------------------------
|
| +
|
| + void CreateCacheEntries(size_t main_count, size_t media_count) {
|
| + entries_.resize(main_count + media_count);
|
| +
|
| + SetNumberOfWaitedTasks(main_count + media_count);
|
| + for (size_t i = 0; i < main_count; ++i) {
|
| + WaitForCompletion(main_backend_->CreateEntry(
|
| + GetUniqueEntryKey(), &entries_[i], done_callback_));
|
| + }
|
| + for (size_t i = main_count; i < main_count + media_count; ++i) {
|
| + WaitForCompletion(media_backend_->CreateEntry(
|
| + GetUniqueEntryKey(), &entries_[i], done_callback_));
|
| + }
|
| + }
|
| +
|
| + void WriteDataToEntries(const std::vector<int>& sizes) {
|
| + DCHECK_EQ(entries_.size(), sizes.size());
|
| + std::string data(*std::max_element(sizes.begin(), sizes.end()), ' ');
|
| + scoped_refptr<net::StringIOBuffer> buffer = new net::StringIOBuffer(data);
|
| +
|
| + SetNumberOfWaitedTasks(entries_.size());
|
| + for (size_t i = 0; i < entries_.size(); ++i) {
|
| + // Alternate between writing to the first and second stream to test that
|
| + // we're taking all streams into account.
|
| + WaitForCompletion(entries_[i]->WriteData(
|
| + i % 2, 0, buffer.get(), sizes[i], done_callback_, true));
|
| + }
|
| + }
|
| +
|
| + private:
|
| + // Generates a unique key for a new cache entry.
|
| + std::string GetUniqueEntryKey() {
|
| + return std::to_string(next_key_++);
|
| + }
|
| +
|
| + int next_key_;
|
| +
|
| + content::StoragePartition* partition_;
|
| + disk_cache::Backend* main_backend_ = nullptr;
|
| + disk_cache::Backend* media_backend_ = nullptr;
|
| +
|
| + // Shorthands for callback binding.
|
| + base::Callback<void(int)> done_callback_;
|
| + base::Closure removal_callback_;
|
| + net::Int64CompletionCallback result_callback_;
|
| +
|
| + int64 result_;
|
| + scoped_ptr<base::RunLoop> loop_;
|
| + scoped_ptr<base::RunLoop> io_thread_loop_;
|
| +
|
| + std::vector<disk_cache::Entry*> entries_;
|
| + int remaining_tasks_;
|
| +};
|
| +
|
| +// Test that the size of empty cache is computed as 0.
|
| +IN_PROC_BROWSER_TEST_F(
|
| + StoragePartitionHttpCacheDataRemoverBrowserTest, Empty) {
|
| + // Calculate the size of the empty caches. The result should be 0.
|
| + GetNewRemover()->Count(GetResultCallback());
|
| + WaitForResultOrRemoval();
|
| + EXPECT_TRUE(GetResult() == 0 || GetResult() == net::ERR_NOT_IMPLEMENTED);
|
| +}
|
| +
|
| +// Test that StoragePartitionHttpCacheDataRemover correctly counts the total
|
| +// size of items in the main and media cache.
|
| +IN_PROC_BROWSER_TEST_F(
|
| + StoragePartitionHttpCacheDataRemoverBrowserTest, Counting) {
|
| + // Create 5 entries and write 23 bytes of data, distributed to both caches,
|
| + // different entries, and different streams within them.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + CreateCacheEntries,
|
| + base::Unretained(this),
|
| + 3, 2));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + std::vector<int> data;
|
| + data.push_back(10);
|
| + data.push_back(3);
|
| + data.push_back(4);
|
| + data.push_back(1);
|
| + data.push_back(5);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + WriteDataToEntries,
|
| + base::Unretained(this),
|
| + data));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + // Calculate the size of the caches now. The result should be 23.
|
| + // TODO(msramek): Change the test to "EXPECT_EQ(23, GetResult());" as soon as
|
| + // the size calculation is implemented for memory and simple cache backends.
|
| + GetNewRemover()->Count(GetResultCallback());
|
| + WaitForResultOrRemoval();
|
| + EXPECT_TRUE(GetResult() == 23 || GetResult() == net::ERR_NOT_IMPLEMENTED);
|
| +}
|
| +
|
| +// Test that StoragePartitionHttpCacheDataRemover correctly recognizes the cache
|
| +// to be empty when it was populated and cleared again.
|
| +IN_PROC_BROWSER_TEST_F(
|
| + StoragePartitionHttpCacheDataRemoverBrowserTest, PopulatedAndCleared) {
|
| + // Write data to both caches.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + CreateCacheEntries,
|
| + base::Unretained(this),
|
| + 1, 2));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + std::vector<int> data;
|
| + data.push_back(10000);
|
| + data.push_back(12345);
|
| + data.push_back(20000);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + WriteDataToEntries,
|
| + base::Unretained(this),
|
| + data));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + // Clear both caches.
|
| + GetNewRemover()->Remove(GetRemovalCallback());
|
| + WaitForResultOrRemoval();
|
| +
|
| + // Calculate the size of the caches. The result should be 0.
|
| + // TODO(msramek): Change the test to "EXPECT_EQ(0, GetResult());" as soon as
|
| + // the size calculation is implemented for memory and simple cache backends.
|
| + GetNewRemover()->Count(GetResultCallback());
|
| + WaitForResultOrRemoval();
|
| + EXPECT_TRUE(GetResult() == 0 || GetResult() == net::ERR_NOT_IMPLEMENTED);
|
| +}
|
| +
|
| +// Test that StoragePartitionHttpCacheDataRemover correctly counts the cache
|
| +// size when data are incrementally added.
|
| +IN_PROC_BROWSER_TEST_F(
|
| + StoragePartitionHttpCacheDataRemoverBrowserTest, Incremental) {
|
| + // Write data to both caches.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + CreateCacheEntries,
|
| + base::Unretained(this),
|
| + 1, 2));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + std::vector<int> data;
|
| + data.push_back(5);
|
| + data.push_back(7);
|
| + data.push_back(9);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + WriteDataToEntries,
|
| + base::Unretained(this),
|
| + data));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + // The size should be 21.
|
| + // TODO(msramek): Change the test to "EXPECT_EQ(21, GetResult());" as soon as
|
| + // the size calculation is implemented for memory and simple cache backends.
|
| + GetNewRemover()->Count(GetResultCallback());
|
| + WaitForResultOrRemoval();
|
| + EXPECT_TRUE(GetResult() == 21 || GetResult() == net::ERR_NOT_IMPLEMENTED);
|
| +
|
| + // Create a new batch of entries and write more data.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + CreateCacheEntries,
|
| + base::Unretained(this),
|
| + 4, 3));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + data.clear();
|
| + data.push_back(0);
|
| + data.push_back(1);
|
| + data.push_back(1);
|
| + data.push_back(8);
|
| + data.push_back(9);
|
| + data.push_back(9);
|
| + data.push_back(9);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + WriteDataToEntries,
|
| + base::Unretained(this),
|
| + data));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + // The size should be 58.
|
| + // TODO(msramek): Change the test to "EXPECT_EQ(58, GetResult());" as soon as
|
| + // the size calculation is implemented for memory and simple cache backends.
|
| + GetNewRemover()->Count(GetResultCallback());
|
| + WaitForResultOrRemoval();
|
| + EXPECT_TRUE(GetResult() == 58 || GetResult() == net::ERR_NOT_IMPLEMENTED);
|
| +
|
| + // Update the entries from the last batch with new values.
|
| + data.clear();
|
| + data.push_back(1);
|
| + data.push_back(2);
|
| + data.push_back(3);
|
| + data.push_back(4);
|
| + data.push_back(5);
|
| + data.push_back(6);
|
| + data.push_back(7);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + WriteDataToEntries,
|
| + base::Unretained(this),
|
| + data));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + // The size should now be 49.
|
| + // TODO(msramek): Change the test to "EXPECT_EQ(49, GetResult());" as soon as
|
| + // the size calculation is implemented for memory and simple cache backends.
|
| + GetNewRemover()->Count(GetResultCallback());
|
| + WaitForResultOrRemoval();
|
| + EXPECT_TRUE(GetResult() == 49 || GetResult() == net::ERR_NOT_IMPLEMENTED);
|
| +}
|
| +
|
| +IN_PROC_BROWSER_TEST_F(
|
| + StoragePartitionHttpCacheDataRemoverBrowserTest, TimePeriod) {
|
| + // Write a batch of entries.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + CreateCacheEntries,
|
| + base::Unretained(this),
|
| + 2, 2));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + std::vector<int> data;
|
| + data.push_back(7);
|
| + data.push_back(2);
|
| + data.push_back(5);
|
| + data.push_back(3);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + WriteDataToEntries,
|
| + base::Unretained(this),
|
| + data));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + // Skip at least a millisecond. Since time ranges are half-closed intervals,
|
| + // |threshold| must be strictly greater than timestamps of any previous entry.
|
| + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
|
| + base::Time threshold = base::Time::Now();
|
| +
|
| + // Write another batch of entries.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + CreateCacheEntries,
|
| + base::Unretained(this),
|
| + 1, 2));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + data.clear();
|
| + data.push_back(1);
|
| + data.push_back(6);
|
| + data.push_back(4);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&StoragePartitionHttpCacheDataRemoverBrowserTest::
|
| + WriteDataToEntries,
|
| + base::Unretained(this),
|
| + data));
|
| + WaitForTasksOnIOThread();
|
| +
|
| + // Count the entries added before the threshold. The result should be 17.
|
| + // TODO(msramek): Change the test to "EXPECT_EQ(17, GetResult());" as soon as
|
| + // the size calculation is implemented for memory and simple cache backends.
|
| + GetNewRemoverForRange(base::Time(), threshold)->Count(GetResultCallback());
|
| + WaitForResultOrRemoval();
|
| + EXPECT_TRUE(GetResult() == 17 || GetResult() == net::ERR_NOT_IMPLEMENTED);
|
| +
|
| + // Count the entries added after the threshold. The result should be 11.
|
| + // TODO(msramek): Change the test to "EXPECT_EQ(11, GetResult());" as soon as
|
| + // the size calculation is implemented for memory and simple cache backends.
|
| + GetNewRemoverForRange(
|
| + threshold, base::Time::Now())->Count(GetResultCallback());
|
| + WaitForResultOrRemoval();
|
| + EXPECT_TRUE(GetResult() == 11 || GetResult() == net::ERR_NOT_IMPLEMENTED);
|
| +}
|
|
|