mirror of
https://github.com/block/buzz.git
synced 2026-10-29 21:41:33 +00:00
44 lines
3.0 KiB
TypeScript
44 lines
3.0 KiB
TypeScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mkdtempSync, realpathSync, writeFileSync, readFileSync, existsSync, rmSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join, resolve } from 'node:path';
|
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
import { ConversationSession } from '../src/broker.ts';
|
|
import { newKey, publicKey } from '../src/protocol.ts';
|
|
|
|
test('broker enforces model, completion health, cancellation and owned teardown across escaped shims', async () => {
|
|
for (const mode of ['ok', 'optional-ok', 'optional-reject', 'optional-reack-fails', 'model-config-reject', 'reject', 'wrong-model', 'conflict', 'bad-tail', 'delayed', 'cancel', 'foreign-workspace', 'injected-mcp', 'wrong-protocol', 'missing-native', 'missing-profile', 'current-drift', 'config-drift', 'coalesced-drift']) {
|
|
const dir = realpathSync(mkdtempSync(join(tmpdir(), 'bh-broker-test-')));
|
|
const owner = publicKey(newKey());
|
|
const executable = realpathSync(process.execPath); const runtime = join(dir, 'runtime');
|
|
writeFileSync(runtime, `#!/bin/sh\nexec '${executable}' '${resolve('test/conversation-runtime-fixture.ts')}'\n`, { mode: 0o700 });
|
|
writeFileSync(join(dir, 'mode'), mode);
|
|
const session = new ConversationSession({ executable: runtime, relay: 'ws://127.0.0.1:1', ...(['injected-mcp'].includes(mode) ? { replyTool: { executable } } : {}) }, {
|
|
executable, args: [resolve('test/conversation-harness-fixture.ts')], workspace: dir, home: dir, configDirectory: dir,
|
|
databricksHost: 'https://fixture.invalid', model: 'databricks-claude-haiku-4-5',
|
|
}, newKey(), owner, 2000);
|
|
const result = session.verify().then(value => ({ value }), error => ({ error }));
|
|
try {
|
|
if (mode === 'delayed' || mode === 'cancel') {
|
|
for (let i = 0; i < 80 && !existsSync(join(dir, mode === 'cancel' ? 'cancel-observed' : 'prompt-started')); i++) await delay(20);
|
|
assert.ok(existsSync(join(dir, mode === 'cancel' ? 'cancel-observed' : 'prompt-started')));
|
|
session.cancel();
|
|
}
|
|
const r = await result;
|
|
if (['ok', 'optional-ok', 'optional-reject'].includes(mode)) {
|
|
if (mode === 'optional-reject') assert.equal(readFileSync(join(dir, 'config-error-forwarded'), 'utf8'), 'yes');
|
|
assert.ok('value' in r, `${mode}: ${'error' in r ? String(r.error) : 'missing evidence'}`); assert.equal(r.value.session, 'conversation-session');
|
|
for (let i = 0; i < 40 && !existsSync(join(dir, 'reverse-rpc')); i++) await delay(20);
|
|
assert.equal(readFileSync(join(dir, 'reverse-rpc'), 'utf8'), 'ok');
|
|
} else assert.ok('error' in r, `${mode} must not commit evidence`);
|
|
} finally {
|
|
await session.stop();
|
|
for (const file of ['runtime-pid', 'shim-pid', 'harness-pid', 'descendant-pid']) {
|
|
if (existsSync(join(dir, file))) assert.throws(() => process.kill(Number(readFileSync(join(dir, file), 'utf8')), 0), { code: 'ESRCH' }, `${mode}: ${file}`);
|
|
}
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
});
|