io-v2-utf8.test.mjs (2192B)
1 import test from 'node:test'; 2 import assert from 'node:assert/strict'; 3 import {encodeUTF8,decodeUTF8} from '../dist/io-v2-utf8.js'; 4 test('all Unicode scalars match independent platform encoding and strict decoding',()=>{ 5 const encoder=new TextEncoder(); 6 for(let start=0;start<=0x10ffff;start+=1024){ 7 const scalars=[];for(let n=start;n<Math.min(start+1024,0x110000);n++)if(n<0xd800||n>0xdfff)scalars.push(n); 8 const text=String.fromCodePoint(...scalars),expected=[...encoder.encode(text)]; 9 assert.deepEqual(encodeUTF8(text),expected);assert.deepEqual(decodeUTF8(expected,true),{text,carry:[]}); 10 } 11 }); 12 test('every valid multibyte scalar prefix yields only copied bounded carry, and fails when final',()=>{ 13 const encoder=new TextEncoder(); 14 for(let n=128;n<=0x10ffff;n++){ 15 if(n>=0xd800&&n<=0xdfff)continue; 16 const bytes=[...encoder.encode(String.fromCodePoint(n))]; 17 for(let split=1;split<bytes.length;split++){ 18 const prefix=bytes.slice(0,split),out=decodeUTF8(prefix,false); 19 assert.equal(out.text,'');assert.deepEqual(out.carry,prefix);assert.notEqual(out.carry,prefix); 20 } 21 } 22 // Exhaustive prefixes above; explicit final/invalid-prefix controls below keep 23 // exception creation out of the million-scalar loop. 24 for(const bytes of [[0xc2],[0xe0,0xa0],[0xf4,0x8f,0xbf]])assert.throws(()=>decodeUTF8(bytes,true),/incomplete/); 25 }); 26 test('invalid lead/continuation/overlong/surrogate/range prefixes fail before finality',()=>{ 27 for(const bytes of [[0x80],[0xc0],[0xc1],[0xf5],[0xff],[0xe0,0x9f],[0xed,0xa0],[0xf0,0x8f],[0xf4,0x90],[0xc2,0x41],[0xe2,0x82,0x41]]) 28 for(const final of [false,true])assert.throws(()=>decodeUTF8(bytes,final),/invalid UTF-8/); 29 assert.throws(()=>decodeUTF8([65,0xff],false),/at byte 1$/); 30 }); 31 test('BOM, NUL, combining scalars and line endings are unchanged; scalar/byte bounds are separate',()=>{ 32 const text='\ufeffa\0\r\nĪ»še\u0301';assert.deepEqual(decodeUTF8(encodeUTF8(text),true),{text,carry:[]}); 33 assert.equal(encodeUTF8('š'.repeat(1024)).length,4096); 34 assert.throws(()=>encodeUTF8('a'.repeat(1025)),/scalar/);assert.throws(()=>encodeUTF8('\ud800'),/scalar/); 35 assert.throws(()=>decodeUTF8(Array(4097).fill(65),false),/byte/); 36 });