// Copyright 2018 The Fuchsia 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 "src/ledger/bin/app/page_eviction_policies.h"

#include <lib/callback/capture.h>
#include <lib/callback/set_when_called.h>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/ledger/bin/testing/test_with_environment.h"

namespace ledger {
namespace {

using ::testing::ElementsAre;
using ::testing::IsEmpty;

// A wrapper storage::Iterator for the elements of an std::vector<T>.
template <class T>
class VectorIterator : public storage::Iterator<T> {
 public:
  VectorIterator(const std::vector<T>& v) : it_(v.begin()), end_(v.end()) {}

  ~VectorIterator() {}

  storage::Iterator<T>& Next() override {
    ++it_;
    return *this;
  }

  bool Valid() const override { return it_ != end_; }

  storage::Status GetStatus() const override { return storage::Status::OK; }

  T& operator*() const override { return *it_; }

  T* operator->() const override { return &*it_; }

 private:
  typename std::vector<T>::iterator it_;
  typename std::vector<T>::iterator end_;

  FXL_DISALLOW_COPY_AND_ASSIGN(VectorIterator);
};

// A fake PageEvictionDelegate, that stores the set of pages that were evicted.
class FakePageEvictionDelegate : public PageEvictionDelegate {
 public:
  FakePageEvictionDelegate() {}
  ~FakePageEvictionDelegate() {}

  void TryEvictPage(
      fxl::StringView ledger_name, storage::PageIdView page_id,
      PageEvictionCondition condition,
      fit::function<void(storage::Status, PageWasEvicted)> callback) {
    if (try_evict_page_status_ != storage::Status::OK) {
      callback(try_evict_page_status_, PageWasEvicted(false));
      return;
    }
    if (pages_not_to_evict_.find(page_id.ToString()) !=
        pages_not_to_evict_.end()) {
      callback(storage::Status::OK, PageWasEvicted(false));
      return;
    }
    evicted_pages_.push_back(page_id.ToString());
    callback(storage::Status::OK, PageWasEvicted(true));
  }

  const std::vector<storage::PageId>& GetEvictedPages() {
    return evicted_pages_;
  }

  void SetPagesNotToEvict(std::set<storage::PageId> pages_not_to_evict) {
    pages_not_to_evict_ = std::move(pages_not_to_evict);
  }

  void SetTryEvictPageStatus(storage::Status status) {
    try_evict_page_status_ = status;
  }

 private:
  // The vector of pages for which |TryEvictPage| returned PageWasEvicted(true).
  std::vector<storage::PageId> evicted_pages_;
  // Pages in this set will return PageWasEvicted(false) if TryEvictPage is
  // called on them.
  std::set<storage::PageId> pages_not_to_evict_;
  // The status to be returned by |TryEvictPage|.
  storage::Status try_evict_page_status_ = storage::Status::OK;

  FXL_DISALLOW_COPY_AND_ASSIGN(FakePageEvictionDelegate);
};

using PageEvictionPoliciesTest = TestWithEnvironment;

TEST_F(PageEvictionPoliciesTest, LeastRecentyUsed) {
  FakePageEvictionDelegate delegate;
  std::string ledger_name = "ledger";
  std::vector<const PageInfo> pages = {
      {ledger_name, "page1", zx::time_utc(1)},
      {ledger_name, "page2", zx::time_utc(2)},
      {ledger_name, "page3", zx::time_utc(3)},
      {ledger_name, "page4", zx::time_utc(4)},
  };

  std::unique_ptr<PageEvictionPolicy> policy =
      NewLeastRecentyUsedPolicy(environment_.coroutine_service(), &delegate);

  // Expect to only evict the least recently used page, i.e. "page1".
  bool called;
  storage::Status status;
  policy->SelectAndEvict(
      std::make_unique<VectorIterator<const PageInfo>>(pages),
      callback::Capture(callback::SetWhenCalled(&called), &status));
  EXPECT_TRUE(called);
  EXPECT_EQ(storage::Status::OK, status);
  EXPECT_THAT(delegate.GetEvictedPages(), ElementsAre("page1"));
}

TEST_F(PageEvictionPoliciesTest, LeastRecentyUsedWithOpenPages) {
  FakePageEvictionDelegate delegate;
  std::string ledger_name = "ledger";
  std::vector<const PageInfo> pages = {
      {ledger_name, "page1", PageInfo::kOpenedPageTimestamp},
      {ledger_name, "page2", zx::time_utc(2)},
      {ledger_name, "page3", zx::time_utc(3)},
      {ledger_name, "page4", zx::time_utc(4)},
  };

  std::unique_ptr<PageEvictionPolicy> policy =
      NewLeastRecentyUsedPolicy(environment_.coroutine_service(), &delegate);

  // "page1" should not be evicted as it is marked as open. Expect to only evict
  // the least recently used page, i.e. "page2".
  bool called;
  storage::Status status;
  policy->SelectAndEvict(
      std::make_unique<VectorIterator<const PageInfo>>(pages),
      callback::Capture(callback::SetWhenCalled(&called), &status));
  EXPECT_TRUE(called);
  EXPECT_EQ(storage::Status::OK, status);
  EXPECT_THAT(delegate.GetEvictedPages(), ElementsAre("page2"));
}

TEST_F(PageEvictionPoliciesTest, LeastRecentyUsedNoPagesToEvict) {
  FakePageEvictionDelegate delegate;
  std::string ledger_name = "ledger";
  std::vector<const PageInfo> pages = {
      {ledger_name, "page1", PageInfo::kOpenedPageTimestamp},
      {ledger_name, "page2", zx::time_utc(2)},
      {ledger_name, "page3", zx::time_utc(3)},
      {ledger_name, "page4", zx::time_utc(4)},
  };

  delegate.SetPagesNotToEvict({"page2", "page3", "page4"});

  std::unique_ptr<PageEvictionPolicy> policy =
      NewLeastRecentyUsedPolicy(environment_.coroutine_service(), &delegate);

  // "page1" is marked as open, and pages 2-4 will fail to be evicted. The
  // returned status should be ok, and not pages will be evicted.
  bool called;
  storage::Status status;
  policy->SelectAndEvict(
      std::make_unique<VectorIterator<const PageInfo>>(pages),
      callback::Capture(callback::SetWhenCalled(&called), &status));
  EXPECT_TRUE(called);
  EXPECT_EQ(storage::Status::OK, status);
  EXPECT_THAT(delegate.GetEvictedPages(), IsEmpty());
}

TEST_F(PageEvictionPoliciesTest, LeastRecentyUsedErrorWhileEvicting) {
  FakePageEvictionDelegate delegate;
  std::string ledger_name = "ledger";
  std::vector<const PageInfo> pages = {
      {ledger_name, "page1", zx::time_utc(1)},
      {ledger_name, "page2", zx::time_utc(2)},
      {ledger_name, "page3", zx::time_utc(3)},
      {ledger_name, "page4", zx::time_utc(4)},
  };
  delegate.SetTryEvictPageStatus(storage::Status::INTERNAL_ERROR);

  // If |TryEvictPage| fails, so should |SelectAndEvict|. Expect to find the
  // same error status.
  std::unique_ptr<PageEvictionPolicy> policy =
      NewLeastRecentyUsedPolicy(environment_.coroutine_service(), &delegate);
  bool called;
  storage::Status status;
  policy->SelectAndEvict(
      std::make_unique<VectorIterator<const PageInfo>>(pages),
      callback::Capture(callback::SetWhenCalled(&called), &status));
  EXPECT_TRUE(called);
  EXPECT_EQ(storage::Status::INTERNAL_ERROR, status);
}

}  // namespace
}  // namespace ledger
