tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

io-events.test.mjs (2877B)


      1 import test from 'node:test';
      2 import assert from 'node:assert/strict';
      3 import {Events} from '../dist/io-events.js';
      4 test('invalid/stale/wrong-kind replies preserve the live read',async()=>{
      5  const e=new Events('1'),c=new AbortController(),pending=e.read(3,c.signal);
      6  assert.equal(e.reply({run:'1',id:1,kind:'read',bytes:[1],eof:false}),false);
      7  const event=e.take()[0];
      8  for(const change of [{run:'2'},{id:2},{kind:'write',count:1},{bytes:[0,1,2,3]},{bytes:[256]},{bytes:[],eof:false},{bytes:[1],eof:true},{kind:'cancelled'}])
      9   assert.equal(e.reply({...event,bytes:[1],eof:false,...change}),false);
     10  assert.equal(e.counts.pending,1);assert(e.reply({...event,bytes:[1,2],eof:false}));assert.deepEqual(await pending,{kind:'read',bytes:[1,2],eof:false});
     11  assert.equal(e.reply({...event,bytes:[1],eof:false}),false);assert.deepEqual(e.counts,{pending:0,queued:0});
     12 });
     13 test('cancellation before dispatch has no host effect; delivered cancellation waits for acknowledgement',async()=>{
     14  const e=new Events('1'),a=new AbortController(),p=e.read(4,a.signal);a.abort();assert.deepEqual(e.take(),[]);assert.deepEqual(await p,{kind:'cancelled'});
     15  const b=new AbortController(),q=e.read(4,b.signal),event=e.take()[0];let settled=false;q.then(()=>{settled=true;});
     16  b.abort();b.abort();await Promise.resolve();assert(!settled);assert.deepEqual(e.take(),[{run:'1',id:event.id,kind:'cancel',operation:'read'}]);
     17  assert(e.reply({...event,kind:'cancelled'}));assert.deepEqual(await q,{kind:'cancelled'});assert.deepEqual(e.counts,{pending:0,queued:0});
     18 });
     19 test('normal completion racing abort acknowledges cleanup but discards its data',async()=>{
     20  const e=new Events('1'),c=new AbortController(),p=e.write('output',[1,2],c.signal),event=e.take()[0];c.abort();
     21  assert(e.reply({...event,kind:'write',count:1}));assert.deepEqual(await p,{kind:'cancelled'});assert.deepEqual(e.take(),[]);
     22 });
     23 test('output snapshots cannot mutate validation; partial progress is explicit',async()=>{
     24  const e=new Events('1'),bytes=[1,2],c=new AbortController(),p=e.write('error',bytes,c.signal);bytes.push(3);
     25  const event=e.take()[0];event.bytes.push(4);event.kind='read';
     26  assert(!e.reply({run:'1',id:1,kind:'write',count:3}));assert(e.reply({run:'1',id:1,kind:'write',count:1}));
     27  assert.deepEqual(await p,{kind:'write',count:1});
     28 });
     29 test('identity exhaustion cannot prevent cancellation or retirement; repeated operations retain no history',async()=>{
     30  const e=new Events('1',1),c=new AbortController(),p=e.read(1,c.signal),event=e.take()[0];
     31  assert.throws(()=>e.read(1,c.signal),/exhausted/);c.abort();assert(e.reply({...event,kind:'cancelled'}));await p;
     32  const many=new Events('2');for(let i=0;i<1000;i++){const pending=many.read(1,new AbortController().signal),ev=many.take()[0];assert(many.reply({...ev,bytes:[],eof:true}));await pending;assert.deepEqual(many.counts,{pending:0,queued:0});}
     33 });