1
0
Fork 0
zmodemjs/tests/zheader.js
Daniel Baumann 4d3e0bf859
Adding upstream version 0.1.10+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-04-22 16:48:36 +02:00

309 lines
8.7 KiB
JavaScript
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
"use strict";
var tape = require('blue-tape');
var testhelp = require('./lib/testhelp');
global.Zmodem = require('./lib/zmodem');
var zdle = new Zmodem.ZDLE( { escape_ctrl_chars: true } );
tape('trim_leading_garbage', function(t) {
var header = Zmodem.Header.build('ZACK');
var header_octets = new Map( [
[ "hex", header.to_hex(), ],
[ "b16", header.to_binary16(zdle), ],
[ "b32", header.to_binary32(zdle), ],
] );
var leading_garbage = [
"",
" ",
"\n\n",
"\r\n\r\n",
"*",
"**",
"*\x18",
"*\x18D",
"**\x18",
];
leading_garbage.forEach( (garbage) => {
let garbage_json = JSON.stringify(garbage);
let garbage_octets = testhelp.string_to_octets( garbage );
for ( let [label, hdr_octets] of header_octets ) {
var input = garbage_octets.slice(0).concat( hdr_octets );
var trimmed = Zmodem.Header.trim_leading_garbage(input);
t.deepEquals(trimmed, garbage_octets, `${garbage_json} + ${label}: garbage trimmed`);
t.deepEquals(input, hdr_octets, `… leaving the header`);
}
} );
//----------------------------------------------------------------------
//input, number of bytes trimmed
var partial_trims = [
[ "*", 0 ],
[ "**", 0 ],
[ "***", 1 ],
[ "*\x18**", 2 ],
[ "*\x18*\x18", 2 ],
[ "*\x18*\x18**", 4 ],
[ "*\x18*\x18*\x18", 4 ],
];
partial_trims.forEach( (cur) => {
let [ input, trimmed_count ] = cur;
let input_json = JSON.stringify(input);
let input_octets = testhelp.string_to_octets(input);
let garbage = Zmodem.Header.trim_leading_garbage(input_octets.slice(0));
t.deepEquals(
garbage,
input_octets.slice(0, trimmed_count),
`${input_json}: trim first ${trimmed_count} byte(s)`
);
} );
t.end();
});
//Test that we parse a trailing 0x8a, since we ourselves follow the
//documentation and put a plain LF (0x0a).
tape('parse_hex', function(t) {
var octets = testhelp.string_to_octets( "**\x18B0901020304a57f\x0d\x8a" );
var parsed = Zmodem.Header.parse( octets );
t.is( parsed[1], 16, 'CRC size' );
t.is(
parsed[0].NAME,
'ZRPOS',
'parsed NAME'
);
t.is(
parsed[0].TYPENUM,
9,
'parsed TYPENUM'
);
t.is(
parsed[0].get_offset(),
0x04030201, //its little-endian
'parsed offset'
);
t.end();
} );
tape('round-trip, empty headers', function(t) {
["ZRQINIT", "ZSKIP", "ZABORT", "ZFIN", "ZFERR"].forEach( (n) => {
var orig = Zmodem.Header.build(n);
var hex = orig.to_hex();
var b16 = orig.to_binary16(zdle);
var b32 = orig.to_binary32(zdle);
var rounds = new Map( [
[ "to_hex", hex ],
[ "to_binary16", b16 ],
[ "to_binary32", b32 ],
] );
for ( const [ enc, h ] of rounds ) {
let [ parsed, crclen ] = Zmodem.Header.parse(h);
t.is( parsed.NAME, orig.NAME, `${n}, ${enc}: NAME` );
t.is( parsed.TYPENUM, orig.TYPENUM, `${n}, ${enc}: TYPENUM` );
//Heres where we test the CRC length in the response.
t.is(
crclen,
/32/.test(enc) ? 32 : 16,
`${n}, ${enc}: CRC length`,
);
}
} );
t.end();
} );
tape('round-trip, offset headers', function(t) {
["ZRPOS", "ZDATA", "ZEOF"].forEach( (n) => {
var orig = Zmodem.Header.build(n, 12345);
var hex = orig.to_hex();
var b16 = orig.to_binary16(zdle);
var b32 = orig.to_binary32(zdle);
var rounds = new Map( [
[ "to_hex", hex ],
[ "to_binary16", b16 ],
[ "to_binary32", b32 ],
] );
for ( const [ enc, h ] of rounds ) {
//Heres where we test that parse() leaves in trailing bytes.
let extra = [99, 99, 99];
let bytes_with_extra = h.slice().concat(extra);
let parsed = Zmodem.Header.parse(bytes_with_extra)[0];
t.is( parsed.NAME, orig.NAME, `${n}, ${enc}: NAME` );
t.is( parsed.TYPENUM, orig.TYPENUM, `${n}, ${enc}: TYPENUM` );
t.is( parsed.get_offset(), orig.get_offset(), `${n}, ${enc}: get_offset()` );
let expected = extra.slice(0);
if (enc === "to_hex") {
expected.splice( 0, 0, Zmodem.ZMLIB.XON );
}
t.deepEquals(
bytes_with_extra,
expected,
`${enc}: parse() leaves in trailing bytes`,
);
}
} );
t.end();
} );
tape('round-trip, ZSINIT', function(t) {
var opts = [
[],
["ESCCTL"],
];
opts.forEach( (args) => {
var orig = Zmodem.Header.build("ZSINIT", args);
var hex = orig.to_hex();
var b16 = orig.to_binary16(zdle);
var b32 = orig.to_binary32(zdle);
var rounds = new Map( [
[ "to_hex", hex ],
[ "to_binary16", b16 ],
[ "to_binary32", b32 ],
] );
var args_str = JSON.stringify(args);
for ( const [ enc, h ] of rounds ) {
let parsed = Zmodem.Header.parse(h)[0];
t.is( parsed.NAME, orig.NAME, `opts ${args_str}: ${enc}: NAME` );
t.is( parsed.TYPENUM, orig.TYPENUM, `opts ${args_str}: ${enc}: TYPENUM` );
t.is( parsed.escape_ctrl_chars(), orig.escape_ctrl_chars(), `opts ${args_str}: ${enc}: escape_ctrl_chars()` );
t.is( parsed.escape_8th_bit(), orig.escape_8th_bit(), `opts ${args_str}: ${enc}: escape_8th_bit()` );
}
} );
t.end();
} );
tape('round-trip, ZRINIT', function(t) {
var opts = [];
[ [], ["CANFDX"] ].forEach( (canfdx) => {
[ [], ["CANOVIO"] ].forEach( (canovio) => {
[ [], ["CANBRK"] ].forEach( (canbrk) => {
[ [], ["CANFC32"] ].forEach( (canfc32) => {
[ [], ["ESCCTL"] ].forEach( (escctl) => {
opts.push( [
...canfdx,
...canovio,
...canbrk,
...canfc32,
...escctl,
] );
} );
} );
} );
} );
} );
opts.forEach( (args) => {
var orig = Zmodem.Header.build("ZRINIT", args);
var hex = orig.to_hex();
var b16 = orig.to_binary16(zdle);
var b32 = orig.to_binary32(zdle);
var rounds = new Map( [
[ "to_hex", hex ],
[ "to_binary16", b16 ],
[ "to_binary32", b32 ],
] );
var args_str = JSON.stringify(args);
for ( const [ enc, h ] of rounds ) {
let parsed = Zmodem.Header.parse(h)[0];
t.is( parsed.NAME, orig.NAME, `opts ${args_str}: ${enc}: NAME` );
t.is( parsed.TYPENUM, orig.TYPENUM, `opts ${args_str}: ${enc}: TYPENUM` );
t.is( parsed.can_full_duplex(), orig.can_full_duplex(), `opts ${args_str}: ${enc}: can_full_duplex()` );
t.is( parsed.can_overlap_io(), orig.can_overlap_io(), `opts ${args_str}: ${enc}: can_overlap_io()` );
t.is( parsed.can_break(), orig.can_break(), `opts ${args_str}: ${enc}: can_break()` );
t.is( parsed.can_fcs_32(), orig.can_fcs_32(), `opts ${args_str}: ${enc}: can_fcs_32()` );
t.is( parsed.escape_ctrl_chars(), orig.escape_ctrl_chars(), `opts ${args_str}: ${enc}: escape_ctrl_chars()` );
t.is( parsed.escape_8th_bit(), orig.escape_8th_bit(), `opts ${args_str}: ${enc}: escape_8th_bit()` );
}
} );
t.end();
} );
tape('hex_final_XON', function(t) {
var hex_ZFIN = Zmodem.Header.build("ZFIN").to_hex();
t.notEquals(
hex_ZFIN.slice(-1)[0],
Zmodem.ZMLIB.XON,
'ZFIN hex does NOT end with XON',
);
var hex_ZACK = Zmodem.Header.build("ZACK").to_hex();
t.notEquals(
hex_ZACK.slice(-1)[0],
Zmodem.ZMLIB.XON,
'ZACK hex does NOT end with XON',
);
var headers = [
"ZRQINIT",
Zmodem.Header.build("ZRINIT", []),
Zmodem.Header.build("ZSINIT", []),
"ZRPOS",
"ZABORT",
"ZFERR",
];
//These are the only headers we expect to send as hex … right?
headers.forEach( hdr => {
if (typeof hdr === "string") hdr = Zmodem.Header.build(hdr);
t.is(
hdr.to_hex().slice(-1)[0],
Zmodem.ZMLIB.XON,
`${hdr.NAME} hex ends with XON`
);
} );
t.end();
} );