use dora_message::common::NodeExitStatus;
use std::io;
use std::process::ExitStatus;
#[test]
fn exit_code_zero_is_success() {
let status = create_exit_status(0);
let node_status: NodeExitStatus = Ok(status).into();
assert!(
matches!(node_status, NodeExitStatus::Success),
"Exit code 0 must map to Success, got: {:?}",
node_status
);
}
#[test]
fn non_zero_exit_codes() {
let test_cases = vec![1, 2, 127, 255];
for code in test_cases {
let status = create_exit_status(code);
let node_status: NodeExitStatus = Ok(status).into();
assert!(
matches!(node_status, NodeExitStatus::ExitCode(c) if c == code),
"Exit code {} must map to ExitCode({}), got: {:?}",
code,
code,
node_status
);
}
}
#[test]
fn io_error_maps_to_io_error_variant() {
let io_err = io::Error::new(io::ErrorKind::BrokenPipe, "test error");
let node_status: NodeExitStatus = Err(io_err).into();
assert!(
matches!(node_status, NodeExitStatus::IoError(_)),
"io::Error must map to IoError variant, got: {:?}",
node_status
);
}
#[cfg(unix)]
#[test]
fn unix_signal_termination() {
use std::os::unix::process::ExitStatusExt;
let test_signals = vec![(9, "SIGKILL"), (15, "SIGTERM"), (11, "SIGSEGV")];
for (signal, name) in test_signals {
let status = ExitStatus::from_raw(signal);
let node_status: NodeExitStatus = Ok(status).into();
assert!(
matches!(node_status, NodeExitStatus::Signal(s) if s == signal),
"Signal {} ({}) must map to Signal({}), got: {:?}",
signal,
name,
signal,
node_status
);
}
}
#[test]
fn unknown_is_not_produced_for_valid_inputs() {
for code in 0..=10 {
let status = create_exit_status(code);
let node_status: NodeExitStatus = Ok(status).into();
assert!(
!matches!(node_status, NodeExitStatus::Unknown),
"Exit code {} should not produce Unknown, got: {:?}",
code,
node_status
);
}
let io_err = io::Error::new(io::ErrorKind::Other, "test");
let node_status: NodeExitStatus = Err(io_err).into();
assert!(
!matches!(node_status, NodeExitStatus::Unknown),
"I/O error should not produce Unknown"
);
#[cfg(unix)]
{
use std::os::unix::process::ExitStatusExt;
for signal in [1, 2, 9, 15] {
let status = ExitStatus::from_raw(signal);
let node_status: NodeExitStatus = Ok(status).into();
assert!(
!matches!(node_status, NodeExitStatus::Unknown),
"Signal {} should not produce Unknown, got: {:?}",
signal,
node_status
);
}
}
}
#[cfg(unix)]
fn create_exit_status(code: i32) -> ExitStatus {
use std::os::unix::process::ExitStatusExt;
ExitStatus::from_raw(code << 8)
}
#[cfg(windows)]
fn create_exit_status(code: i32) -> ExitStatus {
use std::os::windows::process::ExitStatusExt;
ExitStatus::from_raw(code as u32)
}
#[cfg(not(any(unix, windows)))]
fn create_exit_status(_code: i32) -> ExitStatus {
compile_error!("Unsupported platform for exit status tests");
}