diff --git a/static/web_serial_readuntil_test.mjs b/static/web_serial_readuntil_test.mjs new file mode 100644 index 0000000..c7170a9 --- /dev/null +++ b/static/web_serial_readuntil_test.mjs @@ -0,0 +1,69 @@ +/** + * Node regression tests for Web Serial readUntil buffer handling. + * Run: node led-tool/static/web_serial_readuntil_test.mjs + */ + +function bytesIndexOf(buf, suffix) { + if (!suffix.length) return 0; + if (buf.length < suffix.length) return -1; + for (let i = 0; i <= buf.length - suffix.length; i += 1) { + let ok = true; + for (let j = 0; j < suffix.length; j += 1) { + if (buf[i + j] !== suffix[j]) { + ok = false; + break; + } + } + if (ok) return i; + } + return -1; +} + +function readUntilConsume(rxBuf, suffixBytes) { + const idx = bytesIndexOf(rxBuf, suffixBytes); + if (idx < 0) return null; + const end = idx + suffixBytes.length; + const matched = rxBuf.slice(0, end); + rxBuf.splice(0, end); + return matched; +} + +function enc(s) { + return [...new TextEncoder().encode(s)]; +} + +function assert(cond, msg) { + if (!cond) throw new Error(msg); +} + +const RAW = 'raw REPL; CTRL-B to exit\r\n'; +const SOFT = 'soft reboot\r\n'; + +// Old bug: one chunk with soft reboot + banner; suffix-at-end + clear-all loses banner. +{ + const rx = enc(`MPY: ${SOFT}${RAW}boot.py line\r\n`); + const soft = enc(SOFT); + const m1 = readUntilConsume(rx, soft); + assert(m1 !== null, 'soft reboot should match'); + const banner = enc(RAW); + const m2 = readUntilConsume(rx, banner); + assert(m2 !== null, 'banner must remain in buffer after soft reboot match'); + assert(rx.length > 0, 'boot.py tail should remain after banner'); +} + +// Banner anywhere in buffer, not only at end. +{ + const rx = enc(`noise${RAW}>>> `); + const banner = enc(RAW); + const m = readUntilConsume(rx, banner); + assert(m !== null, 'banner should match mid-buffer'); +} + +// MPY: soft reboot marker +{ + const rx = enc(`MPY: ${SOFT}`); + const soft = enc('MPY: soft reboot\r\n'); + assert(readUntilConsume(rx, soft) !== null, 'MPY soft reboot marker'); +} + +console.log('web_serial_readuntil_test: ok');