From c447863c8da01306f39db6e28e70663b26e8996b Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 7 Jul 2021 14:30:38 +0200 Subject: [PATCH 01/10] tests/common: refactor to reduce duplicate code * move fn expected_result to common/util.rs * move fn check_coreutil_version to common/util.rs * move fn whoami to common/util.rs * move macro unwrap_or_return to common/macros.rs * add documentation * add tests --- tests/common/macros.rs | 16 ++++ tests/common/util.rs | 198 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 213 insertions(+), 1 deletion(-) diff --git a/tests/common/macros.rs b/tests/common/macros.rs index 03d2051d0..2a1c20af2 100644 --- a/tests/common/macros.rs +++ b/tests/common/macros.rs @@ -66,3 +66,19 @@ macro_rules! at_and_ucmd { (ts.fixtures.clone(), ts.ucmd()) }}; } + +/// If `common::util::expected_result` returns an error, i.e. the `util` in `$PATH` doesn't +/// include a coreutils version string or the version is too low, +/// this macro can be used to automatically skip the test and print the reason. +#[macro_export] +macro_rules! unwrap_or_return { + ( $e:expr ) => { + match $e { + Ok(x) => x, + Err(e) => { + println!("test skipped: {}", e); + return; + } + } + }; +} diff --git a/tests/common/util.rs b/tests/common/util.rs index f881cff21..79af471e3 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1,10 +1,11 @@ -//spell-checker: ignore (linux) rlimit prlimit Rlim +//spell-checker: ignore (linux) rlimit prlimit Rlim coreutil #![allow(dead_code)] use pretty_assertions::assert_eq; #[cfg(target_os = "linux")] use rlimit::{prlimit, rlim}; +use std::borrow::Cow; use std::env; #[cfg(not(windows))] use std::ffi::CString; @@ -1036,6 +1037,179 @@ pub fn vec_of_size(n: usize) -> Vec { result } +pub fn whoami() -> String { + // Apparently some CI environments have configuration issues, e.g. with 'whoami' and 'id'. + // + // From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)" + // whoami: cannot find name for user ID 1001 + // id --name: cannot find name for user ID 1001 + // id --name: cannot find name for group ID 116 + // + // However, when running "id" from within "/bin/bash" it looks fine: + // id: "uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),101(systemd-journal)" + // whoami: "runner" + + // Use environment variable to get current user instead of + // invoking `whoami` and fall back to user "nobody" on error. + std::env::var("USER").unwrap_or_else(|e| { + println!("{}: {}, using \"nobody\" instead", UUTILS_WARNING, e); + "nobody".to_string() + }) +} + +/// Add prefix 'g' for `util_name` if not on linux +#[cfg(unix)] +pub fn host_name_for<'a>(util_name: &'a str) -> Cow<'a, str> { + // In some environments, e.g. macOS/freebsd, the GNU coreutils are prefixed with "g" + // to not interfere with the BSD counterparts already in `$PATH`. + #[cfg(not(target_os = "linux"))] + return format!("g{}", util_name).into(); + #[cfg(target_os = "linux")] + return util_name.into(); +} + +// GNU coreutils version 8.32 is the reference version since it is the latest version and the +// GNU test suite in "coreutils/.github/workflows/GnuTests.yml" runs against it. +// However, here 8.30 was chosen because right now there's no ubuntu image for the github actions +// CICD available with a higher version than 8.30. +// GNU coreutils versions from the CICD images for comparison: +// ubuntu-2004: 8.30 (latest) +// ubuntu-1804: 8.28 +// macos-latest: 8.32 +const VERSION_MIN: &str = "8.30"; // minimum Version for the reference `coreutil` in `$PATH` + +const UUTILS_WARNING: &str = "uutils-tests-warning"; +const UUTILS_INFO: &str = "uutils-tests-info"; + +/// Run `util_name --version` and return Ok if the version is >= `version_expected`. +/// Returns an error if +/// * `util_name` cannot run +/// * the version cannot be parsed +/// * the version is too low +/// +/// This is used by `expected_result` to check if the coreutils version is >= `VERSION_MIN`. +/// It makes sense to use this manually in a test if a feature +/// is tested that was introduced after `VERSION_MIN` +/// +/// Example: +/// +/// ```no_run +/// use crate::common::util::*; +/// const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; +/// +/// #[test] +/// fn test_xyz() { +/// unwrap_or_return!(check_coreutil_version( +/// util_name!(), +/// VERSION_MIN_MULTIPLE_USERS +/// )); +/// // proceed with the test... +/// } +/// ``` +#[cfg(unix)] +pub fn check_coreutil_version( + util_name: &str, + version_expected: &str, +) -> std::result::Result { + // example: + // $ id --version | head -n 1 + // id (GNU coreutils) 8.32.162-4eda + + let util_name = &host_name_for(util_name); + log_info("run", format!("{} --version", util_name)); + let version_check = match Command::new(util_name.as_ref()) + .env("LC_ALL", "C") + .arg("--version") + .output() + { + Ok(s) => s, + Err(e) => { + return Err(format!( + "{}: '{}' {}", + UUTILS_WARNING, + util_name, + e.to_string() + )) + } + }; + std::str::from_utf8(&version_check.stdout).unwrap() + .split('\n') + .collect::>() + .get(0) + .map_or_else( + || Err(format!("{}: unexpected output format for reference coreutil: '{} --version'", UUTILS_WARNING, util_name)), + |s| { + if s.contains(&format!("(GNU coreutils) {}", version_expected)) { + Ok(format!("{}: {}", UUTILS_INFO, s.to_string())) + } else if s.contains("(GNU coreutils)") { + let version_found = s.split_whitespace().last().unwrap()[..4].parse::().unwrap_or_default(); + let version_expected = version_expected.parse::().unwrap_or_default(); + if version_found > version_expected { + Ok(format!("{}: version for the reference coreutil '{}' is higher than expected; expected: {}, found: {}", UUTILS_INFO, util_name, version_expected, version_found)) + } else { + Err(format!("{}: version for the reference coreutil '{}' does not match; expected: {}, found: {}", UUTILS_WARNING, util_name, version_expected, version_found)) } + } else { + Err(format!("{}: no coreutils version string found for reference coreutils '{} --version'", UUTILS_WARNING, util_name)) + } + }, + ) +} + +/// This runs the GNU coreutils `util_name` binary in `$PATH` in order to +/// dynamically gather reference values on the system. +/// If the `util_name` in `$PATH` doesn't include a coreutils version string, +/// or the version is too low, this returns an error and the test should be skipped. +/// +/// Example: +/// +/// ```no_run +/// use crate::common::util::*; +/// #[test] +/// fn test_xyz() { +/// let result = new_ucmd!().run(); +/// let exp_result = unwrap_or_return!(expected_result(util_name!(), &[])); +/// result +/// .stdout_is(exp_result.stdout_str()) +/// .stderr_is(exp_result.stderr_str()) +/// .code_is(exp_result.code()); +/// } +///``` +#[cfg(unix)] +pub fn expected_result(util_name: &str, args: &[&str]) -> std::result::Result { + let util_name = &host_name_for(util_name); + println!("{}", check_coreutil_version(util_name, VERSION_MIN)?); + + let scene = TestScenario::new(util_name); + let result = scene + .cmd_keepenv(util_name.as_ref()) + .env("LC_ALL", "C") + .args(args) + .run(); + + let (stdout, stderr): (String, String) = if cfg!(target_os = "linux") { + ( + result.stdout_str().to_string(), + result.stderr_str().to_string(), + ) + } else { + // `host_name_for` added prefix, strip 'g' prefix from results: + let from = util_name.to_string() + ":"; + let to = &from[1..]; + ( + result.stdout_str().replace(&from, to), + result.stderr_str().replace(&from, to), + ) + }; + + Ok(CmdResult::new( + Some(result.tmpd()), + Some(result.code()), + result.succeeded(), + stdout.as_bytes(), + stderr.as_bytes(), + )) +} + /// Sanity checks for test utils #[cfg(test)] mod tests { @@ -1272,4 +1446,26 @@ mod tests { res.normalized_newlines_stdout_is("A\r\nB\nC\n"); } + + #[test] + #[cfg(unix)] + fn test_check_coreutil_version() { + match check_coreutil_version("id", VERSION_MIN) { + Ok(s) => s.starts_with("uutils-tests-"), + Err(s) => s.starts_with("uutils-tests-warning"), + }; + std::assert_eq!( + check_coreutil_version("no test name", VERSION_MIN), + Err("uutils-tests-warning: 'no test name' \ + No such file or directory (os error 2)" + .to_string()) + ); + } + + #[test] + #[cfg(unix)] + fn test_expected_result() { + assert!(expected_result("id", &[]).is_ok()); + assert!(expected_result("no test name", &[]).is_err()); + } } From 9631d8cf2b1cfb6612c00a2995e88d23a309dcaf Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 7 Jul 2021 15:52:56 +0200 Subject: [PATCH 02/10] test_groups: refactor use expected_result from common/util.rs --- tests/by-util/test_groups.rs | 143 ++--------------------------------- 1 file changed, 7 insertions(+), 136 deletions(-) diff --git a/tests/by-util/test_groups.rs b/tests/by-util/test_groups.rs index 9bd0cd12a..9cebdf878 100644 --- a/tests/by-util/test_groups.rs +++ b/tests/by-util/test_groups.rs @@ -1,55 +1,12 @@ use crate::common::util::*; -// spell-checker:ignore (ToDO) coreutil - -// These tests run the GNU coreutils `(g)groups` binary in `$PATH` in order to gather reference values. -// If the `(g)groups` in `$PATH` doesn't include a coreutils version string, -// or the version is too low, the test is skipped. - -// The reference version is 8.32. Here 8.30 was chosen because right now there's no -// ubuntu image for github action available with a higher version than 8.30. -const VERSION_MIN: &str = "8.30"; // minimum Version for the reference `groups` in $PATH const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced in GNU's coreutils 8.31 -const UUTILS_WARNING: &str = "uutils-tests-warning"; -const UUTILS_INFO: &str = "uutils-tests-info"; - -macro_rules! unwrap_or_return { - ( $e:expr ) => { - match $e { - Ok(x) => x, - Err(e) => { - println!("{}: test skipped: {}", UUTILS_INFO, e); - return; - } - } - }; -} - -fn whoami() -> String { - // Apparently some CI environments have configuration issues, e.g. with 'whoami' and 'id'. - // - // From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)" - // whoami: cannot find name for user ID 1001 - // id --name: cannot find name for user ID 1001 - // id --name: cannot find name for group ID 116 - // - // However, when running "id" from within "/bin/bash" it looks fine: - // id: "uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),101(systemd-journal)" - // whoami: "runner" - - // Use environment variable to get current user instead of - // invoking `whoami` and fall back to user "nobody" on error. - std::env::var("USER").unwrap_or_else(|e| { - println!("{}: {}, using \"nobody\" instead", UUTILS_WARNING, e); - "nobody".to_string() - }) -} #[test] #[cfg(unix)] fn test_groups() { let result = new_ucmd!().run(); - let exp_result = unwrap_or_return!(expected_result(&[])); + let exp_result = unwrap_or_return!(expected_result(util_name!(), &[])); result .stdout_is(exp_result.stdout_str()) @@ -63,7 +20,7 @@ fn test_groups_username() { let test_users = [&whoami()[..]]; let result = new_ucmd!().args(&test_users).run(); - let exp_result = unwrap_or_return!(expected_result(&test_users)); + let exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); result .stdout_is(exp_result.stdout_str()) @@ -74,103 +31,17 @@ fn test_groups_username() { #[test] #[cfg(unix)] fn test_groups_username_multiple() { - // TODO: [2021-06; jhscheer] refactor this as `let util_name = host_name_for(util_name!())` when that function is added to 'tests/common' - #[cfg(target_os = "linux")] - let util_name = util_name!(); - #[cfg(all(unix, not(target_os = "linux")))] - let util_name = &format!("g{}", util_name!()); - let version_check_string = check_coreutil_version(util_name, VERSION_MIN_MULTIPLE_USERS); - if version_check_string.starts_with(UUTILS_WARNING) { - println!("{}\ntest skipped", version_check_string); - return; - } + unwrap_or_return!(check_coreutil_version( + util_name!(), + VERSION_MIN_MULTIPLE_USERS + )); let test_users = ["root", "man", "postfix", "sshd", &whoami()]; let result = new_ucmd!().args(&test_users).run(); - let exp_result = unwrap_or_return!(expected_result(&test_users)); + let exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) .code_is(exp_result.code()); } - -fn check_coreutil_version(util_name: &str, version_expected: &str) -> String { - // example: - // $ id --version | head -n 1 - // id (GNU coreutils) 8.32.162-4eda - let scene = TestScenario::new(util_name); - let version_check = scene - .cmd_keepenv(&util_name) - .env("LC_ALL", "C") - .arg("--version") - .run(); - version_check - .stdout_str() - .split('\n') - .collect::>() - .get(0) - .map_or_else( - || format!("{}: unexpected output format for reference coreutil: '{} --version'", UUTILS_WARNING, util_name), - |s| { - if s.contains(&format!("(GNU coreutils) {}", version_expected)) { - s.to_string() - } else if s.contains("(GNU coreutils)") { - let version_found = s.split_whitespace().last().unwrap()[..4].parse::().unwrap_or_default(); - let version_expected = version_expected.parse::().unwrap_or_default(); - if version_found > version_expected { - format!("{}: version for the reference coreutil '{}' is higher than expected; expected: {}, found: {}", UUTILS_INFO, util_name, version_expected, version_found) - } else { - format!("{}: version for the reference coreutil '{}' does not match; expected: {}, found: {}", UUTILS_WARNING, util_name, version_expected, version_found) } - } else { - format!("{}: no coreutils version string found for reference coreutils '{} --version'", UUTILS_WARNING, util_name) - } - }, - ) -} - -#[allow(clippy::needless_borrow)] -#[cfg(unix)] -fn expected_result(args: &[&str]) -> Result { - // TODO: [2021-06; jhscheer] refactor this as `let util_name = host_name_for(util_name!())` when that function is added to 'tests/common' - #[cfg(target_os = "linux")] - let util_name = util_name!(); - #[cfg(all(unix, not(target_os = "linux")))] - let util_name = &format!("g{}", util_name!()); - - let version_check_string = check_coreutil_version(util_name, VERSION_MIN); - if version_check_string.starts_with(UUTILS_WARNING) { - return Err(version_check_string); - } - println!("{}", version_check_string); - - let scene = TestScenario::new(util_name); - let result = scene - .cmd_keepenv(util_name) - .env("LC_ALL", "C") - .args(args) - .run(); - - let (stdout, stderr): (String, String) = if cfg!(target_os = "linux") { - ( - result.stdout_str().to_string(), - result.stderr_str().to_string(), - ) - } else { - // strip 'g' prefix from results: - let from = util_name.to_string() + ":"; - let to = &from[1..]; - ( - result.stdout_str().replace(&from, to), - result.stderr_str().replace(&from, to), - ) - }; - - Ok(CmdResult::new( - Some(result.tmpd()), - Some(result.code()), - result.succeeded(), - stdout.as_bytes(), - stderr.as_bytes(), - )) -} From c2bd7ae9b1be95ec4ae4197a37790eb58093eeb1 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 7 Jul 2021 15:53:26 +0200 Subject: [PATCH 03/10] test_id: refactor use expected_result from common/util.rs --- tests/by-util/test_id.rs | 198 +++++++-------------------------------- 1 file changed, 34 insertions(+), 164 deletions(-) diff --git a/tests/by-util/test_id.rs b/tests/by-util/test_id.rs index bacf57037..6c6f168fe 100644 --- a/tests/by-util/test_id.rs +++ b/tests/by-util/test_id.rs @@ -2,54 +2,13 @@ use crate::common::util::*; // spell-checker:ignore (ToDO) coreutil -// These tests run the GNU coreutils `(g)id` binary in `$PATH` in order to gather reference values. -// If the `(g)id` in `$PATH` doesn't include a coreutils version string, -// or the version is too low, the test is skipped. - -// The reference version is 8.32. Here 8.30 was chosen because right now there's no -// ubuntu image for github action available with a higher version than 8.30. -const VERSION_MIN: &str = "8.30"; // minimum Version for the reference `id` in $PATH const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced in GNU's coreutils 8.31 -const UUTILS_WARNING: &str = "uutils-tests-warning"; -const UUTILS_INFO: &str = "uutils-tests-info"; - -macro_rules! unwrap_or_return { - ( $e:expr ) => { - match $e { - Ok(x) => x, - Err(e) => { - println!("{}: test skipped: {}", UUTILS_INFO, e); - return; - } - } - }; -} - -fn whoami() -> String { - // Apparently some CI environments have configuration issues, e.g. with 'whoami' and 'id'. - // - // From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)" - // whoami: cannot find name for user ID 1001 - // id --name: cannot find name for user ID 1001 - // id --name: cannot find name for group ID 116 - // - // However, when running "id" from within "/bin/bash" it looks fine: - // id: "uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),101(systemd-journal)" - // whoami: "runner" - - // Use environment variable to get current user instead of - // invoking `whoami` and fall back to user "nobody" on error. - std::env::var("USER").unwrap_or_else(|e| { - println!("{}: {}, using \"nobody\" instead", UUTILS_WARNING, e); - "nobody".to_string() - }) -} #[test] #[cfg(unix)] fn test_id_no_specified_user() { let result = new_ucmd!().run(); - let exp_result = unwrap_or_return!(expected_result(&[])); + let exp_result = unwrap_or_return!(expected_result(util_name!(), &[])); let mut _exp_stdout = exp_result.stdout_str().to_string(); #[cfg(target_os = "linux")] @@ -72,7 +31,7 @@ fn test_id_single_user() { let test_users = [&whoami()[..]]; let scene = TestScenario::new(util_name!()); - let mut exp_result = unwrap_or_return!(expected_result(&test_users)); + let mut exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); scene .ucmd() .args(&test_users) @@ -85,7 +44,7 @@ fn test_id_single_user() { for &opt in &["--user", "--group", "--groups"] { let mut args = vec![opt]; args.extend_from_slice(&test_users); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -94,7 +53,7 @@ fn test_id_single_user() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--zero"); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -103,7 +62,7 @@ fn test_id_single_user() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--name"); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -112,7 +71,7 @@ fn test_id_single_user() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.pop(); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -128,7 +87,7 @@ fn test_id_single_user() { fn test_id_single_user_non_existing() { let args = &["hopefully_non_existing_username"]; let result = new_ucmd!().args(args).run(); - let exp_result = unwrap_or_return!(expected_result(args)); + let exp_result = unwrap_or_return!(expected_result(util_name!(), args)); // It is unknown why on macOS (and possibly others?) `id` adds "Invalid argument". // coreutils 8.32: $ LC_ALL=C id foobar @@ -147,7 +106,7 @@ fn test_id_name() { for &opt in &["--user", "--group", "--groups"] { let args = [opt, "--name"]; let result = scene.ucmd().args(&args).run(); - let exp_result = unwrap_or_return!(expected_result(&args)); + let exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) @@ -166,7 +125,7 @@ fn test_id_real() { for &opt in &["--user", "--group", "--groups"] { let args = [opt, "--real"]; let result = scene.ucmd().args(&args).run(); - let exp_result = unwrap_or_return!(expected_result(&args)); + let exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) @@ -206,21 +165,16 @@ fn test_id_password_style() { #[test] #[cfg(unix)] fn test_id_multiple_users() { - #[cfg(target_os = "linux")] - let util_name = util_name!(); - #[cfg(all(unix, not(target_os = "linux")))] - let util_name = &format!("g{}", util_name!()); - let version_check_string = check_coreutil_version(util_name, VERSION_MIN_MULTIPLE_USERS); - if version_check_string.starts_with(UUTILS_WARNING) { - println!("{}\ntest skipped", version_check_string); - return; - } + unwrap_or_return!(check_coreutil_version( + util_name!(), + VERSION_MIN_MULTIPLE_USERS + )); // Same typical users that GNU test suite is using. let test_users = ["root", "man", "postfix", "sshd", &whoami()]; let scene = TestScenario::new(util_name!()); - let mut exp_result = unwrap_or_return!(expected_result(&test_users)); + let mut exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); scene .ucmd() .args(&test_users) @@ -233,7 +187,7 @@ fn test_id_multiple_users() { for &opt in &["--user", "--group", "--groups"] { let mut args = vec![opt]; args.extend_from_slice(&test_users); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -242,7 +196,7 @@ fn test_id_multiple_users() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--zero"); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -251,7 +205,7 @@ fn test_id_multiple_users() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--name"); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -260,7 +214,7 @@ fn test_id_multiple_users() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.pop(); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -274,15 +228,10 @@ fn test_id_multiple_users() { #[test] #[cfg(unix)] fn test_id_multiple_users_non_existing() { - #[cfg(target_os = "linux")] - let util_name = util_name!(); - #[cfg(all(unix, not(target_os = "linux")))] - let util_name = &format!("g{}", util_name!()); - let version_check_string = check_coreutil_version(util_name, VERSION_MIN_MULTIPLE_USERS); - if version_check_string.starts_with(UUTILS_WARNING) { - println!("{}\ntest skipped", version_check_string); - return; - } + unwrap_or_return!(check_coreutil_version( + util_name!(), + VERSION_MIN_MULTIPLE_USERS + )); let test_users = [ "root", @@ -298,7 +247,7 @@ fn test_id_multiple_users_non_existing() { ]; let scene = TestScenario::new(util_name!()); - let mut exp_result = unwrap_or_return!(expected_result(&test_users)); + let mut exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); scene .ucmd() .args(&test_users) @@ -311,7 +260,7 @@ fn test_id_multiple_users_non_existing() { for &opt in &["--user", "--group", "--groups"] { let mut args = vec![opt]; args.extend_from_slice(&test_users); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -320,7 +269,7 @@ fn test_id_multiple_users_non_existing() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--zero"); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -329,7 +278,7 @@ fn test_id_multiple_users_non_existing() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--name"); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -338,7 +287,7 @@ fn test_id_multiple_users_non_existing() { .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.pop(); - exp_result = unwrap_or_return!(expected_result(&args)); + exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); scene .ucmd() .args(&args) @@ -360,12 +309,12 @@ fn test_id_default_format() { .ucmd() .args(&args) .fails() - .stderr_only(unwrap_or_return!(expected_result(&args)).stderr_str()); + .stderr_only(unwrap_or_return!(expected_result(util_name!(), &args)).stderr_str()); for &opt2 in &["--user", "--group", "--groups"] { // u/g/G n/r let args = [opt2, opt1]; let result = scene.ucmd().args(&args).run(); - let exp_result = unwrap_or_return!(expected_result(&args)); + let exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) @@ -379,7 +328,7 @@ fn test_id_default_format() { .ucmd() .args(&args) .succeeds() - .stdout_only(unwrap_or_return!(expected_result(&args)).stdout_str()); + .stdout_only(unwrap_or_return!(expected_result(util_name!(), &args)).stdout_str()); } } @@ -393,7 +342,7 @@ fn test_id_zero() { .ucmd() .args(&[z_flag]) .fails() - .stderr_only(unwrap_or_return!(expected_result(&[z_flag])).stderr_str()); + .stderr_only(unwrap_or_return!(expected_result(util_name!(), &[z_flag])).stderr_str()); for &opt1 in &["--name", "--real"] { // id: cannot print only names or real IDs in default format let args = [opt1, z_flag]; @@ -401,12 +350,12 @@ fn test_id_zero() { .ucmd() .args(&args) .fails() - .stderr_only(unwrap_or_return!(expected_result(&args)).stderr_str()); + .stderr_only(unwrap_or_return!(expected_result(util_name!(), &args)).stderr_str()); for &opt2 in &["--user", "--group", "--groups"] { // u/g/G n/r z let args = [opt2, z_flag, opt1]; let result = scene.ucmd().args(&args).run(); - let exp_result = unwrap_or_return!(expected_result(&args)); + let exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) @@ -420,86 +369,7 @@ fn test_id_zero() { .ucmd() .args(&args) .succeeds() - .stdout_only(unwrap_or_return!(expected_result(&args)).stdout_str()); + .stdout_only(unwrap_or_return!(expected_result(util_name!(), &args)).stdout_str()); } } } - -fn check_coreutil_version(util_name: &str, version_expected: &str) -> String { - // example: - // $ id --version | head -n 1 - // id (GNU coreutils) 8.32.162-4eda - let scene = TestScenario::new(util_name); - let version_check = scene - .cmd_keepenv(&util_name) - .env("LC_ALL", "C") - .arg("--version") - .run(); - version_check - .stdout_str() - .split('\n') - .collect::>() - .get(0) - .map_or_else( - || format!("{}: unexpected output format for reference coreutil: '{} --version'", UUTILS_WARNING, util_name), - |s| { - if s.contains(&format!("(GNU coreutils) {}", version_expected)) { - s.to_string() - } else if s.contains("(GNU coreutils)") { - let version_found = s.split_whitespace().last().unwrap()[..4].parse::().unwrap_or_default(); - let version_expected = version_expected.parse::().unwrap_or_default(); - if version_found > version_expected { - format!("{}: version for the reference coreutil '{}' is higher than expected; expected: {}, found: {}", UUTILS_INFO, util_name, version_expected, version_found) - } else { - format!("{}: version for the reference coreutil '{}' does not match; expected: {}, found: {}", UUTILS_WARNING, util_name, version_expected, version_found) } - } else { - format!("{}: no coreutils version string found for reference coreutils '{} --version'", UUTILS_WARNING, util_name) - } - }, - ) -} - -#[allow(clippy::needless_borrow)] -#[cfg(unix)] -fn expected_result(args: &[&str]) -> Result { - #[cfg(target_os = "linux")] - let util_name = util_name!(); - #[cfg(all(unix, not(target_os = "linux")))] - let util_name = &format!("g{}", util_name!()); - - let version_check_string = check_coreutil_version(util_name, VERSION_MIN); - if version_check_string.starts_with(UUTILS_WARNING) { - return Err(version_check_string); - } - println!("{}", version_check_string); - - let scene = TestScenario::new(util_name); - let result = scene - .cmd_keepenv(util_name) - .env("LC_ALL", "C") - .args(args) - .run(); - - let (stdout, stderr): (String, String) = if cfg!(target_os = "linux") { - ( - result.stdout_str().to_string(), - result.stderr_str().to_string(), - ) - } else { - // strip 'g' prefix from results: - let from = util_name.to_string() + ":"; - let to = &from[1..]; - ( - result.stdout_str().replace(&from, to), - result.stderr_str().replace(&from, to), - ) - }; - - Ok(CmdResult::new( - Some(result.tmpd()), - Some(result.code()), - result.succeeded(), - stdout.as_bytes(), - stderr.as_bytes(), - )) -} From 90de4257b19de89dc7de2a4ca17424a875363d71 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 7 Jul 2021 15:53:46 +0200 Subject: [PATCH 04/10] test_pinky: refactor use expected_result from common/util.rs --- tests/by-util/test_pinky.rs | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/tests/by-util/test_pinky.rs b/tests/by-util/test_pinky.rs index bc2833a42..3d29bf249 100644 --- a/tests/by-util/test_pinky.rs +++ b/tests/by-util/test_pinky.rs @@ -42,15 +42,17 @@ fn test_long_format() { )); } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_long_format_multiple_users() { let args = ["-l", "root", "root", "root"]; + let expect = unwrap_or_return!(expected_result(util_name!(), &args)); new_ucmd!() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expect.stdout_str()) + .stderr_is(expect.stderr_str()); } #[test] @@ -59,55 +61,38 @@ fn test_long_format_wo_user() { new_ucmd!().arg("-l").fails().code_is(1); } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[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 = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = expected_result(&args); + let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); 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(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[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 = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = expected_result(&args); + let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); 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(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_no_flag() { let actual = new_ucmd!().succeeds().stdout_move_str(); - let expect = expected_result(&[]); + let expect = unwrap_or_return!(expected_result(util_name!(), &[])).stdout_move_str(); 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(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!()); - - // note: clippy::needless_borrow *false positive* - #[allow(clippy::needless_borrow)] - TestScenario::new(&util_name) - .cmd_keepenv(util_name) - .env("LC_ALL", "C") - .args(args) - .succeeds() - .stdout_move_str() -} From 805e024794636a45effa64a5e29178db61356c52 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 7 Jul 2021 15:54:03 +0200 Subject: [PATCH 05/10] test_stat: refactor use expected_result from common/util.rs --- tests/by-util/test_stat.rs | 69 ++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 41 deletions(-) diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index ddf78815f..ec85f8f27 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -109,30 +109,26 @@ const FS_FORMAT_STR: &str = "%b %c %i %l %n %s %S %t %T"; // avoid "%a %d %f" wh #[cfg(target_os = "linux")] fn test_terse_fs_format() { let args = ["-f", "-t", "/proc"]; - new_ucmd!() - .args(&args) - .run() - .stdout_is(expected_result(&args)); + let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); + new_ucmd!().args(&args).run().stdout_is(expected_stdout); } #[test] #[cfg(target_os = "linux")] fn test_fs_format() { let args = ["-f", "-c", FS_FORMAT_STR, "/dev/shm"]; - new_ucmd!() - .args(&args) - .run() - .stdout_is(expected_result(&args)); + let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); + new_ucmd!().args(&args).run().stdout_is(expected_stdout); } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(unix)] #[test] 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 let args = ["-t", "/"]; let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = expected_result(&args); + let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); let v_actual: Vec<&str> = actual.trim().split(' ').collect(); @@ -156,12 +152,12 @@ fn test_terse_normal_format() { ); } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(unix)] #[test] fn test_format_created_time() { let args = ["-c", "%w", "/bin"]; let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = expected_result(&args); + let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences @@ -180,12 +176,12 @@ fn test_format_created_time() { ); } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(unix)] #[test] fn test_format_created_seconds() { let args = ["-c", "%W", "/bin"]; let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = expected_result(&args); + let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences @@ -204,17 +200,18 @@ fn test_format_created_seconds() { ); } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(unix)] #[test] fn test_normal_format() { let args = ["-c", NORMAL_FORMAT_STR, "/bin"]; + let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); new_ucmd!() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expected_stdout); } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(unix)] #[test] fn test_symlinks() { let scene = TestScenario::new(util_name!()); @@ -232,18 +229,22 @@ fn test_symlinks() { if at.file_exists(file) && at.is_symlink(file) { tested = true; let args = ["-c", NORMAL_FORMAT_STR, file]; + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); scene .ucmd() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expected_stdout); // -L, --dereference follow links let args = ["-L", "-c", NORMAL_FORMAT_STR, file]; + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); scene .ucmd() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expected_stdout); } } if !tested { @@ -269,13 +270,14 @@ fn test_char() { #[cfg(any(target_vendor = "apple"))] "/dev/ptmx", ]; + let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); new_ucmd!() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expected_stdout); } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(unix)] #[test] fn test_multi_files() { let args = [ @@ -287,38 +289,23 @@ fn test_multi_files() { "/etc/fstab", "/var", ]; + let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); new_ucmd!() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expected_stdout); } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_printf() { let args = [ "--printf=123%-# 15q\\r\\\"\\\\\\a\\b\\e\\f\\v%+020.23m\\x12\\167\\132\\112\\n", "/", ]; + let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); new_ucmd!() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); -} - -#[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!()); - - // note: clippy::needless_borrow *false positive* - #[allow(clippy::needless_borrow)] - TestScenario::new(&util_name) - .cmd_keepenv(util_name) - .env("LC_ALL", "C") - .args(args) - .succeeds() - .stdout_move_str() + .stdout_is(expected_stdout); } From 735ec4014e1cab2cd7417e928e64e6159fd0b8bb Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 7 Jul 2021 16:19:58 +0200 Subject: [PATCH 06/10] test_who: refactor use expected_result from common/util.rs --- tests/by-util/test_groups.rs | 5 ++ tests/by-util/test_id.rs | 7 +- tests/by-util/test_pinky.rs | 5 ++ tests/by-util/test_stat.rs | 5 ++ tests/by-util/test_who.rs | 153 +++++++++++++++-------------------- tests/common/macros.rs | 5 ++ tests/common/util.rs | 5 ++ 7 files changed, 98 insertions(+), 87 deletions(-) diff --git a/tests/by-util/test_groups.rs b/tests/by-util/test_groups.rs index 9cebdf878..52ac00a0d 100644 --- a/tests/by-util/test_groups.rs +++ b/tests/by-util/test_groups.rs @@ -1,3 +1,8 @@ +// * This file is part of the uutils coreutils package. +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. + use crate::common::util::*; const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced in GNU's coreutils 8.31 diff --git a/tests/by-util/test_id.rs b/tests/by-util/test_id.rs index 6c6f168fe..e491236d8 100644 --- a/tests/by-util/test_id.rs +++ b/tests/by-util/test_id.rs @@ -1,7 +1,12 @@ -use crate::common::util::*; +// * This file is part of the uutils coreutils package. +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. // spell-checker:ignore (ToDO) coreutil +use crate::common::util::*; + const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced in GNU's coreutils 8.31 #[test] diff --git a/tests/by-util/test_pinky.rs b/tests/by-util/test_pinky.rs index 3d29bf249..220fd9108 100644 --- a/tests/by-util/test_pinky.rs +++ b/tests/by-util/test_pinky.rs @@ -1,3 +1,8 @@ +// * This file is part of the uutils coreutils package. +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. + extern crate uucore; use crate::common::util::*; diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index ec85f8f27..2e0551ec5 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -1,3 +1,8 @@ +// * This file is part of the uutils coreutils package. +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. + extern crate regex; use crate::common::util::*; diff --git a/tests/by-util/test_who.rs b/tests/by-util/test_who.rs index 9315a5956..c84ad0f2f 100644 --- a/tests/by-util/test_who.rs +++ b/tests/by-util/test_who.rs @@ -1,30 +1,33 @@ -use crate::common::util::*; +// * This file is part of the uutils coreutils package. +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. // spell-checker:ignore (flags) runlevel mesg -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +use crate::common::util::*; + +#[cfg(unix)] #[test] fn test_count() { for opt in &["-q", "--count"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_boot() { for opt in &["-b", "--boot"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_heading() { for opt in &["-H", "--heading"] { @@ -32,7 +35,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 = unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); let v_actual: Vec<&str> = actual.split_whitespace().collect(); @@ -41,76 +44,70 @@ fn test_heading() { } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_short() { for opt in &["-s", "--short"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_login() { for opt in &["-l", "--login"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_m() { for opt in &["-m"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_process() { for opt in &["-p", "--process"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } +#[cfg(unix)] #[test] fn test_runlevel() { for opt in &["-r", "--runlevel"] { - #[cfg(any(target_vendor = "apple", target_os = "linux"))] - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); #[cfg(not(target_os = "linux"))] new_ucmd!().arg(opt).succeeds().stdout_is(""); } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_time() { for opt in &["-t", "--time"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_mesg() { // -T, -w, --mesg @@ -120,21 +117,22 @@ fn test_mesg() { // --writable // same as -T for opt in &["-T", "-w", "--mesg", "--message", "--writable"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } +#[cfg(unix)] #[test] fn test_arg1_arg2() { let args = ["am", "i"]; + let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); new_ucmd!() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expected_stdout); } #[test] @@ -146,12 +144,12 @@ fn test_too_many_args() { new_ucmd!().args(&args).fails().stderr_contains(EXPECTED); } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_users() { for opt in &["-u", "--users"] { let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str(); - let expect = expected_result(&[opt]); + let expect = unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); @@ -170,28 +168,26 @@ fn test_users() { } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_lookup() { let opt = "--lookup"; - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_dead() { for opt in &["-d", "--dead"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_all_separately() { if cfg!(target_os = "macos") { @@ -201,20 +197,23 @@ fn test_all_separately() { // -a, --all same as -b -d --login -p -r -t -T -u let args = ["-b", "-d", "--login", "-p", "-r", "-t", "-T", "-u"]; + let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); let scene = TestScenario::new(util_name!()); scene .ucmd() .args(&args) .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expected_stdout); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &["--all"])).stdout_move_str(); scene .ucmd() .arg("--all") .succeeds() - .stdout_is(expected_result(&args)); + .stdout_is(expected_stdout); } -#[cfg(any(target_vendor = "apple", target_os = "linux"))] +#[cfg(unix)] #[test] fn test_all() { if cfg!(target_os = "macos") { @@ -223,26 +222,8 @@ fn test_all() { } for opt in &["-a", "--all"] { - new_ucmd!() - .arg(opt) - .succeeds() - .stdout_is(expected_result(&[opt])); + let expected_stdout = + unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); } } - -#[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!()); - - // note: clippy::needless_borrow *false positive* - #[allow(clippy::needless_borrow)] - TestScenario::new(&util_name) - .cmd_keepenv(util_name) - .env("LC_ALL", "C") - .args(args) - .succeeds() - .stdout_move_str() -} diff --git a/tests/common/macros.rs b/tests/common/macros.rs index 2a1c20af2..62b8c4824 100644 --- a/tests/common/macros.rs +++ b/tests/common/macros.rs @@ -1,3 +1,8 @@ +// * This file is part of the uutils coreutils package. +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. + /// Platform-independent helper for constructing a PathBuf from individual elements #[macro_export] macro_rules! path_concat { diff --git a/tests/common/util.rs b/tests/common/util.rs index 79af471e3..2cff46224 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1,3 +1,8 @@ +// * This file is part of the uutils coreutils package. +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. + //spell-checker: ignore (linux) rlimit prlimit Rlim coreutil #![allow(dead_code)] From 31aa8b206299a3bc8e711c00e428b40aa2bd8599 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 7 Jul 2021 22:09:01 +0200 Subject: [PATCH 07/10] test_du: refactor use expected_result from common/util.rs --- tests/by-util/test_du.rs | 117 +++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 61 deletions(-) diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 029f5e516..607d5dc45 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -39,13 +39,13 @@ fn _du_basics(s: &str) { #[test] fn test_du_basics_subdir() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); - let result = scene.ucmd().arg(SUB_DIR).succeeds(); + let result = ts.ucmd().arg(SUB_DIR).succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg(SUB_DIR).run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &[SUB_DIR])); if result_reference.succeeded() { assert_eq!(result.stdout_str(), result_reference.stdout_str()); return; @@ -83,15 +83,16 @@ fn _du_basics_subdir(s: &str) { #[test] fn test_du_invalid_size() { let args = &["block-size", "threshold"]; + let ts = TestScenario::new(util_name!()); for s in args { - new_ucmd!() + ts.ucmd() .arg(format!("--{}=1fb4t", s)) .arg("/tmp") .fails() .code_is(1) .stderr_only(format!("du: invalid --{} argument '1fb4t'", s)); #[cfg(not(target_pointer_width = "128"))] - new_ucmd!() + ts.ucmd() .arg(format!("--{}=1Y", s)) .arg("/tmp") .fails() @@ -110,16 +111,16 @@ fn test_du_basics_bad_name() { #[test] fn test_du_soft_link() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; at.symlink_file(SUB_FILE, SUB_LINK); - let result = scene.ucmd().arg(SUB_DIR_LINKS).succeeds(); + let result = ts.ucmd().arg(SUB_DIR_LINKS).succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &[SUB_DIR_LINKS])); if result_reference.succeeded() { assert_eq!(result.stdout_str(), result_reference.stdout_str()); return; @@ -157,16 +158,16 @@ fn _du_soft_link(s: &str) { #[test] fn test_du_hard_link() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; at.hard_link(SUB_FILE, SUB_LINK); - let result = scene.ucmd().arg(SUB_DIR_LINKS).succeeds(); + let result = ts.ucmd().arg(SUB_DIR_LINKS).succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &[SUB_DIR_LINKS])); if result_reference.succeeded() { assert_eq!(result.stdout_str(), result_reference.stdout_str()); return; @@ -204,13 +205,13 @@ fn _du_hard_link(s: &str) { #[test] fn test_du_d_flag() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); - let result = scene.ucmd().arg("-d1").succeeds(); + let result = ts.ucmd().arg("-d1").succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg("-d1").run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &["-d1"])); if result_reference.succeeded() { assert_eq!(result.stdout_str(), result_reference.stdout_str()); return; @@ -247,16 +248,17 @@ fn _du_d_flag(s: &str) { #[test] fn test_du_dereference() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; at.symlink_dir(SUB_DEEPER_DIR, SUB_DIR_LINKS_DEEPER_SYM_DIR); - let result = scene.ucmd().arg("-L").arg(SUB_DIR_LINKS).succeeds(); + let result = ts.ucmd().arg("-L").arg(SUB_DIR_LINKS).succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg("-L").arg(SUB_DIR_LINKS).run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &["-L", SUB_DIR_LINKS])); + if result_reference.succeeded() { assert_eq!(result.stdout_str(), result_reference.stdout_str()); return; @@ -294,12 +296,12 @@ fn _du_dereference(s: &str) { #[test] fn test_du_inodes_basic() { - let scene = TestScenario::new(util_name!()); - let result = scene.ucmd().arg("--inodes").succeeds(); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().arg("--inodes").succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg("--inodes").run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &["--inodes"])); assert_eq!(result.stdout_str(), result_reference.stdout_str()); } @@ -335,20 +337,15 @@ fn _du_inodes_basic(s: &str) { #[test] fn test_du_inodes() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); - scene - .ucmd() + ts.ucmd() .arg("--summarize") .arg("--inodes") .succeeds() .stdout_only("11\t.\n"); - let result = scene - .ucmd() - .arg("--separate-dirs") - .arg("--inodes") - .succeeds(); + let result = ts.ucmd().arg("--separate-dirs").arg("--inodes").succeeds(); #[cfg(target_os = "windows")] result.stdout_contains("3\t.\\subdir\\links\n"); @@ -358,7 +355,8 @@ fn test_du_inodes() { #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg("--separate-dirs").arg("--inodes").run(); + let result_reference = + unwrap_or_return!(expected_result(&ts, &["--separate-dirs", "--inodes"])); assert_eq!(result.stdout_str(), result_reference.stdout_str()); } } @@ -375,31 +373,29 @@ fn test_du_h_flag_empty_file() { #[cfg(feature = "touch")] #[test] fn test_du_time() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); - scene - .ccmd("touch") + ts.ccmd("touch") .arg("-a") .arg("-t") .arg("201505150000") .arg("date_test") .succeeds(); - scene - .ccmd("touch") + ts.ccmd("touch") .arg("-m") .arg("-t") .arg("201606160000") .arg("date_test") .succeeds(); - let result = scene.ucmd().arg("--time").arg("date_test").succeeds(); + let result = ts.ucmd().arg("--time").arg("date_test").succeeds(); result.stdout_only("0\t2016-06-16 00:00\tdate_test\n"); - let result = scene.ucmd().arg("--time=atime").arg("date_test").succeeds(); + let result = ts.ucmd().arg("--time=atime").arg("date_test").succeeds(); result.stdout_only("0\t2015-05-15 00:00\tdate_test\n"); - let result = scene.ucmd().arg("--time=ctime").arg("date_test").succeeds(); + let result = ts.ucmd().arg("--time=ctime").arg("date_test").succeeds(); result.stdout_only("0\t2016-06-16 00:00\tdate_test\n"); #[cfg(not(target_env = "musl"))] @@ -408,7 +404,7 @@ fn test_du_time() { let re_birth = Regex::new(r"0\t[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}\tdate_test").unwrap(); - let result = scene.ucmd().arg("--time=birth").arg("date_test").succeeds(); + let result = ts.ucmd().arg("--time=birth").arg("date_test").succeeds(); result.stdout_matches(&re_birth); } } @@ -417,21 +413,21 @@ fn test_du_time() { #[cfg(feature = "chmod")] #[test] fn test_du_no_permission() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; at.mkdir_all(SUB_DIR_LINKS); - scene.ccmd("chmod").arg("-r").arg(SUB_DIR_LINKS).succeeds(); + ts.ccmd("chmod").arg("-r").arg(SUB_DIR_LINKS).succeeds(); - let result = scene.ucmd().arg(SUB_DIR_LINKS).run(); // TODO: replace with ".fails()" once `du` is fixed + let result = ts.ucmd().arg(SUB_DIR_LINKS).run(); // TODO: replace with ".fails()" once `du` is fixed result.stderr_contains( "du: cannot read directory 'subdir/links': Permission denied (os error 13)", ); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).fails(); + let result_reference = unwrap_or_return!(expected_result(&ts, &[SUB_DIR_LINKS])); if result_reference .stderr_str() .contains("du: cannot read directory 'subdir/links': Permission denied") @@ -455,13 +451,13 @@ fn _du_no_permission(s: &str) { #[test] fn test_du_one_file_system() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); - let result = scene.ucmd().arg("-x").arg(SUB_DIR).succeeds(); + let result = ts.ucmd().arg("-x").arg(SUB_DIR).succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg("-x").arg(SUB_DIR).run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &["-x", SUB_DIR])); if result_reference.succeeded() { assert_eq!(result.stdout_str(), result_reference.stdout_str()); return; @@ -472,19 +468,17 @@ fn test_du_one_file_system() { #[test] fn test_du_threshold() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); let threshold = if cfg!(windows) { "7K" } else { "10K" }; - scene - .ucmd() + ts.ucmd() .arg(format!("--threshold={}", threshold)) .succeeds() .stdout_contains("links") .stdout_does_not_contain("deeper_dir"); - scene - .ucmd() + ts.ucmd() .arg(format!("--threshold=-{}", threshold)) .succeeds() .stdout_does_not_contain("links") @@ -493,12 +487,12 @@ fn test_du_threshold() { #[test] fn test_du_apparent_size() { - let scene = TestScenario::new(util_name!()); - let result = scene.ucmd().arg("--apparent-size").succeeds(); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().arg("--apparent-size").succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg("--apparent-size").run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &["--apparent-size"])); assert_eq!(result.stdout_str(), result_reference.stdout_str()); } @@ -561,12 +555,12 @@ fn _du_apparent_size(s: &str) { #[test] fn test_du_bytes() { - let scene = TestScenario::new(util_name!()); - let result = scene.ucmd().arg("--bytes").succeeds(); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().arg("--bytes").succeeds(); #[cfg(target_os = "linux")] { - let result_reference = scene.cmd("du").arg("--bytes").run(); + let result_reference = unwrap_or_return!(expected_result(&ts, &["--bytes"])); assert_eq!(result.stdout_str(), result_reference.stdout_str()); } @@ -579,7 +573,8 @@ fn test_du_bytes() { #[cfg(all( not(target_vendor = "apple"), not(target_os = "windows"), - not(target_os = "freebsd") + not(target_os = "freebsd"), + not(target_os = "linux") ))] result.stdout_contains("21529\t./subdir\n"); } From abc59fbe8544845a66eb81ee14bffadd3476da40 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Wed, 7 Jul 2021 22:46:16 +0200 Subject: [PATCH 08/10] tests/common: refactor: use TestScenario instead of util_name for expected_result() --- tests/by-util/test_groups.rs | 15 ++-- tests/by-util/test_id.rs | 143 ++++++++++++++++------------------- tests/by-util/test_pinky.rs | 41 +++++----- tests/by-util/test_stat.rs | 79 ++++++++----------- tests/by-util/test_who.rs | 112 +++++++++++++-------------- tests/common/util.rs | 20 ++--- 6 files changed, 189 insertions(+), 221 deletions(-) diff --git a/tests/by-util/test_groups.rs b/tests/by-util/test_groups.rs index 52ac00a0d..14e5a356d 100644 --- a/tests/by-util/test_groups.rs +++ b/tests/by-util/test_groups.rs @@ -10,8 +10,9 @@ const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced #[test] #[cfg(unix)] fn test_groups() { - let result = new_ucmd!().run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), &[])); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &[])); result .stdout_is(exp_result.stdout_str()) @@ -24,8 +25,9 @@ fn test_groups() { fn test_groups_username() { let test_users = [&whoami()[..]]; - let result = new_ucmd!().args(&test_users).run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().args(&test_users).run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &test_users)); result .stdout_is(exp_result.stdout_str()) @@ -42,8 +44,9 @@ fn test_groups_username_multiple() { )); let test_users = ["root", "man", "postfix", "sshd", &whoami()]; - let result = new_ucmd!().args(&test_users).run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().args(&test_users).run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &test_users)); result .stdout_is(exp_result.stdout_str()) diff --git a/tests/by-util/test_id.rs b/tests/by-util/test_id.rs index e491236d8..e62f105de 100644 --- a/tests/by-util/test_id.rs +++ b/tests/by-util/test_id.rs @@ -12,13 +12,17 @@ const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced #[test] #[cfg(unix)] fn test_id_no_specified_user() { - let result = new_ucmd!().run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), &[])); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &[])); let mut _exp_stdout = exp_result.stdout_str().to_string(); #[cfg(target_os = "linux")] { // NOTE: (SELinux NotImplemented) strip 'context' part from exp_stdout: + // example: + // uid=1001(runner) gid=121(docker) groups=121(docker),4(adm),101(systemd-journal) \ + // context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 if let Some(context_offset) = exp_result.stdout_str().find(" context=") { _exp_stdout.replace_range(context_offset.._exp_stdout.len() - 1, ""); } @@ -35,10 +39,9 @@ fn test_id_no_specified_user() { fn test_id_single_user() { let test_users = [&whoami()[..]]; - let scene = TestScenario::new(util_name!()); - let mut exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); - scene - .ucmd() + let ts = TestScenario::new(util_name!()); + let mut exp_result = unwrap_or_return!(expected_result(&ts, &test_users)); + ts.ucmd() .args(&test_users) .run() .stdout_is(exp_result.stdout_str()) @@ -49,36 +52,32 @@ fn test_id_single_user() { for &opt in &["--user", "--group", "--groups"] { let mut args = vec![opt]; args.extend_from_slice(&test_users); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--zero"); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--name"); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.pop(); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) @@ -91,8 +90,9 @@ fn test_id_single_user() { #[cfg(unix)] fn test_id_single_user_non_existing() { let args = &["hopefully_non_existing_username"]; - let result = new_ucmd!().args(args).run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), args)); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().args(args).run(); + let exp_result = unwrap_or_return!(expected_result(&ts, args)); // It is unknown why on macOS (and possibly others?) `id` adds "Invalid argument". // coreutils 8.32: $ LC_ALL=C id foobar @@ -107,11 +107,11 @@ fn test_id_single_user_non_existing() { #[test] #[cfg(unix)] fn test_id_name() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); for &opt in &["--user", "--group", "--groups"] { let args = [opt, "--name"]; - let result = scene.ucmd().args(&args).run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); + let result = ts.ucmd().args(&args).run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &args)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) @@ -126,11 +126,11 @@ fn test_id_name() { #[test] #[cfg(unix)] fn test_id_real() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); for &opt in &["--user", "--group", "--groups"] { let args = [opt, "--real"]; - let result = scene.ucmd().args(&args).run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); + let result = ts.ucmd().args(&args).run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &args)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) @@ -178,10 +178,9 @@ fn test_id_multiple_users() { // Same typical users that GNU test suite is using. let test_users = ["root", "man", "postfix", "sshd", &whoami()]; - let scene = TestScenario::new(util_name!()); - let mut exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); - scene - .ucmd() + let ts = TestScenario::new(util_name!()); + let mut exp_result = unwrap_or_return!(expected_result(&ts, &test_users)); + ts.ucmd() .args(&test_users) .run() .stdout_is(exp_result.stdout_str()) @@ -192,36 +191,32 @@ fn test_id_multiple_users() { for &opt in &["--user", "--group", "--groups"] { let mut args = vec![opt]; args.extend_from_slice(&test_users); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--zero"); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--name"); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.pop(); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) @@ -251,10 +246,9 @@ fn test_id_multiple_users_non_existing() { &whoami(), ]; - let scene = TestScenario::new(util_name!()); - let mut exp_result = unwrap_or_return!(expected_result(util_name!(), &test_users)); - scene - .ucmd() + let ts = TestScenario::new(util_name!()); + let mut exp_result = unwrap_or_return!(expected_result(&ts, &test_users)); + ts.ucmd() .args(&test_users) .run() .stdout_is(exp_result.stdout_str()) @@ -265,36 +259,32 @@ fn test_id_multiple_users_non_existing() { for &opt in &["--user", "--group", "--groups"] { let mut args = vec![opt]; args.extend_from_slice(&test_users); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--zero"); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.push("--name"); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str().replace(": Invalid argument", "")) .code_is(exp_result.code()); args.pop(); - exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); - scene - .ucmd() + exp_result = unwrap_or_return!(expected_result(&ts, &args)); + ts.ucmd() .args(&args) .run() .stdout_is(exp_result.stdout_str()) @@ -306,20 +296,19 @@ fn test_id_multiple_users_non_existing() { #[test] #[cfg(unix)] fn test_id_default_format() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); for &opt1 in &["--name", "--real"] { // id: cannot print only names or real IDs in default format let args = [opt1]; - scene - .ucmd() + ts.ucmd() .args(&args) .fails() - .stderr_only(unwrap_or_return!(expected_result(util_name!(), &args)).stderr_str()); + .stderr_only(unwrap_or_return!(expected_result(&ts, &args)).stderr_str()); for &opt2 in &["--user", "--group", "--groups"] { // u/g/G n/r let args = [opt2, opt1]; - let result = scene.ucmd().args(&args).run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); + let result = ts.ucmd().args(&args).run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &args)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) @@ -329,38 +318,35 @@ fn test_id_default_format() { for &opt2 in &["--user", "--group", "--groups"] { // u/g/G let args = [opt2]; - scene - .ucmd() + ts.ucmd() .args(&args) .succeeds() - .stdout_only(unwrap_or_return!(expected_result(util_name!(), &args)).stdout_str()); + .stdout_only(unwrap_or_return!(expected_result(&ts, &args)).stdout_str()); } } #[test] #[cfg(unix)] fn test_id_zero() { - let scene = TestScenario::new(util_name!()); + let ts = TestScenario::new(util_name!()); for z_flag in &["-z", "--zero"] { // id: option --zero not permitted in default format - scene - .ucmd() + ts.ucmd() .args(&[z_flag]) .fails() - .stderr_only(unwrap_or_return!(expected_result(util_name!(), &[z_flag])).stderr_str()); + .stderr_only(unwrap_or_return!(expected_result(&ts, &[z_flag])).stderr_str()); for &opt1 in &["--name", "--real"] { // id: cannot print only names or real IDs in default format let args = [opt1, z_flag]; - scene - .ucmd() + ts.ucmd() .args(&args) .fails() - .stderr_only(unwrap_or_return!(expected_result(util_name!(), &args)).stderr_str()); + .stderr_only(unwrap_or_return!(expected_result(&ts, &args)).stderr_str()); for &opt2 in &["--user", "--group", "--groups"] { // u/g/G n/r z let args = [opt2, z_flag, opt1]; - let result = scene.ucmd().args(&args).run(); - let exp_result = unwrap_or_return!(expected_result(util_name!(), &args)); + let result = ts.ucmd().args(&args).run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &args)); result .stdout_is(exp_result.stdout_str()) .stderr_is(exp_result.stderr_str()) @@ -370,11 +356,10 @@ fn test_id_zero() { for &opt2 in &["--user", "--group", "--groups"] { // u/g/G z let args = [opt2, z_flag]; - scene - .ucmd() + ts.ucmd() .args(&args) .succeeds() - .stdout_only(unwrap_or_return!(expected_result(util_name!(), &args)).stdout_str()); + .stdout_only(unwrap_or_return!(expected_result(&ts, &args)).stdout_str()); } } } diff --git a/tests/by-util/test_pinky.rs b/tests/by-util/test_pinky.rs index 220fd9108..5394dfde9 100644 --- a/tests/by-util/test_pinky.rs +++ b/tests/by-util/test_pinky.rs @@ -25,19 +25,16 @@ fn test_long_format() { let login = "root"; let pw: Passwd = Passwd::locate(login).unwrap(); let real_name = pw.user_info().replace("&", &pw.name().capitalize()); - new_ucmd!() - .arg("-l") - .arg(login) - .succeeds() - .stdout_is(format!( - "Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n", - login, - real_name, - pw.user_dir(), - pw.user_shell() - )); + let ts = TestScenario::new(util_name!()); + ts.ucmd().arg("-l").arg(login).succeeds().stdout_is(format!( + "Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n", + login, + real_name, + pw.user_dir(), + pw.user_shell() + )); - new_ucmd!() + ts.ucmd() .arg("-lb") .arg(login) .succeeds() @@ -51,9 +48,10 @@ fn test_long_format() { #[test] fn test_long_format_multiple_users() { let args = ["-l", "root", "root", "root"]; - let expect = unwrap_or_return!(expected_result(util_name!(), &args)); + let ts = TestScenario::new(util_name!()); + let expect = unwrap_or_return!(expected_result(&ts, &args)); - new_ucmd!() + ts.ucmd() .args(&args) .succeeds() .stdout_is(expect.stdout_str()) @@ -72,8 +70,9 @@ 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 = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); + let ts = TestScenario::new(util_name!()); + let actual = ts.ucmd().args(&args).succeeds().stdout_move_str(); + let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect(); assert_eq!(v_actual, v_expect); @@ -85,8 +84,9 @@ 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 = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); + let ts = TestScenario::new(util_name!()); + let actual = ts.ucmd().args(&args).succeeds().stdout_move_str(); + let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect(); assert_eq!(v_actual, v_expect); @@ -95,8 +95,9 @@ fn test_short_format_q() { #[cfg(unix)] #[test] fn test_no_flag() { - let actual = new_ucmd!().succeeds().stdout_move_str(); - let expect = unwrap_or_return!(expected_result(util_name!(), &[])).stdout_move_str(); + let ts = TestScenario::new(util_name!()); + let actual = ts.ucmd().succeeds().stdout_move_str(); + let expect = unwrap_or_return!(expected_result(&ts, &[])).stdout_move_str(); let v_actual: Vec<&str> = actual.split_whitespace().collect(); let v_expect: Vec<&str> = expect.split_whitespace().collect(); assert_eq!(v_actual, v_expect); diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 2e0551ec5..7cff0d89c 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -114,16 +114,18 @@ const FS_FORMAT_STR: &str = "%b %c %i %l %n %s %S %t %T"; // avoid "%a %d %f" wh #[cfg(target_os = "linux")] fn test_terse_fs_format() { let args = ["-f", "-t", "/proc"]; - let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - new_ucmd!().args(&args).run().stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).run().stdout_is(expected_stdout); } #[test] #[cfg(target_os = "linux")] fn test_fs_format() { let args = ["-f", "-c", FS_FORMAT_STR, "/dev/shm"]; - let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - new_ucmd!().args(&args).run().stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).run().stdout_is(expected_stdout); } #[cfg(unix)] @@ -132,8 +134,9 @@ 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 let args = ["-t", "/"]; - let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); + let ts = TestScenario::new(util_name!()); + let actual = ts.ucmd().args(&args).succeeds().stdout_move_str(); + let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); let v_actual: Vec<&str> = actual.trim().split(' ').collect(); @@ -161,8 +164,9 @@ fn test_terse_normal_format() { #[test] fn test_format_created_time() { let args = ["-c", "%w", "/bin"]; - let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); + let ts = TestScenario::new(util_name!()); + let actual = ts.ucmd().args(&args).succeeds().stdout_move_str(); + let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences @@ -185,8 +189,9 @@ fn test_format_created_time() { #[test] fn test_format_created_seconds() { let args = ["-c", "%W", "/bin"]; - let actual = new_ucmd!().args(&args).succeeds().stdout_move_str(); - let expect = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); + let ts = TestScenario::new(util_name!()); + let actual = ts.ucmd().args(&args).succeeds().stdout_move_str(); + let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences @@ -209,18 +214,16 @@ fn test_format_created_seconds() { #[test] fn test_normal_format() { let args = ["-c", NORMAL_FORMAT_STR, "/bin"]; - let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - new_ucmd!() - .args(&args) - .succeeds() - .stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } #[cfg(unix)] #[test] fn test_symlinks() { - let scene = TestScenario::new(util_name!()); - let at = &scene.fixtures; + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; let mut tested: bool = false; // arbitrarily chosen symlinks with hope that the CI environment provides at least one of them @@ -234,22 +237,12 @@ fn test_symlinks() { if at.file_exists(file) && at.is_symlink(file) { tested = true; let args = ["-c", NORMAL_FORMAT_STR, file]; - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - scene - .ucmd() - .args(&args) - .succeeds() - .stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); // -L, --dereference follow links let args = ["-L", "-c", NORMAL_FORMAT_STR, file]; - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - scene - .ucmd() - .args(&args) - .succeeds() - .stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } } if !tested { @@ -275,11 +268,9 @@ fn test_char() { #[cfg(any(target_vendor = "apple"))] "/dev/ptmx", ]; - let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - new_ucmd!() - .args(&args) - .succeeds() - .stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } #[cfg(unix)] @@ -294,11 +285,9 @@ fn test_multi_files() { "/etc/fstab", "/var", ]; - let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - new_ucmd!() - .args(&args) - .succeeds() - .stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } #[cfg(unix)] @@ -308,9 +297,7 @@ fn test_printf() { "--printf=123%-# 15q\\r\\\"\\\\\\a\\b\\e\\f\\v%+020.23m\\x12\\167\\132\\112\\n", "/", ]; - let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - new_ucmd!() - .args(&args) - .succeeds() - .stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } diff --git a/tests/by-util/test_who.rs b/tests/by-util/test_who.rs index c84ad0f2f..d05715517 100644 --- a/tests/by-util/test_who.rs +++ b/tests/by-util/test_who.rs @@ -10,32 +10,33 @@ use crate::common::util::*; #[cfg(unix)] #[test] fn test_count() { + let ts = TestScenario::new(util_name!()); for opt in &["-q", "--count"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } #[cfg(unix)] #[test] fn test_boot() { + let ts = TestScenario::new(util_name!()); for opt in &["-b", "--boot"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } #[cfg(unix)] #[test] fn test_heading() { + let ts = TestScenario::new(util_name!()); for opt in &["-H", "--heading"] { // allow whitespace variation // * 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 = unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + let actual = ts.ucmd().arg(opt).succeeds().stdout_move_str(); + let expect = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); let v_actual: Vec<&str> = actual.split_whitespace().collect(); @@ -47,63 +48,63 @@ fn test_heading() { #[cfg(unix)] #[test] fn test_short() { + let ts = TestScenario::new(util_name!()); for opt in &["-s", "--short"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } #[cfg(unix)] #[test] fn test_login() { + let ts = TestScenario::new(util_name!()); for opt in &["-l", "--login"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } #[cfg(unix)] #[test] fn test_m() { + let ts = TestScenario::new(util_name!()); for opt in &["-m"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } #[cfg(unix)] #[test] fn test_process() { + let ts = TestScenario::new(util_name!()); for opt in &["-p", "--process"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } #[cfg(unix)] #[test] fn test_runlevel() { + let ts = TestScenario::new(util_name!()); for opt in &["-r", "--runlevel"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); #[cfg(not(target_os = "linux"))] - new_ucmd!().arg(opt).succeeds().stdout_is(""); + ts.ucmd().arg(opt).succeeds().stdout_is(""); } } #[cfg(unix)] #[test] fn test_time() { + let ts = TestScenario::new(util_name!()); for opt in &["-t", "--time"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } @@ -116,10 +117,10 @@ fn test_mesg() { // same as -T // --writable // same as -T + let ts = TestScenario::new(util_name!()); for opt in &["-T", "-w", "--mesg", "--message", "--writable"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } @@ -127,12 +128,9 @@ fn test_mesg() { #[test] fn test_arg1_arg2() { let args = ["am", "i"]; - let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - - new_ucmd!() - .args(&args) - .succeeds() - .stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); } #[test] @@ -147,9 +145,10 @@ fn test_too_many_args() { #[cfg(unix)] #[test] fn test_users() { + let ts = TestScenario::new(util_name!()); for opt in &["-u", "--users"] { - let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str(); - let expect = unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); + let actual = ts.ucmd().arg(opt).succeeds().stdout_move_str(); + let expect = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); println!("actual: {:?}", actual); println!("expect: {:?}", expect); @@ -172,18 +171,18 @@ fn test_users() { #[test] fn test_lookup() { let opt = "--lookup"; - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } #[cfg(unix)] #[test] fn test_dead() { + let ts = TestScenario::new(util_name!()); for opt in &["-d", "--dead"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } @@ -197,20 +196,11 @@ fn test_all_separately() { // -a, --all same as -b -d --login -p -r -t -T -u let args = ["-b", "-d", "--login", "-p", "-r", "-t", "-T", "-u"]; - let expected_stdout = unwrap_or_return!(expected_result(util_name!(), &args)).stdout_move_str(); - let scene = TestScenario::new(util_name!()); - scene - .ucmd() - .args(&args) - .succeeds() - .stdout_is(expected_stdout); - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &["--all"])).stdout_move_str(); - scene - .ucmd() - .arg("--all") - .succeeds() - .stdout_is(expected_stdout); + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &["--all"])).stdout_move_str(); + ts.ucmd().arg("--all").succeeds().stdout_is(expected_stdout); } #[cfg(unix)] @@ -221,9 +211,9 @@ fn test_all() { return; } + let ts = TestScenario::new(util_name!()); for opt in &["-a", "--all"] { - let expected_stdout = - unwrap_or_return!(expected_result(util_name!(), &[opt])).stdout_move_str(); - new_ucmd!().arg(opt).succeeds().stdout_is(expected_stdout); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &[opt])).stdout_move_str(); + ts.ucmd().arg(opt).succeeds().stdout_is(expected_stdout); } } diff --git a/tests/common/util.rs b/tests/common/util.rs index 2cff46224..acffaca13 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -701,7 +701,7 @@ impl AtPath { /// Fixtures can be found under `tests/fixtures/$util_name/` pub struct TestScenario { bin_path: PathBuf, - util_name: String, + pub util_name: String, pub fixtures: AtPath, tmpd: Rc, } @@ -1171,8 +1171,9 @@ pub fn check_coreutil_version( /// use crate::common::util::*; /// #[test] /// fn test_xyz() { -/// let result = new_ucmd!().run(); -/// let exp_result = unwrap_or_return!(expected_result(util_name!(), &[])); +/// let ts = TestScenario::new(util_name!()); +/// let result = ts.ucmd().run(); +/// let exp_result = unwrap_or_return!(expected_result(&ts, &[])); /// result /// .stdout_is(exp_result.stdout_str()) /// .stderr_is(exp_result.stderr_str()) @@ -1180,12 +1181,11 @@ pub fn check_coreutil_version( /// } ///``` #[cfg(unix)] -pub fn expected_result(util_name: &str, args: &[&str]) -> std::result::Result { - let util_name = &host_name_for(util_name); +pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result { + let util_name = &host_name_for(&ts.util_name); println!("{}", check_coreutil_version(util_name, VERSION_MIN)?); - let scene = TestScenario::new(util_name); - let result = scene + let result = ts .cmd_keepenv(util_name.as_ref()) .env("LC_ALL", "C") .args(args) @@ -1470,7 +1470,9 @@ mod tests { #[test] #[cfg(unix)] fn test_expected_result() { - assert!(expected_result("id", &[]).is_ok()); - assert!(expected_result("no test name", &[]).is_err()); + let ts = TestScenario::new("id"); + assert!(expected_result(&ts, &[]).is_ok()); + let ts = TestScenario::new("no test name"); + assert!(expected_result(&ts, &[]).is_err()); } } From d57f474ae1c5d33b2482a28d7663cced0f0958ac Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Thu, 8 Jul 2021 00:21:28 +0200 Subject: [PATCH 09/10] test_whoami: refactor use expected_result and whoami from common/util.rs --- tests/by-util/test_whoami.rs | 86 ++++++++++++++---------------------- 1 file changed, 34 insertions(+), 52 deletions(-) diff --git a/tests/by-util/test_whoami.rs b/tests/by-util/test_whoami.rs index a98541b2d..cba941558 100644 --- a/tests/by-util/test_whoami.rs +++ b/tests/by-util/test_whoami.rs @@ -1,63 +1,45 @@ +// * This file is part of the uutils coreutils package. +// * +// * For the full copyright and license information, please view the LICENSE +// * file that was distributed with this source code. + use crate::common::util::*; -// Apparently some CI environments have configuration issues, e.g. with 'whoami' and 'id'. -// If we are running inside the CI and "needle" is in "stderr" skipping this test is -// considered okay. If we are not inside the CI this calls assert!(result.success). -// -// From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)" -// stderr: "whoami: failed to get username" -// Maybe: "adduser --uid 1001 username" can put things right? -fn skipping_test_is_okay(result: &CmdResult, needle: &str) -> bool { - if !result.succeeded() { - println!("result.stdout = {}", result.stdout_str()); - println!("result.stderr = {}", result.stderr_str()); - if is_ci() && result.stderr_str().contains(needle) { - println!("test skipped:"); - return true; - } else { - result.success(); - } - } - false -} - #[test] +#[cfg(unix)] fn test_normal() { - let (_, mut ucmd) = at_and_ucmd!(); + let ts = TestScenario::new(util_name!()); + let result = ts.ucmd().run(); + let exp_result = unwrap_or_return!(expected_result(&ts, &[])); - let result = ucmd.run(); - - // use std::env; - // println!("env::var(CI).is_ok() = {}", env::var("CI").is_ok()); - // for (key, value) in env::vars() { - // println!("{}: {}", key, value); - // } - - if skipping_test_is_okay(&result, "failed to get username") { - return; - } - - result.no_stderr(); - assert!(!result.stdout_str().trim().is_empty()); + result + .stdout_is(exp_result.stdout_str()) + .stderr_is(exp_result.stderr_str()) + .code_is(exp_result.code()); } #[test] -#[cfg(not(windows))] +#[cfg(unix)] fn test_normal_compare_id() { - let scene = TestScenario::new(util_name!()); - - let result_ucmd = scene.ucmd().run(); - if skipping_test_is_okay(&result_ucmd, "failed to get username") { - return; + let ts = TestScenario::new("id"); + let id_un = unwrap_or_return!(expected_result(&ts, &["-un"])); + if id_un.succeeded() { + new_ucmd!().succeeds().stdout_is(id_un.stdout_str()); + } else if is_ci() && id_un.stderr_str().contains("cannot find name for user ID") { + println!("test skipped:"); + } else { + id_un.success(); + } +} + +#[test] +#[cfg(unix)] +fn test_normal_compare_env() { + let whoami = whoami(); + if whoami == "nobody" { + println!("test skipped:"); + return; + } else { + new_ucmd!().succeeds().stdout_is(format!("{}\n", whoami)); } - - let result_cmd = scene.cmd("id").arg("-un").run(); - if skipping_test_is_okay(&result_cmd, "cannot find name for user ID") { - return; - } - - assert_eq!( - result_ucmd.stdout_str().trim(), - result_cmd.stdout_str().trim() - ); } From 14b348dd4b4c467ad44426852c4a4d270553f092 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Thu, 8 Jul 2021 01:32:39 +0200 Subject: [PATCH 10/10] tests: fix tests for CICD environment --- tests/by-util/test_du.rs | 3 +-- tests/by-util/test_groups.rs | 2 ++ tests/by-util/test_whoami.rs | 5 ++++- tests/common/util.rs | 12 +++++++++--- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 607d5dc45..e63aa4585 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -573,8 +573,7 @@ fn test_du_bytes() { #[cfg(all( not(target_vendor = "apple"), not(target_os = "windows"), - not(target_os = "freebsd"), - not(target_os = "linux") + not(target_os = "freebsd") ))] result.stdout_contains("21529\t./subdir\n"); } diff --git a/tests/by-util/test_groups.rs b/tests/by-util/test_groups.rs index 14e5a356d..73837235f 100644 --- a/tests/by-util/test_groups.rs +++ b/tests/by-util/test_groups.rs @@ -3,6 +3,8 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. +//spell-checker: ignore coreutil + use crate::common::util::*; const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced in GNU's coreutils 8.31 diff --git a/tests/by-util/test_whoami.rs b/tests/by-util/test_whoami.rs index cba941558..0afe94161 100644 --- a/tests/by-util/test_whoami.rs +++ b/tests/by-util/test_whoami.rs @@ -3,6 +3,7 @@ // * For the full copyright and license information, please view the LICENSE // * file that was distributed with this source code. +#[cfg(unix)] use crate::common::util::*; #[test] @@ -39,7 +40,9 @@ fn test_normal_compare_env() { if whoami == "nobody" { println!("test skipped:"); return; - } else { + } else if !is_ci() { new_ucmd!().succeeds().stdout_is(format!("{}\n", whoami)); + } else { + println!("test skipped:"); } } diff --git a/tests/common/util.rs b/tests/common/util.rs index acffaca13..7a641a353 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -10,6 +10,7 @@ use pretty_assertions::assert_eq; #[cfg(target_os = "linux")] use rlimit::{prlimit, rlim}; +#[cfg(unix)] use std::borrow::Cow; use std::env; #[cfg(not(windows))] @@ -1456,9 +1457,10 @@ mod tests { #[cfg(unix)] fn test_check_coreutil_version() { match check_coreutil_version("id", VERSION_MIN) { - Ok(s) => s.starts_with("uutils-tests-"), - Err(s) => s.starts_with("uutils-tests-warning"), + Ok(s) => assert!(s.starts_with("uutils-tests-")), + Err(s) => assert!(s.starts_with("uutils-tests-warning")), }; + #[cfg(target_os = "linux")] std::assert_eq!( check_coreutil_version("no test name", VERSION_MIN), Err("uutils-tests-warning: 'no test name' \ @@ -1471,7 +1473,11 @@ mod tests { #[cfg(unix)] fn test_expected_result() { let ts = TestScenario::new("id"); - assert!(expected_result(&ts, &[]).is_ok()); + // assert!(expected_result(&ts, &[]).is_ok()); + match expected_result(&ts, &[]) { + Ok(r) => assert!(r.succeeded()), + Err(s) => assert!(s.starts_with("uutils-tests-warning")), + } let ts = TestScenario::new("no test name"); assert!(expected_result(&ts, &[]).is_err()); }