// 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/internal/gc-info.h"

#include "include/cppgc/platform.h"
#include "src/base/page-allocator.h"
#include "src/base/platform/platform.h"
#include "src/heap/cppgc/gc-info-table.h"
#include "test/unittests/heap/cppgc/tests.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cppgc {
namespace internal {

namespace {

constexpr GCInfo GetEmptyGCInfo() { return {nullptr, nullptr, nullptr, false}; }

}  // namespace

TEST(GCInfoTableTest, InitialEmpty) {
  v8::base::PageAllocator page_allocator;
  GCInfoTable table(&page_allocator);
  EXPECT_EQ(GCInfoTable::kMinIndex, table.NumberOfGCInfosForTesting());
}

TEST(GCInfoTableTest, ResizeToMaxIndex) {
  v8::base::PageAllocator page_allocator;
  GCInfoTable table(&page_allocator);
  GCInfo info = GetEmptyGCInfo();
  for (GCInfoIndex i = GCInfoTable::kMinIndex; i < GCInfoTable::kMaxIndex;
       i++) {
    GCInfoIndex index = table.RegisterNewGCInfo(info);
    EXPECT_EQ(i, index);
  }
}

TEST(GCInfoTableDeathTest, MoreThanMaxIndexInfos) {
  v8::base::PageAllocator page_allocator;
  GCInfoTable table(&page_allocator);
  GCInfo info = GetEmptyGCInfo();
  // Create GCInfoTable::kMaxIndex entries.
  for (GCInfoIndex i = GCInfoTable::kMinIndex; i < GCInfoTable::kMaxIndex;
       i++) {
    table.RegisterNewGCInfo(info);
  }
  EXPECT_DEATH_IF_SUPPORTED(table.RegisterNewGCInfo(info), "");
}

TEST(GCInfoTableDeathTest, OldTableAreaIsReadOnly) {
  v8::base::PageAllocator page_allocator;
  GCInfoTable table(&page_allocator);
  GCInfo info = GetEmptyGCInfo();
  // Use up all slots until limit.
  GCInfoIndex limit = table.LimitForTesting();
  // Bail out if initial limit is already the maximum because of large committed
  // pages. In this case, nothing can be comitted as read-only.
  if (limit == GCInfoTable::kMaxIndex) {
    return;
  }
  for (GCInfoIndex i = GCInfoTable::kMinIndex; i < limit; i++) {
    table.RegisterNewGCInfo(info);
  }
  EXPECT_EQ(limit, table.LimitForTesting());
  table.RegisterNewGCInfo(info);
  EXPECT_NE(limit, table.LimitForTesting());
  // Old area is now read-only.
  auto& first_slot = table.TableSlotForTesting(GCInfoTable::kMinIndex);
  EXPECT_DEATH_IF_SUPPORTED(first_slot.finalize = nullptr, "");
}

namespace {

class ThreadRegisteringGCInfoObjects final : public v8::base::Thread {
 public:
  ThreadRegisteringGCInfoObjects(GCInfoTable* table,
                                 GCInfoIndex num_registrations)
      : v8::base::Thread(Options("Thread registering GCInfo objects.")),
        table_(table),
        num_registrations_(num_registrations) {}

  void Run() final {
    GCInfo info = GetEmptyGCInfo();
    for (GCInfoIndex i = 0; i < num_registrations_; i++) {
      table_->RegisterNewGCInfo(info);
    }
  }

 private:
  GCInfoTable* table_;
  GCInfoIndex num_registrations_;
};

}  // namespace

TEST(GCInfoTableTest, MultiThreadedResizeToMaxIndex) {
  constexpr size_t num_threads = 4;
  constexpr size_t main_thread_initialized = 2;
  constexpr size_t gc_infos_to_register =
      (GCInfoTable::kMaxIndex - 1) -
      (GCInfoTable::kMinIndex + main_thread_initialized);
  static_assert(gc_infos_to_register % num_threads == 0,
                "must sum up to kMaxIndex");
  constexpr size_t gc_infos_per_thread = gc_infos_to_register / num_threads;

  v8::base::PageAllocator page_allocator;
  GCInfoTable table(&page_allocator);
  GCInfo info = GetEmptyGCInfo();
  for (size_t i = 0; i < main_thread_initialized; i++) {
    table.RegisterNewGCInfo(info);
  }

  v8::base::Thread* threads[num_threads];
  for (size_t i = 0; i < num_threads; i++) {
    threads[i] =
        new ThreadRegisteringGCInfoObjects(&table, gc_infos_per_thread);
  }
  for (size_t i = 0; i < num_threads; i++) {
    CHECK(threads[i]->Start());
  }
  for (size_t i = 0; i < num_threads; i++) {
    threads[i]->Join();
    delete threads[i];
  }
}

// Tests using the global table and GCInfoTrait.

namespace {

class GCInfoTraitTest : public testing::TestWithPlatform {};

class BasicType final {
 public:
  void Trace(Visitor*) const {}
};
class OtherBasicType final {
 public:
  void Trace(Visitor*) const {}
};

}  // namespace

TEST_F(GCInfoTraitTest, IndexInBounds) {
  const GCInfoIndex index = GCInfoTrait<BasicType>::Index();
  EXPECT_GT(GCInfoTable::kMaxIndex, index);
  EXPECT_LE(GCInfoTable::kMinIndex, index);
}

TEST_F(GCInfoTraitTest, TraitReturnsSameIndexForSameType) {
  const GCInfoIndex index1 = GCInfoTrait<BasicType>::Index();
  const GCInfoIndex index2 = GCInfoTrait<BasicType>::Index();
  EXPECT_EQ(index1, index2);
}

TEST_F(GCInfoTraitTest, TraitReturnsDifferentIndexForDifferentTypes) {
  const GCInfoIndex index1 = GCInfoTrait<BasicType>::Index();
  const GCInfoIndex index2 = GCInfoTrait<OtherBasicType>::Index();
  EXPECT_NE(index1, index2);
}

}  // namespace internal
}  // namespace cppgc
