test: integrate reliable event recovery and receiving evidence
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { spawn } from 'node:child_process'
|
||||
import { spawn, spawnSync } from 'node:child_process'
|
||||
import { createServer } from 'node:http'
|
||||
import { mkdtemp, readFile, rm } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
@@ -19,7 +19,7 @@ const event = (id = targetId, planId = '2100000000000000001') => ({ eventId: id,
|
||||
payload: { loadingPlanId: planId, syntheticPrivateField: secret } })
|
||||
const close = server => new Promise(resolve => server.close(resolve))
|
||||
|
||||
async function fixture(selector = ['--loading-plan-id', '2100000000000000001']) {
|
||||
async function fixture(selector = ['--loading-plan-id', '2100000000000000001'], eventType = 'LoadingCompleted') {
|
||||
const calls = []
|
||||
const applied = new Set()
|
||||
let invalidAck = false
|
||||
@@ -40,7 +40,7 @@ async function fixture(selector = ['--loading-plan-id', '2100000000000000001'])
|
||||
const directory = await mkdtemp(join(tmpdir(), 'event-fault-offline-'))
|
||||
const log = join(directory, 'evidence.jsonl')
|
||||
const child = spawn(process.env.PYTHON || 'python', [script, '--upstream',
|
||||
`http://127.0.0.1:${consumer.address().port}/internal/events`, '--event-type', 'LoadingCompleted',
|
||||
`http://127.0.0.1:${consumer.address().port}/internal/events`, '--event-type', eventType,
|
||||
...selector, '--log', log], { env: { ...process.env, EVENT_FAULT_CONTROL_TOKEN: controlToken },
|
||||
stdio: ['ignore', 'pipe', 'pipe'] })
|
||||
let output = ''; let errors = ''
|
||||
@@ -179,3 +179,42 @@ test('explicit event-ID selector requires exact event type and forwards unrelate
|
||||
assert.equal(status.attempt, 1)
|
||||
assert.equal(status.eventId, targetId)
|
||||
})
|
||||
|
||||
test('unloading selector pins only the exact source booking and preserves reverse-event ACK recovery', async t => {
|
||||
const bookingId = '2100000000000000066'
|
||||
const proxy = await fixture(['--container-booking-id', bookingId], 'OverseasContainerUnloaded')
|
||||
t.after(() => proxy.stop())
|
||||
await proxy.control('/mode', { mode: 'FAULT' })
|
||||
const unloaded = { ...event(), eventType: 'OverseasContainerUnloaded',
|
||||
payload: { sourceContainerBookingId: bookingId, containerNo: 'TEST-CONTAINER' } }
|
||||
for (const unrelated of [
|
||||
{ ...unloaded, eventId: otherId, payload: { sourceContainerBookingId: '2100000000000000067' } },
|
||||
{ ...unloaded, eventId: otherId, payload: { loadingPlanId: bookingId } },
|
||||
{ ...unloaded, eventId: otherId, eventType: 'OverseasDeliveryCompleted' },
|
||||
]) assert.equal((await proxy.send(unrelated)).status, 200)
|
||||
assert.equal((await proxy.send(unloaded)).status, 503)
|
||||
assert.equal((await proxy.send(unloaded)).status, 503)
|
||||
assert.equal((await proxy.send({ ...unloaded, eventId: samePlanOtherId })).status, 200)
|
||||
const before = proxy.calls.length
|
||||
assert.equal((await proxy.send({ ...unloaded, payload: { sourceContainerBookingId: '2100000000000000067' } })).status, 409)
|
||||
assert.equal(proxy.calls.length, before)
|
||||
await proxy.control('/mode', { mode: 'PASS' })
|
||||
const recovered = await proxy.send(unloaded)
|
||||
assert.equal(recovered.status, 200)
|
||||
assert.equal(JSON.parse(recovered.raw).data.outcome, 'DUPLICATE')
|
||||
const status = await (await proxy.control('/status')).json()
|
||||
assert.equal(status.eventId, targetId)
|
||||
assert.deepEqual(status.records.filter(row => row.errorCode !== 'TARGET_EVENT_HASH_CONFLICT').map(row => row.outcome),
|
||||
['APPLIED', 'DUPLICATE', 'DUPLICATE'])
|
||||
})
|
||||
|
||||
test('booking selector rejects malformed identities and mixed selection before starting listeners', () => {
|
||||
for (const args of [['--container-booking-id', '0'], ['--container-booking-id', '../66'],
|
||||
['--container-booking-id', '66', '--loading-plan-id', '77'], ['--container-booking-id', '66', '--event-id', targetId]]) {
|
||||
const result = spawnSync(process.env.PYTHON || 'python', [script, '--upstream', 'http://127.0.0.1:1/internal/events',
|
||||
'--event-type', 'OverseasContainerUnloaded', ...args], { encoding: 'utf8', timeout: 5000,
|
||||
env: { ...process.env, EVENT_FAULT_CONTROL_TOKEN: controlToken } })
|
||||
assert.equal(result.status, 2)
|
||||
assert.ok(!result.stdout.includes('"ready"'))
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user