// Copyright 2019 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 <memory.h>

#include <cinttypes>

#include <zxtest/base/assertion.h>
#include <zxtest/base/runner.h>
#include <zxtest/base/test-driver.h>
#include <zxtest/base/test.h>

#define ZXTEST_INCLUDE_INTERNAL_HEADERS
#include <zxtest/c/zxtest.h>
#undef ZXTEST_INCLUDE_INTERNAL_HEADERS

#include "zircon/assert.h"

#ifdef __Fuchsia__
#include <zxtest/base/death-statement.h>
#endif

#include <zxtest/cpp/scoped_trace.h>

namespace {

class CTestWrapper final : public zxtest::Test {
 public:
  CTestWrapper() = default;
  ~CTestWrapper() final {}

  void SetCFunction(zxtest_test_fn_t test_fn) {
    ZX_ASSERT_MSG(test_fn_ == nullptr, "Once set test_fn_ should never change.");
    test_fn_ = test_fn;
  }

 private:
  void TestBody() final { test_fn_(); }

  zxtest_test_fn_t test_fn_ = nullptr;
};

}  // namespace

int zxtest_run_all_tests(int argc, char** argv) { return zxtest::RunAllTests(argc, argv); }

zxtest_test_ref_t zxtest_runner_register_test(const char* testcase_name, const char* test_name,
                                              const char* file, int line_number,
                                              zxtest_test_fn_t test_fn) {
  zxtest::TestRef test_ref =
      zxtest::Runner::GetInstance()->RegisterTest<zxtest::Test, CTestWrapper>(
          testcase_name, test_name, file, line_number,
          [test_fn](zxtest::internal::TestDriver* driver) -> std::unique_ptr<zxtest::Test> {
            std::unique_ptr<CTestWrapper> test_wrapper = zxtest::Test::Create<CTestWrapper>(driver);
            test_wrapper->SetCFunction(test_fn);
            return test_wrapper;
          });

  return {.test_index = test_ref.test_index, .test_case_index = test_ref.test_case_index};
}

void zxtest_runner_notify_assertion(const char* desc, const char* expected,
                                    const char* expected_eval, const char* actual,
                                    const char* actual_eval, const char* file, int64_t line,
                                    bool is_fatal) {
  zxtest::Runner::GetInstance()->NotifyAssertion(zxtest::Assertion(
      desc, expected, expected_eval, actual, actual_eval, {.filename = file, .line_number = line},
      is_fatal, zxtest::Runner::GetInstance()->GetScopedTraces()));
}

bool zxtest_runner_current_test_has_fatal_failures(void) {
  return zxtest::Runner::GetInstance()->CurrentTestHasFatalFailures();
}

bool zxtest_runner_current_test_has_failures(void) {
  return zxtest::Runner::GetInstance()->CurrentTestHasFailures();
}

bool zxtest_runner_current_test_is_skipped(void) {
  return zxtest::Runner::GetInstance()->IsSkipped();
}

size_t _zxtest_print_int(int val, char* buffer, size_t buffer_size) {
  return snprintf(buffer, buffer_size, "%d", val);
}

size_t _zxtest_print_unsigned_int(unsigned int val, char* buffer, size_t buffer_size) {
  return snprintf(buffer, buffer_size, "%u", val);
}

size_t _zxtest_print_long_long(long long val, char* buffer, size_t buffer_size) {
  return snprintf(buffer, buffer_size, "%lld", val);
}

size_t _zxtest_print_unsigned_long_long(unsigned long long val, char* buffer, size_t buffer_size) {
  return snprintf(buffer, buffer_size, "%llu", val);
}

size_t _zxtest_print_double(double val, char* buffer, size_t buffer_size) {
  return snprintf(buffer, buffer_size, "%f", val);
}

size_t _zxtest_print_long_double(long double val, char* buffer, size_t buffer_size) {
  return snprintf(buffer, buffer_size, "%Lf", val);
}

size_t _zxtest_print_bool(bool val, char* buffer, size_t buffer_size) {
  return snprintf(buffer, buffer_size, "%s", (val) ? "true" : "false");
}

size_t _zxtest_print_str(const char* val, char* buffer, size_t buffer_size) {
  return snprintf(buffer, buffer_size, "%s", (val == nullptr) ? "<nullptr>" : val);
}

size_t _zxtest_print_ptr(const void* val, char* buffer, size_t buffer_size) {
  if (val == nullptr) {
    return snprintf(buffer, buffer_size, "<nullptr>");
  }
  return snprintf(buffer, buffer_size, "%p", val);
}

size_t _zxtest_print_hex(const void* val, size_t size, char* buffer, size_t buffer_size) {
  if (buffer_size == 0 || buffer_size < 2 * size + 1) {
    return 3 * size + 1;
  }

  if (val == nullptr) {
    snprintf(buffer, 10, "<nullptr>");
  }

  for (size_t curr = 0; curr < size; ++curr) {
    snprintf(buffer + 3 * curr, buffer_size - curr, "%02X%*s", *((uint8_t*)(val) + curr),
             (curr < size - 1) ? 1 : 0, " ");
  }
  return 0;
}

void zxtest_c_clean_buffer(char** buffer) { free(*buffer); }

void zxtest_runner_fail_current_test(bool is_fatal, const char* file, int line,
                                     const char* message) {
  zxtest::Runner::GetInstance()->NotifyAssertion(
      zxtest::Assertion(message, {.filename = file, .line_number = line}, is_fatal,
                        zxtest::Runner::GetInstance()->GetScopedTraces()));
}

void zxtest_runner_skip_current_test(const char* file, int line, const char* message) {
  zxtest::Message mesg(message, {.filename = file, .line_number = line});
  zxtest::Runner::GetInstance()->SkipCurrent(mesg);
}

bool zxtest_runner_is_running(void) { return zxtest::Runner::GetInstance()->IsRunning(); }

struct zxtest_scoped_trace_t {
 public:
  zxtest_scoped_trace_t(const char* message, const char* filename, uint64_t line)
      : trace_({.filename = filename, .line_number = static_cast<int64_t>(line)}, message) {}

 private:
  zxtest::ScopedTrace trace_;
};

zxtest_scoped_trace_t* zxtest_runner_push_trace(const char* message, const char* filename,
                                                uint64_t line) {
  zxtest_scoped_trace_t* trace = new zxtest_scoped_trace_t(message, filename, line);
  return trace;
}

void zxtest_runner_pop_trace(struct zxtest_scoped_trace_t** ptr) { delete *ptr; }

#ifdef __Fuchsia__
bool zxtest_death_statement_execute(zxtest_test_fn_t statement, enum DeathResult result,
                                    const char* file, int line, const char* message) {
  zxtest::internal::DeathStatement death_statement([statement]() { statement(); });
  death_statement.Execute();
  bool success = false;

  switch (result) {
    case DeathResult::kDeathResultComplete:
      success = (death_statement.state() == zxtest::internal::DeathStatement::State::kSuccess);
      break;
    case DeathResult::kDeathResultRaiseException:
      success = (death_statement.state() == zxtest::internal::DeathStatement::State::kException);
      break;
    default:
      break;
  }

  if (success) {
    return true;
  }

  if (death_statement.state() == zxtest::internal::DeathStatement::State::kBadState) {
    zxtest::Runner::GetInstance()->NotifyFatalError();
  }

  // For now all death death_statements assertions are fatal.
  std::string error_message;
  if (!death_statement.error_message().empty()) {
    zxtest_runner_fail_current_test(true, file, line, death_statement.error_message().data());
  } else {
    zxtest_runner_fail_current_test(true, file, line, message);
  }
  return false;
}
#endif
