Files
baiyue-firstleg/scripts/fba-core-regression-evidence.test.mjs
T

75 lines
5.6 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { assertReadOnlySql, buildReceivingEvidenceSql, receivingEvidenceFromRows, buildCompletionEvidenceSql,
completionEvidenceFromRows, buildEvidenceRemoteScript, createTestEvidenceReaders } from './fba-core-regression-evidence.mjs'
const env=()=>({JENKINS_URL:'https://ci.example.invalid/',JENKINS_USER:'offline-ci',JENKINS_API_TOKEN:'offline-api-secret',FBA_CORE_JENKINS_AGENT:'java-test-agent'})
const scope=()=>({customerId:'2105209721220861954',warehouseId:'193000000000200003',bookingId:'2105220190013755394',
stage:'BEFORE_COMPLETE',containerNo:'TEST-ONE',inboundCodes:['IN-1'],sourceInboundIds:['2105220155339444226'],
expectedPackagesByInbound:{'IN-1':1}})
const completion=()=>({customerId:'90',rootOrderId:'100',sourceOrderIds:['100','101'],eventType:'FIRST_LEG_ORDER_FULFILLMENT_COMPLETED'})
const completionRows=()=>['100','101'].map(orderId=>({customerId:'90',rootOrderId:'100',orderId,
eventType:'FIRST_LEG_ORDER_FULFILLMENT_COMPLETED',count:orderId==='100'?1:0,publishedCount:orderId==='100'?1:0,pendingCount:0,failedCount:0}))
test('both queries use consistent read-only transactions and exact scope without losing long identifiers',()=>{
const sql=buildReceivingEvidenceSql(scope())
assert.equal(buildReceivingEvidenceSql({...scope(),stage:'AFTER_EVENT_RECOVERY'}),sql)
assert.throws(()=>buildReceivingEvidenceSql({...scope(),stage:'UNKNOWN_RECOVERY'}))
assert.equal(assertReadOnlySql(sql),sql)
assert.match(sql,/START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY/)
assert.ok(sql.includes(Buffer.from(scope().customerId).toString('hex')))
assert.doesNotMatch(sql,/customer_id=2105209721220861954/)
assert.match(sql,/CAST\(b.id AS CHAR\)/)
assert.match(assertReadOnlySql(buildCompletionEvidenceSql(completion())),/LEFT JOIN ord_outbox_event/)
})
test('read-only guard rejects mutation, multiple statements, lock or unsafe select effects',()=>{
const sql=buildCompletionEvidenceSql(completion())
for(const statement of ['DELETE FROM ord_order;','SELECT 1 INTO OUTFILE \'x\';','SELECT SLEEP(1);',
'SELECT 1; DROP TABLE x;','SET SESSION autocommit=1;'])assert.throws(()=>assertReadOnlySql(sql.replace(/SELECT .+;/,statement)))
assert.throws(()=>assertReadOnlySql('SELECT 1;'))
assert.throws(()=>buildEvidenceRemoteScript('prod',sql,'test'))
})
test('invalid and injected IDs fail before transport; cancelled child zero evidence cannot disappear',()=>{
assert.throws(()=>buildReceivingEvidenceSql({...scope(),bookingId:'1 OR 1=1'}))
assert.throws(()=>buildCompletionEvidenceSql({...completion(),sourceOrderIds:['100','100']}))
assert.equal(completionEvidenceFromRows(completion(),completionRows()).orders[1].count,0)
for(const mutate of [r=>r.pop(),r=>r[1].customerId='91',r=>r[1].count=null,r=>r[1].orderId='100']) {
const rows=completionRows();mutate(rows);assert.throws(()=>completionEvidenceFromRows(completion(),rows))
}
})
test('receiving rows require exact source and session; empty or foreign scope fails',()=>{
assert.throws(()=>receivingEvidenceFromRows(scope(),[]))
const s=scope(),rows=[{collection:'sources',row:{id:'1',customerId:s.customerId,overseasWarehouseId:s.warehouseId,
sourceContainerBookingId:s.bookingId,containerNo:s.containerNo,sourceInboundId:s.sourceInboundIds[0],inboundCode:'IN-1',sourceRegion:'FIRSTLEG',packageCount:1}},
{collection:'sessions',row:{id:'2',sourceContainerBookingId:s.bookingId,containerNo:s.containerNo,overseasWarehouseId:s.warehouseId}}]
assert.deepEqual(receivingEvidenceFromRows(s,rows).balances,[])
rows[0].row.customerId='99';assert.throws(()=>receivingEvidenceFromRows(s,rows))
})
test('transport frames valid empty rows and suppresses raw remote and connection secrets',async()=>{
let calls=0
const transport=createTestEvidenceReaders(env(),async()=>{calls++;return {ok:true,text:async()=> 'FBA_CORE_JSON='+JSON.stringify({ok:true,rows:[{testProbe:1}]})}})
await transport.preflight();assert.equal(calls,2)
for(const output of ['secret-leak','FBA_CORE_JSON={bad','FBA_CORE_JSON={"ok":false,"error":"password=secret-leak"}']) {
const reader=createTestEvidenceReaders(env(),async()=>({ok:true,text:async()=>output}))
await assert.rejects(reader.preflight(),error=>!error.message.includes('secret-leak'))
}
const reader=createTestEvidenceReaders(env(),async()=>{throw Error('offline-api-secret')})
await assert.rejects(reader.preflight(),/TEST evidence transport failed/)
const script=buildEvidenceRemoteScript('order',buildCompletionEvidenceSql(completion()),'java-test-agent')
assert.equal(script.includes(env().JENKINS_API_TOKEN),false)
})
test('Firstleg receiver evidence stays on its exact TEST container and rejects writes', () => {
const sql = buildCompletionEvidenceSql(completion())
const decode = value => Buffer.from([...value.matchAll(/'([A-Za-z0-9+/=]{40,})'/g)].map(m => m[1]).join(''), 'base64').toString('utf8')
const python = decode(decode(buildEvidenceRemoteScript('firstleg', sql, 'java-test-agent')))
assert.match(python, /docker','inspect','firstleg-test-firstleg'/)
assert.match(python, /get\('Name'\)!='\/firstleg-test-firstleg'/)
assert.match(python, /com\.docker\.compose\.project'\)!='firstleg-test'/)
assert.match(python, /e\['FIRSTLEG_DB_URL'\]/)
assert.match(python, /e\['FIRSTLEG_DB_USERNAME'\]/)
assert.match(python, /MYSQL_PWD=e\['FIRSTLEG_DB_PASSWORD'\]/)
assert.throws(() => buildEvidenceRemoteScript('firstleg', sql.replace('COMMIT;', 'DELETE FROM fl_inbound_order;\nCOMMIT;'), 'java-test-agent'))
assert.throws(() => buildEvidenceRemoteScript('firstleg-prod', sql, 'java-test-agent'))
})