1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This command-line program generates the set of files needed for the crash-
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// cache unit tests (DiskCacheTest,CacheBackend_Recover*). This program only
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// works properly on debug mode, because the crash functionality is not compiled
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// on release builds of the cache.
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/at_exit.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/command_line.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_util.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/path_service.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/process_util.h"
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/test_completion_callback.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/backend_impl.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/disk_cache.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/disk_cache_test_util.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/rankings.h"
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time;
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottenum Errors {
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GENERIC = -1,
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ALL_GOOD = 0,
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  INVALID_ARGUMENT = 1,
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CRASH_OVERWRITE,
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  NOT_REACHED
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing disk_cache::RankCrashes;
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Starts a new process, to generate the files.
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint RunSlave(RankCrashes action) {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath exe;
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PathService::Get(base::FILE_EXE, &exe);
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CommandLine cmdline(exe);
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  cmdline.AppendArg(base::IntToString(action));
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::ProcessHandle handle;
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!base::LaunchApp(cmdline, false, false, &handle)) {
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    printf("Unable to run test %d\n", action);
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int exit_code;
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!base::WaitForExitCode(handle, &exit_code)) {
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    printf("Unable to get return code, test %d\n", action);
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ALL_GOOD != exit_code)
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    printf("Test %d failed, code %d\n", action, exit_code);
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return exit_code;
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Main loop for the master process.
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MasterCode() {
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = disk_cache::NO_CRASH + 1; i < disk_cache::MAX_CRASH; i++) {
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int ret = RunSlave(static_cast<RankCrashes>(i));
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (ALL_GOOD != ret)
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ret;
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ALL_GOOD;
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// -----------------------------------------------------------------------
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottextern RankCrashes g_rankings_crash;
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* kCrashEntryName = "the first key";
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Creates the destinaton folder for this run, and returns it on full_path.
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool CreateTargetFolder(const FilePath& path, RankCrashes action,
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        FilePath* full_path) {
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* folders[] = {
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "",
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "insert_empty1",
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "insert_empty2",
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "insert_empty3",
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "insert_one1",
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "insert_one2",
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "insert_one3",
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "insert_load1",
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "insert_load2",
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_one1",
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_one2",
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_one3",
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_one4",
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_head1",
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_head2",
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_head3",
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_head4",
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_tail1",
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_tail2",
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_tail3",
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_load1",
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_load2",
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "remove_load3"
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  COMPILE_ASSERT(arraysize(folders) == disk_cache::MAX_CRASH, sync_folders);
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(action > disk_cache::NO_CRASH && action < disk_cache::MAX_CRASH);
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *full_path = path.AppendASCII(folders[action]);
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (file_util::PathExists(*full_path))
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return file_util::CreateDirectory(*full_path);
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Makes sure that any pending task is processed.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FlushQueue(disk_cache::Backend* cache) {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback cb;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv =
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      reinterpret_cast<disk_cache::BackendImpl*>(cache)->FlushQueueForTest(&cb);
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cb.GetResult(rv);  // Ignore the result;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Generates the files for an empty and one item cache.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SimpleInsert(const FilePath& path, RankCrashes action,
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 base::Thread* cache_thread) {
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback cb;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::Backend* cache;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false,
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          cache_thread->message_loop_proxy(),
1383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                          NULL, &cache, &cb);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK || cache->GetEntryCount())
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* test_name = "some other key";
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::INSERT_EMPTY_3) {
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    test_name = kCrashEntryName;
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_rankings_crash = action;
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disk_cache::Entry* entry;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = cache->CreateEntry(test_name, &entry, &cb);
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK)
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Close();
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FlushQueue(cache);
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(action <= disk_cache::INSERT_ONE_3);
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  g_rankings_crash = action;
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  test_name = kCrashEntryName;
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = cache->CreateEntry(test_name, &entry, &cb);
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK)
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NOT_REACHED;
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Generates the files for a one item cache, and removing the head.
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SimpleRemove(const FilePath& path, RankCrashes action,
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 base::Thread* cache_thread) {
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(action >= disk_cache::REMOVE_ONE_1);
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(action <= disk_cache::REMOVE_TAIL_3);
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback cb;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::Backend* cache;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Use a simple LRU for eviction.
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = disk_cache::CreateCacheBackend(net::MEDIA_CACHE, path, 0, false,
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          cache_thread->message_loop_proxy(),
1793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                          NULL, &cache, &cb);
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK || cache->GetEntryCount())
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disk_cache::Entry* entry;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = cache->CreateEntry(kCrashEntryName, &entry, &cb);
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK)
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Close();
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FlushQueue(cache);
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action >= disk_cache::REMOVE_TAIL_1) {
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = cache->CreateEntry("some other key", &entry, &cb);
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (cb.GetResult(rv) != net::OK)
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return GENERIC;
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry->Close();
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FlushQueue(cache);
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = cache->OpenEntry(kCrashEntryName, &entry, &cb);
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK)
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  g_rankings_crash = action;
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Doom();
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Close();
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FlushQueue(cache);
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NOT_REACHED;
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HeadRemove(const FilePath& path, RankCrashes action,
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               base::Thread* cache_thread) {
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(action >= disk_cache::REMOVE_HEAD_1);
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(action <= disk_cache::REMOVE_HEAD_4);
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback cb;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::Backend* cache;
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Use a simple LRU for eviction.
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = disk_cache::CreateCacheBackend(net::MEDIA_CACHE, path, 0, false,
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          cache_thread->message_loop_proxy(),
2223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                          NULL, &cache, &cb);
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK || cache->GetEntryCount())
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disk_cache::Entry* entry;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = cache->CreateEntry("some other key", &entry, &cb);
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK)
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Close();
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FlushQueue(cache);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = cache->CreateEntry(kCrashEntryName, &entry, &cb);
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK)
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Close();
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FlushQueue(cache);
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = cache->OpenEntry(kCrashEntryName, &entry, &cb);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK)
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  g_rankings_crash = action;
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Doom();
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Close();
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FlushQueue(cache);
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NOT_REACHED;
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Generates the files for insertion and removals on heavy loaded caches.
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint LoadOperations(const FilePath& path, RankCrashes action,
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   base::Thread* cache_thread) {
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(action >= disk_cache::INSERT_LOAD_1);
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Work with a tiny index table (16 entries).
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::BackendImpl* cache = new disk_cache::BackendImpl(
2593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      path, 0xf, cache_thread->message_loop_proxy(), NULL);
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!cache || !cache->SetMaxSize(0x100000))
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return GENERIC;
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback cb;
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = cache->Init(&cb);
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK || cache->GetEntryCount())
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int seed = static_cast<int>(Time::Now().ToInternalValue());
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  srand(seed);
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disk_cache::Entry* entry;
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < 100; i++) {
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string key = GenerateKey(true);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = cache->CreateEntry(key, &entry, &cb);
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (cb.GetResult(rv) != net::OK)
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return GENERIC;
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry->Close();
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FlushQueue(cache);
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (50 == i && action >= disk_cache::REMOVE_LOAD_1) {
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rv = cache->CreateEntry(kCrashEntryName, &entry, &cb);
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (cb.GetResult(rv) != net::OK)
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return GENERIC;
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      entry->Close();
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FlushQueue(cache);
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::INSERT_LOAD_2) {
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    g_rankings_crash = action;
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = cache->CreateEntry(kCrashEntryName, &entry, &cb);
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (cb.GetResult(rv) != net::OK)
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return GENERIC;
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = cache->OpenEntry(kCrashEntryName, &entry, &cb);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cb.GetResult(rv) != net::OK)
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return GENERIC;
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  g_rankings_crash = action;
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Doom();
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Close();
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FlushQueue(cache);
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NOT_REACHED;
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Main function on the child process.
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SlaveCode(const FilePath& path, RankCrashes action) {
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoopForIO message_loop;
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath full_path;
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!CreateTargetFolder(path, action, &full_path)) {
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    printf("Destination folder found, please remove it.\n");
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return CRASH_OVERWRITE;
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Thread cache_thread("CacheThread");
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!cache_thread.StartWithOptions(
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          base::Thread::Options(MessageLoop::TYPE_IO, 0)))
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return GENERIC;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::INSERT_ONE_3)
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return SimpleInsert(full_path, action, &cache_thread);
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::INSERT_LOAD_2)
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return LoadOperations(full_path, action, &cache_thread);
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::REMOVE_ONE_4)
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return SimpleRemove(full_path, action, &cache_thread);
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::REMOVE_HEAD_4)
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return HeadRemove(full_path, action, &cache_thread);
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::REMOVE_TAIL_3)
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return SimpleRemove(full_path, action, &cache_thread);
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::REMOVE_LOAD_3)
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return LoadOperations(full_path, action, &cache_thread);
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NOT_REACHED;
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// -----------------------------------------------------------------------
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint main(int argc, const char* argv[]) {
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Setup an AtExitManager so Singleton objects will be destructed.
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::AtExitManager at_exit_manager;
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (argc < 2)
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return MasterCode();
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char* end;
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RankCrashes action = static_cast<RankCrashes>(strtol(argv[1], &end, 0));
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (action <= disk_cache::NO_CRASH || action >= disk_cache::MAX_CRASH) {
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    printf("Invalid action\n");
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return INVALID_ARGUMENT;
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path;
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PathService::Get(base::DIR_SOURCE_ROOT, &path);
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  path = path.AppendASCII("net");
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  path = path.AppendASCII("data");
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  path = path.AppendASCII("cache_tests");
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  path = path.AppendASCII("new_crashes");
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return SlaveCode(path, action);
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
370