[libcxx-commits] [PATCH] D154557: [libc++] Add more general death tests and make them work on more platforms
Louis Dionne via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Aug 7 09:35:35 PDT 2023
ldionne added a comment.
I'm ambivalent on this patch because it leaves us in a state where we have two frameworks for death tests and both are reasonably heavyweight. Instead, if we wanted to improve significantly on top of what we have today, I think we would need to implement support for these tests in the test harness (Lit).
We explored this a bit and it could look something like this:
#define TEST_EXPECTED_ERROR(expr, message)
do {
if (gather_tests) {
print(f"{test_counter} [[[{message}]]]");
} else if (test_counter-- == 0) {
expr();
}
} while (false)
// From lit:
// 1. Run the test with no arguments.
// 2. Parse the output and build a mapping like this:
// {test-number => expected-error-message}
// 3. Then you run the executable with each test number and you check the error message.
TEST_RUN_VERIFY_MAIN() {
{
typedef std::array<int, 0> C;
C c = {};
C const& cc = c;
TEST_EXPECTED_ERROR(c[0], "cannot call array<T, 0>::operator[] on a zero-sized array");
TEST_EXPECTED_ERROR(c[1], "cannot call array<T, 0>::operator[] on a zero-sized array");
TEST_EXPECTED_ERROR(cc[0], "cannot call array<T, 0>::operator[] on a zero-sized array");
TEST_EXPECTED_ERROR(cc[1], "cannot call array<T, 0>::operator[] on a zero-sized array");
}
{
typedef std::array<const int, 0> C;
C c = {{}};
C const& cc = c;
TEST_EXPECTED_ERROR(c[0], "cannot call array<T, 0>::operator[] on a zero-sized array");
TEST_EXPECTED_ERROR(c[1], "cannot call array<T, 0>::operator[] on a zero-sized array");
TEST_EXPECTED_ERROR(cc[0], "cannot call array<T, 0>::operator[] on a zero-sized array");
TEST_EXPECTED_ERROR(cc[1], "cannot call array<T, 0>::operator[] on a zero-sized array");
}
return 0;
}
Unfortunately, the `"From Lit"` part ends up being quite complicated (we prototyped) and so it's not clear it's worth pursuing at this time. Barring that, I think we should instead improve the current death test framework to support intentional calls to `std::terminate`, which should be doable roughly with
diff --git a/libcxx/test/support/check_assertion.h b/libcxx/test/support/check_assertion.h
index 741dc4a78828..263413b50b62 100644
--- a/libcxx/test/support/check_assertion.h
+++ b/libcxx/test/support/check_assertion.h
@@ -111,7 +111,7 @@ inline AssertionInfoMatcher& GlobalMatcher() {
struct DeathTest {
enum ResultKind {
- RK_DidNotDie, RK_MatchFound, RK_MatchFailure, RK_SetupFailure, RK_Unknown
+ RK_DidNotDie, RK_MatchFound, RK_MatchFailure, RK_SetupFailure, RK_TerminatedAsExpected, RK_Unknown
};
static const char* ResultKindToString(ResultKind RK) {
@@ -121,6 +121,7 @@ struct DeathTest {
CASE(RK_DidNotDie);
CASE(RK_SetupFailure);
CASE(RK_MatchFound);
+ CASE(RK_TerminatedAsExpected);
CASE(RK_Unknown);
}
return "not a result kind";
@@ -256,6 +257,11 @@ void std::__libcpp_verbose_abort(char const* format, ...) {
template <class Func>
inline bool ExpectDeath(const char* stmt, Func&& func, AssertionInfoMatcher Matcher) {
DeathTest DT(Matcher);
+ set_terminate([] {
+ if (__expect_to_terminate__)
+ std::exit(RK_TerminatedAsExpected);
+ std::abort();
+ });
DeathTest::ResultKind RK = DT.Run(func);
auto OnFailure = [&](const char* msg) {
std::fprintf(stderr, "EXPECT_DEATH( %s ) failed! (%s)\n\n", stmt, msg);
@@ -273,6 +279,8 @@ inline bool ExpectDeath(const char* stmt, Func&& func, AssertionInfoMatcher Matc
switch (RK) {
case DeathTest::RK_MatchFound:
return true;
+ case DeathTest::RK_TerminatedAsExpected:
+ return true;
case DeathTest::RK_SetupFailure:
return OnFailure("child failed to setup test environment");
case DeathTest::RK_Unknown:
================
Comment at: libcxx/test/libcxx/containers/sequences/array/array.zero/assert.subscript.pass.cpp:20
int main(int, char**) {
{
----------------
Should this be `TEST_TERMINATIONS`? It's also problematic that the test is going to appear to work if you misuse the "test framework" like this. Could probably be detected by referencing something that `TEST_TERMINATIONS` defines from `EXPECT_LIBCPP_ASSERT_FAILURE`.
================
Comment at: libcxx/test/support/terminating_test_helper.h:9
+
+#ifndef TEST_TERMINATING_TEST_HELPER_H
+#define TEST_TERMINATING_TEST_HELPER_H
----------------
================
Comment at: libcxx/test/support/terminating_test_helper.h:37
+ std_terminate,
+ nondetermenistic_test_count,
+#ifdef _LIBCPP_VERSION
----------------
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D154557/new/
https://reviews.llvm.org/D154557
More information about the libcxx-commits
mailing list