tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

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 });