#!/usr/bin/env node "use strict"; const tape = require('blue-tape'); global.Zmodem = require('./lib/zmodem'); const zcrc = Zmodem.CRC; var now = new Date(); var now_epoch = Math.floor( now.getTime() / 1000 ); var failures = [ [ 'empty name', { name: "" }, function(t, e) { t.ok( /name/.test(e.message), 'has “name”' ); }, ], [ 'non-string name', { name: 123 }, function(t, e) { t.ok( /name/.test(e.message), 'has “name”' ); t.ok( /string/.test(e.message), 'has “string”' ); }, ], [ 'non-empty serial', { name: "123", serial: 0 }, function(t, e) { t.ok( /serial/.test(e.message), 'has “serial”' ); }, ], [ 'files_remaining === 0', { name: "123", files_remaining: 0 }, function(t, e) { t.ok( /files_remaining/.test(e.message), 'has “files_remaining”' ); }, ], [ 'pre-epoch mtime', { name: "123", mtime: new Date("1969-12-30T01:02:03Z") }, function(t, e) { t.ok( /mtime/.test(e.message), 'has “mtime”' ); t.ok( /1969/.test(e.message), 'has “1969”' ); t.ok( /1970/.test(e.message), 'has “1970”' ); }, ], ]; ["size", "mode", "mtime", "files_remaining", "bytes_remaining"].forEach( (k) => { var input = { name: "the name" }; input[k] = "123123"; var key_regexp = new RegExp(k); var value_regexp = new RegExp(input[k]); failures.push( [ `string “${k}”`, input, function(t, e) { t.ok( key_regexp.test(e.message), `has “${k}”` ); t.ok( value_regexp.test(e.message), 'has value' ); t.ok( /number/.test(e.message), 'has “number”' ); }, ] ); input = Object.assign( {}, input ); input[k] = -input[k]; var negative_regexp = new RegExp(input[k]); failures.push( [ `negative “${k}”`, input, function(t, e) { t.ok( key_regexp.test(e.message), `has “${k}”` ); t.ok( negative_regexp.test(e.message), 'has value' ); }, ] ); input = Object.assign( {}, input ); input[k] = -input[k] - 0.1; var fraction_regexp = new RegExp( ("" + input[k]).replace(/\./, "\\.") ); failures.push( [ `fraction “${k}”`, input, function(t, e) { t.ok( key_regexp.test(e.message), `has “${k}”` ); t.ok( fraction_regexp.test(e.message), 'has value' ); }, ] ); } ); var transformations = [ [ 'name only', { name: "My name", }, { name: "My name", size: null, mtime: null, mode: null, serial: null, files_remaining: null, bytes_remaining: null, }, ], [ 'name is all numerals', { name: "0", }, { name: "0", size: null, mtime: null, mode: null, serial: null, files_remaining: null, bytes_remaining: null, }, ], [ 'name only (undefined rather than null)', { name: "My name", size: undefined, mtime: undefined, mode: undefined, serial: undefined, files_remaining: undefined, bytes_remaining: undefined, }, { name: "My name", size: null, mtime: null, mode: null, serial: null, files_remaining: null, bytes_remaining: null, }, ], [ 'name and all numbers', { name: "My name", size: 0, mtime: 0, mode: parseInt("0644", 8), serial: null, files_remaining: 1, bytes_remaining: 0, }, { name: "My name", size: 0, mtime: 0, mode: parseInt("100644", 8), serial: null, files_remaining: 1, bytes_remaining: 0, }, ], [ 'name, zero size', { name: "My name", mtime: now }, { name: "My name", size: null, mtime: now_epoch, mode: null, serial: null, files_remaining: null, bytes_remaining: null, }, ], [ 'name, mtime as Date', { name: "My name", size: 0 }, { name: "My name", size: 0, mtime: null, mode: null, serial: null, files_remaining: null, bytes_remaining: null, }, ], ]; tape('offer_parameters - failures', function(t) { for (const [label, input, todo] of failures) { let err; try { Zmodem.Validation.offer_parameters(input); } catch(e) { err = e } t.ok( err instanceof Zmodem.Error, `throws ok: ${label}` ); todo(t, err); } t.end(); }); tape('offer_parameters - happy path', function(t) { for (const [label, input, output] of transformations) { t.deepEquals( Zmodem.Validation.offer_parameters(input), output, label, ); } t.end(); });