// Copyright (c) 2011 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.

// This command-line program generates the set of files needed for the crash-
// cache unit tests (DiskCacheTest,CacheBackend_Recover*). This program only
// works properly on debug mode, because the crash functionality is not compiled
// on release builds of the cache.

#include <string>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/base/test_completion_callback.h"
#include "net/disk_cache/blockfile/backend_impl.h"
#include "net/disk_cache/blockfile/rankings.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/disk_cache_test_util.h"

using base::Time;

enum Errors {
  GENERIC = -1,
  ALL_GOOD = 0,
  INVALID_ARGUMENT = 1,
  CRASH_OVERWRITE,
  NOT_REACHED
};

using disk_cache::RankCrashes;

// Starts a new process, to generate the files.
int RunSlave(RankCrashes action) {
  base::FilePath exe;
  PathService::Get(base::FILE_EXE, &exe);

  base::CommandLine cmdline(exe);
  cmdline.AppendArg(base::IntToString(action));

  base::ProcessHandle handle;
  if (!base::LaunchProcess(cmdline, base::LaunchOptions(), &handle)) {
    printf("Unable to run test %d\n", action);
    return GENERIC;
  }

  int exit_code;

  if (!base::WaitForExitCode(handle, &exit_code)) {
    printf("Unable to get return code, test %d\n", action);
    return GENERIC;
  }
  if (ALL_GOOD != exit_code)
    printf("Test %d failed, code %d\n", action, exit_code);

  return exit_code;
}

// Main loop for the master process.
int MasterCode() {
  for (int i = disk_cache::NO_CRASH + 1; i < disk_cache::MAX_CRASH; i++) {
    int ret = RunSlave(static_cast<RankCrashes>(i));
    if (ALL_GOOD != ret)
      return ret;
  }

  return ALL_GOOD;
}

// -----------------------------------------------------------------------

namespace disk_cache {
NET_EXPORT_PRIVATE extern RankCrashes g_rankings_crash;
}

const char* kCrashEntryName = "the first key";

// Creates the destinaton folder for this run, and returns it on full_path.
bool CreateTargetFolder(const base::FilePath& path, RankCrashes action,
                        base::FilePath* full_path) {
  const char* folders[] = {
    "",
    "insert_empty1",
    "insert_empty2",
    "insert_empty3",
    "insert_one1",
    "insert_one2",
    "insert_one3",
    "insert_load1",
    "insert_load2",
    "remove_one1",
    "remove_one2",
    "remove_one3",
    "remove_one4",
    "remove_head1",
    "remove_head2",
    "remove_head3",
    "remove_head4",
    "remove_tail1",
    "remove_tail2",
    "remove_tail3",
    "remove_load1",
    "remove_load2",
    "remove_load3"
  };
  COMPILE_ASSERT(arraysize(folders) == disk_cache::MAX_CRASH, sync_folders);
  DCHECK(action > disk_cache::NO_CRASH && action < disk_cache::MAX_CRASH);

  *full_path = path.AppendASCII(folders[action]);

  if (base::PathExists(*full_path))
    return false;

  return base::CreateDirectory(*full_path);
}

// Makes sure that any pending task is processed.
void FlushQueue(disk_cache::Backend* cache) {
  net::TestCompletionCallback cb;
  int rv =
      reinterpret_cast<disk_cache::BackendImpl*>(cache)->FlushQueueForTest(
          cb.callback());
  cb.GetResult(rv);  // Ignore the result;
}

bool CreateCache(const base::FilePath& path,
                 base::Thread* thread,
                 disk_cache::Backend** cache,
                 net::TestCompletionCallback* cb) {
  int size = 1024 * 1024;
  disk_cache::BackendImpl* backend = new disk_cache::BackendImpl(
      path, thread->message_loop_proxy().get(), NULL);
  backend->SetMaxSize(size);
  backend->SetType(net::DISK_CACHE);
  backend->SetFlags(disk_cache::kNoRandom);
  int rv = backend->Init(cb->callback());
  *cache = backend;
  return (cb->GetResult(rv) == net::OK && !(*cache)->GetEntryCount());
}

// Generates the files for an empty and one item cache.
int SimpleInsert(const base::FilePath& path, RankCrashes action,
                 base::Thread* cache_thread) {
  net::TestCompletionCallback cb;
  disk_cache::Backend* cache;
  if (!CreateCache(path, cache_thread, &cache, &cb))
    return GENERIC;

  const char* test_name = "some other key";

  if (action <= disk_cache::INSERT_EMPTY_3) {
    test_name = kCrashEntryName;
    disk_cache::g_rankings_crash = action;
  }

  disk_cache::Entry* entry;
  int rv = cache->CreateEntry(test_name, &entry, cb.callback());
  if (cb.GetResult(rv) != net::OK)
    return GENERIC;

  entry->Close();
  FlushQueue(cache);

  DCHECK(action <= disk_cache::INSERT_ONE_3);
  disk_cache::g_rankings_crash = action;
  test_name = kCrashEntryName;

  rv = cache->CreateEntry(test_name, &entry, cb.callback());
  if (cb.GetResult(rv) != net::OK)
    return GENERIC;

  return NOT_REACHED;
}

// Generates the files for a one item cache, and removing the head.
int SimpleRemove(const base::FilePath& path, RankCrashes action,
                 base::Thread* cache_thread) {
  DCHECK(action >= disk_cache::REMOVE_ONE_1);
  DCHECK(action <= disk_cache::REMOVE_TAIL_3);

  net::TestCompletionCallback cb;
  disk_cache::Backend* cache;
  if (!CreateCache(path, cache_thread, &cache, &cb))
    return GENERIC;

  disk_cache::Entry* entry;
  int rv = cache->CreateEntry(kCrashEntryName, &entry, cb.callback());
  if (cb.GetResult(rv) != net::OK)
    return GENERIC;

  entry->Close();
  FlushQueue(cache);

  if (action >= disk_cache::REMOVE_TAIL_1) {
    rv = cache->CreateEntry("some other key", &entry, cb.callback());
    if (cb.GetResult(rv) != net::OK)
      return GENERIC;

    entry->Close();
    FlushQueue(cache);
  }

  rv = cache->OpenEntry(kCrashEntryName, &entry, cb.callback());
  if (cb.GetResult(rv) != net::OK)
    return GENERIC;

  disk_cache::g_rankings_crash = action;
  entry->Doom();
  entry->Close();
  FlushQueue(cache);

  return NOT_REACHED;
}

int HeadRemove(const base::FilePath& path, RankCrashes action,
               base::Thread* cache_thread) {
  DCHECK(action >= disk_cache::REMOVE_HEAD_1);
  DCHECK(action <= disk_cache::REMOVE_HEAD_4);

  net::TestCompletionCallback cb;
  disk_cache::Backend* cache;
  if (!CreateCache(path, cache_thread, &cache, &cb))
    return GENERIC;

  disk_cache::Entry* entry;
  int rv = cache->CreateEntry("some other key", &entry, cb.callback());
  if (cb.GetResult(rv) != net::OK)
    return GENERIC;

  entry->Close();
  FlushQueue(cache);
  rv = cache->CreateEntry(kCrashEntryName, &entry, cb.callback());
  if (cb.GetResult(rv) != net::OK)
    return GENERIC;

  entry->Close();
  FlushQueue(cache);

  rv = cache->OpenEntry(kCrashEntryName, &entry, cb.callback());
  if (cb.GetResult(rv) != net::OK)
    return GENERIC;

  disk_cache::g_rankings_crash = action;
  entry->Doom();
  entry->Close();
  FlushQueue(cache);

  return NOT_REACHED;
}

// Generates the files for insertion and removals on heavy loaded caches.
int LoadOperations(const base::FilePath& path, RankCrashes action,
                   base::Thread* cache_thread) {
  DCHECK(action >= disk_cache::INSERT_LOAD_1);

  // Work with a tiny index table (16 entries).
  disk_cache::BackendImpl* cache = new disk_cache::BackendImpl(
      path, 0xf, cache_thread->message_loop_proxy().get(), NULL);
  if (!cache->SetMaxSize(0x100000))
    return GENERIC;

  // No experiments and use a simple LRU.
  cache->SetFlags(disk_cache::kNoRandom);
  net::TestCompletionCallback cb;
  int rv = cache->Init(cb.callback());
  if (cb.GetResult(rv) != net::OK || cache->GetEntryCount())
    return GENERIC;

  int seed = static_cast<int>(Time::Now().ToInternalValue());
  srand(seed);

  disk_cache::Entry* entry;
  for (int i = 0; i < 100; i++) {
    std::string key = GenerateKey(true);
    rv = cache->CreateEntry(key, &entry, cb.callback());
    if (cb.GetResult(rv) != net::OK)
      return GENERIC;
    entry->Close();
    FlushQueue(cache);
    if (50 == i && action >= disk_cache::REMOVE_LOAD_1) {
      rv = cache->CreateEntry(kCrashEntryName, &entry, cb.callback());
      if (cb.GetResult(rv) != net::OK)
        return GENERIC;
      entry->Close();
      FlushQueue(cache);
    }
  }

  if (action <= disk_cache::INSERT_LOAD_2) {
    disk_cache::g_rankings_crash = action;

    rv = cache->CreateEntry(kCrashEntryName, &entry, cb.callback());
    if (cb.GetResult(rv) != net::OK)
      return GENERIC;
  }

  rv = cache->OpenEntry(kCrashEntryName, &entry, cb.callback());
  if (cb.GetResult(rv) != net::OK)
    return GENERIC;

  disk_cache::g_rankings_crash = action;

  entry->Doom();
  entry->Close();
  FlushQueue(cache);

  return NOT_REACHED;
}

// Main function on the child process.
int SlaveCode(const base::FilePath& path, RankCrashes action) {
  base::MessageLoopForIO message_loop;

  base::FilePath full_path;
  if (!CreateTargetFolder(path, action, &full_path)) {
    printf("Destination folder found, please remove it.\n");
    return CRASH_OVERWRITE;
  }

  base::Thread cache_thread("CacheThread");
  if (!cache_thread.StartWithOptions(
          base::Thread::Options(base::MessageLoop::TYPE_IO, 0)))
    return GENERIC;

  if (action <= disk_cache::INSERT_ONE_3)
    return SimpleInsert(full_path, action, &cache_thread);

  if (action <= disk_cache::INSERT_LOAD_2)
    return LoadOperations(full_path, action, &cache_thread);

  if (action <= disk_cache::REMOVE_ONE_4)
    return SimpleRemove(full_path, action, &cache_thread);

  if (action <= disk_cache::REMOVE_HEAD_4)
    return HeadRemove(full_path, action, &cache_thread);

  if (action <= disk_cache::REMOVE_TAIL_3)
    return SimpleRemove(full_path, action, &cache_thread);

  if (action <= disk_cache::REMOVE_LOAD_3)
    return LoadOperations(full_path, action, &cache_thread);

  return NOT_REACHED;
}

// -----------------------------------------------------------------------

int main(int argc, const char* argv[]) {
  // Setup an AtExitManager so Singleton objects will be destructed.
  base::AtExitManager at_exit_manager;

  if (argc < 2)
    return MasterCode();

  char* end;
  RankCrashes action = static_cast<RankCrashes>(strtol(argv[1], &end, 0));
  if (action <= disk_cache::NO_CRASH || action >= disk_cache::MAX_CRASH) {
    printf("Invalid action\n");
    return INVALID_ARGUMENT;
  }

  base::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("new_crashes");

  return SlaveCode(path, action);
}
