Files
orca/src/relay/git-command-admission.test.ts
T
Neil 328caa2160 fix(git): reduce queries and preserve data across execution hosts (#24602)
* fix(git): reduce queries and preserve data across execution hosts

* fix(ci): exercise pinned Git and serialize mobile dependency entrypoints

* fix(relay): preserve fresh diff retries after hung shared reads

* test(git): wait for fetch barrier before canceling preparation

* fix(i18n): describe index-preserving discard in every locale

* fix(git): retain clone diagnostics and allow WSL policy startup

* test(git): refresh default-base and branch-safety fixtures
2026-10-02 18:05:37 -07:00

146 lines
5.5 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { ProcessSpec } from '../shared/child-process/process-spec'
import { GitAdmissionScheduler } from '../shared/git-admission-scheduler'
const { capture } = vi.hoisted(() => ({ capture: vi.fn() }))
vi.mock('../shared/child-process/run-process', () => ({ runProcess: capture }))
import {
_resetRelayGitAdmissionForTests,
runGitToTermination
} from './git-handler-command-termination'
describe('relay Git command ownership', () => {
let scheduler: GitAdmissionScheduler
const success = { code: 0, signal: null, stdout: 'result', stderr: '', timedOut: false }
beforeEach(() => {
scheduler = new GitAdmissionScheduler({ generalCap: 1, generalHeadroom: 0 })
_resetRelayGitAdmissionForTests(scheduler)
capture.mockReset()
})
afterEach(() => _resetRelayGitAdmissionForTests())
it('bounds reads while preserving explicit write and network timeout policy', async () => {
capture.mockImplementation(async (spec: ProcessSpec) => {
spec.onChildTerminated?.()
return success
})
await runGitToTermination(
['-c', 'core.quotePath=false', 'show', 'HEAD:file'],
{ cwd: '/repo' },
undefined
)
await runGitToTermination(['fetch', 'origin'], { cwd: '/repo' }, undefined)
await runGitToTermination(['reset', '--quiet'], { cwd: '/repo', timeout: 800 }, undefined)
expect(capture.mock.calls.map(([spec]) => spec.timeoutMs)).toEqual([120_000, null, 800])
expect(capture.mock.calls[0][0]).toMatchObject({
terminationBarrier: true,
killOnOutputLimit: true
})
})
it('cancels a queued read without spawning or releasing an active child', async () => {
let finish!: () => void
capture.mockImplementationOnce(
(spec: ProcessSpec) =>
new Promise((resolve) => {
finish = () => {
spec.onChildTerminated?.()
resolve(success)
}
})
)
const active = runGitToTermination(['show', 'HEAD:file'], { cwd: '/repo' }, undefined)
await vi.waitFor(() => expect(capture).toHaveBeenCalledTimes(1))
const controller = new AbortController()
const queued = runGitToTermination(
['show', 'HEAD:other'],
{ cwd: '/repo', signal: controller.signal },
undefined
)
const rejection = expect(queued).rejects.toMatchObject({ name: 'AbortError' })
controller.abort()
await rejection
expect(capture).toHaveBeenCalledTimes(1)
expect(scheduler.snapshot()).toMatchObject({ queued: 0, budgets: { general: { baseUsed: 1 } } })
finish()
await active
expect(scheduler.snapshot().budgets.general.baseUsed).toBe(0)
})
it('holds admission after a capture rejects until child termination is reported', async () => {
let reportTermination: (() => void) | undefined
capture.mockImplementationOnce(async (spec: ProcessSpec) => {
reportTermination = spec.onChildTerminated
throw new Error('capture failed before close')
})
await expect(runGitToTermination(['status'], { cwd: '/repo' }, undefined)).rejects.toThrow(
'before close'
)
expect(scheduler.snapshot().budgets.general.baseUsed).toBe(1)
reportTermination?.()
expect(scheduler.snapshot().budgets.general.baseUsed).toBe(0)
})
it('rejects truncated zero-exit output instead of parsing an incomplete result', async () => {
capture.mockImplementationOnce(async (spec: ProcessSpec) => {
spec.onChildTerminated?.()
return { ...success, outputTruncated: true }
})
await expect(runGitToTermination(['log'], { cwd: '/repo' }, undefined)).rejects.toMatchObject({
code: 'ENOBUFS'
})
})
it('allows truncated diagnostic tails without terminating a successful clone', async () => {
capture.mockImplementationOnce(async (spec: ProcessSpec, mode: string) => {
expect(mode).toBe('tail')
expect(spec).toMatchObject({ maxOutputBytes: 4096, killOnOutputLimit: false })
spec.onChildTerminated?.()
return { ...success, outputTruncated: true }
})
await expect(
runGitToTermination(
['clone', '--progress', 'source', 'target'],
{ cwd: '/repo', maxBuffer: 4096, outputCapture: 'tail' },
undefined
)
).resolves.toEqual({ stdout: 'result', stderr: '' })
expect(scheduler.snapshot().budgets.network.baseUsed).toBe(0)
})
it.each([
{ code: 128, timedOut: false, signal: null, message: 'fatal: repository unavailable' },
{ code: null, timedOut: true, signal: 'SIGTERM', message: 'git clone timed out.' }
])('preserves a noisy clone failure or deadline: $message', async (failure) => {
capture.mockImplementationOnce(async (spec: ProcessSpec) => {
spec.onChildTerminated?.()
return {
...success,
...failure,
stderr: 'fatal: repository unavailable',
outputTruncated: true
}
})
await expect(
runGitToTermination(['clone'], { cwd: '/repo', outputCapture: 'tail' }, undefined)
).rejects.toMatchObject({ code: failure.code, message: failure.message })
})
it('returns captured bytes without round-tripping through UTF-8', async () => {
const bytes = Buffer.from([0, 255, 254, 128, 65])
capture.mockImplementationOnce(async (spec: ProcessSpec) => {
expect(spec.captureStdoutAsBytes).toBe(true)
spec.onChildTerminated?.()
return { ...success, stdout: '', stdoutBytes: bytes }
})
const result = await runGitToTermination(
['show', 'HEAD:file'],
{ cwd: '/repo', captureStdoutAsBytes: true },
undefined
)
expect(result.stdoutBytes).toEqual(bytes)
})
})