// Copyright (c) 2013 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.

#include "chromiumos-wide-profiling/test_utils.h"

#include <string.h>

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <sstream>

#include "base/logging.h"

#include "chromiumos-wide-profiling/compat/proto.h"
#include "chromiumos-wide-profiling/perf_protobuf_io.h"
#include "chromiumos-wide-profiling/run_command.h"
#include "chromiumos-wide-profiling/utils.h"

using quipper::PerfDataProto;
using quipper::SplitString;
using quipper::TextFormat;

namespace {

// Newline character.
const char kNewLineDelimiter = '\n';

// Extension of protobuf files in text format.
const char kProtobufTextExtension[] = ".pb_text";

// Extension of protobuf files in serialized format.
const char kProtobufDataExtension[] = ".pb_data";

// Extension of build ID lists.
const char kBuildIDListExtension[] = ".buildids";

enum PerfDataType {
  kPerfDataNormal,    // Perf data is in normal format.
  kPerfDataPiped,     // Perf data is in piped format.
};

// The piped commands above produce comma-separated lines with the following
// fields:
enum {
  PERF_REPORT_OVERHEAD,
  PERF_REPORT_SAMPLES,
  PERF_REPORT_COMMAND,
  PERF_REPORT_SHARED_OBJECT,
  NUM_PERF_REPORT_FIELDS,
};

// Split a char buffer into separate lines.
void SeparateLines(const std::vector<char>& bytes, std::vector<string>* lines) {
  if (!bytes.empty())
    SplitString(string(&bytes[0], bytes.size()), kNewLineDelimiter, lines);
}

bool ReadExistingProtobufText(const string& filename, string* output_string) {
  std::vector<char> output_buffer;
  if (!quipper::FileToBuffer(filename, &output_buffer)) {
    LOG(ERROR) << "Could not open file " << filename;
    return false;
  }
  output_string->assign(&output_buffer[0], output_buffer.size());
  return true;
}

// Given a perf data file, return its protobuf representation as a text string
// and/or a serialized data stream.
bool PerfDataToProtoRepresentation(const string& filename,
                                   string* output_text,
                                   string* output_data) {
  PerfDataProto perf_data_proto;
  if (!SerializeFromFile(filename, &perf_data_proto)) {
    return false;
  }
  // Reset the timestamp field since it causes reproducability issues when
  // testing.
  perf_data_proto.set_timestamp_sec(0);

  if (output_text &&
      !TextFormat::PrintToString(perf_data_proto, output_text)) {
    return false;
  }
  if (output_data && !perf_data_proto.SerializeToString(output_data))
    return false;

  return true;
}

}  // namespace

namespace quipper {

const char* kSupportedMetadata[] = {
  "hostname",
  "os release",
  "perf version",
  "arch",
  "nrcpus online",
  "nrcpus avail",
  "cpudesc",
  "cpuid",
  "total memory",
  "cmdline",
  "event",
  "sibling cores",        // CPU topology.
  "sibling threads",      // CPU topology.
  "node0 meminfo",        // NUMA topology.
  "node0 cpu list",       // NUMA topology.
  "node1 meminfo",        // NUMA topology.
  "node1 cpu list",       // NUMA topology.
  NULL,
};

#ifndef QUIPPER_EXTERNAL_TEST_PATHS
string GetTestInputFilePath(const string& filename) {
  return "testdata/" + filename;
}

string GetPerfPath() {
  return "/usr/bin/perf";
}
#endif  // !QUIPPER_EXTERNAL_TEST_PATHS

int64_t GetFileSize(const string& filename) {
  FILE* fp = fopen(filename.c_str(), "rb");
  if (!fp)
    return -1;
  int64_t file_size = GetFileSizeFromHandle(fp);
  fclose(fp);
  return file_size;
}

bool CompareFileContents(const string& filename1, const string& filename2) {
  std::vector<char> file1_contents;
  std::vector<char> file2_contents;
  if (!FileToBuffer(filename1, &file1_contents) ||
      !FileToBuffer(filename2, &file2_contents)) {
    return false;
  }

  return file1_contents == file2_contents;
}

bool GetPerfBuildIDMap(const string& filename,
                       std::map<string, string>* output) {
  // Try reading from a pre-generated report.  If it doesn't exist, call perf
  // buildid-list.
  std::vector<char> buildid_list;
  LOG(INFO) << filename + kBuildIDListExtension;
  if (!quipper::FileToBuffer(filename + kBuildIDListExtension, &buildid_list)) {
    buildid_list.clear();
    if (RunCommand({GetPerfPath(), "buildid-list", "--force", "-i", filename},
                   &buildid_list) != 0) {
      LOG(ERROR) << "Failed to run perf buildid-list";
      return false;
    }
  }
  std::vector<string> lines;
  SeparateLines(buildid_list, &lines);

  /* The output now looks like the following:
     cff4586f322eb113d59f54f6e0312767c6746524 [kernel.kallsyms]
     c099914666223ff6403882604c96803f180688f5 /lib64/libc-2.15.so
     7ac2d19f88118a4970adb48a84ed897b963e3fb7 /lib64/libpthread-2.15.so
  */
  output->clear();
  for (string line : lines) {
    TrimWhitespace(&line);
    size_t separator = line.find(' ');
    string build_id = line.substr(0, separator);
    string filename = line.substr(separator + 1);
    (*output)[filename] = build_id;
  }

  return true;
}

namespace {
// Running tests while this is true will blindly make tests pass! So, remember
// to look at the diffs and explain them before submitting.
// TODO(dhsharp): replace this with a command-line flag.
static const bool kWriteNewGoldenFiles = false;

// This flag enables comparisons of protobufs in serialized format as a faster
// alternative to comparing their human-readable text representations. Set this
// flag to false to compare text representations instead. It's also useful for
// diffing against the old golden files when writing new golden files.
const bool UseProtobufDataFormat = true;
}  // namespace

bool CheckPerfDataAgainstBaseline(const string& filename) {
  string extension =
      UseProtobufDataFormat ? kProtobufDataExtension : kProtobufTextExtension;
  string protobuf_representation;
  if (UseProtobufDataFormat) {
    if (!PerfDataToProtoRepresentation(filename, nullptr,
                                       &protobuf_representation)) {
      return false;
    }
  } else {
    if (!PerfDataToProtoRepresentation(filename, &protobuf_representation,
                                       nullptr)) {
      return false;
    }
  }

  string existing_input_file =
      GetTestInputFilePath(basename(filename.c_str())) + extension;
  string baseline;
  if (!ReadExistingProtobufText(existing_input_file , &baseline)) {
    return false;
  }
  bool matches_baseline = (baseline == protobuf_representation);
  if (kWriteNewGoldenFiles) {
    string existing_input_pb_text = existing_input_file + ".new";
    if (matches_baseline) {
      LOG(INFO) << "NOT writing identical golden file! "
                << existing_input_pb_text;
      return true;
    }
    LOG(INFO) << "Writing new golden file! " << existing_input_pb_text;
    BufferToFile(existing_input_pb_text, protobuf_representation);

    // TODO(sque): Also write the other kind of protobuf format, which is useful
    // for generating new golden files.

    return true;
  }
  return matches_baseline;
}

bool ComparePerfBuildIDLists(const string& file1, const string& file2) {
  std::map<string, string> output1;
  std::map<string, string> output2;

  // Generate a build id list for each file.
  CHECK(GetPerfBuildIDMap(file1, &output1));
  CHECK(GetPerfBuildIDMap(file2, &output2));

  // Compare the output strings.
  return output1 == output2;
}

PerfParserOptions GetTestOptions() {
  PerfParserOptions options;
  options.sample_mapping_percentage_threshold = 100.0f;
  return options;
}

}  // namespace quipper
