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/blockfile/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/memory/mem_backend_impl.h"
19 #include "net/disk_cache/simple/simple_backend_impl.h"
20 #include "net/disk_cache/simple/simple_index.h"
21
DiskCacheTest()22 DiskCacheTest::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
~DiskCacheTest()29 DiskCacheTest::~DiskCacheTest() {
30 }
31
CopyTestCache(const std::string & name)32 bool 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
CleanupCacheDir()45 bool DiskCacheTest::CleanupCacheDir() {
46 return DeleteCache(cache_path_);
47 }
48
TearDown()49 void DiskCacheTest::TearDown() {
50 base::RunLoop().RunUntilIdle();
51 }
52
DiskCacheTestWithCache()53 DiskCacheTestWithCache::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
~DiskCacheTestWithCache()71 DiskCacheTestWithCache::~DiskCacheTestWithCache() {}
72
InitCache()73 void 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.
SimulateCrash()85 void 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
SetTestMode()98 void DiskCacheTestWithCache::SetTestMode() {
99 ASSERT_TRUE(!memory_only_);
100 cache_impl_->SetUnitTestMode();
101 }
102
SetMaxSize(int size)103 void 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
OpenEntry(const std::string & key,disk_cache::Entry ** entry)115 int 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
CreateEntry(const std::string & key,disk_cache::Entry ** entry)122 int 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
DoomEntry(const std::string & key)129 int 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
DoomAllEntries()135 int DiskCacheTestWithCache::DoomAllEntries() {
136 net::TestCompletionCallback cb;
137 int rv = cache_->DoomAllEntries(cb.callback());
138 return cb.GetResult(rv);
139 }
140
DoomEntriesBetween(const base::Time initial_time,const base::Time end_time)141 int 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
DoomEntriesSince(const base::Time initial_time)148 int 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
OpenNextEntry(void ** iter,disk_cache::Entry ** next_entry)154 int 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
FlushQueueForTest()161 void 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
RunTaskForTest(const base::Closure & closure)170 void 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
ReadData(disk_cache::Entry * entry,int index,int offset,net::IOBuffer * buf,int len)181 int 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
WriteData(disk_cache::Entry * entry,int index,int offset,net::IOBuffer * buf,int len,bool truncate)188 int 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
ReadSparseData(disk_cache::Entry * entry,int64 offset,net::IOBuffer * buf,int len)196 int 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
WriteSparseData(disk_cache::Entry * entry,int64 offset,net::IOBuffer * buf,int len)204 int 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
TrimForTest(bool empty)212 void DiskCacheTestWithCache::TrimForTest(bool empty) {
213 RunTaskForTest(base::Bind(&disk_cache::BackendImpl::TrimForTest,
214 base::Unretained(cache_impl_),
215 empty));
216 }
217
TrimDeletedListForTest(bool empty)218 void DiskCacheTestWithCache::TrimDeletedListForTest(bool empty) {
219 RunTaskForTest(base::Bind(&disk_cache::BackendImpl::TrimDeletedListForTest,
220 base::Unretained(cache_impl_),
221 empty));
222 }
223
AddDelay()224 void 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
TearDown()242 void 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
InitMemoryCache()258 void 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
InitDiskCache()269 void 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
CreateBackend(uint32 flags,base::Thread * thread)282 void 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