diff --git a/src/uucore/src/lib/macros.rs b/src/uucore/src/lib/macros.rs index 0aa6d8f0a..6836f81aa 100644 --- a/src/uucore/src/lib/macros.rs +++ b/src/uucore/src/lib/macros.rs @@ -5,6 +5,9 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +/// Deduce the name of the binary from the current source code filename. +/// +/// e.g.: `src/uu/cp/src/cp.rs` -> `cp` #[macro_export] macro_rules! executable( () => ({ @@ -18,6 +21,7 @@ macro_rules! executable( }) ); +/// Show an error to stderr in a silimar style to GNU coreutils. #[macro_export] macro_rules! show_error( ($($args:tt)+) => ({ @@ -26,6 +30,7 @@ macro_rules! show_error( }) ); +/// Show a warning to stderr in a silimar style to GNU coreutils. #[macro_export] macro_rules! show_warning( ($($args:tt)+) => ({ @@ -34,6 +39,7 @@ macro_rules! show_warning( }) ); +/// Show an info message to stderr in a silimar style to GNU coreutils. #[macro_export] macro_rules! show_info( ($($args:tt)+) => ({ @@ -42,6 +48,7 @@ macro_rules! show_info( }) ); +/// Show a bad inocation help message in a similar style to GNU coreutils. #[macro_export] macro_rules! show_usage_error( ($($args:tt)+) => ({ @@ -51,6 +58,7 @@ macro_rules! show_usage_error( }) ); +/// Display the provided error message, then `exit()` with the provided exit code #[macro_export] macro_rules! crash( ($exit_code:expr, $($args:tt)+) => ({ @@ -59,6 +67,7 @@ macro_rules! crash( }) ); +/// Calls `exit()` with the provided exit code. #[macro_export] macro_rules! exit( ($exit_code:expr) => ({ @@ -66,6 +75,8 @@ macro_rules! exit( }) ); +/// Unwraps the Result. Instead of panicking, it exists the program with the +/// provided exit code. #[macro_export] macro_rules! crash_if_err( ($exit_code:expr, $exp:expr) => ( @@ -76,6 +87,9 @@ macro_rules! crash_if_err( ) ); +/// Unwraps the Result. Instead of panicking, it shows the error and then +/// returns from the function with the provided exit code. +/// Assumes the current function returns an i32 value. #[macro_export] macro_rules! return_if_err( ($exit_code:expr, $exp:expr) => ( @@ -109,6 +123,8 @@ macro_rules! safe_writeln( ) ); +/// Unwraps the Result. Instead of panicking, it exists the program with exit +/// code 1. #[macro_export] macro_rules! safe_unwrap( ($exp:expr) => ( diff --git a/tests/by-util/test_pathchk.rs b/tests/by-util/test_pathchk.rs index bdce377b3..e24a464e0 100644 --- a/tests/by-util/test_pathchk.rs +++ b/tests/by-util/test_pathchk.rs @@ -9,7 +9,7 @@ fn test_default_mode() { // fail on long inputs new_ucmd!() - .args(&[repeat_str("test", 20000)]) + .args(&["test".repeat(20000)]) .fails() .no_stdout(); } diff --git a/tests/common/macros.rs b/tests/common/macros.rs index 645cfcc67..32ff7cbe8 100644 --- a/tests/common/macros.rs +++ b/tests/common/macros.rs @@ -1,3 +1,6 @@ +/// Assertion helper macro for [`CmdResult`] types +/// +/// [`CmdResult`]: crate::tests::common::util::CmdResult #[macro_export] macro_rules! assert_empty_stderr( ($cond:expr) => ( @@ -7,6 +10,9 @@ macro_rules! assert_empty_stderr( ); ); +/// Assertion helper macro for [`CmdResult`] types +/// +/// [`CmdResult`]: crate::tests::common::util::CmdResult #[macro_export] macro_rules! assert_empty_stdout( ($cond:expr) => ( @@ -16,6 +22,9 @@ macro_rules! assert_empty_stdout( ); ); +/// Assertion helper macro for [`CmdResult`] types +/// +/// [`CmdResult`]: crate::tests::common::util::CmdResult #[macro_export] macro_rules! assert_no_error( ($cond:expr) => ( @@ -26,6 +35,7 @@ macro_rules! assert_no_error( ); ); +/// Platform-independent helper for constructing a PathBuf from individual elements #[macro_export] macro_rules! path_concat { ($e:expr, ..$n:expr) => {{ @@ -47,6 +57,9 @@ macro_rules! path_concat { }}; } +/// Deduce the name of the test binary from the test filename. +/// +/// e.g.: `tests/by-util/test_cat.rs` -> `cat` #[macro_export] macro_rules! util_name { () => { @@ -54,6 +67,16 @@ macro_rules! util_name { }; } +/// Convenience macro for acquiring a [`UCommand`] builder. +/// +/// Returns the following: +/// - a [`UCommand`] builder for invoking the binary to be tested +/// +/// This macro is intended for quick, single-call tests. For more complex tests +/// that require multiple invocations of the tested binary, see [`TestScenario`] +/// +/// [`UCommand`]: crate::tests::common::util::UCommand +/// [`TestScenario]: crate::tests::common::util::TestScenario #[macro_export] macro_rules! new_ucmd { () => { @@ -61,6 +84,18 @@ macro_rules! new_ucmd { }; } +/// Convenience macro for acquiring a [`UCommand`] builder and a test path. +/// +/// Returns a tuple containing the following: +/// - an [`AsPath`] that points to a unique temporary test directory +/// - a [`UCommand`] builder for invoking the binary to be tested +/// +/// This macro is intended for quick, single-call tests. For more complex tests +/// that require multiple invocations of the tested binary, see [`TestScenario`] +/// +/// [`UCommand`]: crate::tests::common::util::UCommand +/// [`AsPath`]: crate::tests::common::util::AsPath +/// [`TestScenario]: crate::tests::common::util::TestScenario #[macro_export] macro_rules! at_and_ucmd { () => {{ diff --git a/tests/common/util.rs b/tests/common/util.rs index 0f1acd49a..a2fab66c6 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use std::env; use std::ffi::OsStr; use std::fs::{self, File, OpenOptions}; @@ -27,7 +29,7 @@ static ALREADY_RUN: &str = " you have already run this UCommand, if you want to testing();"; static MULTIPLE_STDIN_MEANINGLESS: &str = "Ucommand is designed around a typical use case of: provide args and input stream -> spawn process -> block until completion -> return output streams. For verifying that a particular section of the input stream is what causes a particular behavior, use the Command type directly."; -/// Test if the program are running under CI +/// Test if the program is running under CI pub fn is_ci() -> bool { std::env::var("CI") .unwrap_or(String::from("false")) @@ -55,14 +57,6 @@ fn read_scenario_fixture>(tmpd: &Option>, file_rel_p AtPath::new(tmpdir_path).read(file_rel_path.as_ref().to_str().unwrap()) } -pub fn repeat_str(s: &str, n: u32) -> String { - let mut repeated = String::new(); - for _ in 0..n { - repeated.push_str(s); - } - repeated -} - /// A command result is the outputs of a command (streams and status code) /// within a struct which has convenience assertion functions about those outputs #[derive(Debug)] @@ -384,8 +378,10 @@ impl AtPath { /// An environment for running a single uutils test case, serves three functions: /// 1. centralizes logic for locating the uutils binary and calling the utility -/// 2. provides a temporary directory for the test case +/// 2. provides a unique temporary directory for the test case /// 3. copies over fixtures for the utility to the temporary directory +/// +/// Fixtures can be found under `tests/fixtures/$util_name/` pub struct TestScenario { bin_path: PathBuf, util_name: String, @@ -420,12 +416,16 @@ impl TestScenario { ts } + /// Returns builder for invoking the target uutils binary. Paths given are + /// treated relative to the environment's unique temporary test directory. pub fn ucmd(&self) -> UCommand { let mut cmd = self.cmd(&self.bin_path); cmd.arg(&self.util_name); cmd } + /// Returns builder for invoking any system command. Paths given are treated + /// relative to the environment's unique temporary test directory. pub fn cmd>(&self, bin: S) -> UCommand { UCommand::new_from_tmp(bin, self.tmpd.clone(), true) } @@ -495,6 +495,8 @@ impl UCommand { ucmd } + /// Add a parameter to the invocation. Path arguments are treated relative + /// to the test environment directory. pub fn arg>(&mut self, arg: S) -> Box<&mut UCommand> { if self.has_run { panic!(ALREADY_RUN); @@ -505,6 +507,8 @@ impl UCommand { Box::new(self) } + /// Add multiple parameters to the invocation. Path arguments are treated relative + /// to the test environment directory. pub fn args>(&mut self, args: &[S]) -> Box<&mut UCommand> { if self.has_run { panic!(MULTIPLE_STDIN_MEANINGLESS);