| // 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> |
| #include <zxtest/c/zxtest.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)); |
| } |
| |
| #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 |