// Copyright 2015 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 <stdlib.h>
#include <string.h>

#include "src/v8.h"

#include "src/list.h"
#include "src/list-inl.h"
#include "test/cctest/cctest.h"

using v8::IdleTask;
using v8::Task;
using v8::Isolate;

#include "src/tracing/trace-event.h"

#define GET_TRACE_OBJECTS_LIST platform.GetMockTraceObjects()

#define GET_TRACE_OBJECT(Index) GET_TRACE_OBJECTS_LIST->at(Index)


struct MockTraceObject {
  char phase;
  std::string name;
  uint64_t id;
  uint64_t bind_id;
  int num_args;
  unsigned int flags;
  MockTraceObject(char phase, std::string name, uint64_t id, uint64_t bind_id,
                  int num_args, int flags)
      : phase(phase),
        name(name),
        id(id),
        bind_id(bind_id),
        num_args(num_args),
        flags(flags) {}
};

typedef v8::internal::List<MockTraceObject*> MockTraceObjectList;

class MockTracingPlatform : public v8::Platform {
 public:
  explicit MockTracingPlatform(v8::Platform* platform) {}
  virtual ~MockTracingPlatform() {
    for (int i = 0; i < trace_object_list_.length(); ++i) {
      delete trace_object_list_[i];
    }
    trace_object_list_.Clear();
  }
  void CallOnBackgroundThread(Task* task,
                              ExpectedRuntime expected_runtime) override {}

  void CallOnForegroundThread(Isolate* isolate, Task* task) override {}

  void CallDelayedOnForegroundThread(Isolate* isolate, Task* task,
                                     double delay_in_seconds) override {}

  double MonotonicallyIncreasingTime() override { return 0.0; }

  void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) override {}

  bool IdleTasksEnabled(Isolate* isolate) override { return false; }

  bool PendingIdleTask() { return false; }

  void PerformIdleTask(double idle_time_in_seconds) {}

  bool PendingDelayedTask() { return false; }

  void PerformDelayedTask() {}

  uint64_t AddTraceEvent(char phase, const uint8_t* category_enabled_flag,
                         const char* name, uint64_t id, uint64_t bind_id,
                         int num_args, const char** arg_names,
                         const uint8_t* arg_types, const uint64_t* arg_values,
                         unsigned int flags) override {
    MockTraceObject* to = new MockTraceObject(phase, std::string(name), id,
                                              bind_id, num_args, flags);
    trace_object_list_.Add(to);
    return 0;
  }

  void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
                                const char* name, uint64_t handle) override {}

  const uint8_t* GetCategoryGroupEnabled(const char* name) override {
    if (strcmp(name, "v8-cat")) {
      static uint8_t no = 0;
      return &no;
    } else {
      static uint8_t yes = 0x7;
      return &yes;
    }
  }

  const char* GetCategoryGroupName(
      const uint8_t* category_enabled_flag) override {
    static const char dummy[] = "dummy";
    return dummy;
  }

  MockTraceObjectList* GetMockTraceObjects() { return &trace_object_list_; }

 private:
  MockTraceObjectList trace_object_list_;
};


TEST(TraceEventDisabledCategory) {
  v8::Platform* old_platform = i::V8::GetCurrentPlatform();
  MockTracingPlatform platform(old_platform);
  i::V8::SetPlatformForTesting(&platform);

  // Disabled category, will not add events.
  TRACE_EVENT_BEGIN0("cat", "e1");
  TRACE_EVENT_END0("cat", "e1");
  CHECK_EQ(0, GET_TRACE_OBJECTS_LIST->length());

  i::V8::SetPlatformForTesting(old_platform);
}


TEST(TraceEventNoArgs) {
  v8::Platform* old_platform = i::V8::GetCurrentPlatform();
  MockTracingPlatform platform(old_platform);
  i::V8::SetPlatformForTesting(&platform);

  // Enabled category will add 2 events.
  TRACE_EVENT_BEGIN0("v8-cat", "e1");
  TRACE_EVENT_END0("v8-cat", "e1");

  CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
  CHECK_EQ('B', GET_TRACE_OBJECT(0)->phase);
  CHECK_EQ("e1", GET_TRACE_OBJECT(0)->name);
  CHECK_EQ(0, GET_TRACE_OBJECT(0)->num_args);

  CHECK_EQ('E', GET_TRACE_OBJECT(1)->phase);
  CHECK_EQ("e1", GET_TRACE_OBJECT(1)->name);
  CHECK_EQ(0, GET_TRACE_OBJECT(1)->num_args);

  i::V8::SetPlatformForTesting(old_platform);
}


TEST(TraceEventWithOneArg) {
  v8::Platform* old_platform = i::V8::GetCurrentPlatform();
  MockTracingPlatform platform(old_platform);
  i::V8::SetPlatformForTesting(&platform);

  TRACE_EVENT_BEGIN1("v8-cat", "e1", "arg1", 42);
  TRACE_EVENT_END1("v8-cat", "e1", "arg1", 42);
  TRACE_EVENT_BEGIN1("v8-cat", "e2", "arg1", "abc");
  TRACE_EVENT_END1("v8-cat", "e2", "arg1", "abc");

  CHECK_EQ(4, GET_TRACE_OBJECTS_LIST->length());

  CHECK_EQ(1, GET_TRACE_OBJECT(0)->num_args);
  CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args);
  CHECK_EQ(1, GET_TRACE_OBJECT(2)->num_args);
  CHECK_EQ(1, GET_TRACE_OBJECT(3)->num_args);

  i::V8::SetPlatformForTesting(old_platform);
}


TEST(TraceEventWithTwoArgs) {
  v8::Platform* old_platform = i::V8::GetCurrentPlatform();
  MockTracingPlatform platform(old_platform);
  i::V8::SetPlatformForTesting(&platform);

  TRACE_EVENT_BEGIN2("v8-cat", "e1", "arg1", 42, "arg2", "abc");
  TRACE_EVENT_END2("v8-cat", "e1", "arg1", 42, "arg2", "abc");
  TRACE_EVENT_BEGIN2("v8-cat", "e2", "arg1", "abc", "arg2", 43);
  TRACE_EVENT_END2("v8-cat", "e2", "arg1", "abc", "arg2", 43);

  CHECK_EQ(4, GET_TRACE_OBJECTS_LIST->length());

  CHECK_EQ(2, GET_TRACE_OBJECT(0)->num_args);
  CHECK_EQ(2, GET_TRACE_OBJECT(1)->num_args);
  CHECK_EQ(2, GET_TRACE_OBJECT(2)->num_args);
  CHECK_EQ(2, GET_TRACE_OBJECT(3)->num_args);

  i::V8::SetPlatformForTesting(old_platform);
}


TEST(ScopedTraceEvent) {
  v8::Platform* old_platform = i::V8::GetCurrentPlatform();
  MockTracingPlatform platform(old_platform);
  i::V8::SetPlatformForTesting(&platform);

  { TRACE_EVENT0("v8-cat", "e"); }

  CHECK_EQ(1, GET_TRACE_OBJECTS_LIST->length());
  CHECK_EQ(0, GET_TRACE_OBJECT(0)->num_args);

  { TRACE_EVENT1("v8-cat", "e1", "arg1", "abc"); }

  CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
  CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args);

  { TRACE_EVENT2("v8-cat", "e1", "arg1", "abc", "arg2", 42); }

  CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->length());
  CHECK_EQ(2, GET_TRACE_OBJECT(2)->num_args);

  i::V8::SetPlatformForTesting(old_platform);
}


TEST(TestEventWithFlow) {
  v8::Platform* old_platform = i::V8::GetCurrentPlatform();
  MockTracingPlatform platform(old_platform);
  i::V8::SetPlatformForTesting(&platform);

  static uint64_t bind_id = 21;
  {
    TRACE_EVENT_WITH_FLOW0("v8-cat", "f1", bind_id, TRACE_EVENT_FLAG_FLOW_OUT);
  }
  {
    TRACE_EVENT_WITH_FLOW0(
        "v8-cat", "f2", bind_id,
        TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  }
  { TRACE_EVENT_WITH_FLOW0("v8-cat", "f3", bind_id, TRACE_EVENT_FLAG_FLOW_IN); }

  CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->length());
  CHECK_EQ(bind_id, GET_TRACE_OBJECT(0)->bind_id);
  CHECK_EQ(TRACE_EVENT_FLAG_FLOW_OUT, GET_TRACE_OBJECT(0)->flags);
  CHECK_EQ(bind_id, GET_TRACE_OBJECT(1)->bind_id);
  CHECK_EQ(TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
           GET_TRACE_OBJECT(1)->flags);
  CHECK_EQ(bind_id, GET_TRACE_OBJECT(2)->bind_id);
  CHECK_EQ(TRACE_EVENT_FLAG_FLOW_IN, GET_TRACE_OBJECT(2)->flags);

  i::V8::SetPlatformForTesting(old_platform);
}


TEST(TestEventWithId) {
  v8::Platform* old_platform = i::V8::GetCurrentPlatform();
  MockTracingPlatform platform(old_platform);
  i::V8::SetPlatformForTesting(&platform);

  static uint64_t event_id = 21;
  TRACE_EVENT_ASYNC_BEGIN0("v8-cat", "a1", event_id);
  TRACE_EVENT_ASYNC_END0("v8-cat", "a1", event_id);

  CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
  CHECK_EQ(TRACE_EVENT_PHASE_ASYNC_BEGIN, GET_TRACE_OBJECT(0)->phase);
  CHECK_EQ(event_id, GET_TRACE_OBJECT(0)->id);
  CHECK_EQ(TRACE_EVENT_PHASE_ASYNC_END, GET_TRACE_OBJECT(1)->phase);
  CHECK_EQ(event_id, GET_TRACE_OBJECT(1)->id);

  i::V8::SetPlatformForTesting(old_platform);
}
