aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-20 14:05:55 +0900
committernsfisis <nsfisis@gmail.com>2026-06-20 14:05:55 +0900
commite77a37c5447a4d122629ef8fbc9bef309668aa89 (patch)
tree3a25db8f65a1a20d19c0962157651984dbbfeb95
parentfc39608de4226286c34aed0c0803edd15a8623a8 (diff)
downloadphp-shirabe-e77a37c5447a4d122629ef8fbc9bef309668aa89.tar.gz
php-shirabe-e77a37c5447a4d122629ef8fbc9bef309668aa89.tar.zst
php-shirabe-e77a37c5447a4d122629ef8fbc9bef309668aa89.zip
test(cli): add more smoke tests
-rw-r--r--Cargo.lock33
-rw-r--r--Cargo.toml1
-rw-r--r--crates/shirabe/Cargo.toml3
-rw-r--r--crates/shirabe/tests/cli.rs105
4 files changed, 142 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 089dfdf..9d585bf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index 0292112..cf1fcd2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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",
+}