Files
Endoleap/tests/headless/network.test.mjs

18 lines
2.0 KiB
JavaScript

/**
* 网络准入门的微任务级测试。容量设为1,用手动Promise控制排队顺序,验证拿到名额后仍要核对身份与取消。
* 这里不发真实HTTP,也不测试服务端幂等或浏览器网络栈。
*/
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {createNetworkGate} from '../../src/lib/canvas-runtime/network.ts';
/** 暴露resolve的手动等待点,让首请求占住名额,测试可在第二请求获准前改变身份或abort。 */
const deferred=()=>{let resolve;const promise=new Promise(yes=>resolve=yes);return{resolve,promise};};
// 首请求等待时使身份失效,次请求不执行;恢复身份后第三请求能执行,证明拒绝的名额已释放。
test('transport rechecks identity after waiting for capacity and releases a rejected permit',async()=>{
let current=true,calls=0;const gate=createNetworkGate(1,()=>{if(!current)throw Error('identity_changed');}),hold=deferred(),signal=new AbortController().signal,first=gate.run(signal,async()=>{calls++;await hold.promise;}),second=assert.rejects(gate.run(signal,async()=>{calls++;}),/identity_changed/);await Promise.resolve();current=false;hold.resolve();await first;await second;assert.equal(calls,1);current=true;await gate.run(signal,async()=>{calls++;});assert.equal(calls,2);
});
// 排队请求先abort,随后释放首请求并运行第三个;调用数与护栏计数都只能包含真正获准的两个任务。
test('an aborted queued transport cannot pass the effect guard or consume the next capacity grant',async()=>{
let guards=0,calls=0;const gate=createNetworkGate(1,()=>guards++),hold=deferred(),signal=new AbortController().signal,abort=new AbortController(),first=gate.run(signal,async()=>{calls++;await hold.promise;}),second=assert.rejects(gate.run(abort.signal,async()=>{calls++;}),/cancelled/);await Promise.resolve();abort.abort(Error('cancelled'));await second;hold.resolve();await first;await gate.run(signal,async()=>{calls++;});assert.equal(calls,2);assert.equal(guards,2);
});