// 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 "include/cppgc/allocation.h"
#include "include/cppgc/custom-space.h"
#include "src/heap/cppgc/heap-page.h"
#include "src/heap/cppgc/raw-heap.h"
#include "test/unittests/heap/cppgc/tests.h"

namespace cppgc {

class CustomSpace1 : public CustomSpace<CustomSpace1> {
 public:
  static constexpr size_t kSpaceIndex = 0;
};

class CustomSpace2 : public CustomSpace<CustomSpace2> {
 public:
  static constexpr size_t kSpaceIndex = 1;
};

namespace internal {

namespace {

size_t g_destructor_callcount;

class TestWithHeapWithCustomSpaces : public testing::TestWithPlatform {
 protected:
  TestWithHeapWithCustomSpaces() {
    Heap::HeapOptions options;
    options.custom_spaces.emplace_back(std::make_unique<CustomSpace1>());
    options.custom_spaces.emplace_back(std::make_unique<CustomSpace2>());
    heap_ = Heap::Create(platform_, std::move(options));
    g_destructor_callcount = 0;
  }

  void PreciseGC() {
    heap_->ForceGarbageCollectionSlow(
        ::testing::UnitTest::GetInstance()->current_test_info()->name(),
        "Testing", cppgc::Heap::StackState::kNoHeapPointers);
  }

  cppgc::Heap* GetHeap() const { return heap_.get(); }

 private:
  std::unique_ptr<cppgc::Heap> heap_;
};

class RegularGCed final : public GarbageCollected<RegularGCed> {
 public:
  void Trace(Visitor*) const {}
};

class CustomGCed1 final : public GarbageCollected<CustomGCed1> {
 public:
  ~CustomGCed1() { g_destructor_callcount++; }
  void Trace(Visitor*) const {}
};
class CustomGCed2 final : public GarbageCollected<CustomGCed2> {
 public:
  ~CustomGCed2() { g_destructor_callcount++; }
  void Trace(Visitor*) const {}
};

class CustomGCedBase : public GarbageCollected<CustomGCedBase> {
 public:
  void Trace(Visitor*) const {}
};
class CustomGCedFinal1 final : public CustomGCedBase {
 public:
  ~CustomGCedFinal1() { g_destructor_callcount++; }
};
class CustomGCedFinal2 final : public CustomGCedBase {
 public:
  ~CustomGCedFinal2() { g_destructor_callcount++; }
};

}  // namespace

}  // namespace internal

template <>
struct SpaceTrait<internal::CustomGCed1> {
  using Space = CustomSpace1;
};

template <>
struct SpaceTrait<internal::CustomGCed2> {
  using Space = CustomSpace2;
};

template <typename T>
struct SpaceTrait<
    T, std::enable_if_t<std::is_base_of<internal::CustomGCedBase, T>::value>> {
  using Space = CustomSpace1;
};

namespace internal {

TEST_F(TestWithHeapWithCustomSpaces, AllocateOnCustomSpaces) {
  auto* regular =
      MakeGarbageCollected<RegularGCed>(GetHeap()->GetAllocationHandle());
  auto* custom1 =
      MakeGarbageCollected<CustomGCed1>(GetHeap()->GetAllocationHandle());
  auto* custom2 =
      MakeGarbageCollected<CustomGCed2>(GetHeap()->GetAllocationHandle());
  EXPECT_EQ(RawHeap::kNumberOfRegularSpaces,
            NormalPage::FromPayload(custom1)->space()->index());
  EXPECT_EQ(RawHeap::kNumberOfRegularSpaces + 1,
            NormalPage::FromPayload(custom2)->space()->index());
  EXPECT_EQ(static_cast<size_t>(RawHeap::RegularSpaceType::kNormal1),
            NormalPage::FromPayload(regular)->space()->index());
}

TEST_F(TestWithHeapWithCustomSpaces,
       AllocateOnCustomSpacesSpecifiedThroughBase) {
  auto* regular =
      MakeGarbageCollected<RegularGCed>(GetHeap()->GetAllocationHandle());
  auto* custom1 =
      MakeGarbageCollected<CustomGCedFinal1>(GetHeap()->GetAllocationHandle());
  auto* custom2 =
      MakeGarbageCollected<CustomGCedFinal2>(GetHeap()->GetAllocationHandle());
  EXPECT_EQ(RawHeap::kNumberOfRegularSpaces,
            NormalPage::FromPayload(custom1)->space()->index());
  EXPECT_EQ(RawHeap::kNumberOfRegularSpaces,
            NormalPage::FromPayload(custom2)->space()->index());
  EXPECT_EQ(static_cast<size_t>(RawHeap::RegularSpaceType::kNormal1),
            NormalPage::FromPayload(regular)->space()->index());
}

TEST_F(TestWithHeapWithCustomSpaces, SweepCustomSpace) {
  MakeGarbageCollected<CustomGCedFinal1>(GetHeap()->GetAllocationHandle());
  MakeGarbageCollected<CustomGCedFinal2>(GetHeap()->GetAllocationHandle());
  MakeGarbageCollected<CustomGCed1>(GetHeap()->GetAllocationHandle());
  MakeGarbageCollected<CustomGCed2>(GetHeap()->GetAllocationHandle());
  EXPECT_EQ(0u, g_destructor_callcount);
  PreciseGC();
  EXPECT_EQ(4u, g_destructor_callcount);
}

}  // namespace internal

// Test custom space compactability.

class CompactableCustomSpace : public CustomSpace<CompactableCustomSpace> {
 public:
  static constexpr size_t kSpaceIndex = 0;
  static constexpr bool kSupportsCompaction = true;
};

class NotCompactableCustomSpace
    : public CustomSpace<NotCompactableCustomSpace> {
 public:
  static constexpr size_t kSpaceIndex = 1;
  static constexpr bool kSupportsCompaction = false;
};

class DefaultCompactableCustomSpace
    : public CustomSpace<DefaultCompactableCustomSpace> {
 public:
  static constexpr size_t kSpaceIndex = 2;
  // By default space are not compactable.
};

namespace internal {
namespace {

class TestWithHeapWithCompactableCustomSpaces
    : public testing::TestWithPlatform {
 protected:
  TestWithHeapWithCompactableCustomSpaces() {
    Heap::HeapOptions options;
    options.custom_spaces.emplace_back(
        std::make_unique<CompactableCustomSpace>());
    options.custom_spaces.emplace_back(
        std::make_unique<NotCompactableCustomSpace>());
    options.custom_spaces.emplace_back(
        std::make_unique<DefaultCompactableCustomSpace>());
    heap_ = Heap::Create(platform_, std::move(options));
    g_destructor_callcount = 0;
  }

  void PreciseGC() {
    heap_->ForceGarbageCollectionSlow("TestWithHeapWithCompactableCustomSpaces",
                                      "Testing",
                                      cppgc::Heap::StackState::kNoHeapPointers);
  }

  cppgc::Heap* GetHeap() const { return heap_.get(); }

 private:
  std::unique_ptr<cppgc::Heap> heap_;
};

class CompactableGCed final : public GarbageCollected<CompactableGCed> {
 public:
  void Trace(Visitor*) const {}
};
class NotCompactableGCed final : public GarbageCollected<NotCompactableGCed> {
 public:
  void Trace(Visitor*) const {}
};
class DefaultCompactableGCed final
    : public GarbageCollected<DefaultCompactableGCed> {
 public:
  void Trace(Visitor*) const {}
};

}  // namespace
}  // namespace internal

template <>
struct SpaceTrait<internal::CompactableGCed> {
  using Space = CompactableCustomSpace;
};
template <>
struct SpaceTrait<internal::NotCompactableGCed> {
  using Space = NotCompactableCustomSpace;
};
template <>
struct SpaceTrait<internal::DefaultCompactableGCed> {
  using Space = DefaultCompactableCustomSpace;
};

namespace internal {

TEST_F(TestWithHeapWithCompactableCustomSpaces,
       AllocateOnCompactableCustomSpaces) {
  auto* compactable =
      MakeGarbageCollected<CompactableGCed>(GetHeap()->GetAllocationHandle());
  auto* not_compactable = MakeGarbageCollected<NotCompactableGCed>(
      GetHeap()->GetAllocationHandle());
  auto* default_compactable = MakeGarbageCollected<DefaultCompactableGCed>(
      GetHeap()->GetAllocationHandle());
  EXPECT_TRUE(NormalPage::FromPayload(compactable)->space()->is_compactable());
  EXPECT_FALSE(
      NormalPage::FromPayload(not_compactable)->space()->is_compactable());
  EXPECT_FALSE(
      NormalPage::FromPayload(default_compactable)->space()->is_compactable());
}

}  // namespace internal

}  // namespace cppgc
