50 lines
3.5 KiB
JavaScript
50 lines
3.5 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {createRequire} from 'node:module';
|
|
const require=createRequire(import.meta.url),{createWorkAdmission}=require('../apps/network-broker/work-admission.cjs');
|
|
function deferred(){let resolve,reject;const promise=new Promise((yes,no)=>{resolve=yes;reject=no;});return {promise,resolve,reject};}
|
|
test('outer deadline and abort races cannot free never-settled worker admission',async()=>{
|
|
const admission=createWorkAdmission({maxJobs:2}),first=deferred(),second=deferred();
|
|
const bytes=Buffer.from('synthetic private body');
|
|
const work=admission.run(()=>first.promise,{payload:bytes});
|
|
assert.equal(await Promise.race([work,Promise.resolve('outer aborted')]),'outer aborted');
|
|
assert.equal(bytes.toString(),'synthetic private body');
|
|
const other=admission.run(()=>second.promise);
|
|
assert.equal(await Promise.race([other,Promise.resolve('outer deadline')]),'outer deadline');
|
|
assert.throws(()=>admission.run(()=>{throw Error('must not execute');}),{code:'work_capacity_exhausted'});
|
|
assert.equal(admission.status().active,2);
|
|
first.resolve(42);assert.equal(await work,42);assert.ok(bytes.every(value=>value===0));
|
|
assert.equal(admission.status().active,1);
|
|
second.resolve(17);assert.equal(await other,17);assert.equal(admission.status().active,0);
|
|
});
|
|
test('reservation is synchronous and shared across concurrent callbacks',async()=>{
|
|
const admission=createWorkAdmission({maxJobs:1}),pending=deferred();let calls=0;
|
|
const work=admission.run(()=>{calls++;return pending.promise;});
|
|
assert.throws(()=>admission.run(()=>calls++),{code:'work_capacity_exhausted'});assert.equal(calls,1);
|
|
pending.resolve();await work;
|
|
assert.equal(await admission.run(()=>++calls),2);
|
|
});
|
|
test('sync and async failure preserve identity release slot and wipe private payload',async()=>{
|
|
const admission=createWorkAdmission({maxJobs:1}),failure=new Error('synthetic worker failure'),bytes=Buffer.from('private');
|
|
assert.throws(()=>admission.run(()=>{throw failure;},{payload:bytes}),error=>error===failure);
|
|
assert.ok(bytes.every(value=>value===0));assert.equal(admission.status().active,0);
|
|
const other=Buffer.from('private');
|
|
await assert.rejects(admission.run(()=>Promise.reject(failure),{payload:other}),error=>error===failure);
|
|
assert.ok(other.every(value=>value===0));assert.equal(admission.status().active,0);
|
|
});
|
|
test('close rejects new work without claiming pending workers terminated',async()=>{
|
|
const admission=createWorkAdmission({maxJobs:1}),pending=deferred(),bytes=Buffer.from('still used');
|
|
const work=admission.run(()=>pending.promise,{payload:bytes});admission.close();
|
|
assert.deepEqual(admission.status(),{active:1,maxJobs:1,closed:true,available:0});
|
|
assert.equal(bytes.toString(),'still used');assert.throws(()=>admission.run(()=>true),{code:'work_admission_closed'});
|
|
pending.resolve();await work;assert.equal(admission.status().active,0);assert.ok(bytes.every(value=>value===0));
|
|
});
|
|
test('configuration and admission failures use fixed public errors and immutable status',()=>{
|
|
assert.throws(()=>createWorkAdmission({maxJobs:0}),{message:'work_configuration_invalid'});
|
|
const admission=createWorkAdmission();assert.equal(Object.isFrozen(admission.status()),true);
|
|
assert.throws(()=>admission.run(()=>{}, {payload:'private content'}),{message:'work_configuration_invalid'});
|
|
admission.close();const bytes=Buffer.from('not admitted');
|
|
assert.throws(()=>admission.run(()=>{}, {payload:bytes}),{code:'work_admission_closed'});
|
|
assert.ok(bytes.every(value=>value===0));
|
|
});
|