xref: /llvm-project/libcxx/test/support/test.support/test_check_assertion.pass.cpp (revision 314526557ec66ee627ae8a1c03f6ccc610668fdb)
1b0fd9497SLouis Dionne //===----------------------------------------------------------------------===//
2b0fd9497SLouis Dionne //
3b0fd9497SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b0fd9497SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
5b0fd9497SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b0fd9497SLouis Dionne //
7b0fd9497SLouis Dionne //===----------------------------------------------------------------------===//
8b0fd9497SLouis Dionne 
9f3a970a8SJohn Brawn // REQUIRES: has-unix-headers
10f3a970a8SJohn Brawn // UNSUPPORTED: c++03
1164d413efSKonstantin Varlamov // UNSUPPORTED: libcpp-hardening-mode=none
12f0fc8c48SLouis Dionne // XFAIL: availability-verbose_abort-missing
13b0fd9497SLouis Dionne 
14b0fd9497SLouis Dionne #include <cassert>
15b0fd9497SLouis Dionne #include <cstdio>
16b0fd9497SLouis Dionne #include <string>
17b0fd9497SLouis Dionne 
18b0fd9497SLouis Dionne #include "check_assertion.h"
19b0fd9497SLouis Dionne 
20b0fd9497SLouis Dionne template <class Func>
TestDeathTest(Outcome expected_outcome,DeathCause expected_cause,const char * stmt,Func && func,const Matcher & matcher)2158780b81SKonstantin Varlamov bool TestDeathTest(
2258780b81SKonstantin Varlamov     Outcome expected_outcome, DeathCause expected_cause, const char* stmt, Func&& func, const Matcher& matcher) {
2358780b81SKonstantin Varlamov   auto get_matcher = [&] {
2458780b81SKonstantin Varlamov #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
2558780b81SKonstantin Varlamov     return matcher;
2658780b81SKonstantin Varlamov #else
2758780b81SKonstantin Varlamov     (void)matcher;
2858780b81SKonstantin Varlamov     return MakeAnyMatcher();
2958780b81SKonstantin Varlamov #endif
30b0fd9497SLouis Dionne   };
3158780b81SKonstantin Varlamov 
3258780b81SKonstantin Varlamov   DeathTest test_case;
33*31452655SLouis Dionne   DeathTestResult test_result = test_case.Run(std::array<DeathCause, 1>{expected_cause}, func, get_matcher());
3458780b81SKonstantin Varlamov   std::string maybe_failure_description;
3558780b81SKonstantin Varlamov 
3658780b81SKonstantin Varlamov   Outcome outcome = test_result.outcome();
3758780b81SKonstantin Varlamov   if (expected_outcome != outcome) {
3858780b81SKonstantin Varlamov     maybe_failure_description +=
3958780b81SKonstantin Varlamov         std::string("Test outcome was different from expected; expected ") + ToString(expected_outcome) +
4058780b81SKonstantin Varlamov         ", got: " + ToString(outcome);
4158780b81SKonstantin Varlamov   }
4258780b81SKonstantin Varlamov 
4358780b81SKonstantin Varlamov   DeathCause cause = test_result.cause();
4458780b81SKonstantin Varlamov   if (expected_cause != cause) {
4558780b81SKonstantin Varlamov     auto failure_description =
4658780b81SKonstantin Varlamov         std::string("Cause of death was different from expected; expected ") + ToString(expected_cause) +
4758780b81SKonstantin Varlamov         ", got: " + ToString(cause);
4858780b81SKonstantin Varlamov     if (maybe_failure_description.empty()) {
4958780b81SKonstantin Varlamov       maybe_failure_description = failure_description;
5058780b81SKonstantin Varlamov     } else {
5158780b81SKonstantin Varlamov       maybe_failure_description += std::string("; ") + failure_description;
5258780b81SKonstantin Varlamov     }
5358780b81SKonstantin Varlamov   }
5458780b81SKonstantin Varlamov 
5558780b81SKonstantin Varlamov   if (!maybe_failure_description.empty()) {
5658780b81SKonstantin Varlamov     test_case.PrintFailureDetails(maybe_failure_description, stmt, test_result.cause());
5758780b81SKonstantin Varlamov     return false;
5858780b81SKonstantin Varlamov   }
5958780b81SKonstantin Varlamov 
60b0fd9497SLouis Dionne   return true;
61b0fd9497SLouis Dionne }
62b0fd9497SLouis Dionne 
6358780b81SKonstantin Varlamov // clang-format off
64b0fd9497SLouis Dionne 
6558780b81SKonstantin Varlamov #define TEST_DEATH_TEST(outcome, cause, ...)                   \
6658780b81SKonstantin Varlamov   assert(( TestDeathTest(outcome, cause, #__VA_ARGS__, [&]() { __VA_ARGS__; }, MakeAnyMatcher()) ))
6758780b81SKonstantin Varlamov #define TEST_DEATH_TEST_MATCHES(outcome, cause, matcher, ...)  \
6858780b81SKonstantin Varlamov   assert(( TestDeathTest(outcome, cause, #__VA_ARGS__, [&]() { __VA_ARGS__; }, matcher) ))
69b0fd9497SLouis Dionne 
7058780b81SKonstantin Varlamov // clang-format on
71b0fd9497SLouis Dionne 
7258780b81SKonstantin Varlamov #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
7358780b81SKonstantin Varlamov DeathCause assertion_death_cause = DeathCause::VerboseAbort;
7458780b81SKonstantin Varlamov #else
7558780b81SKonstantin Varlamov DeathCause assertion_death_cause = DeathCause::Trap;
7658780b81SKonstantin Varlamov #endif
77b0fd9497SLouis Dionne 
main(int,char **)78b0fd9497SLouis Dionne int main(int, char**) {
7958780b81SKonstantin Varlamov   auto fail_assert     = [] { _LIBCPP_ASSERT(false, "Some message"); };
8058780b81SKonstantin Varlamov   Matcher good_matcher = MakeAssertionMessageMatcher("Some message");
8158780b81SKonstantin Varlamov   Matcher bad_matcher  = MakeAssertionMessageMatcher("Bad expected message");
8258780b81SKonstantin Varlamov 
8358780b81SKonstantin Varlamov   // Test the implementation of death tests. We're bypassing the assertions added by the actual `EXPECT_DEATH` macros
8458780b81SKonstantin Varlamov   // which allows us to test failure cases (where the assertion would fail) as well.
8558780b81SKonstantin Varlamov   {
8658780b81SKonstantin Varlamov     // Success -- `std::terminate`.
8758780b81SKonstantin Varlamov     TEST_DEATH_TEST(Outcome::Success, DeathCause::StdTerminate, std::terminate());
8858780b81SKonstantin Varlamov 
8958780b81SKonstantin Varlamov     // Success -- trapping.
9058780b81SKonstantin Varlamov     TEST_DEATH_TEST(Outcome::Success, DeathCause::Trap, __builtin_trap());
9158780b81SKonstantin Varlamov 
9258780b81SKonstantin Varlamov     // Success -- assertion failure with any matcher.
9358780b81SKonstantin Varlamov     TEST_DEATH_TEST_MATCHES(Outcome::Success, assertion_death_cause, MakeAnyMatcher(), fail_assert());
9458780b81SKonstantin Varlamov 
9558780b81SKonstantin Varlamov     // Success -- assertion failure with a specific matcher.
9658780b81SKonstantin Varlamov     TEST_DEATH_TEST_MATCHES(Outcome::Success, assertion_death_cause, good_matcher, fail_assert());
9758780b81SKonstantin Varlamov 
9858780b81SKonstantin Varlamov #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
9958780b81SKonstantin Varlamov     // Failure -- error message doesn't match.
10058780b81SKonstantin Varlamov     TEST_DEATH_TEST_MATCHES(Outcome::UnexpectedErrorMessage, assertion_death_cause, bad_matcher, fail_assert());
10158780b81SKonstantin Varlamov #endif
10258780b81SKonstantin Varlamov 
10358780b81SKonstantin Varlamov     // Invalid cause -- child did not die.
10458780b81SKonstantin Varlamov     TEST_DEATH_TEST(Outcome::InvalidCause, DeathCause::DidNotDie, ((void)0));
10558780b81SKonstantin Varlamov 
10658780b81SKonstantin Varlamov     // Invalid cause --  unknown.
10758780b81SKonstantin Varlamov     TEST_DEATH_TEST(Outcome::InvalidCause, DeathCause::Unknown, std::exit(13));
10858780b81SKonstantin Varlamov   }
10958780b81SKonstantin Varlamov 
11058780b81SKonstantin Varlamov   // Test the `EXPECT_DEATH` macros themselves. Since they assert success, we can only test successful cases.
11158780b81SKonstantin Varlamov   {
112*31452655SLouis Dionne     auto invoke_verbose_abort = [] { _LIBCPP_VERBOSE_ABORT("contains some message"); };
113*31452655SLouis Dionne     auto invoke_abort         = [] { std::abort(); };
11458780b81SKonstantin Varlamov 
11558780b81SKonstantin Varlamov     auto simple_matcher = [](const std::string& text) {
11658780b81SKonstantin Varlamov       bool success = text.find("some") != std::string::npos;
11758780b81SKonstantin Varlamov       return MatchResult(success, "");
11858780b81SKonstantin Varlamov     };
11958780b81SKonstantin Varlamov 
120*31452655SLouis Dionne     EXPECT_ANY_DEATH(_LIBCPP_VERBOSE_ABORT(""));
121*31452655SLouis Dionne     EXPECT_ANY_DEATH(std::abort());
122*31452655SLouis Dionne     EXPECT_ANY_DEATH(std::terminate());
123*31452655SLouis Dionne     EXPECT_DEATH(invoke_verbose_abort());
124*31452655SLouis Dionne     EXPECT_DEATH_MATCHES(MakeAnyMatcher(), invoke_verbose_abort());
125*31452655SLouis Dionne     EXPECT_DEATH_MATCHES(simple_matcher, invoke_verbose_abort());
126*31452655SLouis Dionne     EXPECT_STD_ABORT(invoke_abort());
12758780b81SKonstantin Varlamov     EXPECT_STD_TERMINATE([] { std::terminate(); });
12858780b81SKonstantin Varlamov     TEST_LIBCPP_ASSERT_FAILURE(fail_assert(), "Some message");
12958780b81SKonstantin Varlamov   }
13058780b81SKonstantin Varlamov 
131b0fd9497SLouis Dionne   return 0;
132b0fd9497SLouis Dionne }
133