summaryrefslogtreecommitdiffstats
path: root/net/disk_cache/stress_cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/disk_cache/stress_cache.cc')
-rw-r--r--net/disk_cache/stress_cache.cc89
1 files changed, 66 insertions, 23 deletions
diff --git a/net/disk_cache/stress_cache.cc b/net/disk_cache/stress_cache.cc
index 7fad2ef..a18df2a 100644
--- a/net/disk_cache/stress_cache.cc
+++ b/net/disk_cache/stress_cache.cc
@@ -12,15 +12,7 @@
// A regular build should never crash.
// To test that the disk cache doesn't generate critical errors with regular
-// application level crashes, add the following code and re-compile:
-//
-// void BackendImpl::CriticalError(int error) {
-// NOTREACHED();
-//
-// void BackendImpl::ReportError(int error) {
-// if (error && error != ERR_PREVIOUS_CRASH) {
-// NOTREACHED();
-// }
+// application level crashes, edit stress_support.h.
#include <string>
#include <vector>
@@ -44,6 +36,12 @@
#include "net/disk_cache/backend_impl.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/disk_cache_test_util.h"
+#include "net/disk_cache/stress_support.h"
+#include "net/disk_cache/trace.h"
+
+#if defined(OS_WIN)
+#include "base/logging_win.h"
+#endif
using base::Time;
@@ -87,11 +85,21 @@ int MasterCode() {
// -----------------------------------------------------------------------
+std::string GenerateStressKey() {
+ char key[20 * 1024];
+ size_t size = 50 + rand() % 20000;
+ CacheTestFillBuffer(key, size, true);
+
+ key[size - 1] = '\0';
+ return std::string(key);
+}
+
// This thread will loop forever, adding and removing entries from the cache.
// iteration is the current crash cycle, so the entries on the cache are marked
// to know which instance of the application wrote them.
void StressTheCache(int iteration) {
- int cache_size = 0x800000; // 8MB
+ int cache_size = 0x2000000; // 32MB.
+ uint32 mask = 0xfff; // 4096 entries.
FilePath path = GetCacheFilePath().InsertBeforeExtensionASCII("_stress");
base::Thread cache_thread("CacheThread");
@@ -99,12 +107,14 @@ void StressTheCache(int iteration) {
base::Thread::Options(MessageLoop::TYPE_IO, 0)))
return;
+ disk_cache::BackendImpl* cache =
+ new disk_cache::BackendImpl(path, mask, cache_thread.message_loop_proxy(),
+ NULL);
+ cache->SetMaxSize(cache_size);
+ cache->SetFlags(disk_cache::kNoLoadProtection);
+
TestOldCompletionCallback cb;
- disk_cache::Backend* cache;
- int rv = disk_cache::BackendImpl::CreateBackend(
- path, false, cache_size, net::DISK_CACHE,
- disk_cache::kNoLoadProtection | disk_cache::kNoRandom,
- cache_thread.message_loop_proxy(), NULL, &cache, &cb);
+ int rv = cache->Init(&cb);
if (cb.GetResult(rv) != net::OK) {
printf("Unable to initialize cache.\n");
@@ -116,20 +126,22 @@ void StressTheCache(int iteration) {
int seed = static_cast<int>(Time::Now().ToInternalValue());
srand(seed);
+ // kNumKeys is meant to be enough to have about 3x or 4x iterations before
+ // the process crashes.
#ifdef NDEBUG
- const int kNumKeys = 5000;
+ const int kNumKeys = 4000;
#else
- const int kNumKeys = 1700;
+ const int kNumKeys = 1200;
#endif
const int kNumEntries = 30;
std::string keys[kNumKeys];
disk_cache::Entry* entries[kNumEntries] = {0};
for (int i = 0; i < kNumKeys; i++) {
- keys[i] = GenerateKey(true);
+ keys[i] = GenerateStressKey();
}
- const int kSize = 4000;
+ const int kSize = 20000;
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
memset(buffer->data(), 'k', kSize);
@@ -137,7 +149,7 @@ void StressTheCache(int iteration) {
int slot = rand() % kNumEntries;
int key = rand() % kNumKeys;
bool truncate = rand() % 2 ? false : true;
- int size = kSize - (rand() % 4) * kSize / 4;
+ int size = kSize - (rand() % 20) * kSize / 20;
if (entries[slot])
entries[slot]->Close();
@@ -149,8 +161,8 @@ void StressTheCache(int iteration) {
}
base::snprintf(buffer->data(), kSize,
- "i: %d iter: %d, size: %d, truncate: %d", i, iteration, size,
- truncate ? 1 : 0);
+ "i: %d iter: %d, size: %d, truncate: %d ", i, iteration,
+ size, truncate ? 1 : 0);
rv = entries[slot]->WriteData(0, 0, buffer, size, &cb, truncate);
CHECK_EQ(size, cb.GetResult(rv));
@@ -181,7 +193,7 @@ class CrashTask : public Task {
if (g_crashing)
return;
- if (rand() % 100 > 1) {
+ if (rand() % 100 > 30) {
printf("sweet death...\n");
#if defined(OS_WIN)
// Windows does more work on _exit() that we would like, so we use Kill.
@@ -216,8 +228,29 @@ void CrashHandler(const std::string& str) {
base::debug::BreakDebugger();
}
+bool MessageHandler(int severity, const char* file, int line,
+ size_t message_start, const std::string& str) {
+ const size_t kMaxMessageLen = 48;
+ char message[kMaxMessageLen];
+ size_t len = std::min(str.length() - message_start, kMaxMessageLen - 1);
+
+ memcpy(message, str.c_str() + message_start, len);
+ message[len] = '\0';
+#if !defined(DISK_CACHE_TRACE_TO_LOG)
+ disk_cache::Trace("%s", message);
+#endif
+ return false;
+}
+
// -----------------------------------------------------------------------
+#if defined(OS_WIN)
+// {B9A153D4-31C3-48e4-9ABF-D54383F14A0D}
+const GUID kStressCacheTraceProviderName = {
+ 0xb9a153d4, 0x31c3, 0x48e4,
+ { 0x9a, 0xbf, 0xd5, 0x43, 0x83, 0xf1, 0x4a, 0xd } };
+#endif
+
int main(int argc, const char* argv[]) {
// Setup an AtExitManager so Singleton objects will be destructed.
base::AtExitManager at_exit_manager;
@@ -226,6 +259,16 @@ int main(int argc, const char* argv[]) {
return MasterCode();
logging::SetLogAssertHandler(CrashHandler);
+ logging::SetLogMessageHandler(MessageHandler);
+
+#if defined(OS_WIN)
+ logging::LogEventProvider::Initialize(kStressCacheTraceProviderName);
+#else
+ CommandLine::Init(argc, argv);
+ logging::InitLogging(NULL, logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
+ logging::LOCK_LOG_FILE, logging::DELETE_OLD_LOG_FILE,
+ logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
+#endif
// Some time for the memory manager to flush stuff.
base::PlatformThread::Sleep(3000);