// Copyright 2019 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/memory-measurement-inl.h"
#include "src/heap/memory-measurement.h"
#include "test/cctest/cctest.h"
#include "test/cctest/heap/heap-tester.h"
#include "test/cctest/heap/heap-utils.h"

namespace v8 {
namespace internal {
namespace heap {

namespace {
Handle<NativeContext> GetNativeContext(Isolate* isolate,
                                       v8::Local<v8::Context> v8_context) {
  Handle<Context> context = v8::Utils::OpenHandle(*v8_context);
  return handle(context->native_context(), isolate);
}
}  // anonymous namespace

TEST(NativeContextInferrerGlobalObject) {
  LocalContext env;
  Isolate* isolate = CcTest::i_isolate();
  HandleScope handle_scope(isolate);
  Handle<NativeContext> native_context = GetNativeContext(isolate, env.local());
  Handle<JSGlobalObject> global =
      handle(native_context->global_object(), isolate);
  NativeContextInferrer inferrer;
  Address inferred_context = 0;
  CHECK(inferrer.Infer(isolate, global->map(), *global, &inferred_context));
  CHECK_EQ(native_context->ptr(), inferred_context);
}

TEST(NativeContextInferrerJSFunction) {
  LocalContext env;
  Isolate* isolate = CcTest::i_isolate();
  HandleScope scope(isolate);
  Handle<NativeContext> native_context = GetNativeContext(isolate, env.local());
  v8::Local<v8::Value> result = CompileRun("(function () { return 1; })");
  Handle<Object> object = Utils::OpenHandle(*result);
  Handle<HeapObject> function = Handle<HeapObject>::cast(object);
  NativeContextInferrer inferrer;
  Address inferred_context = 0;
  CHECK(inferrer.Infer(isolate, function->map(), *function, &inferred_context));
  CHECK_EQ(native_context->ptr(), inferred_context);
}

TEST(NativeContextInferrerJSObject) {
  LocalContext env;
  Isolate* isolate = CcTest::i_isolate();
  HandleScope scope(isolate);
  Handle<NativeContext> native_context = GetNativeContext(isolate, env.local());
  v8::Local<v8::Value> result = CompileRun("({a : 10})");
  Handle<Object> object = Utils::OpenHandle(*result);
  Handle<HeapObject> function = Handle<HeapObject>::cast(object);
  NativeContextInferrer inferrer;
  Address inferred_context = 0;
  // TODO(ulan): Enable this test once we have more precise native
  // context inference.
  CHECK(inferrer.Infer(isolate, function->map(), *function, &inferred_context));
  CHECK_EQ(native_context->ptr(), inferred_context);
}

TEST(NativeContextStatsMerge) {
  LocalContext env;
  Isolate* isolate = CcTest::i_isolate();
  HandleScope scope(isolate);
  Handle<NativeContext> native_context = GetNativeContext(isolate, env.local());
  v8::Local<v8::Value> result = CompileRun("({a : 10})");
  Handle<HeapObject> object =
      Handle<HeapObject>::cast(Utils::OpenHandle(*result));
  NativeContextStats stats1, stats2;
  stats1.IncrementSize(native_context->ptr(), object->map(), *object, 10);
  stats2.IncrementSize(native_context->ptr(), object->map(), *object, 20);
  stats1.Merge(stats2);
  CHECK_EQ(30, stats1.Get(native_context->ptr()));
}

TEST(NativeContextStatsArrayBuffers) {
  LocalContext env;
  Isolate* isolate = CcTest::i_isolate();
  HandleScope scope(isolate);
  Handle<NativeContext> native_context = GetNativeContext(isolate, env.local());
  v8::Local<v8::ArrayBuffer> array_buffer =
      v8::ArrayBuffer::New(CcTest::isolate(), 1000);
  Handle<JSArrayBuffer> i_array_buffer = Utils::OpenHandle(*array_buffer);
  NativeContextStats stats;
  stats.IncrementSize(native_context->ptr(), i_array_buffer->map(),
                      *i_array_buffer, 10);
  CHECK_EQ(1010, stats.Get(native_context->ptr()));
}
namespace {

class TestResource : public v8::String::ExternalStringResource {
 public:
  explicit TestResource(uint16_t* data) : data_(data), length_(0) {
    while (data[length_]) ++length_;
  }

  ~TestResource() override { i::DeleteArray(data_); }

  const uint16_t* data() const override { return data_; }

  size_t length() const override { return length_; }

 private:
  uint16_t* data_;
  size_t length_;
};

}  // anonymous namespace

TEST(NativeContextStatsExternalString) {
  LocalContext env;
  Isolate* isolate = CcTest::i_isolate();
  HandleScope scope(isolate);
  Handle<NativeContext> native_context = GetNativeContext(isolate, env.local());
  const char* c_source = "0123456789";
  uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
  TestResource* resource = new TestResource(two_byte_source);
  Local<v8::String> string =
      v8::String::NewExternalTwoByte(CcTest::isolate(), resource)
          .ToLocalChecked();
  Handle<String> i_string = Utils::OpenHandle(*string);
  NativeContextStats stats;
  stats.IncrementSize(native_context->ptr(), i_string->map(), *i_string, 10);
  CHECK_EQ(10 + 10 * 2, stats.Get(native_context->ptr()));
}

namespace {

class MockPlatform : public TestPlatform {
 public:
  MockPlatform() : TestPlatform(), mock_task_runner_(new MockTaskRunner()) {
    // Now that it's completely constructed, make this the current platform.
    i::V8::SetPlatformForTesting(this);
  }

  std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner(
      v8::Isolate*) override {
    return mock_task_runner_;
  }

  double Delay() { return mock_task_runner_->Delay(); }

  void PerformTask() { mock_task_runner_->PerformTask(); }

  bool TaskPosted() { return mock_task_runner_->TaskPosted(); }

 private:
  class MockTaskRunner : public v8::TaskRunner {
   public:
    void PostTask(std::unique_ptr<v8::Task> task) override {}

    void PostDelayedTask(std::unique_ptr<Task> task,
                         double delay_in_seconds) override {
      task_ = std::move(task);
      delay_ = delay_in_seconds;
    }

    void PostIdleTask(std::unique_ptr<IdleTask> task) override {
      UNREACHABLE();
    }

    bool NonNestableTasksEnabled() const override { return true; }

    bool NonNestableDelayedTasksEnabled() const override { return true; }

    bool IdleTasksEnabled() override { return false; }

    double Delay() { return delay_; }

    void PerformTask() {
      std::unique_ptr<Task> task = std::move(task_);
      task->Run();
    }

    bool TaskPosted() { return task_.get(); }

   private:
    double delay_ = -1;
    std::unique_ptr<Task> task_;
  };
  std::shared_ptr<MockTaskRunner> mock_task_runner_;
};

class MockMeasureMemoryDelegate : public v8::MeasureMemoryDelegate {
 public:
  bool ShouldMeasure(v8::Local<v8::Context> context) override { return true; }

  void MeasurementComplete(
      const std::vector<std::pair<v8::Local<v8::Context>, size_t>>&
          context_sizes_in_bytes,
      size_t unattributed_size_in_bytes) override {
    // Empty.
  }
};

}  // namespace

TEST(RandomizedTimeout) {
  MockPlatform platform;
  v8::Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
  // We have to create the isolate manually here. Using CcTest::isolate() would
  // lead to the situation when the isolate outlives MockPlatform which may lead
  // to UAF on the background thread.
  v8::Isolate* isolate = v8::Isolate::New(create_params);
  std::vector<double> delays;
  for (int i = 0; i < 10; i++) {
    isolate->MeasureMemory(std::make_unique<MockMeasureMemoryDelegate>());
    delays.push_back(platform.Delay());
    platform.PerformTask();
  }
  std::sort(delays.begin(), delays.end());
  isolate->Dispose();
  CHECK_LT(delays[0], delays.back());
}

TEST(LazyMemoryMeasurement) {
  CcTest::InitializeVM();
  MockPlatform platform;
  CcTest::isolate()->MeasureMemory(
      std::make_unique<MockMeasureMemoryDelegate>(),
      v8::MeasureMemoryExecution::kLazy);
  CHECK(!platform.TaskPosted());
}

TEST(PartiallyInitializedJSFunction) {
  LocalContext env;
  Isolate* isolate = CcTest::i_isolate();
  Factory* factory = isolate->factory();
  HandleScope scope(isolate);
  Handle<JSFunction> js_function =
      factory->NewFunctionForTest(factory->NewStringFromAsciiChecked("test"));
  Handle<Context> context = handle(js_function->context(), isolate);

  // 1. Start simulating deserializaiton.
  isolate->RegisterDeserializerStarted();
  // 2. Set the context field to the uninitialized sentintel.
  TaggedField<Object, JSFunction::kContextOffset>::store(
      *js_function, Deserializer::uninitialized_field_value());
  // 3. Request memory meaurement and run all tasks. GC that runs as part
  // of the measurement should not crash.
  CcTest::isolate()->MeasureMemory(
      std::make_unique<MockMeasureMemoryDelegate>(),
      v8::MeasureMemoryExecution::kEager);
  while (v8::platform::PumpMessageLoop(v8::internal::V8::GetCurrentPlatform(),
                                       CcTest::isolate())) {
  }
  // 4. Restore the value and complete deserialization.
  TaggedField<Object, JSFunction::kContextOffset>::store(*js_function,
                                                         *context);
  isolate->RegisterDeserializerFinished();
}

TEST(PartiallyInitializedContext) {
  LocalContext env;
  Isolate* isolate = CcTest::i_isolate();
  Factory* factory = isolate->factory();
  HandleScope scope(isolate);
  Handle<ScopeInfo> scope_info =
      ReadOnlyRoots(isolate).global_this_binding_scope_info_handle();
  Handle<Context> context = factory->NewScriptContext(
      GetNativeContext(isolate, env.local()), scope_info);
  Handle<Map> map = handle(context->map(), isolate);
  Handle<NativeContext> native_context = handle(map->native_context(), isolate);
  // 1. Start simulating deserializaiton.
  isolate->RegisterDeserializerStarted();
  // 2. Set the native context field to the uninitialized sentintel.
  TaggedField<Object, Map::kConstructorOrBackPointerOrNativeContextOffset>::
      store(*map, Deserializer::uninitialized_field_value());
  // 3. Request memory meaurement and run all tasks. GC that runs as part
  // of the measurement should not crash.
  CcTest::isolate()->MeasureMemory(
      std::make_unique<MockMeasureMemoryDelegate>(),
      v8::MeasureMemoryExecution::kEager);
  while (v8::platform::PumpMessageLoop(v8::internal::V8::GetCurrentPlatform(),
                                       CcTest::isolate())) {
  }
  // 4. Restore the value and complete deserialization.
  TaggedField<Object, Map::kConstructorOrBackPointerOrNativeContextOffset>::
      store(*map, *native_context);
  isolate->RegisterDeserializerFinished();
}

}  // namespace heap
}  // namespace internal
}  // namespace v8
