From 980b399ea8eecd7145cfa25d7f4f29d55a8a02cd Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 26 Jul 2026 22:33:42 +0200 Subject: [PATCH] test(session/gamelease): the live-process test waits out the shim window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Its child is `sh` running a script that `exec`s a binary outside the install dir, so neither the image path nor the command line carries the directory — the host's own child is the only signal there is. Which is exactly the case the shim window now gates: a live child that might still turn out to be a launcher is not called the game until that window passes. So "running" legitimately arrives up to SHIM_WINDOW later than it used to, and the assertion at 1.5 s was asserting the old behavior. Waiting it out is the point now, not an accident of timing. The delay is the deliberate cost of the fix: until the window passes there is no way to tell "the child IS the game" from "the child is about to hand off". It shows as a few seconds of `launching` in the console, and only for a title whose store gave us signals. .25: the ignored live test passes (Child -> Running -> terminate via the SIGTERM->SIGKILL group ladder -> Exited, session-end action correctly NOT fired), full suite 305 passed. --- crates/punktfunk-host/src/gamelease.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/punktfunk-host/src/gamelease.rs b/crates/punktfunk-host/src/gamelease.rs index d202627c..975198a8 100644 --- a/crates/punktfunk-host/src/gamelease.rs +++ b/crates/punktfunk-host/src/gamelease.rs @@ -1246,13 +1246,19 @@ mod tests { let shared = lease.shared(); assert!(matches!(shared.kind(), LeaseKind::Child)); - // Seen running on the first poll, because the host holds the child. - std::thread::sleep(Duration::from_millis(1_500)); - assert_eq!(shared.state(), GameState::Running, "should be running"); + // This script `exec`s a binary OUTSIDE the install dir, so neither the image path nor the + // command line carries the directory: the host's own child is the only signal there is. + // Which means the shim window gates it — a live child that might still turn out to be a + // launcher is not called the game until that window has passed. Waiting it out is the point + // of the assertion, not an accident of timing. + std::thread::sleep(SHIM_WINDOW + Duration::from_millis(1_500)); + assert_eq!( + shared.state(), + GameState::Running, + "a child that outlives the shim window IS the game" + ); assert_eq!(EXITS.load(Ordering::SeqCst), 0, "nothing has exited yet"); - // Past the shim window, so its exit counts as the game's rather than a launcher handing off. - std::thread::sleep(SHIM_WINDOW); terminate(shared.clone(), "test asked"); // The ladder asks politely first; `sleep` dies on SIGTERM, so this resolves well inside the