diff options
| -rw-r--r-- | Cargo.lock | 33 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | crates/shirabe/Cargo.toml | 3 | ||||
| -rw-r--r-- | crates/shirabe/tests/cli.rs | 105 |
4 files changed, 142 insertions, 0 deletions
@@ -642,6 +642,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] name = "litemap" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -876,6 +882,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -988,6 +1007,7 @@ dependencies = [ "shirabe-external-packages", "shirabe-php-shim", "shirabe-semver", + "tempfile", "tokio", "url", ] @@ -1109,6 +1129,19 @@ dependencies = [ ] [[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] name = "time" version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -23,6 +23,7 @@ regex = "1.12.3" serde = { version = "1.0.228", features = ["derive"] } serde_json = { version = "1.0.149", features = ["preserve_order"] } sha1 = "0.10.6" +tempfile = "3.27.0" tokio = { version = "1.52.3", features = ["full"] } url = "2.5.8" zip = "8.6.0" diff --git a/crates/shirabe/Cargo.toml b/crates/shirabe/Cargo.toml index aed4c1c..7b95ae5 100644 --- a/crates/shirabe/Cargo.toml +++ b/crates/shirabe/Cargo.toml @@ -21,5 +21,8 @@ sha1.workspace = true tokio.workspace = true url.workspace = true +[dev-dependencies] +tempfile.workspace = true + [lints] workspace = true diff --git a/crates/shirabe/tests/cli.rs b/crates/shirabe/tests/cli.rs index 09b9746..549e5a3 100644 --- a/crates/shirabe/tests/cli.rs +++ b/crates/shirabe/tests/cli.rs @@ -80,3 +80,108 @@ fn each_command_help() { let failed: Vec<&&str> = COMMANDS.iter().filter(|c| !run(&[c, "--help"])).collect(); assert!(failed.is_empty(), "`<cmd> --help` failed for: {failed:?}"); } + +/// Runs the CLI with `args` from inside an empty temporary directory. Returns true if the call did +/// not panic (any exit code, including non-zero or an `Err` return, counts as success). +fn run_no_panic(args: &[&str]) -> bool { + QUIET_PANIC.call_once(|| std::panic::set_hook(Box::new(|_| {}))); + let _guard = SERIAL.lock().unwrap_or_else(|e| e.into_inner()); + + let original = std::env::current_dir().ok(); + let dir = tempfile::tempdir().expect("create temp dir"); + std::env::set_current_dir(dir.path()).expect("chdir to temp dir"); + + // SAFETY: all environment access here happens while holding `SERIAL`, so no other thread + // touches the environment or working directory concurrently. + unsafe { + std::env::remove_var("COLUMNS"); + std::env::remove_var("LINES"); + } + + let mut argv = vec!["composer".to_string()]; + argv.extend(args.iter().map(|s| s.to_string())); + let result = catch_unwind(AssertUnwindSafe(|| shirabe::run(argv))); + + if let Some(orig) = original { + let _ = std::env::set_current_dir(orig); + } + + result.is_ok() +} + +macro_rules! run_no_panic_tests { + ($( $(#[$attr:meta])* $name:ident => $cmd:expr ),* $(,)?) => { + $( + $(#[$attr])* + #[test] + fn $name() { + assert!(run_no_panic(&[$cmd]), "`{}` panicked", $cmd); + } + )* + }; +} + +run_no_panic_tests! { + run_about => "about", + #[ignore = "currently panics"] + run_archive => "archive", + #[ignore = "currently panics"] + run_audit => "audit", + #[ignore = "currently panics"] + run_browse => "browse", + #[ignore = "currently panics"] + run_bump => "bump", + #[ignore = "currently panics"] + run_check_platform_reqs => "check-platform-reqs", + #[ignore = "currently panics"] + run_clear_cache => "clear-cache", + #[ignore = "currently panics"] + run_config => "config", + #[ignore = "currently panics"] + run_create_project => "create-project", + #[ignore = "currently panics"] + run_depends => "depends", + #[ignore = "currently panics"] + run_diagnose => "diagnose", + #[ignore = "currently panics"] + run_dump_autoload => "dump-autoload", + #[ignore = "currently panics"] + run_exec => "exec", + #[ignore = "currently panics"] + run_fund => "fund", + #[ignore = "stack overflow aborts the process (uncatchable)"] + run_global => "global", + #[ignore = "currently panics"] + run_init => "init", + #[ignore = "currently panics"] + run_install => "install", + #[ignore = "currently panics"] + run_licenses => "licenses", + #[ignore = "currently panics"] + run_outdated => "outdated", + #[ignore = "currently panics"] + run_prohibits => "prohibits", + #[ignore = "currently panics"] + run_reinstall => "reinstall", + #[ignore = "currently panics"] + run_remove => "remove", + #[ignore = "currently panics"] + run_repository => "repository", + #[ignore = "currently panics"] + run_require => "require", + #[ignore = "currently panics"] + run_run_script => "run-script", + #[ignore = "currently panics"] + run_search => "search", + run_self_update => "self-update", + #[ignore = "currently panics"] + run_show => "show", + #[ignore = "currently panics"] + run_status => "status", + #[ignore = "currently panics"] + run_suggests => "suggests", + #[ignore = "currently panics"] + run_update => "update", + #[ignore = "currently panics"] + run_validate => "validate", +} |
