[libcxx-commits] [libcxx] [libc++][hardening] In production hardening modes, trap rather than abort (PR #78561)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jan 19 10:18:34 PST 2024
================
@@ -18,47 +18,111 @@
#include "check_assertion.h"
template <class Func>
-inline bool TestDeathTest(const char* stmt, Func&& func, DeathTest::ResultKind ExpectResult, AssertionInfoMatcher Matcher = AnyMatcher) {
- DeathTest DT(Matcher);
- DeathTest::ResultKind RK = DT.Run(func);
- auto OnFailure = [&](std::string msg) {
- std::fprintf(stderr, "EXPECT_DEATH( %s ) failed! (%s)\n\n", stmt, msg.c_str());
- if (!DT.getChildStdErr().empty()) {
- std::fprintf(stderr, "---------- standard err ----------\n%s\n", DT.getChildStdErr().c_str());
- }
- if (!DT.getChildStdOut().empty()) {
- std::fprintf(stderr, "---------- standard out ----------\n%s\n", DT.getChildStdOut().c_str());
+bool TestDeathTest(
+ Outcome expected_outcome, DeathCause expected_cause, const char* stmt, Func&& func, const Matcher& matcher) {
+ auto get_matcher = [&] {
+#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+ return matcher;
+#else
+ (void)matcher;
+ return MakeAnyMatcher();
+#endif
+ };
+
+ DeathTest test_case;
+ DeathTestResult test_result = test_case.Run(expected_cause, func, get_matcher());
+ std::string maybe_failure_description;
+
+ Outcome outcome = test_result.outcome();
+ if (expected_outcome != outcome) {
+ maybe_failure_description +=
+ std::string("Test outcome was different from expected; expected ") + ToString(expected_outcome) +
+ ", got: " + ToString(outcome);
+ }
+
+ DeathCause cause = test_result.cause();
+ if (expected_cause != cause) {
+ auto failure_description =
+ std::string("Cause of death was different from expected; expected ") + ToString(expected_cause) +
+ ", got: " + ToString(cause);
+ if (maybe_failure_description.empty()) {
+ maybe_failure_description = failure_description;
+ } else {
+ maybe_failure_description += std::string("; ") + failure_description;
}
+ }
+
+ if (!maybe_failure_description.empty()) {
+ test_case.PrintFailureDetails(maybe_failure_description, stmt, test_result.cause());
return false;
- };
- if (RK != ExpectResult)
- return OnFailure(std::string("expected result did not occur: expected ") + DeathTest::ResultKindToString(ExpectResult) + " got: " + DeathTest::ResultKindToString(RK));
+ }
+
return true;
}
-#define TEST_DEATH_TEST(RK, ...) assert((TestDeathTest(#__VA_ARGS__, [&]() { __VA_ARGS__; }, RK, AnyMatcher )))
-
-#define TEST_DEATH_TEST_MATCHES(RK, Matcher, ...) assert((TestDeathTest(#__VA_ARGS__, [&]() { __VA_ARGS__; }, RK, Matcher)))
-void my_libcpp_assert() {
- _LIBCPP_ASSERT(false, "other");
-}
+// clang-format off
-void test_no_match_found() {
- AssertionInfoMatcher ExpectMatch("my message");
- TEST_DEATH_TEST_MATCHES(DeathTest::RK_MatchFailure, ExpectMatch, my_libcpp_assert());
-}
+#define TEST_DEATH_TEST(outcome, cause, ...) \
+ assert(( TestDeathTest(outcome, cause, #__VA_ARGS__, [&]() { __VA_ARGS__; }, MakeAnyMatcher()) ))
+#define TEST_DEATH_TEST_MATCHES(outcome, cause, matcher, ...) \
+ assert(( TestDeathTest(outcome, cause, #__VA_ARGS__, [&]() { __VA_ARGS__; }, matcher) ))
-void test_did_not_die() {
- TEST_DEATH_TEST(DeathTest::RK_DidNotDie, ((void)0));
-}
+// clang-format on
-void test_unknown() {
- TEST_DEATH_TEST(DeathTest::RK_Unknown, std::exit(13));
-}
+#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+DeathCause assertion_death_cause = DeathCause::VerboseAbort;
+#else
+DeathCause assertion_death_cause = DeathCause::Trap;
+#endif
int main(int, char**) {
- test_no_match_found();
- test_did_not_die();
- test_unknown();
+ auto fail_assert = [] { _LIBCPP_ASSERT(false, "Some message"); };
+ Matcher good_matcher = MakeAssertionMessageMatcher("Some message");
+ Matcher bad_matcher = MakeAssertionMessageMatcher("Bad expected message");
+
+ // Test the implementation of death tests. We're bypassing the assertions added by the actual `EXPECT_DEATH` macros
+ // which allows us to test failure cases (where the assertion would fail) as well.
+ {
+ // Success -- `std::terminate`.
+ TEST_DEATH_TEST(Outcome::Success, DeathCause::StdTerminate, std::terminate());
+
+ (void)fail_assert;
----------------
ldionne wrote:
Leftover?
https://github.com/llvm/llvm-project/pull/78561
More information about the libcxx-commits
mailing list