xref: /llvm-project/libcxx/test/support/assert_macros.h (revision 748023dc3210533df2c1c6efc8af1b5954493701)
1f8bed136SMark de Wever //===----------------------------------------------------------------------===//
2f8bed136SMark de Wever //
3f8bed136SMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f8bed136SMark de Wever // See https://llvm.org/LICENSE.txt for license information.
5f8bed136SMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f8bed136SMark de Wever //
7f8bed136SMark de Wever //===----------------------------------------------------------------------===//
8f8bed136SMark de Wever 
9f8bed136SMark de Wever #ifndef TEST_SUPPORT_ASSERT_MACROS_H
10f8bed136SMark de Wever #define TEST_SUPPORT_ASSERT_MACROS_H
11f8bed136SMark de Wever 
12f8bed136SMark de Wever // Contains a set of validation macros.
13f8bed136SMark de Wever //
14f8bed136SMark de Wever // Note these test were added after C++20 was well supported by the compilers
15f8bed136SMark de Wever // used. To make the implementation simple the macros require C++20 or newer.
16f8bed136SMark de Wever // It's not expected that existing tests start to use these new macros.
17f8bed136SMark de Wever //
18f8bed136SMark de Wever // These macros are an alternative to using assert. The differences are:
19f8bed136SMark de Wever // - The assert message isn't localized.
20f8bed136SMark de Wever // - It's possible to log additional information. This is useful when the
21f8bed136SMark de Wever //   function asserting is a helper function. In these cases the assertion
22f8bed136SMark de Wever //   failure contains to little information to find the issue. For example, in
23f8bed136SMark de Wever //   the format functions, the really useful information is the actual output,
24f8bed136SMark de Wever //   the expected output, and the format string used. These macros allow
25f8bed136SMark de Wever //   logging additional arguments.
26f8bed136SMark de Wever 
27f8bed136SMark de Wever #include "test_macros.h"
28f8bed136SMark de Wever 
29f8bed136SMark de Wever #include <cstdio>
30f8bed136SMark de Wever #include <cstdlib>
31f8bed136SMark de Wever 
32dbe6894aSLouis Dionne // This function prints the given arguments to standard error.
33dbe6894aSLouis Dionne //
34dbe6894aSLouis Dionne // Keeping this as a separate function is important since it provides a single point for
35dbe6894aSLouis Dionne // downstreams to customize how errors are printed on exotic targets, if needed.
36dbe6894aSLouis Dionne template <class ...Args>
37dbe6894aSLouis Dionne void test_eprintf(char const* fmt, Args const& ...args) {
38dbe6894aSLouis Dionne   std::fprintf(stderr, fmt, args...);
39dbe6894aSLouis Dionne }
40dbe6894aSLouis Dionne 
413476b56fSMark de Wever void test_log(const char* condition, const char* file, int line, const char* message) {
423476b56fSMark de Wever   const char* msg = condition ? "Assertion failure: " : "Unconditional failure:";
43dbe6894aSLouis Dionne   test_eprintf("%s%s %s %d\n%s", msg, condition, file, line, message);
44f8bed136SMark de Wever }
45f8bed136SMark de Wever 
463476b56fSMark de Wever template <class F>
473476b56fSMark de Wever void test_log(const char* condition, const char* file, int line, const F& functor) {
48dbe6894aSLouis Dionne   test_eprintf("Assertion failure: %s %s %d\n", condition, file, line);
493476b56fSMark de Wever   functor();
503476b56fSMark de Wever }
51f8bed136SMark de Wever 
523476b56fSMark de Wever template <class Arg>
53*748023dcSNikolas Klauser [[noreturn]] void test_fail(const char* file, int line, const Arg& arg) {
542f2ed477SMark de Wever   test_log("", file, line, arg);
558e13ec9eSKonstantin Varlamov   std::abort();
56f8bed136SMark de Wever }
57f8bed136SMark de Wever 
583476b56fSMark de Wever template <class Arg>
592f2ed477SMark de Wever void test_require(bool condition, const char* condition_str, const char* file, int line, const Arg& arg) {
60f8bed136SMark de Wever   if (condition)
61f8bed136SMark de Wever     return;
62f8bed136SMark de Wever 
632f2ed477SMark de Wever   test_log(condition_str, file, line, arg);
643476b56fSMark de Wever   std::abort();
65f8bed136SMark de Wever }
66f8bed136SMark de Wever 
67f8bed136SMark de Wever // assert(false) replacement
683476b56fSMark de Wever // The ARG is either a
69f5832babSStephan T. Lavavej // - c-string or std::string, in which case the string is printed to stderr,
703476b56fSMark de Wever // - an invocable object, which will be invoked.
713476b56fSMark de Wever #define TEST_FAIL(ARG) ::test_fail(__FILE__, __LINE__, ARG)
72f8bed136SMark de Wever 
73f8bed136SMark de Wever // assert replacement.
743476b56fSMark de Wever // ARG is the same as for TEST_FAIL
753476b56fSMark de Wever #define TEST_REQUIRE(CONDITION, ARG) ::test_require(CONDITION, #CONDITION, __FILE__, __LINE__, ARG)
76f8bed136SMark de Wever 
77f8bed136SMark de Wever // LIBCPP_ASSERT replacement
78f8bed136SMark de Wever //
79f8bed136SMark de Wever // This requirement is only tested when the test suite is used for libc++.
80f8bed136SMark de Wever // This allows checking libc++ specific requirements, for example the error
81f8bed136SMark de Wever // messages of exceptions.
823476b56fSMark de Wever // ARG is the same as for TEST_FAIL
833476b56fSMark de Wever #if defined(_LIBCPP_VERSION)
843476b56fSMark de Wever #  define TEST_LIBCPP_REQUIRE(CONDITION, ARG) ::test_require(CONDITION, #CONDITION, __FILE__, __LINE__, ARG)
853476b56fSMark de Wever #else
863476b56fSMark de Wever #  define TEST_LIBCPP_REQUIRE(...) /* DO NOTHING */
873476b56fSMark de Wever #endif
883476b56fSMark de Wever 
893476b56fSMark de Wever // Helper macro to test an expression does not throw any exception.
903476b56fSMark de Wever #ifndef TEST_HAS_NO_EXCEPTIONS
913476b56fSMark de Wever #  define TEST_DOES_NOT_THROW(EXPR)                                                                                    \
923476b56fSMark de Wever     do {                                                                                                               \
933476b56fSMark de Wever       try {                                                                                                            \
943476b56fSMark de Wever         static_cast<void>(EXPR);                                                                                       \
953476b56fSMark de Wever       } catch (...) {                                                                                                  \
963476b56fSMark de Wever         ::test_log(#EXPR, __FILE__, __LINE__, "no exception was expected\n");                                          \
973476b56fSMark de Wever         ::std::abort();                                                                                                \
983476b56fSMark de Wever       }                                                                                                                \
993476b56fSMark de Wever     } while (false) /* */
1003476b56fSMark de Wever 
1013476b56fSMark de Wever // Helper macro to test an expression throws an exception of the expected type.
1023476b56fSMark de Wever #  define TEST_THROWS_TYPE(TYPE, EXPR)                                                                                 \
1033476b56fSMark de Wever     do {                                                                                                               \
1043476b56fSMark de Wever       try {                                                                                                            \
1053476b56fSMark de Wever         static_cast<void>(EXPR);                                                                                       \
1063476b56fSMark de Wever         ::test_log(nullptr,                                                                                            \
1073476b56fSMark de Wever                    __FILE__,                                                                                           \
1083476b56fSMark de Wever                    __LINE__,                                                                                           \
1093476b56fSMark de Wever                    "no exception is thrown while an exception of type " #TYPE " was expected\n");                      \
1103476b56fSMark de Wever         ::std::abort();                                                                                                \
1113476b56fSMark de Wever       } catch (const TYPE&) {                                                                                          \
1123476b56fSMark de Wever         /* DO NOTHING */                                                                                               \
1133476b56fSMark de Wever       } catch (...) {                                                                                                  \
1143476b56fSMark de Wever         ::test_log(nullptr,                                                                                            \
1153476b56fSMark de Wever                    __FILE__,                                                                                           \
1163476b56fSMark de Wever                    __LINE__,                                                                                           \
1173476b56fSMark de Wever                    "the type of the exception caught differs from the expected type " #TYPE "\n");                     \
1183476b56fSMark de Wever         ::std::abort();                                                                                                \
1193476b56fSMark de Wever       }                                                                                                                \
1203476b56fSMark de Wever     } while (false) /* */
1213476b56fSMark de Wever 
1223476b56fSMark de Wever // Helper macro to test an expression throws an exception of the expected type and satisfies a predicate.
1233476b56fSMark de Wever //
1243476b56fSMark de Wever // In order to log additional information the predicate can use log macros.
1253476b56fSMark de Wever // The exception caught is used as argument to the predicate.
1263476b56fSMark de Wever #  define TEST_VALIDATE_EXCEPTION(TYPE, PRED, EXPR)                                                                    \
1273476b56fSMark de Wever     do {                                                                                                               \
1283476b56fSMark de Wever       try {                                                                                                            \
1293476b56fSMark de Wever         static_cast<void>(EXPR);                                                                                       \
1303476b56fSMark de Wever         ::test_log(nullptr,                                                                                            \
1313476b56fSMark de Wever                    __FILE__,                                                                                           \
1323476b56fSMark de Wever                    __LINE__,                                                                                           \
1333476b56fSMark de Wever                    "no exception is thrown while an exception of type " #TYPE " was expected\n");                      \
1343476b56fSMark de Wever         ::std::abort();                                                                                                \
1353476b56fSMark de Wever       } catch (const TYPE& EXCEPTION) {                                                                                \
1363476b56fSMark de Wever         PRED(EXCEPTION);                                                                                               \
1373476b56fSMark de Wever       } catch (...) {                                                                                                  \
1383476b56fSMark de Wever         ::test_log(nullptr,                                                                                            \
1393476b56fSMark de Wever                    __FILE__,                                                                                           \
1403476b56fSMark de Wever                    __LINE__,                                                                                           \
1413476b56fSMark de Wever                    "the type of the exception caught differs from the expected type " #TYPE "\n");                     \
1423476b56fSMark de Wever         ::std::abort();                                                                                                \
1433476b56fSMark de Wever       }                                                                                                                \
1443476b56fSMark de Wever     } while (false)                    /* */
1453476b56fSMark de Wever 
1463476b56fSMark de Wever #else                                  // TEST_HAS_NO_EXCEPTIONS
1473476b56fSMark de Wever #  define TEST_DOES_NOT_THROW(EXPR) static_cast<void>(EXPR);
1483476b56fSMark de Wever #  define TEST_THROWS_TYPE(...)        /* DO NOTHING */
1493476b56fSMark de Wever #  define TEST_VALIDATE_EXCEPTION(...) /* DO NOTHING */
1503476b56fSMark de Wever #endif                                 // TEST_HAS_NO_EXCEPTIONS
151f8bed136SMark de Wever 
152f8bed136SMark de Wever #endif // TEST_SUPPORT_ASSERT_MACROS_H
153