UNPKG

dbus-native

Version:

D-bus protocol implementation in native javascript

423 lines (401 loc) 14 kB
const Buffer = require('safe-buffer').Buffer; const marshall = require('../lib/marshall'); const unmarshall = require('../lib/unmarshall'); const assert = require('assert'); const Long = require('long'); var LongMaxS64 = Long.fromString('9223372036854775807', false); var LongMinS64 = Long.fromString('-9223372036854775808', false); var LongMaxU64 = Long.fromString('18446744073709551615', true); var LongMinU64 = Long.fromString('0', true); var LongMaxS53 = Long.fromString('9007199254740991', false); var LongMinS53 = Long.fromString('-9007199254740991', false); var LongMaxU53 = Long.fromString('9007199254740991', true); var LongMinU53 = Long.fromString('0', true); /** Take the data and marshall it then unmarshall it */ function marshallAndUnmarshall(signature, data, unmarshall_opts) { var marshalledBuffer = marshall(signature, data); var result = unmarshall( marshalledBuffer, signature, undefined, unmarshall_opts ); return result; } function test(signature, data, other_result, unmarshall_opts) { var result = marshallAndUnmarshall(signature, data, unmarshall_opts); try { if (other_result !== undefined) { assert.deepStrictEqual(result, other_result); } else { assert.deepStrictEqual(data, result); } } catch (e) { console.log('signature :', signature); console.log('orig :', data); console.log('unmarshalled:', result); if (other_result !== undefined) { throw new Error(`results don't match (${result}) != (${other_result})`); } else { throw new Error(`results don't match (${data}) != (${result})`); } } } var str300chars = ''; for (var i = 0; i < 300; ++i) str300chars += 'i'; var b30000bytes = Buffer.alloc(30000, 60); var str30000chars = b30000bytes.toString('ascii'); function expectMarshallToThrowOnBadArguments(badSig, badData, errorRegex) { assert.throws(function() { marshall(badSig, badData); }, errorRegex); } describe('marshall', function() { it('throws error on bad data', function() { var badData = [ ['s', [3], /Expected string or buffer argument/], ['s', ['as\0df'], /String contains null byte/], ['g', [3], /Expected string or buffer argument/], ['g', ['ccc'], /Unknown type.*in signature.*/], ['g', ['as\0df'], /String contains null byte/], ['g', [str300chars], /Data:.* is too long for signature type/], ['g', ['iii(i'], /Bad signature: unexpected end/], ['g', ['iii{i'], /Bad signature: unexpected end/], [ 'g', [ 'i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i(i)))))))))))))))))))))))))))))))))' ], /Maximum container type nesting exceeded/ ], ['y', ['n'], /Data:.*was not of type number/], ['y', [-1], /Number outside range/], ['y', [1.5], /Data:.*was not an integer/], ['y', [256], /Number outside range/], ['b', ['n'], /Data:.*was not of type boolean/], ['b', [-1], /Data:.*was not of type boolean/], ['b', [0.5], /Data:.*was not of type boolean/], ['b', [2], /Data:.*was not of type boolean/], ['n', ['n'], /Data:.*was not of type number/], ['n', [-0x7fff - 2], /Number outside range/], ['n', [1.5], /Data:.*was not an integer/], ['n', [0x7fff + 1], /Number outside range/], ['q', ['n'], /Data:.*was not of type number/], ['q', [-1], /Number outside range/], ['q', [1.5], /Data:.*was not an integer/], ['q', [0xffff + 1], /Number outside range/], ['i', ['n'], /Data:.*was not of type number/], ['i', [-0x7fffffff - 2], /Number outside range/], ['i', [1.5], /Data:.*was not an integer/], ['i', [0x7fffffff + 1], /Number outside range/], ['u', ['n'], /Data:.*was not of type number/], ['u', [-1], /Number outside range/], ['u', [1.5], /Data:.*was not an integer/], ['u', [0xffffffff + 1], /Number outside range/], ['x', ['n'], /Data:.*did not convert correctly to signed 64 bit/], ['x', [-Math.pow(2, 53) - 1], /Number outside range.*/], ['x', [1.5], /Data:.*was not an integer.*/], ['x', [Math.pow(2, 53)], /Number outside range.*/], [ 'x', ['9223372036854775808'], /Data:.*did not convert correctly to signed 64 bit*/ ], // exceed S64 [ 'x', ['-9223372036854775809'], /Data:.*did not convert correctly to signed 64 bit*/ ], // exceed S64 ['t', ['n'], /Data:.*did not convert correctly to unsigned 64 bit/], ['t', [-1], /Number outside range.*/], [ 't', ['18446744073709551616'], /Data:.*did not convert correctly to unsigned 64 bit*/ ], // exceed U64 ['t', [1.5], /Data:.*was not an integer.*/], ['t', [Math.pow(2, 53)], /Number outside range.*/], [ 'x', [LongMaxU53], /Longjs object is unsigned, but marshalling into signed 64 bit field/ ], // Longjs unsigned/signed must match with field? [ 't', [LongMaxS53], /Longjs object is signed, but marshalling into unsigned 64 bit field/ ], ['d', ['n'], /Data:.*was not of type number/], ['d', [Number.NEGATIVE_INFINITY], /Number outside range/], ['d', [NaN], /Data:.*was not a number/], ['d', [Number.POSITIVE_INFINITY], /Number outside range/] ]; for (var ii = 0; ii < badData.length; ++ii) { var badRow = badData[ii]; var badSig = badRow[0]; var badDatum = badRow[1]; var errorRegex = badRow[2]; expectMarshallToThrowOnBadArguments(badSig, badDatum, errorRegex); } }); it('throws error on bad signature', function() { var badSig = '1'; var badData = 1; expectMarshallToThrowOnBadArguments( badSig, badData, /Unknown type.*in signature.*/ ); }); }); describe('marshall/unmarshall', function() { // signature, data, not expected to fail?, data after unmarshall (when expected to convert to canonic form and different from input), unmarshall_options var tests = { 'simple types': [ ['s', ['short string']], ['s', [str30000chars]], ['o', ['/object/path']], ['o', ['invalid/object/path'], false], ['g', ['xxxtt(t)s{u}uuiibb']], ['g', ['signature'], false], // TODO: validate on input //['g', [str300chars], false], // max 255 chars ['o', ['/']], ['b', [false]], ['b', [true]], ['y', [10]], //['y', [300], false], // TODO: validate on input //['y', [-10]], // TODO: validate on input ['n', [300]], ['n', [16300]], //['n', [65535], false] // TODO: signed 16 bit //['n', [-100], false]; // TODO: validate on input, should fail ['q', [65535]], //['q', [-100], false], // TODO: validate on input, should fail // i - signed, u - unsigned ['i', [1048576]], ['i', [0]], ['i', [-1]], ['u', [1048576]], ['u', [0]], //['u', [-1], false] // TODO validate input, should fail ['x', [9007199254740991]], // 53bit numbers convert to 53bit numbers ['x', [-9007199254740991]], ['t', [9007199254740991]], ['t', [0]], ['x', ['9007199254740991'], false, [9007199254740991]], // strings should parse and convert to 53bit numbers ['x', ['-9007199254740991'], false, [-9007199254740991]], ['t', ['9007199254740991'], false, [9007199254740991]], ['t', ['0'], false, [0]], ['x', ['0x1FFFFFFFFFFFFF'], false, [9007199254740991]], // hex strings ['x', ['-0x1FFFFFFFFFFFFF'], false, [-9007199254740991]], ['x', ['0x0000'], false, [0]], [ 'x', ['0x7FFFFFFFFFFFFFFF'], false, [LongMaxS64], { ReturnLongjs: true } ], ['t', ['0x1FFFFFFFFFFFFF'], false, [9007199254740991]], ['t', ['0x0000'], false, [0]], [ 't', ['0xFFFFFFFFFFFFFFFF'], false, [LongMaxU64], { ReturnLongjs: true } ], ['x', [LongMaxS53], false, [9007199254740991]], // make sure Longjs objects convert to 53bit numbers ['x', [LongMinS53], false, [-9007199254740991]], ['t', [LongMaxU53], false, [9007199254740991]], ['t', [LongMinU53], false, [0]], ['x', [9007199254740991], false, [LongMaxS53], { ReturnLongjs: true }], // 53bit numbers to objects ['x', [-9007199254740991], false, [LongMinS53], { ReturnLongjs: true }], ['t', [9007199254740991], false, [LongMaxU53], { ReturnLongjs: true }], ['t', [0], false, [LongMinU53], { ReturnLongjs: true }], [ 'x', ['9223372036854775807'], false, [LongMaxS64], { ReturnLongjs: true } ], // strings to objects [ 'x', ['-9223372036854775808'], false, [LongMinS64], { ReturnLongjs: true } ], [ 't', ['18446744073709551615'], false, [LongMaxU64], { ReturnLongjs: true } ], ['t', ['0'], false, [LongMinU64], { ReturnLongjs: true }], ['x', [LongMaxS64], false, [LongMaxS64], { ReturnLongjs: true }], // Longjs object to objects ['x', [LongMinS64], false, [LongMinS64], { ReturnLongjs: true }], ['t', [LongMaxU64], false, [LongMaxU64], { ReturnLongjs: true }], ['t', [LongMinU64], false, [LongMinU64], { ReturnLongjs: true }], [ 'x', [ { low: LongMaxS64.low, high: LongMaxS64.high, unsigned: LongMaxS64.unsigned } ], false, [LongMaxS64], { ReturnLongjs: true } ], // non-instance Longjs object to objects [ 'x', [ { low: LongMaxS53.low, high: LongMaxS53.high, unsigned: LongMaxS53.unsigned } ], false, [9007199254740991] ], [ 't', [ { low: LongMaxU64.low, high: LongMaxU64.high, unsigned: LongMaxU64.unsigned } ], false, [LongMaxU64], { ReturnLongjs: true } ], [ 't', [ { low: LongMaxU53.low, high: LongMaxU53.high, unsigned: LongMaxU53.unsigned } ], false, [9007199254740991] ], ['x', [new String(9007199254740991)], false, [9007199254740991]], // quick check String instance conversion ['t', [new String('9007199254740991')], false, [9007199254740991]], ['x', [new Number(9007199254740991)], false, [9007199254740991]], // quick check Number instance conversion ['t', [new Number('9007199254740991')], false, [9007199254740991]] ], 'simple structs': [ ['(yyy)y', [[1, 2, 3], 4]], ['y(yyy)y', [5, [1, 2, 3], 4]], ['yy(yyy)y', [5, 6, [1, 2, 3], 4]], ['yyy(yyy)y', [5, 6, 7, [1, 2, 3], 4]], ['yyyy(yyy)y', [5, 6, 7, 8, [1, 2, 3], 4]], ['yyyyy(yyy)y', [5, 6, 7, 8, 9, [1, 2, 3], 4]] ], 'arrays of simple types': [ ['ai', [[1, 2, 3, 4, 5, 6, 7]]], ['aai', [[[300, 400, 500], [1, 2, 3, 4, 5, 6, 7]]]], ['aiai', [[1, 2, 3], [300, 400, 500]]] ], 'compound types': [ ['iyai', [10, 100, [1, 2, 3, 4, 5, 6]]], // TODO: fix 'array of structs offset problem ['a(iyai)', [[[10, 100, [1, 2, 3, 4, 5, 6]], [11, 200, [15, 4, 5, 6]]]]], [ 'sa(iyai)', [ 'test test test test', [[10, 100, [1, 2, 3, 4, 5, 6]], [11, 200, [15, 4, 5, 6]]] ] ], ['a(iyai)', [[[10, 100, [1, 2, 3, 4, 5, 6]], [11, 200, [15, 4, 5, 6]]]]], ['a(yai)', [[[100, [1, 2, 3, 4, 5, 6]], [200, [15, 4, 5, 6]]]]], [ 'a(yyai)', [[[100, 101, [1, 2, 3, 4, 5, 6]], [200, 201, [15, 4, 5, 6]]]] ], [ 'a(yyyai)', [[[100, 101, 102, [1, 2, 3, 4, 5, 6]], [200, 201, 202, [15, 4, 5, 6]]]] ], ['ai', [[1, 2, 3, 4, 5, 6]]], ['aii', [[1, 2, 3, 4, 5, 6], 10]], ['a(ai)', [[[[1, 2, 3, 4, 5, 6]], [[15, 4, 5, 6]]]]], ['aai', [[[1, 2, 3, 4, 5, 6], [15, 4, 5, 6]]]] ], buffers: [ ['ayay', [Buffer.from([0, 1, 2, 3, 4, 5, 6, 0xff]), Buffer.from([])]] ] }; var testName, testData, testNum; for (testName in tests) { for (testNum = 0; testNum < tests[testName].length; ++testNum) { testData = tests[testName][testNum]; var testDesc = `${testName} ${testNum} ${testData[0]}<-${JSON.stringify( testData[1] )}`; if (testData[2] === false) { // should fail (function(testData) { it(testDesc, function() { test(testData[0], testData[1], testData[3], testData[4]); }); })(testData); } else { (function(testData) { it(testDesc, function() { test(testData[0], testData[1], testData[3], testData[4]); }); })(testData); } } } }); // issue-128: marshall/unmarshall of "n" var data = [10, 1000]; var s = 'nn'; var buf = marshall(s, data); assert.equal(buf.toString('hex'), '0a00e803'); assert.deepStrictEqual(unmarshall(buf, s), data); //test('a(yai)', [[[100,[1,2,3,4,5,6]],[200,[15,4,5,6]]]], console.log); //test('a(yv)', [[[6,["s","final"]],[8,["g","uuu"]]]], console.log) // 7 a(ai)<-[[[[1,2,3,4,5,6]],[[15,4,5,6]]]] /* test('a(ai)', [ [ [[1,2,3,4,5,6]], [[7, 7, 4,5,6,7,8,9]] ] ], console.log); */ /* test('aai', [ [ [1,2,3,4,5,6], [7, 7, 4,5,6,7,8,9] ] ], console.log); */ /* intTypes = ['y', 'n', 'q', 'i', 'u']; //, 'x', 't']; for (var t1 = 0; t1 < intTypes.length; ++t1) for (var t2 = 0; t2 < intTypes.length; ++t2) { test(intTypes[t1] + intTypes[t2], [1, 2]); } // arrays test('ai', [[]]); test('aai', [[[]]]); // TODO: epsilon-test floats // test('bdsai', [0, 3.141590118408203, 'test string', [1, 2, 3, 0, 0, 0, 4, 5, 6, 7]]); */