// 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/object-start-bitmap.h"

#include "include/cppgc/allocation.h"
#include "src/base/macros.h"
#include "src/heap/cppgc/globals.h"
#include "src/heap/cppgc/heap-object-header.h"
#include "src/heap/cppgc/page-memory.h"
#include "src/heap/cppgc/raw-heap.h"
#include "test/unittests/heap/cppgc/tests.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cppgc {
namespace internal {

namespace {

bool IsEmpty(const ObjectStartBitmap& bitmap) {
  size_t count = 0;
  bitmap.Iterate([&count](Address) { count++; });
  return count == 0;
}

// Abstraction for objects that hides ObjectStartBitmap::kGranularity and
// the base address as getting either of it wrong will result in failed DCHECKs.
class Object {
 public:
  static Address kBaseOffset;

  explicit Object(size_t number) : number_(number) {
    const size_t max_entries = ObjectStartBitmap::MaxEntries();
    EXPECT_GE(max_entries, number_);
  }

  Address address() const {
    return kBaseOffset + ObjectStartBitmap::Granularity() * number_;
  }

  HeapObjectHeader* header() const {
    return reinterpret_cast<HeapObjectHeader*>(address());
  }

  // Allow implicitly converting Object to Address.
  operator Address() const { return address(); }

 private:
  const size_t number_;
};

Address Object::kBaseOffset = reinterpret_cast<Address>(0x4000);

}  // namespace

TEST(ObjectStartBitmapTest, MoreThanZeroEntriesPossible) {
  const size_t max_entries = ObjectStartBitmap::MaxEntries();
  EXPECT_LT(0u, max_entries);
}

TEST(ObjectStartBitmapTest, InitialEmpty) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  EXPECT_TRUE(IsEmpty(bitmap));
}

TEST(ObjectStartBitmapTest, SetBitImpliesNonEmpty) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  bitmap.SetBit(Object(0));
  EXPECT_FALSE(IsEmpty(bitmap));
}

TEST(ObjectStartBitmapTest, SetBitCheckBit) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object(7);
  bitmap.SetBit(object);
  EXPECT_TRUE(bitmap.CheckBit(object));
}

TEST(ObjectStartBitmapTest, SetBitClearbitCheckBit) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object(77);
  bitmap.SetBit(object);
  bitmap.ClearBit(object);
  EXPECT_FALSE(bitmap.CheckBit(object));
}

TEST(ObjectStartBitmapTest, SetBitClearBitImpliesEmpty) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object(123);
  bitmap.SetBit(object);
  bitmap.ClearBit(object);
  EXPECT_TRUE(IsEmpty(bitmap));
}

TEST(ObjectStartBitmapTest, AdjacentObjectsAtBegin) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object0(0);
  Object object1(1);
  bitmap.SetBit(object0);
  bitmap.SetBit(object1);
  EXPECT_FALSE(bitmap.CheckBit(Object(3)));
  size_t count = 0;
  bitmap.Iterate([&count, object0, object1](Address current) {
    if (count == 0) {
      EXPECT_EQ(object0.address(), current);
    } else if (count == 1) {
      EXPECT_EQ(object1.address(), current);
    }
    count++;
  });
  EXPECT_EQ(2u, count);
}

TEST(ObjectStartBitmapTest, AdjacentObjectsAtEnd) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  const size_t last_entry_index = ObjectStartBitmap::MaxEntries() - 1;
  Object object0(last_entry_index - 1);
  Object object1(last_entry_index);
  bitmap.SetBit(object0);
  bitmap.SetBit(object1);
  EXPECT_FALSE(bitmap.CheckBit(Object(last_entry_index - 2)));
  size_t count = 0;
  bitmap.Iterate([&count, object0, object1](Address current) {
    if (count == 0) {
      EXPECT_EQ(object0.address(), current);
    } else if (count == 1) {
      EXPECT_EQ(object1.address(), current);
    }
    count++;
  });
  EXPECT_EQ(2u, count);
}

TEST(ObjectStartBitmapTest, FindHeaderExact) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object(654);
  bitmap.SetBit(object);
  EXPECT_EQ(object.header(), bitmap.FindHeader(object.address()));
}

TEST(ObjectStartBitmapTest, FindHeaderApproximate) {
  static const size_t kInternalDelta = 37;
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object(654);
  bitmap.SetBit(object);
  EXPECT_EQ(object.header(),
            bitmap.FindHeader(object.address() + kInternalDelta));
}

TEST(ObjectStartBitmapTest, FindHeaderIteratingWholeBitmap) {
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object_to_find(Object(0));
  Address hint_index = Object(ObjectStartBitmap::MaxEntries() - 1);
  bitmap.SetBit(object_to_find);
  EXPECT_EQ(object_to_find.header(), bitmap.FindHeader(hint_index));
}

TEST(ObjectStartBitmapTest, FindHeaderNextCell) {
  // This white box test makes use of the fact that cells are of type uint8_t.
  const size_t kCellSize = sizeof(uint8_t);
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object_to_find(Object(kCellSize - 1));
  Address hint = Object(kCellSize);
  bitmap.SetBit(Object(0));
  bitmap.SetBit(object_to_find);
  EXPECT_EQ(object_to_find.header(), bitmap.FindHeader(hint));
}

TEST(ObjectStartBitmapTest, FindHeaderSameCell) {
  // This white box test makes use of the fact that cells are of type uint8_t.
  const size_t kCellSize = sizeof(uint8_t);
  ObjectStartBitmap bitmap(Object::kBaseOffset);
  Object object_to_find(Object(kCellSize - 1));
  bitmap.SetBit(Object(0));
  bitmap.SetBit(object_to_find);
  EXPECT_EQ(object_to_find.header(),
            bitmap.FindHeader(object_to_find.address()));
}

}  // namespace internal
}  // namespace cppgc
