execution.test.mjs (4150B)
1 import test from 'node:test'; 2 import assert from 'node:assert/strict'; 3 import {Graph} from '../dist/graph.js'; 4 import {BROWSER_BUDGET,collectionPolicy,operationFailure,operationTimeout,PACKAGE_LOAD_MS} from '../dist/execution.js'; 5 import {ActiveClock} from '../dist/clock.js'; 6 7 test('browser execution has no configurable ceilings; GC is independent',()=>{ 8 assert.deepEqual(BROWSER_BUDGET,{nodes:Infinity,fuel:Infinity,stack:Infinity}); 9 const g=new Graph(BROWSER_BUDGET,collectionPolicy(BROWSER_BUDGET)); 10 assert.equal(g.stats.fuel,Infinity); 11 assert.deepEqual(collectionPolicy(BROWSER_BUDGET),{threshold:250000}); 12 // Finite evaluator budgets remain available to bounded reference tests. 13 assert.deepEqual(collectionPolicy({nodes:100}),{threshold:100}); 14 assert.equal(collectionPolicy({nodes:1}),undefined); 15 }); 16 17 function fakeClock(){ 18 let now=0,id=0,expired=0;const pending=new Map(); 19 const clock=new ActiveClock(()=>expired++,()=>now,(fn,delay)=>{pending.set(++id,{fn,delay});return id;},key=>pending.delete(key)); 20 return {clock,pending,elapsed(ms){now+=ms;},fire(){const [key,item]=pending.entries().next().value;pending.delete(key);now+=item.delay;item.fn();},get expired(){return expired;}}; 21 } 22 test('active deadline excludes pauses, restarts per operation and supports off',()=>{ 23 const f=fakeClock();f.clock.reset(1000);f.clock.start();f.clock.start();assert.equal(f.pending.size,1); 24 f.elapsed(400);f.clock.pause();assert.equal(f.pending.size,0); 25 f.elapsed(10000);f.clock.start();assert.equal([...f.pending.values()][0].delay,600); 26 f.fire();assert.equal(f.expired,1); 27 f.clock.reset(2000);f.clock.start();f.clock.pause();assert.equal(f.pending.size,0); 28 f.clock.reset(Infinity);f.clock.start();assert.equal(f.pending.size,0); 29 assert.throws(()=>f.clock.reset(0),/deadline/); 30 }); 31 test('large infrastructure deadlines use signed-32-bit-safe timer chunks',()=>{ 32 const f=fakeClock();f.clock.reset(5000000000);f.clock.start(); 33 assert.equal([...f.pending.values()][0].delay,2147483647); 34 f.fire();assert.equal(f.expired,0);f.fire();assert.equal(f.expired,0); 35 assert.equal([...f.pending.values()][0].delay,705032706); 36 f.fire();assert.equal(f.expired,1);assert.equal(f.pending.size,0); 37 }); 38 39 test('operation work resets preserve cumulative counters, handles and memory caps',()=>{ 40 const g=new Graph({nodes:2,fuel:10,stack:1}),value=g.stem(g.leaf); 41 while(g.stats.fuel>0)g.tick(); 42 assert.throws(()=>g.tick(),/fuel/); 43 const before=g.stats;g.beginOperation(); 44 assert.equal(g.stats.fuel,10); 45 for(const key of ['nodes','work','allocations','peakNodes','collections','reclaimed','gcWork'])assert.equal(g.stats[key],before[key]); 46 assert.equal(g.observe(value).node.kind,'stem'); 47 assert.throws(()=>g.stem(g.leaf),/allocation/); 48 assert.ok(g.stats.work>before.work); 49 const limited=new Graph({fuel:1000,stack:1}); 50 const I=limited.fromTernary('21100');let application=limited.leaf; 51 for(let i=0;i<10;i++)application=limited.app(I,application); 52 limited.beginOperation();assert.throws(()=>limited.force(application),/stack/); 53 const unlimited=new Graph({fuel:Infinity});unlimited.tick();unlimited.beginOperation(); 54 assert.equal(unlimited.stats.fuel,Infinity);assert.equal(unlimited.stats.work,1); 55 }); 56 57 test('operation failures and deadlines identify the actual phase, not generic execution',()=>{ 58 assert.equal(PACKAGE_LOAD_MS,60000); 59 const labels={catalogue:'Program catalogue loading',loading:'Package loading',compiling:'Draft compilation',running:'Program execution',exporting:'Definition export',downloading:'Bundle download'}; 60 for(const [operation,label] of Object.entries(labels)){ 61 assert.equal(operationFailure(operation,'SHA-256 mismatch'),`${label} failed: SHA-256 mismatch`); 62 const timeout=operationTimeout(operation); 63 assert.ok(timeout.startsWith(label)); 64 if(['catalogue','loading','downloading'].includes(operation)){ 65 assert.match(timeout,/timed out/);assert.doesNotMatch(timeout,/active time/); 66 }else assert.match(timeout,/active time limit exceeded/); 67 } 68 assert.equal(operationFailure(undefined,'Invalid literal'),'Invalid literal'); 69 assert.equal(new Set(Object.keys(labels).map(operationTimeout)).size,6); 70 });