blob: d9c79559943737aa01c323912213e38caed39847 [file] [edit]
// 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.
#ifndef ZXTEST_CPP_ZXTEST_H_
#define ZXTEST_CPP_ZXTEST_H_
#include <cstdlib>
#include <type_traits>
#include <fbl/string.h>
#include <fbl/string_printf.h>
#include <zxtest/base/assertion.h>
#include <zxtest/base/runner.h>
#include <zxtest/base/test.h>
#include <zxtest/cpp/internal.h>
#ifdef __Fuchsia__
#include <zircon/status.h>
#include <zxtest/base/death-statement.h>
#endif
// Macro definitions for usage within CPP.
#define RUN_ALL_TESTS(argc, argv) zxtest::RunAllTests(argc, argv)
#define _ZXTEST_TEST_REF(TestCase, Test) TestCase##_##Test##_Ref
#define _ZXTEST_DEFAULT_FIXTURE ::zxtest::Test
#define _ZXTEST_TEST_CLASS(TestCase, Test) TestCase##_##Test##_Class
#define _ZXTEST_TEST_CLASS_DECL(Fixture, TestClass) \
class TestClass final : public Fixture { \
public: \
TestClass() = default; \
~TestClass() final = default; \
\
private: \
void TestBody() final; \
}
#define _ZXTEST_BEGIN_TEST_BODY(TestClass) void TestClass::TestBody()
#define _ZXTEST_REGISTER(TestCase, Test, Fixture) \
_ZXTEST_TEST_CLASS_DECL(Fixture, _ZXTEST_TEST_CLASS(TestCase, Test)); \
[[maybe_unused]] static zxtest::TestRef _ZXTEST_TEST_REF(TestCase, Test) = \
zxtest::Runner::GetInstance()->RegisterTest<Fixture, _ZXTEST_TEST_CLASS(TestCase, Test)>( \
#TestCase, #Test, __FILE__, __LINE__); \
_ZXTEST_BEGIN_TEST_BODY(_ZXTEST_TEST_CLASS(TestCase, Test))
#define TEST(TestCase, Test) _ZXTEST_REGISTER(TestCase, Test, _ZXTEST_DEFAULT_FIXTURE)
#define TEST_F(TestCase, Test) _ZXTEST_REGISTER(TestCase, Test, TestCase)
#define _ZXTEST_NULLPTR nullptr
#define _ZXTEST_ABORT_IF_ERROR zxtest::Runner::GetInstance()->CurrentTestHasFatalFailures()
#define _ZXTEST_STRCMP(actual, expected) zxtest::StrCmp(actual, expected)
#define _ZXTEST_AUTO_VAR_TYPE(var) decltype(var)
#define _ZXTEST_TEST_HAS_ERRORS zxtest::Runner::GetInstance()->CurrentTestHasFailures()
// Pre-processor magic to allow EXPECT_ macros not enforce a return type on helper functions.
#define _RETURN_IF_FATAL_true \
do { \
unittest_fails(); \
if (_ZXTEST_ABORT_IF_ERROR) { \
return; \
} \
} while (0)
#define _RETURN_IF_FATAL_false \
do { \
unittest_fails(); \
} while (0)
#define _RETURN_IF_FATAL(fatal) _RETURN_IF_FATAL_##fatal
// Definition of operations used to evaluate assertion conditions.
#define _EQ(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a == b; })
#define _NE(actual, expected) !_EQ(actual, expected)
#define _BOOL(actual, expected) (static_cast<bool>(actual) == static_cast<bool>(expected))
#define _LT(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a < b; })
#define _LE(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a <= b; })
#define _GT(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a > b; })
#define _GE(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a >= b; })
#define _STREQ(actual, expected) zxtest::StrCmp(actual, expected)
#define _STRNE(actual, expected) !_STREQ(actual, expected)
#define _SUBSTR(str, substr) zxtest::StrContain(str, substr)
#define _BYTEEQ(actual, expected, size) \
(memcmp(static_cast<const void*>(actual), static_cast<const void*>(expected), size) == 0)
#define _BYTENE(actual, expected, size) !(_BYTEEQ(actual, expected, size))
// Functions used as arguments for EvaluateCondition.
#define _DESC_PROVIDER(desc, ...) \
[&]() -> fbl::String { \
fbl::String out_desc; \
auto format_msg = fbl::StringPrintf(" " __VA_ARGS__); \
out_desc = fbl::String::Concat({fbl::String(desc), format_msg}); \
return out_desc; \
}
#define _COMPARE_FN(op) \
[](const auto& expected_, const auto& actual_) { return op(expected_, actual_); }
#define _COMPARE_3_FN(op, third_param) \
[third_param](const auto& expected_, const auto& actual_) { \
return op(expected_, actual_, third_param); \
}
// Printers for converting values into readable strings.
#define _DEFAULT_PRINTER [](const auto& val) { return zxtest::PrintValue(val); }
#ifdef __Fuchsia__
#define _STATUS_PRINTER [](zx_status_t status) { return zxtest::PrintStatus(status); }
#else
#define _STATUS_PRINTER _DEFAULT_PRINTER
#endif
#define _HEXDUMP_PRINTER(size) \
[size](const auto& val) { \
return zxtest::internal::ToHex(static_cast<const void*>(val), byte_count); \
}
// Basic assert macro implementation.
#define _ASSERT_VAR(op, expected, actual, fatal, file, line, desc, ...) \
do { \
if (!zxtest::internal::EvaluateCondition(actual, expected, #actual, #expected, \
{.filename = file, .line_number = line}, fatal, \
_DESC_PROVIDER(desc, __VA_ARGS__), _COMPARE_FN(op), \
_DEFAULT_PRINTER, _DEFAULT_PRINTER)) { \
_RETURN_IF_FATAL(fatal); \
} \
} while (0)
#define _ASSERT_VAR_STATUS(op, expected, actual, fatal, file, line, desc, ...) \
do { \
if (!zxtest::internal::EvaluateStatusCondition( \
actual, expected, #actual, #expected, {.filename = file, .line_number = line}, fatal, \
_DESC_PROVIDER(desc, __VA_ARGS__), _COMPARE_FN(op), _STATUS_PRINTER, \
_STATUS_PRINTER)) { \
_RETURN_IF_FATAL(fatal); \
} \
} while (0)
#define _ASSERT_VAR_COERCE(op, expected, actual, coerce_type, fatal, file, line, desc, ...) \
do { \
auto buffer_compare = [&](const auto& expected_, const auto& actual_) { \
using DecayType = typename std::decay<coerce_type>::type; \
return op(static_cast<const DecayType&>(actual_), static_cast<const DecayType&>(expected_)); \
}; \
if (!zxtest::internal::EvaluateCondition(actual, expected, #actual, #expected, \
{.filename = file, .line_number = line}, fatal, \
_DESC_PROVIDER(desc, __VA_ARGS__), buffer_compare, \
_DEFAULT_PRINTER, _DEFAULT_PRINTER)) { \
_RETURN_IF_FATAL(fatal); \
} \
} while (0)
#define _ASSERT_VAR_BYTES(op, expected, actual, size, fatal, file, line, desc, ...) \
do { \
size_t byte_count = size; \
if (!zxtest::internal::EvaluateCondition( \
zxtest::internal::ToPointer(actual), zxtest::internal::ToPointer(expected), #actual, \
#expected, {.filename = file, .line_number = line}, fatal, \
_DESC_PROVIDER(desc, __VA_ARGS__), _COMPARE_3_FN(op, byte_count), \
_HEXDUMP_PRINTER(byte_count), _HEXDUMP_PRINTER(byte_count))) { \
_RETURN_IF_FATAL(fatal); \
} \
} while (0)
#define _ZXTEST_FAIL_NO_RETURN(fatal, desc, ...) \
do { \
zxtest::Runner::GetInstance()->NotifyAssertion( \
zxtest::Assertion(_DESC_PROVIDER(desc, __VA_ARGS__)(), \
{.filename = __FILE__, .line_number = __LINE__}, fatal)); \
} while (0)
#define _ZXTEST_ASSERT_ERROR(has_errors, fatal, desc, ...) \
do { \
if (has_errors) { \
_ZXTEST_FAIL_NO_RETURN(fatal, desc, ##__VA_ARGS__); \
_RETURN_IF_FATAL(fatal); \
} \
} while (0)
#ifdef __Fuchsia__
#define _ZXTEST_DEATH_STATUS_COMPLETE zxtest::internal::DeathStatement::State::kSuccess
#define _ZXTEST_DEATH_STATUS_EXCEPTION zxtest::internal::DeathStatement::State::kException
#define _ZXTEST_DEATH_STATEMENT(statement, expected_result, desc, ...) \
do { \
zxtest::internal::DeathStatement death_statement(statement); \
death_statement.Execute(); \
if (death_statement.state() != expected_result) { \
if (death_statement.state() == zxtest::internal::DeathStatement::State::kBadState) { \
zxtest::Runner::GetInstance()->NotifyFatalError(); \
} \
if (!death_statement.error_message().empty()) { \
_ZXTEST_ASSERT_ERROR(true, true, death_statement.error_message().data()); \
} else { \
_ZXTEST_ASSERT_ERROR(true, true, desc, ##__VA_ARGS__); \
} \
} \
} while (0)
#endif
#endif // ZXTEST_CPP_ZXTEST_H_