Files
wehub-resource-sync 6db8fca185
docmd CI verification / verify (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:31:55 +08:00

85 lines
2.9 KiB
JavaScript

/**
* --------------------------------------------------------------------
* docmd : the zero-config documentation engine.
*
* M-11 — `docmd stop` sends SIGTERM first and waits for graceful
* shutdown before escalating to SIGKILL.
*
* Before the fix, `docmd stop` either killed the dev server
* immediately (SIGKILL on first failure) or relied on SIGTERM
* landing without checking whether the dev server had time to run
* its cleanup handlers. After the fix, the dev server installs a
* graceful-shutdown handler on SIGTERM (same as SIGINT) and `docmd
* stop` polls for process exit before escalating.
*
* Run: `node tests/runner.js --only=stop`
* --------------------------------------------------------------------
*/
import {
setup,
writeFile,
runTestFile
} from '../shared.js';
import { spawn, execSync } from 'node:child_process';
import { waitForExit } from '../../packages/core/dist/commands/stop.js';
let passed = 0;
let failed = 0;
const failures = [];
function assert(condition, message) {
if (!condition) {
failed++;
failures.push(message);
console.log(` ❌ ${message}`);
} else {
passed++;
console.log(` ✅ ${message}`);
}
}
export const test = runTestFile({
name: 'Stop sends SIGTERM and waits for graceful exit (M-11)',
emoji: '🛑',
run: async () => {
// waitForExit returns true when the target process exits within
// the grace window. We spawn `sleep 30`, send SIGTERM after a
// short delay, and assert waitForExit returns true within 1s.
{
const child = spawn('sleep', ['30'], { stdio: 'pipe' });
setTimeout(() => {
try { process.kill(child.pid, 'SIGTERM'); } catch { /* ignore */ }
}, 50);
const exited = await waitForExit(child.pid, 1000);
assert(exited, 'M-11: waitForExit returns true after SIGTERM kills a sleep child');
}
// waitForExit returns false when the target process is still
// alive at the timeout. Spawn `sleep 30`, do NOT signal it,
// assert waitForExit returns false within 300ms.
// (Use a short timeout to keep the test fast.)
{
const child = spawn('sleep', ['30'], { stdio: 'pipe' });
const exited = await waitForExit(child.pid, 300);
assert(exited === false, 'M-11: waitForExit returns false when process is still alive at timeout');
try { process.kill(child.pid, 'SIGKILL'); } catch { /* ignore */ }
}
// waitForExit returns true immediately for a pid that does not
// exist (ESRCH). No process spawned.
{
// Pick a pid that's very unlikely to exist. Use a large number.
const fakePid = 999999;
const exited = await waitForExit(fakePid, 1000);
assert(exited, 'M-11: waitForExit returns true for a non-existent pid (ESRCH)');
}
}
});
export const results = {
get passed() { return passed; },
get failed() { return failed; },
get failures() { return [...failures]; }
};