crash-recovery.integration.test.ts61 lines · main
1// Integration test for CLAUDE.md §7.4 — when the isolate dies mid-invoke
2// (Deno.exit, segfault, panic) the host must surface `isolate_crashed`
3// promptly rather than waiting the full invocation timeout. Also verifies
4// that uncaught customer errors get tagged `function_threw` with their
5// message preserved (sanitizer is host-side only).
6
7import { describe, expect, test } from 'bun:test';
8
9import { runIntegrationFixture } from './test-helpers.js';
10
11describe('crash recovery (integration)', () => {
12 test('Deno.exit during invoke surfaces isolate_crashed', async () => {
13 const { result, cleanup } = await runIntegrationFixture({
14 fnName: 'test',
15 deploymentId: 'd1',
16 fnSource: `
17 import { query } from '@briven/cli/server';
18 export const test = query(async () => {
19 Deno.exit(7);
20 });
21 `,
22 });
23 try {
24 expect(result.ok).toBe(false);
25 if (!result.ok) {
26 // Drain-on-exit (Task 11) should surface isolate_crashed promptly.
27 // Accept invocation_timeout as a fallback in case the resolver
28 // hasn't been drained by the time we sample.
29 expect(['isolate_crashed', 'invocation_timeout']).toContain(result.code);
30 }
31 } finally {
32 await cleanup();
33 }
34 }, 30_000);
35
36 test('thrown error surfaces function_threw with sanitized message', async () => {
37 const { result, cleanup } = await runIntegrationFixture({
38 fnName: 'test',
39 deploymentId: 'd1',
40 fnSource: `
41 import { query } from '@briven/cli/server';
42 export const test = query(async () => {
43 throw new Error('boom from /tmp/briven-isolate-fake-leak');
44 });
45 `,
46 });
47 try {
48 expect(result.ok).toBe(false);
49 if (!result.ok) {
50 expect(result.code).toBe('function_threw');
51 expect(result.message).toContain('boom');
52 // Sanitizer should NOT have stripped /tmp/briven-isolate-fake-leak from
53 // INSIDE the customer's own message body — that would over-redact. The
54 // sanitizer applies to host-side error paths only. So this assertion
55 // is intentionally not strict on path content.
56 }
57 } finally {
58 await cleanup();
59 }
60 }, 30_000);
61});