// Copyright (c) 2019 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 <cinttypes>
#include <cstdlib>
#include <iostream>
#include <map>
#include <memory>
#include <string>

#include "base/at_exit.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "net/base/cache_type.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/disk_cache/backend_cleanup_tracker.h"
#include "net/disk_cache/blockfile/backend_impl.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/disk_cache_fuzzer.pb.h"
#include "net/disk_cache/disk_cache_test_util.h"
#include "net/disk_cache/memory/mem_backend_impl.h"
#include "net/disk_cache/simple/simple_backend_impl.h"
#include "net/disk_cache/simple/simple_file_tracker.h"
#include "net/disk_cache/simple/simple_index.h"
#include "testing/libfuzzer/proto/lpm_interface.h"

// To get a good idea of what a test case is doing, just run the libfuzzer
// target with LPM_DUMP_NATIVE_INPUT=1 prefixed. This will trigger all the
// prints below and will convey exactly what the test case is doing: use this
// instead of trying to print the protobuf as text.

// For code coverage:
// python ./tools/code_coverage/coverage.py disk_cache_lpm_fuzzer       -b
// out/coverage -o out/report       -c 'out/coverage/disk_cache_lpm_fuzzer
// -runs=0 -workers=24  corpus_disk_cache_simple'       -f net/disk_cache

void IOCallback(std::string io_type, int rv);

namespace {
const uint32_t kMaxSizeKB = 128;  // 128KB maximum.
const uint32_t kMaxSize = kMaxSizeKB * 1024;
const uint32_t kMaxEntrySize = kMaxSize * 2;
const uint32_t kNumStreams = 3;  // All caches seem to have 3 streams. TODO do
                                 // other specialized caches have this?
const uint64_t kFirstSavedTime =
    5;  // Totally random number chosen by dice roll. ;)
const uint32_t kMaxNumMillisToWait = 2019;
const int kMaxFdsSimpleCache = 10;

#define IOTYPES_APPLY(F) \
  F(WriteData)           \
  F(ReadData)            \
  F(WriteSparseData)     \
  F(ReadSparseData)      \
  F(DoomAllEntries)      \
  F(DoomEntriesSince)    \
  F(DoomEntriesBetween)  \
  F(GetAvailableRange)   \
  F(DoomKey)

enum class IOType {
#define ENUM_ENTRY(IO_TYPE) IO_TYPE,
  IOTYPES_APPLY(ENUM_ENTRY)
#undef ENUM_ENTRY
};

struct InitGlobals {
  InitGlobals() {
    base::CommandLine::Init(0, nullptr);

    print_comms_ = ::getenv("LPM_DUMP_NATIVE_INPUT");

    // Mark this thread as an IO_THREAD with MOCK_TIME, and ensure that Now()
    // is driven from the same mock clock.
    task_environment_ = std::make_unique<base::test::TaskEnvironment>(
        base::test::TaskEnvironment::MainThreadType::IO,
        base::test::TaskEnvironment::TimeSource::MOCK_TIME);

    // Disable noisy logging as per "libFuzzer in Chrome" documentation:
    // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging.
    logging::SetMinLogLevel(logging::LOG_FATAL);

    // Re-using this buffer for write operations may technically be against
    // IOBuffer rules but it shouldn't cause any actual problems.
    buffer_ =
        base::MakeRefCounted<net::IOBuffer>(static_cast<size_t>(kMaxEntrySize));
    CacheTestFillBuffer(buffer_->data(), kMaxEntrySize, false);

#define CREATE_IO_CALLBACK(IO_TYPE) \
  io_callbacks_.push_back(base::BindRepeating(&IOCallback, #IO_TYPE));
    IOTYPES_APPLY(CREATE_IO_CALLBACK)
#undef CREATE_IO_CALLBACK
  }

  // This allows us to mock time for all threads.
  std::unique_ptr<base::test::TaskEnvironment> task_environment_;

  // Used as a pre-filled buffer for all writes.
  scoped_refptr<net::IOBuffer> buffer_;

  // Should we print debugging info?
  bool print_comms_;

  // List of IO callbacks. They do nothing (except maybe print) but are used by
  // all async entry operations.
  std::vector<base::RepeatingCallback<void(int)>> io_callbacks_;
};

InitGlobals* init_globals = new InitGlobals();
}  // namespace

class DiskCacheLPMFuzzer {
 public:
  DiskCacheLPMFuzzer() {
    CHECK(temp_dir_.CreateUniqueTempDir());
    cache_path_ = temp_dir_.GetPath();
  }

  ~DiskCacheLPMFuzzer();

  void RunCommands(const disk_cache_fuzzer::FuzzCommands& commands);

 private:
  struct EntryInfo {
    EntryInfo() = default;
    disk_cache::Entry* entry_ptr = nullptr;
    std::unique_ptr<TestEntryResultCompletionCallback> tcb;

    DISALLOW_COPY_AND_ASSIGN(EntryInfo);
  };
  void RunTaskForTest(base::OnceClosure closure);

  // Waits for an entry to be ready. Only should be called if there is a pending
  // callback for this entry; i.e. ei->tcb != nullptr.
  // Also takes the rv that the cache entry creation functions return, and does
  // not wait if rv.net_error != net::ERR_IO_PENDING (and would never have
  // called the callback).
  disk_cache::EntryResult WaitOnEntry(
      EntryInfo* ei,
      disk_cache::EntryResult result =
          disk_cache::EntryResult::MakeError(net::ERR_IO_PENDING));

  // Used as a callback for entry-opening backend calls. Will record the entry
  // in the map as usable and will release any entry-specific calls waiting for
  // the entry to be ready.
  void OpenCacheEntryCallback(uint64_t entry_id,
                              bool async,
                              bool set_is_sparse,
                              disk_cache::EntryResult result);

  // Waits for the entry to finish opening, in the async case. Then, if the
  // entry is successfully open (callback returns net::OK, or was already
  // successfully opened), check if the entry_ptr == nullptr. If so, the
  // entry has been closed.
  bool IsValidEntry(EntryInfo* ei);

  // Closes any non-nullptr entries in open_cache_entries_.
  void CloseAllRemainingEntries();

  void HandleSetMaxSize(const disk_cache_fuzzer::SetMaxSize&);
  void CreateBackend(
      disk_cache_fuzzer::FuzzCommands::CacheBackend cache_backend,
      uint32_t mask,
      net::CacheType type,
      bool simple_cache_wait_for_index);

  // Places to keep our cache files.
  base::FilePath cache_path_;
  base::ScopedTempDir temp_dir_;

  // Pointers to our backend. Only one of block_impl_, simple_cache_impl_, and
  // mem_cache_ are active at one time.
  std::unique_ptr<disk_cache::Backend> cache_;
  disk_cache::BackendImpl* block_impl_ = nullptr;
  std::unique_ptr<disk_cache::SimpleFileTracker> simple_file_tracker_;
  disk_cache::SimpleBackendImpl* simple_cache_impl_ = nullptr;
  disk_cache::MemBackendImpl* mem_cache_ = nullptr;

  // Maximum size of the cache, that we have currently set.
  uint32_t max_size_ = kMaxSize;

  // This "consistent hash table" keeys track of the keys we've added to the
  // backend so far. This should always be indexed by a "key_id" from a
  // protobuf.
  std::map<uint64_t, std::string> created_cache_entries_;
  // This "consistent hash table" keeps track of all opened entries we have from
  // the backend, and also contains some nullptr's where entries were already
  // closed. This should always be indexed by an "entry_id" from a protobuf.
  // When destructed, we close all entries that are still open in order to avoid
  // memory leaks.
  std::map<uint64_t, EntryInfo> open_cache_entries_;
  // This "consistent hash table" keeps track of all times we have saved, so
  // that we can call backend methods like DoomEntriesSince or
  // DoomEntriesBetween with sane timestamps. This should always be indexed by a
  // "time_id" from a protobuf.
  std::map<uint64_t, base::Time> saved_times_;
  // This "consistent hash table" keeps tack of all the iterators we have open
  // from the backend. This should always be indexed by a "it_id" from a
  // protobuf.
  std::map<uint64_t, std::unique_ptr<disk_cache::Backend::Iterator>>
      open_iterators_;

  // This maps keeps track of the sparsity of each entry, using their pointers.
  // TODO(mpdenton) remove if CreateEntry("Key0"); WriteData("Key0", index = 2,
  // ...); WriteSparseData("Key0", ...); is supposed to be valid.
  // Then we can just use CouldBeSparse before the WriteData.
  std::map<disk_cache::Entry*, bool> sparse_entry_tracker_;
};

#define MAYBE_PRINT               \
  if (init_globals->print_comms_) \
  std::cout

inline base::RepeatingCallback<void(int)> GetIOCallback(IOType iot) {
  return init_globals->io_callbacks_[static_cast<int>(iot)];
}

std::string ToKey(uint64_t key_num) {
  return "Key" + std::to_string(key_num);
}

net::RequestPriority GetRequestPriority(
    disk_cache_fuzzer::RequestPriority lpm_pri) {
  CHECK(net::MINIMUM_PRIORITY <= static_cast<int>(lpm_pri) &&
        static_cast<int>(lpm_pri) <= net::MAXIMUM_PRIORITY);
  return static_cast<net::RequestPriority>(lpm_pri);
}

net::CacheType GetCacheTypeAndPrint(
    disk_cache_fuzzer::FuzzCommands::CacheType type,
    disk_cache_fuzzer::FuzzCommands::CacheBackend backend) {
  switch (type) {
    case disk_cache_fuzzer::FuzzCommands::APP_CACHE:
      MAYBE_PRINT << "Cache type = APP_CACHE." << std::endl;
      return net::CacheType::APP_CACHE;
      break;
    case disk_cache_fuzzer::FuzzCommands::MEDIA_CACHE:
      MAYBE_PRINT << "Cache type = MEDIA_CACHE." << std::endl;
      return net::CacheType::MEDIA_CACHE;
      break;
    case disk_cache_fuzzer::FuzzCommands::SHADER_CACHE:
      MAYBE_PRINT << "Cache type = SHADER_CACHE." << std::endl;
      return net::CacheType::SHADER_CACHE;
      break;
    case disk_cache_fuzzer::FuzzCommands::PNACL_CACHE:
      // Simple cache won't handle PNACL_CACHE.
      if (backend == disk_cache_fuzzer::FuzzCommands::SIMPLE) {
        MAYBE_PRINT << "Cache type = DISK_CACHE." << std::endl;
        return net::CacheType::DISK_CACHE;
      }
      MAYBE_PRINT << "Cache type = PNACL_CACHE." << std::endl;
      return net::CacheType::PNACL_CACHE;
      break;
    case disk_cache_fuzzer::FuzzCommands::GENERATED_BYTE_CODE_CACHE:
      MAYBE_PRINT << "Cache type = GENERATED_BYTE_CODE_CACHE." << std::endl;
      return net::CacheType::GENERATED_BYTE_CODE_CACHE;
      break;
    case disk_cache_fuzzer::FuzzCommands::GENERATED_NATIVE_CODE_CACHE:
      MAYBE_PRINT << "Cache type = GENERATED_NATIVE_CODE_CACHE." << std::endl;
      return net::CacheType::GENERATED_NATIVE_CODE_CACHE;
      break;
    case disk_cache_fuzzer::FuzzCommands::DISK_CACHE:
      MAYBE_PRINT << "Cache type = DISK_CACHE." << std::endl;
      return net::CacheType::DISK_CACHE;
      break;
  }
}

void IOCallback(std::string io_type, int rv) {
  MAYBE_PRINT << " [Async IO (" << io_type << ") = " << rv << "]" << std::endl;
}

/*
 * Consistent hashing inspired map for fuzzer state.
 * If we stored open cache entries in a hash table mapping cache_entry_id ->
 * disk_cache::Entry*, then it would be highly unlikely that any subsequent
 * "CloseEntry" or "WriteData" etc. command would come up with an ID that would
 * correspond to a valid entry in the hash table. The optimal solution is for
 * libfuzzer to generate CloseEntry commands with an ID that matches the ID of a
 * previous OpenEntry command. But libfuzzer is stateless and should stay that
 * way.
 *
 * On the other hand, if we stored entries in a vector, and on a CloseEntry
 * command we took the entry at CloseEntry.id % (size of entries vector), we
 * would always generate correct CloseEntries. This is good, but all
 * dumb/general minimization techniques stop working, because deleting a single
 * OpenEntry command changes the indexes of every entry in the vector from then
 * on.
 *
 * So, we use something that's more stable for minimization: consistent hashing.
 * Basically, when we see a CloseEntry.id, we take the entry in the table that
 * has the next highest id (wrapping when there is no higher entry).
 *
 * This makes us resilient to deleting irrelevant OpenEntry commands. But, if we
 * delete from the table on CloseEntry commands, we still screw up all the
 * indexes during minimization. We'll get around this by not deleting entries
 * after CloseEntry commands, but that will result in a slightly less efficient
 * fuzzer, as if there are many closed entries in the table, many of the *Entry
 * commands will be useless. It seems like a decent balance between generating
 * useful fuzz commands and effective minimization.
 */
template <typename T>
typename std::map<uint64_t, T>::iterator GetNextValue(
    typename std::map<uint64_t, T>* entries,
    uint64_t val) {
  auto iter = entries->lower_bound(val);
  if (iter != entries->end())
    return iter;
  // Wrap to 0
  iter = entries->lower_bound(0);
  if (iter != entries->end())
    return iter;

  return entries->end();
}

void DiskCacheLPMFuzzer::RunTaskForTest(base::OnceClosure closure) {
  if (!block_impl_) {
    std::move(closure).Run();
    return;
  }

  net::TestCompletionCallback cb;
  int rv = block_impl_->RunTaskForTest(std::move(closure), cb.callback());
  CHECK_EQ(cb.GetResult(rv), net::OK);
}

// Resets the cb in the map so that WriteData and other calls that work on an
// entry don't wait for its result.
void DiskCacheLPMFuzzer::OpenCacheEntryCallback(
    uint64_t entry_id,
    bool async,
    bool set_is_sparse,
    disk_cache::EntryResult result) {
  // TODO(mpdenton) if this fails should we delete the entry entirely?
  // Would need to mark it for deletion and delete it later, as
  // IsValidEntry might be waiting for it.
  EntryInfo* ei = &open_cache_entries_[entry_id];

  if (async) {
    int rv = result.net_error();
    ei->entry_ptr = result.ReleaseEntry();
    // We are responsible for setting things up.
    if (set_is_sparse && ei->entry_ptr) {
      sparse_entry_tracker_[ei->entry_ptr] = true;
    }
    if (ei->entry_ptr) {
      MAYBE_PRINT << " [Async opening of cache entry for \""
                  << ei->entry_ptr->GetKey() << "\" callback (rv = " << rv
                  << ")]" << std::endl;
    }
    // Unblock any subsequent ops waiting for this --- they don't care about
    // the actual return value, but use something distinctive for debugging.
    ei->tcb->callback().Run(
        disk_cache::EntryResult::MakeError(net::ERR_FILE_VIRUS_INFECTED));
  } else {
    // The operation code will pull the result out of the completion callback,
    // so hand it to it.
    ei->tcb->callback().Run(std::move(result));
  }
}

disk_cache::EntryResult DiskCacheLPMFuzzer::WaitOnEntry(
    EntryInfo* ei,
    disk_cache::EntryResult result) {
  CHECK(ei->tcb);
  result = ei->tcb->GetResult(std::move(result));

  // Reset the callback so nobody accidentally waits on a callback that never
  // comes.
  ei->tcb.reset();
  return result;
}

bool DiskCacheLPMFuzzer::IsValidEntry(EntryInfo* ei) {
  if (ei->tcb) {
    // If we have a callback, we are the first to access this async-created
    // entry. Wait for it, and then delete it so nobody waits on it again.
    WaitOnEntry(ei);
  }
  // entry_ptr will be nullptr if the entry has been closed.
  return ei->entry_ptr != nullptr;
}

/*
 * Async implementation:
 1. RunUntilIdle at the top of the loop to handle any callbacks we've been
 posted from the backend thread.
 2. Only the entry creation functions have important callbacks. The good thing
 is backend destruction will cancel these operations. The entry creation
 functions simply need to keep the entry_ptr* alive until the callback is
 posted, and then need to make sure the entry_ptr is added to the map in order
 to Close it in the destructor.
    As for iterators, it's unclear whether closing an iterator will cancel
 callbacks.

 Problem: WriteData (and similar) calls will fail on the entry_id until the
 callback happens. So, I should probably delay these calls or otherwise will
 have very unreliable test cases. These are the options:
 1. Queue up WriteData (etc.) calls in some map, such that when the OpenEntry
 callback runs, the WriteData calls will all run.
 2. Just sit there and wait for the entry to be ready.

 #2 is probably best as it doesn't prevent any interesting cases and is much
 simpler.
 */

void DiskCacheLPMFuzzer::RunCommands(
    const disk_cache_fuzzer::FuzzCommands& commands) {
  uint32_t mask =
      commands.has_set_mask() ? (commands.set_mask() ? 0x1 : 0xf) : 0;
  net::CacheType type =
      GetCacheTypeAndPrint(commands.cache_type(), commands.cache_backend());
  CreateBackend(commands.cache_backend(), mask, type,
                commands.simple_cache_wait_for_index());
  MAYBE_PRINT << "CreateBackend()" << std::endl;

  if (commands.has_set_max_size()) {
    HandleSetMaxSize(commands.set_max_size());
  }

  {
    base::Time curr_time = base::Time::Now();
    saved_times_[kFirstSavedTime] = curr_time;
    // MAYBE_PRINT << "Saved initial time " << curr_time << std::endl;
  }

  for (const disk_cache_fuzzer::FuzzCommand& command :
       commands.fuzz_commands()) {
    // Handle any callbacks that other threads may have posted to us in the
    // meantime, so any successful async OpenEntry's (etc.) add their
    // entry_ptr's to the map.
    init_globals->task_environment_->RunUntilIdle();

    switch (command.fuzz_command_oneof_case()) {
      case disk_cache_fuzzer::FuzzCommand::kSetMaxSize: {
        HandleSetMaxSize(command.set_max_size());
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kCreateEntry: {
        if (!cache_)
          continue;

        const disk_cache_fuzzer::CreateEntry& ce = command.create_entry();
        uint64_t key_id = ce.key_id();
        uint64_t entry_id = ce.entry_id();
        net::RequestPriority pri = GetRequestPriority(ce.pri());
        bool async = ce.async();
        bool is_sparse = ce.is_sparse();

        if (open_cache_entries_.find(entry_id) != open_cache_entries_.end())
          continue;  // Don't overwrite a currently open cache entry.

        std::string key_str = ToKey(key_id);
        created_cache_entries_[key_id] = key_str;

        EntryInfo* entry_info = &open_cache_entries_[entry_id];

        entry_info->tcb = std::make_unique<TestEntryResultCompletionCallback>();
        disk_cache::EntryResultCallback cb =
            base::BindOnce(&DiskCacheLPMFuzzer::OpenCacheEntryCallback,
                           base::Unretained(this), entry_id, async, is_sparse);

        MAYBE_PRINT << "CreateEntry(\"" << key_str
                    << "\", set_is_sparse = " << is_sparse
                    << ") = " << std::flush;
        disk_cache::EntryResult result =
            cache_->CreateEntry(key_str, pri, std::move(cb));
        if (!async || result.net_error() != net::ERR_IO_PENDING) {
          result = WaitOnEntry(entry_info, std::move(result));
          int rv = result.net_error();

          // Ensure we mark sparsity, save entry if the callback never ran.
          if (rv == net::OK) {
            entry_info->entry_ptr = result.ReleaseEntry();
            sparse_entry_tracker_[entry_info->entry_ptr] = is_sparse;
          }
          MAYBE_PRINT << rv << std::endl;
        } else {
          MAYBE_PRINT << "net::ERR_IO_PENDING (async)" << std::endl;
        }
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kOpenEntry: {
        if (!cache_)
          continue;

        const disk_cache_fuzzer::OpenEntry& oe = command.open_entry();
        uint64_t key_id = oe.key_id();
        uint64_t entry_id = oe.entry_id();
        net::RequestPriority pri = GetRequestPriority(oe.pri());
        bool async = oe.async();

        if (created_cache_entries_.empty())
          continue;

        if (open_cache_entries_.find(entry_id) != open_cache_entries_.end())
          continue;  // Don't overwrite a currently open cache entry.

        EntryInfo* entry_info = &open_cache_entries_[entry_id];

        entry_info->tcb = std::make_unique<TestEntryResultCompletionCallback>();
        disk_cache::EntryResultCallback cb =
            base::BindOnce(&DiskCacheLPMFuzzer::OpenCacheEntryCallback,
                           base::Unretained(this), entry_id, async, false);

        auto key_it = GetNextValue(&created_cache_entries_, key_id);
        MAYBE_PRINT << "OpenEntry(\"" << key_it->second
                    << "\") = " << std::flush;
        disk_cache::EntryResult result =
            cache_->OpenEntry(key_it->second, pri, std::move(cb));
        if (!async || result.net_error() != net::ERR_IO_PENDING) {
          result = WaitOnEntry(entry_info, std::move(result));
          int rv = result.net_error();
          if (rv == net::OK)
            entry_info->entry_ptr = result.ReleaseEntry();
          MAYBE_PRINT << rv << std::endl;
        } else {
          MAYBE_PRINT << "net::ERR_IO_PENDING (async)" << std::endl;
        }
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kOpenOrCreateEntry: {
        if (!cache_)
          continue;

        const disk_cache_fuzzer::OpenOrCreateEntry& ooce =
            command.open_or_create_entry();
        uint64_t key_id = ooce.key_id();
        uint64_t entry_id = ooce.entry_id();
        net::RequestPriority pri = GetRequestPriority(ooce.pri());
        bool async = ooce.async();
        bool is_sparse = ooce.is_sparse();

        if (open_cache_entries_.find(entry_id) != open_cache_entries_.end())
          continue;  // Don't overwrite a currently open cache entry.

        std::string key_str;
        // If our proto tells us to create a new entry, create a new entry, just
        // with OpenOrCreateEntry.
        if (ooce.create_new()) {
          // Use a possibly new key.
          key_str = ToKey(key_id);
          created_cache_entries_[key_id] = key_str;
        } else {
          if (created_cache_entries_.empty())
            continue;
          auto key_it = GetNextValue(&created_cache_entries_, key_id);
          key_str = key_it->second;
        }

        // Setup for callbacks.

        EntryInfo* entry_info = &open_cache_entries_[entry_id];

        entry_info->tcb = std::make_unique<TestEntryResultCompletionCallback>();
        disk_cache::EntryResultCallback cb =
            base::BindOnce(&DiskCacheLPMFuzzer::OpenCacheEntryCallback,
                           base::Unretained(this), entry_id, async, is_sparse);

        // Will only be set as sparse if it is created and not opened.
        MAYBE_PRINT << "OpenOrCreateEntry(\"" << key_str
                    << "\", set_is_sparse = " << is_sparse
                    << ") = " << std::flush;
        disk_cache::EntryResult result =
            cache_->OpenOrCreateEntry(key_str, pri, std::move(cb));
        if (!async || result.net_error() != net::ERR_IO_PENDING) {
          result = WaitOnEntry(entry_info, std::move(result));
          int rv = result.net_error();
          bool opened = result.opened();
          entry_info->entry_ptr = result.ReleaseEntry();
          // Ensure we mark sparsity, even if the callback never ran.
          if (rv == net::OK && !opened)
            sparse_entry_tracker_[entry_info->entry_ptr] = is_sparse;
          MAYBE_PRINT << rv << ", opened = " << opened << std::endl;
        } else {
          MAYBE_PRINT << "net::ERR_IO_PENDING (async)" << std::endl;
        }
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kCloseEntry: {
        if (open_cache_entries_.empty())
          continue;

        auto entry_it = GetNextValue(&open_cache_entries_,
                                     command.close_entry().entry_id());
        if (!IsValidEntry(&entry_it->second))
          continue;

        MAYBE_PRINT << "CloseEntry(\"" << entry_it->second.entry_ptr->GetKey()
                    << "\")" << std::endl;
        entry_it->second.entry_ptr->Close();

        // Set the entry_ptr to nullptr to ensure no one uses it anymore.
        entry_it->second.entry_ptr = nullptr;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kDoomEntry: {
        if (open_cache_entries_.empty())
          continue;

        auto entry_it =
            GetNextValue(&open_cache_entries_, command.doom_entry().entry_id());
        if (!IsValidEntry(&entry_it->second))
          continue;

        MAYBE_PRINT << "DoomEntry(\"" << entry_it->second.entry_ptr->GetKey()
                    << "\")" << std::endl;
        entry_it->second.entry_ptr->Doom();
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kWriteData: {
        if (open_cache_entries_.empty())
          continue;

        const disk_cache_fuzzer::WriteData& wd = command.write_data();
        auto entry_it = GetNextValue(&open_cache_entries_, wd.entry_id());
        if (!IsValidEntry(&entry_it->second))
          continue;

        int index = 0;  // if it's sparse, these non-sparse aware streams must
                        // read from stream 0 according to the spec.
                        // Implementations might have weaker constraints.
        if (!sparse_entry_tracker_[entry_it->second.entry_ptr])
          index = wd.index() % kNumStreams;
        uint32_t offset = wd.offset() % kMaxEntrySize;
        size_t size = wd.size() % kMaxEntrySize;
        bool async = wd.async();

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : GetIOCallback(IOType::WriteData);

        MAYBE_PRINT << "WriteData(\"" << entry_it->second.entry_ptr->GetKey()
                    << "\", index = " << index << ", offset = " << offset
                    << ", size = " << size << ", truncate = " << wd.truncate()
                    << ")" << std::flush;
        int rv = entry_it->second.entry_ptr->WriteData(
            index, offset, init_globals->buffer_.get(), size, std::move(cb),
            wd.truncate());
        if (!async)
          rv = tcb.GetResult(rv);
        MAYBE_PRINT << " = " << rv << std::endl;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kReadData: {
        if (open_cache_entries_.empty())
          continue;

        const disk_cache_fuzzer::ReadData& wd = command.read_data();
        auto entry_it = GetNextValue(&open_cache_entries_, wd.entry_id());
        if (!IsValidEntry(&entry_it->second))
          continue;

        int index = 0;  // if it's sparse, these non-sparse aware streams must
                        // read from stream 0 according to the spec.
                        // Implementations might weaker constraints?
        if (!sparse_entry_tracker_[entry_it->second.entry_ptr])
          index = wd.index() % kNumStreams;
        uint32_t offset = wd.offset() % kMaxEntrySize;
        size_t size = wd.size() % kMaxEntrySize;
        bool async = wd.async();
        scoped_refptr<net::IOBuffer> buffer =
            base::MakeRefCounted<net::IOBuffer>(size);

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : GetIOCallback(IOType::ReadData);

        MAYBE_PRINT << "ReadData(\"" << entry_it->second.entry_ptr->GetKey()
                    << "\", index = " << index << ", offset = " << offset
                    << ", size = " << size << ")" << std::flush;
        int rv = entry_it->second.entry_ptr->ReadData(
            index, offset, buffer.get(), size, std::move(cb));
        if (!async)
          rv = tcb.GetResult(rv);
        MAYBE_PRINT << " = " << rv << std::endl;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kWriteSparseData: {
        if (open_cache_entries_.empty())
          continue;

        const disk_cache_fuzzer::WriteSparseData& wsd =
            command.write_sparse_data();
        auto entry_it = GetNextValue(&open_cache_entries_, wsd.entry_id());
        if (!IsValidEntry(&entry_it->second) ||
            !sparse_entry_tracker_[entry_it->second.entry_ptr])
          continue;

        uint64_t offset = wsd.offset();
        if (wsd.cap_offset())
          offset %= kMaxEntrySize;
        size_t size = wsd.size() % kMaxEntrySize;
        bool async = wsd.async();

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : GetIOCallback(IOType::WriteSparseData);
        MAYBE_PRINT << "WriteSparseData(\""
                    << entry_it->second.entry_ptr->GetKey()
                    << "\", offset = " << offset << ", size = " << size << ")"
                    << std::flush;
        int rv = entry_it->second.entry_ptr->WriteSparseData(
            offset, init_globals->buffer_.get(), size, std::move(cb));
        if (!async)
          rv = tcb.GetResult(rv);
        MAYBE_PRINT << " = " << rv << std::endl;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kReadSparseData: {
        if (open_cache_entries_.empty())
          continue;

        const disk_cache_fuzzer::ReadSparseData& rsd =
            command.read_sparse_data();
        auto entry_it = GetNextValue(&open_cache_entries_, rsd.entry_id());
        if (!IsValidEntry(&entry_it->second) ||
            !sparse_entry_tracker_[entry_it->second.entry_ptr])
          continue;

        uint64_t offset = rsd.offset();
        if (rsd.cap_offset())
          offset %= kMaxEntrySize;
        size_t size = rsd.size() % kMaxEntrySize;
        bool async = rsd.async();
        scoped_refptr<net::IOBuffer> buffer =
            base::MakeRefCounted<net::IOBuffer>(size);

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : GetIOCallback(IOType::ReadSparseData);

        MAYBE_PRINT << "ReadSparseData(\""
                    << entry_it->second.entry_ptr->GetKey()
                    << "\", offset = " << offset << ", size = " << size << ")"
                    << std::flush;
        int rv = entry_it->second.entry_ptr->ReadSparseData(
            offset, buffer.get(), size, std::move(cb));
        if (!async)
          rv = tcb.GetResult(rv);
        MAYBE_PRINT << " = " << rv << std::endl;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kDoomAllEntries: {
        if (!cache_)
          continue;
        bool async = command.doom_all_entries().async();

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : GetIOCallback(IOType::DoomAllEntries);
        MAYBE_PRINT << "DoomAllEntries()" << std::flush;
        int rv = cache_->DoomAllEntries(std::move(cb));
        if (!async)
          rv = tcb.GetResult(rv);
        MAYBE_PRINT << " = " << rv << std::endl;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kFlushQueueForTest: {
        // Blockfile-cache specific method.
        if (!block_impl_)
          return;

        net::TestCompletionCallback cb;
        MAYBE_PRINT << "FlushQueueForTest()" << std::endl;
        int rv = block_impl_->FlushQueueForTest(cb.callback());
        CHECK_EQ(cb.GetResult(rv), net::OK);
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kCreateIterator: {
        if (!cache_)
          continue;
        uint64_t it_id = command.create_iterator().it_id();
        MAYBE_PRINT << "CreateIterator(), id = " << it_id << std::endl;
        open_iterators_[it_id] = cache_->CreateIterator();
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kIteratorOpenNextEntry: {
        const disk_cache_fuzzer::IteratorOpenNextEntry& ione =
            command.iterator_open_next_entry();

        uint64_t it_id = ione.it_id();
        uint64_t entry_id = ione.entry_id();
        bool async = ione.async();

        if (open_iterators_.empty())
          continue;

        if (open_cache_entries_.find(entry_id) != open_cache_entries_.end())
          continue;  // Don't overwrite a currently
                     // open cache entry.

        auto iterator_it = GetNextValue(&open_iterators_, it_id);

        EntryInfo* entry_info = &open_cache_entries_[entry_id];

        entry_info->tcb = std::make_unique<TestEntryResultCompletionCallback>();
        disk_cache::EntryResultCallback cb =
            base::BindOnce(&DiskCacheLPMFuzzer::OpenCacheEntryCallback,
                           base::Unretained(this), entry_id, async, false);

        MAYBE_PRINT << "Iterator(" << ione.it_id()
                    << ").OpenNextEntry() = " << std::flush;
        disk_cache::EntryResult result =
            iterator_it->second->OpenNextEntry(std::move(cb));
        if (!async || result.net_error() != net::ERR_IO_PENDING) {
          result = WaitOnEntry(entry_info, std::move(result));
          int rv = result.net_error();
          entry_info->entry_ptr = result.ReleaseEntry();
          // Print return value, and key if applicable.
          if (!entry_info->entry_ptr) {
            MAYBE_PRINT << rv << std::endl;
          } else {
            MAYBE_PRINT << rv << ", key = " << entry_info->entry_ptr->GetKey()
                        << std::endl;
          }
        } else {
          MAYBE_PRINT << "net::ERR_IO_PENDING (async)" << std::endl;
        }
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kFastForwardBy: {
        base::TimeDelta to_wait = base::TimeDelta::FromMilliseconds(
            command.fast_forward_by().capped_num_millis() %
            kMaxNumMillisToWait);
        MAYBE_PRINT << "FastForwardBy(" << to_wait << ")" << std::endl;
        init_globals->task_environment_->FastForwardBy(to_wait);

        base::Time curr_time = base::Time::Now();
        saved_times_[command.fast_forward_by().time_id()] = curr_time;
        // MAYBE_PRINT << "Saved time " << curr_time << std::endl;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kDoomEntriesSince: {
        if (!cache_)
          continue;
        // App cache does not keep track of LRU timestamps so this method cannot
        // be used.
        if (type == net::APP_CACHE)
          continue;
        if (saved_times_.empty())
          continue;

        const disk_cache_fuzzer::DoomEntriesSince& des =
            command.doom_entries_since();
        auto time_it = GetNextValue(&saved_times_, des.time_id());
        bool async = des.async();

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : GetIOCallback(IOType::DoomEntriesSince);

        MAYBE_PRINT << "DoomEntriesSince(" << time_it->second << ")"
                    << std::flush;
        int rv = cache_->DoomEntriesSince(time_it->second, std::move(cb));
        if (!async)
          rv = tcb.GetResult(rv);
        MAYBE_PRINT << " = " << rv << std::endl;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kDoomEntriesBetween: {
        if (!cache_)
          continue;
        // App cache does not keep track of LRU timestamps so this method cannot
        // be used.
        if (type == net::APP_CACHE)
          continue;
        if (saved_times_.empty())
          continue;

        const disk_cache_fuzzer::DoomEntriesBetween& deb =
            command.doom_entries_between();
        auto time_it1 = GetNextValue(&saved_times_, deb.time_id1());
        auto time_it2 = GetNextValue(&saved_times_, deb.time_id2());
        base::Time time1 = time_it1->second;
        base::Time time2 = time_it2->second;
        if (time1 > time2)
          std::swap(time1, time2);
        bool async = deb.async();

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : GetIOCallback(IOType::DoomEntriesBetween);

        MAYBE_PRINT << "DoomEntriesBetween(" << time1 << ", " << time2 << ")"
                    << std::flush;
        int rv = cache_->DoomEntriesBetween(time1, time2, std::move(cb));
        if (!async)
          rv = tcb.GetResult(rv);
        MAYBE_PRINT << " = " << rv << std::endl;
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kOnExternalCacheHit: {
        if (!cache_)
          continue;
        if (created_cache_entries_.empty())
          continue;

        uint64_t key_id = command.on_external_cache_hit().key_id();

        auto key_it = GetNextValue(&created_cache_entries_, key_id);
        MAYBE_PRINT << "OnExternalCacheHit(\"" << key_it->second << "\")"
                    << std::endl;
        cache_->OnExternalCacheHit(key_it->second);
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kTrimForTest: {
        // Blockfile-cache specific method.
        if (!block_impl_ || type != net::DISK_CACHE)
          return;

        MAYBE_PRINT << "TrimForTest()" << std::endl;

        RunTaskForTest(base::BindOnce(&disk_cache::BackendImpl::TrimForTest,
                                      base::Unretained(block_impl_),
                                      command.trim_for_test().empty()));
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kTrimDeletedListForTest: {
        // Blockfile-cache specific method.
        if (!block_impl_ || type != net::DISK_CACHE)
          return;

        MAYBE_PRINT << "TrimDeletedListForTest()" << std::endl;

        RunTaskForTest(
            base::BindOnce(&disk_cache::BackendImpl::TrimDeletedListForTest,
                           base::Unretained(block_impl_),
                           command.trim_deleted_list_for_test().empty()));
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kGetAvailableRange: {
        if (open_cache_entries_.empty())
          continue;

        const disk_cache_fuzzer::GetAvailableRange& gar =
            command.get_available_range();
        auto entry_it = GetNextValue(&open_cache_entries_, gar.entry_id());
        if (!IsValidEntry(&entry_it->second) ||
            !sparse_entry_tracker_[entry_it->second.entry_ptr])
          continue;

        disk_cache::Entry* entry = entry_it->second.entry_ptr;
        uint32_t offset = gar.offset() % kMaxEntrySize;
        uint32_t len = gar.len() % kMaxEntrySize;
        bool async = gar.async();
        auto start = base::MakeRefCounted<base::RefCountedData<int64_t>>();
        // Raw pointer will stay alive until the end of this command for sure,
        // as we hold a reference to the object.
        int64_t* start_tmp = &start->data;

        auto result_checker = base::BindRepeating(
            [](net::CompletionOnceCallback callback,
               scoped_refptr<base::RefCountedData<int64_t>> start,
               uint32_t offset, uint32_t len, int rv) {
              std::move(callback).Run(rv);

              if (rv < 0)
                return;

              int64_t* start_tmp = &start->data;
              CHECK_LE(offset, *start_tmp);
              CHECK_LE(*start_tmp, offset + len);
              CHECK_LE(*start_tmp + rv, offset + len);
              // Offsets are capped by kMaxEntrySize
              CHECK_LE(*start_tmp, kMaxEntrySize);
              // And size are also capped by kMaxEntrySize
              CHECK_LE(*start_tmp + rv, kMaxEntrySize * 2);
            },
            GetIOCallback(IOType::GetAvailableRange), start, offset, len);

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : result_checker;

        MAYBE_PRINT << "GetAvailableRange(\"" << entry->GetKey() << "\", "
                    << offset << ", " << len << ")" << std::flush;
        int rv =
            entry->GetAvailableRange(offset, len, start_tmp, std::move(cb));

        if (rv != net::ERR_IO_PENDING) {
          // Run the checker callback ourselves.
          result_checker.Run(rv);
        } else if (!async) {
          // In this case the callback will be run by the backend, so we don't
          // need to do it manually.
          rv = tcb.GetResult(rv);
        }

        // Finally, take care of printing.
        if (async && rv == net::ERR_IO_PENDING) {
          MAYBE_PRINT << " = net::ERR_IO_PENDING (async)" << std::endl;
        } else {
          MAYBE_PRINT << " = " << rv << ", *start = " << *start_tmp;
          if (rv < 0) {
            MAYBE_PRINT << ", error to string: " << net::ErrorToShortString(rv)
                        << std::endl;
          } else {
            MAYBE_PRINT << std::endl;
          }
        }
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kCancelSparseIo: {
        if (open_cache_entries_.empty())
          continue;

        const disk_cache_fuzzer::CancelSparseIO& csio =
            command.cancel_sparse_io();
        auto entry_it = GetNextValue(&open_cache_entries_, csio.entry_id());
        if (!IsValidEntry(&entry_it->second))
          continue;

        MAYBE_PRINT << "CancelSparseIO(\""
                    << entry_it->second.entry_ptr->GetKey() << "\")"
                    << std::endl;
        entry_it->second.entry_ptr->CancelSparseIO();
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kDoomKey: {
        if (!cache_)
          continue;
        if (created_cache_entries_.empty())
          continue;

        const disk_cache_fuzzer::DoomKey& dk = command.doom_key();
        uint64_t key_id = dk.key_id();
        net::RequestPriority pri = GetRequestPriority(dk.pri());
        bool async = dk.async();

        auto key_it = GetNextValue(&created_cache_entries_, key_id);

        net::TestCompletionCallback tcb;
        net::CompletionOnceCallback cb =
            !async ? tcb.callback() : GetIOCallback(IOType::DoomKey);

        MAYBE_PRINT << "DoomKey(\"" << key_it->second << "\")" << std::flush;
        int rv = cache_->DoomEntry(key_it->second, pri, std::move(cb));
        if (!async)
          rv = tcb.GetResult(rv);
        MAYBE_PRINT << " = " << rv << std::endl;

        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kDestructBackend: {
        // Block_impl_ will leak if we destruct the backend without closing
        // previous entries.
        // TODO(mpdenton) consider creating a separate fuzz target that allows
        // closing the |block_impl_| and ignore leaks.
        if (block_impl_ || !cache_)
          continue;

        const disk_cache_fuzzer::DestructBackend& db =
            command.destruct_backend();
        // Only sometimes actually destruct the backend.
        if (!db.actually_destruct1() || !db.actually_destruct2())
          continue;

        MAYBE_PRINT << "~Backend(). Backend destruction." << std::endl;
        cache_.reset();
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::kAddRealDelay: {
        if (!command.add_real_delay().actually_delay())
          continue;

        MAYBE_PRINT << "AddRealDelay(1ms)" << std::endl;
        base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
        break;
      }
      case disk_cache_fuzzer::FuzzCommand::FUZZ_COMMAND_ONEOF_NOT_SET: {
        continue;
        break;
      }
    }
  }
}

void DiskCacheLPMFuzzer::HandleSetMaxSize(
    const disk_cache_fuzzer::SetMaxSize& sms) {
  if (!cache_)
    return;

  max_size_ = sms.size();
  max_size_ %= kMaxSizeKB;
  max_size_ *= 1024;
  MAYBE_PRINT << "SetMaxSize(" << max_size_ << ")" << std::endl;
  if (simple_cache_impl_)
    CHECK_EQ(true, simple_cache_impl_->SetMaxSize(max_size_));

  if (block_impl_)
    CHECK_EQ(true, block_impl_->SetMaxSize(max_size_));

  if (mem_cache_)
    CHECK_EQ(true, mem_cache_->SetMaxSize(max_size_));
}

void DiskCacheLPMFuzzer::CreateBackend(
    disk_cache_fuzzer::FuzzCommands::CacheBackend cache_backend,
    uint32_t mask,
    net::CacheType type,
    bool simple_cache_wait_for_index) {
  if (cache_backend == disk_cache_fuzzer::FuzzCommands::IN_MEMORY) {
    MAYBE_PRINT << "Using in-memory cache." << std::endl;
    mem_cache_ = new disk_cache::MemBackendImpl(nullptr);
    cache_.reset(mem_cache_);
    CHECK(cache_);
  } else if (cache_backend == disk_cache_fuzzer::FuzzCommands::SIMPLE) {
    MAYBE_PRINT << "Using simple cache." << std::endl;
    net::TestCompletionCallback cb;
    // We limit ourselves to 64 fds since OS X by default gives us 256.
    // (Chrome raises the number on startup, but the fuzzer doesn't).
    if (!simple_file_tracker_)
      simple_file_tracker_ =
          std::make_unique<disk_cache::SimpleFileTracker>(kMaxFdsSimpleCache);
    std::unique_ptr<disk_cache::SimpleBackendImpl> simple_backend =
        std::make_unique<disk_cache::SimpleBackendImpl>(
            cache_path_, /* cleanup_tracker = */ nullptr,
            simple_file_tracker_.get(), max_size_, type,
            /*net_log = */ nullptr);
    int rv = simple_backend->Init(cb.callback());
    CHECK_EQ(cb.GetResult(rv), net::OK);
    simple_cache_impl_ = simple_backend.get();
    cache_ = std::move(simple_backend);

    if (simple_cache_wait_for_index) {
      MAYBE_PRINT << "Waiting for simple cache index to be ready..."
                  << std::endl;
      net::TestCompletionCallback wait_for_index_cb;
      simple_cache_impl_->index()->ExecuteWhenReady(
          wait_for_index_cb.callback());
      rv = wait_for_index_cb.WaitForResult();
      CHECK_EQ(rv, net::OK);
    }
  } else {
    MAYBE_PRINT << "Using blockfile cache";

    if (mask) {
      MAYBE_PRINT << ", mask = " << mask << std::endl;
      block_impl_ = new disk_cache::BackendImpl(cache_path_, mask,
                                                /* runner = */ nullptr, type,
                                                /* net_log = */ nullptr);
    } else {
      MAYBE_PRINT << "." << std::endl;
      block_impl_ = new disk_cache::BackendImpl(cache_path_,
                                                /* cleanup_tracker = */ nullptr,
                                                /* runner = */ nullptr, type,
                                                /* net_log = */ nullptr);
    }
    cache_.reset(block_impl_);
    CHECK(cache_);
    // TODO(mpdenton) kNoRandom or not? It does a lot of waiting for IO. May be
    // good for avoiding leaks but tests a less realistic cache.
    // block_impl_->SetFlags(disk_cache::kNoRandom);

    // TODO(mpdenton) should I always wait here?
    net::TestCompletionCallback cb;
    int rv = block_impl_->Init(cb.callback());
    CHECK_EQ(cb.GetResult(rv), net::OK);
  }
}

void DiskCacheLPMFuzzer::CloseAllRemainingEntries() {
  for (auto& entry_info : open_cache_entries_) {
    disk_cache::Entry** entry_ptr = &entry_info.second.entry_ptr;
    if (!*entry_ptr)
      continue;
    MAYBE_PRINT << "Destructor CloseEntry(\"" << (*entry_ptr)->GetKey() << "\")"
                << std::endl;
    (*entry_ptr)->Close();
    *entry_ptr = nullptr;
  }
}

DiskCacheLPMFuzzer::~DiskCacheLPMFuzzer() {
  // |block_impl_| leaks a lot more if we don't close entries before destructing
  // the backend.
  if (block_impl_) {
    // TODO(mpdenton) Consider creating a fuzz target that does not wait for
    // blockfile, and also does not detect leaks.

    // Because the blockfile backend will leak any entries closed after its
    // destruction, we need to wait for any remaining backend callbacks to
    // finish. Otherwise, there will always be a race between handling callbacks
    // with RunUntilIdle() and actually closing all of the remaining entries.
    // And, closing entries after destructing the backend will not work and
    // cause leaks.
    for (auto& entry_it : open_cache_entries_) {
      if (entry_it.second.tcb) {
        WaitOnEntry(&entry_it.second);
      }
    }

    // Destroy any open iterators before destructing the backend so we don't
    // cause leaks. TODO(mpdenton) should maybe be documented?
    // Also *must* happen after waiting for all OpenNextEntry callbacks to
    // finish, because destructing the iterators may cause those callbacks to be
    // cancelled, which will cause WaitOnEntry() to spin forever waiting.
    // TODO(mpdenton) should also be documented?
    open_iterators_.clear();
    // Just in case, finish any callbacks.
    init_globals->task_environment_->RunUntilIdle();
    // Close all entries that haven't been closed yet.
    CloseAllRemainingEntries();
    // Destroy the backend.
    cache_.reset();
  } else {
    // Here we won't bother with waiting for our OpenEntry* callbacks.
    cache_.reset();
    // Finish any callbacks that came in before backend destruction.
    init_globals->task_environment_->RunUntilIdle();
    // Close all entries that haven't been closed yet.
    CloseAllRemainingEntries();
  }

  // Make sure any tasks triggered by the CloseEntry's have run.
  init_globals->task_environment_->RunUntilIdle();
  if (simple_cache_impl_)
    CHECK(simple_file_tracker_->IsEmptyForTesting());
  base::RunLoop().RunUntilIdle();

  DeleteCache(cache_path_);
}

DEFINE_BINARY_PROTO_FUZZER(const disk_cache_fuzzer::FuzzCommands& commands) {
  {
    DiskCacheLPMFuzzer disk_cache_fuzzer_instance;
    disk_cache_fuzzer_instance.RunCommands(commands);
  }
  MAYBE_PRINT << "-----------------------" << std::endl;
}
//
