Files
Unlucky-Launcher/crates/core/tests/child_quiet.rs
T
AskaEth 5959a27add
Guards / 依赖许可与来源(cargo-deny) (push) Canceled after 0s
Guards / 文件行数 ≤400 守门 (push) Canceled after 0s
Guards / unsafe 落点守门(集合必须恰好等于期望) (push) Canceled after 0s
Guards / design 零第三方依赖守门 (push) Canceled after 0s
Guards / presenter 零 UI 守门 (push) Canceled after 0s
Guards / core 零 UI 守门 (push) Canceled after 0s
Dev Guards / 架构与合规守门(同 main 口径) (push) Canceled after 0s
Dev Guards / fmt (rustfmt --check) (push) Canceled after 0s
Dev Guards / clippy (ubuntu) (push) Canceled after 0s
fix(core): child_quiet.rs 446 行越 400 红线,按职责拆成两个测试文件
M213 r2 把守卫的剥注释+两条新用例都塞进同一个文件,涨到 446 行。tower 的合并门里
400 行扫描算出了 OVER=1,但 push 写在扫描之后没有用它拦住自己,所以 dev 上先红了一次。

- child_quiet.rs(85):quiet 的**行为**测试(管道/退出码/env/错误语义)
- child_quiet_guard.rs(370):源码扫描型守卫(角色表 + 4 条变异对应的用例 + 解析 helper)

拆分后复验:两文件 5+4=9 条全绿;变异 D(discover.rs:156 改裸构造)仍 exit 101 并点名该行
——守卫的牙没在拆分中丢掉。
2026-11-09 15:14:23 +08:00

86 lines
3.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! M213:`platform::child::quiet` 的**行为**测试(它仍是一个普通 `Command`)。
//!
//! 抑制窗口最容易顺手搞坏的是「`.output()` 的管道、退出码、env、错误语义」,
//! 所以这一组用真程序把这四件事各钉一条。
//!
//! 源码扫描型守卫(所有 spawn 是否都经 `quiet`)在 `child_quiet_guard.rs`,
//! 与这里分开是为了让两边都留在 400 行以内,不靠压缩论证换行数。
use std::process::Command;
#[test]
fn quiet_is_a_plain_command_that_still_captures_output() {
// 抑制窗口不能顺手把输出吞了:`.output()` 的管道与退出码必须照旧可用。
let output = shell(&["echo hi"]).output().expect("spawn 失败");
assert!(output.status.success(), "退出码:{}", output.status);
assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "hi");
}
#[test]
fn quiet_keeps_stderr_and_nonzero_exit_code() {
let output = shell(&["echo oops 1>&2", "exit 3"])
.output()
.expect("spawn 失败");
assert_eq!(output.status.code(), Some(3), "退出码没透传");
assert!(
String::from_utf8_lossy(&output.stderr).contains("oops"),
"stderr 没被捕获:{:?}",
String::from_utf8_lossy(&output.stderr),
);
}
#[test]
fn quiet_keeps_env_and_args() {
// 走 argv 与 env 两条通道,证明 `quiet` 没把 Command 包装成别的东西。
let script = if cfg!(windows) {
"echo %ULL_QUIET_PROBE%"
} else {
"echo $ULL_QUIET_PROBE"
};
let output = shell(&[script])
.env("ULL_QUIET_PROBE", "m213")
.output()
.expect("spawn 失败");
assert!(output.status.success(), "退出码:{}", output.status);
assert_eq!(
String::from_utf8_lossy(&output.stdout).trim(),
"m213",
"参数/环境变量在构造器里丢了",
);
}
#[test]
fn quiet_does_not_swallow_spawn_errors() {
// 找不到程序时仍然是 Err:构造器不加任何「失败即静默」的逻辑。
let error = unlucky_core::platform::child::quiet("ull-no-such-program-m213")
.output()
.expect_err("不存在的程序居然 spawn 成功了?");
assert_eq!(error.kind(), std::io::ErrorKind::NotFound);
}
/// 构造器的返回值必须能直接当 `std::process::Command` 用(下游 `run_with_timeout` 就是这么接的)。
#[test]
fn quiet_returns_a_std_command() {
fn takes_command(_: Command) {}
takes_command(unlucky_core::platform::child::quiet("ull-type-check-only"));
}
/// 走构造器起一个 shell,拼上本平台的「跑一段脚本」参数。
fn shell(scripts: &[&str]) -> Command {
let (program, flag) = if cfg!(windows) {
("cmd", "/C")
} else {
("sh", "-c")
};
let mut command = unlucky_core::platform::child::quiet(program);
command.arg(flag);
// Windows 的 `cmd /C` 只吃一条命令行;POSIX 的 `sh -c` 同理,所以用 `&` / `;` 串起来。
let joined = if cfg!(windows) {
scripts.join(" & ")
} else {
scripts.join("; ")
};
command.arg(joined);
command
}