From 725e64bd21f1fce4e9b432e4150ac579879d35f8 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 7 Aug 2024 12:05:57 -0400 Subject: [PATCH 1/2] Clarify that 8-bit exit codes aren't a problem on macOS/Linux/Windows. The documentation for the experimental exit tests feature currently says that on POSIX-like systems, only the low 8 bits of a process' exit code are preserved. This would be true if we used `wait()`, `wait4()`, etc. and `WEXITSTATUS()`, but we use `waitid()` instead which is [supposed to](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exit.html) preserve the full exit code. Now, we're not currently building for any other POSIX-like systems that support processes (WASI/Wasm doesn't count here), so I've left in some weasel words and added a canary unit test. It will let us know if/when we add a platform that where `waitid()` doesn't preserve all the bits of the exit code, and we can amend the documentation in that case. Exit tests remain an experimental feature only. --- Sources/Testing/ExitTests/ExitCondition.swift | 6 +++--- Tests/TestingTests/ExitTestTests.swift | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Sources/Testing/ExitTests/ExitCondition.swift b/Sources/Testing/ExitTests/ExitCondition.swift index e3074740d..1d7813ddf 100644 --- a/Sources/Testing/ExitTests/ExitCondition.swift +++ b/Sources/Testing/ExitTests/ExitCondition.swift @@ -44,9 +44,9 @@ public enum ExitCondition: Sendable { /// | Linux | [``](https://sourceware.org/glibc/manual/latest/html_node/Exit-Status.html), `` | /// | Windows | [``](https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure) | /// - /// On POSIX-like systems including macOS and Linux, only the low unsigned 8 - /// bits (0–255) of the exit code are reliably preserved and reported to - /// a parent process. + /// On macOS, Linux, and Windows, the full exit code reported by the process + /// is yielded to the parent process. Other POSIX-like systems may only + /// reliably report the low unsigned 8 bits (0–255) of the exit code. case exitCode(_ exitCode: CInt) /// The process terminated with the given signal. diff --git a/Tests/TestingTests/ExitTestTests.swift b/Tests/TestingTests/ExitTestTests.swift index 55c22a9bb..7b5480a5b 100644 --- a/Tests/TestingTests/ExitTestTests.swift +++ b/Tests/TestingTests/ExitTestTests.swift @@ -197,6 +197,21 @@ private import _TestingInternals }.run(configuration: configuration) } } + + @Test("Exit test reports > 8 bits of the exit code") + func fullWidthExitCode() async { + // On macOS and Linux, we use waitid() which per POSIX should report the + // full exit code, not just the low 8 bits. This behaviour is not + // well-documented and other POSIX-like implementations may not follow it, + // so this test serves as a canary when adding new platforms that we need + // to document the difference. + // + // Windows does not have the 8-bit exit code restriction and always reports + // the full CInt value back to the testing library. + await #expect(exitsWith: .exitCode(512)) { + exit(512) + } + } } // MARK: - Fixtures From 761c98be231c0e7f1d153b4cba1a2c70954bcd50 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Wed, 7 Aug 2024 12:23:05 -0400 Subject: [PATCH 2/2] Alas, Linux --- Sources/Testing/ExitTests/ExitCondition.swift | 4 ++-- Tests/TestingTests/ExitTestTests.swift | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Sources/Testing/ExitTests/ExitCondition.swift b/Sources/Testing/ExitTests/ExitCondition.swift index 1d7813ddf..aaf09cfd4 100644 --- a/Sources/Testing/ExitTests/ExitCondition.swift +++ b/Sources/Testing/ExitTests/ExitCondition.swift @@ -44,8 +44,8 @@ public enum ExitCondition: Sendable { /// | Linux | [``](https://sourceware.org/glibc/manual/latest/html_node/Exit-Status.html), `` | /// | Windows | [``](https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure) | /// - /// On macOS, Linux, and Windows, the full exit code reported by the process - /// is yielded to the parent process. Other POSIX-like systems may only + /// On macOS and Windows, the full exit code reported by the process is + /// yielded to the parent process. Linux and other POSIX-like systems may only /// reliably report the low unsigned 8 bits (0–255) of the exit code. case exitCode(_ exitCode: CInt) diff --git a/Tests/TestingTests/ExitTestTests.swift b/Tests/TestingTests/ExitTestTests.swift index 7b5480a5b..b26975edc 100644 --- a/Tests/TestingTests/ExitTestTests.swift +++ b/Tests/TestingTests/ExitTestTests.swift @@ -198,13 +198,15 @@ private import _TestingInternals } } +#if !os(Linux) @Test("Exit test reports > 8 bits of the exit code") func fullWidthExitCode() async { // On macOS and Linux, we use waitid() which per POSIX should report the // full exit code, not just the low 8 bits. This behaviour is not - // well-documented and other POSIX-like implementations may not follow it, - // so this test serves as a canary when adding new platforms that we need - // to document the difference. + // well-documented and while Darwin correctly reports the full value, Linux + // does not (at least as of this writing) and other POSIX-like systems may + // also have issues. This test serves as a canary when adding new platforms + // that we need to document the difference. // // Windows does not have the 8-bit exit code restriction and always reports // the full CInt value back to the testing library. @@ -212,6 +214,7 @@ private import _TestingInternals exit(512) } } +#endif } // MARK: - Fixtures