This source file includes following definitions.
- CreateExistingEntryCache
- GeneratePendingIO
- InitSparseCache
- CreateSetOfRandomEntries
- EnumerateAndMatchKeys
- BackendBasics
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendKeying
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendShutdownWithPendingFileIO
- TEST_F
- TEST_F
- TEST_F
- BackendShutdownWithPendingIO
- TEST_F
- TEST_F
- BackendShutdownWithPendingCreate
- TEST_F
- TEST_F
- TEST_F
- BackendSetSize
- TEST_F
- TEST_F
- TEST_F
- BackendLoad
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendChain
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendValidEntry
- TEST_F
- TEST_F
- BackendInvalidEntry
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendInvalidEntryRead
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendInvalidEntryWithLoad
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendTrimInvalidEntry
- TEST_F
- TEST_F
- BackendTrimInvalidEntry2
- TEST_F
- TEST_F
- BackendEnumerations
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendEnumerations2
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendInvalidEntryEnumeration
- TEST_F
- TEST_F
- BackendFixEnumerators
- TEST_F
- TEST_F
- BackendDoomRecent
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendDoomBetween
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendTransaction
- BackendRecoverInsert
- TEST_F
- TEST_F
- BackendRecoverRemove
- TEST_F
- TEST_F
- BackendRecoverWithEviction
- TEST_F
- TEST_F
- TEST_F
- GetEntropyForTrial
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendInvalidEntry2
- TEST_F
- TEST_F
- BackendInvalidEntry3
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendInvalidEntry7
- TEST_F
- TEST_F
- BackendInvalidEntry8
- TEST_F
- TEST_F
- BackendInvalidEntry9
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendInvalidEntry10
- TEST_F
- TEST_F
- BackendInvalidEntry11
- TEST_F
- TEST_F
- BackendTrimInvalidEntry12
- TEST_F
- TEST_F
- BackendInvalidRankings2
- TEST_F
- TEST_F
- BackendInvalidRankings
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendDisable
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendDisable2
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendDisable3
- TEST_F
- TEST_F
- BackendDisable4
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendDoomAll
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- BackendDoomAll2
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TracingBackendBasics
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/metrics/field_trial.h"
#include "base/port.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_restrictions.h"
#include "net/base/cache_type.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/disk_cache/blockfile/backend_impl.h"
#include "net/disk_cache/blockfile/entry_impl.h"
#include "net/disk_cache/blockfile/experiments.h"
#include "net/disk_cache/blockfile/histogram_macros.h"
#include "net/disk_cache/blockfile/mapped_file.h"
#include "net/disk_cache/cache_util.h"
#include "net/disk_cache/disk_cache_test_base.h"
#include "net/disk_cache/disk_cache_test_util.h"
#include "net/disk_cache/memory/mem_backend_impl.h"
#include "net/disk_cache/simple/simple_backend_impl.h"
#include "net/disk_cache/simple/simple_entry_format.h"
#include "net/disk_cache/simple/simple_test_util.h"
#include "net/disk_cache/simple/simple_util.h"
#include "net/disk_cache/tracing/tracing_cache_backend.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_WIN)
#include "base/win/scoped_handle.h"
#endif
#define CACHE_UMA_BACKEND_IMPL_OBJ backend_
using base::Time;
namespace {
const char kExistingEntryKey[] = "existing entry key";
scoped_ptr<disk_cache::BackendImpl> CreateExistingEntryCache(
const base::Thread& cache_thread,
base::FilePath& cache_path) {
net::TestCompletionCallback cb;
scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
cache_path, cache_thread.message_loop_proxy(), NULL));
int rv = cache->Init(cb.callback());
if (cb.GetResult(rv) != net::OK)
return scoped_ptr<disk_cache::BackendImpl>();
disk_cache::Entry* entry = NULL;
rv = cache->CreateEntry(kExistingEntryKey, &entry, cb.callback());
if (cb.GetResult(rv) != net::OK)
return scoped_ptr<disk_cache::BackendImpl>();
entry->Close();
return cache.Pass();
}
}
class DiskCacheBackendTest : public DiskCacheTestWithCache {
protected:
int GeneratePendingIO(net::TestCompletionCallback* cb);
void InitSparseCache(base::Time* doomed_start, base::Time* doomed_end);
bool CreateSetOfRandomEntries(std::set<std::string>* key_pool);
bool EnumerateAndMatchKeys(int max_to_open,
void** iter,
std::set<std::string>* keys_to_match,
size_t* count);
void BackendBasics();
void BackendKeying();
void BackendShutdownWithPendingFileIO(bool fast);
void BackendShutdownWithPendingIO(bool fast);
void BackendShutdownWithPendingCreate(bool fast);
void BackendSetSize();
void BackendLoad();
void BackendChain();
void BackendValidEntry();
void BackendInvalidEntry();
void BackendInvalidEntryRead();
void BackendInvalidEntryWithLoad();
void BackendTrimInvalidEntry();
void BackendTrimInvalidEntry2();
void BackendEnumerations();
void BackendEnumerations2();
void BackendInvalidEntryEnumeration();
void BackendFixEnumerators();
void BackendDoomRecent();
void BackendDoomBetween();
void BackendTransaction(const std::string& name, int num_entries, bool load);
void BackendRecoverInsert();
void BackendRecoverRemove();
void BackendRecoverWithEviction();
void BackendInvalidEntry2();
void BackendInvalidEntry3();
void BackendInvalidEntry7();
void BackendInvalidEntry8();
void BackendInvalidEntry9(bool eviction);
void BackendInvalidEntry10(bool eviction);
void BackendInvalidEntry11(bool eviction);
void BackendTrimInvalidEntry12();
void BackendDoomAll();
void BackendDoomAll2();
void BackendInvalidRankings();
void BackendInvalidRankings2();
void BackendDisable();
void BackendDisable2();
void BackendDisable3();
void BackendDisable4();
void TracingBackendBasics();
};
int DiskCacheBackendTest::GeneratePendingIO(net::TestCompletionCallback* cb) {
if (!use_current_thread_) {
ADD_FAILURE();
return net::ERR_FAILED;
}
disk_cache::Entry* entry;
int rv = cache_->CreateEntry("some key", &entry, cb->callback());
if (cb->GetResult(rv) != net::OK)
return net::ERR_CACHE_CREATE_FAILURE;
const int kSize = 25000;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
for (int i = 0; i < 10 * 1024 * 1024; i += 64 * 1024) {
if (!simple_cache_mode_) {
rv = static_cast<disk_cache::EntryImpl*>(entry)->WriteDataImpl(
0, i, buffer.get(), kSize, cb->callback(), false);
} else {
rv = entry->WriteData(0, i, buffer.get(), kSize, cb->callback(), false);
}
if (rv == net::ERR_IO_PENDING)
break;
if (rv != kSize)
rv = net::ERR_FAILED;
}
if (!simple_cache_mode_)
static_cast<disk_cache::EntryImpl*>(entry)->Release();
else
entry->Close();
return rv;
}
void DiskCacheBackendTest::InitSparseCache(base::Time* doomed_start,
base::Time* doomed_end) {
InitCache();
const int kSize = 50;
const int kOffset = 10 + 1024 * 1024;
disk_cache::Entry* entry0 = NULL;
disk_cache::Entry* entry1 = NULL;
disk_cache::Entry* entry2 = NULL;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
ASSERT_EQ(net::OK, CreateEntry("zeroth", &entry0));
ASSERT_EQ(kSize, WriteSparseData(entry0, 0, buffer.get(), kSize));
ASSERT_EQ(kSize,
WriteSparseData(entry0, kOffset + kSize, buffer.get(), kSize));
entry0->Close();
FlushQueueForTest();
AddDelay();
if (doomed_start)
*doomed_start = base::Time::Now();
ASSERT_EQ(net::OK, CreateEntry("first", &entry1));
ASSERT_EQ(kSize, WriteSparseData(entry1, 0, buffer.get(), kSize));
ASSERT_EQ(kSize,
WriteSparseData(entry1, kOffset + kSize, buffer.get(), kSize));
entry1->Close();
ASSERT_EQ(net::OK, CreateEntry("second", &entry2));
ASSERT_EQ(kSize, WriteSparseData(entry2, 0, buffer.get(), kSize));
ASSERT_EQ(kSize,
WriteSparseData(entry2, kOffset + kSize, buffer.get(), kSize));
entry2->Close();
FlushQueueForTest();
AddDelay();
if (doomed_end)
*doomed_end = base::Time::Now();
disk_cache::Entry* entry3 = NULL;
disk_cache::Entry* entry4 = NULL;
ASSERT_EQ(net::OK, CreateEntry("third", &entry3));
ASSERT_EQ(kSize, WriteSparseData(entry3, 0, buffer.get(), kSize));
ASSERT_EQ(net::OK, CreateEntry("fourth", &entry4));
ASSERT_EQ(kSize, WriteSparseData(entry4, 0, buffer.get(), kSize));
ASSERT_EQ(kSize,
WriteSparseData(entry3, kOffset + kSize, buffer.get(), kSize));
ASSERT_EQ(kSize,
WriteSparseData(entry4, kOffset + kSize, buffer.get(), kSize));
entry3->Close();
entry4->Close();
FlushQueueForTest();
AddDelay();
}
bool DiskCacheBackendTest::CreateSetOfRandomEntries(
std::set<std::string>* key_pool) {
const int kNumEntries = 10;
for (int i = 0; i < kNumEntries; ++i) {
std::string key = GenerateKey(true);
disk_cache::Entry* entry;
if (CreateEntry(key, &entry) != net::OK)
return false;
key_pool->insert(key);
entry->Close();
}
return key_pool->size() == implicit_cast<size_t>(cache_->GetEntryCount());
}
bool DiskCacheBackendTest::EnumerateAndMatchKeys(
int max_to_open,
void** iter,
std::set<std::string>* keys_to_match,
size_t* count) {
disk_cache::Entry* entry;
while (OpenNextEntry(iter, &entry) == net::OK) {
if (!entry)
return false;
EXPECT_EQ(1U, keys_to_match->erase(entry->GetKey()));
entry->Close();
++(*count);
if (max_to_open >= 0 && implicit_cast<int>(*count) >= max_to_open)
break;
};
return true;
}
void DiskCacheBackendTest::BackendBasics() {
InitCache();
disk_cache::Entry *entry1 = NULL, *entry2 = NULL;
EXPECT_NE(net::OK, OpenEntry("the first key", &entry1));
ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1));
ASSERT_TRUE(NULL != entry1);
entry1->Close();
entry1 = NULL;
ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
ASSERT_TRUE(NULL != entry1);
entry1->Close();
entry1 = NULL;
EXPECT_NE(net::OK, CreateEntry("the first key", &entry1));
ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
EXPECT_NE(net::OK, OpenEntry("some other key", &entry2));
ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2));
ASSERT_TRUE(NULL != entry1);
ASSERT_TRUE(NULL != entry2);
EXPECT_EQ(2, cache_->GetEntryCount());
disk_cache::Entry* entry3 = NULL;
ASSERT_EQ(net::OK, OpenEntry("some other key", &entry3));
ASSERT_TRUE(NULL != entry3);
EXPECT_TRUE(entry2 == entry3);
EXPECT_EQ(2, cache_->GetEntryCount());
EXPECT_EQ(net::OK, DoomEntry("some other key"));
EXPECT_EQ(1, cache_->GetEntryCount());
entry1->Close();
entry2->Close();
entry3->Close();
EXPECT_EQ(net::OK, DoomEntry("the first key"));
EXPECT_EQ(0, cache_->GetEntryCount());
ASSERT_EQ(net::OK, CreateEntry("the first key", &entry1));
ASSERT_EQ(net::OK, CreateEntry("some other key", &entry2));
entry1->Doom();
entry1->Close();
EXPECT_EQ(net::OK, DoomEntry("some other key"));
EXPECT_EQ(0, cache_->GetEntryCount());
entry2->Close();
}
TEST_F(DiskCacheBackendTest, Basics) {
BackendBasics();
}
TEST_F(DiskCacheBackendTest, NewEvictionBasics) {
SetNewEviction();
BackendBasics();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyBasics) {
SetMemoryOnlyMode();
BackendBasics();
}
TEST_F(DiskCacheBackendTest, AppCacheBasics) {
SetCacheType(net::APP_CACHE);
BackendBasics();
}
TEST_F(DiskCacheBackendTest, ShaderCacheBasics) {
SetCacheType(net::SHADER_CACHE);
BackendBasics();
}
void DiskCacheBackendTest::BackendKeying() {
InitCache();
const char* kName1 = "the first key";
const char* kName2 = "the first Key";
disk_cache::Entry *entry1, *entry2;
ASSERT_EQ(net::OK, CreateEntry(kName1, &entry1));
ASSERT_EQ(net::OK, CreateEntry(kName2, &entry2));
EXPECT_TRUE(entry1 != entry2) << "Case sensitive";
entry2->Close();
char buffer[30];
base::strlcpy(buffer, kName1, arraysize(buffer));
ASSERT_EQ(net::OK, OpenEntry(buffer, &entry2));
EXPECT_TRUE(entry1 == entry2);
entry2->Close();
base::strlcpy(buffer + 1, kName1, arraysize(buffer) - 1);
ASSERT_EQ(net::OK, OpenEntry(buffer + 1, &entry2));
EXPECT_TRUE(entry1 == entry2);
entry2->Close();
base::strlcpy(buffer + 3, kName1, arraysize(buffer) - 3);
ASSERT_EQ(net::OK, OpenEntry(buffer + 3, &entry2));
EXPECT_TRUE(entry1 == entry2);
entry2->Close();
char buffer2[20000];
memset(buffer2, 's', sizeof(buffer2));
buffer2[1023] = '\0';
ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on block file";
entry2->Close();
buffer2[1023] = 'g';
buffer2[19999] = '\0';
ASSERT_EQ(net::OK, CreateEntry(buffer2, &entry2)) << "key on external file";
entry2->Close();
entry1->Close();
}
TEST_F(DiskCacheBackendTest, Keying) {
BackendKeying();
}
TEST_F(DiskCacheBackendTest, NewEvictionKeying) {
SetNewEviction();
BackendKeying();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) {
SetMemoryOnlyMode();
BackendKeying();
}
TEST_F(DiskCacheBackendTest, AppCacheKeying) {
SetCacheType(net::APP_CACHE);
BackendKeying();
}
TEST_F(DiskCacheBackendTest, ShaderCacheKeying) {
SetCacheType(net::SHADER_CACHE);
BackendKeying();
}
TEST_F(DiskCacheTest, CreateBackend) {
net::TestCompletionCallback cb;
{
ASSERT_TRUE(CleanupCacheDir());
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
scoped_ptr<disk_cache::Backend> cache;
cache = disk_cache::MemBackendImpl::CreateBackend(0, NULL);
ASSERT_TRUE(cache.get());
cache.reset();
int rv =
disk_cache::CreateCacheBackend(net::DISK_CACHE,
net::CACHE_BACKEND_DEFAULT,
cache_path_,
0,
false,
cache_thread.message_loop_proxy().get(),
NULL,
&cache,
cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
ASSERT_TRUE(cache.get());
cache.reset();
rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE,
net::CACHE_BACKEND_DEFAULT,
base::FilePath(), 0,
false, NULL, NULL, &cache,
cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
ASSERT_TRUE(cache.get());
cache.reset();
}
base::MessageLoop::current()->RunUntilIdle();
}
TEST_F(DiskCacheBackendTest, CreateBackend_MissingFile) {
ASSERT_TRUE(CopyTestCache("bad_entry"));
base::FilePath filename = cache_path_.AppendASCII("data_1");
base::DeleteFile(filename, false);
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
net::TestCompletionCallback cb;
bool prev = base::ThreadRestrictions::SetIOAllowed(false);
scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
cache_path_, cache_thread.message_loop_proxy().get(), NULL));
int rv = cache->Init(cb.callback());
EXPECT_EQ(net::ERR_FAILED, cb.GetResult(rv));
base::ThreadRestrictions::SetIOAllowed(prev);
cache.reset();
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, ExternalFiles) {
InitCache();
base::FilePath filename = cache_path_.AppendASCII("f_000001");
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer1->data(), kSize, false);
ASSERT_EQ(kSize, base::WriteFile(filename, buffer1->data(), kSize));
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry("key", &entry));
ASSERT_EQ(0, WriteData(entry, 0, 20000, buffer1.get(), 0, false));
entry->Close();
scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
ASSERT_EQ(kSize, base::ReadFile(filename, buffer2->data(), kSize));
EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize));
}
void DiskCacheBackendTest::BackendShutdownWithPendingFileIO(bool fast) {
ASSERT_TRUE(CleanupCacheDir());
uint32 flags = disk_cache::kNoBuffering;
if (!fast)
flags |= disk_cache::kNoRandom;
UseCurrentThread();
CreateBackend(flags, NULL);
net::TestCompletionCallback cb;
int rv = GeneratePendingIO(&cb);
cache_.reset();
if (rv == net::ERR_IO_PENDING) {
if (fast || simple_cache_mode_)
EXPECT_FALSE(cb.have_result());
else
EXPECT_TRUE(cb.have_result());
}
base::MessageLoop::current()->RunUntilIdle();
#if !defined(OS_IOS)
rv = cb.GetResult(rv);
#endif
}
TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO) {
BackendShutdownWithPendingFileIO(false);
}
#if !defined(LEAK_SANITIZER)
TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO_Fast) {
SetNewEviction();
BackendShutdownWithPendingFileIO(true);
}
#endif
#if !defined(OS_IOS)
TEST_F(DiskCacheBackendTest, MultipleInstancesWithPendingFileIO) {
base::ScopedTempDir store;
ASSERT_TRUE(store.CreateUniqueTempDir());
net::TestCompletionCallback cb;
scoped_ptr<disk_cache::Backend> extra_cache;
int rv = disk_cache::CreateCacheBackend(
net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, store.path(), 0,
false, base::MessageLoopProxy::current().get(), NULL,
&extra_cache, cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
ASSERT_TRUE(extra_cache.get() != NULL);
ASSERT_TRUE(CleanupCacheDir());
SetNewEviction();
UseCurrentThread();
CreateBackend(disk_cache::kNoBuffering, NULL);
rv = GeneratePendingIO(&cb);
extra_cache.reset();
if (rv == net::ERR_IO_PENDING)
EXPECT_FALSE(cb.have_result());
base::MessageLoop::current()->RunUntilIdle();
rv = cb.GetResult(rv);
}
#endif
void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) {
net::TestCompletionCallback cb;
{
ASSERT_TRUE(CleanupCacheDir());
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
uint32 flags = disk_cache::kNoBuffering;
if (!fast)
flags |= disk_cache::kNoRandom;
CreateBackend(flags, &cache_thread);
disk_cache::Entry* entry;
int rv = cache_->CreateEntry("some key", &entry, cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
entry->Close();
cache_.reset();
}
base::MessageLoop::current()->RunUntilIdle();
}
TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO) {
BackendShutdownWithPendingIO(false);
}
#if !defined(LEAK_SANITIZER)
TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO_Fast) {
SetNewEviction();
BackendShutdownWithPendingIO(true);
}
#endif
void DiskCacheBackendTest::BackendShutdownWithPendingCreate(bool fast) {
net::TestCompletionCallback cb;
{
ASSERT_TRUE(CleanupCacheDir());
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
disk_cache::BackendFlags flags =
fast ? disk_cache::kNone : disk_cache::kNoRandom;
CreateBackend(flags, &cache_thread);
disk_cache::Entry* entry;
int rv = cache_->CreateEntry("some key", &entry, cb.callback());
ASSERT_EQ(net::ERR_IO_PENDING, rv);
cache_.reset();
EXPECT_FALSE(cb.have_result());
}
base::MessageLoop::current()->RunUntilIdle();
}
TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate) {
BackendShutdownWithPendingCreate(false);
}
#if !defined(LEAK_SANITIZER)
TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate_Fast) {
SetNewEviction();
BackendShutdownWithPendingCreate(true);
}
#endif
#if !defined(OS_ANDROID)
TEST_F(DiskCacheTest, TruncatedIndex) {
ASSERT_TRUE(CleanupCacheDir());
base::FilePath index = cache_path_.AppendASCII("index");
ASSERT_EQ(5, base::WriteFile(index, "hello", 5));
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
net::TestCompletionCallback cb;
scoped_ptr<disk_cache::Backend> backend;
int rv =
disk_cache::CreateCacheBackend(net::DISK_CACHE,
net::CACHE_BACKEND_BLOCKFILE,
cache_path_,
0,
false,
cache_thread.message_loop_proxy().get(),
NULL,
&backend,
cb.callback());
ASSERT_NE(net::OK, cb.GetResult(rv));
ASSERT_FALSE(backend);
}
#endif
void DiskCacheBackendTest::BackendSetSize() {
const int cache_size = 0x10000;
SetMaxSize(cache_size);
InitCache();
std::string first("some key");
std::string second("something else");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(cache_size));
memset(buffer->data(), 0, cache_size);
EXPECT_EQ(cache_size / 10,
WriteData(entry, 0, 0, buffer.get(), cache_size / 10, false))
<< "normal file";
EXPECT_EQ(net::ERR_FAILED,
WriteData(entry, 1, 0, buffer.get(), cache_size / 5, false))
<< "file size above the limit";
SetMaxSize(cache_size * 2);
EXPECT_EQ(cache_size / 5,
WriteData(entry, 1, 0, buffer.get(), cache_size / 5, false));
SetMaxSize(cache_size * 10);
EXPECT_EQ(cache_size * 3 / 4,
WriteData(entry, 0, 0, buffer.get(), cache_size * 3 / 4, false));
entry->Close();
FlushQueueForTest();
SetMaxSize(cache_size);
ASSERT_EQ(net::OK, CreateEntry(second, &entry));
EXPECT_EQ(cache_size / 10,
WriteData(entry, 0, 0, buffer.get(), cache_size / 10, false));
disk_cache::Entry* entry2;
ASSERT_EQ(net::OK, CreateEntry("an extra key", &entry2));
EXPECT_EQ(cache_size / 10,
WriteData(entry2, 0, 0, buffer.get(), cache_size / 10, false));
entry2->Close();
EXPECT_NE(net::OK, OpenEntry(first, &entry2));
FlushQueueForTest();
FlushQueueForTest();
entry->Close();
ASSERT_EQ(net::OK, OpenEntry(second, &entry));
EXPECT_EQ(cache_size / 10, entry->GetDataSize(0));
entry->Close();
}
TEST_F(DiskCacheBackendTest, SetSize) {
BackendSetSize();
}
TEST_F(DiskCacheBackendTest, NewEvictionSetSize) {
SetNewEviction();
BackendSetSize();
}
TEST_F(DiskCacheBackendTest, MemoryOnlySetSize) {
SetMemoryOnlyMode();
BackendSetSize();
}
void DiskCacheBackendTest::BackendLoad() {
InitCache();
int seed = static_cast<int>(Time::Now().ToInternalValue());
srand(seed);
disk_cache::Entry* entries[100];
for (int i = 0; i < 100; i++) {
std::string key = GenerateKey(true);
ASSERT_EQ(net::OK, CreateEntry(key, &entries[i]));
}
EXPECT_EQ(100, cache_->GetEntryCount());
for (int i = 0; i < 100; i++) {
int source1 = rand() % 100;
int source2 = rand() % 100;
disk_cache::Entry* temp = entries[source1];
entries[source1] = entries[source2];
entries[source2] = temp;
}
for (int i = 0; i < 100; i++) {
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, OpenEntry(entries[i]->GetKey(), &entry));
EXPECT_TRUE(entry == entries[i]);
entry->Close();
entries[i]->Doom();
entries[i]->Close();
}
FlushQueueForTest();
EXPECT_EQ(0, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, Load) {
SetMask(0xf);
SetMaxSize(0x100000);
BackendLoad();
}
TEST_F(DiskCacheBackendTest, NewEvictionLoad) {
SetNewEviction();
SetMask(0xf);
SetMaxSize(0x100000);
BackendLoad();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyLoad) {
SetMaxSize(0x100000);
SetMemoryOnlyMode();
BackendLoad();
}
TEST_F(DiskCacheBackendTest, AppCacheLoad) {
SetCacheType(net::APP_CACHE);
SetMask(0xf);
SetMaxSize(0x100000);
BackendLoad();
}
TEST_F(DiskCacheBackendTest, ShaderCacheLoad) {
SetCacheType(net::SHADER_CACHE);
SetMask(0xf);
SetMaxSize(0x100000);
BackendLoad();
}
void DiskCacheBackendTest::BackendChain() {
SetMask(0x1);
SetMaxSize(0x3000);
InitCache();
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry("The first key", &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry("The Second key", &entry));
entry->Close();
}
TEST_F(DiskCacheBackendTest, Chain) {
BackendChain();
}
TEST_F(DiskCacheBackendTest, NewEvictionChain) {
SetNewEviction();
BackendChain();
}
TEST_F(DiskCacheBackendTest, AppCacheChain) {
SetCacheType(net::APP_CACHE);
BackendChain();
}
TEST_F(DiskCacheBackendTest, ShaderCacheChain) {
SetCacheType(net::SHADER_CACHE);
BackendChain();
}
TEST_F(DiskCacheBackendTest, NewEvictionTrim) {
SetNewEviction();
InitCache();
disk_cache::Entry* entry;
for (int i = 0; i < 100; i++) {
std::string name(base::StringPrintf("Key %d", i));
ASSERT_EQ(net::OK, CreateEntry(name, &entry));
entry->Close();
if (i < 90) {
ASSERT_EQ(net::OK, OpenEntry(name, &entry));
entry->Close();
}
}
TrimForTest(false);
EXPECT_NE(net::OK, OpenEntry("Key 0", &entry));
TrimForTest(false);
EXPECT_NE(net::OK, OpenEntry("Key 90", &entry));
ASSERT_EQ(net::OK, OpenEntry("Key 1", &entry));
entry->Close();
ASSERT_EQ(net::OK, OpenEntry("Key 91", &entry));
entry->Close();
}
void DiskCacheBackendTest::BackendValidEntry() {
InitCache();
std::string key("Some key");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
memset(buffer1->data(), 0, kSize);
base::strlcpy(buffer1->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer1.get(), kSize, false));
entry->Close();
SimulateCrash();
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
memset(buffer2->data(), 0, kSize);
EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer2.get(), kSize));
entry->Close();
EXPECT_STREQ(buffer1->data(), buffer2->data());
}
TEST_F(DiskCacheBackendTest, ValidEntry) {
BackendValidEntry();
}
TEST_F(DiskCacheBackendTest, NewEvictionValidEntry) {
SetNewEviction();
BackendValidEntry();
}
void DiskCacheBackendTest::BackendInvalidEntry() {
InitCache();
std::string key("Some key");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 0, kSize);
base::strlcpy(buffer->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
SimulateCrash();
EXPECT_NE(net::OK, OpenEntry(key, &entry));
EXPECT_EQ(0, cache_->GetEntryCount());
}
#if !defined(LEAK_SANITIZER)
TEST_F(DiskCacheBackendTest, InvalidEntry) {
BackendInvalidEntry();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry) {
SetNewEviction();
BackendInvalidEntry();
}
TEST_F(DiskCacheBackendTest, AppCacheInvalidEntry) {
SetCacheType(net::APP_CACHE);
BackendInvalidEntry();
}
TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntry) {
SetCacheType(net::SHADER_CACHE);
BackendInvalidEntry();
}
void DiskCacheBackendTest::BackendInvalidEntryRead() {
InitCache();
std::string key("Some key");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 0, kSize);
base::strlcpy(buffer->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
entry->Close();
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
EXPECT_EQ(kSize, ReadData(entry, 0, 0, buffer.get(), kSize));
SimulateCrash();
if (type_ == net::APP_CACHE) {
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
EXPECT_EQ(1, cache_->GetEntryCount());
entry->Close();
} else {
EXPECT_NE(net::OK, OpenEntry(key, &entry));
EXPECT_EQ(0, cache_->GetEntryCount());
}
}
TEST_F(DiskCacheBackendTest, InvalidEntryRead) {
BackendInvalidEntryRead();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryRead) {
SetNewEviction();
BackendInvalidEntryRead();
}
TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryRead) {
SetCacheType(net::APP_CACHE);
BackendInvalidEntryRead();
}
TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntryRead) {
SetCacheType(net::SHADER_CACHE);
BackendInvalidEntryRead();
}
void DiskCacheBackendTest::BackendInvalidEntryWithLoad() {
SetMask(0xf);
SetMaxSize(0x100000);
InitCache();
int seed = static_cast<int>(Time::Now().ToInternalValue());
srand(seed);
const int kNumEntries = 100;
disk_cache::Entry* entries[kNumEntries];
for (int i = 0; i < kNumEntries; i++) {
std::string key = GenerateKey(true);
ASSERT_EQ(net::OK, CreateEntry(key, &entries[i]));
}
EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
for (int i = 0; i < kNumEntries; i++) {
int source1 = rand() % kNumEntries;
int source2 = rand() % kNumEntries;
disk_cache::Entry* temp = entries[source1];
entries[source1] = entries[source2];
entries[source2] = temp;
}
std::string keys[kNumEntries];
for (int i = 0; i < kNumEntries; i++) {
keys[i] = entries[i]->GetKey();
if (i < kNumEntries / 2)
entries[i]->Close();
}
SimulateCrash();
for (int i = kNumEntries / 2; i < kNumEntries; i++) {
disk_cache::Entry* entry;
EXPECT_NE(net::OK, OpenEntry(keys[i], &entry));
}
for (int i = 0; i < kNumEntries / 2; i++) {
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, OpenEntry(keys[i], &entry));
entry->Close();
}
EXPECT_EQ(kNumEntries / 2, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, InvalidEntryWithLoad) {
BackendInvalidEntryWithLoad();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryWithLoad) {
SetNewEviction();
BackendInvalidEntryWithLoad();
}
TEST_F(DiskCacheBackendTest, AppCacheInvalidEntryWithLoad) {
SetCacheType(net::APP_CACHE);
BackendInvalidEntryWithLoad();
}
TEST_F(DiskCacheBackendTest, ShaderCacheInvalidEntryWithLoad) {
SetCacheType(net::SHADER_CACHE);
BackendInvalidEntryWithLoad();
}
void DiskCacheBackendTest::BackendTrimInvalidEntry() {
const int kSize = 0x3000;
SetMaxSize(kSize * 10);
InitCache();
std::string first("some key");
std::string second("something else");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 0, kSize);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
SimulateCrash();
ASSERT_EQ(net::OK, CreateEntry(second, &entry));
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
EXPECT_EQ(2, cache_->GetEntryCount());
SetMaxSize(kSize);
entry->Close();
FlushQueueForTest();
base::MessageLoop::current()->RunUntilIdle();
ANNOTATE_IGNORE_READS_BEGIN();
EXPECT_GE(1, cache_->GetEntryCount());
ANNOTATE_IGNORE_READS_END();
EXPECT_NE(net::OK, OpenEntry(first, &entry));
}
TEST_F(DiskCacheBackendTest, TrimInvalidEntry) {
BackendTrimInvalidEntry();
}
TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry) {
SetNewEviction();
BackendTrimInvalidEntry();
}
void DiskCacheBackendTest::BackendTrimInvalidEntry2() {
SetMask(0xf);
const int kSize = 0x3000;
SetMaxSize(kSize * 40);
InitCache();
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 0, kSize);
disk_cache::Entry* entry;
for (int i = 0; i < 32; i++) {
std::string key(base::StringPrintf("some key %d", i));
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
entry->Close();
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
}
SimulateCrash();
ASSERT_EQ(net::OK, CreateEntry("Something else", &entry));
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, false));
FlushQueueForTest();
EXPECT_EQ(33, cache_->GetEntryCount());
SetMaxSize(kSize);
if (new_eviction_) {
EXPECT_EQ(net::OK, DoomAllEntries());
}
entry->Close();
FlushQueueForTest();
base::MessageLoop::current()->RunUntilIdle();
FlushQueueForTest();
ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
EXPECT_GE(30, cache_->GetEntryCount());
ANNOTATE_IGNORE_READS_AND_WRITES_END();
}
TEST_F(DiskCacheBackendTest, TrimInvalidEntry2) {
BackendTrimInvalidEntry2();
}
TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry2) {
SetNewEviction();
BackendTrimInvalidEntry2();
}
#endif
void DiskCacheBackendTest::BackendEnumerations() {
InitCache();
Time initial = Time::Now();
const int kNumEntries = 100;
for (int i = 0; i < kNumEntries; i++) {
std::string key = GenerateKey(true);
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
entry->Close();
}
EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
Time final = Time::Now();
disk_cache::Entry* entry;
void* iter = NULL;
int count = 0;
Time last_modified[kNumEntries];
Time last_used[kNumEntries];
while (OpenNextEntry(&iter, &entry) == net::OK) {
ASSERT_TRUE(NULL != entry);
if (count < kNumEntries) {
last_modified[count] = entry->GetLastModified();
last_used[count] = entry->GetLastUsed();
EXPECT_TRUE(initial <= last_modified[count]);
EXPECT_TRUE(final >= last_modified[count]);
}
entry->Close();
count++;
};
EXPECT_EQ(kNumEntries, count);
iter = NULL;
count = 0;
while (OpenNextEntry(&iter, &entry) == net::OK) {
ASSERT_TRUE(NULL != entry);
if (count < kNumEntries) {
EXPECT_TRUE(last_modified[count] == entry->GetLastModified());
EXPECT_TRUE(last_used[count] == entry->GetLastUsed());
}
entry->Close();
count++;
};
EXPECT_EQ(kNumEntries, count);
}
TEST_F(DiskCacheBackendTest, Enumerations) {
BackendEnumerations();
}
TEST_F(DiskCacheBackendTest, NewEvictionEnumerations) {
SetNewEviction();
BackendEnumerations();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations) {
SetMemoryOnlyMode();
BackendEnumerations();
}
TEST_F(DiskCacheBackendTest, ShaderCacheEnumerations) {
SetCacheType(net::SHADER_CACHE);
BackendEnumerations();
}
TEST_F(DiskCacheBackendTest, AppCacheEnumerations) {
SetCacheType(net::APP_CACHE);
BackendEnumerations();
}
void DiskCacheBackendTest::BackendEnumerations2() {
InitCache();
const std::string first("first");
const std::string second("second");
disk_cache::Entry *entry1, *entry2;
ASSERT_EQ(net::OK, CreateEntry(first, &entry1));
entry1->Close();
ASSERT_EQ(net::OK, CreateEntry(second, &entry2));
entry2->Close();
FlushQueueForTest();
AddDelay();
ASSERT_EQ(net::OK, OpenEntry(second, &entry1));
void* iter = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
EXPECT_EQ(entry2->GetKey(), second);
entry1->Close();
entry2->Close();
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
EXPECT_EQ(entry2->GetKey(), first);
entry2->Close();
cache_->EndEnumeration(&iter);
ASSERT_EQ(net::OK, OpenEntry(first, &entry1));
EXPECT_EQ(0, WriteData(entry1, 0, 200, NULL, 0, false));
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
if (type_ == net::APP_CACHE) {
EXPECT_EQ(entry2->GetKey(), second);
} else {
EXPECT_EQ(entry2->GetKey(), first);
}
entry1->Close();
entry2->Close();
cache_->EndEnumeration(&iter);
}
TEST_F(DiskCacheBackendTest, Enumerations2) {
BackendEnumerations2();
}
TEST_F(DiskCacheBackendTest, NewEvictionEnumerations2) {
SetNewEviction();
BackendEnumerations2();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyEnumerations2) {
SetMemoryOnlyMode();
BackendEnumerations2();
}
TEST_F(DiskCacheBackendTest, AppCacheEnumerations2) {
SetCacheType(net::APP_CACHE);
BackendEnumerations2();
}
TEST_F(DiskCacheBackendTest, ShaderCacheEnumerations2) {
SetCacheType(net::SHADER_CACHE);
BackendEnumerations2();
}
TEST_F(DiskCacheBackendTest, ShaderCacheEnumerationReadData) {
SetCacheType(net::SHADER_CACHE);
InitCache();
const std::string first("first");
const std::string second("second");
disk_cache::Entry *entry1, *entry2;
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
ASSERT_EQ(net::OK, CreateEntry(first, &entry1));
memset(buffer1->data(), 0, kSize);
base::strlcpy(buffer1->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1.get(), kSize, false));
ASSERT_EQ(net::OK, CreateEntry(second, &entry2));
entry2->Close();
FlushQueueForTest();
AddDelay();
EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1.get(), kSize));
entry1->Close();
void* iter = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2));
EXPECT_EQ(entry2->GetKey(), second);
entry2->Close();
cache_->EndEnumeration(&iter);
}
#if !defined(LEAK_SANITIZER)
void DiskCacheBackendTest::BackendInvalidEntryEnumeration() {
InitCache();
std::string key("Some key");
disk_cache::Entry *entry, *entry1, *entry2;
ASSERT_EQ(net::OK, CreateEntry(key, &entry1));
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
memset(buffer1->data(), 0, kSize);
base::strlcpy(buffer1->data(), "And the data to save", kSize);
EXPECT_EQ(kSize, WriteData(entry1, 0, 0, buffer1.get(), kSize, false));
entry1->Close();
ASSERT_EQ(net::OK, OpenEntry(key, &entry1));
EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1.get(), kSize));
std::string key2("Another key");
ASSERT_EQ(net::OK, CreateEntry(key2, &entry2));
entry2->Close();
ASSERT_EQ(2, cache_->GetEntryCount());
SimulateCrash();
void* iter = NULL;
int count = 0;
while (OpenNextEntry(&iter, &entry) == net::OK) {
ASSERT_TRUE(NULL != entry);
EXPECT_EQ(key2, entry->GetKey());
entry->Close();
count++;
};
EXPECT_EQ(1, count);
EXPECT_EQ(1, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, InvalidEntryEnumeration) {
BackendInvalidEntryEnumeration();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntryEnumeration) {
SetNewEviction();
BackendInvalidEntryEnumeration();
}
#endif
void DiskCacheBackendTest::BackendFixEnumerators() {
InitCache();
int seed = static_cast<int>(Time::Now().ToInternalValue());
srand(seed);
const int kNumEntries = 10;
for (int i = 0; i < kNumEntries; i++) {
std::string key = GenerateKey(true);
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
entry->Close();
}
EXPECT_EQ(kNumEntries, cache_->GetEntryCount());
disk_cache::Entry *entry1, *entry2;
void* iter1 = NULL;
void* iter2 = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1));
ASSERT_TRUE(NULL != entry1);
entry1->Close();
entry1 = NULL;
for (int i = 0; i < kNumEntries / 2; i++) {
if (entry1)
entry1->Close();
ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1));
ASSERT_TRUE(NULL != entry1);
ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
ASSERT_TRUE(NULL != entry2);
entry2->Close();
}
entry1->Doom();
ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
ASSERT_TRUE(NULL != entry2);
EXPECT_NE(entry2->GetKey(), entry1->GetKey());
entry1->Close();
entry2->Close();
ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2));
ASSERT_TRUE(NULL != entry2);
entry2->Close();
cache_->EndEnumeration(&iter1);
cache_->EndEnumeration(&iter2);
}
TEST_F(DiskCacheBackendTest, FixEnumerators) {
BackendFixEnumerators();
}
TEST_F(DiskCacheBackendTest, NewEvictionFixEnumerators) {
SetNewEviction();
BackendFixEnumerators();
}
void DiskCacheBackendTest::BackendDoomRecent() {
InitCache();
disk_cache::Entry *entry;
ASSERT_EQ(net::OK, CreateEntry("first", &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry("second", &entry));
entry->Close();
FlushQueueForTest();
AddDelay();
Time middle = Time::Now();
ASSERT_EQ(net::OK, CreateEntry("third", &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
entry->Close();
FlushQueueForTest();
AddDelay();
Time final = Time::Now();
ASSERT_EQ(4, cache_->GetEntryCount());
EXPECT_EQ(net::OK, DoomEntriesSince(final));
ASSERT_EQ(4, cache_->GetEntryCount());
EXPECT_EQ(net::OK, DoomEntriesSince(middle));
ASSERT_EQ(2, cache_->GetEntryCount());
ASSERT_EQ(net::OK, OpenEntry("second", &entry));
entry->Close();
}
TEST_F(DiskCacheBackendTest, DoomRecent) {
BackendDoomRecent();
}
TEST_F(DiskCacheBackendTest, NewEvictionDoomRecent) {
SetNewEviction();
BackendDoomRecent();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyDoomRecent) {
SetMemoryOnlyMode();
BackendDoomRecent();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyDoomEntriesSinceSparse) {
SetMemoryOnlyMode();
base::Time start;
InitSparseCache(&start, NULL);
DoomEntriesSince(start);
EXPECT_EQ(1, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, DoomEntriesSinceSparse) {
base::Time start;
InitSparseCache(&start, NULL);
DoomEntriesSince(start);
EXPECT_EQ(3, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAllSparse) {
SetMemoryOnlyMode();
InitSparseCache(NULL, NULL);
EXPECT_EQ(net::OK, DoomAllEntries());
EXPECT_EQ(0, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, DoomAllSparse) {
InitSparseCache(NULL, NULL);
EXPECT_EQ(net::OK, DoomAllEntries());
EXPECT_EQ(0, cache_->GetEntryCount());
}
void DiskCacheBackendTest::BackendDoomBetween() {
InitCache();
disk_cache::Entry *entry;
ASSERT_EQ(net::OK, CreateEntry("first", &entry));
entry->Close();
FlushQueueForTest();
AddDelay();
Time middle_start = Time::Now();
ASSERT_EQ(net::OK, CreateEntry("second", &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry("third", &entry));
entry->Close();
FlushQueueForTest();
AddDelay();
Time middle_end = Time::Now();
AddDelay();
ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
entry->Close();
ASSERT_EQ(net::OK, OpenEntry("fourth", &entry));
entry->Close();
FlushQueueForTest();
AddDelay();
Time final = Time::Now();
ASSERT_EQ(4, cache_->GetEntryCount());
EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, middle_end));
ASSERT_EQ(2, cache_->GetEntryCount());
ASSERT_EQ(net::OK, OpenEntry("fourth", &entry));
entry->Close();
EXPECT_EQ(net::OK, DoomEntriesBetween(middle_start, final));
ASSERT_EQ(1, cache_->GetEntryCount());
ASSERT_EQ(net::OK, OpenEntry("first", &entry));
entry->Close();
}
TEST_F(DiskCacheBackendTest, DoomBetween) {
BackendDoomBetween();
}
TEST_F(DiskCacheBackendTest, NewEvictionDoomBetween) {
SetNewEviction();
BackendDoomBetween();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyDoomBetween) {
SetMemoryOnlyMode();
BackendDoomBetween();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyDoomEntriesBetweenSparse) {
SetMemoryOnlyMode();
base::Time start, end;
InitSparseCache(&start, &end);
DoomEntriesBetween(start, end);
EXPECT_EQ(3, cache_->GetEntryCount());
start = end;
end = base::Time::Now();
DoomEntriesBetween(start, end);
EXPECT_EQ(1, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, DoomEntriesBetweenSparse) {
base::Time start, end;
InitSparseCache(&start, &end);
DoomEntriesBetween(start, end);
EXPECT_EQ(9, cache_->GetEntryCount());
start = end;
end = base::Time::Now();
DoomEntriesBetween(start, end);
EXPECT_EQ(3, cache_->GetEntryCount());
}
void DiskCacheBackendTest::BackendTransaction(const std::string& name,
int num_entries, bool load) {
success_ = false;
ASSERT_TRUE(CopyTestCache(name));
DisableFirstCleanup();
uint32 mask;
if (load) {
mask = 0xf;
SetMaxSize(0x100000);
} else {
mask = 0;
SetMaxSize(0);
}
SetMask(mask);
InitCache();
ASSERT_EQ(num_entries + 1, cache_->GetEntryCount());
std::string key("the first key");
disk_cache::Entry* entry1;
ASSERT_NE(net::OK, OpenEntry(key, &entry1));
int actual = cache_->GetEntryCount();
if (num_entries != actual) {
ASSERT_TRUE(load);
ASSERT_EQ(num_entries - 1, actual);
}
cache_.reset();
cache_impl_ = NULL;
ASSERT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask));
success_ = true;
}
void DiskCacheBackendTest::BackendRecoverInsert() {
BackendTransaction("insert_empty1", 0, false);
ASSERT_TRUE(success_) << "insert_empty1";
BackendTransaction("insert_empty2", 0, false);
ASSERT_TRUE(success_) << "insert_empty2";
BackendTransaction("insert_empty3", 0, false);
ASSERT_TRUE(success_) << "insert_empty3";
BackendTransaction("insert_one1", 1, false);
ASSERT_TRUE(success_) << "insert_one1";
BackendTransaction("insert_one2", 1, false);
ASSERT_TRUE(success_) << "insert_one2";
BackendTransaction("insert_one3", 1, false);
ASSERT_TRUE(success_) << "insert_one3";
BackendTransaction("insert_load1", 100, true);
ASSERT_TRUE(success_) << "insert_load1";
BackendTransaction("insert_load2", 100, true);
ASSERT_TRUE(success_) << "insert_load2";
}
TEST_F(DiskCacheBackendTest, RecoverInsert) {
BackendRecoverInsert();
}
TEST_F(DiskCacheBackendTest, NewEvictionRecoverInsert) {
SetNewEviction();
BackendRecoverInsert();
}
void DiskCacheBackendTest::BackendRecoverRemove() {
BackendTransaction("remove_one1", 0, false);
ASSERT_TRUE(success_) << "remove_one1";
BackendTransaction("remove_one2", 0, false);
ASSERT_TRUE(success_) << "remove_one2";
BackendTransaction("remove_one3", 0, false);
ASSERT_TRUE(success_) << "remove_one3";
BackendTransaction("remove_head1", 1, false);
ASSERT_TRUE(success_) << "remove_head1";
BackendTransaction("remove_head2", 1, false);
ASSERT_TRUE(success_) << "remove_head2";
BackendTransaction("remove_head3", 1, false);
ASSERT_TRUE(success_) << "remove_head3";
BackendTransaction("remove_tail1", 1, false);
ASSERT_TRUE(success_) << "remove_tail1";
BackendTransaction("remove_tail2", 1, false);
ASSERT_TRUE(success_) << "remove_tail2";
BackendTransaction("remove_tail3", 1, false);
ASSERT_TRUE(success_) << "remove_tail3";
BackendTransaction("remove_load1", 100, true);
ASSERT_TRUE(success_) << "remove_load1";
BackendTransaction("remove_load2", 100, true);
ASSERT_TRUE(success_) << "remove_load2";
BackendTransaction("remove_load3", 100, true);
ASSERT_TRUE(success_) << "remove_load3";
BackendTransaction("remove_one4", 0, false);
ASSERT_TRUE(success_) << "remove_one4";
BackendTransaction("remove_head4", 1, false);
ASSERT_TRUE(success_) << "remove_head4";
}
TEST_F(DiskCacheBackendTest, RecoverRemove) {
BackendRecoverRemove();
}
TEST_F(DiskCacheBackendTest, NewEvictionRecoverRemove) {
SetNewEviction();
BackendRecoverRemove();
}
void DiskCacheBackendTest::BackendRecoverWithEviction() {
success_ = false;
ASSERT_TRUE(CopyTestCache("insert_load1"));
DisableFirstCleanup();
SetMask(0xf);
SetMaxSize(0x1000);
InitCache();
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, RecoverWithEviction) {
BackendRecoverWithEviction();
}
TEST_F(DiskCacheBackendTest, NewEvictionRecoverWithEviction) {
SetNewEviction();
BackendRecoverWithEviction();
}
TEST_F(DiskCacheTest, WrongVersion) {
ASSERT_TRUE(CopyTestCache("wrong_version"));
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
net::TestCompletionCallback cb;
scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
cache_path_, cache_thread.message_loop_proxy().get(), NULL));
int rv = cache->Init(cb.callback());
ASSERT_EQ(net::ERR_FAILED, cb.GetResult(rv));
}
class BadEntropyProvider : public base::FieldTrial::EntropyProvider {
public:
virtual ~BadEntropyProvider() {}
virtual double GetEntropyForTrial(const std::string& trial_name,
uint32 randomization_seed) const OVERRIDE {
return 0.5;
}
};
#if !defined(OS_ANDROID)
TEST_F(DiskCacheTest, SimpleCacheControlJoin) {
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
scoped_ptr<disk_cache::BackendImpl> cache =
CreateExistingEntryCache(cache_thread, cache_path_);
ASSERT_TRUE(cache.get());
cache.reset();
base::FieldTrialList field_trial_list(new BadEntropyProvider());
base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial",
"ExperimentControl");
net::TestCompletionCallback cb;
scoped_ptr<disk_cache::Backend> base_cache;
int rv =
disk_cache::CreateCacheBackend(net::DISK_CACHE,
net::CACHE_BACKEND_BLOCKFILE,
cache_path_,
0,
true,
cache_thread.message_loop_proxy().get(),
NULL,
&base_cache,
cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
EXPECT_EQ(0, base_cache->GetEntryCount());
}
#endif
TEST_F(DiskCacheTest, SimpleCacheControlRestart) {
base::FieldTrialList field_trial_list(new BadEntropyProvider());
base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial",
"ExperimentControl");
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
scoped_ptr<disk_cache::BackendImpl> cache =
CreateExistingEntryCache(cache_thread, cache_path_);
ASSERT_TRUE(cache.get());
net::TestCompletionCallback cb;
const int kRestartCount = 5;
for (int i = 0; i < kRestartCount; ++i) {
cache.reset(new disk_cache::BackendImpl(
cache_path_, cache_thread.message_loop_proxy(), NULL));
int rv = cache->Init(cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
EXPECT_EQ(1, cache->GetEntryCount());
disk_cache::Entry* entry = NULL;
rv = cache->OpenEntry(kExistingEntryKey, &entry, cb.callback());
EXPECT_EQ(net::OK, cb.GetResult(rv));
EXPECT_TRUE(entry);
entry->Close();
}
}
TEST_F(DiskCacheTest, SimpleCacheControlLeave) {
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
{
base::FieldTrialList field_trial_list(new BadEntropyProvider());
base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial",
"ExperimentControl");
scoped_ptr<disk_cache::BackendImpl> cache =
CreateExistingEntryCache(cache_thread, cache_path_);
ASSERT_TRUE(cache.get());
}
base::FieldTrialList field_trial_list(new BadEntropyProvider());
base::FieldTrialList::CreateFieldTrial("SimpleCacheTrial", "ExperimentNo");
net::TestCompletionCallback cb;
const int kRestartCount = 5;
for (int i = 0; i < kRestartCount; ++i) {
scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
cache_path_, cache_thread.message_loop_proxy(), NULL));
int rv = cache->Init(cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
EXPECT_EQ(1, cache->GetEntryCount());
disk_cache::Entry* entry = NULL;
rv = cache->OpenEntry(kExistingEntryKey, &entry, cb.callback());
EXPECT_EQ(net::OK, cb.GetResult(rv));
EXPECT_TRUE(entry);
entry->Close();
}
}
#if !defined(OS_ANDROID)
TEST_F(DiskCacheBackendTest, DeleteOld) {
ASSERT_TRUE(CopyTestCache("wrong_version"));
SetNewEviction();
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
net::TestCompletionCallback cb;
bool prev = base::ThreadRestrictions::SetIOAllowed(false);
base::FilePath path(cache_path_);
int rv =
disk_cache::CreateCacheBackend(net::DISK_CACHE,
net::CACHE_BACKEND_BLOCKFILE,
path,
0,
true,
cache_thread.message_loop_proxy().get(),
NULL,
&cache_,
cb.callback());
path.clear();
ASSERT_EQ(net::OK, cb.GetResult(rv));
base::ThreadRestrictions::SetIOAllowed(prev);
cache_.reset();
EXPECT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask_));
}
#endif
void DiskCacheBackendTest::BackendInvalidEntry2() {
ASSERT_TRUE(CopyTestCache("bad_entry"));
DisableFirstCleanup();
InitCache();
disk_cache::Entry *entry1, *entry2;
ASSERT_EQ(net::OK, OpenEntry("the first key", &entry1));
EXPECT_NE(net::OK, OpenEntry("some other key", &entry2));
entry1->Close();
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, InvalidEntry2) {
BackendInvalidEntry2();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry2) {
SetNewEviction();
BackendInvalidEntry2();
}
void DiskCacheBackendTest::BackendInvalidEntry3() {
SetMask(0x1);
SetMaxSize(0x3000);
DisableFirstCleanup();
InitCache();
disk_cache::Entry* entry;
void* iter = NULL;
while (OpenNextEntry(&iter, &entry) == net::OK) {
entry->Close();
}
}
TEST_F(DiskCacheBackendTest, InvalidEntry3) {
ASSERT_TRUE(CopyTestCache("dirty_entry3"));
BackendInvalidEntry3();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry3) {
ASSERT_TRUE(CopyTestCache("dirty_entry4"));
SetNewEviction();
BackendInvalidEntry3();
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, InvalidEntry4) {
ASSERT_TRUE(CopyTestCache("dirty_entry3"));
SetMask(0x1);
SetMaxSize(0x3000);
DisableFirstCleanup();
InitCache();
TrimForTest(false);
}
TEST_F(DiskCacheBackendTest, InvalidEntry5) {
ASSERT_TRUE(CopyTestCache("dirty_entry4"));
SetNewEviction();
SetMask(0x1);
SetMaxSize(0x3000);
DisableFirstCleanup();
InitCache();
TrimDeletedListForTest(false);
}
TEST_F(DiskCacheBackendTest, InvalidEntry6) {
ASSERT_TRUE(CopyTestCache("dirty_entry5"));
SetMask(0x1);
SetMaxSize(0x3000);
DisableFirstCleanup();
InitCache();
TrimForTest(false);
}
TEST_F(DiskCacheBackendTest, BadNextEntry1) {
ASSERT_TRUE(CopyTestCache("list_loop2"));
SetMask(0x1);
SetMaxSize(0x3000);
DisableFirstCleanup();
InitCache();
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry("The first key", &entry));
entry->Close();
TrimForTest(false);
TrimForTest(false);
ASSERT_EQ(net::OK, OpenEntry("The first key", &entry));
entry->Close();
EXPECT_EQ(1, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, BadNextEntry2) {
ASSERT_TRUE(CopyTestCache("list_loop3"));
SetMask(0x1);
SetMaxSize(0x3000);
DisableFirstCleanup();
InitCache();
disk_cache::Entry* entry;
ASSERT_NE(net::OK, OpenEntry("Not present key", &entry));
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry6) {
ASSERT_TRUE(CopyTestCache("bad_rankings3"));
DisableFirstCleanup();
SetNewEviction();
InitCache();
disk_cache::Entry* entry;
ASSERT_NE(net::OK, OpenEntry("the second key", &entry));
ASSERT_EQ(net::OK, OpenEntry("the first key", &entry));
entry->Doom();
FlushQueueForTest();
entry->Close();
ASSERT_EQ(net::OK, OpenEntry("some other key", &entry));
entry->Close();
}
void DiskCacheBackendTest::BackendInvalidEntry7() {
const int kSize = 0x3000;
SetMaxSize(kSize * 10);
InitCache();
std::string first("some key");
std::string second("something else");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry(second, &entry));
disk_cache::EntryImpl* entry_impl =
static_cast<disk_cache::EntryImpl*>(entry);
entry_impl->rankings()->Data()->next = 0;
entry_impl->rankings()->Store();
entry->Close();
FlushQueueForTest();
EXPECT_EQ(2, cache_->GetEntryCount());
EXPECT_NE(net::OK, OpenEntry(second, &entry));
EXPECT_EQ(1, cache_->GetEntryCount());
void* iter = NULL;
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
FlushQueueForTest();
EXPECT_EQ(0, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, InvalidEntry7) {
BackendInvalidEntry7();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry7) {
SetNewEviction();
BackendInvalidEntry7();
}
void DiskCacheBackendTest::BackendInvalidEntry8() {
const int kSize = 0x3000;
SetMaxSize(kSize * 10);
InitCache();
std::string first("some key");
std::string second("something else");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry(second, &entry));
disk_cache::EntryImpl* entry_impl =
static_cast<disk_cache::EntryImpl*>(entry);
entry_impl->rankings()->Data()->contents = 0;
entry_impl->rankings()->Store();
entry->Close();
FlushQueueForTest();
EXPECT_EQ(2, cache_->GetEntryCount());
EXPECT_NE(net::OK, OpenEntry(second, &entry));
EXPECT_EQ(1, cache_->GetEntryCount());
void* iter = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
entry->Close();
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
EXPECT_EQ(1, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, InvalidEntry8) {
BackendInvalidEntry8();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry8) {
SetNewEviction();
BackendInvalidEntry8();
}
void DiskCacheBackendTest::BackendInvalidEntry9(bool eviction) {
const int kSize = 0x3000;
SetMaxSize(kSize * 10);
InitCache();
std::string first("some key");
std::string second("something else");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry(second, &entry));
disk_cache::EntryImpl* entry_impl =
static_cast<disk_cache::EntryImpl*>(entry);
entry_impl->entry()->Data()->state = 0xbad;
entry_impl->entry()->Store();
entry->Close();
FlushQueueForTest();
EXPECT_EQ(2, cache_->GetEntryCount());
if (eviction) {
TrimForTest(false);
EXPECT_EQ(1, cache_->GetEntryCount());
TrimForTest(false);
EXPECT_EQ(1, cache_->GetEntryCount());
} else {
void* iter = NULL;
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
entry->Close();
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
EXPECT_NE(net::OK, OpenEntry(second, &entry));
EXPECT_EQ(2, cache_->GetEntryCount());
}
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, InvalidEntry9) {
BackendInvalidEntry9(false);
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidEntry9) {
SetNewEviction();
BackendInvalidEntry9(false);
}
TEST_F(DiskCacheBackendTest, TrimInvalidEntry9) {
BackendInvalidEntry9(true);
}
TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry9) {
SetNewEviction();
BackendInvalidEntry9(true);
}
void DiskCacheBackendTest::BackendInvalidEntry10(bool eviction) {
const int kSize = 0x3000;
SetMaxSize(kSize * 10);
SetNewEviction();
InitCache();
std::string first("some key");
std::string second("something else");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
entry->Close();
ASSERT_EQ(net::OK, OpenEntry(first, &entry));
EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry(second, &entry));
disk_cache::EntryImpl* entry_impl =
static_cast<disk_cache::EntryImpl*>(entry);
entry_impl->entry()->Data()->state = 0xbad;
entry_impl->entry()->Store();
entry->Close();
ASSERT_EQ(net::OK, CreateEntry("third", &entry));
entry->Close();
EXPECT_EQ(3, cache_->GetEntryCount());
if (eviction) {
TrimForTest(false);
EXPECT_EQ(3, cache_->GetEntryCount());
TrimForTest(false);
EXPECT_EQ(2, cache_->GetEntryCount());
TrimForTest(false);
EXPECT_EQ(1, cache_->GetEntryCount());
} else {
void* iter = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
entry->Close();
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
EXPECT_EQ(first, entry->GetKey());
entry->Close();
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
}
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, InvalidEntry10) {
BackendInvalidEntry10(false);
}
TEST_F(DiskCacheBackendTest, TrimInvalidEntry10) {
BackendInvalidEntry10(true);
}
void DiskCacheBackendTest::BackendInvalidEntry11(bool eviction) {
const int kSize = 0x3000;
SetMaxSize(kSize * 10);
SetNewEviction();
InitCache();
std::string first("some key");
std::string second("something else");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
entry->Close();
ASSERT_EQ(net::OK, OpenEntry(first, &entry));
EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry(second, &entry));
entry->Close();
ASSERT_EQ(net::OK, OpenEntry(second, &entry));
EXPECT_EQ(0, WriteData(entry, 0, 200, NULL, 0, false));
disk_cache::EntryImpl* entry_impl =
static_cast<disk_cache::EntryImpl*>(entry);
entry_impl->entry()->Data()->state = 0xbad;
entry_impl->entry()->Store();
entry->Close();
ASSERT_EQ(net::OK, CreateEntry("third", &entry));
entry->Close();
FlushQueueForTest();
EXPECT_EQ(3, cache_->GetEntryCount());
if (eviction) {
TrimForTest(false);
EXPECT_EQ(2, cache_->GetEntryCount());
TrimForTest(false);
EXPECT_EQ(1, cache_->GetEntryCount());
TrimForTest(false);
EXPECT_EQ(1, cache_->GetEntryCount());
} else {
void* iter = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
entry->Close();
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
entry->Close();
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
entry->Close();
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
}
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, InvalidEntry11) {
BackendInvalidEntry11(false);
}
TEST_F(DiskCacheBackendTest, TrimInvalidEntry11) {
BackendInvalidEntry11(true);
}
void DiskCacheBackendTest::BackendTrimInvalidEntry12() {
const int kSize = 0x3000;
SetMaxSize(kSize * 10);
InitCache();
std::string first("some key");
std::string second("something else");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(first, &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry(second, &entry));
disk_cache::EntryImpl* entry_impl =
static_cast<disk_cache::EntryImpl*>(entry);
entry_impl->entry()->Data()->state = 0xbad;
entry_impl->entry()->Store();
entry->Close();
ASSERT_EQ(net::OK, CreateEntry("third", &entry));
entry->Close();
ASSERT_EQ(net::OK, CreateEntry("fourth", &entry));
TrimForTest(true);
EXPECT_EQ(1, cache_->GetEntryCount());
entry->Close();
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, TrimInvalidEntry12) {
BackendTrimInvalidEntry12();
}
TEST_F(DiskCacheBackendTest, NewEvictionTrimInvalidEntry12) {
SetNewEviction();
BackendTrimInvalidEntry12();
}
void DiskCacheBackendTest::BackendInvalidRankings2() {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
InitCache();
disk_cache::Entry *entry1, *entry2;
EXPECT_NE(net::OK, OpenEntry("the first key", &entry1));
ASSERT_EQ(net::OK, OpenEntry("some other key", &entry2));
entry2->Close();
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, InvalidRankings2) {
BackendInvalidRankings2();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankings2) {
SetNewEviction();
BackendInvalidRankings2();
}
void DiskCacheBackendTest::BackendInvalidRankings() {
disk_cache::Entry* entry;
void* iter = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry));
entry->Close();
EXPECT_EQ(2, cache_->GetEntryCount());
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry));
FlushQueueForTest();
EXPECT_EQ(0, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, InvalidRankingsSuccess) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
InitCache();
BackendInvalidRankings();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsSuccess) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
SetNewEviction();
InitCache();
BackendInvalidRankings();
}
TEST_F(DiskCacheBackendTest, InvalidRankingsFailure) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
InitCache();
SetTestMode();
BackendInvalidRankings();
}
TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsFailure) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
SetNewEviction();
InitCache();
SetTestMode();
BackendInvalidRankings();
}
void DiskCacheBackendTest::BackendDisable() {
disk_cache::Entry *entry1, *entry2;
void* iter = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2));
EXPECT_EQ(0, cache_->GetEntryCount());
EXPECT_NE(net::OK, CreateEntry("Something new", &entry2));
entry1->Close();
FlushQueueForTest();
FlushQueueForTest();
EXPECT_EQ(0, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, DisableSuccess) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
InitCache();
BackendDisable();
}
TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
SetNewEviction();
InitCache();
BackendDisable();
}
TEST_F(DiskCacheBackendTest, DisableFailure) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
InitCache();
SetTestMode();
BackendDisable();
}
TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
SetNewEviction();
InitCache();
SetTestMode();
BackendDisable();
}
void DiskCacheBackendTest::BackendDisable2() {
EXPECT_EQ(8, cache_->GetEntryCount());
disk_cache::Entry* entry;
void* iter = NULL;
int count = 0;
while (OpenNextEntry(&iter, &entry) == net::OK) {
ASSERT_TRUE(NULL != entry);
entry->Close();
count++;
ASSERT_LT(count, 9);
};
FlushQueueForTest();
EXPECT_EQ(0, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, DisableSuccess2) {
ASSERT_TRUE(CopyTestCache("list_loop"));
DisableFirstCleanup();
InitCache();
BackendDisable2();
}
TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess2) {
ASSERT_TRUE(CopyTestCache("list_loop"));
DisableFirstCleanup();
SetNewEviction();
InitCache();
BackendDisable2();
}
TEST_F(DiskCacheBackendTest, DisableFailure2) {
ASSERT_TRUE(CopyTestCache("list_loop"));
DisableFirstCleanup();
InitCache();
SetTestMode();
BackendDisable2();
}
TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure2) {
ASSERT_TRUE(CopyTestCache("list_loop"));
DisableFirstCleanup();
SetNewEviction();
InitCache();
SetTestMode();
BackendDisable2();
}
void DiskCacheBackendTest::BackendDisable3() {
disk_cache::Entry *entry1, *entry2;
void* iter = NULL;
EXPECT_EQ(2, cache_->GetEntryCount());
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
entry1->Close();
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2));
FlushQueueForTest();
ASSERT_EQ(net::OK, CreateEntry("Something new", &entry2));
entry2->Close();
EXPECT_EQ(1, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, DisableSuccess3) {
ASSERT_TRUE(CopyTestCache("bad_rankings2"));
DisableFirstCleanup();
SetMaxSize(20 * 1024 * 1024);
InitCache();
BackendDisable3();
}
TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess3) {
ASSERT_TRUE(CopyTestCache("bad_rankings2"));
DisableFirstCleanup();
SetMaxSize(20 * 1024 * 1024);
SetNewEviction();
InitCache();
BackendDisable3();
}
void DiskCacheBackendTest::BackendDisable4() {
disk_cache::Entry *entry1, *entry2, *entry3, *entry4;
void* iter = NULL;
ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1));
char key2[2000];
char key3[20000];
CacheTestFillBuffer(key2, sizeof(key2), true);
CacheTestFillBuffer(key3, sizeof(key3), true);
key2[sizeof(key2) - 1] = '\0';
key3[sizeof(key3) - 1] = '\0';
ASSERT_EQ(net::OK, CreateEntry(key2, &entry2));
ASSERT_EQ(net::OK, CreateEntry(key3, &entry3));
const int kBufSize = 20000;
scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kBufSize));
memset(buf->data(), 0, kBufSize);
EXPECT_EQ(100, WriteData(entry2, 0, 0, buf.get(), 100, false));
EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf.get(), kBufSize, false));
EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry4));
EXPECT_EQ(0, cache_->GetEntryCount());
EXPECT_NE(net::OK, CreateEntry("cache is disabled", &entry4));
EXPECT_EQ(100, ReadData(entry2, 0, 0, buf.get(), 100));
EXPECT_EQ(100, WriteData(entry2, 0, 0, buf.get(), 100, false));
EXPECT_EQ(100, WriteData(entry2, 1, 0, buf.get(), 100, false));
EXPECT_EQ(kBufSize, ReadData(entry3, 0, 0, buf.get(), kBufSize));
EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf.get(), kBufSize, false));
EXPECT_EQ(kBufSize, WriteData(entry3, 1, 0, buf.get(), kBufSize, false));
std::string key = entry2->GetKey();
EXPECT_EQ(sizeof(key2) - 1, key.size());
key = entry3->GetKey();
EXPECT_EQ(sizeof(key3) - 1, key.size());
entry1->Close();
entry2->Close();
entry3->Close();
FlushQueueForTest();
FlushQueueForTest();
EXPECT_EQ(0, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, DisableSuccess4) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
InitCache();
BackendDisable4();
}
TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess4) {
ASSERT_TRUE(CopyTestCache("bad_rankings"));
DisableFirstCleanup();
SetNewEviction();
InitCache();
BackendDisable4();
}
TEST_F(DiskCacheTest, Backend_UsageStatsTimer) {
MessageLoopHelper helper;
ASSERT_TRUE(CleanupCacheDir());
scoped_ptr<disk_cache::BackendImpl> cache;
cache.reset(new disk_cache::BackendImpl(
cache_path_, base::MessageLoopProxy::current().get(), NULL));
ASSERT_TRUE(NULL != cache.get());
cache->SetUnitTestMode();
ASSERT_EQ(net::OK, cache->SyncInit());
helper.WaitUntilCacheIoFinished(1);
}
TEST_F(DiskCacheBackendTest, TimerNotCreated) {
ASSERT_TRUE(CopyTestCache("wrong_version"));
scoped_ptr<disk_cache::BackendImpl> cache;
cache.reset(new disk_cache::BackendImpl(
cache_path_, base::MessageLoopProxy::current().get(), NULL));
ASSERT_TRUE(NULL != cache.get());
cache->SetUnitTestMode();
ASSERT_NE(net::OK, cache->SyncInit());
ASSERT_TRUE(NULL == cache->GetTimerForTest());
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, Backend_UsageStats) {
InitCache();
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry("key", &entry));
entry->Close();
FlushQueueForTest();
disk_cache::StatsItems stats;
cache_->GetStats(&stats);
EXPECT_FALSE(stats.empty());
disk_cache::StatsItems::value_type hits("Create hit", "0x1");
EXPECT_EQ(1, std::count(stats.begin(), stats.end(), hits));
cache_.reset();
DisableFirstCleanup();
InitCache();
EXPECT_EQ(1, cache_->GetEntryCount());
stats.clear();
cache_->GetStats(&stats);
EXPECT_FALSE(stats.empty());
EXPECT_EQ(1, std::count(stats.begin(), stats.end(), hits));
}
void DiskCacheBackendTest::BackendDoomAll() {
InitCache();
disk_cache::Entry *entry1, *entry2;
ASSERT_EQ(net::OK, CreateEntry("first", &entry1));
ASSERT_EQ(net::OK, CreateEntry("second", &entry2));
entry1->Close();
entry2->Close();
ASSERT_EQ(net::OK, CreateEntry("third", &entry1));
ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2));
ASSERT_EQ(4, cache_->GetEntryCount());
EXPECT_EQ(net::OK, DoomAllEntries());
ASSERT_EQ(0, cache_->GetEntryCount());
base::MessageLoop::current()->RunUntilIdle();
disk_cache::Entry *entry3, *entry4;
EXPECT_NE(net::OK, OpenEntry("third", &entry3));
ASSERT_EQ(net::OK, CreateEntry("third", &entry3));
ASSERT_EQ(net::OK, CreateEntry("fourth", &entry4));
EXPECT_EQ(net::OK, DoomAllEntries());
ASSERT_EQ(0, cache_->GetEntryCount());
entry1->Close();
entry2->Close();
entry3->Doom();
entry3->Close();
entry4->Close();
ASSERT_EQ(net::OK, CreateEntry("third", &entry1));
ASSERT_EQ(net::OK, CreateEntry("fourth", &entry2));
entry1->Close();
entry2->Close();
ASSERT_EQ(2, cache_->GetEntryCount());
EXPECT_EQ(net::OK, DoomAllEntries());
ASSERT_EQ(0, cache_->GetEntryCount());
EXPECT_EQ(net::OK, DoomAllEntries());
}
TEST_F(DiskCacheBackendTest, DoomAll) {
BackendDoomAll();
}
TEST_F(DiskCacheBackendTest, NewEvictionDoomAll) {
SetNewEviction();
BackendDoomAll();
}
TEST_F(DiskCacheBackendTest, MemoryOnlyDoomAll) {
SetMemoryOnlyMode();
BackendDoomAll();
}
TEST_F(DiskCacheBackendTest, AppCacheOnlyDoomAll) {
SetCacheType(net::APP_CACHE);
BackendDoomAll();
}
TEST_F(DiskCacheBackendTest, ShaderCacheOnlyDoomAll) {
SetCacheType(net::SHADER_CACHE);
BackendDoomAll();
}
void DiskCacheBackendTest::BackendDoomAll2() {
EXPECT_EQ(2, cache_->GetEntryCount());
EXPECT_EQ(net::OK, DoomAllEntries());
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry("Something new", &entry));
entry->Close();
EXPECT_EQ(1, cache_->GetEntryCount());
}
TEST_F(DiskCacheBackendTest, DoomAll2) {
ASSERT_TRUE(CopyTestCache("bad_rankings2"));
DisableFirstCleanup();
SetMaxSize(20 * 1024 * 1024);
InitCache();
BackendDoomAll2();
}
TEST_F(DiskCacheBackendTest, NewEvictionDoomAll2) {
ASSERT_TRUE(CopyTestCache("bad_rankings2"));
DisableFirstCleanup();
SetMaxSize(20 * 1024 * 1024);
SetNewEviction();
InitCache();
BackendDoomAll2();
}
TEST_F(DiskCacheTest, MultipleInstances) {
base::ScopedTempDir store1, store2;
ASSERT_TRUE(store1.CreateUniqueTempDir());
ASSERT_TRUE(store2.CreateUniqueTempDir());
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
net::TestCompletionCallback cb;
const int kNumberOfCaches = 2;
scoped_ptr<disk_cache::Backend> cache[kNumberOfCaches];
int rv =
disk_cache::CreateCacheBackend(net::DISK_CACHE,
net::CACHE_BACKEND_DEFAULT,
store1.path(),
0,
false,
cache_thread.message_loop_proxy().get(),
NULL,
&cache[0],
cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
rv = disk_cache::CreateCacheBackend(net::MEDIA_CACHE,
net::CACHE_BACKEND_DEFAULT,
store2.path(),
0,
false,
cache_thread.message_loop_proxy().get(),
NULL,
&cache[1],
cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
ASSERT_TRUE(cache[0].get() != NULL && cache[1].get() != NULL);
std::string key("the first key");
disk_cache::Entry* entry;
for (int i = 0; i < kNumberOfCaches; i++) {
rv = cache[i]->CreateEntry(key, &entry, cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
entry->Close();
}
}
TEST_F(DiskCacheTest, AutomaticMaxSize) {
using disk_cache::kDefaultCacheSize;
int64 large_size = kDefaultCacheSize;
EXPECT_EQ((kDefaultCacheSize - 1) * 8 / 10,
disk_cache::PreferredCacheSize(large_size - 1));
EXPECT_EQ(kDefaultCacheSize * 8 / 10,
disk_cache::PreferredCacheSize(large_size));
EXPECT_EQ(kDefaultCacheSize - 1,
disk_cache::PreferredCacheSize(large_size * 10 / 8 - 1));
EXPECT_EQ(kDefaultCacheSize,
disk_cache::PreferredCacheSize(large_size * 10 / 8));
EXPECT_EQ(kDefaultCacheSize,
disk_cache::PreferredCacheSize(large_size * 10 - 1));
EXPECT_EQ(kDefaultCacheSize,
disk_cache::PreferredCacheSize(large_size * 10));
EXPECT_EQ((kDefaultCacheSize * 25 - 1) / 10,
disk_cache::PreferredCacheSize(large_size * 25 - 1));
EXPECT_EQ(kDefaultCacheSize * 25 / 10,
disk_cache::PreferredCacheSize(large_size * 25));
EXPECT_EQ(kDefaultCacheSize * 25 / 10,
disk_cache::PreferredCacheSize(large_size * 100 - 1));
EXPECT_EQ(kDefaultCacheSize * 25 / 10,
disk_cache::PreferredCacheSize(large_size * 100));
EXPECT_EQ(kDefaultCacheSize * 25 / 10,
disk_cache::PreferredCacheSize(large_size * 250 - 1));
int64 largest_size = kDefaultCacheSize * 4;
EXPECT_EQ(kDefaultCacheSize * 25 / 10,
disk_cache::PreferredCacheSize(large_size * 250));
EXPECT_EQ(largest_size - 1,
disk_cache::PreferredCacheSize(largest_size * 100 - 1));
EXPECT_EQ(largest_size,
disk_cache::PreferredCacheSize(largest_size * 100));
EXPECT_EQ(largest_size,
disk_cache::PreferredCacheSize(largest_size * 10000));
}
TEST_F(DiskCacheBackendTest, Histograms) {
InitCache();
disk_cache::BackendImpl* backend_ = cache_impl_;
for (int i = 1; i < 3; i++) {
CACHE_UMA(HOURS, "FillupTime", i, 28);
}
}
TEST_F(DiskCacheBackendTest, TotalBuffersSize1) {
InitCache();
std::string key("the first key");
disk_cache::Entry* entry;
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
const int kSize = 200;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, true);
for (int i = 0; i < 10; i++) {
SCOPED_TRACE(i);
EXPECT_EQ(kSize, WriteData(entry, 0, 0, buffer.get(), kSize, true));
EXPECT_EQ(kSize, WriteData(entry, 1, 0, buffer.get(), kSize, true));
EXPECT_EQ(kSize,
WriteData(entry, 0, 1024 * 1024, buffer.get(), kSize, false));
EXPECT_EQ(kSize,
WriteData(entry, 1, 1024 * 1024, buffer.get(), kSize, false));
EXPECT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, true));
EXPECT_EQ(0, WriteData(entry, 1, 10, buffer.get(), 0, true));
entry->Close();
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
}
entry->Close();
EXPECT_EQ(0, cache_impl_->GetTotalBuffersSize());
}
TEST_F(DiskCacheBackendTest, TotalBuffersSize2) {
InitCache();
const int kOneMB = 1024 * 1024;
EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
EXPECT_EQ(kOneMB, cache_impl_->GetTotalBuffersSize());
EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize());
EXPECT_TRUE(cache_impl_->IsAllocAllowed(0, kOneMB));
EXPECT_EQ(kOneMB * 3, cache_impl_->GetTotalBuffersSize());
cache_impl_->BufferDeleted(kOneMB);
EXPECT_EQ(kOneMB * 2, cache_impl_->GetTotalBuffersSize());
EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, 30 * kOneMB));
for (int i = 0; i < 30; i++)
cache_impl_->IsAllocAllowed(0, kOneMB);
EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, kOneMB));
}
TEST_F(DiskCacheBackendTest, FileSharing) {
InitCache();
disk_cache::Addr address(0x80000001);
ASSERT_TRUE(cache_impl_->CreateExternalFile(&address));
base::FilePath name = cache_impl_->GetFileName(address);
scoped_refptr<disk_cache::File> file(new disk_cache::File(false));
file->Init(name);
#if defined(OS_WIN)
DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
DWORD access = GENERIC_READ | GENERIC_WRITE;
base::win::ScopedHandle file2(CreateFile(
name.value().c_str(), access, sharing, NULL, OPEN_EXISTING, 0, NULL));
EXPECT_FALSE(file2.IsValid());
sharing |= FILE_SHARE_DELETE;
file2.Set(CreateFile(name.value().c_str(), access, sharing, NULL,
OPEN_EXISTING, 0, NULL));
EXPECT_TRUE(file2.IsValid());
#endif
EXPECT_TRUE(base::DeleteFile(name, false));
const int kSize = 200;
char buffer1[kSize];
char buffer2[kSize];
memset(buffer1, 't', kSize);
memset(buffer2, 0, kSize);
EXPECT_TRUE(file->Write(buffer1, kSize, 0));
EXPECT_TRUE(file->Read(buffer2, kSize, 0));
EXPECT_EQ(0, memcmp(buffer1, buffer2, kSize));
EXPECT_TRUE(disk_cache::DeleteCacheFile(name));
}
TEST_F(DiskCacheBackendTest, UpdateRankForExternalCacheHit) {
InitCache();
disk_cache::Entry* entry;
for (int i = 0; i < 2; ++i) {
std::string key = base::StringPrintf("key%d", i);
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
entry->Close();
}
cache_->OnExternalCacheHit("key0");
TrimForTest(false);
EXPECT_EQ(1, cache_->GetEntryCount());
ASSERT_EQ(net::OK, OpenEntry("key0", &entry));
entry->Close();
}
TEST_F(DiskCacheBackendTest, ShaderCacheUpdateRankForExternalCacheHit) {
SetCacheType(net::SHADER_CACHE);
InitCache();
disk_cache::Entry* entry;
for (int i = 0; i < 2; ++i) {
std::string key = base::StringPrintf("key%d", i);
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
entry->Close();
}
cache_->OnExternalCacheHit("key0");
TrimForTest(false);
EXPECT_EQ(1, cache_->GetEntryCount());
ASSERT_EQ(net::OK, OpenEntry("key0", &entry));
entry->Close();
}
void DiskCacheBackendTest::TracingBackendBasics() {
InitCache();
cache_.reset(new disk_cache::TracingCacheBackend(cache_.Pass()));
cache_impl_ = NULL;
EXPECT_EQ(net::DISK_CACHE, cache_->GetCacheType());
if (!simple_cache_mode_) {
EXPECT_EQ(0, cache_->GetEntryCount());
}
net::TestCompletionCallback cb;
disk_cache::Entry* entry = NULL;
EXPECT_NE(net::OK, OpenEntry("key", &entry));
EXPECT_TRUE(NULL == entry);
ASSERT_EQ(net::OK, CreateEntry("key", &entry));
EXPECT_TRUE(NULL != entry);
disk_cache::Entry* same_entry = NULL;
ASSERT_EQ(net::OK, OpenEntry("key", &same_entry));
EXPECT_TRUE(NULL != same_entry);
if (!simple_cache_mode_) {
EXPECT_EQ(1, cache_->GetEntryCount());
}
entry->Close();
entry = NULL;
same_entry->Close();
same_entry = NULL;
}
TEST_F(DiskCacheBackendTest, TracingBackendBasics) {
TracingBackendBasics();
}
#if defined(OS_POSIX)
TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingCreate) {
SetCacheType(net::APP_CACHE);
SetSimpleCacheMode();
BackendShutdownWithPendingCreate(false);
}
TEST_F(DiskCacheBackendTest, SimpleCacheShutdownWithPendingFileIO) {
SetCacheType(net::APP_CACHE);
SetSimpleCacheMode();
BackendShutdownWithPendingFileIO(false);
}
TEST_F(DiskCacheBackendTest, SimpleCacheBasics) {
SetSimpleCacheMode();
BackendBasics();
}
TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheBasics) {
SetCacheType(net::APP_CACHE);
SetSimpleCacheMode();
BackendBasics();
}
TEST_F(DiskCacheBackendTest, SimpleCacheKeying) {
SetSimpleCacheMode();
BackendKeying();
}
TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheKeying) {
SetSimpleCacheMode();
SetCacheType(net::APP_CACHE);
BackendKeying();
}
TEST_F(DiskCacheBackendTest, DISABLED_SimpleCacheSetSize) {
SetSimpleCacheMode();
BackendSetSize();
}
#if defined(OS_MACOSX)
#define SIMPLE_MAYBE_MACOS(TestName) DISABLED_ ## TestName
#else
#define SIMPLE_MAYBE_MACOS(TestName) TestName
#endif
TEST_F(DiskCacheBackendTest, SIMPLE_MAYBE_MACOS(SimpleCacheLoad)) {
SetMaxSize(0x100000);
SetSimpleCacheMode();
BackendLoad();
}
TEST_F(DiskCacheBackendTest, SIMPLE_MAYBE_MACOS(SimpleCacheAppCacheLoad)) {
SetCacheType(net::APP_CACHE);
SetSimpleCacheMode();
SetMaxSize(0x100000);
BackendLoad();
}
TEST_F(DiskCacheBackendTest, SimpleDoomRecent) {
SetSimpleCacheMode();
BackendDoomRecent();
}
TEST_F(DiskCacheBackendTest, SimpleDoomBetween) {
SetSimpleCacheMode();
BackendDoomBetween();
}
TEST_F(DiskCacheBackendTest, SimpleCacheDoomAll) {
SetSimpleCacheMode();
BackendDoomAll();
}
TEST_F(DiskCacheBackendTest, SimpleCacheAppCacheOnlyDoomAll) {
SetCacheType(net::APP_CACHE);
SetSimpleCacheMode();
BackendDoomAll();
}
TEST_F(DiskCacheBackendTest, SimpleCacheTracingBackendBasics) {
SetSimpleCacheMode();
TracingBackendBasics();
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, SimpleCacheOpenMissingFile) {
SetSimpleCacheMode();
InitCache();
const char* key = "the first key";
disk_cache::Entry* entry = NULL;
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
ASSERT_TRUE(entry != NULL);
entry->Close();
entry = NULL;
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
ASSERT_TRUE(entry != NULL);
entry->Close();
entry = NULL;
base::FilePath to_delete_file = cache_path_.AppendASCII(
disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
EXPECT_TRUE(base::PathExists(to_delete_file));
EXPECT_TRUE(disk_cache::DeleteCacheFile(to_delete_file));
ASSERT_EQ(net::ERR_FAILED, OpenEntry(key, &entry));
for (int i = 1; i < disk_cache::kSimpleEntryFileCount; ++i) {
base::FilePath should_be_gone_file(cache_path_.AppendASCII(
disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, i)));
EXPECT_FALSE(base::PathExists(should_be_gone_file));
}
}
TEST_F(DiskCacheBackendTest, SimpleCacheOpenBadFile) {
SetSimpleCacheMode();
InitCache();
const char* key = "the first key";
disk_cache::Entry* entry = NULL;
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
disk_cache::Entry* null = NULL;
ASSERT_NE(null, entry);
entry->Close();
entry = NULL;
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
ASSERT_NE(null, entry);
entry->Close();
entry = NULL;
base::FilePath entry_file1_path = cache_path_.AppendASCII(
disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
disk_cache::SimpleFileHeader header;
header.initial_magic_number = GG_UINT64_C(0xbadf00d);
EXPECT_EQ(
implicit_cast<int>(sizeof(header)),
base::WriteFile(entry_file1_path, reinterpret_cast<char*>(&header),
sizeof(header)));
ASSERT_EQ(net::ERR_FAILED, OpenEntry(key, &entry));
}
TEST_F(DiskCacheBackendTest, SimpleCacheOverBlockfileCache) {
InitCache();
disk_cache::Entry* entry;
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
ASSERT_EQ(net::OK, CreateEntry("key", &entry));
ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false));
entry->Close();
cache_.reset();
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
disk_cache::SimpleBackendImpl* simple_cache =
new disk_cache::SimpleBackendImpl(cache_path_,
0,
net::DISK_CACHE,
cache_thread.message_loop_proxy().get(),
NULL);
net::TestCompletionCallback cb;
int rv = simple_cache->Init(cb.callback());
EXPECT_NE(net::OK, cb.GetResult(rv));
delete simple_cache;
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, BlockfileCacheOverSimpleCache) {
SetSimpleCacheMode();
InitCache();
disk_cache::Entry* entry;
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
ASSERT_EQ(net::OK, CreateEntry("key", &entry));
ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false));
entry->Close();
cache_.reset();
base::Thread cache_thread("CacheThread");
ASSERT_TRUE(cache_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
disk_cache::BackendImpl* cache = new disk_cache::BackendImpl(
cache_path_, base::MessageLoopProxy::current().get(), NULL);
cache->SetUnitTestMode();
net::TestCompletionCallback cb;
int rv = cache->Init(cb.callback());
EXPECT_NE(net::OK, cb.GetResult(rv));
delete cache;
DisableIntegrityCheck();
}
TEST_F(DiskCacheBackendTest, SimpleCacheFixEnumerators) {
SetSimpleCacheMode();
BackendFixEnumerators();
}
TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationBasics) {
SetSimpleCacheMode();
InitCache();
std::set<std::string> key_pool;
ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool));
std::set<std::string> keys_to_match(key_pool);
void* iter = NULL;
size_t count = 0;
ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count));
cache_->EndEnumeration(&iter);
EXPECT_EQ(key_pool.size(), count);
EXPECT_TRUE(keys_to_match.empty());
keys_to_match = key_pool;
iter = NULL;
count = 0;
disk_cache::Entry* entry_opened_before;
ASSERT_EQ(net::OK, OpenEntry(*(key_pool.begin()), &entry_opened_before));
ASSERT_TRUE(EnumerateAndMatchKeys(key_pool.size()/2,
&iter,
&keys_to_match,
&count));
disk_cache::Entry* entry_opened_middle;
ASSERT_EQ(net::OK,
OpenEntry(*(keys_to_match.begin()), &entry_opened_middle));
ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count));
cache_->EndEnumeration(&iter);
entry_opened_before->Close();
entry_opened_middle->Close();
EXPECT_EQ(key_pool.size(), count);
EXPECT_TRUE(keys_to_match.empty());
}
TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationWhileDoomed) {
SetSimpleCacheMode();
InitCache();
std::set<std::string> key_pool;
ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool));
std::set<std::string> keys_to_match(key_pool);
void* iter = NULL;
size_t count = 0;
ASSERT_TRUE(EnumerateAndMatchKeys(key_pool.size()/2,
&iter,
&keys_to_match,
&count));
std::string key_to_delete = *(keys_to_match.begin());
DoomEntry(key_to_delete);
keys_to_match.erase(key_to_delete);
key_pool.erase(key_to_delete);
ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count));
cache_->EndEnumeration(&iter);
EXPECT_EQ(key_pool.size(), count);
EXPECT_TRUE(keys_to_match.empty());
}
TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationCorruption) {
SetSimpleCacheMode();
InitCache();
std::set<std::string> key_pool;
ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool));
const std::string key = "the key";
disk_cache::Entry* corrupted_entry;
ASSERT_EQ(net::OK, CreateEntry(key, &corrupted_entry));
ASSERT_TRUE(corrupted_entry);
const int kSize = 50;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
CacheTestFillBuffer(buffer->data(), kSize, false);
ASSERT_EQ(kSize,
WriteData(corrupted_entry, 0, 0, buffer.get(), kSize, false));
ASSERT_EQ(kSize, ReadData(corrupted_entry, 0, 0, buffer.get(), kSize));
corrupted_entry->Close();
EXPECT_TRUE(disk_cache::simple_util::CreateCorruptFileForTests(
key, cache_path_));
EXPECT_EQ(key_pool.size() + 1,
implicit_cast<size_t>(cache_->GetEntryCount()));
std::set<std::string> keys_to_match(key_pool);
void* iter = NULL;
size_t count = 0;
ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count));
cache_->EndEnumeration(&iter);
EXPECT_EQ(key_pool.size(), count);
EXPECT_TRUE(keys_to_match.empty());
}
#endif