blob: a32025bb08695cd1f79625710c6dc800ec7e0d29 [file] [log] [blame]
// 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