io-protocol.test.mjs (2503B)
1 import test from 'node:test'; 2 import assert from 'node:assert/strict'; 3 import {Graph} from '../dist/graph.js'; 4 import {natural,text} from '../dist/codecs.js'; 5 import {canonicalNat,decodeAction,header} from '../dist/io-protocol.js'; 6 function setup(){ 7 const g=new Graph(),poison=g.app(g.leaf,g.leaf),observe=g.observe.bind(g); 8 g.observe=id=>{if(id===poison)throw Error('FORCED opaque payload');return observe(id);}; 9 const request=(group,revision,op,args=poison)=>g.fork(natural(g,10n),g.fork(group,g.fork(revision,g.fork(op,args)))); 10 return {g,poison,request}; 11 } 12 test('v2 header decoding preserves opaque core and future request payloads',()=>{ 13 const {g,poison,request}=setup(); 14 for(let n=0;n<10;n++)assert.deepEqual(decodeAction(g,g.fork(natural(g,BigInt(n)),poison)),{kind:'core',code:n,payload:poison}); 15 for(const n of [11n,255n,256n])assert.throws(()=>decodeAction(g,g.fork(natural(g,n),poison)),/unknown computation/); 16 assert.deepEqual(header(g,request(text(g,'future-9'),natural(g,65535n),text(g,'unknown'))),{kind:'request',group:'future-9',revision:65535,operation:'unknown'}); 17 assert.throws(()=>decodeAction(g,g.leaf),/invalid computation shape/); 18 }); 19 test('v2 names, revisions and bits are bounded and strictly canonical',()=>{ 20 const {g,poison,request}=setup(),good=text(g,'file'),one=natural(g,1n),zero=g.fork(g.leaf,g.leaf); 21 for(const invalid of ['', '-file','1file','File','a_b','a b','a\x7f','a'.repeat(65)]){ 22 assert.throws(()=>decodeAction(g,request(text(g,invalid),one,good)),/invalid facility header/); 23 assert.throws(()=>decodeAction(g,request(good,one,text(g,invalid))),/invalid facility header/); 24 } 25 for(const revision of [g.leaf,zero,natural(g,65536n)])assert.throws(()=>decodeAction(g,request(good,revision,good)),/invalid facility header/); 26 assert.throws(()=>decodeAction(g,request(g.leaf,poison,poison)),/invalid facility header/); 27 assert.equal(canonicalNat(g,zero,8),undefined); 28 assert.throws(()=>decodeAction(g,g.fork(zero,poison)),/unknown computation/); 29 assert.equal(header(g,request(text(g,'a'.repeat(64)),one,good)).group.length,64); 30 let excess=g.fork(poison,poison); 31 for(let i=0;i<64;i++)excess=g.fork(natural(g,97n),excess); 32 assert.throws(()=>decodeAction(g,request(excess,one,good)),/invalid facility header/); 33 let long=g.fork(poison,poison); 34 for(let i=0;i<8;i++)long=g.fork(g.leaf,long); 35 assert.equal(canonicalNat(g,long,8),undefined); 36 assert.throws(()=>decodeAction(g,poison),/FORCED/); // reduction faults are not malformed-header Results 37 });