tricu

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

io-v2-terminal.test.mjs (2765B)


      1 import test from 'node:test';
      2 import assert from 'node:assert/strict';
      3 import {Terminal} from '../dist/io-v2-terminal.js';
      4 const read=(id,limit=4096)=>({run:'1',id,kind:'read',limit});
      5 test('line input is scalar bounded, strict, LF framed and explicitly distinct from EOF',()=>{
      6  const t=new Terminal('1');assert.equal(t.handle(read(1)),undefined);
      7  for(const value of ['x\ny','\ud800','😀'.repeat(257),null])assert.equal(t.line('1',1,value),undefined);
      8  assert.equal(t.line('2',1,'x'),undefined);assert.deepEqual(t.waiting,{run:'1',id:1});
      9  assert.deepEqual(t.line('1',1,''),{run:'1',id:1,kind:'read',bytes:[10],eof:false});
     10  t.handle(read(2));assert.deepEqual(t.endInput('1',2),{run:'1',id:2,kind:'read',bytes:[],eof:true});
     11  assert.equal(t.handle(read(3)).eof,true);t.finish();
     12 });
     13 test('encoded line is split at requested byte bounds, without loss or invented EOF',()=>{
     14  const t=new Terminal('1');t.handle(read(1,1));const parts=[...t.line('1',1,'😀'.repeat(256)).bytes];
     15  for(let id=2;id<=1025;id++) {const r=t.handle(read(id,1));assert.equal(r.eof,false);parts.push(...r.bytes);}
     16  assert.deepEqual(parts,[...new TextEncoder().encode('😀'.repeat(256)),10]);
     17  assert.equal(t.handle(read(1026)),undefined);assert.throws(()=>t.finish(),/pending/);
     18 });
     19 test('cancellation retires exactly the pending prompt; stale submissions do not consume its successor',()=>{
     20  const t=new Terminal('1');t.handle(read(1));
     21  assert.deepEqual(t.handle({run:'1',id:1,kind:'cancel',operation:'read'}),{run:'1',id:1,kind:'cancelled'});
     22  t.handle(read(2));assert.equal(t.line('1',1,'stale'),undefined);assert.equal(t.endInput('1',1),undefined);
     23  assert.equal(t.handle({run:'1',id:1,kind:'cancel',operation:'read'}),undefined);
     24  assert.equal(t.waiting.id,2);assert.deepEqual(t.line('1',2,'ok').bytes,[111,107,10]);t.finish();
     25 });
     26 test('binary write acknowledgement is independent of display decoding and abort races never duplicate it',()=>{
     27  const t=new Terminal('1'),event={run:'1',id:1,kind:'write',stream:'output',bytes:[255,240,159]};
     28  assert.deepEqual(t.handle(event),{run:'1',id:1,kind:'write',count:3});
     29  assert.equal(t.handle({run:'1',id:1,kind:'cancel',operation:'write'}),undefined);
     30  assert.throws(()=>t.handle(event),/stale/);t.finish();
     31  assert.deepEqual(t.output.snapshot().output.bytes,event.bytes);assert.equal(t.output.snapshot().output.tokens.at(-1).reason,'incomplete');
     32 });
     33 test('invalid input events preserve current waits and do not consume future identities',()=>{
     34  const t=new Terminal('1');assert.throws(()=>t.handle(read(2,0)),/read/);t.handle(read(1));
     35  assert.throws(()=>t.handle(read(2)),/read/);assert.throws(()=>t.handle({...read(2),run:'2'}),/event/);
     36  assert.equal(t.waiting.id,1);t.endInput('1',1);assert.equal(t.handle(read(2)).eof,true);
     37 });