Commit Graph
6 Commits
Author SHA1 Message Date
Daan De Meyer 9d10457a3e test-user-util: Migrate to new assertion macros 2025-12-19 11:11:39 +01:00
Daan De Meyer 87fbd33372 clang-tidy: Fix all remaining misc-include-cleaner violations
- Remove unused includes
- Add common false positive headers to misc-include-cleaner.IgnoreHeaders
- Add IWYU pragma keep for uncommon false positive headers
2025-11-22 10:19:41 +01:00
Chris Down e21a431ec4 tests: ASSERT_SIGNAL: Do not allow parent to hallucinate it is the child
assert_signal_internal() returns 0 in two distinct cases:

1. In the child process (immediately after fork returns 0).
2. In the parent process, if the child exited normally (no signal).

ASSERT_SIGNAL fails to distinguish these cases. When a child exited
normally (case 2), the parent process receives 0, incorrectly interprets
it as meaning it is the child, and re-executes the test expression
inside the parent process. Goodness gracious!

This causes two severe test integrity issues:

1. False positives. The parent can run the expression, succeed, and call
   _exit(EXIT_SUCCESS), causing the test to pass even though no signal
   was raised.
2. Silent truncation. The _exit() call in the parent terminates the test
   runner prematurely, preventing subsequent tests in the same file from
   running.

Example of the bug in action, from #39674:

    ASSERT_SIGNAL(fd_is_writable(closed_fd), SIGABRT)

This test should fail (fd_is_writable does not SIGABRT here), but with
the bug, the parent hallucinated being the child, re-ran the expression
successfully, and exited with success.

Fix this by refactoring assert_signal_internal() to be much more strict
about separating control flow from data.

The signal status is now returned via a strictly typed output parameter,
guaranteeing that determining whether we are the child is never
conflated with whether the child exited cleanly.
2025-11-20 02:40:07 +08:00
Chris Down 39adecfcd8 tests: ASSERT_SIGNAL: Stop exit codes from masquerading as signals
When a child process exits normally (si_code == CLD_EXITED),
siginfo.si_status contains the exit code. When it is killed by a signal
(si_code == CLD_KILLED or CLD_DUMPED), si_status contains the signal
number.  However, assert_signal_internal() returns si_status blindly.
This causes exit codes to be misinterpreted as signal numbers.

This allows failing tests to silently pass if their exit code
numerically coincides with the expected signal. For example, a test
expecting SIGABRT (6) would incorrectly pass if the child simply exited
with status 6 instead of being killed by a signal.

Fix this by checking si_code. Only return si_status as a signal number
if the child was actually killed by a signal (CLD_KILLED or CLD_DUMPED).
If the child exited normally (CLD_EXITED), return 0 to indicate that no
signal occurred.
2025-11-20 02:40:07 +08:00
Zbigniew Jędrzejewski-Szmek 367b325554 tests: add new ASSERT_OK_OR macro
IN_SET() fails if __VA_ARGS__ is just one item. I inserted a bogus 0 item into
the check to work around this.
2025-07-01 17:51:49 +02:00
Zbigniew Jędrzejewski-Szmek a1296fa5e5 test-tests: move assert tests to new file
Those macros are defined in tests.[ch], so the tests should be in test-tests.c.
2025-07-01 17:51:46 +02:00