312 lines
7.6 KiB
JavaScript
Executable file
312 lines
7.6 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
||
|
||
"use strict";
|
||
|
||
const test = require('tape');
|
||
|
||
const helper = require('./lib/testhelp');
|
||
global.Zmodem = require('./lib/zmodem');
|
||
|
||
var ZSession = Zmodem.Session;
|
||
|
||
var receiver, sender, sender_promise, received_file;
|
||
|
||
var offer;
|
||
|
||
function wait(seconds) {
|
||
return new Promise( resolve => setTimeout(_ => resolve("theValue"), 1000 * seconds) );
|
||
}
|
||
|
||
function _init(async) {
|
||
sender = null;
|
||
receiver = new Zmodem.Session.Receive();
|
||
|
||
/*
|
||
receiver.on("receive", function(hdr) {
|
||
console.log("Receiver input", hdr);
|
||
} );
|
||
receiver.on("offer", function(my_offer) {
|
||
//console.log("RECEIVED OFFER (window.offer)", my_offer);
|
||
offer = my_offer;
|
||
});
|
||
*/
|
||
|
||
var resolver;
|
||
sender_promise = new Promise( (res, rej) => { resolver = res; } );
|
||
|
||
function receiver_sender(bytes_arr) {
|
||
//console.log("receiver sending", String.fromCharCode.apply(String, bytes_arr), bytes_arr);
|
||
|
||
if (sender) {
|
||
var consumer = () => {
|
||
sender.consume(bytes_arr);
|
||
};
|
||
|
||
if (async) {
|
||
wait(0.5).then(consumer);
|
||
}
|
||
else consumer();
|
||
}
|
||
else {
|
||
var hdr = Zmodem.Header.parse(bytes_arr)[0];
|
||
sender = new Zmodem.Session.Send(hdr);
|
||
resolver(sender);
|
||
|
||
sender.set_sender( function(bytes_arr) {
|
||
var consumer = () => {
|
||
receiver.consume(bytes_arr);
|
||
};
|
||
|
||
if (async) {
|
||
wait(0.5).then(consumer);
|
||
}
|
||
else consumer();
|
||
} );
|
||
|
||
/*
|
||
sender.on("receive", function(hdr) {
|
||
console.log("Sender input", hdr);
|
||
} );
|
||
*/
|
||
}
|
||
}
|
||
|
||
receiver.set_sender(receiver_sender);
|
||
}
|
||
|
||
test('Sender receives extra ZRPOS', (t) => {
|
||
_init();
|
||
|
||
var zrinit = Zmodem.Header.build("ZRINIT", ["CANFDX", "CANOVIO", "ESCCTL"]);
|
||
var mysender = new Zmodem.Session.Send(zrinit);
|
||
|
||
var zrpos = Zmodem.Header.build("ZRPOS", 12345);
|
||
|
||
var err;
|
||
|
||
try {
|
||
mysender.consume(zrpos.to_hex());
|
||
}
|
||
catch(e) {
|
||
err = e;
|
||
}
|
||
|
||
t.match(err.toString(), /header/, "error as expected");
|
||
t.match(err.toString(), /ZRPOS/, "error as expected");
|
||
|
||
return Promise.resolve();
|
||
} );
|
||
|
||
test('Offer events', (t) => {
|
||
_init();
|
||
|
||
var inputs = [];
|
||
var completed = false;
|
||
|
||
var r_pms = receiver.start().then( (offer) => {
|
||
t.deepEquals(
|
||
offer.get_details(),
|
||
{
|
||
name: "my file",
|
||
size: 32,
|
||
mode: null,
|
||
mtime: null,
|
||
serial: null,
|
||
files_remaining: null,
|
||
bytes_remaining: null,
|
||
},
|
||
'get_details() returns expected values'
|
||
);
|
||
|
||
offer.on("input", (payload) => {
|
||
inputs.push(
|
||
{
|
||
offset: offer.get_offset(),
|
||
payload: payload,
|
||
}
|
||
);
|
||
} );
|
||
|
||
offer.on("complete", () => { completed = true });
|
||
|
||
return offer.accept();
|
||
} );
|
||
|
||
var s_pms = sender.send_offer(
|
||
{ name: "my file", size: 32 }
|
||
).then( (sender_xfer) => {
|
||
sender_xfer.send( [1, 2, 3] );
|
||
sender_xfer.send( [4, 5, 6, 7] );
|
||
sender_xfer.end( [8, 9] ).then( () => {
|
||
return sender.close();
|
||
} );
|
||
} );
|
||
|
||
return Promise.all( [ r_pms, s_pms ] ).then( () => {
|
||
t.deepEquals(
|
||
inputs,
|
||
[
|
||
{
|
||
payload: [1, 2, 3],
|
||
offset: 3,
|
||
},
|
||
{
|
||
payload: [4, 5, 6, 7],
|
||
offset: 7,
|
||
},
|
||
{
|
||
payload: [8, 9],
|
||
offset: 9,
|
||
},
|
||
],
|
||
'Offer “input” events',
|
||
);
|
||
|
||
t.ok( completed, 'Offer “complete” event' );
|
||
} );
|
||
} );
|
||
|
||
test('receive one, promises', (t) => {
|
||
_init();
|
||
|
||
var r_pms = receiver.start().then( (offer) => {
|
||
t.deepEquals(
|
||
offer.get_details(),
|
||
{
|
||
name: "my file",
|
||
size: 32,
|
||
mode: null,
|
||
mtime: null,
|
||
serial: null,
|
||
files_remaining: null,
|
||
bytes_remaining: null,
|
||
},
|
||
'get_details() returns expected values'
|
||
);
|
||
|
||
return offer.accept();
|
||
} );
|
||
|
||
//r_pms.then( () => { console.log("RECEIVER DONE") } );
|
||
|
||
var s_pms = sender.send_offer(
|
||
{ name: "my file", size: 32 }
|
||
).then( (sender_xfer) => {
|
||
sender_xfer.end( [12, 23, 34] ).then( () => {
|
||
return sender.close();
|
||
} );
|
||
} );
|
||
|
||
return Promise.all( [ r_pms, s_pms ] );
|
||
} );
|
||
|
||
test('receive one, events', (t) => {
|
||
_init();
|
||
|
||
var content = [ 1,2,3,4,5,6,7,8,9,2,3,5,1,5,33,2,23,7 ];
|
||
|
||
var now_epoch = Math.floor(Date.now() / 1000);
|
||
|
||
receiver.on("offer", (offer) => {
|
||
t.deepEquals(
|
||
offer.get_details(),
|
||
{
|
||
name: "my file",
|
||
size: content.length,
|
||
mode: parseInt("100644", 8),
|
||
mtime: new Date( now_epoch * 1000 ),
|
||
serial: null,
|
||
files_remaining: null,
|
||
bytes_remaining: null,
|
||
},
|
||
'get_details() returns expected values'
|
||
);
|
||
|
||
offer.accept();
|
||
} );
|
||
receiver.start();
|
||
|
||
return sender.send_offer( {
|
||
name: "my file",
|
||
size: content.length,
|
||
mtime: now_epoch,
|
||
mode: parseInt("0644", 8),
|
||
} ).then(
|
||
(sender_xfer) => {
|
||
sender_xfer.end(content).then( sender.close.bind(sender) );
|
||
}
|
||
);
|
||
} );
|
||
|
||
test('skip one, receive the next', (t) => {
|
||
_init();
|
||
|
||
var r_pms = receiver.start().then( (offer) => {
|
||
//console.log("first offer", offer);
|
||
|
||
t.equals( offer.get_details().name, "my file", "first file’s name" );
|
||
var next_pms = offer.skip();
|
||
//console.log("next", next_pms);
|
||
return next_pms;
|
||
} ).then( (offer) => {
|
||
t.equals( offer.get_details().name, "file 2", "second file’s name" );
|
||
return offer.skip();
|
||
} );
|
||
|
||
var s_pms = sender.send_offer(
|
||
{ name: "my file" }
|
||
).then(
|
||
(sender_xfer) => {
|
||
t.ok( !sender_xfer, "skip() -> sender sees no transfer object" );
|
||
return sender.send_offer( { name: "file 2" } );
|
||
}
|
||
).then(
|
||
(xfer) => {
|
||
t.ok( !xfer, "2nd skip() -> sender sees no transfer object" );
|
||
return sender.close();
|
||
}
|
||
);
|
||
|
||
return Promise.all( [ r_pms, s_pms ] );
|
||
} );
|
||
|
||
test('abort mid-download', (t) => {
|
||
_init();
|
||
|
||
var transferred_bytes = [];
|
||
|
||
var aborted;
|
||
|
||
var r_pms = receiver.start().then( (offer) => {
|
||
offer.on("input", (payload) => {
|
||
[].push.apply(transferred_bytes, payload);
|
||
|
||
if (aborted) throw "already aborted!";
|
||
aborted = true;
|
||
|
||
receiver.abort();
|
||
});
|
||
return offer.accept();
|
||
} );
|
||
|
||
var s_pms = sender.send_offer(
|
||
{ name: "my file" }
|
||
).then(
|
||
(xfer) => {
|
||
xfer.send( [1, 2, 3] );
|
||
xfer.end( [99, 99, 99] ); //should never get here
|
||
}
|
||
);
|
||
|
||
return Promise.all( [r_pms, s_pms] ).catch(
|
||
(err) => {
|
||
t.ok( err.message.match('abort'), 'error message is about abort' );
|
||
}
|
||
).then( () => {
|
||
t.deepEquals(
|
||
transferred_bytes,
|
||
[1, 2, 3],
|
||
'abort() stopped us from sending more',
|
||
);
|
||
} );
|
||
} );
|