feat: release Dever 0.1.4 with enforceable project guidance
This commit is contained in:
1 parent
201bdee372
commit
89629c2197
86 files changed
+2798
-338
No files matched your search
@@ -0,0 +1,114 @@
|
||||
use super::{TemporaryProject, process};
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
const DESCENDANTS: &str = r#"
|
||||
/bin/sh -c 'echo $$ > descendant; /bin/sleep 30 & echo $! > grandchild; wait' &
|
||||
while [ ! -s grandchild ]; do :; done
|
||||
"#;
|
||||
|
||||
// subreaper 是进程级状态;此单例测试顺序覆盖所有真实进程场景。
|
||||
#[test]
|
||||
fn case_process_captures_output_times_out_and_reaps_only_owned_descendants() {
|
||||
let original_reaper = rustix::process::child_subreaper().unwrap();
|
||||
let mut unrelated = Command::new("/bin/sleep").arg("30").spawn().unwrap();
|
||||
let result = std::panic::catch_unwind(|| {
|
||||
for (body, descendants, expected) in [
|
||||
("printf hidden; printf hidden-error >&2; exit 0", false, None),
|
||||
(
|
||||
"printf output; printf diagnostic >&2; exit 7",
|
||||
false,
|
||||
Some("exit status: 7"),
|
||||
),
|
||||
(
|
||||
"printf before-timeout; /bin/sleep 30",
|
||||
false,
|
||||
Some("timed out after 100 ms"),
|
||||
),
|
||||
("exit 0", true, None),
|
||||
("printf owned-error >&2; exit 7", true, Some("exit status: 7")),
|
||||
("printf started; wait", true, Some("timed out after 100 ms")),
|
||||
] {
|
||||
let root = TemporaryProject::new().unwrap();
|
||||
let started = Instant::now();
|
||||
let script = if descendants {
|
||||
format!("{DESCENDANTS}\n{body}")
|
||||
} else {
|
||||
body.to_owned()
|
||||
};
|
||||
let result = process::run(
|
||||
Command::new("/bin/sh")
|
||||
.arg("-c")
|
||||
.arg(&script)
|
||||
.env_clear()
|
||||
.current_dir(root.path()),
|
||||
root.path(),
|
||||
Duration::from_millis(100),
|
||||
);
|
||||
assert!(started.elapsed() < Duration::from_secs(5));
|
||||
match expected {
|
||||
None => result.unwrap(),
|
||||
Some(message) => {
|
||||
let failure = result.unwrap_err();
|
||||
assert!(failure.message.contains(message), "{failure:?}");
|
||||
if script.contains("printf output") {
|
||||
assert_eq!(failure.stdout, b"output");
|
||||
assert_eq!(failure.stderr, b"diagnostic");
|
||||
}
|
||||
if script.contains("printf before-timeout") {
|
||||
assert_eq!(failure.stdout, b"before-timeout");
|
||||
}
|
||||
if script.contains("printf owned-error") {
|
||||
assert_eq!(failure.stderr, b"owned-error");
|
||||
}
|
||||
}
|
||||
}
|
||||
for name in ["descendant", "grandchild"] {
|
||||
let path = root.path().join(name);
|
||||
if descendants {
|
||||
let pid = fs::read_to_string(path)
|
||||
.unwrap()
|
||||
.trim()
|
||||
.parse::<u32>()
|
||||
.unwrap();
|
||||
assert!(
|
||||
!std::path::Path::new(&format!("/proc/{pid}")).exists(),
|
||||
"unreaped {name} {pid}"
|
||||
);
|
||||
}
|
||||
}
|
||||
assert_eq!(rustix::process::child_subreaper().unwrap(), original_reaper);
|
||||
}
|
||||
|
||||
let root = TemporaryProject::new().unwrap();
|
||||
let failure = process::run(
|
||||
Command::new("/bin/sh")
|
||||
.arg("-c")
|
||||
.arg("/bin/dd if=/dev/zero bs=131072 count=2 2>/dev/null; printf end >&2; exit 9")
|
||||
.env_clear(),
|
||||
root.path(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(failure.message.contains("exit status: 9"));
|
||||
assert_eq!(failure.stdout.len(), 262_144);
|
||||
assert_eq!(failure.stderr, b"end");
|
||||
|
||||
let root = TemporaryProject::new().unwrap();
|
||||
let failure = process::run(
|
||||
&mut Command::new(root.path().join("missing-executable")),
|
||||
root.path(),
|
||||
Duration::from_millis(100),
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(failure.message.contains("cannot run test process"));
|
||||
assert_eq!(rustix::process::child_subreaper().unwrap(), original_reaper);
|
||||
});
|
||||
// 即使断言失败也回收此对照进程,不能让测试自身遗留资源。
|
||||
let unrelated_running = unrelated.try_wait().unwrap().is_none();
|
||||
let _ = unrelated.kill();
|
||||
unrelated.wait().unwrap();
|
||||
result.unwrap();
|
||||
assert!(unrelated_running, "case cleanup affected an unrelated child");
|
||||
}
|
||||
Reference in new issue
Block a user