| 1 | import test from 'node:test' |
| 2 | import assert from 'node:assert/strict' |
| 3 | import { transformStockSnapshot } from '../dist/stock-adapters.mjs' |
| 4 | import { createHarnessModule } from '../dist/builtin/harness.mjs' |
| 5 | const complete = extra => ({ kind: 'pdf_process', state: 'complete', success: true, exit_code: 0, stdout_truncated: false, stderr_truncated: false, stderr: '', ...extra }) |
| 6 | const decision = input => transformStockSnapshot(input).result.metadata |
| 7 | |
| 8 | test('PDF success is a directive and never carries extracted document bytes', () => { |
| 9 | const value = transformStockSnapshot(complete({})) |
| 10 | assert.deepEqual(value.result.metadata, { kind: 'pdf_decision', code: 'success' }) |
| 11 | assert.equal(value.result.content, '') |
| 12 | }) |
| 13 | test('PDF stdout overflow wins over process failure and stderr', () => { |
| 14 | assert.deepEqual(decision(complete({ success: false, exit_code: 2, stdout_truncated: true, stderr: 'bad input' })), { kind: 'pdf_decision', code: 'execution', message: 'pdftotext output exceeded the 16777216 byte safety limit' }) |
| 15 | }) |
| 16 | test('PDF errors preserve exit-code, empty stderr, signal and truncation spelling', () => { |
| 17 | assert.equal(decision(complete({ success: false, exit_code: 2, stderr: 'bad\ufffd[31m' })).message, 'pdftotext failed (exit Some(2)): bad\ufffd[31m') |
| 18 | assert.equal(decision(complete({ success: false, exit_code: null })).message, 'pdftotext failed (exit None): no diagnostic output') |
| 19 | assert.equal(decision(complete({ success: false, exit_code: -7, stderr: 'diagnostic', stderr_truncated: true })).message, 'pdftotext failed (exit Some(-7)): diagnostic [truncated]') |
| 20 | }) |
| 21 | test('PDF typed faults retain their captured status and diagnostic', () => { |
| 22 | for (const state of ['binary_unavailable', 'cancelled', 'timed_out', 'execution']) assert.deepEqual(decision({ kind: 'pdf_process', state, message: 'exact diagnostic' }), { kind: 'pdf_decision', code: state, message: 'exact diagnostic' }) |
| 23 | }) |
| 24 | test('PDF malformed and oversized projections refuse', () => { |
| 25 | for (const value of [complete({ success: 'true' }), complete({ stdout_truncated: null }), complete({ stderr_truncated: 0 }), complete({ exit_code: undefined }), complete({ exit_code: 1.1 }), complete({ exit_code: 2 ** 31 }), complete({ stderr: null }), complete({ stderr: 'x'.repeat(1024 * 1024) }), { kind: 'pdf_process', state: 'retry', message: 'retry' }]) assert.throws(() => transformStockSnapshot(value)) |
| 26 | }) |
| 27 | test('actual compiled harness redeems the exact opaque PDF job once', async () => { |
| 28 | const owner = { plugin_id: 'host:harness', generation: 3, owner_token: 'fixture-owner' } |
| 29 | const calls = [] |
| 30 | const runner = createHarnessModule({ async request(method, params) { calls.push([method, params]); return complete({}) } }, owner) |
| 31 | const value = await runner.run({ owner, execution_id: 'private-pdf-job', ticket: 'single-use-grant', deadline_ms: 1000 }, new AbortController().signal) |
| 32 | assert.deepEqual(value.result.metadata, { kind: 'pdf_decision', code: 'success' }) |
| 33 | assert.deepEqual(calls, [['exec/redeem', { owner, execution_id: 'private-pdf-job', ticket: 'single-use-grant' }]]) |
| 34 | assert.equal(JSON.stringify(calls).includes('pdftotext'), false) |
| 35 | await runner.dispose() |
| 36 | }) |
| 37 | test('PDF runner cancellation refuses late output and never replays the process', async () => { |
| 38 | const owner = { plugin_id: 'host:harness', generation: 3, owner_token: 'fixture-owner' } |
| 39 | const abort = new AbortController() |
| 40 | let finish, calls = 0 |
| 41 | const runner = createHarnessModule({ request() { calls++; return new Promise(resolve => { finish = resolve }) } }, owner) |
| 42 | const pending = runner.run({ owner, execution_id: 'private-pdf-job', ticket: 'single-use-grant', deadline_ms: 1000 }, abort.signal) |
| 43 | abort.abort() |
| 44 | await assert.rejects(pending, /cancelled/) |
| 45 | finish(complete({})); assert.equal(calls, 1) |
| 46 | await runner.dispose() |
| 47 | }) |
| 48 |