/* Copyright (c) 2015, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include "file_test.h"

#include <algorithm>
#include <utility>

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/err.h>

#include "../internal.h"


FileTest::FileTest(std::unique_ptr<FileTest::LineReader> reader,
                   std::function<void(const std::string &)> comment_callback,
                   bool is_kas_test)
    : reader_(std::move(reader)),
      is_kas_test_(is_kas_test),
      comment_callback_(std::move(comment_callback)) {}

FileTest::~FileTest() {}

// FindDelimiter returns a pointer to the first '=' or ':' in |str| or nullptr
// if there is none.
static const char *FindDelimiter(const char *str) {
  while (*str) {
    if (*str == ':' || *str == '=') {
      return str;
    }
    str++;
  }
  return nullptr;
}

// StripSpace returns a string containing up to |len| characters from |str| with
// leading and trailing whitespace removed.
static std::string StripSpace(const char *str, size_t len) {
  // Remove leading space.
  while (len > 0 && isspace(*str)) {
    str++;
    len--;
  }
  while (len > 0 && isspace(str[len - 1])) {
    len--;
  }
  return std::string(str, len);
}

static std::pair<std::string, std::string> ParseKeyValue(const char *str, const size_t len) {
  const char *delimiter = FindDelimiter(str);
  std::string key, value;
  if (delimiter == nullptr) {
    key = StripSpace(str, len);
  } else {
    key = StripSpace(str, delimiter - str);
    value = StripSpace(delimiter + 1, str + len - delimiter - 1);
  }
  return {key, value};
}

FileTest::ReadResult FileTest::ReadNext() {
  // If the previous test had unused attributes or instructions, it is an error.
  if (!unused_attributes_.empty()) {
    for (const std::string &key : unused_attributes_) {
      PrintLine("Unused attribute: %s", key.c_str());
    }
    return kReadError;
  }
  if (!unused_instructions_.empty()) {
    for (const std::string &key : unused_instructions_) {
      PrintLine("Unused instruction: %s", key.c_str());
    }
    return kReadError;
  }

  ClearTest();

  static const size_t kBufLen = 8192 * 4;
  std::unique_ptr<char[]> buf(new char[kBufLen]);

  bool in_instruction_block = false;
  is_at_new_instruction_block_ = false;

  while (true) {
    // Read the next line.
    switch (reader_->ReadLine(buf.get(), kBufLen)) {
      case kReadError:
        fprintf(stderr, "Error reading from input at line %u.\n", line_ + 1);
        return kReadError;
      case kReadEOF:
        // EOF is a valid terminator for a test.
        return start_line_ > 0 ? kReadSuccess : kReadEOF;
      case kReadSuccess:
        break;
    }

    line_++;
    size_t len = strlen(buf.get());
    if (buf[0] == '\n' || buf[0] == '\r' || buf[0] == '\0') {
      // Empty lines delimit tests.
      if (start_line_ > 0) {
        return kReadSuccess;
      }
      if (in_instruction_block) {
        in_instruction_block = false;
        // Delimit instruction block from test with a blank line.
        current_test_ += "\r\n";
      } else if (is_kas_test_) {
        // KAS tests have random blank lines scattered around.
        current_test_ += "\r\n";
      }
    } else if (buf[0] == '#') {
      if (is_kas_test_ && seen_non_comment_) {
        // KAS tests have comments after the initial comment block which need
        // to be included in the corresponding place in the output.
        current_test_ += std::string(buf.get());
      } else if (comment_callback_) {
        comment_callback_(buf.get());
      }
      // Otherwise ignore comments.
    } else if (strcmp("[B.4.2 Key Pair Generation by Testing Candidates]\r\n",
                      buf.get()) == 0) {
      // The above instruction-like line is ignored because the FIPS lab's
      // request files are hopelessly inconsistent.
    } else if (buf[0] == '[') {  // Inside an instruction block.
      is_at_new_instruction_block_ = true;
      seen_non_comment_ = true;
      if (start_line_ != 0) {
        // Instructions should be separate blocks.
        fprintf(stderr, "Line %u is an instruction in a test case.\n", line_);
        return kReadError;
      }
      if (!in_instruction_block) {
        ClearInstructions();
        in_instruction_block = true;
      }

      // Parse the line as an instruction ("[key = value]" or "[key]").

      // KAS tests contain invalid syntax.
      std::string kv = buf.get();
      const bool is_broken_kas_instruction =
          is_kas_test_ &&
          (kv == "[SHA(s) supported (Used for hashing Z): SHA512 \r\n");

      if (!is_broken_kas_instruction) {
        kv = StripSpace(buf.get(), len);
        if (kv[kv.size() - 1] != ']') {
          fprintf(stderr, "Line %u, invalid instruction: '%s'\n", line_,
                  kv.c_str());
          return kReadError;
        }
      } else {
        // Just remove the newline for the broken instruction.
        kv = kv.substr(0, kv.size() - 2);
      }

      current_test_ += kv + "\r\n";
      kv = std::string(kv.begin() + 1, kv.end() - 1);

      for (;;) {
        size_t idx = kv.find(",");
        if (idx == std::string::npos) {
          idx = kv.size();
        }
        std::string key, value;
        std::tie(key, value) = ParseKeyValue(kv.c_str(), idx);
        instructions_[key] = value;
        if (idx == kv.size())
          break;
        kv = kv.substr(idx + 1);
      }
    } else {
      // Parsing a test case.
      if (in_instruction_block) {
        // Some NIST CAVP test files (TDES) have a test case immediately
        // following an instruction block, without a separate blank line, some
        // of the time.
        in_instruction_block = false;
      }

      current_test_ += std::string(buf.get(), len);
      std::string key, value;
      std::tie(key, value) = ParseKeyValue(buf.get(), len);

      // Duplicate keys are rewritten to have “/2”, “/3”, … suffixes.
      std::string mapped_key = key;
      for (unsigned i = 2; attributes_.count(mapped_key) != 0; i++) {
        char suffix[32];
        snprintf(suffix, sizeof(suffix), "/%u", i);
        suffix[sizeof(suffix)-1] = 0;
        mapped_key = key + suffix;
      }

      unused_attributes_.insert(mapped_key);
      attributes_[mapped_key] = value;
      if (start_line_ == 0) {
        // This is the start of a test.
        type_ = mapped_key;
        parameter_ = value;
        start_line_ = line_;
        for (const auto &kv : instructions_) {
          unused_instructions_.insert(kv.first);
        }
      }
    }
  }
}

void FileTest::PrintLine(const char *format, ...) {
  va_list args;
  va_start(args, format);

  fprintf(stderr, "Line %u: ", start_line_);
  vfprintf(stderr, format, args);
  fprintf(stderr, "\n");

  va_end(args);
}

const std::string &FileTest::GetType() {
  OnKeyUsed(type_);
  return type_;
}

const std::string &FileTest::GetParameter() {
  OnKeyUsed(type_);
  return parameter_;
}

bool FileTest::HasAttribute(const std::string &key) {
  OnKeyUsed(key);
  return attributes_.count(key) > 0;
}

bool FileTest::GetAttribute(std::string *out_value, const std::string &key) {
  OnKeyUsed(key);
  auto iter = attributes_.find(key);
  if (iter == attributes_.end()) {
    PrintLine("Missing attribute '%s'.", key.c_str());
    return false;
  }
  *out_value = iter->second;
  return true;
}

const std::string &FileTest::GetAttributeOrDie(const std::string &key) {
  if (!HasAttribute(key)) {
    abort();
  }
  return attributes_[key];
}

bool FileTest::HasInstruction(const std::string &key) {
  OnInstructionUsed(key);
  return instructions_.count(key) > 0;
}

bool FileTest::GetInstruction(std::string *out_value, const std::string &key) {
  OnInstructionUsed(key);
  auto iter = instructions_.find(key);
  if (iter == instructions_.end()) {
    PrintLine("Missing instruction '%s'.", key.c_str());
    return false;
  }
  *out_value = iter->second;
  return true;
}

const std::string &FileTest::GetInstructionOrDie(const std::string &key) {
  if (!HasInstruction(key)) {
    abort();
  }
  return instructions_[key];
}

bool FileTest::GetInstructionBytes(std::vector<uint8_t> *out,
                                   const std::string &key) {
  std::string value;
  return GetInstruction(&value, key) && ConvertToBytes(out, value);
}

const std::string &FileTest::CurrentTestToString() const {
  return current_test_;
}

bool FileTest::GetBytes(std::vector<uint8_t> *out, const std::string &key) {
  std::string value;
  return GetAttribute(&value, key) && ConvertToBytes(out, value);
}

static std::string EncodeHex(const uint8_t *in, size_t in_len) {
  static const char kHexDigits[] = "0123456789abcdef";
  std::string ret;
  ret.reserve(in_len * 2);
  for (size_t i = 0; i < in_len; i++) {
    ret += kHexDigits[in[i] >> 4];
    ret += kHexDigits[in[i] & 0xf];
  }
  return ret;
}

bool FileTest::ExpectBytesEqual(const uint8_t *expected, size_t expected_len,
                                const uint8_t *actual, size_t actual_len) {
  if (expected_len == actual_len &&
      OPENSSL_memcmp(expected, actual, expected_len) == 0) {
    return true;
  }

  std::string expected_hex = EncodeHex(expected, expected_len);
  std::string actual_hex = EncodeHex(actual, actual_len);
  PrintLine("Expected: %s", expected_hex.c_str());
  PrintLine("Actual:   %s", actual_hex.c_str());
  return false;
}

void FileTest::ClearTest() {
  start_line_ = 0;
  type_.clear();
  parameter_.clear();
  attributes_.clear();
  unused_attributes_.clear();
  unused_instructions_.clear();
  current_test_ = "";
}

void FileTest::ClearInstructions() {
  instructions_.clear();
  unused_attributes_.clear();
}

void FileTest::OnKeyUsed(const std::string &key) {
  unused_attributes_.erase(key);
}

void FileTest::OnInstructionUsed(const std::string &key) {
  unused_instructions_.erase(key);
}

static bool FromHexDigit(uint8_t *out, char c) {
  if ('0' <= c && c <= '9') {
    *out = c - '0';
    return true;
  }
  if ('a' <= c && c <= 'f') {
    *out = c - 'a' + 10;
    return true;
  }
  if ('A' <= c && c <= 'F') {
    *out = c - 'A' + 10;
    return true;
  }
  return false;
}

bool FileTest::ConvertToBytes(std::vector<uint8_t> *out,
                              const std::string &value) {
  if (value.size() >= 2 && value[0] == '"' && value[value.size() - 1] == '"') {
    out->assign(value.begin() + 1, value.end() - 1);
    return true;
  }

  if (value.size() % 2 != 0) {
    PrintLine("Error decoding value: %s", value.c_str());
    return false;
  }
  out->clear();
  out->reserve(value.size() / 2);
  for (size_t i = 0; i < value.size(); i += 2) {
    uint8_t hi, lo;
    if (!FromHexDigit(&hi, value[i]) || !FromHexDigit(&lo, value[i + 1])) {
      PrintLine("Error decoding value: %s", value.c_str());
      return false;
    }
    out->push_back((hi << 4) | lo);
  }
  return true;
}

bool FileTest::IsAtNewInstructionBlock() const {
  return is_at_new_instruction_block_;
}

void FileTest::InjectInstruction(const std::string &key,
                                 const std::string &value) {
  instructions_[key] = value;
}

class FileLineReader : public FileTest::LineReader {
 public:
  explicit FileLineReader(const char *path) : file_(fopen(path, "r")) {}
  ~FileLineReader() override {
    if (file_ != nullptr) {
      fclose(file_);
    }
  }

  // is_open returns true if the file was successfully opened.
  bool is_open() const { return file_ != nullptr; }

  FileTest::ReadResult ReadLine(char *out, size_t len) override {
    assert(len > 0);
    if (file_ == nullptr) {
      return FileTest::kReadError;
    }

    if (fgets(out, len, file_) == nullptr) {
      return feof(file_) ? FileTest::kReadEOF : FileTest::kReadError;
    }

    if (strlen(out) == len - 1 && out[len - 2] != '\n' && !feof(file_)) {
      fprintf(stderr, "Line too long.\n");
      return FileTest::kReadError;
    }

    return FileTest::kReadSuccess;
  }

 private:
  FILE *file_;

  FileLineReader(const FileLineReader &) = delete;
  FileLineReader &operator=(const FileLineReader &) = delete;
};

int FileTestMain(FileTestFunc run_test, void *arg, const char *path) {
  FileTest::Options opts;
  opts.callback = run_test;
  opts.arg = arg;
  opts.path = path;

  return FileTestMain(opts);
}

int FileTestMain(const FileTest::Options &opts) {
  std::unique_ptr<FileLineReader> reader(
      new FileLineReader(opts.path));
  if (!reader->is_open()) {
    fprintf(stderr, "Could not open file %s: %s.\n", opts.path,
            strerror(errno));
    return 1;
  }

  FileTest t(std::move(reader), opts.comment_callback, opts.is_kas_test);

  bool failed = false;
  while (true) {
    FileTest::ReadResult ret = t.ReadNext();
    if (ret == FileTest::kReadError) {
      return 1;
    } else if (ret == FileTest::kReadEOF) {
      break;
    }

    bool result = opts.callback(&t, opts.arg);
    if (t.HasAttribute("Error")) {
      if (result) {
        t.PrintLine("Operation unexpectedly succeeded.");
        failed = true;
        continue;
      }
      uint32_t err = ERR_peek_error();
      if (ERR_reason_error_string(err) != t.GetAttributeOrDie("Error")) {
        t.PrintLine("Unexpected error; wanted '%s', got '%s'.",
                    t.GetAttributeOrDie("Error").c_str(),
                    ERR_reason_error_string(err));
        failed = true;
        ERR_clear_error();
        continue;
      }
      ERR_clear_error();
    } else if (!result) {
      // In case the test itself doesn't print output, print something so the
      // line number is reported.
      t.PrintLine("Test failed");
      ERR_print_errors_fp(stderr);
      failed = true;
      continue;
    }
  }

  if (!opts.silent && !failed) {
    printf("PASS\n");
  }

  return failed ? 1 : 0;
}

void FileTest::SkipCurrent() {
  ClearTest();
}
