mirror of
https://github.com/stablyai/orca.git
synced 2026-10-20 08:03:28 +00:00
test(dictation): pin the churn clock and the window's lower bound
The two 250-refresh churn tests measured real elapsed time against a 5s window, so a loaded runner that took longer than one window to run the loop would roll the window and go red. Pin Date.now in both. Pinning alone leaves CHURN_WINDOW_MS unpinned below: shrinking it 5_000 -> 50 kept all 13 tests green, yet a 50ms window can never accumulate 250 refreshes and the detector would be dead. Add a storm spread across most of one window so the constant has to be wide enough to hold a sustained storm, not just an instantaneous burst. Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -112,6 +112,7 @@ afterEach(() => {
|
||||
act(() => root?.unmount())
|
||||
document.body.replaceChildren()
|
||||
vi.unstubAllGlobals()
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -191,6 +192,9 @@ describe('speech model download progress storm (render pressure)', () => {
|
||||
})
|
||||
|
||||
it('records the churn breadcrumb when refreshes outrun coalescing', async () => {
|
||||
// Why pin Date.now: the threshold is per 5s window, so a loaded machine that
|
||||
// takes longer than one window to run the loop would measure itself, not the rule.
|
||||
vi.spyOn(Date, 'now').mockReturnValue(1_000_000)
|
||||
// Own store instance: the churn window is per-slice state the other tests advance.
|
||||
const churnStore = create<DictationTestStore>(dictationSlice)
|
||||
for (let refresh = 0; refresh < 250; refresh += 1) {
|
||||
|
||||
@@ -124,6 +124,7 @@ describe('dictation model-state stabilisation', () => {
|
||||
})
|
||||
|
||||
it('reports churn once the renderer is driven far past whole-percent pacing', async () => {
|
||||
pinClock()
|
||||
const store = newStore()
|
||||
reply = [{ id: 'whisper-tiny', status: 'downloading', progress: 0.42 }]
|
||||
for (let refresh = 0; refresh < 250; refresh += 1) {
|
||||
@@ -135,6 +136,23 @@ describe('dictation model-state stabilisation', () => {
|
||||
expect(churn[0].data).toMatchObject({ refreshes: 250, noOpRefreshes: 249 })
|
||||
})
|
||||
|
||||
// Why spread across the window: a burst-only test passes for any window length,
|
||||
// including one too short for a real storm to ever accumulate the threshold. The
|
||||
// window has to be wide enough to hold a sustained storm, not just an instant one.
|
||||
it('still reports a storm that is spread across most of one window', async () => {
|
||||
const clock = pinClock()
|
||||
const store = newStore()
|
||||
reply = [{ id: 'whisper-tiny', status: 'downloading', progress: 0.42 }]
|
||||
for (let refresh = 0; refresh < 250; refresh += 1) {
|
||||
await store.getState().refreshModelStates()
|
||||
clock.advance(19)
|
||||
}
|
||||
|
||||
const churn = churnBreadcrumbs()
|
||||
expect(churn).toHaveLength(1)
|
||||
expect(churn[0].data).toMatchObject({ refreshes: 250, windowMs: 249 * 19 })
|
||||
})
|
||||
|
||||
// Stopping at exactly the threshold cannot tell "fires once" from "fires on every
|
||||
// refresh after", and the second floods the 30-entry ring this breadcrumb is
|
||||
// coalesced into to protect.
|
||||
|
||||
Reference in New Issue
Block a user