mirror of
https://github.com/garrytan/gbrain.git
synced 2026-08-14 08:53:22 +00:00
Wave-assembled from PR #3964 by @NidTamil. Co-Authored-By: Nidhin Tamil <nidhin@ymail.com>
53 lines
2.9 KiB
TypeScript
53 lines
2.9 KiB
TypeScript
/**
|
|
* fork-patch #9 — the sync baseline-commit guard must distinguish a CLEAN
|
|
* unborn-HEAD signal from any ambiguous probe failure (timeout / lock / other)
|
|
* and fail CLOSED on ambiguity. `classifyHeadProbeError` isolates that decision
|
|
* as a pure predicate so the born/unborn/ambiguous distinction is unit-testable
|
|
* without fault injection.
|
|
*
|
|
* Empirical basis (verified on the installed git): `git rev-parse --verify
|
|
* --quiet HEAD` exits EXACTLY 1 with empty stderr on an unborn HEAD, exit 0 on
|
|
* a born HEAD. A 30s execFileSync timeout throws with `signal:'SIGTERM'` and
|
|
* `status:null`; an index/ref lock exits non-zero (e.g. 128) with a `fatal:`
|
|
* line on stderr. Only the clean exit-1 signal may be treated as unborn.
|
|
*/
|
|
import { describe, test, expect } from 'bun:test';
|
|
import { classifyHeadProbeError } from '../src/commands/sync.ts';
|
|
|
|
describe('classifyHeadProbeError: clean-unborn vs ambiguous (fork-patch #9)', () => {
|
|
test("exit 1 + no signal + empty stderr => 'unborn'", () => {
|
|
expect(classifyHeadProbeError({ status: 1, signal: null, stderr: '' })).toBe('unborn');
|
|
expect(classifyHeadProbeError({ status: 1, signal: null, stderr: Buffer.from('') })).toBe('unborn');
|
|
// stderr that trims to empty is still the clean signal.
|
|
expect(classifyHeadProbeError({ status: 1, signal: null, stderr: ' \n' })).toBe('unborn');
|
|
// a missing stderr field (undefined) with the clean exit is still unborn.
|
|
expect(classifyHeadProbeError({ status: 1, signal: null })).toBe('unborn');
|
|
});
|
|
|
|
test("timeout kill (SIGTERM / status null) => 'ambiguous' (the incident class)", () => {
|
|
expect(classifyHeadProbeError({ status: null, signal: 'SIGTERM', stderr: '' })).toBe('ambiguous');
|
|
expect(classifyHeadProbeError({ status: null, signal: 'SIGKILL', stderr: '' })).toBe('ambiguous');
|
|
});
|
|
|
|
test("index/ref lock or any non-empty stderr => 'ambiguous'", () => {
|
|
expect(
|
|
classifyHeadProbeError({ status: 128, signal: null, stderr: "fatal: Unable to create '/x/.git/index.lock': File exists" }),
|
|
).toBe('ambiguous');
|
|
// even exit 1: if stderr is non-empty it is NOT the clean unborn signal.
|
|
expect(classifyHeadProbeError({ status: 1, signal: null, stderr: 'fatal: something' })).toBe('ambiguous');
|
|
});
|
|
|
|
test("any nonzero-but-not-1 exit => 'ambiguous'", () => {
|
|
expect(classifyHeadProbeError({ status: 128, signal: null, stderr: '' })).toBe('ambiguous');
|
|
expect(classifyHeadProbeError({ status: 129, signal: null, stderr: '' })).toBe('ambiguous');
|
|
});
|
|
|
|
test('malformed / missing input never crashes and never claims unborn', () => {
|
|
expect(classifyHeadProbeError(undefined)).toBe('ambiguous');
|
|
expect(classifyHeadProbeError(null)).toBe('ambiguous');
|
|
expect(classifyHeadProbeError({})).toBe('ambiguous');
|
|
expect(classifyHeadProbeError(new Error('boom'))).toBe('ambiguous');
|
|
expect(classifyHeadProbeError('nope')).toBe('ambiguous');
|
|
});
|
|
});
|