1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef TEST_SUPPORT_ASSERT_MACROS_H
10 #define TEST_SUPPORT_ASSERT_MACROS_H
12 // Contains a set of validation macros.
14 // Note these test were added after C++20 was well supported by the compilers
15 // used. To make the implementation simple the macros require C++20 or newer.
16 // It's not expected that existing tests start to use these new macros.
18 // These macros are an alternative to using assert. The differences are:
19 // - The assert message isn't localized.
20 // - It's possible to log additional information. This is useful when the
21 // function asserting is a helper function. In these cases the assertion
22 // failure contains to little information to find the issue. For example, in
23 // the format functions, the really useful information is the actual output,
24 // the expected output, and the format string used. These macros allow
25 // logging additional arguments.
27 #include "test_macros.h"
32 // This function prints the given arguments to standard error.
34 // Keeping this as a separate function is important since it provides a single point for
35 // downstreams to customize how errors are printed on exotic targets, if needed.
36 template <class ...Args
>
37 void test_eprintf(char const* fmt
, Args
const& ...args
) {
38 std::fprintf(stderr
, fmt
, args
...);
41 void test_log(const char* condition
, const char* file
, int line
, const char* message
) {
42 const char* msg
= condition
? "Assertion failure: " : "Unconditional failure:";
43 test_eprintf("%s%s %s %d\n%s", msg
, condition
, file
, line
, message
);
47 void test_log(const char* condition
, const char* file
, int line
, const F
& functor
) {
48 test_eprintf("Assertion failure: %s %s %d\n", condition
, file
, line
);
53 [[noreturn
]] void test_fail(const char* file
, int line
, const Arg
& arg
) {
54 test_log("", file
, line
, arg
);
59 void test_require(bool condition
, const char* condition_str
, const char* file
, int line
, const Arg
& arg
) {
63 test_log(condition_str
, file
, line
, arg
);
67 // assert(false) replacement
68 // The ARG is either a
69 // - c-ctring or std::string, in which case the string is printed to stderr,
70 // - an invocable object, which will be invoked.
71 #define TEST_FAIL(ARG) ::test_fail(__FILE__, __LINE__, ARG)
73 // assert replacement.
74 // ARG is the same as for TEST_FAIL
75 #define TEST_REQUIRE(CONDITION, ARG) ::test_require(CONDITION, #CONDITION, __FILE__, __LINE__, ARG)
77 // LIBCPP_ASSERT replacement
79 // This requirement is only tested when the test suite is used for libc++.
80 // This allows checking libc++ specific requirements, for example the error
81 // messages of exceptions.
82 // ARG is the same as for TEST_FAIL
83 #if defined(_LIBCPP_VERSION)
84 # define TEST_LIBCPP_REQUIRE(CONDITION, ARG) ::test_require(CONDITION, #CONDITION, __FILE__, __LINE__, ARG)
86 # define TEST_LIBCPP_REQUIRE(...) /* DO NOTHING */
89 // Helper macro to test an expression does not throw any exception.
90 #ifndef TEST_HAS_NO_EXCEPTIONS
91 # define TEST_DOES_NOT_THROW(EXPR) \
94 static_cast<void>(EXPR); \
96 ::test_log(#EXPR, __FILE__, __LINE__, "no exception was expected\n"); \
101 // Helper macro to test an expression throws an exception of the expected type.
102 # define TEST_THROWS_TYPE(TYPE, EXPR) \
105 static_cast<void>(EXPR); \
106 ::test_log(nullptr, \
109 "no exception is thrown while an exception of type " #TYPE " was expected\n"); \
111 } catch (const TYPE&) { \
114 ::test_log(nullptr, \
117 "the type of the exception caught differs from the expected type " #TYPE "\n"); \
120 } while (false) /* */
122 // Helper macro to test an expression throws an exception of the expected type and satisfies a predicate.
124 // In order to log additional information the predicate can use log macros.
125 // The exception caught is used as argument to the predicate.
126 # define TEST_VALIDATE_EXCEPTION(TYPE, PRED, EXPR) \
129 static_cast<void>(EXPR); \
130 ::test_log(nullptr, \
133 "no exception is thrown while an exception of type " #TYPE " was expected\n"); \
135 } catch (const TYPE& EXCEPTION) { \
138 ::test_log(nullptr, \
141 "the type of the exception caught differs from the expected type " #TYPE "\n"); \
144 } while (false) /* */
146 #else // TEST_HAS_NO_EXCEPTIONS
147 # define TEST_DOES_NOT_THROW(EXPR) static_cast<void>(EXPR);
148 # define TEST_THROWS_TYPE(...) /* DO NOTHING */
149 # define TEST_VALIDATE_EXCEPTION(...) /* DO NOTHING */
150 #endif // TEST_HAS_NO_EXCEPTIONS
152 #endif // TEST_SUPPORT_ASSERT_MACROS_H