From 82e31fbce0266b452c28eb958507a2920d8b0251 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 5 Oct 2026 13:36:13 -0700 Subject: [PATCH 1/2] chore: claim quest/m1/test-flakes-2/publish-audio-clock Co-Authored-By: Grok 4.7 From dc06301c1623ad4f028d444f7574fd39b0317162 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 5 Oct 2026 13:42:08 -0700 Subject: [PATCH 2/2] test(publish): run the audio delay test on a mock clock The delay case subtracts 100ms from performance.now(). Early in the process that stamp is negative, and encoding rejects it, so the test fails when its file runs alone. Co-Authored-By: Grok 4.7 --- js/publish/src/audio/encoder.test.ts | 39 ++++++++++++------- quest/m1/test-flakes-2/README.md | 1 - quest/m1/test-flakes-2/publish-audio-clock.md | 11 ------ 3 files changed, 25 insertions(+), 26 deletions(-) delete mode 100644 quest/m1/test-flakes-2/publish-audio-clock.md diff --git a/js/publish/src/audio/encoder.test.ts b/js/publish/src/audio/encoder.test.ts index 1152a76b5b..156817e7ee 100644 --- a/js/publish/src/audio/encoder.test.ts +++ b/js/publish/src/audio/encoder.test.ts @@ -1,4 +1,5 @@ import { describe, expect, mock, spyOn, test } from "bun:test"; +import { u53 } from "@moq/hang/catalog"; import * as Moq from "@moq/net"; import { Time } from "@moq/net"; import { Signal } from "@moq/signals"; @@ -320,24 +321,34 @@ test("passes an explicit Opus DTX request to the encoder", async () => { // it, which the catalog advertises as `delay`. test("a rendition trailing the broadcast's earliest advertises delay", async () => { using _webcodecs = installFakeWebCodecs(); - const baseline = new Baseline(); - using env = await setup(baseline); - const { encoder, feed } = env; + // A process that has just started reports performance.now() under 100ms, so a capture "100ms ago" + // is negative and the frame encoder rejects it. A fixed origin keeps every stamp nonnegative. + const clock = spyOn(performance, "now").mockReturnValue(200); + try { + const baseline = new Baseline(); + using env = await setup(baseline); + const { encoder, feed } = env; - expect(encoder.out.catalog.peek()?.delay).toBeUndefined(); + expect(encoder.out.catalog.peek()?.delay).toBeUndefined(); - // A sibling that flushes each frame the instant it is captured. - baseline.observe(0, performance.now() * 1000); + // A sibling that flushes each frame the instant it is captured. + baseline.observe(0, performance.now() * 1000); - // Captured 100ms ago, so this rendition flushes at least that late. - const start = performance.now() * 1000 - 100_000; - for (let index = 0; index < 4; index++) { - await feed.push({ timestamp: Time.Micro(start + index * 20_000), channels: [new Float32Array(960)] }); - } - await feed.drain(); + // Captured 100ms ago, so this rendition flushes at least that late. + const start = performance.now() * 1000 - 100_000; + for (let index = 0; index < 4; index++) { + await feed.push({ timestamp: Time.Micro(start + index * 20_000), channels: [new Float32Array(960)] }); + } + await feed.drain(); - expect(env.written.length).toBe(2); - expect(encoder.out.catalog.peek()?.delay).toBeGreaterThanOrEqual(100); + expect(env.written).toEqual([ + [100_000, 1], + [120_000, 1], + ]); + expect(encoder.out.catalog.peek()?.delay).toBe(u53(100)); + } finally { + clock.mockRestore(); + } }); // Regression: codec settings that can't resolve left the encoder unsettled, so `` never diff --git a/quest/m1/test-flakes-2/README.md b/quest/m1/test-flakes-2/README.md index 345570e472..123198fe9e 100644 --- a/quest/m1/test-flakes-2/README.md +++ b/quest/m1/test-flakes-2/README.md @@ -37,7 +37,6 @@ Public API: none. Wire: none. - [Shaper virtual time](/quest/m1/test-flakes-2/shaper-virtual-time.md) - `moq-shaper` tests judge seeded decisions on paused time, not on wall-clock delivery under load - [Scoped WARN capture](/quest/m1/test-flakes-2/warn-capture.md) - the drop-unfinished tests count only their own WARNs - [moq-mux debounce clock](/quest/m1/test-flakes-2/mux-debounce-clock.md) - the TS export debounce test advances on the paused clock -- [js/publish audio clock](/quest/m1/test-flakes-2/publish-audio-clock.md) - the audio encoder delay test runs on mock time - [WebSocket paused TLS dial](/quest/m1/test-flakes-2/websocket-paused-tls.md) - the fixed-address WebSocket tests stop pausing the clock over a real dial - [Rejoin after idle](/quest/m1/test-flakes-2/rejoin-idle-race.md) - an IETF rejoin never gets the stale warm cache first, because the copy goes idle before the cancel diff --git a/quest/m1/test-flakes-2/publish-audio-clock.md b/quest/m1/test-flakes-2/publish-audio-clock.md deleted file mode 100644 index ccc4becaad..0000000000 --- a/quest/m1/test-flakes-2/publish-audio-clock.md +++ /dev/null @@ -1,11 +0,0 @@ -# [XS] js/publish audio delay test on mock time - -## Goal - -The js/publish audio encoder test "a rendition trailing the broadcast's -earliest advertises delay" passes when its file runs alone. - -## Plan - -It reads the real clock, so timestamps go negative early in the process and -it fails when run alone (#4414). Run it on mock time.