Files
buzz/beehive/test/cli-shutdown.test.ts
2026-09-10 03:26:36 -04:00

36 lines
2.0 KiB
TypeScript

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, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { WebSocket } from 'ws';
import { newKey, publicKey, seal, message } from '../src/protocol.ts';
for (const fault of [false, true]) test(`actual relay CLI SIGINT surfaces uncertainty=${fault}`, { timeout: 10000 }, async () => {
const dir = mkdtempSync(join(tmpdir(), 'beehive-cli-close-'));
const secret = newKey(), path = join(dir, 'history.json');
const child = spawn(process.execPath, [...(fault ? ['--import', './test/relay-cli-fault.ts'] : []), 'src/cli.ts', 'relay', '0', publicKey(secret), path], { stdio: ['ignore', 'pipe', 'pipe'] });
let output = '', errors = ''; child.stdout.on('data', b => output = (output + b).slice(-8192)); child.stderr.on('data', b => errors = (errors + b).slice(-8192));
const exited = once(child, 'exit');
let ws: WebSocket | undefined;
try {
while (!output.includes('\n')) await once(child.stdout, 'data');
const address = JSON.parse(output.trim().replace('Development relay listening ', ''));
ws = new WebSocket(`ws://127.0.0.1:${address.port}`); await once(ws, 'open');
const observed = once(ws, fault ? 'close' : 'message');
const envelope = seal(message('inspect', 'h', 'a'), secret); ws.send(JSON.stringify(envelope));
const result = await observed;
if (fault) assert.equal(result[0], 1011);
assert.deepEqual(JSON.parse(readFileSync(path, 'utf8')), [envelope], 'replacement is possible, not a durable rejection');
child.kill('SIGINT');
assert.deepEqual(await exited, [fault ? 1 : 0, null]);
if (fault) assert.match(errors, /storage durability may be uncertain/); else assert.equal(errors, '');
} finally {
ws?.terminate();
if (child.exitCode === null && child.signalCode === null) { child.kill('SIGTERM'); await exited; }
rmSync(dir, { recursive: true, force: true });
}
});