#![cfg(not(miri))]
use std::process::{Command, Output};
use cargo_gamma_lib::internals::commands::{EXIT_OK, EXIT_USAGE};
fn gamma(arguments: &[&str]) -> Output {
Command::new(env!("CARGO_BIN_EXE_cargo-gamma"))
.args(arguments)
.output()
.expect("the built cargo-gamma binary runs")
}
#[track_caller]
fn code(output: &Output) -> i32 {
output.status.code().unwrap_or_else(|| {
panic!(
"the process was killed rather than exiting: {}",
String::from_utf8_lossy(&output.stderr)
)
})
}
fn states_a_version(printed: &str) -> bool {
printed.split_whitespace().last().is_some_and(|last| {
let (without_build, build) = last.split_once('+').map_or((last, None), |(version, build)| (version, Some(build)));
let (core, prerelease) = without_build
.split_once('-')
.map_or((without_build, None), |(core, prerelease)| (core, Some(prerelease)));
let mut parts = core.split('.');
[parts.next(), parts.next(), parts.next()]
.into_iter()
.all(|part| part.is_some_and(|part| !part.is_empty() && part.chars().all(|c| c.is_ascii_digit())))
&& parts.next().is_none()
&& prerelease.is_none_or(valid_identifiers)
&& build.is_none_or(valid_identifiers)
})
}
fn valid_identifiers(value: &str) -> bool {
!value.is_empty()
&& value
.split('.')
.all(|identifier| !identifier.is_empty() && identifier.chars().all(|c| c.is_ascii_alphanumeric() || c == '-'))
}
#[test]
fn version_shape_accepts_semver_metadata() {
assert!(states_a_version("cargo-gamma 1.2.3-beta.1+git.42"));
assert!(!states_a_version("cargo-gamma 1.2.3-"));
assert!(!states_a_version("cargo-gamma 1.2.3+"));
}
#[test]
fn the_installed_binary_reports_its_version_and_succeeds() {
let output = gamma(&["--version"]);
let printed = String::from_utf8_lossy(&output.stdout);
assert_eq!(code(&output), EXIT_OK, "{}", String::from_utf8_lossy(&output.stderr));
assert!(
states_a_version(&printed),
"the version was not printed to standard output: {printed}"
);
}
#[test]
fn the_installed_binary_accepts_the_argument_shape_cargo_passes_it() {
let output = gamma(&["gamma", "--version"]);
let printed = String::from_utf8_lossy(&output.stdout);
assert_eq!(code(&output), EXIT_OK, "{}", String::from_utf8_lossy(&output.stderr));
assert!(
states_a_version(&printed),
"the version was not printed to standard output: {printed}"
);
}
#[test]
fn an_unknown_command_exits_with_the_usage_code_and_explains_itself_on_standard_error() {
let output = gamma(&["definitely-not-a-command"]);
let complaint = String::from_utf8_lossy(&output.stderr);
assert_eq!(code(&output), EXIT_USAGE, "an unknown command must not be reported as success");
assert!(!complaint.trim().is_empty(), "an unknown command was refused without saying why");
assert!(
String::from_utf8_lossy(&output.stdout).trim().is_empty(),
"a diagnostic reached standard output, where it would corrupt piped report output"
);
}