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 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 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 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 58 FilePath GetCacheFilePath() { 59 return BuildCachePath("cache_test"); 60 } 61 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 76 bool DeleteCache(const FilePath& path) { 77 disk_cache::DeleteCache(path, false); 78 return true; 79 } 80 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 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 108 ScopedTestCache::ScopedTestCache() : path_(GetCacheFilePath()) { 109 bool result = DeleteCache(path_); 110 DCHECK(result); 111 } 112 113 ScopedTestCache::ScopedTestCache(const std::string& name) 114 : path_(BuildCachePath(name)) { 115 bool result = DeleteCache(path_); 116 DCHECK(result); 117 } 118 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 128 CallbackTest::CallbackTest(bool reuse) : result_(-1), reuse_(reuse ? 0 : 1) {} 129 130 CallbackTest::~CallbackTest() {} 131 132 // On the actual callback, increase the number of tests received and check for 133 // errors (an unexpected test received) 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 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 158 MessageLoopHelper::~MessageLoopHelper() { 159 } 160 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). 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