// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMIUMOS_WIDE_PROFILING_TEST_PERF_DATA_H_
#define CHROMIUMOS_WIDE_PROFILING_TEST_PERF_DATA_H_

#include <memory>
#include <ostream>  // NOLINT
#include <vector>

#include "chromiumos-wide-profiling/compat/string.h"
#include "chromiumos-wide-profiling/kernel/perf_internals.h"
#include "chromiumos-wide-profiling/utils.h"

namespace quipper {
namespace testing {

// Union for punning 32-bit words into a 64-bit word.
union PunU32U64 {
  u32 v32[2];
  u64 v64;
};

class StreamWriteable {
 public:
  StreamWriteable() : is_cross_endian_(false) {}
  virtual ~StreamWriteable() {}

  virtual void WriteTo(std::ostream* out) const = 0;

  virtual StreamWriteable& WithCrossEndianness(bool value) {
    is_cross_endian_ = value;
    return *this;
  }

  // Do not call MaybeSwap() directly. The syntax of test data structure
  // initialization makes data sizes ambiguous, so these force the caller to
  // explicitly specify value sizes.
  uint16_t MaybeSwap16(uint16_t value) const {
    return MaybeSwap(value);
  }
  uint32_t MaybeSwap32(uint32_t value) const {
    return MaybeSwap(value);
  }
  uint64_t MaybeSwap64(uint64_t value) const {
    return MaybeSwap(value);
  }

 protected:
  // Derived classes can call this to determine the cross-endianness. However,
  // the actual implementation of cross-endianness is up to the derived class,
  // if it supports it at all.
  bool is_cross_endian() const {
    return is_cross_endian_;
  }

 private:
  template <typename T>
  T MaybeSwap(T value) const {
    if (is_cross_endian())
      ByteSwap(&value);
    return value;
  }

  bool is_cross_endian_;
};

// Normal mode header
class ExamplePerfDataFileHeader : public StreamWriteable {
 public:
  typedef ExamplePerfDataFileHeader SelfT;
  explicit ExamplePerfDataFileHeader(const unsigned long features);  // NOLINT

  SelfT& WithAttrIdsCount(size_t n);
  SelfT& WithAttrCount(size_t n);
  SelfT& WithDataSize(size_t sz);

  // Used for testing compatibility w.r.t. sizeof(perf_event_attr)
  SelfT& WithCustomPerfEventAttrSize(size_t sz);

  const struct perf_file_header& header() const {
    return header_;
  }

  u64 data_end_offset() const {
    return header_.data.offset + header_.data.size;
  }
  ssize_t data_end() const {
    return static_cast<ssize_t>(data_end_offset());
  }

  void WriteTo(std::ostream* out) const override;

 protected:
  struct perf_file_header header_;
  size_t attr_ids_count_ = 0;

 private:
  void UpdateSectionOffsets();
};

// Produces the pipe-mode file header.
class ExamplePipedPerfDataFileHeader : public StreamWriteable {
 public:
  ExamplePipedPerfDataFileHeader() {}
  void WriteTo(std::ostream* out) const override;
};

// Produces a PERF_RECORD_HEADER_ATTR event with struct perf_event_attr
// describing a hardware event. The sample_type mask and the sample_id_all
// bit are paramatized.
class ExamplePerfEventAttrEvent_Hardware : public StreamWriteable {
 public:
  typedef ExamplePerfEventAttrEvent_Hardware SelfT;
  explicit ExamplePerfEventAttrEvent_Hardware(u64 sample_type,
                                              bool sample_id_all)
      : attr_size_(sizeof(perf_event_attr)),
        sample_type_(sample_type),
        sample_id_all_(sample_id_all),
        config_(0) {
  }
  SelfT& WithConfig(u64 config) { config_ = config; return *this; }
  SelfT& WithAttrSize(u32 size) { attr_size_ = size; return *this; }
  SelfT& WithId(u64 id) { ids_.push_back(id); return *this; }
  SelfT& WithIds(std::initializer_list<u64> ids) {
    ids_.insert(ids_.end(), ids.begin(), ids.end());
    return *this;
  }
  void WriteTo(std::ostream* out) const override;
 private:
  u32 attr_size_;
  const u64 sample_type_;
  const bool sample_id_all_;
  u64 config_;
  std::vector<u64> ids_;
};

class AttrIdsSection : public StreamWriteable {
 public:
  explicit AttrIdsSection(size_t initial_offset) : offset_(initial_offset) {}

  perf_file_section AddId(u64 id) { return AddIds({id}); }
  perf_file_section AddIds(std::initializer_list<u64> ids) {
    ids_.insert(ids_.end(), ids.begin(), ids.end());
    perf_file_section s = {
      .offset = offset_,
      .size = ids.size() * sizeof(decltype(ids)::value_type),
    };
    offset_ += s.size;
    return s;
  }
  void WriteTo(std::ostream* out) const override;
 private:
  u64 offset_;
  std::vector<u64> ids_;
};

// Produces a struct perf_file_attr with a perf_event_attr describing a
// hardware event.
class ExamplePerfFileAttr_Hardware : public StreamWriteable {
 public:
  typedef ExamplePerfFileAttr_Hardware SelfT;
  explicit ExamplePerfFileAttr_Hardware(u64 sample_type, bool sample_id_all)
      : attr_size_(sizeof(perf_event_attr)),
        sample_type_(sample_type),
        sample_id_all_(sample_id_all),
        config_(0),
        ids_section_({.offset = MaybeSwap64(104), .size = MaybeSwap64(0)}) {
  }
  SelfT& WithAttrSize(u32 size) { attr_size_ = size; return *this; }
  SelfT& WithConfig(u64 config) { config_ = config; return *this; }
  SelfT& WithIds(const perf_file_section& section) {
    ids_section_ = section;
    return *this;
  }
  void WriteTo(std::ostream* out) const override;
 private:
  u32 attr_size_;
  const u64 sample_type_;
  const bool sample_id_all_;
  u64 config_;
  perf_file_section ids_section_;
};

// Produces a struct perf_file_attr with a perf_event_attr describing a
// tracepoint event.
class ExamplePerfFileAttr_Tracepoint : public StreamWriteable {
 public:
  explicit ExamplePerfFileAttr_Tracepoint(const u64 tracepoint_event_id)
      : tracepoint_event_id_(tracepoint_event_id) {}
  void WriteTo(std::ostream* out) const override;
 private:
  const u64 tracepoint_event_id_;
};

// Produces a sample field array that can be used with either SAMPLE events
// or as the sample_id of another event.
// NB: This class simply places the fields in the order called. It does not
// enforce that they are in the correct order, or match the sample type.
// See enum perf_event_type in perf_event.h.
class SampleInfo {
 public:
  SampleInfo& Ip(u64 ip) { return AddField(ip); }
  SampleInfo& Tid(u32 pid, u32 tid) {
    return AddField(PunU32U64{.v32 = {pid, tid}}.v64);
  }
  SampleInfo& Tid(u32 pid) {
    return AddField(PunU32U64{.v32 = {pid, pid}}.v64);
  }
  SampleInfo& Time(u64 time) { return AddField(time); }
  SampleInfo& Id(u64 id) { return AddField(id); }
  SampleInfo& BranchStack_nr(u64 nr) { return AddField(nr); }
  SampleInfo& BranchStack_lbr(u64 from, u64 to, u64 flags) {
    AddField(from);
    AddField(to);
    AddField(flags);
    return *this;
  }

  const char* data() const {
    return reinterpret_cast<const char *>(fields_.data());
  }
  const size_t size() const {
    return fields_.size() * sizeof(decltype(fields_)::value_type);
  }

 private:
  SampleInfo& AddField(u64 value) {
    fields_.push_back(value);
    return *this;
  }

  std::vector<u64> fields_;
};

// Produces a PERF_RECORD_MMAP event with the given file and mapping.
class ExampleMmapEvent : public StreamWriteable {
 public:
  ExampleMmapEvent(u32 pid, u64 start, u64 len, u64 pgoff, string filename,
                   const SampleInfo& sample_id)
      : pid_(pid),
        start_(start),
        len_(len),
        pgoff_(pgoff),
        filename_(filename),
        sample_id_(sample_id) {
  }
  size_t GetSize() const;
  void WriteTo(std::ostream* out) const override;
 private:
  const u32 pid_;
  const u64 start_;
  const u64 len_;
  const u64 pgoff_;
  const string filename_;
  const SampleInfo sample_id_;
};

// Produces a PERF_RECORD_MMAP2 event with the given file and mapping.
class ExampleMmap2Event : public StreamWriteable {
 public:
  typedef ExampleMmap2Event SelfT;
  // pid is used as both pid and tid.
  ExampleMmap2Event(u32 pid, u64 start, u64 len, u64 pgoff,
                    string filename, const SampleInfo& sample_id)
      : ExampleMmap2Event(pid, pid, start, len, pgoff, filename, sample_id) {}
  ExampleMmap2Event(u32 pid, u32 tid, u64 start, u64 len, u64 pgoff,
                    string filename, const SampleInfo& sample_id)
      : pid_(pid),
        tid_(tid),
        start_(start),
        len_(len),
        pgoff_(pgoff),
        maj_(6),
        min_(7),
        ino_(8),
        filename_(filename),
        sample_id_(sample_id) {
  }

  SelfT& WithDeviceInfo(u32 maj, u32 min, u64 ino) {
    maj_ = maj;
    min_ = min;
    ino_ = ino;
    return *this;
  }

  void WriteTo(std::ostream* out) const override;
 private:
  const u32 pid_;
  const u32 tid_;
  const u64 start_;
  const u64 len_;
  const u64 pgoff_;
  u32 maj_;
  u32 min_;
  u64 ino_;
  const string filename_;
  const SampleInfo sample_id_;
};

// Produces a PERF_RECORD_FORK or PERF_RECORD_EXIT event.
// Cannot be instantiated directly; use a derived class.
class ExampleForkExitEvent : public StreamWriteable {
 public:
  void WriteTo(std::ostream* out) const override;
 protected:
  ExampleForkExitEvent(u32 type, u32 pid, u32 ppid, u32 tid, u32 ptid, u64 time,
                       const SampleInfo& sample_id)
      : type_(type),
        pid_(pid), ppid_(ppid),
        tid_(tid), ptid_(ptid),
        time_(time),
        sample_id_(sample_id) {}
  const u32 type_;    // Either PERF_RECORD_FORK or PERF_RECORD_EXIT.
 private:
  const u32 pid_;
  const u32 ppid_;
  const u32 tid_;
  const u32 ptid_;
  const u64 time_;
  const SampleInfo sample_id_;
};

// Produces a PERF_RECORD_FORK event.
class ExampleForkEvent : public ExampleForkExitEvent {
 public:
  ExampleForkEvent(u32 pid, u32 ppid, u32 tid, u32 ptid, u64 time,
                   const SampleInfo& sample_id)
      : ExampleForkExitEvent(PERF_RECORD_FORK, pid, ppid, tid, ptid, time,
                             sample_id) {}
};

// Produces a PERF_RECORD_EXIT event.
class ExampleExitEvent : public ExampleForkExitEvent {
 public:
  ExampleExitEvent(u32 pid, u32 ppid, u32 tid, u32 ptid, u64 time,
                   const SampleInfo& sample_id)
      : ExampleForkExitEvent(PERF_RECORD_EXIT, pid, ppid, tid, ptid, time,
                             sample_id) {}
};

// Produces the PERF_RECORD_FINISHED_ROUND event. This event is just a header.
class FinishedRoundEvent : public StreamWriteable {
 public:
  void WriteTo(std::ostream* out) const override;
};

// Produces a simple PERF_RECORD_SAMPLE event with the given sample info.
// NB: The sample_info must match the sample_type of the relevant attr.
class ExamplePerfSampleEvent : public StreamWriteable {
 public:
  explicit ExamplePerfSampleEvent(const SampleInfo& sample_info)
      : sample_info_(sample_info) {
  }
  size_t GetSize() const;
  void WriteTo(std::ostream* out) const override;
 private:
  const SampleInfo sample_info_;
};

class ExamplePerfSampleEvent_BranchStack : public ExamplePerfSampleEvent {
 public:
  ExamplePerfSampleEvent_BranchStack();
  static const size_t kEventSize;
};

// Produces a struct sample_event matching ExamplePerfFileAttr_Tracepoint.
class ExamplePerfSampleEvent_Tracepoint : public StreamWriteable {
 public:
  ExamplePerfSampleEvent_Tracepoint() {}
  void WriteTo(std::ostream* out) const override;
  static const size_t kEventSize;
};

// Produces a struct perf_file_section suitable for use in the metadata index.
class MetadataIndexEntry : public StreamWriteable {
 public:
  MetadataIndexEntry(u64 offset, u64 size)
    : index_entry_{.offset = offset, .size = size} {}
  void WriteTo(std::ostream* out) const override {
    struct perf_file_section entry = {
      .offset = MaybeSwap64(index_entry_.offset),
      .size = MaybeSwap64(index_entry_.size),
    };
    out->write(reinterpret_cast<const char*>(&entry), sizeof(entry));
  }
 public:
  const perf_file_section index_entry_;
};

// Produces sample string metadata, and corresponding metadata index entry.
class ExampleStringMetadata : public StreamWriteable {
 public:
  // The input string gets zero-padded/truncated to |kStringAlignSize| bytes if
  // it is shorter/longer, respectively.
  explicit ExampleStringMetadata(const string& data, size_t offset)
      : data_(data),
        index_entry_(offset, sizeof(u32) + kStringAlignSize) {
    data_.resize(kStringAlignSize);
  }
  void WriteTo(std::ostream* out) const override;

  const MetadataIndexEntry& index_entry() { return index_entry_; }
  size_t size() const {
    return sizeof(u32) + data_.size();
  }

  StreamWriteable& WithCrossEndianness(bool value) override {
    // Set index_entry_'s endianness since it is owned by this class.
    index_entry_.WithCrossEndianness(value);
    return StreamWriteable::WithCrossEndianness(value);
  }

 private:
  string data_;
  MetadataIndexEntry index_entry_;

  static const int kStringAlignSize = 64;
};

// Produces sample string metadata event for piped mode.
class ExampleStringMetadataEvent : public StreamWriteable {
 public:
  // The input string gets aligned to |kStringAlignSize|.
  explicit ExampleStringMetadataEvent(u32 type, const string& data)
      : type_(type), data_(data) {
    data_.resize(kStringAlignSize);
  }
  void WriteTo(std::ostream* out) const override;

 private:
  u32 type_;
  string data_;

  static const int kStringAlignSize = 64;
};

// Produces sample tracing metadata, and corresponding metadata index entry.
class ExampleTracingMetadata {
 public:
  class Data : public StreamWriteable {
   public:
    static const string kTraceMetadata;

    explicit Data(ExampleTracingMetadata* parent) : parent_(parent) {}

    const string& value() const { return kTraceMetadata; }

    void WriteTo(std::ostream* out) const override;

   private:
    ExampleTracingMetadata* parent_;
  };

  explicit ExampleTracingMetadata(size_t offset)
      : data_(this), index_entry_(offset, data_.value().size()) {}

  const Data &data() { return data_; }
  const MetadataIndexEntry &index_entry() { return index_entry_; }

 private:
  friend class Data;
  Data data_;
  MetadataIndexEntry index_entry_;
};

}  // namespace testing
}  // namespace quipper

#endif  // CHROMIUMOS_WIDE_PROFILING_TEST_PERF_DATA_H_
