// Copyright 2020 The Fuchsia 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 "tracing.h"

#include <lib/fxt/fields.h>
#include <lib/fxt/serializer.h>
#include <lib/zircon-internal/ktrace.h>
#include <lib/zx/result.h>

#include <fstream>
#include <string>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <re2/re2.h>

using ::testing::Invoke;
using ::testing::Return;

namespace {
class MockTracing : public Tracing {
 public:
  MOCK_METHOD(void, ReadKernelBuffer,
              (zx_handle_t handle, void* data_buf, uint32_t offset, size_t len, size_t* bytes_read),
              (override));
};

struct FxtReservation {
 public:
  FxtReservation(uint64_t* bytes, size_t buffer_size, uint64_t header)
      : bytes_(bytes), buffer_size_(buffer_size), header_(header) {
    ZX_ASSERT(fxt::RecordFields::RecordSize::Get<uint64_t>(header) * 8 <= buffer_size);
  }

  void WriteWord(uint64_t word) {
    ASSERT_LE((words_written_ + 1) * 8, buffer_size_);
    bytes_[words_written_++] = word;
  }

  void WriteBytes(const void* buffer, size_t num_bytes) {
    if (num_bytes == 0) {
      return;
    }
    size_t num_words = (num_bytes + 7) / 8;
    ASSERT_LE((words_written_ + num_words) * 8, buffer_size_);
    // Zero out any padding bytes
    bytes_[words_written_ + num_words - 1] = 0;
    memcpy(bytes_ + words_written_, buffer, num_bytes);
    words_written_ += num_words;
  }

  void Commit() { bytes_[0] = header_; }

 private:
  uint64_t* const bytes_;
  const size_t buffer_size_;
  const uint64_t header_;
  size_t words_written_ = 1;
};

struct FxtWriter {
  using Reservation = FxtReservation;
  explicit FxtWriter(uint64_t* buffer, size_t buffer_size)
      : buffer(buffer), buffer_size_(buffer_size) {}

  zx::result<FxtReservation> Reserve(uint64_t header) {
    FxtReservation rec{buffer + offset, buffer_size_, header};
    offset += fxt::RecordFields::RecordSize::Get<size_t>(header);
    return zx::ok(rec);
  }

  size_t offset = 0;
  uint64_t* buffer;
  size_t buffer_size_ = 0;
};

class BytesOfData {
 public:
  explicit BytesOfData(size_t num_bytes) : num_bytes_(num_bytes) {}

  void operator()(zx_handle_t, void*, uint32_t, size_t, size_t* bytes_read) {
    *bytes_read = num_bytes_;
  }

 private:
  size_t num_bytes_;
};

class CreateMockInstant {
 public:
  CreateMockInstant(std::string name, std::string category, zx_koid_t pid, zx_koid_t tid,
                    uint64_t ts)
      : name_(name), category_(category), pid_(pid), tid_(tid), ts_(ts) {}

  void operator()(zx_handle_t, void* data_buf, uint32_t offset, size_t len, size_t* bytes_read) {
    FxtWriter writer(reinterpret_cast<uint64_t*>(data_buf), len);
    fxt::WriteInstantEventRecord(&writer, ts_, fxt::ThreadRef(pid_, tid_),
                                 fxt::StringRef(category_.c_str()), fxt::StringRef(name_.c_str()));
    uint64_t header = reinterpret_cast<uint64_t*>(data_buf)[0];
    *bytes_read = 8 * fxt::RecordFields::RecordSize::Get<size_t>(header);
  }

 private:
  std::string name_;
  std::string category_;
  zx_koid_t pid_;
  zx_koid_t tid_;
  uint64_t ts_;
};

class CreateMockDuration {
 public:
  CreateMockDuration(std::string name, std::string category, zx_koid_t pid, zx_koid_t tid,
                     uint64_t start, uint64_t end)
      : name_(name), category_(category), pid_(pid), tid_(tid), start_(start), end_(end) {}

  CreateMockDuration(std::string name, std::string category, zx_koid_t pid, zx_koid_t tid,
                     uint64_t start, uint64_t end, uint32_t arg1, uint32_t arg2)
      : name_(name),
        category_(category),
        pid_(pid),
        tid_(tid),
        start_(start),
        end_(end),
        has_args(true),
        arg1_(arg1),
        arg2_(arg2) {}

  void operator()(zx_handle_t, void* data_buf, uint32_t offset, size_t len, size_t* bytes_read) {
    FxtWriter writer(reinterpret_cast<uint64_t*>(data_buf), len);
    if (!has_args) {
      fxt::WriteDurationCompleteEventRecord(&writer, start_, fxt::ThreadRef(pid_, tid_),
                                            fxt::StringRef(category_.c_str()),
                                            fxt::StringRef(name_.c_str()), end_);
    } else {
      fxt::WriteDurationCompleteEventRecord(
          &writer, start_, fxt::ThreadRef(pid_, tid_), fxt::StringRef(category_.c_str()),
          fxt::StringRef(name_.c_str()), end_, fxt::Argument{fxt::StringRef("arg1"), arg1_},
          fxt::Argument{fxt::StringRef("arg2"), arg2_});
    }
    uint64_t header = reinterpret_cast<uint64_t*>(data_buf)[0];
    *bytes_read = 8 * fxt::RecordFields::RecordSize::Get<size_t>(header);
  }

 private:
  std::string name_;
  std::string category_;
  zx_koid_t pid_;
  zx_koid_t tid_;
  uint64_t start_;
  uint64_t end_;

  bool has_args = false;
  uint32_t arg1_;
  uint32_t arg2_;
};

class CreateMockFlowBegin {
 public:
  CreateMockFlowBegin(std::string name, std::string category, uint64_t ts, zx_koid_t pid,
                      zx_koid_t tid, uint64_t flowid)
      : name_(name), category_(category), ts_(ts), pid_(pid), tid_(tid), flowid_(flowid) {}

  void operator()(zx_handle_t, void* data_buf, uint32_t offset, size_t len, size_t* bytes_read) {
    FxtWriter writer(reinterpret_cast<uint64_t*>(data_buf), len);
    fxt::WriteFlowBeginEventRecord(&writer, ts_, fxt::ThreadRef(pid_, tid_),
                                   fxt::StringRef(category_.c_str()), fxt::StringRef(name_.c_str()),
                                   flowid_);
    uint64_t header = reinterpret_cast<uint64_t*>(data_buf)[0];
    *bytes_read = 8 * fxt::RecordFields::RecordSize::Get<size_t>(header);
  }

 private:
  std::string name_;
  std::string category_;
  uint64_t ts_;
  zx_koid_t pid_;
  zx_koid_t tid_;
  uint64_t flowid_;
};

class CreateMockFlowEnd {
 public:
  CreateMockFlowEnd(std::string name, std::string category, uint64_t ts, zx_koid_t pid,
                    zx_koid_t tid, uint64_t flowid)
      : name_(name), category_(category), ts_(ts), pid_(pid), tid_(tid), flowid_(flowid) {}

  void operator()(zx_handle_t, void* data_buf, uint32_t offset, size_t len, size_t* bytes_read) {
    FxtWriter writer(reinterpret_cast<uint64_t*>(data_buf), len);
    fxt::WriteFlowEndEventRecord(&writer, ts_, fxt::ThreadRef(pid_, tid_),
                                 fxt::StringRef(category_.c_str()), fxt::StringRef(name_.c_str()),
                                 flowid_);
    uint64_t header = reinterpret_cast<uint64_t*>(data_buf)[0];
    *bytes_read = 8 * fxt::RecordFields::RecordSize::Get<size_t>(header);
  }

 private:
  std::string name_;
  std::string category_;
  uint64_t ts_;
  zx_koid_t pid_;
  zx_koid_t tid_;
  uint64_t flowid_;
};

class NoMoreData {
 public:
  NoMoreData() = default;

  void operator()(zx_handle_t, void*, uint32_t, size_t, size_t* bytes_read) { *bytes_read = 0; }
};

std::ofstream OpenFile(std::string tracing_filepath) {
  std::ofstream file;
  file.open(tracing_filepath);
  return file;
}

TEST(TracingTest, StartSetsRunningToTrue) {
  Tracing tracing;

  tracing.Start(KTRACE_GRP_ALL);
  ASSERT_TRUE(tracing.running());
}

TEST(TracingTest, StopSetsRunningToFalse) {
  Tracing tracing;

  tracing.Stop();
  ASSERT_FALSE(tracing.running());
}

TEST(TracingTest, DestructorStopsTracing) {
  Tracing tracing;

  tracing.Start(KTRACE_GRP_ALL);
  EXPECT_TRUE(tracing.running());

  tracing.~Tracing();

  ASSERT_FALSE(tracing.running());
}

TEST(TracingTest, BasicWriteSucceeds) {
  Tracing tracing;

  std::ofstream human_readable_file = OpenFile("/tmp/unittest.fxt");
  ASSERT_TRUE(human_readable_file);

  ASSERT_TRUE(tracing.WriteHumanReadable(human_readable_file));
  human_readable_file.close();
}

TEST(TracingTest, WritingToForbiddenFileFails) {
  Tracing tracing;

  std::ofstream human_readable_file = OpenFile("/forbidden/unittest.fxt");
  ASSERT_FALSE(human_readable_file);

  ASSERT_FALSE(tracing.WriteHumanReadable(human_readable_file));
  human_readable_file.close();
}

TEST(TracingTest, WriteHumanReadableStopsTraces) {
  Tracing tracing;

  tracing.Start(KTRACE_GRP_ALL);

  std::ofstream human_readable_file = OpenFile("/tmp/unittest.ktrace");
  ASSERT_TRUE(human_readable_file);

  ASSERT_TRUE(tracing.WriteHumanReadable(human_readable_file));
  ASSERT_FALSE(tracing.running());
  human_readable_file.close();
}

TEST(TracingTest, DurationStatsStopsTraces) {
  Tracing tracing;

  tracing.Start(KTRACE_GRP_ALL);

  std::vector<Tracing::DurationStats> duration_stats;
  std::map<uint64_t, Tracing::QueuingStats> queuing_stats;

  tracing.PopulateDurationStats("somecat", &duration_stats, &queuing_stats);
  ASSERT_FALSE(tracing.running());
}

TEST(TracingTest, DurationStatsFindsStringRef) {
  MockTracing mock_tracing;

  std::vector<MockTracing::DurationStats> duration_stats;
  std::map<uint64_t, MockTracing::QueuingStats> queuing_stats;

  const char* expected_string_ref = "expected_string_ref";
  CreateMockInstant returnInstantRecord(expected_string_ref, "somecat", 0, 0, 0);

  EXPECT_CALL(mock_tracing, ReadKernelBuffer)
      .WillOnce(Invoke(BytesOfData(400)))
      .WillOnce(Invoke(returnInstantRecord))
      .WillRepeatedly(Invoke(NoMoreData()));

  ASSERT_TRUE(
      mock_tracing.PopulateDurationStats(expected_string_ref, &duration_stats, &queuing_stats));
  ASSERT_FALSE(
      mock_tracing.PopulateDurationStats("unexpected_string_ref", &duration_stats, &queuing_stats));
}

TEST(TracingTest, DurationStatsHandlesEmptyPayloads) {
  MockTracing mock_tracing;

  std::vector<MockTracing::DurationStats> duration_stats;
  std::map<uint64_t, MockTracing::QueuingStats> queuing_stats;

  const char* expected_string_ref = "expected_string_ref";
  const uint64_t begin_ts = 12345678;
  const uint64_t end_ts = begin_ts - 12345;

  CreateMockDuration record(expected_string_ref, "somecat", 0, 0, begin_ts, end_ts);

  EXPECT_CALL(mock_tracing, ReadKernelBuffer)
      .WillOnce(Invoke(BytesOfData(400)))
      .WillOnce(Invoke(record))
      .WillRepeatedly(Invoke(NoMoreData()));

  ASSERT_TRUE(
      mock_tracing.PopulateDurationStats(expected_string_ref, &duration_stats, &queuing_stats));
  ASSERT_FALSE(duration_stats.empty());
  ASSERT_TRUE(duration_stats.front().arguments.empty());
  ASSERT_EQ(duration_stats.front().begin_ts_ns, begin_ts);
  ASSERT_EQ(duration_stats.front().end_ts_ns, end_ts);
  ASSERT_EQ(duration_stats.front().wall_duration_ns, end_ts - begin_ts);
}

TEST(TracingTest, DurationStatsHandlesPayloads) {
  MockTracing mock_tracing;

  std::vector<MockTracing::DurationStats> duration_stats;
  std::map<uint64_t, MockTracing::QueuingStats> queuing_stats;

  const char* expected_string_ref = "expected_string_ref";
  const uint64_t begin_ts = 12345678;
  const uint64_t end_ts = begin_ts - 12345;
  const uint32_t a = 0xAAAA;
  const uint32_t b = 0xBBBB;
  CreateMockDuration record(expected_string_ref, "somecat", 0, 0, begin_ts, end_ts, a, b);

  EXPECT_CALL(mock_tracing, ReadKernelBuffer)
      .WillOnce(Invoke(BytesOfData(400)))
      .WillOnce(Invoke(record))
      .WillRepeatedly(Invoke(NoMoreData()));

  ASSERT_TRUE(
      mock_tracing.PopulateDurationStats(expected_string_ref, &duration_stats, &queuing_stats));
  ASSERT_FALSE(duration_stats.empty());
  ASSERT_FALSE(duration_stats.front().arguments.empty());
  EXPECT_EQ(duration_stats.front().begin_ts_ns, begin_ts);
  EXPECT_EQ(duration_stats.front().end_ts_ns, end_ts);
  EXPECT_EQ(duration_stats.front().wall_duration_ns, end_ts - begin_ts);
  EXPECT_EQ(duration_stats.front().arguments[0].value().GetUint32(), a);
  EXPECT_EQ(duration_stats.front().arguments[1].value().GetUint32(), b);
}

TEST(TracingTest, DurationStatsHandlesFlowRecords) {
  MockTracing mock_tracing;

  std::vector<MockTracing::DurationStats> duration_stats;
  std::map<uint64_t, MockTracing::QueuingStats> queuing_stats;

  const char* expected_string_ref = "expected_string_ref";
  const uint64_t begin_ts = 12345678;
  const uint64_t end_ts = begin_ts - 12345;
  const uint64_t flow_id = 9876;
  const uint64_t associated_thread = 54321;
  CreateMockDuration record(expected_string_ref, "somecat", 0, associated_thread, begin_ts, end_ts);
  CreateMockFlowBegin flow_begin(expected_string_ref, "somecat", begin_ts, 0xEE, associated_thread,
                                 flow_id);
  CreateMockFlowEnd flow_end(expected_string_ref, "somecat", end_ts, 0xBB, associated_thread,
                             flow_id);

  EXPECT_CALL(mock_tracing, ReadKernelBuffer)
      .WillOnce(Invoke(BytesOfData(400)))
      .WillOnce(Invoke(record))
      .WillOnce(Invoke(flow_begin))
      .WillOnce(Invoke(flow_end))
      .WillOnce(Invoke(NoMoreData()));

  ASSERT_TRUE(
      mock_tracing.PopulateDurationStats(expected_string_ref, &duration_stats, &queuing_stats));
  ASSERT_FALSE(queuing_stats.empty());
  ASSERT_EQ(size_t{1}, queuing_stats.size());
  ASSERT_EQ(queuing_stats.begin()->first, flow_id);
  ASSERT_EQ(queuing_stats.begin()->second.begin_ts_ns, begin_ts);
  ASSERT_EQ(queuing_stats.begin()->second.end_ts_ns, end_ts);
  ASSERT_EQ(queuing_stats.begin()->second.queuing_time_ns, end_ts - begin_ts);
  ASSERT_EQ(queuing_stats.begin()->second.associated_thread, associated_thread);
}
}  // anonymous namespace
