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_util.h"
6
7 #include "base/logging.h"
8 #include "base/file_util.h"
9 #include "base/message_loop_proxy.h"
10 #include "base/path_service.h"
11 #include "net/base/net_errors.h"
12 #include "net/disk_cache/backend_impl.h"
13 #include "net/disk_cache/cache_util.h"
14 #include "net/disk_cache/file.h"
15
16 using base::Time;
17 using base::TimeDelta;
18
19 namespace {
20
BuildCachePath(const std::string & name)21 FilePath BuildCachePath(const std::string& name) {
22 FilePath path;
23 PathService::Get(base::DIR_TEMP, &path); // Ignore return value;
24 path = path.AppendASCII(name);
25 if (!file_util::PathExists(path))
26 file_util::CreateDirectory(path);
27
28 return path;
29 }
30
31 } // namespace.
32
GenerateKey(bool same_length)33 std::string GenerateKey(bool same_length) {
34 char key[200];
35 CacheTestFillBuffer(key, sizeof(key), same_length);
36
37 key[199] = '\0';
38 return std::string(key);
39 }
40
CacheTestFillBuffer(char * buffer,size_t len,bool no_nulls)41 void CacheTestFillBuffer(char* buffer, size_t len, bool no_nulls) {
42 static bool called = false;
43 if (!called) {
44 called = true;
45 int seed = static_cast<int>(Time::Now().ToInternalValue());
46 srand(seed);
47 }
48
49 for (size_t i = 0; i < len; i++) {
50 buffer[i] = static_cast<char>(rand());
51 if (!buffer[i] && no_nulls)
52 buffer[i] = 'g';
53 }
54 if (len && !buffer[0])
55 buffer[0] = 'g';
56 }
57
GetCacheFilePath()58 FilePath GetCacheFilePath() {
59 return BuildCachePath("cache_test");
60 }
61
CreateCacheTestFile(const FilePath & name)62 bool CreateCacheTestFile(const FilePath& name) {
63 int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
64 base::PLATFORM_FILE_READ |
65 base::PLATFORM_FILE_WRITE;
66
67 scoped_refptr<disk_cache::File> file(new disk_cache::File(
68 base::CreatePlatformFile(name, flags, NULL, NULL)));
69 if (!file->IsValid())
70 return false;
71
72 file->SetLength(4 * 1024 * 1024);
73 return true;
74 }
75
DeleteCache(const FilePath & path)76 bool DeleteCache(const FilePath& path) {
77 disk_cache::DeleteCache(path, false);
78 return true;
79 }
80
CopyTestCache(const std::string & name)81 bool CopyTestCache(const std::string& name) {
82 FilePath path;
83 PathService::Get(base::DIR_SOURCE_ROOT, &path);
84 path = path.AppendASCII("net");
85 path = path.AppendASCII("data");
86 path = path.AppendASCII("cache_tests");
87 path = path.AppendASCII(name);
88
89 FilePath dest = GetCacheFilePath();
90 if (!DeleteCache(dest))
91 return false;
92 return file_util::CopyDirectory(path, dest, false);
93 }
94
CheckCacheIntegrity(const FilePath & path,bool new_eviction)95 bool CheckCacheIntegrity(const FilePath& path, bool new_eviction) {
96 scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
97 path, base::MessageLoopProxy::CreateForCurrentThread(), NULL));
98 if (!cache.get())
99 return false;
100 if (new_eviction)
101 cache->SetNewEviction();
102 cache->SetFlags(disk_cache::kNoRandom);
103 if (cache->SyncInit() != net::OK)
104 return false;
105 return cache->SelfCheck() >= 0;
106 }
107
ScopedTestCache()108 ScopedTestCache::ScopedTestCache() : path_(GetCacheFilePath()) {
109 bool result = DeleteCache(path_);
110 DCHECK(result);
111 }
112
ScopedTestCache(const std::string & name)113 ScopedTestCache::ScopedTestCache(const std::string& name)
114 : path_(BuildCachePath(name)) {
115 bool result = DeleteCache(path_);
116 DCHECK(result);
117 }
118
~ScopedTestCache()119 ScopedTestCache::~ScopedTestCache() {
120 file_util::Delete(path(), true);
121 }
122
123 // -----------------------------------------------------------------------
124
125 volatile int g_cache_tests_received = 0;
126 volatile bool g_cache_tests_error = 0;
127
CallbackTest(bool reuse)128 CallbackTest::CallbackTest(bool reuse) : result_(-1), reuse_(reuse ? 0 : 1) {}
129
~CallbackTest()130 CallbackTest::~CallbackTest() {}
131
132 // On the actual callback, increase the number of tests received and check for
133 // errors (an unexpected test received)
RunWithParams(const Tuple1<int> & params)134 void CallbackTest::RunWithParams(const Tuple1<int>& params) {
135 if (reuse_) {
136 DCHECK(1 == reuse_);
137 if (2 == reuse_)
138 g_cache_tests_error = true;
139 reuse_++;
140 }
141
142 result_ = params.a;
143 g_cache_tests_received++;
144 }
145
146 // -----------------------------------------------------------------------
147
MessageLoopHelper()148 MessageLoopHelper::MessageLoopHelper()
149 : num_callbacks_(0),
150 num_iterations_(0),
151 last_(0),
152 completed_(false) {
153 // Create a recurrent timer of 50 mS.
154 timer_.Start(
155 TimeDelta::FromMilliseconds(50), this, &MessageLoopHelper::TimerExpired);
156 }
157
~MessageLoopHelper()158 MessageLoopHelper::~MessageLoopHelper() {
159 }
160
WaitUntilCacheIoFinished(int num_callbacks)161 bool MessageLoopHelper::WaitUntilCacheIoFinished(int num_callbacks) {
162 if (num_callbacks == g_cache_tests_received)
163 return true;
164
165 ExpectCallbacks(num_callbacks);
166 MessageLoop::current()->Run();
167 return completed_;
168 }
169
170 // Quits the message loop when all callbacks are called or we've been waiting
171 // too long for them (2 secs without a callback).
TimerExpired()172 void MessageLoopHelper::TimerExpired() {
173 if (g_cache_tests_received > num_callbacks_) {
174 NOTREACHED();
175 } else if (g_cache_tests_received == num_callbacks_) {
176 completed_ = true;
177 MessageLoop::current()->Quit();
178 } else {
179 // Not finished yet. See if we have to abort.
180 if (last_ == g_cache_tests_received)
181 num_iterations_++;
182 else
183 last_ = g_cache_tests_received;
184 if (40 == num_iterations_)
185 MessageLoop::current()->Quit();
186 }
187 }
188