1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

who/stat/pinky: adjust tests to be compatible with running on macOS

A lot of tests depend on GNU's coreutils to be installed in order
to obtain reference values during testing.
In these cases testing is limited to `target_os = linux`.
This PR installs GNU's coreutils on "github actions" and adjusts the
tests for `who`, `stat` and `pinky` in order to be compatible with macOS.

* `brew install coreutils` (prefix is 'g', e.g. `gwho`, `gstat`, etc.
* switch paths for testing to something that's available on both OSs,
    e.g. `/boot` -> `/bin`, etc.
* switch paths for testing to the macOS equivalent,
    e.g. `/dev/pts/ptmx` -> `/dev/ptmx`, etc.
* exclude paths when no equivalent is available,
    e.g. `/proc`, `/etc/fstab`, etc.
* refactor tests to make better use of the testing API
* fix a warning in utmpx.rs to print to stderr instead of stdout
* fix long_usage text in `who`
* fix minor output formatting in `stat`

* the `expected_result` function should be refactored
    to reduce duplicate code
* more tests should be adjusted to not only run on `target_os = linux`
This commit is contained in:
Jan Scheer 2021-05-20 23:11:40 +02:00
parent dc93f29fe3
commit 007e0a4e7f
6 changed files with 207 additions and 196 deletions

View file

@ -657,7 +657,7 @@ impl Stater {
dst.to_string_lossy() dst.to_string_lossy()
); );
} else { } else {
arg = format!("`{}'", file); arg = file.to_string();
} }
otype = OutputType::Str; otype = OutputType::Str;
} }

View file

@ -46,9 +46,10 @@ fn get_usage() -> String {
} }
fn get_long_usage() -> String { fn get_long_usage() -> String {
String::from( format!(
"If FILE is not specified, use /var/run/utmp. /var/log/wtmp as FILE is common.\n\ "If FILE is not specified, use {}. /var/log/wtmp as FILE is common.\n\
If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.", If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.",
utmpx::DEFAULT_FILE,
) )
} }

View file

@ -54,6 +54,8 @@ pub unsafe extern "C" fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
0 0
} }
pub use crate::*; // import macros from `../../macros.rs`
// In case the c_char array doesn't end with NULL // In case the c_char array doesn't end with NULL
macro_rules! chars2string { macro_rules! chars2string {
($arr:expr) => { ($arr:expr) => {
@ -240,7 +242,7 @@ impl UtmpxIter {
utmpxname(cstr.as_ptr()) utmpxname(cstr.as_ptr())
}; };
if res != 0 { if res != 0 {
println!("Warning: {}", IOError::last_os_error()); show_warning!("utmpxname: {}", IOError::last_os_error());
} }
unsafe { unsafe {
setutxent(); setutxent();

View file

@ -20,7 +20,11 @@ fn test_long_format() {
let ulogin = "root"; let ulogin = "root";
let pw: Passwd = Passwd::locate(ulogin).unwrap(); let pw: Passwd = Passwd::locate(ulogin).unwrap();
let real_name = pw.user_info().replace("&", &pw.name().capitalize()); let real_name = pw.user_info().replace("&", &pw.name().capitalize());
new_ucmd!().arg("-l").arg(ulogin).run().stdout_is(format!( new_ucmd!()
.arg("-l")
.arg(ulogin)
.succeeds()
.stdout_is(format!(
"Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n", "Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n",
ulogin, ulogin,
real_name, real_name,
@ -28,34 +32,25 @@ fn test_long_format() {
pw.user_shell() pw.user_shell()
)); ));
new_ucmd!().arg("-lb").arg(ulogin).run().stdout_is(format!( new_ucmd!()
.arg("-lb")
.arg(ulogin)
.succeeds()
.stdout_is(format!(
"Login name: {:<28}In real life: {1}\n\n", "Login name: {:<28}In real life: {1}\n\n",
ulogin, real_name ulogin, real_name
)); ));
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_long_format_multiple_users() { fn test_long_format_multiple_users() {
let scene = TestScenario::new(util_name!()); let args = ["-l", "root", "root", "root"];
let expected = scene new_ucmd!()
.cmd_keepenv(util_name!()) .args(&args)
.env("LANGUAGE", "C")
.arg("-l")
.arg("root")
.arg("root")
.arg("root")
.succeeds();
scene
.ucmd()
.arg("-l")
.arg("root")
.arg("root")
.arg("root")
.succeeds() .succeeds()
.stdout_is(expected.stdout_str()); .stdout_is(expected_result(&args));
} }
#[test] #[test]
@ -64,63 +59,53 @@ fn test_long_format_wo_user() {
new_ucmd!().arg("-l").fails().code_is(1); new_ucmd!().arg("-l").fails().code_is(1);
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_short_format_i() { fn test_short_format_i() {
// allow whitespace variation // allow whitespace variation
// * minor whitespace differences occur between platform built-in outputs; specifically, the number of trailing TABs may be variant // * minor whitespace differences occur between platform built-in outputs; specifically, the number of trailing TABs may be variant
let args = ["-i"]; let args = ["-i"];
let actual = TestScenario::new(util_name!()) let actual = new_ucmd!().args(&args).succeeds().stdout_move_str();
.ucmd()
.args(&args)
.succeeds()
.stdout_move_str();
let expect = expected_result(&args); let expect = expected_result(&args);
let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_actual: Vec<&str> = actual.split_whitespace().collect();
let v_expect: Vec<&str> = expect.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect();
assert_eq!(v_actual, v_expect); assert_eq!(v_actual, v_expect);
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_short_format_q() { fn test_short_format_q() {
// allow whitespace variation // allow whitespace variation
// * minor whitespace differences occur between platform built-in outputs; specifically, the number of trailing TABs may be variant // * minor whitespace differences occur between platform built-in outputs; specifically, the number of trailing TABs may be variant
let args = ["-q"]; let args = ["-q"];
let actual = TestScenario::new(util_name!()) let actual = new_ucmd!().args(&args).succeeds().stdout_move_str();
.ucmd()
.args(&args)
.succeeds()
.stdout_move_str();
let expect = expected_result(&args); let expect = expected_result(&args);
let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_actual: Vec<&str> = actual.split_whitespace().collect();
let v_expect: Vec<&str> = expect.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect();
assert_eq!(v_actual, v_expect); assert_eq!(v_actual, v_expect);
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_no_flag() { fn test_no_flag() {
let scene = TestScenario::new(util_name!()); let actual = new_ucmd!().succeeds().stdout_move_str();
let expect = expected_result(&[]);
let actual = scene.ucmd().succeeds().stdout_move_str();
let expect = scene
.cmd_keepenv(util_name!())
.env("LANGUAGE", "C")
.succeeds()
.stdout_move_str();
let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_actual: Vec<&str> = actual.split_whitespace().collect();
let v_expect: Vec<&str> = expect.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect();
assert_eq!(v_actual, v_expect); assert_eq!(v_actual, v_expect);
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
fn expected_result(args: &[&str]) -> String { fn expected_result(args: &[&str]) -> String {
TestScenario::new(util_name!()) #[cfg(target_os = "linux")]
.cmd_keepenv(util_name!()) let util_name = util_name!();
#[cfg(target_vendor = "apple")]
let util_name = format!("g{}", util_name!());
TestScenario::new(&util_name)
.cmd_keepenv(util_name)
.env("LANGUAGE", "C") .env("LANGUAGE", "C")
.args(args) .args(args)
.run() .succeeds()
.stdout_move_str() .stdout_move_str()
} }

View file

@ -96,10 +96,10 @@ fn test_invalid_option() {
new_ucmd!().arg("-w").arg("-q").arg("/").fails(); new_ucmd!().arg("-w").arg("-q").arg("/").fails();
} }
#[cfg(target_os = "linux")] #[cfg(any(target_os = "linux", target_vendor = "apple"))]
const NORMAL_FMTSTR: &'static str = const NORMAL_FMTSTR: &'static str =
"%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s %u %U %x %X %y %Y %z %Z"; // avoid "%w %W" (birth/creation) due to `stat` limitations and linux kernel & rust version capability variations "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s %u %U %x %X %y %Y %z %Z"; // avoid "%w %W" (birth/creation) due to `stat` limitations and linux kernel & rust version capability variations
#[cfg(target_os = "linux")] #[cfg(any(target_os = "linux"))]
const DEV_FMTSTR: &'static str = const DEV_FMTSTR: &'static str =
"%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (%t/%T) %u %U %w %W %x %X %y %Y %z %Z"; "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (%t/%T) %u %U %w %W %x %X %y %Y %z %Z";
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -125,8 +125,8 @@ fn test_fs_format() {
.stdout_is(expected_result(&args)); .stdout_is(expected_result(&args));
} }
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test] #[test]
#[cfg(target_os = "linux")]
fn test_terse_normal_format() { fn test_terse_normal_format() {
// note: contains birth/creation date which increases test fragility // note: contains birth/creation date which increases test fragility
// * results may vary due to built-in `stat` limitations as well as linux kernel and rust version capability variations // * results may vary due to built-in `stat` limitations as well as linux kernel and rust version capability variations
@ -156,10 +156,10 @@ fn test_terse_normal_format() {
); );
} }
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test] #[test]
#[cfg(target_os = "linux")]
fn test_format_created_time() { fn test_format_created_time() {
let args = ["-c", "%w", "/boot"]; let args = ["-c", "%w", "/bin"];
let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); let actual = new_ucmd!().args(&args).succeeds().stdout_move_str();
let expect = expected_result(&args); let expect = expected_result(&args);
println!("actual: {:?}", actual); println!("actual: {:?}", actual);
@ -180,10 +180,10 @@ fn test_format_created_time() {
); );
} }
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test] #[test]
#[cfg(target_os = "linux")]
fn test_format_created_seconds() { fn test_format_created_seconds() {
let args = ["-c", "%W", "/boot"]; let args = ["-c", "%W", "/bin"];
let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); let actual = new_ucmd!().args(&args).succeeds().stdout_move_str();
let expect = expected_result(&args); let expect = expected_result(&args);
println!("actual: {:?}", actual); println!("actual: {:?}", actual);
@ -204,79 +204,97 @@ fn test_format_created_seconds() {
); );
} }
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test] #[test]
#[cfg(target_os = "linux")]
fn test_normal_format() { fn test_normal_format() {
let args = ["-c", NORMAL_FMTSTR, "/boot"]; let args = ["-c", NORMAL_FMTSTR, "/bin"];
new_ucmd!() new_ucmd!()
.args(&args) .args(&args)
.run() .succeeds()
.stdout_is(expected_result(&args)); .stdout_is(expected_result(&args));
} }
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test] #[test]
#[cfg(target_os = "linux")] fn test_symlinks() {
fn test_follow_symlink() { let scene = TestScenario::new(util_name!());
let args = ["-L", "-c", DEV_FMTSTR, "/dev/cdrom"]; let at = &scene.fixtures;
new_ucmd!()
let mut tested: bool = false;
// arbitrarily chosen symlinks with hope that the CI environment provides at least one of them
for file in vec![
"/bin/sh",
"/bin/sudoedit",
"/usr/bin/ex",
"/etc/localtime",
"/etc/aliases",
] {
if at.file_exists(file) && at.is_symlink(file) {
tested = true;
let args = ["-c", NORMAL_FMTSTR, file];
scene
.ucmd()
.args(&args) .args(&args)
.run() .succeeds()
.stdout_is(expected_result(&args));
// -L, --dereference follow links
let args = ["-L", "-c", NORMAL_FMTSTR, file];
scene
.ucmd()
.args(&args)
.succeeds()
.stdout_is(expected_result(&args)); .stdout_is(expected_result(&args));
} }
}
#[test] if !tested {
#[cfg(target_os = "linux")] panic!("No symlink found to test in this environment");
fn test_symlink() { }
let args = ["-c", DEV_FMTSTR, "/dev/cdrom"];
new_ucmd!()
.args(&args)
.run()
.stdout_is(expected_result(&args));
} }
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test] #[test]
#[cfg(target_os = "linux")]
fn test_char() { fn test_char() {
let args = ["-c", DEV_FMTSTR, "/dev/pts/ptmx"]; // TODO: "(%t) (%x) (%w)" deviate from GNU stat for `character special file` on macOS
// Diff < left / right > :
// <"(f0000) (2021-05-20 23:08:03.442555000 +0200) (1970-01-01 01:00:00.000000000 +0100)\n"
// >"(f) (2021-05-20 23:08:03.455598000 +0200) (-)\n"
let args = [
"-c",
#[cfg(target_os = "linux")]
DEV_FMTSTR,
#[cfg(target_os = "linux")]
"/dev/pts/ptmx",
#[cfg(any(target_vendor = "apple"))]
"%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (/%T) %u %U %W %X %y %Y %z %Z",
#[cfg(any(target_vendor = "apple"))]
"/dev/ptmx",
];
new_ucmd!() new_ucmd!()
.args(&args) .args(&args)
.run() .succeeds()
.stdout_is(expected_result(&args)); .stdout_is(expected_result(&args));
} }
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test] #[test]
#[cfg(target_os = "linux")]
fn test_multi_files() { fn test_multi_files() {
let args = [ let args = [
"-c", "-c",
NORMAL_FMTSTR, NORMAL_FMTSTR,
"/dev", "/dev",
"/usr/lib", "/usr/lib",
#[cfg(target_os = "linux")]
"/etc/fstab", "/etc/fstab",
"/var", "/var",
]; ];
new_ucmd!() new_ucmd!()
.args(&args) .args(&args)
.run() .succeeds()
.stdout_is(expected_result(&args)); .stdout_is(expected_result(&args));
} }
#[cfg(any(target_os = "linux", target_os = "freebsd", target_vendor = "apple"))] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_one_file() {
let (at, mut ucmd) = at_and_ucmd!();
let file = "TEST_FILE.mp4";
at.touch(file);
ucmd.arg(file)
.succeeds()
.stdout_contains(format!("File: `{}'", file))
.stdout_contains(format!("Size: 0"))
.stdout_contains(format!("Access: (0644/-rw-r--r--)"));
}
#[test]
#[cfg(target_os = "linux")]
fn test_printf() { fn test_printf() {
let args = [ let args = [
"--printf=123%-# 15q\\r\\\"\\\\\\a\\b\\e\\f\\v%+020.23m\\x12\\167\\132\\112\\n", "--printf=123%-# 15q\\r\\\"\\\\\\a\\b\\e\\f\\v%+020.23m\\x12\\167\\132\\112\\n",
@ -284,16 +302,21 @@ fn test_printf() {
]; ];
new_ucmd!() new_ucmd!()
.args(&args) .args(&args)
.run() .succeeds()
.stdout_is(expected_result(&args)); .stdout_is(expected_result(&args));
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
fn expected_result(args: &[&str]) -> String { fn expected_result(args: &[&str]) -> String {
TestScenario::new(util_name!()) #[cfg(target_os = "linux")]
.cmd_keepenv(util_name!()) let util_name = util_name!();
#[cfg(target_vendor = "apple")]
let util_name = format!("g{}", util_name!());
TestScenario::new(&util_name)
.cmd_keepenv(util_name)
.env("LANGUAGE", "C") .env("LANGUAGE", "C")
.args(args) .args(args)
.run() .succeeds()
.stdout_move_str() .stdout_move_str()
} }

View file

@ -1,28 +1,28 @@
use crate::common::util::*; use crate::common::util::*;
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_count() { fn test_count() {
for opt in vec!["-q", "--count"] { for opt in vec!["-q", "--count"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_boot() { fn test_boot() {
for opt in vec!["-b", "--boot"] { for opt in vec!["-b", "--boot"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_heading() { fn test_heading() {
for opt in vec!["-H", "--heading"] { for opt in vec!["-H", "--heading"] {
@ -30,7 +30,7 @@ fn test_heading() {
// * minor whitespace differences occur between platform built-in outputs; // * minor whitespace differences occur between platform built-in outputs;
// specifically number of TABs between "TIME" and "COMMENT" may be variant // specifically number of TABs between "TIME" and "COMMENT" may be variant
let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str(); let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str();
let expect = expected_result(opt); let expect = expected_result(&[opt]);
println!("actual: {:?}", actual); println!("actual: {:?}", actual);
println!("expect: {:?}", expect); println!("expect: {:?}", expect);
let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_actual: Vec<&str> = actual.split_whitespace().collect();
@ -39,205 +39,205 @@ fn test_heading() {
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_short() { fn test_short() {
for opt in vec!["-s", "--short"] { for opt in vec!["-s", "--short"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_login() { fn test_login() {
for opt in vec!["-l", "--login"] { for opt in vec!["-l", "--login"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_m() { fn test_m() {
for opt in vec!["-m"] { for opt in vec!["-m"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_process() { fn test_process() {
for opt in vec!["-p", "--process"] { for opt in vec!["-p", "--process"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_runlevel() { fn test_runlevel() {
for opt in vec!["-r", "--runlevel"] { for opt in vec!["-r", "--runlevel"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_time() { fn test_time() {
for opt in vec!["-t", "--time"] { for opt in vec!["-t", "--time"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_mesg() { fn test_mesg() {
for opt in vec!["-w", "-T", "--users", "--message", "--writable"] { // -T, -w, --mesg
// add user's message status as +, - or ?
// --message
// same as -T
// --writable
// same as -T
for opt in vec!["-T", "-w", "--mesg", "--message", "--writable"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")]
#[test] #[test]
fn test_arg1_arg2() { fn test_arg1_arg2() {
let scene = TestScenario::new(util_name!()); let args = ["am", "i"];
let expected = scene new_ucmd!()
.cmd_keepenv(util_name!()) .args(&args)
.env("LANGUAGE", "C")
.arg("am")
.arg("i")
.succeeds();
scene
.ucmd()
.arg("am")
.arg("i")
.succeeds() .succeeds()
.stdout_is(expected.stdout_str()); .stdout_is(expected_result(&args));
} }
#[test] #[test]
fn test_too_many_args() { fn test_too_many_args() {
let expected = const EXPECTED: &str =
"error: The value 'u' was provided to '<FILE>...', but it wasn't expecting any more values"; "error: The value 'u' was provided to '<FILE>...', but it wasn't expecting any more values";
new_ucmd!() let args = ["am", "i", "u"];
.arg("am") new_ucmd!().args(&args).fails().stderr_contains(EXPECTED);
.arg("i")
.arg("u")
.fails()
.stderr_contains(expected);
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_users() { fn test_users() {
for opt in vec!["-u", "--users"] { for opt in vec!["-u", "--users"] {
new_ucmd!() let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str();
.arg(opt) let expect = expected_result(&[opt]);
.succeeds() println!("actual: {:?}", actual);
.stdout_is(expected_result(opt)); println!("expect: {:?}", expect);
let mut v_actual: Vec<&str> = actual.split_whitespace().collect();
let mut v_expect: Vec<&str> = expect.split_whitespace().collect();
// TODO: `--users` differs from GNU's output on manOS running in CI
// Diff < left / right > :
// <"runner console 2021-05-20 22:03 00:08 196\n"
// >"runner console 2021-05-20 22:03 old 196\n"
if is_ci() && cfg!(target_os = "macos") {
v_actual.remove(4);
v_expect.remove(4);
}
assert_eq!(v_actual, v_expect);
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_lookup() { fn test_lookup() {
for opt in vec!["--lookup"] { for opt in vec!["--lookup"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_dead() { fn test_dead() {
for opt in vec!["-d", "--dead"] { for opt in vec!["-d", "--dead"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_all_separately() { fn test_all_separately() {
if is_ci() && cfg!(target_os = "macos") {
// TODO: fix `-u`, see: test_users
return;
}
// -a, --all same as -b -d --login -p -r -t -T -u // -a, --all same as -b -d --login -p -r -t -T -u
let args = ["-b", "-d", "--login", "-p", "-r", "-t", "-T", "-u"];
let scene = TestScenario::new(util_name!()); let scene = TestScenario::new(util_name!());
let expected = scene
.cmd_keepenv(util_name!())
.env("LANGUAGE", "C")
.arg("-b")
.arg("-d")
.arg("--login")
.arg("-p")
.arg("-r")
.arg("-t")
.arg("-T")
.arg("-u")
.succeeds();
scene scene
.ucmd() .ucmd()
.arg("-b") .args(&args)
.arg("-d")
.arg("--login")
.arg("-p")
.arg("-r")
.arg("-t")
.arg("-T")
.arg("-u")
.succeeds() .succeeds()
.stdout_is(expected.stdout_str()); .stdout_is(expected_result(&args));
scene scene
.ucmd() .ucmd()
.arg("--all") .arg("--all")
.succeeds() .succeeds()
.stdout_is(expected.stdout_str()); .stdout_is(expected_result(&args));
} }
#[cfg(target_os = "linux")] #[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[test] #[test]
fn test_all() { fn test_all() {
if is_ci() && cfg!(target_os = "macos") {
// TODO: fix `-u`, see: test_users
return;
}
for opt in vec!["-a", "--all"] { for opt in vec!["-a", "--all"] {
new_ucmd!() new_ucmd!()
.arg(opt) .arg(opt)
.succeeds() .succeeds()
.stdout_is(expected_result(opt)); .stdout_is(expected_result(&[opt]));
} }
} }
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
fn expected_result(args: &[&str]) -> String {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn expected_result(arg: &str) -> String { let util_name = util_name!();
TestScenario::new(util_name!()) #[cfg(target_vendor = "apple")]
.cmd_keepenv(util_name!()) let util_name = format!("g{}", util_name!());
TestScenario::new(&util_name)
.cmd_keepenv(util_name)
.env("LANGUAGE", "C") .env("LANGUAGE", "C")
.args(&[arg]) .args(args)
.succeeds() .succeeds()
.stdout_move_str() .stdout_move_str()
} }