memory-cap.integration.test.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. // Integration test for CLAUDE.md §7.3 — V8 heap cap enforced via
  2. // `--v8-flags=--max-old-space-size=<maxMemoryMb>`. Customer code that
  3. // allocates beyond the cap should crash the isolate (V8 OOM). We accept
  4. // any of the kill-coded errors since the exact surface depends on
  5. // whether V8 throws a clean RangeError before the heap is exhausted or
  6. // the process gets killed mid-allocation.
  7. import { describe, expect, test } from 'bun:test';
  8. import { runIntegrationFixture } from './test-helpers.js';
  9. describe('memory cap (integration)', () => {
  10. test('allocating beyond cap kills isolate', async () => {
  11. const { result, cleanup } = await runIntegrationFixture({
  12. fnName: 'test',
  13. deploymentId: 'd1',
  14. poolConfig: { maxMemoryMb: 64, invocationTimeoutMs: 15_000 },
  15. fnSource: `
  16. import { query } from '@briven/cli/server';
  17. export const test = query(async () => {
  18. // V8's --max-old-space-size caps the old-generation heap. Long
  19. // strings get an "external" backing store outside the heap, and
  20. // typed-array buffers live in array-buffer-allocator memory — both
  21. // bypass the cap. Many small JS objects DO live in the old-gen
  22. // heap, so we allocate millions of them to force a real heap OOM.
  23. const arr: unknown[] = [];
  24. for (let i = 0; i < 5_000_000; i++) {
  25. arr.push({ a: i, b: i * 2, c: i * 3, d: 'k' + i });
  26. }
  27. return arr.length;
  28. });
  29. `,
  30. });
  31. try {
  32. expect(result.ok).toBe(false);
  33. if (!result.ok) {
  34. // V8 may surface this as a heap RangeError (function_threw),
  35. // a process kill (isolate_crashed), or a hung allocation that
  36. // hits the invocation timeout. All three prove the cap matters.
  37. expect([
  38. 'isolate_crashed',
  39. 'memory_limit_exceeded',
  40. 'invocation_timeout',
  41. 'function_threw',
  42. ]).toContain(result.code);
  43. }
  44. } finally {
  45. await cleanup();
  46. }
  47. }, 30_000);
  48. });