// 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/allocation-observer.h"

#include "src/base/logging.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace v8 {
namespace internal {

namespace {
class UnusedObserver : public AllocationObserver {
 public:
  explicit UnusedObserver(size_t step_size) : AllocationObserver(step_size) {}
  void Step(int bytes_allocated, Address soon_object, size_t size) override {
    CHECK(false);
  }
};
}  // namespace

TEST(AllocationObserverTest, AddAndRemoveUnusedObservers) {
  AllocationCounter counter;
  CHECK(!counter.IsActive());

  UnusedObserver observer100(100);
  UnusedObserver observer200(200);

  counter.AddAllocationObserver(&observer200);
  CHECK_EQ(counter.NextBytes(), 200);

  counter.AddAllocationObserver(&observer100);
  CHECK_EQ(counter.NextBytes(), 100);

  counter.AdvanceAllocationObservers(90);
  CHECK_EQ(counter.NextBytes(), 10);

  counter.RemoveAllocationObserver(&observer100);
  CHECK_EQ(counter.NextBytes(), 110);

  counter.RemoveAllocationObserver(&observer200);
  CHECK(!counter.IsActive());
}

namespace {
class VerifyStepObserver : public AllocationObserver {
 public:
  explicit VerifyStepObserver(size_t step_size)
      : AllocationObserver(step_size) {}

  void Step(int bytes_allocated, Address soon_object, size_t size) override {
    CHECK(!do_not_invoke_);

    invocations_++;
    CHECK_EQ(expected_bytes_allocated_, bytes_allocated);
    CHECK_EQ(expected_size_, size);
  }

  void ExpectNoInvocation() { do_not_invoke_ = true; }
  void Expect(int expected_bytes_allocated, size_t expected_size) {
    do_not_invoke_ = false;
    expected_bytes_allocated_ = expected_bytes_allocated;
    expected_size_ = expected_size;
  }

  int Invocations() { return invocations_; }

 private:
  bool do_not_invoke_ = false;
  int invocations_ = 0;
  int expected_bytes_allocated_ = 0;
  size_t expected_size_ = 0;
};
}  // namespace

TEST(AllocationObserverTest, Step) {
  AllocationCounter counter;
  CHECK(!counter.IsActive());
  const Address kSomeObjectAddress = 8;

  VerifyStepObserver observer100(100);
  VerifyStepObserver observer200(200);

  counter.AddAllocationObserver(&observer100);
  counter.AddAllocationObserver(&observer200);

  observer100.Expect(90, 8);
  observer200.ExpectNoInvocation();

  counter.AdvanceAllocationObservers(90);
  counter.InvokeAllocationObservers(kSomeObjectAddress, 8, 10);
  CHECK_EQ(observer100.Invocations(), 1);
  CHECK_EQ(observer200.Invocations(), 0);
  CHECK_EQ(counter.NextBytes(),
           10 /* aligned_object_size */ + 100 /* smallest step size*/);

  observer100.Expect(90, 16);
  observer200.Expect(180, 16);

  counter.AdvanceAllocationObservers(90);
  counter.InvokeAllocationObservers(kSomeObjectAddress, 16, 20);
  CHECK_EQ(observer100.Invocations(), 2);
  CHECK_EQ(observer200.Invocations(), 1);
  CHECK_EQ(counter.NextBytes(),
           20 /* aligned_object_size */ + 100 /* smallest step size*/);
}

namespace {
class RecursiveAddObserver : public AllocationObserver {
 public:
  explicit RecursiveAddObserver(size_t step_size, AllocationCounter* counter,
                                AllocationObserver* observer)
      : AllocationObserver(step_size), counter_(counter), observer_(observer) {}

  void Step(int bytes_allocated, Address soon_object, size_t size) override {
    counter_->AddAllocationObserver(observer_);
  }

 private:
  AllocationCounter* counter_;
  AllocationObserver* observer_;
};
}  // namespace

TEST(AllocationObserverTest, RecursiveAdd) {
  AllocationCounter counter;
  const Address kSomeObjectAddress = 8;

  UnusedObserver observer50(50);
  RecursiveAddObserver observer100(100, &counter, &observer50);

  counter.AddAllocationObserver(&observer100);

  CHECK_EQ(counter.NextBytes(), 100);
  counter.AdvanceAllocationObservers(90);
  counter.InvokeAllocationObservers(kSomeObjectAddress, 10, 10);

  CHECK_EQ(counter.NextBytes(),
           10 /* aligned_object_size */ + 50 /* smallest step size */);
}

namespace {
class RecursiveRemoveObserver : public AllocationObserver {
 public:
  explicit RecursiveRemoveObserver(size_t step_size, AllocationCounter* counter,
                                   AllocationObserver* observer)
      : AllocationObserver(step_size), counter_(counter), observer_(observer) {}

  void Step(int bytes_allocated, Address soon_object, size_t size) override {
    counter_->RemoveAllocationObserver(observer_);
  }

 private:
  AllocationCounter* counter_;
  AllocationObserver* observer_;
};
}  // namespace

TEST(AllocationObserverTest, RecursiveRemove) {
  AllocationCounter counter;
  const Address kSomeObjectAddress = 8;

  UnusedObserver observer75(75);
  RecursiveRemoveObserver observer50(50, &counter, &observer75);

  counter.AddAllocationObserver(&observer50);
  counter.AddAllocationObserver(&observer75);

  CHECK_EQ(counter.NextBytes(), 50);
  counter.AdvanceAllocationObservers(40);
  counter.InvokeAllocationObservers(kSomeObjectAddress, 10, 10);

  CHECK_EQ(counter.NextBytes(),
           10 /* aligned_object_size */ + 50 /* smallest step size */);
}

}  // namespace internal
}  // namespace v8
