blob: de0a56cfc1c23372ebbaada0e17023e4d004ad72 [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.
#ifndef ZXTEST_CPP_ZXTEST_H_
#define ZXTEST_CPP_ZXTEST_H_
#ifndef ZXTEST_INCLUDE_INTERNAL_HEADERS
#error This header is not intended for direct inclusion. Include zxtest/zxtest.h instead.
#endif
#include <cstdlib>
#include <type_traits>
#include <fbl/string.h>
#include <fbl/string_printf.h>
#include <zxtest/base/assertion.h>
#include <zxtest/base/parameterized-value-impl.h>
#include <zxtest/base/runner.h>
#include <zxtest/base/test.h>
#include <zxtest/base/values.h>
#ifdef __Fuchsia__
#include <zircon/status.h>
#include <zxtest/base/death-statement.h>
#endif
#include "scoped_trace.h"
// Pre-processor magic to allow EXPECT_ macros not enforce a return type on helper functions.
#define LIB_ZXTEST_RETURN_IF_FATAL_true \
do { \
unittest_fails(); \
if (LIB_ZXTEST_ABORT_IF_ERROR) { \
return; \
} \
} while (0)
#define LIB_ZXTEST_RETURN_IF_FATAL_false \
do { \
unittest_fails(); \
} while (0)
#define LIB_ZXTEST_RETURN_IF_FATAL(fatal) LIB_ZXTEST_RETURN_IF_FATAL_##fatal
#ifdef ZXTEST_USE_STREAMABLE_MACROS
#include <zxtest/cpp/assert_streams.h>
#else
#include <zxtest/cpp/assert.h>
#endif
// Macro definitions for usage within CPP.
#define LIB_ZXTEST_EXPAND_(arg) arg
#define LIB_ZXTEST_GET_FIRST_(first, ...) first
#define LIB_ZXTEST_GET_SECOND_(first, second, ...) second
#define RUN_ALL_TESTS(argc, argv) zxtest::RunAllTests(argc, argv)
#define LIB_ZXTEST_TEST_REF_N(TestCase, Test, Tag) TestCase##_##Test##_##Tag##_Ref
#define LIB_ZXTEST_TEST_REF(TestCase, Test) LIB_ZXTEST_TEST_REF_N(TestCase, Test, 0)
#define LIB_ZXTEST_CONCAT_TOKEN(foo, bar) LIB_ZXTEST_CONCAT_TOKEN_IMPL(foo, bar)
#define LIB_ZXTEST_CONCAT_TOKEN_IMPL(foo, bar) foo##bar
#define LIB_ZXTEST_DEFAULT_FIXTURE ::zxtest::Test
#define LIB_ZXTEST_PARAM_FIXTURE ::zxtest::TestWithParam
#define LIB_ZXTEST_TEST_CLASS(TestCase, Test) TestCase##_##Test##_Class
#define LIB_ZXTEST_TEST_CLASS_DECL(Fixture, TestClass) \
class TestClass final : public Fixture { \
public: \
TestClass() = default; \
~TestClass() final = default; \
\
private: \
void TestBody() final; \
}
#define LIB_ZXTEST_BEGIN_TEST_BODY(TestClass) void TestClass::TestBody()
#define LIB_ZXTEST_REGISTER_FN(TestCase, Test) TestCase##_##Test##_register_fn
// Group our constructor functions to enforce a specific call order. In particular, we want to be
// sure that parametrized tests are registered before being instanced.
#define LIB_ZXTEST_CTOR_GROUP_REGISTER __attribute__((constructor(101)))
#define LIB_ZXTEST_CTOR_GROUP_INSTANTIATE __attribute__((constructor(102)))
// Note: We intentionally wrap the assignment in a constructor function, to workaround the issue
// where in certain builds (both debug and production), the compiler would generated a global
// initiatialization function for the runtime, which would push a huge amount of memory into the
// stack. For 2048 tests, it pushed ~270 KB, which caused an overflow.
#define LIB_ZXTEST_REGISTER(TestCase, Test, Fixture) \
LIB_ZXTEST_TEST_CLASS_DECL(Fixture, LIB_ZXTEST_TEST_CLASS(TestCase, Test)); \
static zxtest::TestRef LIB_ZXTEST_TEST_REF(TestCase, Test) = {}; \
static void LIB_ZXTEST_REGISTER_FN(TestCase, Test)(void) LIB_ZXTEST_CTOR_GROUP_REGISTER; \
void LIB_ZXTEST_REGISTER_FN(TestCase, Test)(void) { \
LIB_ZXTEST_TEST_REF(TestCase, Test) = \
zxtest::Runner::GetInstance() \
->RegisterTest<Fixture, LIB_ZXTEST_TEST_CLASS(TestCase, Test)>(#TestCase, #Test, \
__FILE__, __LINE__); \
} \
LIB_ZXTEST_BEGIN_TEST_BODY(LIB_ZXTEST_TEST_CLASS(TestCase, Test))
#define LIB_ZXTEST_REGISTER_PARAMETERIZED(TestSuite, Test) \
LIB_ZXTEST_TEST_CLASS_DECL(TestSuite, LIB_ZXTEST_TEST_CLASS(TestSuite, Test)); \
static void LIB_ZXTEST_REGISTER_FN(TestSuite, Test)(void) LIB_ZXTEST_CTOR_GROUP_REGISTER; \
void LIB_ZXTEST_REGISTER_FN(TestSuite, Test)(void) { \
zxtest::Runner::GetInstance()->AddParameterizedTest<TestSuite>( \
std::make_unique<zxtest::internal::AddTestDelegateImpl< \
TestSuite, TestSuite::ParamType, LIB_ZXTEST_TEST_CLASS(TestSuite, Test)>>(), \
#TestSuite, #Test, {.filename = __FILE__, .line_number = __LINE__}); \
} \
LIB_ZXTEST_BEGIN_TEST_BODY(LIB_ZXTEST_TEST_CLASS(TestSuite, Test))
#define TEST(TestCase, Test) LIB_ZXTEST_REGISTER(TestCase, Test, LIB_ZXTEST_DEFAULT_FIXTURE)
#define TEST_F(TestCase, Test) LIB_ZXTEST_REGISTER(TestCase, Test, TestCase)
#define TEST_P(TestSuite, Test) LIB_ZXTEST_REGISTER_PARAMETERIZED(TestSuite, Test)
#define LIB_ZXTEST_NULLPTR nullptr
#define LIB_ZXTEST_ABORT_IF_ERROR zxtest::Runner::GetInstance()->CurrentTestHasFatalFailures()
#define LIB_ZXTEST_STRCMP(actual, expected) zxtest::StrCmp(actual, expected)
#define LIB_ZXTEST_AUTO_VAR_TYPE(var) decltype(var)
#define LIB_ZXTEST_TEST_HAS_ERRORS zxtest::Runner::GetInstance()->CurrentTestHasFailures()
#define LIB_ZXTEST_IS_SKIPPED zxtest::Runner::GetInstance()->IsSkipped()
#define LIB_ZXTEST_ADD_INSTANTIATION_DEFAULT_NAME(arg1) \
[](const auto info) -> std::string { return std::to_string(info.index); }
#define LIB_ZXTEST_ADD_INSTANTIATION_CUSTOM_NAME(arg1, generator) generator
#define LIB_ZXTEST_GET_3RD_ARG(arg1, arg2, arg3, ...) arg3
#define LIB_ZXTEST_NAME_GENERATOR_CHOOSER(...) \
LIB_ZXTEST_GET_3RD_ARG(__VA_ARGS__, LIB_ZXTEST_ADD_INSTANTIATION_CUSTOM_NAME, \
LIB_ZXTEST_ADD_INSTANTIATION_DEFAULT_NAME)
#define LIB_ZXTEST_INSTANTIATION_NAME_FN(...) \
LIB_ZXTEST_NAME_GENERATOR_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
#define INSTANTIATE_TEST_SUITE_P(Prefix, TestSuite, ...) \
static void LIB_ZXTEST_REGISTER_FN(Prefix, TestSuite)(void) LIB_ZXTEST_CTOR_GROUP_INSTANTIATE; \
void LIB_ZXTEST_REGISTER_FN(Prefix, TestSuite)(void) { \
static zxtest::internal::ValueProvider<TestSuite::ParamType> provider( \
LIB_ZXTEST_EXPAND_(LIB_ZXTEST_GET_FIRST_(__VA_ARGS__))); \
zxtest::Runner::GetInstance()->AddInstantiation<TestSuite, TestSuite::ParamType>( \
std::make_unique< \
zxtest::internal::AddInstantiationDelegateImpl<TestSuite, TestSuite::ParamType>>(), \
#Prefix, {.filename = __FILE__, .line_number = __LINE__}, provider, \
LIB_ZXTEST_INSTANTIATION_NAME_FN(__VA_ARGS__)); \
} \
static int LIB_ZXTEST_TEST_REF(Prefix, TestSuite) __attribute__((unused)) = 0
// Definition of operations used to evaluate assertion conditions.
#define LIB_ZXTEST_EQ(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a == b; })
#define LIB_ZXTEST_NE(actual, expected) !LIB_ZXTEST_EQ(actual, expected)
#define LIB_ZXTEST_BOOL(actual, expected) (static_cast<bool>(actual) == static_cast<bool>(expected))
#define LIB_ZXTEST_LT(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a < b; })
#define LIB_ZXTEST_LE(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a <= b; })
#define LIB_ZXTEST_GT(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a > b; })
#define LIB_ZXTEST_GE(actual, expected) \
zxtest::internal::Compare(actual, expected, [](const auto& a, const auto& b) { return a >= b; })
#define LIB_ZXTEST_STREQ(actual, expected) zxtest::StrCmp(actual, expected)
#define LIB_ZXTEST_STRNE(actual, expected) !LIB_ZXTEST_STREQ(actual, expected)
#define LIB_ZXTEST_SUBSTR(str, substr) zxtest::StrContain(str, substr)
#define LIB_ZXTEST_BYTEEQ(actual, expected, size) \
(memcmp(static_cast<const void*>(actual), static_cast<const void*>(expected), size) == 0)
#define LIB_ZXTEST_BYTENE(actual, expected, size) !(LIB_ZXTEST_BYTEEQ(actual, expected, size))
// Functions used as arguments for EvaluateCondition.
#define LIB_ZXTEST_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 LIB_ZXTEST_COMPARE_FN(op) \
[](const auto& expected_, const auto& actual_) { return op(expected_, actual_); }
#define LIB_ZXTEST_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 LIB_ZXTEST_DEFAULT_PRINTER [](const auto& val) { return zxtest::PrintValue(val); }
#ifdef __Fuchsia__
#define LIB_ZXTEST_STATUS_PRINTER [](zx_status_t status) { return zxtest::PrintStatus(status); }
#else
#define LIB_ZXTEST_STATUS_PRINTER LIB_ZXTEST_DEFAULT_PRINTER
#endif
#define LIB_ZXTEST_HEXDUMP_PRINTER(size) \
[size](const auto& val) { \
return zxtest::internal::ToHex(static_cast<const void*>(val), byte_count); \
}
#ifdef __Fuchsia__
#define LIB_ZXTEST_DEATH_STATUS_COMPLETE zxtest::internal::DeathStatement::State::kSuccess
#define LIB_ZXTEST_DEATH_STATUS_EXCEPTION zxtest::internal::DeathStatement::State::kException
#define LIB_ZXTEST_DEATH_STATEMENT(statement, expected_result, desc, ...) \
do { \
LIB_ZXTEST_CHECK_RUNNING(); \
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()) { \
LIB_ZXTEST_ASSERT_ERROR(true, true, death_statement.error_message().data()); \
} else { \
LIB_ZXTEST_ASSERT_ERROR(true, true, desc, ##__VA_ARGS__); \
} \
} \
} while (0)
#endif // __Fuchsia__
#define SCOPED_TRACE(message) \
zxtest::ScopedTrace LIB_ZXTEST_CONCAT_TOKEN(zxtest_trace_, __LINE__)( \
{.filename = __FILE__, .line_number = __LINE__}, message)
#endif // ZXTEST_CPP_ZXTEST_H_