1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/disk_cache/disk_cache_test_base.h" 6 7#include "base/file_util.h" 8#include "base/path_service.h" 9#include "base/run_loop.h" 10#include "base/threading/platform_thread.h" 11#include "net/base/io_buffer.h" 12#include "net/base/net_errors.h" 13#include "net/base/test_completion_callback.h" 14#include "net/disk_cache/backend_impl.h" 15#include "net/disk_cache/cache_util.h" 16#include "net/disk_cache/disk_cache.h" 17#include "net/disk_cache/disk_cache_test_util.h" 18#include "net/disk_cache/mem_backend_impl.h" 19#include "net/disk_cache/simple/simple_backend_impl.h" 20#include "net/disk_cache/simple/simple_index.h" 21 22DiskCacheTest::DiskCacheTest() { 23 CHECK(temp_dir_.CreateUniqueTempDir()); 24 cache_path_ = temp_dir_.path(); 25 if (!base::MessageLoop::current()) 26 message_loop_.reset(new base::MessageLoopForIO()); 27} 28 29DiskCacheTest::~DiskCacheTest() { 30} 31 32bool DiskCacheTest::CopyTestCache(const std::string& name) { 33 base::FilePath path; 34 PathService::Get(base::DIR_SOURCE_ROOT, &path); 35 path = path.AppendASCII("net"); 36 path = path.AppendASCII("data"); 37 path = path.AppendASCII("cache_tests"); 38 path = path.AppendASCII(name); 39 40 if (!CleanupCacheDir()) 41 return false; 42 return base::CopyDirectory(path, cache_path_, false); 43} 44 45bool DiskCacheTest::CleanupCacheDir() { 46 return DeleteCache(cache_path_); 47} 48 49void DiskCacheTest::TearDown() { 50 base::RunLoop().RunUntilIdle(); 51} 52 53DiskCacheTestWithCache::DiskCacheTestWithCache() 54 : cache_impl_(NULL), 55 simple_cache_impl_(NULL), 56 mem_cache_(NULL), 57 mask_(0), 58 size_(0), 59 type_(net::DISK_CACHE), 60 memory_only_(false), 61 simple_cache_mode_(false), 62 simple_cache_wait_for_index_(true), 63 force_creation_(false), 64 new_eviction_(false), 65 first_cleanup_(true), 66 integrity_(true), 67 use_current_thread_(false), 68 cache_thread_("CacheThread") { 69} 70 71DiskCacheTestWithCache::~DiskCacheTestWithCache() {} 72 73void DiskCacheTestWithCache::InitCache() { 74 if (memory_only_) 75 InitMemoryCache(); 76 else 77 InitDiskCache(); 78 79 ASSERT_TRUE(NULL != cache_); 80 if (first_cleanup_) 81 ASSERT_EQ(0, cache_->GetEntryCount()); 82} 83 84// We are expected to leak memory when simulating crashes. 85void DiskCacheTestWithCache::SimulateCrash() { 86 ASSERT_TRUE(!memory_only_); 87 net::TestCompletionCallback cb; 88 int rv = cache_impl_->FlushQueueForTest(cb.callback()); 89 ASSERT_EQ(net::OK, cb.GetResult(rv)); 90 cache_impl_->ClearRefCountForTest(); 91 92 cache_.reset(); 93 EXPECT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask_)); 94 95 CreateBackend(disk_cache::kNoRandom, &cache_thread_); 96} 97 98void DiskCacheTestWithCache::SetTestMode() { 99 ASSERT_TRUE(!memory_only_); 100 cache_impl_->SetUnitTestMode(); 101} 102 103void DiskCacheTestWithCache::SetMaxSize(int size) { 104 size_ = size; 105 if (simple_cache_impl_) 106 EXPECT_TRUE(simple_cache_impl_->SetMaxSize(size)); 107 108 if (cache_impl_) 109 EXPECT_TRUE(cache_impl_->SetMaxSize(size)); 110 111 if (mem_cache_) 112 EXPECT_TRUE(mem_cache_->SetMaxSize(size)); 113} 114 115int DiskCacheTestWithCache::OpenEntry(const std::string& key, 116 disk_cache::Entry** entry) { 117 net::TestCompletionCallback cb; 118 int rv = cache_->OpenEntry(key, entry, cb.callback()); 119 return cb.GetResult(rv); 120} 121 122int DiskCacheTestWithCache::CreateEntry(const std::string& key, 123 disk_cache::Entry** entry) { 124 net::TestCompletionCallback cb; 125 int rv = cache_->CreateEntry(key, entry, cb.callback()); 126 return cb.GetResult(rv); 127} 128 129int DiskCacheTestWithCache::DoomEntry(const std::string& key) { 130 net::TestCompletionCallback cb; 131 int rv = cache_->DoomEntry(key, cb.callback()); 132 return cb.GetResult(rv); 133} 134 135int DiskCacheTestWithCache::DoomAllEntries() { 136 net::TestCompletionCallback cb; 137 int rv = cache_->DoomAllEntries(cb.callback()); 138 return cb.GetResult(rv); 139} 140 141int DiskCacheTestWithCache::DoomEntriesBetween(const base::Time initial_time, 142 const base::Time end_time) { 143 net::TestCompletionCallback cb; 144 int rv = cache_->DoomEntriesBetween(initial_time, end_time, cb.callback()); 145 return cb.GetResult(rv); 146} 147 148int DiskCacheTestWithCache::DoomEntriesSince(const base::Time initial_time) { 149 net::TestCompletionCallback cb; 150 int rv = cache_->DoomEntriesSince(initial_time, cb.callback()); 151 return cb.GetResult(rv); 152} 153 154int DiskCacheTestWithCache::OpenNextEntry(void** iter, 155 disk_cache::Entry** next_entry) { 156 net::TestCompletionCallback cb; 157 int rv = cache_->OpenNextEntry(iter, next_entry, cb.callback()); 158 return cb.GetResult(rv); 159} 160 161void DiskCacheTestWithCache::FlushQueueForTest() { 162 if (memory_only_ || !cache_impl_) 163 return; 164 165 net::TestCompletionCallback cb; 166 int rv = cache_impl_->FlushQueueForTest(cb.callback()); 167 EXPECT_EQ(net::OK, cb.GetResult(rv)); 168} 169 170void DiskCacheTestWithCache::RunTaskForTest(const base::Closure& closure) { 171 if (memory_only_ || !cache_impl_) { 172 closure.Run(); 173 return; 174 } 175 176 net::TestCompletionCallback cb; 177 int rv = cache_impl_->RunTaskForTest(closure, cb.callback()); 178 EXPECT_EQ(net::OK, cb.GetResult(rv)); 179} 180 181int DiskCacheTestWithCache::ReadData(disk_cache::Entry* entry, int index, 182 int offset, net::IOBuffer* buf, int len) { 183 net::TestCompletionCallback cb; 184 int rv = entry->ReadData(index, offset, buf, len, cb.callback()); 185 return cb.GetResult(rv); 186} 187 188int DiskCacheTestWithCache::WriteData(disk_cache::Entry* entry, int index, 189 int offset, net::IOBuffer* buf, int len, 190 bool truncate) { 191 net::TestCompletionCallback cb; 192 int rv = entry->WriteData(index, offset, buf, len, cb.callback(), truncate); 193 return cb.GetResult(rv); 194} 195 196int DiskCacheTestWithCache::ReadSparseData(disk_cache::Entry* entry, 197 int64 offset, net::IOBuffer* buf, 198 int len) { 199 net::TestCompletionCallback cb; 200 int rv = entry->ReadSparseData(offset, buf, len, cb.callback()); 201 return cb.GetResult(rv); 202} 203 204int DiskCacheTestWithCache::WriteSparseData(disk_cache::Entry* entry, 205 int64 offset, 206 net::IOBuffer* buf, int len) { 207 net::TestCompletionCallback cb; 208 int rv = entry->WriteSparseData(offset, buf, len, cb.callback()); 209 return cb.GetResult(rv); 210} 211 212void DiskCacheTestWithCache::TrimForTest(bool empty) { 213 RunTaskForTest(base::Bind(&disk_cache::BackendImpl::TrimForTest, 214 base::Unretained(cache_impl_), 215 empty)); 216} 217 218void DiskCacheTestWithCache::TrimDeletedListForTest(bool empty) { 219 RunTaskForTest(base::Bind(&disk_cache::BackendImpl::TrimDeletedListForTest, 220 base::Unretained(cache_impl_), 221 empty)); 222} 223 224void DiskCacheTestWithCache::AddDelay() { 225 if (simple_cache_mode_) { 226 // The simple cache uses second resolution for many timeouts, so it's safest 227 // to advance by at least whole seconds before falling back into the normal 228 // disk cache epsilon advance. 229 const base::Time initial_time = base::Time::Now(); 230 do { 231 base::PlatformThread::YieldCurrentThread(); 232 } while (base::Time::Now() - 233 initial_time < base::TimeDelta::FromSeconds(1)); 234 } 235 236 base::Time initial = base::Time::Now(); 237 while (base::Time::Now() <= initial) { 238 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); 239 }; 240} 241 242void DiskCacheTestWithCache::TearDown() { 243 base::RunLoop().RunUntilIdle(); 244 disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting(); 245 base::RunLoop().RunUntilIdle(); 246 cache_.reset(); 247 if (cache_thread_.IsRunning()) 248 cache_thread_.Stop(); 249 250 if (!memory_only_ && !simple_cache_mode_ && integrity_) { 251 EXPECT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask_)); 252 } 253 base::RunLoop().RunUntilIdle(); 254 disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting(); 255 DiskCacheTest::TearDown(); 256} 257 258void DiskCacheTestWithCache::InitMemoryCache() { 259 mem_cache_ = new disk_cache::MemBackendImpl(NULL); 260 cache_.reset(mem_cache_); 261 ASSERT_TRUE(cache_); 262 263 if (size_) 264 EXPECT_TRUE(mem_cache_->SetMaxSize(size_)); 265 266 ASSERT_TRUE(mem_cache_->Init()); 267} 268 269void DiskCacheTestWithCache::InitDiskCache() { 270 if (first_cleanup_) 271 ASSERT_TRUE(CleanupCacheDir()); 272 273 if (!cache_thread_.IsRunning()) { 274 ASSERT_TRUE(cache_thread_.StartWithOptions( 275 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); 276 } 277 ASSERT_TRUE(cache_thread_.message_loop() != NULL); 278 279 CreateBackend(disk_cache::kNoRandom, &cache_thread_); 280} 281 282void DiskCacheTestWithCache::CreateBackend(uint32 flags, base::Thread* thread) { 283 base::MessageLoopProxy* runner; 284 if (use_current_thread_) 285 runner = base::MessageLoopProxy::current().get(); 286 else 287 runner = thread->message_loop_proxy().get(); 288 289 if (simple_cache_mode_) { 290 net::TestCompletionCallback cb; 291 scoped_ptr<disk_cache::SimpleBackendImpl> simple_backend( 292 new disk_cache::SimpleBackendImpl( 293 cache_path_, size_, type_, make_scoped_refptr(runner).get(), NULL)); 294 int rv = simple_backend->Init(cb.callback()); 295 ASSERT_EQ(net::OK, cb.GetResult(rv)); 296 simple_cache_impl_ = simple_backend.get(); 297 cache_ = simple_backend.PassAs<disk_cache::Backend>(); 298 if (simple_cache_wait_for_index_) { 299 net::TestCompletionCallback wait_for_index_cb; 300 rv = simple_cache_impl_->index()->ExecuteWhenReady( 301 wait_for_index_cb.callback()); 302 ASSERT_EQ(net::OK, wait_for_index_cb.GetResult(rv)); 303 } 304 return; 305 } 306 307 if (mask_) 308 cache_impl_ = new disk_cache::BackendImpl(cache_path_, mask_, runner, NULL); 309 else 310 cache_impl_ = new disk_cache::BackendImpl(cache_path_, runner, NULL); 311 cache_.reset(cache_impl_); 312 ASSERT_TRUE(cache_); 313 if (size_) 314 EXPECT_TRUE(cache_impl_->SetMaxSize(size_)); 315 if (new_eviction_) 316 cache_impl_->SetNewEviction(); 317 cache_impl_->SetType(type_); 318 cache_impl_->SetFlags(flags); 319 net::TestCompletionCallback cb; 320 int rv = cache_impl_->Init(cb.callback()); 321 ASSERT_EQ(net::OK, cb.GetResult(rv)); 322} 323