// Copyright 2021 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <vm/evictor.h>
#include <vm/stack_owned_loaned_pages_interval.h>

#include "test_helper.h"

namespace vm_unittest {

// Custom pmm node to link with the evictor under test. Facilitates verifying the free count which
// is not possible with the global pmm node.
class TestPmmNode {
 public:
  TestPmmNode() : evictor_(&node_, pmm_page_queues()) { evictor_.EnableEviction(); }

  ~TestPmmNode() {
    // Pages that were evicted are being held in |node_|'s free list.
    // Return them to the global pmm node before exiting.
    DecrementFreePages(node_.CountFreePages());
    ASSERT(node_.CountFreePages() == 0);
  }

  // Reduce free pages in |node_| by |num_pages|.
  void DecrementFreePages(uint64_t num_pages) {
    uint64_t free_count = node_.CountFreePages();
    if (free_count < num_pages) {
      num_pages = free_count;
    }
    list_node list = LIST_INITIAL_VALUE(list);
    zx_status_t status = node_.AllocPages(num_pages, 0, &list);
    ASSERT(status == ZX_OK);

    // Return these pages to the global pmm. Our goal is to just reduce the free count of |node_|,
    // we do not intend to use the allocated pages for anything.
    vm_page_t* page;
    list_for_every_entry (&list, page, vm_page_t, queue_node) {
      page->set_state(vm_page_state::ALLOC);
    }
    pmm_free(&list);
  }

  Evictor::EvictionTarget GetOneShotEvictionTarget() const {
    return evictor_.DebugGetOneShotEvictionTarget();
  }

  void SetMinDiscardableAge(zx_time_t age) { evictor_.DebugSetMinDiscardableAge(age); }

  uint64_t FreePages() const { return node_.CountFreePages(); }

  Evictor* evictor() { return &evictor_; }

 private:
  PmmNode node_;
  Evictor evictor_;
};

// Test that a one shot eviction target can be set as expected.
static bool evictor_set_target_test() {
  BEGIN_TEST;

  TestPmmNode node;

  auto expected = Evictor::EvictionTarget{
      .pending = static_cast<bool>(rand() % 2),
      .free_pages_target = static_cast<uint64_t>(rand()),
      .min_pages_to_free = static_cast<uint64_t>(rand()),
      .level =
          (rand() % 2) ? Evictor::EvictionLevel::IncludeNewest : Evictor::EvictionLevel::OnlyOldest,
  };

  node.evictor()->SetOneShotEvictionTarget(expected);

  auto actual = node.GetOneShotEvictionTarget();

  ASSERT_EQ(actual.pending, expected.pending);
  ASSERT_EQ(actual.free_pages_target, expected.free_pages_target);
  ASSERT_EQ(actual.min_pages_to_free, expected.min_pages_to_free);
  ASSERT_EQ(actual.level, expected.level);

  END_TEST;
}

// Test that multiple one shot eviction targets can be combined as expected.
static bool evictor_combine_targets_test() {
  BEGIN_TEST;

  TestPmmNode node;

  static constexpr int kNumTargets = 5;
  Evictor::EvictionTarget targets[kNumTargets];

  for (auto& target : targets) {
    target = Evictor::EvictionTarget{
        .pending = true,
        .free_pages_target = static_cast<uint64_t>(rand() % 1000),
        .min_pages_to_free = static_cast<uint64_t>(rand() % 1000),
        .level = Evictor::EvictionLevel::IncludeNewest,
    };
    node.evictor()->CombineOneShotEvictionTarget(target);
  }

  Evictor::EvictionTarget expected = {};
  for (auto& target : targets) {
    expected.pending = expected.pending || target.pending;
    expected.level = ktl::max(expected.level, target.level);
    expected.min_pages_to_free += target.min_pages_to_free;
    expected.free_pages_target = ktl::max(expected.free_pages_target, target.free_pages_target);
  }

  auto actual = node.GetOneShotEvictionTarget();

  ASSERT_EQ(actual.pending, expected.pending);
  ASSERT_EQ(actual.free_pages_target, expected.free_pages_target);
  ASSERT_EQ(actual.min_pages_to_free, expected.min_pages_to_free);
  ASSERT_EQ(actual.level, expected.level);

  END_TEST;
}

// Helper to create a pager backed vmo and commit all its pages.
static zx_status_t create_precommitted_pager_backed_vmo(uint64_t size,
                                                        fbl::RefPtr<VmObjectPaged>* vmo_out,
                                                        vm_page_t** out_pages = nullptr) {
  // The size should be page aligned for TakePages and SupplyPages to work.
  if (size % PAGE_SIZE) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::AllocChecker ac;
  fbl::RefPtr<StubPageProvider> pager = fbl::MakeRefCountedChecked<StubPageProvider>(&ac);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  fbl::RefPtr<PageSource> src = fbl::MakeRefCountedChecked<PageSource>(&ac, ktl::move(pager));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  fbl::RefPtr<VmObjectPaged> vmo;
  zx_status_t status = VmObjectPaged::CreateExternal(ktl::move(src), 0u, size, &vmo);
  if (status != ZX_OK) {
    return status;
  }

  // Create an aux VMO to transfer pages into the pager-backed vmo.
  fbl::RefPtr<VmObjectPaged> aux_vmo;
  status = VmObjectPaged::Create(PMM_ALLOC_FLAG_ANY, 0u, size, &aux_vmo);
  if (status != ZX_OK) {
    return status;
  }

  status = aux_vmo->CommitRange(0, size);
  if (status != ZX_OK) {
    return status;
  }

  VmPageSpliceList page_list;
  status = aux_vmo->TakePages(0, size, &page_list);
  if (status != ZX_OK) {
    return status;
  }

  status = vmo->SupplyPages(0, size, &page_list);
  if (status != ZX_OK) {
    return status;
  }

  // Pin the pages momentarily to force the pages to be non-loaned pages.  This allows us to be more
  // strict with asserts that verify how many non-loaned pages are evicted.  Loaned pages can also
  // be evicted along the way to evicting non-loaned pages, but only non-loaned pages count as fully
  // free.
  ASSERT(ZX_OK == vmo->CommitRangePinned(0, size));
  vmo->Unpin(0, size);

  // Get the pages after the pin, so that we find non-loaned pages.
  if (out_pages) {
    for (uint64_t i = 0; i < size; i += PAGE_SIZE) {
      status = vmo->GetPage(i, 0, nullptr, nullptr, &out_pages[i / PAGE_SIZE], nullptr);
      if (status != ZX_OK) {
        return status;
      }
    }
  }

  *vmo_out = ktl::move(vmo);
  return ZX_OK;
}

// Test that the evictor can evict from pager backed vmos as expected.
static bool evictor_pager_backed_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a pager backed vmo to evict pages from.
  fbl::RefPtr<VmObjectPaged> vmo;
  static constexpr size_t kNumPages = 22;
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo));

  // Promote the pages for eviction.
  vmo->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  TestPmmNode node;
  // Only evict from pager backed vmos.
  node.evictor()->SetDiscardableEvictionsPercent(0);

  auto target = Evictor::EvictionTarget{
      .pending = true,
      .free_pages_target = 20,
      .min_pages_to_free = 10,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  // The node starts off with zero pages.
  uint64_t free_count = node.FreePages();
  EXPECT_EQ(free_count, 0u);

  node.evictor()->SetOneShotEvictionTarget(target);
  auto counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No discardable pages were evicted.
  EXPECT_EQ(counts.discardable, 0u);
  // Free pages target was greater than min pages target. So precisely free pages target must have
  // been evicted.
  EXPECT_EQ(counts.pager_backed, target.free_pages_target);
  EXPECT_GE(counts.pager_backed, target.min_pages_to_free);
  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  free_count = node.FreePages();
  EXPECT_EQ(free_count, target.free_pages_target);
  EXPECT_GE(free_count, target.min_pages_to_free);

  // Re-initialize the vmo and try again with a different target.
  vmo.reset();
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo));
  // Promote the pages for eviction.
  vmo->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  target = Evictor::EvictionTarget{
      .pending = true,
      .free_pages_target = 10,
      .min_pages_to_free = 20,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  node.evictor()->SetOneShotEvictionTarget(target);
  counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No discardable pages were evicted.
  EXPECT_EQ(counts.discardable, 0u);
  // Min pages target was greater than free pages target. So precisely min pages target must have
  // been evicted.
  EXPECT_EQ(counts.pager_backed, target.min_pages_to_free);
  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  EXPECT_GE(node.FreePages(), target.free_pages_target);
  EXPECT_EQ(node.FreePages(), free_count + target.min_pages_to_free);

  END_TEST;
}

// Helper to create a fully committed discardable vmo, which is unlocked and can be evicted.
static zx_status_t create_committed_unlocked_discardable_vmo(uint64_t size,
                                                             fbl::RefPtr<VmObjectPaged>* vmo_out) {
  fbl::RefPtr<VmObjectPaged> vmo;
  zx_status_t status =
      VmObjectPaged::Create(PMM_ALLOC_FLAG_ANY, VmObjectPaged::kDiscardable, size, &vmo);
  if (status != ZX_OK) {
    return status;
  }

  // Lock and commit the vmo.
  status = vmo->TryLockRange(0, size);
  if (status != ZX_OK) {
    return status;
  }
  status = vmo->CommitRange(0, size);
  if (status != ZX_OK) {
    return status;
  }

  // Unlock the vmo so that it can be discarded.
  status = vmo->UnlockRange(0, size);
  if (status != ZX_OK) {
    return status;
  }

  *vmo_out = ktl::move(vmo);
  return ZX_OK;
}

// Test that the evictor can discard from discardable vmos as expected.
static bool evictor_discardable_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a discardable vmo.
  fbl::RefPtr<VmObjectPaged> vmo;
  static constexpr size_t kNumPages = 22;
  ASSERT_EQ(ZX_OK, create_committed_unlocked_discardable_vmo(kNumPages * PAGE_SIZE, &vmo));

  TestPmmNode node;
  // Only evict from discardable vmos.
  node.evictor()->SetDiscardableEvictionsPercent(100);
  // Set min discardable age to 0 to that the vmo is eligible for eviction.
  node.SetMinDiscardableAge(0);

  auto target = Evictor::EvictionTarget{
      .pending = true,
      .free_pages_target = 20,
      .min_pages_to_free = 10,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  // The node starts off with zero pages.
  uint64_t free_count = node.FreePages();
  EXPECT_EQ(free_count, 0u);

  node.evictor()->SetOneShotEvictionTarget(target);
  auto counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No pager backed pages were evicted.
  EXPECT_EQ(counts.pager_backed, 0u);
  // Free pages target was greater than min pages target. So precisely free pages target must have
  // been evicted. However, a discardable vmo can only be discarded in its entirety, so we can't
  // check for equality with free pages target. We can't check for equality with |kNumPages| either
  // as it is possible (albeit unlikely) that a discardable vmo other than the one we created
  // here was discarded, since we're discarding from the global list of discardable vmos. In the
  // future (if and) when vmos are PMM node aware, we will be able to control this better by
  // creating a vmo backed by the test node.
  EXPECT_GE(counts.discardable, target.free_pages_target);
  EXPECT_GE(counts.discardable, target.min_pages_to_free);
  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  free_count = node.FreePages();
  EXPECT_GE(free_count, target.free_pages_target);
  EXPECT_GE(free_count, target.min_pages_to_free);

  // Re-initialize the vmo and try again with a different target.
  vmo.reset();
  ASSERT_EQ(ZX_OK, create_committed_unlocked_discardable_vmo(kNumPages * PAGE_SIZE, &vmo));

  target = Evictor::EvictionTarget{
      .pending = true,
      .free_pages_target = 10,
      .min_pages_to_free = 20,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  node.evictor()->SetOneShotEvictionTarget(target);
  counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No pager backed pages were evicted.
  EXPECT_EQ(counts.pager_backed, 0u);
  // Min pages target was greater than free pages target. So precisely min pages target must have
  // been evicted. However, a discardable vmo can only be discarded in its entirety, so we can't
  // check for equality with free pages target. We can't check for equality with |kNumPages| either
  // as it is possible (albeit unlikely) that a discardable vmo other than the one we created
  // here was discarded, since we're discarding from the global list of discardable vmos. In the
  // future (if and) when vmos are PMM node aware, we will be able to control this better by
  // creating a vmo backed by the test node.
  EXPECT_GE(counts.discardable, target.min_pages_to_free);
  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  EXPECT_GE(node.FreePages(), target.free_pages_target);
  EXPECT_GE(node.FreePages(), free_count + target.min_pages_to_free);

  END_TEST;
}

// Test that the evictor can evict out of both discardable and pager backed vmos simultaneously.
static bool evictor_pager_backed_and_discardable_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a pager backed and a discardable vmo to share the eviction load.
  static constexpr uint64_t kNumPages = 11;
  fbl::RefPtr<VmObjectPaged> vmo_pager, vmo_discardable;
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo_pager));
  ASSERT_EQ(ZX_OK,
            create_committed_unlocked_discardable_vmo(kNumPages * PAGE_SIZE, &vmo_discardable));

  // Promote the pages for eviction.
  vmo_pager->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  TestPmmNode node;
  // Half the pages will be evicted from pager backed and the other half from discardable vmos.
  node.evictor()->SetDiscardableEvictionsPercent(50);
  // Set min discardable age to 0 to that the discardable vmo is eligible for eviction.
  node.SetMinDiscardableAge(0);

  auto target = Evictor::EvictionTarget{
      .pending = true,
      .free_pages_target = 20,
      .min_pages_to_free = 10,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  // The node starts off with zero pages.
  uint64_t free_count = node.FreePages();
  EXPECT_EQ(free_count, 0u);

  node.evictor()->SetOneShotEvictionTarget(target);
  auto counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // It's hard to check for equality with discardable vmos in the picture. Refer to the comments in
  // evictor_discardable_test regarding this. Perform some basic sanity checks on the number of
  // pages evicted.
  uint64_t expected_pages_freed = ktl::max(target.free_pages_target, target.min_pages_to_free);
  EXPECT_GE(counts.discardable + counts.pager_backed, expected_pages_freed);
  EXPECT_GE(counts.discardable, 0u);
  EXPECT_GE(counts.pager_backed, 0u);

  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  free_count = node.FreePages();
  EXPECT_GE(free_count, target.free_pages_target);
  EXPECT_GE(free_count, target.min_pages_to_free);

  // Reset the vmos and try with a different target.
  vmo_pager.reset();
  vmo_discardable.reset();
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo_pager));
  ASSERT_EQ(ZX_OK,
            create_committed_unlocked_discardable_vmo(kNumPages * PAGE_SIZE, &vmo_discardable));
  // Promote the pages for eviction.
  vmo_pager->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  target = Evictor::EvictionTarget{
      .pending = true,
      .free_pages_target = 10,
      .min_pages_to_free = 20,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  node.evictor()->SetOneShotEvictionTarget(target);
  counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // It's hard to check for equality with discardable vmos in the picture. Refer to the comments in
  // evictor_discardable_test regarding this. Perform some basic sanity checks on the number of
  // pages evicted.
  expected_pages_freed = ktl::max(target.free_pages_target, target.min_pages_to_free);
  EXPECT_GE(counts.discardable + counts.pager_backed, expected_pages_freed);
  EXPECT_GE(counts.discardable, 0u);
  EXPECT_GE(counts.pager_backed, 0u);

  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  EXPECT_GE(node.FreePages(), target.free_pages_target);
  EXPECT_GE(node.FreePages(), free_count + target.min_pages_to_free);

  END_TEST;
}

// Test that eviction meets the required free and min target as expected.
static bool evictor_free_target_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a pager backed vmo to evict pages from.
  fbl::RefPtr<VmObjectPaged> vmo;
  static constexpr size_t kNumPages = 111;
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo));

  // Promote the pages for eviction.
  vmo->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  TestPmmNode node;
  // Only evict from pager backed vmos.
  node.evictor()->SetDiscardableEvictionsPercent(0);

  auto target = Evictor::EvictionTarget{
      .pending = true,
      .free_pages_target = 20,
      .min_pages_to_free = 0,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  // The node starts off with zero pages.
  uint64_t free_count = node.FreePages();
  EXPECT_EQ(free_count, 0u);

  node.evictor()->SetOneShotEvictionTarget(target);
  auto counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No discardable pages were evicted.
  EXPECT_EQ(counts.discardable, 0u);
  // Free pages target was greater than min pages target. So precisely free pages target must have
  // been evicted.
  EXPECT_EQ(counts.pager_backed, target.free_pages_target);
  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  free_count = node.FreePages();
  EXPECT_EQ(free_count, target.free_pages_target);
  EXPECT_GE(free_count, target.min_pages_to_free);

  // Evict again with the same target.
  node.evictor()->SetOneShotEvictionTarget(target);
  counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No new pages should have been evicted, as the free target was already met with the previous
  // round of eviction, and no minimum pages were requested to be evicted.
  EXPECT_EQ(counts.discardable, 0u);
  EXPECT_EQ(counts.pager_backed, 0u);
  EXPECT_EQ(node.FreePages(), free_count);

  // Evict again with a higher free memory target. No min pages target.
  uint64_t delta_pages = 10;
  target.free_pages_target += delta_pages;
  target.min_pages_to_free = 0;
  node.evictor()->SetOneShotEvictionTarget(target);
  counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No discardable pages evicted.
  EXPECT_EQ(counts.discardable, 0u);
  // Exactly delta_pages evicted.
  EXPECT_EQ(counts.pager_backed, delta_pages);
  EXPECT_GE(counts.pager_backed, target.min_pages_to_free);
  // Free count increased by delta_pages.
  free_count = node.FreePages();
  EXPECT_EQ(free_count, target.free_pages_target);

  // Evict again with a higher free memory target and also a min pages target.
  target.free_pages_target += delta_pages;
  target.min_pages_to_free = delta_pages;
  node.evictor()->SetOneShotEvictionTarget(target);
  counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No discardable pages evicted.
  EXPECT_EQ(counts.discardable, 0u);
  // Exactly delta_pages evicted.
  EXPECT_EQ(counts.pager_backed, delta_pages);
  EXPECT_GE(counts.pager_backed, target.min_pages_to_free);
  // Free count increased by delta_pages.
  free_count = node.FreePages();
  EXPECT_EQ(free_count, target.free_pages_target);

  // Evict again with the same free target, but request a min number of pages to be freed.
  target.min_pages_to_free = 2;
  node.evictor()->SetOneShotEvictionTarget(target);
  counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No discardable pages evicted.
  EXPECT_EQ(counts.discardable, 0u);
  // Exactly min pages evicted.
  EXPECT_EQ(counts.pager_backed, target.min_pages_to_free);
  // Free count increased by min pages.
  EXPECT_EQ(node.FreePages(), free_count + target.min_pages_to_free);

  END_TEST;
}

// Test that pages are evicted when continuous eviction is enabled, and not evicted when disabled.
static bool evictor_continuous_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a pager backed vmo to evict pages from.
  fbl::RefPtr<VmObjectPaged> vmo;
  static constexpr size_t kNumPages = 44;
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo));

  // Promote the pages for eviction.
  vmo->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  TestPmmNode node;

  // Evict every 10 milliseconds.
  node.evictor()->SetContinuousEvictionInterval(ZX_MSEC(10));
  // Enable eviction. Min pages target is 10 pages. Free mem target is 20 pages.
  const uint64_t free_target = 20;
  node.evictor()->EnableContinuousEviction(10u * PAGE_SIZE, free_target * PAGE_SIZE,
                                           Evictor::EvictionLevel::IncludeNewest);

  // Poll the node's free count, relying on the test timeout to kill us if something goes wrong.
  // The free target was 20 and min pages target was 10. We should see 20 pages freed.
  while (node.FreePages() < free_target) {
    printf("polling free count (case 1) ...\n");
    Thread::Current::SleepRelative(ZX_MSEC(10));
  }
  EXPECT_EQ(node.FreePages(), free_target);

  // Get rid of all free pages and wait for eviction to happen again.
  node.DecrementFreePages(node.FreePages());
  // Pages should be evicted per the free target again.
  while (node.FreePages() < free_target) {
    printf("polling free count (case 2) ...\n");
    Thread::Current::SleepRelative(ZX_MSEC(10));
  }
  EXPECT_EQ(node.FreePages(), free_target);

  // No more pages should be evicted even though eviction is enabled, since we've already met our
  // free target. Wait twice the eviction interval just to be sure.
  Thread::Current::SleepRelative(ZX_MSEC(20));
  EXPECT_EQ(node.FreePages(), free_target);

  // No pages evicted after disabling eviction.
  node.evictor()->DisableContinuousEviction();
  Thread::Current::SleepRelative(ZX_MSEC(20));
  node.DecrementFreePages(node.FreePages());
  Thread::Current::SleepRelative(ZX_MSEC(20));
  EXPECT_EQ(node.FreePages(), 0u);

  END_TEST;
}

// Test that the min pages target specified over multiple calls to enable continuous eviction is
// combined as expected.
static bool evictor_continuous_combine_targets_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a pager backed vmo to evict pages from.
  fbl::RefPtr<VmObjectPaged> vmo;
  static constexpr size_t kNumPages = 22;
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo));

  // Promote the pages for eviction.
  vmo->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  TestPmmNode node;

  // Evict every 10 milliseconds.
  node.evictor()->SetContinuousEvictionInterval(ZX_MSEC(10));
  const uint64_t free_target = 4;
  // Enable eviction. Min pages target is 5 pages. Free mem target is 4 pages.
  //
  // The free target is intentionally chosen to be smaller than the min target, so that we can
  // reliably predict how many pages will be evicted, regardless of how the min target updates are
  // interleaved between the test thread setting it and the eviction thread decrementing it after
  // freeing pages.
  //
  // For example, consider the case where the free target was 6 pages, that is greater than the
  // first min target of 5. There are three outcomes possible here (all valid from the evictor's
  // point of view):
  //
  // 1) The second EnableContinuousEviction happens *before* the eviction thread has decremented the
  // min target after freeing the first set of pages. Here the min target will be 13 when the
  // eviction thread goes to decrement it, and the decrement amount will be 6 (since 6 pages were
  // evicted per the free target with a min target of 5). The updated min target will be 7 and so
  // further 7 pages will be evicted. A total of 13 pages are evicted.
  //
  // 2) The second EnableContinuousEviction happens *after* the eviction thread has decremented the
  // min target after freeing the first set of pages. Here the min target will be 5 when the
  // eviction thread goes to decrement it, the decrement amount will be 6, so the min target will be
  // updated to 0. Now the new EnableContinuousEviction call will set min count to 8, so a further
  // of 8 pages will be evicted. A total of 14 pages are evicted.
  //
  // 3) Both EnableContinuousEviction calls happen before the eviction thread has performed any
  // eviction at all, i.e. it processes both requests together. It will see a min target of 13, a
  // free target of 6, and will evict a total of 13 pages at once.
  //
  // To avoid this inconsistency, we let the min target drive how many pages are evicted as opposed
  // to the free target, by setting the free target lower than the min target. In case 1) the
  // decrement amount will be 5, so a further of 8 pages will be evicted, i.e. a total of 13. In
  // case 2) as well, the decrement amount will be 5, so a further of 8 pages will be evicted i.e. a
  // total of 13. And in case 3) as well, a total of 13 pages will be evicted.
  //
  // Note that the opposite case (free target larger than min target) is covered in
  // evictor_continuous_test.
  node.evictor()->EnableContinuousEviction(5u * PAGE_SIZE, free_target * PAGE_SIZE,
                                           Evictor::EvictionLevel::IncludeNewest);
  // Verify that two successive calls to enable combine the min page targets.
  node.evictor()->EnableContinuousEviction(8u * PAGE_SIZE, free_target * PAGE_SIZE,
                                           Evictor::EvictionLevel::IncludeNewest);

  // The free target is 4 pages. The combined min target is 13 pages. We should see 13 pages
  // evicted.
  uint64_t expected_free_count = 13;
  while (node.FreePages() < expected_free_count) {
    printf("polling free count ...\n");
    Thread::Current::SleepRelative(ZX_MSEC(10));
  }
  EXPECT_EQ(node.FreePages(), expected_free_count);
  EXPECT_GE(node.FreePages(), free_target);

  // Make sure eviction is disabled so that the TestPmmNode destructor can clean up freed pages.
  node.evictor()->DisableContinuousEviction();
  Thread::Current::SleepRelative(ZX_MSEC(20));

  END_TEST;
}

// Test that pages are evicted as expected when continuous eviction is enabled and disabled
// repeatedly.
static bool evictor_continuous_repeated_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a pager backed vmo to evict pages from.
  fbl::RefPtr<VmObjectPaged> vmo;
  static constexpr size_t kNumPages = 44;
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo));

  // Promote the pages for eviction.
  vmo->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  TestPmmNode node;

  // Evict every 10 milliseconds.
  node.evictor()->SetContinuousEvictionInterval(ZX_MSEC(10));
  uint64_t free_target = 4;
  // Enable eviction. Min pages target is 5 pages. Free mem target is 4 pages.
  //
  // The free target is intentionally chosen to be smaller than the min target, so that we can
  // reliably predict how many pages will be evicted, regardless of how the min target updates are
  // interleaved between the test thread setting it and the eviction thread decrementing it after
  // freeing pages.
  //
  // For example, consider the case where the free target was 6 pages, that is greater than the
  // first min target of 5. There are two outcomes possible here (both valid from the evictor's
  // point of view):
  //
  // 1) The second EnableContinuousEviction happens *before* the eviction thread has decremented the
  // min target after freeing the first set of pages. Here the min target will be 12 when the
  // eviction thread goes to decrement it, and the decrement amount will be 6 (since 6 pages were
  // evicted per the free target with a min target of 5). The updated min target will be 6 and so
  // further 6 pages will be evicted. A total of 12 pages are evicted.
  //
  // 2) The second EnableContinuousEviction happens *after* the eviction thread has decremented the
  // min target after freeing the first set of pages. Here the min target will be 5 when the
  // eviction thread goes to decrement it, the decrement amount will be 6, so the min target will be
  // updated to 0. Now the new EnableContinuousEviction call will set min count to 7, so a further
  // of 7 pages will be evicted. A total of 13 pages are evicted.
  //
  // To avoid this inconsistency, we let the min target drive how many pages are evicted as opposed
  // to the free target, by setting the free target lower than the min target. In case 1) the
  // decrement amount will be 5, so a further of 7 pages will be evicted, i.e. a total of 12. In
  // case 2) as well, the decrement amount will be 5, so a further of 7 pages will be evicted i.e. a
  // total of 12.
  //
  // Note that the opposite case (free target larger than min target) is covered in
  // evictor_continuous_test.
  node.evictor()->EnableContinuousEviction(5u * PAGE_SIZE, free_target * PAGE_SIZE,
                                           Evictor::EvictionLevel::IncludeNewest);

  // Poll the node's free count, relying on the test timeout to kill us if something goes wrong.
  // The free target was 4 and min pages target was 5. We should see 5 pages freed.
  uint64_t expected_free_count = 5;
  while (node.FreePages() < expected_free_count) {
    printf("polling free count (case 1) ...\n");
    Thread::Current::SleepRelative(ZX_MSEC(10));
  }
  EXPECT_EQ(node.FreePages(), expected_free_count);
  EXPECT_GE(node.FreePages(), free_target);

  // Enable eviction again with a different min pages target.
  node.evictor()->EnableContinuousEviction(7u * PAGE_SIZE, free_target * PAGE_SIZE,
                                           Evictor::EvictionLevel::IncludeNewest);
  expected_free_count += 7;
  // We should see another 7 pages freed.
  while (node.FreePages() < expected_free_count) {
    printf("polling free count (case 2) ...\n");
    Thread::Current::SleepRelative(ZX_MSEC(10));
  }
  EXPECT_EQ(node.FreePages(), expected_free_count);
  EXPECT_GE(node.FreePages(), free_target);

  // Verify that we can disable and re-enable eviction.
  node.evictor()->DisableContinuousEviction();
  // Set a free target that is higher than the current free count to ensure we see some more pages
  // evicted.
  //
  // We're not relying on min target here to avoid another similar race as outlined above with
  // combining min targets. Here, the eviction thread could decrement the min target (based on the
  // previously freed 7 pages) before or after the following EnableContinuousEviction call. Say we
  // were setting the min target to M keeping the free target the same as before, then we could have
  // two cases (both valid from the evictor's point of view):
  //
  // 1) Eviction thread decrements by 7 *before* we enable. After the eviction thread is done, the
  // min target is going to be zero (regardless of the order of the disable call above, which also
  // resets to zero). When we enable, we will set the min target to M, and so M pages will be
  // evicted the next time.
  //
  // 2) Eviction thread decrements by 7 *after* we enable. The eviction thread will find the min
  // target to be M, and so will decrement it by 7. The resulting target will be |M-7| or 0,
  // depending on whether M is greater than 7 or smaller, respectively. So we will evict either
  // |M-7| or 0 pages.
  //
  // To avoid this scenario, we let the free target drive the next round of eviction, and set the
  // min target to 0. In both cases, the eviction thread will evict further pages based on the delta
  // between free target and the current free count.
  free_target = expected_free_count + 3;
  node.evictor()->EnableContinuousEviction(0, free_target * PAGE_SIZE,
                                           Evictor::EvictionLevel::IncludeNewest);
  // We should see another 3 pages freed.
  while (node.FreePages() < free_target) {
    printf("polling free count (case 3) ...\n");
    Thread::Current::SleepRelative(ZX_MSEC(10));
  }
  EXPECT_EQ(node.FreePages(), free_target);

  // Make sure eviction is disabled so that the TestPmmNode destructor can clean up freed pages.
  node.evictor()->DisableContinuousEviction();
  Thread::Current::SleepRelative(ZX_MSEC(20));

  END_TEST;
}

// Test that the evictor can evict DontNeed hinted pager backed pages as expected.
static bool evictor_dont_need_pager_backed_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a pager backed vmo with committed pages.
  fbl::RefPtr<VmObjectPaged> vmo1;
  static constexpr size_t kNumPages = 5;
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo1));

  // Promote the pages for eviction. This will put these pages in the DontNeed queue.
  vmo1->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);
  // Now touch these pages, changing the queue stashed in their vm_page_t without actually moving
  // them from the DontNeed queue. The expectation is that the next eviction attempt will fix up the
  // queue for these pages.
  for (size_t i = 0; i < kNumPages; i++) {
    uint8_t data;
    ASSERT_EQ(ZX_OK, vmo1->Read(&data, i * PAGE_SIZE, sizeof(data)));
  }

  // Create another pager backed vmo, which has newer pages compared to the previous one. This will
  // supply the pages below that actually get evicted.
  fbl::RefPtr<VmObjectPaged> vmo2;
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo2));

  // Promote the pages for eviction. This will put these pages in the DontNeed queue in LRU order,
  // i.e. they will be considered for eviction only after vmo1's pages.
  vmo2->HintRange(0, kNumPages * PAGE_SIZE, VmObject::EvictionHint::DontNeed);

  TestPmmNode node;
  // Only evict from pager backed vmos.
  node.evictor()->SetDiscardableEvictionsPercent(0);

  auto target = Evictor::EvictionTarget{
      .pending = true,
      .free_pages_target = 5,
      .min_pages_to_free = 5,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  // The node starts off with zero pages.
  uint64_t free_count = node.FreePages();
  EXPECT_EQ(free_count, 0u);

  node.evictor()->SetOneShotEvictionTarget(target);
  auto counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No discardable pages were evicted.
  EXPECT_EQ(counts.discardable, 0u);
  // Free pages target was the same as min pages target. So precisely free pages target must have
  // been evicted.
  EXPECT_EQ(counts.pager_backed, target.free_pages_target);
  EXPECT_GE(counts.pager_backed, target.min_pages_to_free);
  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  free_count = node.FreePages();
  EXPECT_EQ(free_count, target.free_pages_target);
  EXPECT_GE(free_count, target.min_pages_to_free);

  // vmo1 should have no pages evicted from it.
  EXPECT_EQ(kNumPages, vmo1->AttributedPages());

  END_TEST;
}

// Tests that evicted pages are removed from the VMO *and* added to the pmm free pool. Regression
// test for fxbug.dev/73865.
static bool evictor_evicted_pages_are_freed_test() {
  BEGIN_TEST;
  AutoVmScannerDisable scanner_disable;

  // Create a pager backed vmo with committed pages.
  fbl::RefPtr<VmObjectPaged> vmo;
  static constexpr size_t kNumPages = 5;
  vm_page_t* pages[kNumPages];
  ASSERT_EQ(ZX_OK, create_precommitted_pager_backed_vmo(kNumPages * PAGE_SIZE, &vmo, pages));

  // Verify that the vmo has committed pages.
  EXPECT_EQ(kNumPages, vmo->AttributedPages());

  // Rotate page queues a few times so the newly committed pages above are eligible for eviction.
  for (int i = 0; i < 3; i++) {
    pmm_page_queues()->RotatePagerBackedQueues();
  }

  TestPmmNode node;
  // Only evict from pager backed vmos.
  node.evictor()->SetDiscardableEvictionsPercent(0);

  auto target = Evictor::EvictionTarget{
      .pending = true,
      // Ensure that all evictable pages end up evicted, so we can verify that the vmo we created
      // has no pages remaining.
      .free_pages_target = UINT64_MAX,
      .min_pages_to_free = 0,
      .level = Evictor::EvictionLevel::IncludeNewest,
  };

  // The node starts off with zero pages.
  uint64_t free_count = node.FreePages();
  EXPECT_EQ(free_count, 0u);

  node.evictor()->SetOneShotEvictionTarget(target);
  auto counts = node.evictor()->EvictOneShotFromPreloadedTarget();

  // No discardable pages were evicted.
  EXPECT_EQ(counts.discardable, 0u);
  // Evicted pager backed pages should be more than or equal to the vmo's pages. If there were no
  // other evictable pages, we should at least have been able to evict from the vmo we created.
  EXPECT_GE(counts.pager_backed, kNumPages);
  EXPECT_GE(counts.pager_backed, target.min_pages_to_free);

  // The node has the desired number of free pages now, and a minimum of min pages have been freed.
  free_count = node.FreePages();
  EXPECT_GE(free_count, kNumPages);
  EXPECT_GE(free_count, target.min_pages_to_free);

  // All the evicted pages should have ended up in the node's free list. Pages that were evicted in
  // this test is the only way we can end up with free pages in this node. This verifies that
  // pages evicted from pager-backed vmos are freed.
  EXPECT_EQ(free_count, counts.pager_backed);

  // Verify that the vmo has no committed pages remaining. Evicted pages are removed from the vmo.
  EXPECT_EQ(0u, vmo->AttributedPages());

  // Verify free state for each page.
  for (auto page : pages) {
    EXPECT_TRUE(page->is_free());
  }

  END_TEST;
}

UNITTEST_START_TESTCASE(evictor_tests)
VM_UNITTEST(evictor_set_target_test)
VM_UNITTEST(evictor_combine_targets_test)
VM_UNITTEST(evictor_pager_backed_test)
VM_UNITTEST(evictor_discardable_test)
VM_UNITTEST(evictor_pager_backed_and_discardable_test)
VM_UNITTEST(evictor_free_target_test)
VM_UNITTEST(evictor_continuous_test)
VM_UNITTEST(evictor_continuous_combine_targets_test)
VM_UNITTEST(evictor_continuous_repeated_test)
VM_UNITTEST(evictor_dont_need_pager_backed_test)
VM_UNITTEST(evictor_evicted_pages_are_freed_test)
UNITTEST_END_TESTCASE(evictor_tests, "evictor", "Evictor tests")

}  // namespace vm_unittest
