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 | |
| 7 | import { describe, expect, test } from 'bun:test'; |
| 8 | |
| 9 | import { runIntegrationFixture } from './test-helpers.js'; |
| 10 | |
| 11 | describe('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 | }); |