// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/globals.h"

#if defined(DART_USE_TCMALLOC) && defined(DEBUG)

#include "platform/assert.h"
#include "vm/globals.h"
#include "vm/malloc_hooks.h"
#include "vm/os.h"
#include "vm/profiler.h"
#include "vm/profiler_service.h"
#include "vm/unit_test.h"

namespace dart {

static void MallocHookTestBufferInitializer(volatile char* buffer,
                                            uintptr_t size) {
  // Run through the buffer and do something. If we don't do this and the memory
  // in buffer isn't touched, the tcmalloc hooks won't be called.
  for (uintptr_t i = 0; i < size; ++i) {
    buffer[i] = i;
  }
}

class EnableMallocHooksScope : public ValueObject {
 public:
  EnableMallocHooksScope() {
    OSThread::Current();  // Ensure not allocated during test.
    saved_enable_malloc_hooks_ = FLAG_profiler_native_memory;
    FLAG_profiler_native_memory = true;
    MallocHooks::Init();
    MallocHooks::ResetStats();
  }

  ~EnableMallocHooksScope() {
    MallocHooks::Cleanup();
    FLAG_profiler_native_memory = saved_enable_malloc_hooks_;
  }

 private:
  bool saved_enable_malloc_hooks_;
};

class EnableMallocHooksAndStacksScope : public EnableMallocHooksScope {
 public:
  EnableMallocHooksAndStacksScope() {
    OSThread::Current();  // Ensure not allocated during test.
    saved_enable_stack_traces_ = MallocHooks::stack_trace_collection_enabled();
    MallocHooks::set_stack_trace_collection_enabled(true);
    if (!FLAG_profiler) {
      FLAG_profiler = true;
      Profiler::Init();
    }
    MallocHooks::ResetStats();
  }

  ~EnableMallocHooksAndStacksScope() {
    MallocHooks::set_stack_trace_collection_enabled(saved_enable_stack_traces_);
  }

 private:
  bool saved_enable_stack_traces_;
};

UNIT_TEST_CASE(BasicMallocHookTest) {
  EnableMallocHooksScope scope;

  EXPECT_EQ(0L, MallocHooks::allocation_count());
  EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes());
  const intptr_t buffer_size = 10;
  char* buffer = new char[buffer_size];
  MallocHookTestBufferInitializer(buffer, buffer_size);

  EXPECT_EQ(1L, MallocHooks::allocation_count());
  EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size),
            MallocHooks::heap_allocated_memory_in_bytes());

  delete[] buffer;
  EXPECT_EQ(0L, MallocHooks::allocation_count());
  EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes());
}

UNIT_TEST_CASE(FreeUnseenMemoryMallocHookTest) {
  EnableMallocHooksScope scope;

  const intptr_t pre_hook_buffer_size = 3;
  char* pre_hook_buffer = new char[pre_hook_buffer_size];
  MallocHookTestBufferInitializer(pre_hook_buffer, pre_hook_buffer_size);

  MallocHooks::ResetStats();
  EXPECT_EQ(0L, MallocHooks::allocation_count());
  EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes());

  const intptr_t buffer_size = 10;
  char* buffer = new char[buffer_size];
  MallocHookTestBufferInitializer(buffer, buffer_size);

  EXPECT_EQ(1L, MallocHooks::allocation_count());
  EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size),
            MallocHooks::heap_allocated_memory_in_bytes());

  delete[] pre_hook_buffer;
  EXPECT_EQ(1L, MallocHooks::allocation_count());
  EXPECT_EQ(static_cast<intptr_t>(sizeof(char) * buffer_size),
            MallocHooks::heap_allocated_memory_in_bytes());

  delete[] buffer;
  EXPECT_EQ(0L, MallocHooks::allocation_count());
  EXPECT_EQ(0L, MallocHooks::heap_allocated_memory_in_bytes());
}

DART_NOINLINE
static void* IgnoreUseAfterFree(void* x) {
  return x;
}

VM_UNIT_TEST_CASE(StackTraceMallocHookSimpleTest) {
  EnableMallocHooksAndStacksScope scope;

  char* var = static_cast<char*>(malloc(16 * sizeof(char)));
  Sample* sample = MallocHooks::GetSample(var);
  EXPECT(sample != NULL);

  void* lookup_var = IgnoreUseAfterFree(var);
  free(var);
  sample = MallocHooks::GetSample(lookup_var);
  EXPECT(sample == NULL);
}

static char* DART_NOINLINE StackTraceLengthHelper(uintptr_t* end_address) {
  char* var = static_cast<char*>(malloc(16 * sizeof(char)));
  *end_address = OS::GetProgramCounter();
  return var;
}

VM_UNIT_TEST_CASE(StackTraceMallocHookLengthTest) {
  EnableMallocHooksAndStacksScope scope;

  uintptr_t test_start_address =
      reinterpret_cast<uintptr_t>(Dart_TestStackTraceMallocHookLengthTest);
  uintptr_t helper_start_address =
      reinterpret_cast<uintptr_t>(StackTraceLengthHelper);
  uintptr_t helper_end_address = 0;

  char* var = StackTraceLengthHelper(&helper_end_address);
  Sample* sample = MallocHooks::GetSample(var);
  EXPECT(sample != NULL);
  uintptr_t test_end_address = OS::GetProgramCounter();

  // Ensure that all stack frames are where we expect them to be in the sample.
  // If they aren't, the kSkipCount constant in malloc_hooks.cc is likely
  // incorrect.
  uword address = sample->At(0);
  bool first_result =
      (helper_start_address <= address) && (helper_end_address >= address);
  EXPECT(first_result);
  address = sample->At(1);
  bool second_result =
      (test_start_address <= address) && (test_end_address >= address);
  EXPECT(second_result);

  if (!(first_result && second_result)) {
    OS::PrintErr(
        "If this test is failing, it's likely that the value set for"
        " the number of frames to skip in malloc_hooks.cc is "
        "incorrect for this configuration/platform. This value can be"
        " found in malloc_hooks.cc in the AllocationInfo class, and "
        "is stored in the kSkipCount constant.\n");
    OS::PrintErr("First result: %d Second Result: %d\n", first_result,
                 second_result);
    OS::PrintErr("Dumping sample stack trace:\n");
    sample->DumpStackTrace();
  }

  free(var);
}

ISOLATE_UNIT_TEST_CASE(StackTraceMallocHookSimpleJSONTest) {
  EnableMallocHooksAndStacksScope scope;

  ClearProfileVisitor cpv(Isolate::Current());
  Profiler::sample_block_buffer()->VisitSamples(&cpv);

  char* var = static_cast<char*>(malloc(16 * sizeof(char)));
  JSONStream js;
  ProfilerService::PrintNativeAllocationJSON(&js, -1, -1, false);
  const char* json = js.ToCString();

  // Check that all the stack frames from the current down to main are actually
  // present in the profile. This is just a simple sanity check to make sure
  // that the ProfileTrie has a representation of the stack trace collected when
  // var is allocated. More intense testing is already done in profiler_test.cc.
  // This is brittle: inlining and ICF in the C compiler and linker will affect
  // the frames we see.
  EXPECT_SUBSTRING("\"dart::Dart_TestStackTraceMallocHookSimpleJSONTest()\"",
                   json);
  EXPECT_SUBSTRING("\"dart::TestCase::Run()\"", json);
  EXPECT_SUBSTRING("\"dart::TestCaseBase::RunTest()\"", json);
  EXPECT_SUBSTRING("\"main\"", json);

  free(var);
}

};  // namespace dart

#endif  // defined(DART_USE_TCMALLOC) && !defined(DEBUG)
