test(edit-history): the ssh kill test no longer races the fake's pid file

The test waited for a real 1000 ms timeout and read the pid file afterwards.
On a loaded machine the kill could land before the fake ssh wrote it. It now
waits for the pid and sends the timeout's SIGTERM itself, which is all Node's
timeout does. Without exec the fake still survives and the test goes red.

The invariants said "the reads" go through buildRemoteEditHistoryCommand; the
image probes go through remoteProbePaths, on the same limiter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-11-06 03:17:14 +01:00
1 parent b5066744be
commit 08d99da5ae
2 files changed
+8 -6

No files matched your search

+7 -5
View File
@@ -700,8 +700,10 @@ describe('a read too large for one ssh line', () => {
});
describe('a timeout ends ssh itself', () => {
// Node signals the local `sh -c`. On dash that shell stays the parent of a plain command, so
// only `exec` makes the signal reach ssh. The fake ssh records its pid and then just waits.
// Node's timeout signals the local `sh -c`. On dash that shell stays the parent of a plain
// command, so only `exec` makes the signal reach ssh. The fake ssh records its pid and then
// waits; the test sends the timeout's SIGTERM itself, once that pid is there, so a slow
// machine cannot kill the fake before it wrote it.
it('kills the ssh process, not only the shell around it', async () => {
const bin = mkdtempSync(join(tmpdir(), 'codeman-fake-ssh-'));
const pidFile = join(bin, 'pid');
@@ -713,10 +715,10 @@ describe('a timeout ends ssh itself', () => {
chmodSync(join(bin, 'ssh'), 0o755);
const command = buildRemoteEditHistoryCommand(REMOTE, buildRemoteClaudeTranscriptLocateCommand(['conv-1']));
expect(command).toMatch(/^exec ssh /);
await new Promise<void>((resolve) => {
exec(command, { timeout: 1000, env: { ...process.env, PATH: `${bin}:${process.env.PATH}` } }, () => resolve());
});
const child = exec(command, { env: { ...process.env, PATH: `${bin}:${process.env.PATH}` } });
await expect.poll(() => existsSync(pidFile), { timeout: 10_000 }).toBe(true);
const pid = Number(readFileSync(pidFile, 'utf8'));
child.kill();
const alive = (): boolean => {
try {
process.kill(pid, 0);