test(desktop): source hand-off test's fake script takes the bridge marker
Contract C2: a script hand-off is confirmed only when the script takes the Desktop's bridge marker in its own name, not when the launcher exits 0. The channel hand-off test mocked spawnUpdaterProcess with a script that never claimed, so apply() waited out the 20 s claim window and correctly reported updater-spawn-failed. The fake now takes the marker as a live foreign pid, and the test releases it after each hand-off (the update finished) so the next apply does not see a live foreign owner. Claim timeout lowered to 2 s. (cherry picked from commit fb43b97f0f501a2693130b4d8828014a380ae211)
This commit is contained in:
@@ -8,6 +8,7 @@ import { promisify } from 'node:util'
|
||||
|
||||
import { expect, it, vi } from 'vitest'
|
||||
|
||||
import { markerPath } from '../update-marker'
|
||||
import * as updaterProcess from '../updater-process'
|
||||
|
||||
import { type CheckoutStrategyDeps, createCheckoutStrategy } from './checkout'
|
||||
@@ -366,6 +367,7 @@ urllib.request.build_opener = local_build
|
||||
isMac: process.platform === 'darwin',
|
||||
defaultUpdateBranch: 'main',
|
||||
updateHandoffDwellMs: 0,
|
||||
handoffClaimTimeoutMs: 2000,
|
||||
resolveUpdateRoot: (): string => root,
|
||||
readSourceUpdate: (install: string, opts: { force?: boolean }): Promise<SourceUpdate | null> =>
|
||||
readSourceUpdate({
|
||||
@@ -395,6 +397,9 @@ urllib.request.build_opener = local_build
|
||||
vi.spyOn(updaterProcess, 'spawnUpdaterProcess').mockImplementation(
|
||||
(command: string, args: string[], options: SpawnOptions): updaterProcess.UpdaterChild => {
|
||||
spawned.push({ command, args, options })
|
||||
// C2: a hand-off has started only once the script takes the Desktop's
|
||||
// bridge marker in its own (live, foreign) name — do that here.
|
||||
fs.writeFileSync(markerPath(home), `${process.ppid}\n${Math.floor(Date.now() / 1000)}\n`)
|
||||
|
||||
return { unref: (): void => {} }
|
||||
}
|
||||
@@ -426,6 +431,8 @@ urllib.request.build_opener = local_build
|
||||
fs.writeFileSync(script, '')
|
||||
expect(await strategy.apply()).toMatchObject({ ok: true, handedOff: true })
|
||||
const handoff: (typeof spawned)[number] | undefined = spawned.pop()
|
||||
// The update ran and released its claim; the next apply starts clean.
|
||||
fs.rmSync(markerPath(home), { force: true })
|
||||
expect(handoff?.args).toContain(script)
|
||||
expect(handoff?.args).toContain(channel)
|
||||
expect(handoff?.args).toContain(process.platform === 'win32' ? '-Channel' : '--channel')
|
||||
@@ -468,6 +475,7 @@ urllib.request.build_opener = local_build
|
||||
expect(spawned.pop()?.args).toEqual(
|
||||
expect.arrayContaining([process.platform === 'win32' ? '-Branch' : '--branch', 'feature/gui'])
|
||||
)
|
||||
fs.rmSync(markerPath(home), { force: true })
|
||||
fs.rmSync(scriptDirectory, { recursive: true, force: true })
|
||||
expect(await strategy.apply()).toMatchObject({ manual: true, command: 'hermes update --branch feature/gui' })
|
||||
// apply() forces a fresh check; under the R2 protocol that re-resolution
|
||||
|
||||
Reference in New Issue
Block a user