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
20template <class Func>
21bool 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
73DeathCause assertion_death_cause = DeathCause::VerboseAbort;
74#else
75DeathCause assertion_death_cause = DeathCause::Trap;
76#endif
77
78int 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(s: "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

source code of libcxx/test/support/test.support/test_check_assertion.pass.cpp