aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock37
-rw-r--r--Cargo.toml1
-rw-r--r--crates/shirabe/Cargo.toml1
-rw-r--r--crates/shirabe/src/lib.rs21
4 files changed, 49 insertions, 11 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1f75c36..5e45bda 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -457,6 +457,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
+name = "futures-executor"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
name = "futures-sink"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1574,6 +1585,31 @@ dependencies = [
]
[[package]]
+name = "serial_test"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "699f4197115b8a7e7ff19c9a315a4bd6fffec26cc4626ef45ecaea389e081c6d"
+dependencies = [
+ "futures-executor",
+ "futures-util",
+ "log",
+ "once_cell",
+ "parking_lot",
+ "serial_test_derive",
+]
+
+[[package]]
+name = "serial_test_derive"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94e153fc76e1c6a068703d6d29c508a0b15c061c4b7e43da59cc097bc342673c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "sha1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1619,6 +1655,7 @@ dependencies = [
"regex",
"serde",
"serde_json",
+ "serial_test",
"sha1",
"shirabe-class-map-generator",
"shirabe-external-packages",
diff --git a/Cargo.toml b/Cargo.toml
index 544bf3a..6aeddda 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,6 +24,7 @@ reqwest = "0.13.4"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = { version = "1.0.149", features = ["preserve_order"] }
serde_urlencoded = "0.7.1"
+serial_test = "3.5.0"
sha1 = "0.11.0"
sha2 = "0.11.0"
tempfile = "3.27.0"
diff --git a/crates/shirabe/Cargo.toml b/crates/shirabe/Cargo.toml
index 7b95ae5..1176165 100644
--- a/crates/shirabe/Cargo.toml
+++ b/crates/shirabe/Cargo.toml
@@ -22,6 +22,7 @@ tokio.workspace = true
url.workspace = true
[dev-dependencies]
+serial_test.workspace = true
tempfile.workspace = true
[lints]
diff --git a/crates/shirabe/src/lib.rs b/crates/shirabe/src/lib.rs
index ec63ee1..9182cbe 100644
--- a/crates/shirabe/src/lib.rs
+++ b/crates/shirabe/src/lib.rs
@@ -47,8 +47,9 @@ pub fn run(argv: Vec<String>) -> anyhow::Result<i32> {
#[cfg(test)]
mod cli_tests {
+ use serial_test::serial;
use std::panic::{AssertUnwindSafe, catch_unwind};
- use std::sync::{Mutex, Once};
+ use std::sync::Once;
const COMMANDS: &[&str] = &[
"about",
@@ -87,20 +88,15 @@ mod cli_tests {
static QUIET_PANIC: Once = Once::new();
- /// `crate::run` reads/writes process-global env, so concurrent invocations race;
- /// serialize them since the default test harness runs tests on many threads.
- static SERIAL: Mutex<()> = Mutex::new(());
-
/// Runs the CLI with `args`. Returns true on clean exit, false on any panic / error / non-zero
/// exit.
fn run(args: &[&str]) -> bool {
QUIET_PANIC.call_once(|| std::panic::set_hook(Box::new(|_| {})));
- let _guard = SERIAL.lock().unwrap_or_else(|e| e.into_inner());
// Each invocation must look like a fresh process.
//
- // SAFETY: all environment access in these tests happens through `crate::run` while holding
- // `SERIAL`, so no other thread reads or writes the environment concurrently with these calls.
+ // SAFETY: every test reaching this code is marked `#[serial]`, so no other thread reads or
+ // writes the environment concurrently with these calls.
unsafe {
std::env::remove_var("COLUMNS");
std::env::remove_var("LINES");
@@ -115,16 +111,19 @@ mod cli_tests {
}
#[test]
+ #[serial]
fn version_flag() {
assert!(run(&["--version"]));
}
#[test]
+ #[serial]
fn help_flag() {
assert!(run(&["--help"]));
}
#[test]
+ #[serial]
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:?}");
@@ -134,14 +133,13 @@ mod cli_tests {
/// 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.
+ // SAFETY: every test reaching this code is marked `#[serial]`, so no other thread touches
+ // the environment or working directory concurrently.
unsafe {
std::env::remove_var("COLUMNS");
std::env::remove_var("LINES");
@@ -163,6 +161,7 @@ mod cli_tests {
$(
$(#[$attr])*
#[test]
+ #[serial]
fn $name() {
assert!(run_no_panic(&[$cmd]), "`{}` panicked", $cmd);
}