test: keep cargo test output quiet with per-test logs and a failure matrix
cargo test used to be unreadable: subprocesses inherited the terminal, so dpkg-buildpackage, apt and configure output interleaved with the harness summary, and env_logger lines from parallel tests crossed each other. New test_support module, compiled into test binaries only (inert stubs otherwise) and initialized before main via .init_array: - all log output goes to target/pkh-test-logs/<test>.log, one file per test thread, so concurrent tests never interleave - context-launched commands are captured line by line into the same file (driver-level wrapper); test-code spawns use run_logged() - a panic hook records failures and an atexit callback prints a matrix (test name, panic location, message, log path) after the libtest summary; tests panicking on purpose can opt out with a guard Also fixes two test bugs found on the way: - diff_checkbuilddeps_matrix compared dpkg-checkbuilddeps diagnostics against English messages without pinning the locale - run_source_build in differential tests now captures output like the live-UI path does
This commit is contained in:
+32
-24
@@ -210,7 +210,10 @@ pub fn run_source_build(
|
||||
opts: &SourceBuildOptions,
|
||||
ui: Option<Arc<DebUi>>,
|
||||
) -> Result<SourceBuildOutput, Box<dyn Error>> {
|
||||
let sink: Option<Arc<dyn LineSink>> = ui.as_ref().map(|u| u.sink());
|
||||
// Without a live UI, test runs still capture command output into the
|
||||
// per-test log file instead of letting it inherit the terminal
|
||||
let sink: Option<Arc<dyn LineSink>> =
|
||||
ui.as_ref().map(|u| u.sink()).or_else(crate::test_support::subprocess_sink);
|
||||
// ------------------------------------------------------------------
|
||||
// 1. Sanity checks
|
||||
// ------------------------------------------------------------------
|
||||
@@ -1304,7 +1307,7 @@ mod differential_tests {
|
||||
}
|
||||
}
|
||||
cmd.arg("-f").arg(&tarball).arg(&dir_name);
|
||||
let status = cmd.status().expect("run tar");
|
||||
let status = crate::test_support::run_logged(&mut cmd).expect("run tar");
|
||||
assert!(status.success(), "tar failed for {}", tarball.display());
|
||||
}
|
||||
|
||||
@@ -1312,12 +1315,10 @@ mod differential_tests {
|
||||
}
|
||||
|
||||
fn copy_path(src: &Path, dst_root: &Path) {
|
||||
let status = Command::new("cp")
|
||||
.arg("-a")
|
||||
.arg(src)
|
||||
.arg(dst_root)
|
||||
.status()
|
||||
.expect("run cp -a");
|
||||
let status = crate::test_support::run_logged(
|
||||
Command::new("cp").arg("-a").arg(src).arg(dst_root),
|
||||
)
|
||||
.expect("run cp -a");
|
||||
assert!(
|
||||
status.success(),
|
||||
"cp -a {} {} failed",
|
||||
@@ -1327,11 +1328,12 @@ mod differential_tests {
|
||||
}
|
||||
|
||||
fn run_dpkg(tree: &Path) {
|
||||
let status = Command::new("dpkg-buildpackage")
|
||||
.current_dir(tree)
|
||||
.args(["-S", "-I", "-i", "-nc", "-d", "--no-sign"])
|
||||
.status()
|
||||
.expect("failed to run dpkg-buildpackage (is dpkg-dev installed?)");
|
||||
let status = crate::test_support::run_logged(
|
||||
Command::new("dpkg-buildpackage")
|
||||
.current_dir(tree)
|
||||
.args(["-S", "-I", "-i", "-nc", "-d", "--no-sign"]),
|
||||
)
|
||||
.expect("failed to run dpkg-buildpackage (is dpkg-dev installed?)");
|
||||
assert!(status.success(), "dpkg-buildpackage failed");
|
||||
}
|
||||
|
||||
@@ -1551,8 +1553,12 @@ mod differential_tests {
|
||||
// builtin dependencies (build-essential:native), matching the
|
||||
// native checker which knows no builtins. All options must precede
|
||||
// the control-file operand (POSIX-style option parsing).
|
||||
// The diagnostics are compared against the native checker's English
|
||||
// messages, so the tool must run under the C locale regardless of
|
||||
// the host configuration.
|
||||
let output = Command::new("dpkg-checkbuilddeps")
|
||||
.current_dir(dir.path())
|
||||
.env("LC_ALL", "C")
|
||||
.arg("--admindir")
|
||||
.arg(&admindir)
|
||||
.args(args)
|
||||
@@ -1782,11 +1788,12 @@ Provides: virtual-thing (= 2.0), plain-virtual
|
||||
let ours_tree = write_tree(&ours_root);
|
||||
|
||||
// Golden side: real dpkg-buildpackage binary build.
|
||||
let status = Command::new("dpkg-buildpackage")
|
||||
.current_dir(&golden_tree)
|
||||
.args(["-b", "-d", "--no-sign"])
|
||||
.status()
|
||||
.expect("run dpkg-buildpackage (is dpkg-dev installed?)");
|
||||
let status = crate::test_support::run_logged(
|
||||
Command::new("dpkg-buildpackage")
|
||||
.current_dir(&golden_tree)
|
||||
.args(["-b", "-d", "--no-sign"]),
|
||||
)
|
||||
.expect("run dpkg-buildpackage (is dpkg-dev installed?)");
|
||||
assert!(status.success(), "golden dpkg-buildpackage -b failed");
|
||||
|
||||
// Ours: emulate the pkh deb flow (rules build + rules binary with a
|
||||
@@ -1811,12 +1818,13 @@ Provides: virtual-thing (= 2.0), plain-virtual
|
||||
.collect();
|
||||
|
||||
for target in ["build", "binary"] {
|
||||
let status = Command::new("debian/rules")
|
||||
.current_dir(&ours_tree)
|
||||
.envs(build_env_vars.clone())
|
||||
.arg(target)
|
||||
.status()
|
||||
.expect("run rules target");
|
||||
let status = crate::test_support::run_logged(
|
||||
Command::new("debian/rules")
|
||||
.current_dir(&ours_tree)
|
||||
.envs(build_env_vars.clone())
|
||||
.arg(target),
|
||||
)
|
||||
.expect("run rules target");
|
||||
assert!(status.success(), "debian/rules {target} failed");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user