1// Copyright (c) 2006-2010 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 "net/base/io_buffer.h"
8#include "net/base/net_errors.h"
9#include "net/base/test_completion_callback.h"
10#include "net/disk_cache/backend_impl.h"
11#include "net/disk_cache/disk_cache_test_util.h"
12#include "net/disk_cache/mem_backend_impl.h"
13
14void DiskCacheTest::TearDown() {
15  MessageLoop::current()->RunAllPending();
16}
17
18DiskCacheTestWithCache::DiskCacheTestWithCache()
19    : cache_(NULL),
20      cache_impl_(NULL),
21      mem_cache_(NULL),
22      mask_(0),
23      size_(0),
24      type_(net::DISK_CACHE),
25      memory_only_(false),
26      implementation_(false),
27      force_creation_(false),
28      new_eviction_(false),
29      first_cleanup_(true),
30      integrity_(true),
31      use_current_thread_(false),
32      cache_thread_("CacheThread") {
33}
34
35DiskCacheTestWithCache::~DiskCacheTestWithCache() {}
36
37void DiskCacheTestWithCache::InitCache() {
38  if (mask_ || new_eviction_)
39    implementation_ = true;
40
41  if (memory_only_)
42    InitMemoryCache();
43  else
44    InitDiskCache();
45
46  ASSERT_TRUE(NULL != cache_);
47  if (first_cleanup_)
48    ASSERT_EQ(0, cache_->GetEntryCount());
49}
50
51// We are expected to leak memory when simulating crashes.
52void DiskCacheTestWithCache::SimulateCrash() {
53  ASSERT_TRUE(implementation_ && !memory_only_);
54  TestCompletionCallback cb;
55  int rv = cache_impl_->FlushQueueForTest(&cb);
56  ASSERT_EQ(net::OK, cb.GetResult(rv));
57  cache_impl_->ClearRefCountForTest();
58
59  delete cache_impl_;
60  FilePath path = GetCacheFilePath();
61  EXPECT_TRUE(CheckCacheIntegrity(path, new_eviction_));
62
63  InitDiskCacheImpl(path);
64}
65
66void DiskCacheTestWithCache::SetTestMode() {
67  ASSERT_TRUE(implementation_ && !memory_only_);
68  cache_impl_->SetUnitTestMode();
69}
70
71void DiskCacheTestWithCache::SetMaxSize(int size) {
72  size_ = size;
73  if (cache_impl_)
74    EXPECT_TRUE(cache_impl_->SetMaxSize(size));
75
76  if (mem_cache_)
77    EXPECT_TRUE(mem_cache_->SetMaxSize(size));
78}
79
80int DiskCacheTestWithCache::OpenEntry(const std::string& key,
81                                      disk_cache::Entry** entry) {
82  TestCompletionCallback cb;
83  int rv = cache_->OpenEntry(key, entry, &cb);
84  return cb.GetResult(rv);
85}
86
87int DiskCacheTestWithCache::CreateEntry(const std::string& key,
88                                        disk_cache::Entry** entry) {
89  TestCompletionCallback cb;
90  int rv = cache_->CreateEntry(key, entry, &cb);
91  return cb.GetResult(rv);
92}
93
94int DiskCacheTestWithCache::DoomEntry(const std::string& key) {
95  TestCompletionCallback cb;
96  int rv = cache_->DoomEntry(key, &cb);
97  return cb.GetResult(rv);
98}
99
100int DiskCacheTestWithCache::DoomAllEntries() {
101  TestCompletionCallback cb;
102  int rv = cache_->DoomAllEntries(&cb);
103  return cb.GetResult(rv);
104}
105
106int DiskCacheTestWithCache::DoomEntriesBetween(const base::Time initial_time,
107                                               const base::Time end_time) {
108  TestCompletionCallback cb;
109  int rv = cache_->DoomEntriesBetween(initial_time, end_time, &cb);
110  return cb.GetResult(rv);
111}
112
113int DiskCacheTestWithCache::DoomEntriesSince(const base::Time initial_time) {
114  TestCompletionCallback cb;
115  int rv = cache_->DoomEntriesSince(initial_time, &cb);
116  return cb.GetResult(rv);
117}
118
119int DiskCacheTestWithCache::OpenNextEntry(void** iter,
120                                          disk_cache::Entry** next_entry) {
121  TestCompletionCallback cb;
122  int rv = cache_->OpenNextEntry(iter, next_entry, &cb);
123  return cb.GetResult(rv);
124}
125
126void DiskCacheTestWithCache::FlushQueueForTest() {
127  if (memory_only_ || !cache_impl_)
128    return;
129
130  TestCompletionCallback cb;
131  int rv = cache_impl_->FlushQueueForTest(&cb);
132  EXPECT_EQ(net::OK, cb.GetResult(rv));
133}
134
135void DiskCacheTestWithCache::RunTaskForTest(Task* task) {
136  if (memory_only_ || !cache_impl_) {
137    task->Run();
138    delete task;
139    return;
140  }
141
142  TestCompletionCallback cb;
143  int rv = cache_impl_->RunTaskForTest(task, &cb);
144  EXPECT_EQ(net::OK, cb.GetResult(rv));
145}
146
147int DiskCacheTestWithCache::ReadData(disk_cache::Entry* entry, int index,
148                                     int offset, net::IOBuffer* buf, int len) {
149  TestCompletionCallback cb;
150  int rv = entry->ReadData(index, offset, buf, len, &cb);
151  return cb.GetResult(rv);
152}
153
154
155int DiskCacheTestWithCache::WriteData(disk_cache::Entry* entry, int index,
156                                      int offset, net::IOBuffer* buf, int len,
157                                      bool truncate) {
158  TestCompletionCallback cb;
159  int rv = entry->WriteData(index, offset, buf, len, &cb, truncate);
160  return cb.GetResult(rv);
161}
162
163int DiskCacheTestWithCache::ReadSparseData(disk_cache::Entry* entry,
164                                           int64 offset, net::IOBuffer* buf,
165                                           int len) {
166  TestCompletionCallback cb;
167  int rv = entry->ReadSparseData(offset, buf, len, &cb);
168  return cb.GetResult(rv);
169}
170
171int DiskCacheTestWithCache::WriteSparseData(disk_cache::Entry* entry,
172                                            int64 offset,
173                                            net::IOBuffer* buf, int len) {
174  TestCompletionCallback cb;
175  int rv = entry->WriteSparseData(offset, buf, len, &cb);
176  return cb.GetResult(rv);
177}
178
179// Simple task to run part of a test from the cache thread.
180class TrimTask : public Task {
181 public:
182  TrimTask(disk_cache::BackendImpl* backend, bool deleted, bool empty)
183      : backend_(backend),
184        deleted_(deleted),
185        empty_(empty) {}
186
187  virtual void Run() {
188    if (deleted_)
189      backend_->TrimDeletedListForTest(empty_);
190    else
191      backend_->TrimForTest(empty_);
192  }
193
194 protected:
195  disk_cache::BackendImpl* backend_;
196  bool deleted_;
197  bool empty_;
198};
199
200void DiskCacheTestWithCache::TrimForTest(bool empty) {
201  RunTaskForTest(new TrimTask(cache_impl_, false, empty));
202}
203
204void DiskCacheTestWithCache::TrimDeletedListForTest(bool empty) {
205  RunTaskForTest(new TrimTask(cache_impl_, true, empty));
206}
207
208void DiskCacheTestWithCache::TearDown() {
209  MessageLoop::current()->RunAllPending();
210  delete cache_;
211  if (cache_thread_.IsRunning())
212    cache_thread_.Stop();
213
214  if (!memory_only_ && integrity_) {
215    FilePath path = GetCacheFilePath();
216    EXPECT_TRUE(CheckCacheIntegrity(path, new_eviction_));
217  }
218
219  PlatformTest::TearDown();
220}
221
222void DiskCacheTestWithCache::InitMemoryCache() {
223  if (!implementation_) {
224    cache_ = disk_cache::MemBackendImpl::CreateBackend(size_, NULL);
225    return;
226  }
227
228  mem_cache_ = new disk_cache::MemBackendImpl(NULL);
229  cache_ = mem_cache_;
230  ASSERT_TRUE(NULL != cache_);
231
232  if (size_)
233    EXPECT_TRUE(mem_cache_->SetMaxSize(size_));
234
235  ASSERT_TRUE(mem_cache_->Init());
236}
237
238void DiskCacheTestWithCache::InitDiskCache() {
239  FilePath path = GetCacheFilePath();
240  if (first_cleanup_)
241    ASSERT_TRUE(DeleteCache(path));
242
243  if (!cache_thread_.IsRunning()) {
244    EXPECT_TRUE(cache_thread_.StartWithOptions(
245                    base::Thread::Options(MessageLoop::TYPE_IO, 0)));
246  }
247  ASSERT_TRUE(cache_thread_.message_loop() != NULL);
248
249  if (implementation_)
250    return InitDiskCacheImpl(path);
251
252  scoped_refptr<base::MessageLoopProxy> thread =
253      use_current_thread_ ? base::MessageLoopProxy::CreateForCurrentThread() :
254                            cache_thread_.message_loop_proxy();
255
256  TestCompletionCallback cb;
257  int rv = disk_cache::BackendImpl::CreateBackend(
258               path, force_creation_, size_, type_,
259               disk_cache::kNoRandom, thread, NULL, &cache_, &cb);
260  ASSERT_EQ(net::OK, cb.GetResult(rv));
261}
262
263void DiskCacheTestWithCache::InitDiskCacheImpl(const FilePath& path) {
264  scoped_refptr<base::MessageLoopProxy> thread =
265      use_current_thread_ ? base::MessageLoopProxy::CreateForCurrentThread() :
266                            cache_thread_.message_loop_proxy();
267  if (mask_)
268    cache_impl_ = new disk_cache::BackendImpl(path, mask_, thread, NULL);
269  else
270    cache_impl_ = new disk_cache::BackendImpl(path, thread, NULL);
271
272  cache_ = cache_impl_;
273  ASSERT_TRUE(NULL != cache_);
274
275  if (size_)
276    EXPECT_TRUE(cache_impl_->SetMaxSize(size_));
277
278  if (new_eviction_)
279    cache_impl_->SetNewEviction();
280
281  cache_impl_->SetType(type_);
282  cache_impl_->SetFlags(disk_cache::kNoRandom);
283  TestCompletionCallback cb;
284  int rv = cache_impl_->Init(&cb);
285  ASSERT_EQ(net::OK, cb.GetResult(rv));
286}
287