// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/mock_http_cache.h"

#include <algorithm>
#include <limits>
#include <memory>
#include <utility>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/task/single_thread_task_runner.h"
#include "net/base/features.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/disk_cache_test_util.h"
#include "net/http/http_cache_writers.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {

namespace {

// During testing, we are going to limit the size of a cache entry to this many
// bytes using DCHECKs in order to prevent a test from causing unbounded memory
// growth. In practice cache entry shouldn't come anywhere near this limit for
// tests that use the mock cache. If they do, that's likely a problem with the
// test. If a test requires using massive cache entries, they should use a real
// cache backend instead.
const int kMaxMockCacheEntrySize = 100 * 1000 * 1000;

// We can override the test mode for a given operation by setting this global
// variable.
int g_test_mode = 0;

int GetTestModeForEntry(const std::string& key) {
  GURL url(HttpCache::GetResourceURLFromHttpCacheKey(key));
  const MockTransaction* t = FindMockTransaction(url);
  DCHECK(t);
  return t->test_mode;
}

}  // namespace

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

struct MockDiskEntry::CallbackInfo {
  scoped_refptr<MockDiskEntry> entry;
  base::OnceClosure callback;
};

MockDiskEntry::MockDiskEntry(const std::string& key)
    : key_(key), max_file_size_(std::numeric_limits<int>::max()) {
  test_mode_ = GetTestModeForEntry(key);
}

void MockDiskEntry::Doom() {
  doomed_ = true;
}

void MockDiskEntry::Close() {
  Release();
}

std::string MockDiskEntry::GetKey() const {
  return key_;
}

base::Time MockDiskEntry::GetLastUsed() const {
  return base::Time::Now();
}

base::Time MockDiskEntry::GetLastModified() const {
  return base::Time::Now();
}

int32_t MockDiskEntry::GetDataSize(int index) const {
  DCHECK(index >= 0 && index < kNumCacheEntryDataIndices);
  return static_cast<int32_t>(data_[index].size());
}

int MockDiskEntry::ReadData(int index,
                            int offset,
                            IOBuffer* buf,
                            int buf_len,
                            CompletionOnceCallback callback) {
  DCHECK(index >= 0 && index < kNumCacheEntryDataIndices);
  DCHECK(!callback.is_null());

  if (fail_requests_ & FAIL_READ)
    return ERR_CACHE_READ_FAILURE;

  if (offset < 0 || offset > static_cast<int>(data_[index].size()))
    return ERR_FAILED;
  if (static_cast<size_t>(offset) == data_[index].size())
    return 0;

  int num = std::min(buf_len, static_cast<int>(data_[index].size()) - offset);
  memcpy(buf->data(), &data_[index][offset], num);

  if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ)
    return num;

  // Pause and resume.
  if (defer_op_ == DEFER_READ) {
    defer_op_ = DEFER_NONE;
    resume_callback_ = std::move(callback);
    resume_return_code_ = num;
    return ERR_IO_PENDING;
  }

  CallbackLater(std::move(callback), num);
  return ERR_IO_PENDING;
}

void MockDiskEntry::ResumeDiskEntryOperation() {
  DCHECK(!resume_callback_.is_null());
  CallbackLater(std::move(resume_callback_), resume_return_code_);
  resume_return_code_ = 0;
}

int MockDiskEntry::WriteData(int index,
                             int offset,
                             IOBuffer* buf,
                             int buf_len,
                             CompletionOnceCallback callback,
                             bool truncate) {
  DCHECK(index >= 0 && index < kNumCacheEntryDataIndices);
  DCHECK(!callback.is_null());
  DCHECK(truncate);

  if (fail_requests_ & FAIL_WRITE) {
    CallbackLater(std::move(callback), ERR_CACHE_READ_FAILURE);
    return ERR_IO_PENDING;
  }

  if (offset < 0 || offset > static_cast<int>(data_[index].size()))
    return ERR_FAILED;

  DCHECK_LT(offset + buf_len, kMaxMockCacheEntrySize);
  if (offset + buf_len > max_file_size_ && index == 1)
    return net::ERR_FAILED;

  data_[index].resize(offset + buf_len);
  if (buf_len)
    memcpy(&data_[index][offset], buf->data(), buf_len);

  if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE)
    return buf_len;

  if (defer_op_ == DEFER_WRITE) {
    defer_op_ = DEFER_NONE;
    resume_callback_ = std::move(callback);
    resume_return_code_ = buf_len;
    return ERR_IO_PENDING;
  }

  CallbackLater(std::move(callback), buf_len);
  return ERR_IO_PENDING;
}

int MockDiskEntry::ReadSparseData(int64_t offset,
                                  IOBuffer* buf,
                                  int buf_len,
                                  CompletionOnceCallback callback) {
  DCHECK(!callback.is_null());
  if (fail_sparse_requests_)
    return ERR_NOT_IMPLEMENTED;
  if (!sparse_ || busy_ || cancel_)
    return ERR_CACHE_OPERATION_NOT_SUPPORTED;
  if (offset < 0)
    return ERR_FAILED;

  if (fail_requests_ & FAIL_READ_SPARSE)
    return ERR_CACHE_READ_FAILURE;

  DCHECK(offset < std::numeric_limits<int32_t>::max());
  int real_offset = static_cast<int>(offset);
  if (!buf_len)
    return 0;

  int num = std::min(static_cast<int>(data_[1].size()) - real_offset,
                     buf_len);
  memcpy(buf->data(), &data_[1][real_offset], num);

  if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ)
    return num;

  CallbackLater(std::move(callback), num);
  busy_ = true;
  delayed_ = false;
  return ERR_IO_PENDING;
}

int MockDiskEntry::WriteSparseData(int64_t offset,
                                   IOBuffer* buf,
                                   int buf_len,
                                   CompletionOnceCallback callback) {
  DCHECK(!callback.is_null());
  if (fail_sparse_requests_)
    return ERR_NOT_IMPLEMENTED;
  if (busy_ || cancel_)
    return ERR_CACHE_OPERATION_NOT_SUPPORTED;
  if (!sparse_) {
    if (data_[1].size())
      return ERR_CACHE_OPERATION_NOT_SUPPORTED;
    sparse_ = true;
  }
  if (offset < 0)
    return ERR_FAILED;
  if (!buf_len)
    return 0;

  if (fail_requests_ & FAIL_WRITE_SPARSE)
    return ERR_CACHE_READ_FAILURE;

  DCHECK(offset < std::numeric_limits<int32_t>::max());
  int real_offset = static_cast<int>(offset);

  if (static_cast<int>(data_[1].size()) < real_offset + buf_len) {
    DCHECK_LT(real_offset + buf_len, kMaxMockCacheEntrySize);
    data_[1].resize(real_offset + buf_len);
  }

  memcpy(&data_[1][real_offset], buf->data(), buf_len);
  if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE)
    return buf_len;

  CallbackLater(std::move(callback), buf_len);
  return ERR_IO_PENDING;
}

disk_cache::RangeResult MockDiskEntry::GetAvailableRange(
    int64_t offset,
    int len,
    RangeResultCallback callback) {
  DCHECK(!callback.is_null());
  if (!sparse_ || busy_ || cancel_)
    return RangeResult(ERR_CACHE_OPERATION_NOT_SUPPORTED);
  if (offset < 0)
    return RangeResult(ERR_FAILED);

  if (fail_requests_ & FAIL_GET_AVAILABLE_RANGE)
    return RangeResult(ERR_CACHE_READ_FAILURE);

  RangeResult result;
  result.net_error = OK;
  result.start = offset;
  result.available_len = 0;
  DCHECK(offset < std::numeric_limits<int32_t>::max());
  int real_offset = static_cast<int>(offset);
  if (static_cast<int>(data_[1].size()) < real_offset)
    return result;

  int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len);
  for (; num > 0; num--, real_offset++) {
    if (!result.available_len) {
      if (data_[1][real_offset]) {
        result.available_len++;
        result.start = real_offset;
      }
    } else {
      if (!data_[1][real_offset])
        break;
      result.available_len++;
    }
  }
  if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) {
    return result;
  }

  CallbackLater(base::BindOnce(std::move(callback), result));
  return RangeResult(ERR_IO_PENDING);
}

bool MockDiskEntry::CouldBeSparse() const {
  if (fail_sparse_requests_)
    return false;
  return sparse_;
}

void MockDiskEntry::CancelSparseIO() {
  cancel_ = true;
}

net::Error MockDiskEntry::ReadyForSparseIO(CompletionOnceCallback callback) {
  if (fail_sparse_requests_)
    return ERR_NOT_IMPLEMENTED;
  if (!cancel_)
    return OK;

  cancel_ = false;
  DCHECK(!callback.is_null());
  if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ)
    return OK;

  // The pending operation is already in the message loop (and hopefully
  // already in the second pass).  Just notify the caller that it finished.
  CallbackLater(std::move(callback), 0);
  return ERR_IO_PENDING;
}

void MockDiskEntry::SetLastUsedTimeForTest(base::Time time) {
  NOTREACHED();
}

// If |value| is true, don't deliver any completion callbacks until called
// again with |value| set to false.  Caution: remember to enable callbacks
// again or all subsequent tests will fail.
// Static.
void MockDiskEntry::IgnoreCallbacks(bool value) {
  if (ignore_callbacks_ == value)
    return;
  ignore_callbacks_ = value;
  if (!value)
    StoreAndDeliverCallbacks(false, nullptr, base::OnceClosure());
}

MockDiskEntry::~MockDiskEntry() = default;

// Unlike the callbacks for MockHttpTransaction, we want this one to run even
// if the consumer called Close on the MockDiskEntry.  We achieve that by
// leveraging the fact that this class is reference counted.
void MockDiskEntry::CallbackLater(base::OnceClosure callback) {
  if (ignore_callbacks_)
    return StoreAndDeliverCallbacks(true, this, std::move(callback));
  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE,
      base::BindOnce(&MockDiskEntry::RunCallback, this, std::move(callback)));
}

void MockDiskEntry::CallbackLater(CompletionOnceCallback callback, int result) {
  CallbackLater(base::BindOnce(std::move(callback), result));
}

void MockDiskEntry::RunCallback(base::OnceClosure callback) {
  if (busy_) {
    // This is kind of hacky, but controlling the behavior of just this entry
    // from a test is sort of complicated.  What we really want to do is
    // delay the delivery of a sparse IO operation a little more so that the
    // request start operation (async) will finish without seeing the end of
    // this operation (already posted to the message loop)... and without
    // just delaying for n mS (which may cause trouble with slow bots).  So
    // we re-post this operation (all async sparse IO operations will take two
    // trips through the message loop instead of one).
    if (!delayed_) {
      delayed_ = true;
      return CallbackLater(std::move(callback));
    }
  }
  busy_ = false;
  std::move(callback).Run();
}

// When |store| is true, stores the callback to be delivered later; otherwise
// delivers any callback previously stored.
// Static.
void MockDiskEntry::StoreAndDeliverCallbacks(bool store,
                                             MockDiskEntry* entry,
                                             base::OnceClosure callback) {
  static std::vector<CallbackInfo> callback_list;
  if (store) {
    CallbackInfo c = {entry, std::move(callback)};
    callback_list.push_back(std::move(c));
  } else {
    for (auto& callback_info : callback_list) {
      callback_info.entry->CallbackLater(std::move(callback_info.callback));
    }
    callback_list.clear();
  }
}

// Statics.
bool MockDiskEntry::ignore_callbacks_ = false;

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

MockDiskCache::MockDiskCache()
    : Backend(DISK_CACHE), max_file_size_(std::numeric_limits<int>::max()) {}

MockDiskCache::~MockDiskCache() {
  ReleaseAll();
}

int32_t MockDiskCache::GetEntryCount() const {
  return static_cast<int32_t>(entries_.size());
}

disk_cache::EntryResult MockDiskCache::OpenOrCreateEntry(
    const std::string& key,
    net::RequestPriority request_priority,
    EntryResultCallback callback) {
  DCHECK(!callback.is_null());

  if (force_fail_callback_later_) {
    CallbackLater(base::BindOnce(
        std::move(callback),
        EntryResult::MakeError(ERR_CACHE_OPEN_OR_CREATE_FAILURE)));
    return EntryResult::MakeError(ERR_IO_PENDING);
  }

  if (fail_requests_)
    return EntryResult::MakeError(ERR_CACHE_OPEN_OR_CREATE_FAILURE);

  EntryResult result;

  // First try opening the entry.
  auto split_callback = base::SplitOnceCallback(std::move(callback));
  result = OpenEntry(key, request_priority, std::move(split_callback.first));
  if (result.net_error() == OK || result.net_error() == ERR_IO_PENDING)
    return result;

  // Unable to open, try creating the entry.
  result = CreateEntry(key, request_priority, std::move(split_callback.second));
  if (result.net_error() == OK || result.net_error() == ERR_IO_PENDING)
    return result;

  return EntryResult::MakeError(ERR_CACHE_OPEN_OR_CREATE_FAILURE);
}

disk_cache::EntryResult MockDiskCache::OpenEntry(
    const std::string& key,
    net::RequestPriority request_priority,
    EntryResultCallback callback) {
  DCHECK(!callback.is_null());
  if (force_fail_callback_later_) {
    CallbackLater(base::BindOnce(
        std::move(callback), EntryResult::MakeError(ERR_CACHE_OPEN_FAILURE)));
    return EntryResult::MakeError(ERR_IO_PENDING);
  }

  if (fail_requests_)
    return EntryResult::MakeError(ERR_CACHE_OPEN_FAILURE);

  auto it = entries_.find(key);
  if (it == entries_.end())
    return EntryResult::MakeError(ERR_CACHE_OPEN_FAILURE);

  if (it->second->is_doomed()) {
    it->second->Release();
    entries_.erase(it);
    return EntryResult::MakeError(ERR_CACHE_OPEN_FAILURE);
  }

  open_count_++;

  MockDiskEntry* entry = it->second;
  entry->AddRef();

  if (soft_failures_ || soft_failures_one_instance_) {
    entry->set_fail_requests(soft_failures_ | soft_failures_one_instance_);
    soft_failures_one_instance_ = 0;
  }

  entry->set_max_file_size(max_file_size_);

  EntryResult result = EntryResult::MakeOpened(entry);
  if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START)
    return result;

  CallbackLater(base::BindOnce(std::move(callback), std::move(result)));
  return EntryResult::MakeError(ERR_IO_PENDING);
}

disk_cache::EntryResult MockDiskCache::CreateEntry(
    const std::string& key,
    net::RequestPriority request_priority,
    EntryResultCallback callback) {
  DCHECK(!callback.is_null());
  if (force_fail_callback_later_) {
    CallbackLater(base::BindOnce(
        std::move(callback), EntryResult::MakeError(ERR_CACHE_CREATE_FAILURE)));
    return EntryResult::MakeError(ERR_IO_PENDING);
  }

  if (fail_requests_)
    return EntryResult::MakeError(ERR_CACHE_CREATE_FAILURE);

  auto it = entries_.find(key);
  if (it != entries_.end()) {
    if (!it->second->is_doomed()) {
      if (double_create_check_)
        NOTREACHED();
      else
        return EntryResult::MakeError(ERR_CACHE_CREATE_FAILURE);
    }
    it->second->Release();
    entries_.erase(it);
  }

  create_count_++;

  MockDiskEntry* new_entry = new MockDiskEntry(key);

  new_entry->AddRef();
  entries_[key] = new_entry;

  new_entry->AddRef();

  if (soft_failures_ || soft_failures_one_instance_) {
    new_entry->set_fail_requests(soft_failures_ | soft_failures_one_instance_);
    soft_failures_one_instance_ = 0;
  }

  if (fail_sparse_requests_)
    new_entry->set_fail_sparse_requests();

  new_entry->set_max_file_size(max_file_size_);

  EntryResult result = EntryResult::MakeCreated(new_entry);
  if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START)
    return result;

  // Pause and resume.
  if (defer_op_ == MockDiskEntry::DEFER_CREATE) {
    defer_op_ = MockDiskEntry::DEFER_NONE;
    resume_callback_ = base::BindOnce(std::move(callback), std::move(result));
    return EntryResult::MakeError(ERR_IO_PENDING);
  }

  CallbackLater(base::BindOnce(std::move(callback), std::move(result)));
  return EntryResult::MakeError(ERR_IO_PENDING);
}

net::Error MockDiskCache::DoomEntry(const std::string& key,
                                    net::RequestPriority request_priority,
                                    CompletionOnceCallback callback) {
  DCHECK(!callback.is_null());
  if (force_fail_callback_later_) {
    CallbackLater(base::BindOnce(std::move(callback), ERR_CACHE_DOOM_FAILURE));
    return ERR_IO_PENDING;
  }

  if (fail_requests_)
    return ERR_CACHE_DOOM_FAILURE;

  auto it = entries_.find(key);
  if (it != entries_.end()) {
    it->second->Release();
    entries_.erase(it);
    doomed_count_++;
  }

  if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START)
    return OK;

  CallbackLater(base::BindOnce(std::move(callback), OK));
  return ERR_IO_PENDING;
}

net::Error MockDiskCache::DoomAllEntries(CompletionOnceCallback callback) {
  return ERR_NOT_IMPLEMENTED;
}

net::Error MockDiskCache::DoomEntriesBetween(const base::Time initial_time,
                                             const base::Time end_time,
                                             CompletionOnceCallback callback) {
  return ERR_NOT_IMPLEMENTED;
}

net::Error MockDiskCache::DoomEntriesSince(const base::Time initial_time,
                                           CompletionOnceCallback callback) {
  return ERR_NOT_IMPLEMENTED;
}

int64_t MockDiskCache::CalculateSizeOfAllEntries(
    Int64CompletionOnceCallback callback) {
  return ERR_NOT_IMPLEMENTED;
}

class MockDiskCache::NotImplementedIterator : public Iterator {
 public:
  EntryResult OpenNextEntry(EntryResultCallback callback) override {
    return EntryResult::MakeError(ERR_NOT_IMPLEMENTED);
  }
};

std::unique_ptr<disk_cache::Backend::Iterator> MockDiskCache::CreateIterator() {
  return std::make_unique<NotImplementedIterator>();
}

void MockDiskCache::GetStats(base::StringPairs* stats) {
}

void MockDiskCache::OnExternalCacheHit(const std::string& key) {
  external_cache_hits_.push_back(key);
}

uint8_t MockDiskCache::GetEntryInMemoryData(const std::string& key) {
  if (!support_in_memory_entry_data_)
    return 0;

  auto it = entries_.find(key);
  if (it != entries_.end())
    return it->second->in_memory_data();
  return 0;
}

void MockDiskCache::SetEntryInMemoryData(const std::string& key, uint8_t data) {
  auto it = entries_.find(key);
  if (it != entries_.end())
    it->second->set_in_memory_data(data);
}

int64_t MockDiskCache::MaxFileSize() const {
  return max_file_size_;
}

void MockDiskCache::ReleaseAll() {
  for (auto entry : entries_)
    entry.second->Release();
  entries_.clear();
}

void MockDiskCache::CallbackLater(base::OnceClosure callback) {
  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, std::move(callback));
}

bool MockDiskCache::IsDiskEntryDoomed(const std::string& key) {
  auto it = entries_.find(key);
  if (it != entries_.end())
    return it->second->is_doomed();

  return false;
}

void MockDiskCache::ResumeCacheOperation() {
  DCHECK(!resume_callback_.is_null());
  CallbackLater(std::move(resume_callback_));
}

scoped_refptr<MockDiskEntry> MockDiskCache::GetDiskEntryRef(
    const std::string& key) {
  auto it = entries_.find(key);
  if (it == entries_.end())
    return nullptr;
  return it->second;
}

const std::vector<std::string>& MockDiskCache::GetExternalCacheHits() const {
  return external_cache_hits_;
}

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

disk_cache::BackendResult MockBackendFactory::CreateBackend(
    NetLog* net_log,
    disk_cache::BackendResultCallback callback) {
  return disk_cache::BackendResult::Make(std::make_unique<MockDiskCache>());
}

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

MockHttpCache::MockHttpCache()
    : MockHttpCache(std::make_unique<MockBackendFactory>()) {}

MockHttpCache::MockHttpCache(
    std::unique_ptr<HttpCache::BackendFactory> disk_cache_factory)
    : http_cache_(std::make_unique<MockNetworkLayer>(),
                  std::move(disk_cache_factory)) {}

disk_cache::Backend* MockHttpCache::backend() {
  TestCompletionCallback cb;
  disk_cache::Backend* backend;
  int rv = http_cache_.GetBackend(&backend, cb.callback());
  rv = cb.GetResult(rv);
  return (rv == OK) ? backend : nullptr;
}

MockDiskCache* MockHttpCache::disk_cache() {
  return static_cast<MockDiskCache*>(backend());
}

int MockHttpCache::CreateTransaction(std::unique_ptr<HttpTransaction>* trans) {
  return http_cache_.CreateTransaction(DEFAULT_PRIORITY, trans);
}

void MockHttpCache::SimulateCacheLockTimeout() {
  http_cache_.SimulateCacheLockTimeoutForTesting();
}

void MockHttpCache::SimulateCacheLockTimeoutAfterHeaders() {
  http_cache_.SimulateCacheLockTimeoutAfterHeadersForTesting();
}

void MockHttpCache::FailConditionalizations() {
  http_cache_.FailConditionalizationForTest();
}

bool MockHttpCache::ReadResponseInfo(disk_cache::Entry* disk_entry,
                                     HttpResponseInfo* response_info,
                                     bool* response_truncated) {
  int size = disk_entry->GetDataSize(0);

  TestCompletionCallback cb;
  scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<IOBuffer>(size);
  int rv = disk_entry->ReadData(0, 0, buffer.get(), size, cb.callback());
  rv = cb.GetResult(rv);
  EXPECT_EQ(size, rv);

  return HttpCache::ParseResponseInfo(buffer->data(), size, response_info,
                                      response_truncated);
}

bool MockHttpCache::WriteResponseInfo(disk_cache::Entry* disk_entry,
                                      const HttpResponseInfo* response_info,
                                      bool skip_transient_headers,
                                      bool response_truncated) {
  base::Pickle pickle;
  response_info->Persist(
      &pickle, skip_transient_headers, response_truncated);

  TestCompletionCallback cb;
  scoped_refptr<WrappedIOBuffer> data = base::MakeRefCounted<WrappedIOBuffer>(
      reinterpret_cast<const char*>(pickle.data()));
  int len = static_cast<int>(pickle.size());

  int rv = disk_entry->WriteData(0, 0, data.get(), len, cb.callback(), true);
  rv = cb.GetResult(rv);
  return (rv == len);
}

bool MockHttpCache::OpenBackendEntry(const std::string& key,
                                     disk_cache::Entry** entry) {
  TestEntryResultCompletionCallback cb;
  disk_cache::EntryResult result =
      backend()->OpenEntry(key, net::HIGHEST, cb.callback());
  result = cb.GetResult(std::move(result));
  if (result.net_error() == OK) {
    *entry = result.ReleaseEntry();
    return true;
  } else {
    return false;
  }
}

bool MockHttpCache::CreateBackendEntry(const std::string& key,
                                       disk_cache::Entry** entry,
                                       NetLog* net_log) {
  TestEntryResultCompletionCallback cb;
  disk_cache::EntryResult result =
      backend()->CreateEntry(key, net::HIGHEST, cb.callback());
  result = cb.GetResult(std::move(result));
  if (result.net_error() == OK) {
    *entry = result.ReleaseEntry();
    return true;
  } else {
    return false;
  }
}

// Static.
int MockHttpCache::GetTestMode(int test_mode) {
  if (!g_test_mode)
    return test_mode;

  return g_test_mode;
}

// Static.
void MockHttpCache::SetTestMode(int test_mode) {
  g_test_mode = test_mode;
}

bool MockHttpCache::IsWriterPresent(const std::string& key) {
  HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
  return entry && entry->writers && !entry->writers->IsEmpty();
}

bool MockHttpCache::IsHeadersTransactionPresent(const std::string& key) {
  HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
  return entry && entry->headers_transaction;
}

int MockHttpCache::GetCountReaders(const std::string& key) {
  HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
  return entry ? entry->readers.size() : 0;
}

int MockHttpCache::GetCountAddToEntryQueue(const std::string& key) {
  HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
  return entry ? entry->add_to_entry_queue.size() : 0;
}

int MockHttpCache::GetCountDoneHeadersQueue(const std::string& key) {
  HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
  return entry ? entry->done_headers_queue.size() : 0;
}

int MockHttpCache::GetCountWriterTransactions(const std::string& key) {
  HttpCache::ActiveEntry* entry = http_cache_.FindActiveEntry(key);
  return entry && entry->writers ? entry->writers->GetTransactionsCount() : 0;
}

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

disk_cache::EntryResult MockDiskCacheNoCB::CreateEntry(
    const std::string& key,
    net::RequestPriority request_priority,
    EntryResultCallback callback) {
  return EntryResult::MakeError(ERR_IO_PENDING);
}

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

disk_cache::BackendResult MockBackendNoCbFactory::CreateBackend(
    NetLog* net_log,
    disk_cache::BackendResultCallback callback) {
  return disk_cache::BackendResult::Make(std::make_unique<MockDiskCacheNoCB>());
}

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

MockBlockingBackendFactory::MockBlockingBackendFactory() = default;
MockBlockingBackendFactory::~MockBlockingBackendFactory() = default;

disk_cache::BackendResult MockBlockingBackendFactory::CreateBackend(
    NetLog* net_log,
    disk_cache::BackendResultCallback callback) {
  if (!block_) {
    return MakeResult();
  }

  callback_ = std::move(callback);
  return disk_cache::BackendResult::MakeError(ERR_IO_PENDING);
}

void MockBlockingBackendFactory::FinishCreation() {
  block_ = false;
  if (!callback_.is_null()) {
    // Running the callback might delete |this|.
    std::move(callback_).Run(MakeResult());
  }
}

disk_cache::BackendResult MockBlockingBackendFactory::MakeResult() {
  if (fail_)
    return disk_cache::BackendResult::MakeError(ERR_FAILED);
  else
    return disk_cache::BackendResult::Make(std::make_unique<MockDiskCache>());
}

}  // namespace net
