From 5cc1cc9ef6bc6b0d710e4682e148f9fa96837c70 Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Thu, 29 Oct 2026 19:48:01 +0100 Subject: [PATCH] Tell a stream that fell behind apart from a pause that lost samples CI task 750 failed the pause check in e2e 34 although the pause lost nothing. The stream on the runner never got a second ahead. It had skipped 1.1 s before the pause was clicked, with 0.04 s left ahead. The wait for the second ran out without a word, so the check blamed the pause for samples the stream had lost from the start. - A check of its own before the pause asks for a second ahead and not a sample skipped. A runner too slow to decode fails there now. - When the stream was behind, the pause check judges only the clock, the resume and the stop, and says in its name that the samples were not judged. - Nothing in the product changes. Tests: - e2e 34 on melektaus-atx: ALL PASSED, 149 checks. The new check saw 1.3 MB ahead and 0 samples skipped. Co-Authored-By: Claude Opus 5.5 --- tools/e2e/34-sound.mjs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tools/e2e/34-sound.mjs b/tools/e2e/34-sound.mjs index 4fb3a695..3e12186c 100644 --- a/tools/e2e/34-sound.mjs +++ b/tools/e2e/34-sound.mjs @@ -3964,9 +3964,23 @@ export async function sound(t) { // counted once it is there, so the pause is judged by what it adds. The wait after it lets the // worklet report how far it has read: until then a stretch sent counts as ahead. const headsOnly = statsBefore.streaming.held; - await waitFor(stats, (s) => s.streaming.held - headsOnly >= STREAM_SECOND_BYTES, 40); + const aheadStreamed = await waitFor(stats, (s) => s.streaming.held - headsOnly >= STREAM_SECOND_BYTES, 40); await sleep(500); const heldStreamed = await stats(); + // A runner too slow to decode never gets the second ahead and skips from the start (CI task 750, + // 0.04 s ahead, 1.1 s skipped before the pause): that is told here, not blamed on the pause. + const streamAhead = + aheadStreamed.streaming.held - headsOnly >= STREAM_SECOND_BYTES && + heldStreamed.streaming.skipped === statsBefore.streaming.skipped; + check( + 'before the pause the stream runs a second ahead, not a sample skipped', + streamAhead, + JSON.stringify({ + before: statsBefore.streaming, + ahead: aheadStreamed.streaming, + held: heldStreamed.streaming, + }), + ); await t.clickToolbar('pause'); await sleep(500); const paused = { clock: await json('__gm.sound.clock()'), state: await json('__gm.sound.clockState()') }; @@ -3988,12 +4002,15 @@ export async function sound(t) { Math.max(...(heardLong?.mix ?? [0])) > 0.01, JSON.stringify({ streaming, heardLong }), ); + // Behind before it, the pause cannot be judged by what it skips: the clock and stopping still are. check( - 'the pause holds the stream where it is, it plays on after it without a sample lost, and stopping ends it', + streamAhead + ? 'the pause holds the stream where it is, it plays on after it without a sample lost, and stopping ends it' + : 'the pause holds the clock and stopping ends it (samples not judged: the stream was behind before the pause)', paused.state === 'suspended' && pausedLater === paused.clock && resumedLong.streaming.playing === 1 && - resumedLong.streaming.skipped === heldStreamed.streaming.skipped && + (!streamAhead || resumedLong.streaming.skipped === heldStreamed.streaming.skipped) && stoppedLong.streaming.playing === 0 && stoppedLong.playing === 0, // Held before the pause too: it tells a stream that fell behind from the start from one the