1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
//
private import _TestingInternals
/// An enumeration describing possible conditions under which an exit test will
/// succeed or fail.
///
/// Values of this type can be passed to
/// ``expect(exitsWith:_:sourceLocation:performing:)`` or
/// ``require(exitsWith:_:sourceLocation:performing:)`` to configure which exit
/// statuses should be considered successful.
@_spi(Experimental)
#if SWT_NO_EXIT_TESTS
@available(*, unavailable, message: "Exit tests are not available on this platform.")
#endif
public enum ExitCondition: Sendable {
/// The process terminated successfully with status `EXIT_SUCCESS`.
public static var success: Self { .exitCode(EXIT_SUCCESS) }
/// The process terminated abnormally with any status other than
/// `EXIT_SUCCESS` or with any signal.
case failure
/// The process terminated with the given exit code.
///
/// - Parameters:
/// - exitCode: The exit code yielded by the process.
///
/// The C programming language defines two [standard exit codes](https://en.cppreference.com/w/c/program/EXIT_status),
/// `EXIT_SUCCESS` and `EXIT_FAILURE`. Platforms may additionally define their
/// own non-standard exit codes:
///
/// | Platform | Header |
/// |-|-|
/// | macOS | [`<stdlib.h>`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/_Exit.3.html), [`<sysexits.h>`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysexits.3.html) |
/// | Linux | [`<stdlib.h>`](https://sourceware.org/glibc/manual/latest/html_node/Exit-Status.html), `<sysexits.h>` |
/// | Windows | [`<stdlib.h>`](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.
case exitCode(_ exitCode: CInt)
/// The process terminated with the given signal.
///
/// - Parameters:
/// - signal: The signal that terminated the process.
///
/// The C programming language defines a number of [standard signals](https://en.cppreference.com/w/c/program/SIG_types).
/// Platforms may additionally define their own non-standard signal codes:
///
/// | Platform | Header |
/// |-|-|
/// | macOS | [`<signal.h>`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/signal.3.html) |
/// | Linux | [`<signal.h>`](https://sourceware.org/glibc/manual/latest/html_node/Standard-Signals.html) |
/// | Windows | [`<signal.h>`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/signal-constants) |
#if os(Windows)
@available(*, unavailable, message: "On Windows, use .failure instead.")
#endif
case signal(_ signal: CInt)
}
// MARK: -
#if SWT_NO_EXIT_TESTS
@available(*, unavailable, message: "Exit tests are not available on this platform.")
#endif
extension ExitCondition {
/// Check whether this instance matches another.
///
/// - Parameters:
/// - other: The other instance to compare against.
///
/// - Returns: Whether or not this instance is equal to, or at least covers,
/// the other instance.
func matches(_ other: ExitCondition) -> Bool {
return switch (self, other) {
case (.failure, .failure):
true
case let (.failure, .exitCode(exitCode)), let (.exitCode(exitCode), .failure):
exitCode != EXIT_SUCCESS
case let (.exitCode(lhs), .exitCode(rhs)):
lhs == rhs
#if !os(Windows)
case let (.signal(lhs), .signal(rhs)):
lhs == rhs
case (.signal, .failure), (.failure, .signal):
// All terminating signals are considered failures.
true
case (.signal, .exitCode), (.exitCode, .signal):
// Signals do not match exit codes.
false
#endif
}
}
}
|