// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/disk_cache/disk_cache_test_util.h" #include "base/logging.h" #include "base/file_util.h" #include "base/message_loop_proxy.h" #include "base/path_service.h" #include "net/base/net_errors.h" #include "net/disk_cache/backend_impl.h" #include "net/disk_cache/cache_util.h" #include "net/disk_cache/file.h" using base::Time; using base::TimeDelta; namespace { FilePath BuildCachePath(const std::string& name) { FilePath path; PathService::Get(base::DIR_TEMP, &path); // Ignore return value; path = path.AppendASCII(name); if (!file_util::PathExists(path)) file_util::CreateDirectory(path); return path; } } // namespace. std::string GenerateKey(bool same_length) { char key[200]; CacheTestFillBuffer(key, sizeof(key), same_length); key[199] = '\0'; return std::string(key); } void CacheTestFillBuffer(char* buffer, size_t len, bool no_nulls) { static bool called = false; if (!called) { called = true; int seed = static_cast<int>(Time::Now().ToInternalValue()); srand(seed); } for (size_t i = 0; i < len; i++) { buffer[i] = static_cast<char>(rand()); if (!buffer[i] && no_nulls) buffer[i] = 'g'; } if (len && !buffer[0]) buffer[0] = 'g'; } FilePath GetCacheFilePath() { return BuildCachePath("cache_test"); } bool CreateCacheTestFile(const FilePath& name) { int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_READ | base::PLATFORM_FILE_WRITE; scoped_refptr<disk_cache::File> file(new disk_cache::File( base::CreatePlatformFile(name, flags, NULL, NULL))); if (!file->IsValid()) return false; file->SetLength(4 * 1024 * 1024); return true; } bool DeleteCache(const FilePath& path) { disk_cache::DeleteCache(path, false); return true; } bool CopyTestCache(const std::string& name) { FilePath path; PathService::Get(base::DIR_SOURCE_ROOT, &path); path = path.AppendASCII("net"); path = path.AppendASCII("data"); path = path.AppendASCII("cache_tests"); path = path.AppendASCII(name); FilePath dest = GetCacheFilePath(); if (!DeleteCache(dest)) return false; return file_util::CopyDirectory(path, dest, false); } bool CheckCacheIntegrity(const FilePath& path, bool new_eviction) { scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl( path, base::MessageLoopProxy::CreateForCurrentThread(), NULL)); if (!cache.get()) return false; if (new_eviction) cache->SetNewEviction(); cache->SetFlags(disk_cache::kNoRandom); if (cache->SyncInit() != net::OK) return false; return cache->SelfCheck() >= 0; } ScopedTestCache::ScopedTestCache() : path_(GetCacheFilePath()) { bool result = DeleteCache(path_); DCHECK(result); } ScopedTestCache::ScopedTestCache(const std::string& name) : path_(BuildCachePath(name)) { bool result = DeleteCache(path_); DCHECK(result); } ScopedTestCache::~ScopedTestCache() { file_util::Delete(path(), true); } // ----------------------------------------------------------------------- volatile int g_cache_tests_received = 0; volatile bool g_cache_tests_error = 0; CallbackTest::CallbackTest(bool reuse) : result_(-1), reuse_(reuse ? 0 : 1) {} CallbackTest::~CallbackTest() {} // On the actual callback, increase the number of tests received and check for // errors (an unexpected test received) void CallbackTest::RunWithParams(const Tuple1<int>& params) { if (reuse_) { DCHECK(1 == reuse_); if (2 == reuse_) g_cache_tests_error = true; reuse_++; } result_ = params.a; g_cache_tests_received++; } // ----------------------------------------------------------------------- MessageLoopHelper::MessageLoopHelper() : num_callbacks_(0), num_iterations_(0), last_(0), completed_(false) { // Create a recurrent timer of 50 mS. timer_.Start( TimeDelta::FromMilliseconds(50), this, &MessageLoopHelper::TimerExpired); } MessageLoopHelper::~MessageLoopHelper() { } bool MessageLoopHelper::WaitUntilCacheIoFinished(int num_callbacks) { if (num_callbacks == g_cache_tests_received) return true; ExpectCallbacks(num_callbacks); MessageLoop::current()->Run(); return completed_; } // Quits the message loop when all callbacks are called or we've been waiting // too long for them (2 secs without a callback). void MessageLoopHelper::TimerExpired() { if (g_cache_tests_received > num_callbacks_) { NOTREACHED(); } else if (g_cache_tests_received == num_callbacks_) { completed_ = true; MessageLoop::current()->Quit(); } else { // Not finished yet. See if we have to abort. if (last_ == g_cache_tests_received) num_iterations_++; else last_ = g_cache_tests_received; if (40 == num_iterations_) MessageLoop::current()->Quit(); } }