|
|
@@ -4759,58 +4759,6 @@ describe('PythonCodeRuntime — hostile peer', () => {
|
|
|
expect(copied).toBeLessThan(256 * 1024)
|
|
|
}, 40_000)
|
|
|
|
|
|
- it('seals trickled stray fragments into blocks without recopying the sealed prefix', async () => {
|
|
|
- // The stray-capture buffer has the same object-overhead exposure as the fd-3
|
|
|
- // reader above: each newline-free `data` chunk is its own Buffer, so a
|
|
|
- // program pacing single-byte `os.write(1, ...)` accumulates one object per
|
|
|
- // write, which the serialized-cost counter cannot see. Past MAX_PENDING_CHUNKS
|
|
|
- // the fragments seal into a finished block; re-merging the whole residual at
|
|
|
- // each threshold instead would copy the sealed prefix again and again, making
|
|
|
- // the cumulative copy volume quadratic. `Buffer.concat` is wrapped to measure
|
|
|
- // that volume — both shapes admit the same final log entry, so the copy total
|
|
|
- // is the discriminator. maxLogBytes is raised so the trickle is retained,
|
|
|
- // not truncated, which is what forces the fragments to accumulate and seal.
|
|
|
- const realConcat = Buffer.concat.bind(Buffer)
|
|
|
- let copied = 0
|
|
|
- Buffer.concat = (list: readonly Uint8Array[], total?: number): Buffer<ArrayBuffer> => {
|
|
|
- for (const part of list) copied += part.length
|
|
|
- return realConcat(list, total)
|
|
|
- }
|
|
|
- let result: CodeRunResult
|
|
|
- try {
|
|
|
- const { runtime } = await setup({ maxLogBytes: 200_000, maxWallMs: 30_000 })
|
|
|
- result = await runtime.run({
|
|
|
- program: [
|
|
|
- 'import os',
|
|
|
- 'for _ in range(60000):',
|
|
|
- ' os.write(1, b"x")',
|
|
|
- ' os.sched_yield()',
|
|
|
- 'os.write(1, b"\\n")',
|
|
|
- 'return "done"',
|
|
|
- ].join('\n'),
|
|
|
- bindings: [],
|
|
|
- })
|
|
|
- } finally {
|
|
|
- Buffer.concat = realConcat
|
|
|
- }
|
|
|
- expect(result.error).toBeUndefined()
|
|
|
- expect(result.value).toBe('done')
|
|
|
- // The trickle coalesces into one log line (no interior newlines). Its exact
|
|
|
- // length depends on pipe coalescing, but it is one entry and non-empty.
|
|
|
- expect(result.logs.length).toBe(1)
|
|
|
- expect((result.logs[0] as string).length).toBeGreaterThan(0)
|
|
|
- // Sealing appends a finished block rather than re-merging everything held, so
|
|
|
- // each byte is copied a bounded number of times. Re-merging the whole
|
|
|
- // residual at every seal threshold instead makes the cumulative copy volume
|
|
|
- // quadratic. Measured like the fd-3 sibling above rather than reasoned about:
|
|
|
- // this sealed shape copies about 120 KB for 60000 trickled bytes, the
|
|
|
- // re-merging shape about 538 KB (the stray path adds one whole-residual
|
|
|
- // concat at the terminating newline over the fd-3 sibling's 119/540, landing
|
|
|
- // at the same order). 256 KiB sits between them with margin on both sides, so
|
|
|
- // reverting the seal to a re-merge turns this assertion red.
|
|
|
- expect(copied).toBeLessThan(256 * 1024)
|
|
|
- }, 40_000)
|
|
|
-
|
|
|
it('caps a huge exception diagnostic child-side before it crosses the wire', async () => {
|
|
|
// A program can raise with a multi-megabyte message; the child must cap
|
|
|
// it at maxValueBytes before formatting/sending, not ship the whole
|