diff --git a/src/uu/stat/src/stat.rs b/src/uu/stat/src/stat.rs index 8b148d39d..5bb0e5f12 100644 --- a/src/uu/stat/src/stat.rs +++ b/src/uu/stat/src/stat.rs @@ -657,7 +657,7 @@ impl Stater { dst.to_string_lossy() ); } else { - arg = format!("`{}'", file); + arg = file.to_string(); } otype = OutputType::Str; } diff --git a/src/uu/who/src/who.rs b/src/uu/who/src/who.rs index aef23b3a2..1ae4f1c8d 100644 --- a/src/uu/who/src/who.rs +++ b/src/uu/who/src/who.rs @@ -46,9 +46,10 @@ fn get_usage() -> String { } fn get_long_usage() -> String { - String::from( - "If FILE is not specified, use /var/run/utmp. /var/log/wtmp as FILE is common.\n\ -If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.", + format!( + "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.", + utmpx::DEFAULT_FILE, ) } diff --git a/src/uucore/src/lib/features/utmpx.rs b/src/uucore/src/lib/features/utmpx.rs index 96db33c35..826831ba6 100644 --- a/src/uucore/src/lib/features/utmpx.rs +++ b/src/uucore/src/lib/features/utmpx.rs @@ -54,6 +54,8 @@ pub unsafe extern "C" fn utmpxname(_file: *const libc::c_char) -> libc::c_int { 0 } +pub use crate::*; // import macros from `../../macros.rs` + // In case the c_char array doesn't end with NULL macro_rules! chars2string { ($arr:expr) => { @@ -240,7 +242,7 @@ impl UtmpxIter { utmpxname(cstr.as_ptr()) }; if res != 0 { - println!("Warning: {}", IOError::last_os_error()); + show_warning!("utmpxname: {}", IOError::last_os_error()); } unsafe { setutxent(); diff --git a/tests/by-util/test_pinky.rs b/tests/by-util/test_pinky.rs index 904a05f93..ccabb7345 100644 --- a/tests/by-util/test_pinky.rs +++ b/tests/by-util/test_pinky.rs @@ -20,42 +20,37 @@ fn test_long_format() { let ulogin = "root"; let pw: Passwd = Passwd::locate(ulogin).unwrap(); let real_name = pw.user_info().replace("&", &pw.name().capitalize()); - new_ucmd!().arg("-l").arg(ulogin).run().stdout_is(format!( - "Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n", - ulogin, - real_name, - pw.user_dir(), - pw.user_shell() - )); + new_ucmd!() + .arg("-l") + .arg(ulogin) + .succeeds() + .stdout_is(format!( + "Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n", + ulogin, + real_name, + pw.user_dir(), + pw.user_shell() + )); - new_ucmd!().arg("-lb").arg(ulogin).run().stdout_is(format!( - "Login name: {:<28}In real life: {1}\n\n", - ulogin, real_name - )); + new_ucmd!() + .arg("-lb") + .arg(ulogin) + .succeeds() + .stdout_is(format!( + "Login name: {:<28}In real life: {1}\n\n", + ulogin, real_name + )); } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_long_format_multiple_users() { - let scene = TestScenario::new(util_name!()); + let args = ["-l", "root", "root", "root"]; - let expected = scene - .cmd_keepenv(util_name!()) - .env("LANGUAGE", "C") - .arg("-l") - .arg("root") - .arg("root") - .arg("root") - .succeeds(); - - scene - .ucmd() - .arg("-l") - .arg("root") - .arg("root") - .arg("root") + new_ucmd!() + .args(&args) .succeeds() - .stdout_is(expected.stdout_str()); + .stdout_is(expected_result(&args)); } #[test] @@ -64,63 +59,53 @@ fn test_long_format_wo_user() { new_ucmd!().arg("-l").fails().code_is(1); } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_short_format_i() { // allow whitespace variation // * minor whitespace differences occur between platform built-in outputs; specifically, the number of trailing TABs may be variant let args = ["-i"]; - let actual = TestScenario::new(util_name!()) - .ucmd() - .args(&args) - .succeeds() - .stdout_move_str(); + let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); let expect = expected_result(&args); let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect(); assert_eq!(v_actual, v_expect); } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_short_format_q() { // allow whitespace variation // * minor whitespace differences occur between platform built-in outputs; specifically, the number of trailing TABs may be variant let args = ["-q"]; - let actual = TestScenario::new(util_name!()) - .ucmd() - .args(&args) - .succeeds() - .stdout_move_str(); + let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); let expect = expected_result(&args); let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect(); assert_eq!(v_actual, v_expect); } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_no_flag() { - let scene = TestScenario::new(util_name!()); - - let actual = scene.ucmd().succeeds().stdout_move_str(); - let expect = scene - .cmd_keepenv(util_name!()) - .env("LANGUAGE", "C") - .succeeds() - .stdout_move_str(); - + let actual = new_ucmd!().succeeds().stdout_move_str(); + let expect = expected_result(&[]); let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect(); assert_eq!(v_actual, v_expect); } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] fn expected_result(args: &[&str]) -> String { - TestScenario::new(util_name!()) - .cmd_keepenv(util_name!()) + #[cfg(target_os = "linux")] + 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") .args(args) - .run() + .succeeds() .stdout_move_str() } diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 308dcb9f5..44bce9cd8 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -96,10 +96,10 @@ fn test_invalid_option() { 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 = "%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 = "%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")] @@ -125,8 +125,8 @@ fn test_fs_format() { .stdout_is(expected_result(&args)); } +#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[test] -#[cfg(target_os = "linux")] fn test_terse_normal_format() { // 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 @@ -156,10 +156,10 @@ fn test_terse_normal_format() { ); } +#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[test] -#[cfg(target_os = "linux")] 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 expect = expected_result(&args); println!("actual: {:?}", actual); @@ -180,10 +180,10 @@ fn test_format_created_time() { ); } +#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[test] -#[cfg(target_os = "linux")] 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 expect = expected_result(&args); println!("actual: {:?}", actual); @@ -204,79 +204,97 @@ fn test_format_created_seconds() { ); } +#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[test] -#[cfg(target_os = "linux")] fn test_normal_format() { - let args = ["-c", NORMAL_FMTSTR, "/boot"]; + let args = ["-c", NORMAL_FMTSTR, "/bin"]; new_ucmd!() .args(&args) - .run() + .succeeds() .stdout_is(expected_result(&args)); } +#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[test] -#[cfg(target_os = "linux")] -fn test_follow_symlink() { - let args = ["-L", "-c", DEV_FMTSTR, "/dev/cdrom"]; - new_ucmd!() - .args(&args) - .run() - .stdout_is(expected_result(&args)); +fn test_symlinks() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + + 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) + .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)); + } + } + if !tested { + panic!("No symlink found to test in this environment"); + } } +#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[test] -#[cfg(target_os = "linux")] -fn test_symlink() { - let args = ["-c", DEV_FMTSTR, "/dev/cdrom"]; - new_ucmd!() - .args(&args) - .run() - .stdout_is(expected_result(&args)); -} - -#[test] -#[cfg(target_os = "linux")] 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!() .args(&args) - .run() + .succeeds() .stdout_is(expected_result(&args)); } +#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[test] -#[cfg(target_os = "linux")] fn test_multi_files() { let args = [ "-c", NORMAL_FMTSTR, "/dev", "/usr/lib", + #[cfg(target_os = "linux")] "/etc/fstab", "/var", ]; new_ucmd!() .args(&args) - .run() + .succeeds() .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] -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() { let args = [ "--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!() .args(&args) - .run() + .succeeds() .stdout_is(expected_result(&args)); } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] fn expected_result(args: &[&str]) -> String { - TestScenario::new(util_name!()) - .cmd_keepenv(util_name!()) + #[cfg(target_os = "linux")] + 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") .args(args) - .run() + .succeeds() .stdout_move_str() } diff --git a/tests/by-util/test_who.rs b/tests/by-util/test_who.rs index a5637f23a..725ec0b1e 100644 --- a/tests/by-util/test_who.rs +++ b/tests/by-util/test_who.rs @@ -1,28 +1,28 @@ use crate::common::util::*; -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_count() { for opt in vec!["-q", "--count"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_boot() { for opt in vec!["-b", "--boot"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_heading() { for opt in vec!["-H", "--heading"] { @@ -30,7 +30,7 @@ fn test_heading() { // * minor whitespace differences occur between platform built-in outputs; // specifically number of TABs between "TIME" and "COMMENT" may be variant let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str(); - let expect = expected_result(opt); + let expect = expected_result(&[opt]); println!("actual: {:?}", actual); println!("expect: {:?}", expect); 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] fn test_short() { for opt in vec!["-s", "--short"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_login() { for opt in vec!["-l", "--login"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_m() { for opt in vec!["-m"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_process() { for opt in vec!["-p", "--process"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_runlevel() { for opt in vec!["-r", "--runlevel"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_time() { for opt in vec!["-t", "--time"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] 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!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] #[test] fn test_arg1_arg2() { - let scene = TestScenario::new(util_name!()); + let args = ["am", "i"]; - let expected = scene - .cmd_keepenv(util_name!()) - .env("LANGUAGE", "C") - .arg("am") - .arg("i") - .succeeds(); - - scene - .ucmd() - .arg("am") - .arg("i") + new_ucmd!() + .args(&args) .succeeds() - .stdout_is(expected.stdout_str()); + .stdout_is(expected_result(&args)); } #[test] fn test_too_many_args() { - let expected = + const EXPECTED: &str = "error: The value 'u' was provided to '...', but it wasn't expecting any more values"; - new_ucmd!() - .arg("am") - .arg("i") - .arg("u") - .fails() - .stderr_contains(expected); + let args = ["am", "i", "u"]; + new_ucmd!().args(&args).fails().stderr_contains(EXPECTED); } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_users() { for opt in vec!["-u", "--users"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(opt)); + let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str(); + let expect = expected_result(&[opt]); + println!("actual: {:?}", actual); + 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] fn test_lookup() { for opt in vec!["--lookup"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_dead() { for opt in vec!["-d", "--dead"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] 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 + let args = ["-b", "-d", "--login", "-p", "-r", "-t", "-T", "-u"]; 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 .ucmd() - .arg("-b") - .arg("-d") - .arg("--login") - .arg("-p") - .arg("-r") - .arg("-t") - .arg("-T") - .arg("-u") + .args(&args) .succeeds() - .stdout_is(expected.stdout_str()); - + .stdout_is(expected_result(&args)); scene .ucmd() .arg("--all") .succeeds() - .stdout_is(expected.stdout_str()); + .stdout_is(expected_result(&args)); } -#[cfg(target_os = "linux")] +#[cfg(any(target_vendor = "apple", target_os = "linux"))] #[test] fn test_all() { + if is_ci() && cfg!(target_os = "macos") { + // TODO: fix `-u`, see: test_users + return; + } + for opt in vec!["-a", "--all"] { new_ucmd!() .arg(opt) .succeeds() - .stdout_is(expected_result(opt)); + .stdout_is(expected_result(&[opt])); } } -#[cfg(target_os = "linux")] -fn expected_result(arg: &str) -> String { - TestScenario::new(util_name!()) - .cmd_keepenv(util_name!()) +#[cfg(any(target_vendor = "apple", target_os = "linux"))] +fn expected_result(args: &[&str]) -> String { + #[cfg(target_os = "linux")] + 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") - .args(&[arg]) + .args(args) .succeeds() .stdout_move_str() }