xref: /llvm-project/libcxx/test/support/test.support/test_check_assertion.pass.cpp (revision 314526557ec66ee627ae8a1c03f6ccc610668fdb)
1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // REQUIRES: has-unix-headers
10 // UNSUPPORTED: c++03
11 // UNSUPPORTED: libcpp-hardening-mode=none
12 // XFAIL: availability-verbose_abort-missing
13 
14 #include <cassert>
15 #include <cstdio>
16 #include <string>
17 
18 #include "check_assertion.h"
19 
20 template <class Func>
TestDeathTest(Outcome expected_outcome,DeathCause expected_cause,const char * stmt,Func && func,const Matcher & matcher)21 bool TestDeathTest(
22     Outcome expected_outcome, DeathCause expected_cause, const char* stmt, Func&& func, const Matcher& matcher) {
23   auto get_matcher = [&] {
24 #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
25     return matcher;
26 #else
27     (void)matcher;
28     return MakeAnyMatcher();
29 #endif
30   };
31 
32   DeathTest test_case;
33   DeathTestResult test_result = test_case.Run(std::array<DeathCause, 1>{expected_cause}, func, get_matcher());
34   std::string maybe_failure_description;
35 
36   Outcome outcome = test_result.outcome();
37   if (expected_outcome != outcome) {
38     maybe_failure_description +=
39         std::string("Test outcome was different from expected; expected ") + ToString(expected_outcome) +
40         ", got: " + ToString(outcome);
41   }
42 
43   DeathCause cause = test_result.cause();
44   if (expected_cause != cause) {
45     auto failure_description =
46         std::string("Cause of death was different from expected; expected ") + ToString(expected_cause) +
47         ", got: " + ToString(cause);
48     if (maybe_failure_description.empty()) {
49       maybe_failure_description = failure_description;
50     } else {
51       maybe_failure_description += std::string("; ") + failure_description;
52     }
53   }
54 
55   if (!maybe_failure_description.empty()) {
56     test_case.PrintFailureDetails(maybe_failure_description, stmt, test_result.cause());
57     return false;
58   }
59 
60   return true;
61 }
62 
63 // clang-format off
64 
65 #define TEST_DEATH_TEST(outcome, cause, ...)                   \
66   assert(( TestDeathTest(outcome, cause, #__VA_ARGS__, [&]() { __VA_ARGS__; }, MakeAnyMatcher()) ))
67 #define TEST_DEATH_TEST_MATCHES(outcome, cause, matcher, ...)  \
68   assert(( TestDeathTest(outcome, cause, #__VA_ARGS__, [&]() { __VA_ARGS__; }, matcher) ))
69 
70 // clang-format on
71 
72 #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
73 DeathCause assertion_death_cause = DeathCause::VerboseAbort;
74 #else
75 DeathCause assertion_death_cause = DeathCause::Trap;
76 #endif
77 
main(int,char **)78 int main(int, char**) {
79   auto fail_assert     = [] { _LIBCPP_ASSERT(false, "Some message"); };
80   Matcher good_matcher = MakeAssertionMessageMatcher("Some message");
81   Matcher bad_matcher  = MakeAssertionMessageMatcher("Bad expected message");
82 
83   // Test the implementation of death tests. We're bypassing the assertions added by the actual `EXPECT_DEATH` macros
84   // which allows us to test failure cases (where the assertion would fail) as well.
85   {
86     // Success -- `std::terminate`.
87     TEST_DEATH_TEST(Outcome::Success, DeathCause::StdTerminate, std::terminate());
88 
89     // Success -- trapping.
90     TEST_DEATH_TEST(Outcome::Success, DeathCause::Trap, __builtin_trap());
91 
92     // Success -- assertion failure with any matcher.
93     TEST_DEATH_TEST_MATCHES(Outcome::Success, assertion_death_cause, MakeAnyMatcher(), fail_assert());
94 
95     // Success -- assertion failure with a specific matcher.
96     TEST_DEATH_TEST_MATCHES(Outcome::Success, assertion_death_cause, good_matcher, fail_assert());
97 
98 #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
99     // Failure -- error message doesn't match.
100     TEST_DEATH_TEST_MATCHES(Outcome::UnexpectedErrorMessage, assertion_death_cause, bad_matcher, fail_assert());
101 #endif
102 
103     // Invalid cause -- child did not die.
104     TEST_DEATH_TEST(Outcome::InvalidCause, DeathCause::DidNotDie, ((void)0));
105 
106     // Invalid cause --  unknown.
107     TEST_DEATH_TEST(Outcome::InvalidCause, DeathCause::Unknown, std::exit(13));
108   }
109 
110   // Test the `EXPECT_DEATH` macros themselves. Since they assert success, we can only test successful cases.
111   {
112     auto invoke_verbose_abort = [] { _LIBCPP_VERBOSE_ABORT("contains some message"); };
113     auto invoke_abort         = [] { std::abort(); };
114 
115     auto simple_matcher = [](const std::string& text) {
116       bool success = text.find("some") != std::string::npos;
117       return MatchResult(success, "");
118     };
119 
120     EXPECT_ANY_DEATH(_LIBCPP_VERBOSE_ABORT(""));
121     EXPECT_ANY_DEATH(std::abort());
122     EXPECT_ANY_DEATH(std::terminate());
123     EXPECT_DEATH(invoke_verbose_abort());
124     EXPECT_DEATH_MATCHES(MakeAnyMatcher(), invoke_verbose_abort());
125     EXPECT_DEATH_MATCHES(simple_matcher, invoke_verbose_abort());
126     EXPECT_STD_ABORT(invoke_abort());
127     EXPECT_STD_TERMINATE([] { std::terminate(); });
128     TEST_LIBCPP_ASSERT_FAILURE(fail_assert(), "Some message");
129   }
130 
131   return 0;
132 }
133