// 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 is a mock of the http cache and related testing classes. To be fair, it
// is not really a mock http cache given that it uses the real implementation of
// the http cache, but it has fake implementations of all required components,
// so it is useful for unit tests at the http layer.

#ifndef NET_HTTP_MOCK_HTTP_CACHE_H_
#define NET_HTTP_MOCK_HTTP_CACHE_H_

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/strings/string_split.h"
#include "net/base/completion_once_callback.h"
#include "net/base/request_priority.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_cache.h"
#include "net/http/http_transaction_test_util.h"
#include "starboard/types.h"

namespace net {

//-----------------------------------------------------------------------------
// Mock disk cache (a very basic memory cache implementation).

class MockDiskEntry : public disk_cache::Entry,
                      public base::RefCounted<MockDiskEntry> {
 public:
  enum DeferOp {
    DEFER_NONE,
    DEFER_CREATE,
    DEFER_READ,
    DEFER_WRITE,
  };

  explicit MockDiskEntry(const std::string& key);

  bool is_doomed() const { return doomed_; }

  void Doom() override;
  void Close() override;
  std::string GetKey() const override;
  base::Time GetLastUsed() const override;
  base::Time GetLastModified() const override;
  int32_t GetDataSize(int index) const override;
  int ReadData(int index,
               int offset,
               IOBuffer* buf,
               int buf_len,
               CompletionOnceCallback callback) override;
  int WriteData(int index,
                int offset,
                IOBuffer* buf,
                int buf_len,
                CompletionOnceCallback callback,
                bool truncate) override;
  int ReadSparseData(int64_t offset,
                     IOBuffer* buf,
                     int buf_len,
                     CompletionOnceCallback callback) override;
  int WriteSparseData(int64_t offset,
                      IOBuffer* buf,
                      int buf_len,
                      CompletionOnceCallback callback) override;
  int GetAvailableRange(int64_t offset,
                        int len,
                        int64_t* start,
                        CompletionOnceCallback callback) override;
  bool CouldBeSparse() const override;
  void CancelSparseIO() override;
  net::Error ReadyForSparseIO(
      CompletionOnceCallback completion_callback) override;
  void SetLastUsedTimeForTest(base::Time time) override;

  uint8_t in_memory_data() const { return in_memory_data_; }
  void set_in_memory_data(uint8_t val) { in_memory_data_ = val; }

  // Fail most subsequent requests.
  void set_fail_requests() { fail_requests_ = true; }

  void set_fail_sparse_requests() { fail_sparse_requests_ = true; }

  // 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 IgnoreCallbacks(bool value);

  // Defers invoking the callback for the given operation. Calling code should
  // invoke ResumeDiskEntryOperation to resume.
  void SetDefer(DeferOp defer_op) { defer_op_ = defer_op; }

  // Resumes deferred cache operation by posting |resume_callback_| with
  // |resume_return_code_|.
  void ResumeDiskEntryOperation();

 private:
  friend class base::RefCounted<MockDiskEntry>;
  struct CallbackInfo;

  ~MockDiskEntry() override;

  // 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 CallbackLater(CompletionOnceCallback callback, int result);

  void RunCallback(CompletionOnceCallback callback, int result);

  // When |store| is true, stores the callback to be delivered later; otherwise
  // delivers any callback previously stored.
  static void StoreAndDeliverCallbacks(bool store,
                                       MockDiskEntry* entry,
                                       CompletionOnceCallback callback,
                                       int result);

  static const int kNumCacheEntryDataIndices = 3;

  std::string key_;
  std::vector<char> data_[kNumCacheEntryDataIndices];
  uint8_t in_memory_data_;
  int test_mode_;
  bool doomed_;
  bool sparse_;
  bool fail_requests_;
  bool fail_sparse_requests_;
  bool busy_;
  bool delayed_;
  bool cancel_;

  // Used for pause and restart.
  DeferOp defer_op_;
  CompletionOnceCallback resume_callback_;
  int resume_return_code_;

  static bool ignore_callbacks_;
};

class MockDiskCache : public disk_cache::Backend {
 public:
  MockDiskCache();
  ~MockDiskCache() override;

  CacheType GetCacheType() const override;
  int32_t GetEntryCount() const override;
  net::Error OpenEntry(const std::string& key,
                       net::RequestPriority request_priority,
                       disk_cache::Entry** entry,
                       CompletionOnceCallback callback) override;
  net::Error CreateEntry(const std::string& key,
                         net::RequestPriority request_priority,
                         disk_cache::Entry** entry,
                         CompletionOnceCallback callback) override;
  net::Error DoomEntry(const std::string& key,
                       net::RequestPriority request_priority,
                       CompletionOnceCallback callback) override;
  net::Error DoomAllEntries(CompletionOnceCallback callback) override;
  net::Error DoomEntriesBetween(base::Time initial_time,
                                base::Time end_time,
                                CompletionOnceCallback callback) override;
  net::Error DoomEntriesSince(base::Time initial_time,
                              CompletionOnceCallback callback) override;
  int64_t CalculateSizeOfAllEntries(
      Int64CompletionOnceCallback callback) override;
  std::unique_ptr<Iterator> CreateIterator() override;
  void GetStats(base::StringPairs* stats) override;
  void OnExternalCacheHit(const std::string& key) override;
  size_t DumpMemoryStats(
      base::trace_event::ProcessMemoryDump* pmd,
      const std::string& parent_absolute_name) const override;
  uint8_t GetEntryInMemoryData(const std::string& key) override;
  void SetEntryInMemoryData(const std::string& key, uint8_t data) override;

  // Returns number of times a cache entry was successfully opened.
  int open_count() const { return open_count_; }

  // Returns number of times a cache entry was successfully created.
  int create_count() const { return create_count_; }

  // Returns number of doomed entries.
  int doomed_count() const { return doomed_count_; }

  // Fail any subsequent CreateEntry and OpenEntry.
  void set_fail_requests() { fail_requests_ = true; }

  // Return entries that fail some of their requests.
  void set_soft_failures(bool value) { soft_failures_ = value; }

  // Makes sure that CreateEntry is not called twice for a given key.
  void set_double_create_check(bool value) { double_create_check_ = value; }

  // Determines whether to provide the GetEntryInMemoryData/SetEntryInMemoryData
  // interface.  Default is true.
  void set_support_in_memory_entry_data(bool value) {
    support_in_memory_entry_data_ = value;
  }

  // Makes all requests for data ranges to fail as not implemented.
  void set_fail_sparse_requests() { fail_sparse_requests_ = true; }

  void ReleaseAll();

  // Returns true if a doomed entry exists with this key.
  bool IsDiskEntryDoomed(const std::string& key);

  // Defers invoking the callback for the given operation. Calling code should
  // invoke ResumeCacheOperation to resume.
  void SetDefer(MockDiskEntry::DeferOp defer_op) { defer_op_ = defer_op; }

  // Resume deferred cache operation by posting |resume_callback_| with
  // |resume_return_code_|.
  void ResumeCacheOperation();

  // Returns a reference to the disk entry with the given |key|.
  scoped_refptr<MockDiskEntry> GetDiskEntryRef(const std::string& key);

 private:
  using EntryMap = std::map<std::string, MockDiskEntry*>;
  class NotImplementedIterator;

  void CallbackLater(CompletionOnceCallback callback, int result);

  EntryMap entries_;
  int open_count_;
  int create_count_;
  int doomed_count_;
  bool fail_requests_;
  bool soft_failures_;
  bool double_create_check_;
  bool fail_sparse_requests_;
  bool support_in_memory_entry_data_;

  // Used for pause and restart.
  MockDiskEntry::DeferOp defer_op_;
  CompletionOnceCallback resume_callback_;
  int resume_return_code_;
};

class MockBackendFactory : public HttpCache::BackendFactory {
 public:
  int CreateBackend(NetLog* net_log,
                    std::unique_ptr<disk_cache::Backend>* backend,
                    CompletionOnceCallback callback) override;
};

class MockHttpCache {
 public:
  MockHttpCache();
  explicit MockHttpCache(
      std::unique_ptr<HttpCache::BackendFactory> disk_cache_factory);
  // |is_main_cache| if set, will set a quic server info factory.
  explicit MockHttpCache(bool is_main_cache);

  MockHttpCache(std::unique_ptr<HttpCache::BackendFactory> disk_cache_factory,
                bool is_main_cache);

  HttpCache* http_cache() { return &http_cache_; }

  MockNetworkLayer* network_layer() {
    return static_cast<MockNetworkLayer*>(http_cache_.network_layer());
  }
  disk_cache::Backend* backend();
  MockDiskCache* disk_cache();

  // Wrapper around http_cache()->CreateTransaction(DEFAULT_PRIORITY...)
  int CreateTransaction(std::unique_ptr<HttpTransaction>* trans);

  // Wrapper to simulate cache lock timeout for new transactions.
  void SimulateCacheLockTimeout();

  // Wrapper to simulate cache lock timeout for new transactions.
  void SimulateCacheLockTimeoutAfterHeaders();

  // Wrapper to fail request conditionalization for new transactions.
  void FailConditionalizations();

  // Helper function for reading response info from the disk cache.
  static bool ReadResponseInfo(disk_cache::Entry* disk_entry,
                               HttpResponseInfo* response_info,
                               bool* response_truncated);

  // Helper function for writing response info into the disk cache.
  static bool WriteResponseInfo(disk_cache::Entry* disk_entry,
                                const HttpResponseInfo* response_info,
                                bool skip_transient_headers,
                                bool response_truncated);

  // Helper function to synchronously open a backend entry.
  bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry);

  // Helper function to synchronously create a backend entry.
  bool CreateBackendEntry(const std::string& key,
                          disk_cache::Entry** entry,
                          NetLog* net_log);

  // Returns the test mode after considering the global override.
  static int GetTestMode(int test_mode);

  // Overrides the test mode for a given operation. Remember to reset it after
  // the test! (by setting test_mode to zero).
  static void SetTestMode(int test_mode);

  // Functions to test the state of ActiveEntry.
  bool IsWriterPresent(const std::string& key);
  bool IsHeadersTransactionPresent(const std::string& key);
  int GetCountReaders(const std::string& key);
  int GetCountAddToEntryQueue(const std::string& key);
  int GetCountDoneHeadersQueue(const std::string& key);
  int GetCountWriterTransactions(const std::string& key);

 private:
  HttpCache http_cache_;
};

// This version of the disk cache doesn't invoke CreateEntry callbacks.
class MockDiskCacheNoCB : public MockDiskCache {
  net::Error CreateEntry(const std::string& key,
                         net::RequestPriority request_priority,
                         disk_cache::Entry** entry,
                         CompletionOnceCallback callback) override;
};

class MockBackendNoCbFactory : public HttpCache::BackendFactory {
 public:
  int CreateBackend(NetLog* net_log,
                    std::unique_ptr<disk_cache::Backend>* backend,
                    CompletionOnceCallback callback) override;
};

// This backend factory allows us to control the backend instantiation.
class MockBlockingBackendFactory : public HttpCache::BackendFactory {
 public:
  MockBlockingBackendFactory();
  ~MockBlockingBackendFactory() override;

  int CreateBackend(NetLog* net_log,
                    std::unique_ptr<disk_cache::Backend>* backend,
                    CompletionOnceCallback callback) override;

  // Completes the backend creation. Any blocked call will be notified via the
  // provided callback.
  void FinishCreation();

  std::unique_ptr<disk_cache::Backend>* backend() { return backend_; }
  void set_fail(bool fail) { fail_ = fail; }

  CompletionOnceCallback ReleaseCallback() { return std::move(callback_); }

 private:
  int Result() { return fail_ ? ERR_FAILED : OK; }

  std::unique_ptr<disk_cache::Backend>* backend_;
  CompletionOnceCallback callback_;
  bool block_;
  bool fail_;
};

}  // namespace net

#endif  // NET_HTTP_MOCK_HTTP_CACHE_H_
