Files
stack/packages/cli/tests/case-sudo-fixture.test.mjs

34 lines
1.7 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { spawn } from 'node:child_process';
import { once } from 'node:events';
import { mkdtempSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { fixtureGuard } from './case-sudo-fixture.mjs';
test('fixture cleanup guard starts its budget at the probe marker', async t => {
const dir = mkdtempSync(join(tmpdir(), 'guard-'));
t.after(() => rmSync(dir, { recursive: true, force: true }));
const records = join(dir, 'pids'), startFile = join(dir, 'probe');
writeFileSync(startFile, '');
const child = spawn(process.execPath, ['-e', 'setInterval(()=>{},1000)'], { stdio: 'ignore' });
const exited = once(child, 'exit');
t.after(() => { if (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL'); });
const raw = readFileSync(`/proc/${child.pid}/stat`, 'utf8');
const sid = Number(raw.slice(raw.lastIndexOf(') ') + 2).split(' ')[3]);
writeFileSync(records, `${child.pid} ${sid}\n`);
const stop = fixtureGuard(t, [records], 100, startFile);
// An empty marker is setup, not the start of the observed probe. This wait
// exceeds the cleanup budget deliberately; no production bound is changed.
await new Promise(resolve => setTimeout(resolve, 500));
assert.equal(child.signalCode, null, 'setup must not consume the probe cleanup budget');
writeFileSync(startFile, 'begin 100.00\n');
const terminal = await Promise.race([exited, new Promise((_, reject) => {
const timer = setTimeout(() => reject(new Error('armed fixture guard did not clean up')), 3000);
timer.unref();
})]);
assert.deepEqual(terminal, [null, 'SIGKILL']);
await stop();
});