blob: db36932f22b9071684c08712d778ba136960b9d2 [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
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));
}
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();
}
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, 9, "<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));
}
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(); }
#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