Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions apps/desktop/electron/backend-ownership.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,19 @@ test('startup reap preserves failed stops for the next launch', async () => {
assert.deepEqual(parseBackendOwnership(store.value()), [entry])
})

test('startup reap stops at the deadline and preserves the unprocessed records', async () => {
test('startup reap stops at the deadline and preserves the unprocessed records', async ({ onTestFinished }) => {
// Advance only when the first probe completes, never with runner scheduling.
const now = vi.spyOn(Date, 'now').mockReturnValue(0)
onTestFinished(() => now.mockRestore())
const first = ownershipEntry({ pid: 60 })
const second = ownershipEntry({ pid: 61 })
const store = memoryStore(stored([first, second]))
const stop = vi.fn()

const ownership = createOwnership(store, {
// Each probe is slow enough to blow a 1ms budget after the first entry.
// Exhaust the budget exactly at the boundary after processing one entry.
matchesIdentity: async () => {
await new Promise(resolve => setTimeout(resolve, 10))
now.mockReturnValue(1)

return false
},
Expand All @@ -201,15 +204,17 @@ test('startup reap stops at the deadline and preserves the unprocessed records',
assert.deepEqual(parseBackendOwnership(store.value()), [second])
})

test('startup reap preserves would-be-reaped records when the budget runs out', async () => {
test('startup reap preserves would-be-reaped records when the budget runs out', async ({ onTestFinished }) => {
const now = vi.spyOn(Date, 'now').mockReturnValue(0)
onTestFinished(() => now.mockRestore())
const first = ownershipEntry({ pid: 62 })
const second = ownershipEntry({ pid: 63 })
const store = memoryStore(stored([first, second]))
const stop = vi.fn()

const ownership = createOwnership(store, {
matchesIdentity: async () => {
await new Promise(resolve => setTimeout(resolve, 10))
now.mockReturnValue(1)

return true
},
Expand Down
12 changes: 12 additions & 0 deletions evals/desktop-reap-clock-pressure.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Replay scheduling pressure without changing Date.now() results:
// NODE_OPTIONS="--require=$PWD/evals/desktop-reap-clock-pressure.cjs" \
// npm run test:desktop:platforms -w apps/desktop -- electron/backend-ownership.test.ts
// The old 1ms fixtures can expire before their first record is processed.
const now = Date.now.bind(Date)
const gate = new Int32Array(new SharedArrayBuffer(4))
Date.now = function () {
if (new Error().stack.includes('/electron/backend-ownership.ts:')) {
Atomics.wait(gate, 0, 0, 5)
}
return now()
}
Loading