// Copyright 2020 the V8 project 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/heap/cppgc/free-list.h"

#include <memory>
#include <numeric>
#include <vector>

#include "src/base/bits.h"
#include "src/heap/cppgc/globals.h"
#include "src/heap/cppgc/heap-object-header.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cppgc {
namespace internal {
namespace {

class Block {
 public:
  Block() = default;
  explicit Block(size_t size) : address_(calloc(1, size)), size_(size) {}

  Block(Block&& other) V8_NOEXCEPT : address_(other.address_),
                                     size_(other.size_) {
    other.address_ = nullptr;
    other.size_ = 0;
  }

  Block& operator=(Block&& other) V8_NOEXCEPT {
    address_ = other.address_;
    size_ = other.size_;
    other.address_ = nullptr;
    other.size_ = 0;
    return *this;
  }

  ~Block() { free(address_); }

  void* Address() const { return address_; }
  size_t Size() const { return size_; }

 private:
  void* address_ = nullptr;
  size_t size_ = 0;
};

std::vector<Block> CreateEntries() {
  static constexpr size_t kFreeListEntrySizeLog2 =
      v8::base::bits::WhichPowerOfTwo(kFreeListEntrySize);
  std::vector<Block> vector;
  vector.reserve(kPageSizeLog2);
  for (size_t i = kFreeListEntrySizeLog2; i < kPageSizeLog2; ++i) {
    vector.emplace_back(static_cast<size_t>(1u) << i);
  }
  return vector;
}

FreeList CreatePopulatedFreeList(const std::vector<Block>& blocks) {
  FreeList list;
  for (const auto& block : blocks) {
    list.Add({block.Address(), block.Size()});
  }
  return list;
}

}  // namespace

TEST(FreeListTest, Empty) {
  FreeList list;
  EXPECT_TRUE(list.IsEmpty());
  EXPECT_EQ(0u, list.Size());

  auto block = list.Allocate(16);
  EXPECT_EQ(nullptr, block.address);
  EXPECT_EQ(0u, block.size);
}

TEST(FreeListTest, Add) {
  auto blocks = CreateEntries();
  FreeList list = CreatePopulatedFreeList(blocks);
  EXPECT_FALSE(list.IsEmpty());
  const size_t allocated_size = std::accumulate(
      blocks.cbegin(), blocks.cend(), 0u,
      [](size_t acc, const Block& b) { return acc + b.Size(); });
  EXPECT_EQ(allocated_size, list.Size());
}

TEST(FreeListTest, AddWasted) {
  FreeList list;
  alignas(HeapObjectHeader) uint8_t buffer[sizeof(HeapObjectHeader)];
  list.Add({buffer, sizeof(buffer)});
  EXPECT_EQ(0u, list.Size());
  EXPECT_TRUE(list.IsEmpty());
}

TEST(FreeListTest, Clear) {
  auto blocks = CreateEntries();
  FreeList list = CreatePopulatedFreeList(blocks);
  list.Clear();
  EXPECT_EQ(0u, list.Size());
  EXPECT_TRUE(list.IsEmpty());
}

TEST(FreeListTest, Move) {
  {
    auto blocks = CreateEntries();
    FreeList list1 = CreatePopulatedFreeList(blocks);
    const size_t expected_size = list1.Size();
    FreeList list2 = std::move(list1);
    EXPECT_EQ(expected_size, list2.Size());
    EXPECT_FALSE(list2.IsEmpty());
    EXPECT_EQ(0u, list1.Size());
    EXPECT_TRUE(list1.IsEmpty());
  }
  {
    auto blocks1 = CreateEntries();
    FreeList list1 = CreatePopulatedFreeList(blocks1);
    const size_t expected_size = list1.Size();

    auto blocks2 = CreateEntries();
    FreeList list2 = CreatePopulatedFreeList(blocks2);

    list2 = std::move(list1);
    EXPECT_EQ(expected_size, list2.Size());
    EXPECT_FALSE(list2.IsEmpty());
    EXPECT_EQ(0u, list1.Size());
    EXPECT_TRUE(list1.IsEmpty());
  }
}

TEST(FreeListTest, Append) {
  auto blocks1 = CreateEntries();
  FreeList list1 = CreatePopulatedFreeList(blocks1);
  const size_t list1_size = list1.Size();

  auto blocks2 = CreateEntries();
  FreeList list2 = CreatePopulatedFreeList(blocks2);
  const size_t list2_size = list1.Size();

  list2.Append(std::move(list1));
  EXPECT_EQ(list1_size + list2_size, list2.Size());
  EXPECT_FALSE(list2.IsEmpty());
  EXPECT_EQ(0u, list1.Size());
  EXPECT_TRUE(list1.IsEmpty());
}

TEST(FreeListTest, Contains) {
  auto blocks = CreateEntries();
  FreeList list = CreatePopulatedFreeList(blocks);

  for (const auto& block : blocks) {
    EXPECT_TRUE(list.Contains({block.Address(), block.Size()}));
  }
}

TEST(FreeListTest, Allocate) {
  static constexpr size_t kFreeListEntrySizeLog2 =
      v8::base::bits::WhichPowerOfTwo(kFreeListEntrySize);

  std::vector<Block> blocks;
  blocks.reserve(kPageSizeLog2);
  for (size_t i = kFreeListEntrySizeLog2; i < kPageSizeLog2; ++i) {
    blocks.emplace_back(static_cast<size_t>(1u) << i);
  }

  FreeList list = CreatePopulatedFreeList(blocks);

  // Try allocate from the biggest block.
  for (auto it = blocks.rbegin(); it < blocks.rend(); ++it) {
    const auto result = list.Allocate(it->Size());
    EXPECT_EQ(it->Address(), result.address);
    EXPECT_EQ(it->Size(), result.size);
  }

  EXPECT_EQ(0u, list.Size());
  EXPECT_TRUE(list.IsEmpty());

  // Check that allocation fails for empty list:
  const auto empty_block = list.Allocate(8);
  EXPECT_EQ(nullptr, empty_block.address);
  EXPECT_EQ(0u, empty_block.size);
}

}  // namespace internal
}  // namespace cppgc
