diff --git a/tests/ecmascript/test-bi-cbor-64bit-tag.js b/tests/ecmascript/test-bi-cbor-64bit-tag.js deleted file mode 100644 index 7afc5901..00000000 --- a/tests/ecmascript/test-bi-cbor-64bit-tag.js +++ /dev/null @@ -1,15 +0,0 @@ -/*--- -{ - "skip": true -} ----*/ - -/*=== -[1,2,3] -done -===*/ - -var t = CBOR.decode(new Uint8Array([ 0xdb, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x83, 0x01, 0x02, 0x03 ])); -print(JSON.stringify(t)); - -print('done'); diff --git a/tests/ecmascript/test-bi-cbor-dec-64bit-tag.js b/tests/ecmascript/test-bi-cbor-dec-64bit-tag.js new file mode 100644 index 00000000..ddf68b1e --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-dec-64bit-tag.js @@ -0,0 +1,19 @@ +/*--- +{ + "skip": true +} +---*/ + +/*=== +[1,2,3] +done +===*/ + +// While 64-bit integers might not be supported, a 64-bit tag must still be +// at least ignored. +var t = CBOR.decode(new Uint8Array([ + 0xdb, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x83, 0x01, 0x02, 0x03 +])); +print(JSON.stringify(t)); + +print('done'); diff --git a/tests/ecmascript/test-bi-cbor-dec-empty.js b/tests/ecmascript/test-bi-cbor-dec-empty.js new file mode 100644 index 00000000..07f4a486 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-dec-empty.js @@ -0,0 +1,19 @@ +/*--- +{ + "skip": true +} +---*/ + +/*=== +TypeError +===*/ + +// Empty input is a decode error, TypeError used now. cbor-js triggers a +// RangeError from reading out of bounds of a DataView. +try { + CBOR.decode(new Uint8Array([]).buffer); + print('never here'); +} catch (e) { + print(e.name); + //print(e.stack || e); +} diff --git a/tests/ecmascript/test-bi-cbor-dec-half-float-full.js b/tests/ecmascript/test-bi-cbor-dec-half-float-full.js new file mode 100644 index 00000000..765d60e4 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-dec-half-float-full.js @@ -0,0 +1,188 @@ +/* + * Full coverage for decoding all half-floats. Compared against cbor-js. + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +f90000 0 +f90001 5.960464477539063e-8 + diff: 5.960464477539063e-8 +f90801 0.00012218952178955078 + diff: 1.1920928955078125e-7 +f90c01 0.00024437904357910156 + diff: 2.384185791015625e-7 +f91001 0.0004887580871582031 + diff: 4.76837158203125e-7 +f91401 0.0009775161743164063 + diff: 9.5367431640625e-7 +f91801 0.0019550323486328125 + diff: 0.0000019073486328125 +f91c01 0.003910064697265625 + diff: 0.000003814697265625 +f92001 0.00782012939453125 + diff: 0.00000762939453125 +f92401 0.0156402587890625 + diff: 0.0000152587890625 +f92801 0.031280517578125 + diff: 0.000030517578125 +f92c01 0.06256103515625 + diff: 0.00006103515625 +f93001 0.1251220703125 + diff: 0.0001220703125 +f93401 0.250244140625 + diff: 0.000244140625 +f93801 0.50048828125 + diff: 0.00048828125 +f93c01 1.0009765625 + diff: 0.0009765625 +f94001 2.001953125 + diff: 0.001953125 +f94401 4.00390625 + diff: 0.00390625 +f94801 8.0078125 + diff: 0.0078125 +f94c01 16.015625 + diff: 0.015625 +f95001 32.03125 + diff: 0.03125 +f95401 64.0625 + diff: 0.0625 +f95801 128.125 + diff: 0.125 +f95c01 256.25 + diff: 0.25 +f96001 512.5 + diff: 0.5 +f96401 1025 + diff: 1 +f96801 2050 + diff: 2 +f96c01 4100 + diff: 4 +f97001 8200 + diff: 8 +f97401 16400 + diff: 16 +f97801 32800 + diff: 32 +f97c00 Infinity +f97c01 NaN +f97c02 NaN + diff: 0 +f98000 -0 +f98001 -5.960464477539063e-8 + diff: -5.960464477539063e-8 +f98801 -0.00012218952178955078 + diff: -1.1920928955078125e-7 +f98c01 -0.00024437904357910156 + diff: -2.384185791015625e-7 +f99001 -0.0004887580871582031 + diff: -4.76837158203125e-7 +f99401 -0.0009775161743164063 + diff: -9.5367431640625e-7 +f99801 -0.0019550323486328125 + diff: -0.0000019073486328125 +f99c01 -0.003910064697265625 + diff: -0.000003814697265625 +f9a001 -0.00782012939453125 + diff: -0.00000762939453125 +f9a401 -0.0156402587890625 + diff: -0.0000152587890625 +f9a801 -0.031280517578125 + diff: -0.000030517578125 +f9ac01 -0.06256103515625 + diff: -0.00006103515625 +f9b001 -0.1251220703125 + diff: -0.0001220703125 +f9b401 -0.250244140625 + diff: -0.000244140625 +f9b801 -0.50048828125 + diff: -0.00048828125 +f9bc01 -1.0009765625 + diff: -0.0009765625 +f9c001 -2.001953125 + diff: -0.001953125 +f9c401 -4.00390625 + diff: -0.00390625 +f9c801 -8.0078125 + diff: -0.0078125 +f9cc01 -16.015625 + diff: -0.015625 +f9d001 -32.03125 + diff: -0.03125 +f9d401 -64.0625 + diff: -0.0625 +f9d801 -128.125 + diff: -0.125 +f9dc01 -256.25 + diff: -0.25 +f9e001 -512.5 + diff: -0.5 +f9e401 -1025 + diff: -1 +f9e801 -2050 + diff: -2 +f9ec01 -4100 + diff: -4 +f9f001 -8200 + diff: -8 +f9f401 -16400 + diff: -16 +f9f801 -32800 + diff: -32 +f9fc00 -Infinity +f9fc01 NaN +f9fc02 NaN + diff: 0 +done +===*/ + +function test() { + var b1, b2, prev = null, prevdiff = null; + + var res = []; + + for (b1 = 0; b1 < 256; b1++) { + for (b2 = 0; b2 < 256; b2++) { + var data = new Uint8Array([ 0xf9, b1, b2 ]).buffer; + var val = CBOR.decode(data); + var obj = { input: Duktape.enc('hex', data), value: val }; + if (prev !== null && Number.isNaN(prev) && Number.isNaN(val)) { + obj.diff = 0; + } else if (prev !== null && Number.isFinite(prev) && Number.isFinite(val)) { + obj.diff = val - prev; + } + prev = val; + res.push(obj); + } + } + + var diff_printed = false; + for (i = 0; i < res.length; i++) { + var prev = (i > 0 ? res[i - 1] : {}); + var curr = res[i]; + if (prev.diff === curr.diff && typeof curr.diff === 'number') { + if (diff_printed) { + } else { + print(' diff: ' + prev.diff); + diff_printed = true; + } + } else { + print(curr.input, Duktape.enc('jx', curr.value)); + diff_printed = false; + } + } +} + +try { + test(); +} catch (e) { + print(e.stack || e); +} + +print('done'); diff --git a/tests/ecmascript/test-bi-cbor-dec-nonbmp.js b/tests/ecmascript/test-bi-cbor-dec-nonbmp.js new file mode 100644 index 00000000..5117eb79 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-dec-nonbmp.js @@ -0,0 +1,34 @@ +/* + * Decoding non-BMP, valid UTF-8 strings. + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +"foo" +"A\U0010fedcB" +done +===*/ + +function test(hexInput) { + try { + print(Duktape.enc('jx', CBOR.decode(Duktape.dec('hex', hexInput)))); + } catch (e) { + print(e.name); + } +} + +// Valid CBOR text string. +test('63666f6f'); + +// Codepoint U+10FEDC. Input is valid UTF-8 which should decode to a +// surrogate pair for ECMAScript compatibility. +// +// Currently decodes to Duktape specific non-BMP codepoint as is. +test('6641f48fbb9c42'); + +print('done'); diff --git a/tests/ecmascript/test-bi-cbor-dec-nonutf8.js b/tests/ecmascript/test-bi-cbor-dec-nonutf8.js new file mode 100644 index 00000000..fe3b3b39 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-dec-nonutf8.js @@ -0,0 +1,56 @@ +/* + * Test for current behavior when decoding non-UTF-8 CBOR text strings + * (technically invalid CBOR). + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +"foo" +"foo\ud800" +"foo\ud800bar" +"\x00" +TypeError +"\ud83d\udca9" +===*/ + +function test(hexInput) { + try { + print(Duktape.enc('jx', CBOR.decode(Duktape.dec('hex', hexInput)))); + } catch (e) { + print(e.name); + } +} + +// Valid CBOR text string. +test('63666f6f'); + +// CESU-8 string, invalid UTF-8 and thus invalid CBOR: U-D800 in string. +// +// Current behavior: decode into an ECMAScript string as is. +// Could also reject, or use U+FFFD. +test('66666f6feda080'); +test('69666f6feda080626172'); + +// Invalid UTF-8 and CESU-8. +// +// Current behavior: decode as is, except if would map into a Duktape +// Symbol which is rejected. +test('62c080'); // "long form" U+0000 +test('6482112233'); + +// Input has valid surrogate pair (CESU-8), which is still invalid +// UTF-8. +// +// Current behavior: accepted as is. +/* +>>> u'\ud83d'.encode('utf-8') +'\xed\xa0\xbd' +>>> u'\udca9'.encode('utf-8') +'\xed\xb2\xa9' +*/ +test('66eda0bdedb2a9'); diff --git a/tests/ecmascript/test-bi-cbor-dec-refuse-symbol.js b/tests/ecmascript/test-bi-cbor-dec-refuse-symbol.js new file mode 100644 index 00000000..b886f0c3 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-dec-refuse-symbol.js @@ -0,0 +1,25 @@ +/* Previous versions of CBOR extra would encode Symbols (represented + * internally as strings) as is: + * + * duk> CBOR.encode(Symbol('foo')) + * = |6881666f6fff302d31| + * + * Check that decoded strings representing any kind of Symbol are + * rejected on decode, at least for now. + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +TypeError +===*/ + +try { + print(String(CBOR.decode(new Uint8Array([ 0x68, 0x81, 0x66, 0x6f, 0x6f, 0xff, 0x30, 0x2d, 0x31 ])))); +} catch (e) { + print(e.name); +} diff --git a/tests/ecmascript/test-bi-cbor-dec-types.js b/tests/ecmascript/test-bi-cbor-dec-types.js new file mode 100644 index 00000000..8b1ca59e --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-dec-types.js @@ -0,0 +1,1020 @@ +/* + * Decode tests for all major types, organized by each initial byte. + * + * For inputs that should decode successfully, also tests that truncated and + * padded inputs are rejected. + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +- Major type 0x00-0x1f: unsigned integer +- Major type 0x20-0x3f: negative integer (not -0) +- Major type 0x40-0x5f: byte string +typeof: object +instanceof ByteArray: false +instanceof Uint8Array: true +proto is Uint8Array.prototype: true +is bare: false +- Major type 0x60-0x7f: text string +- Major type 0x80-0x9f: array +typeof: object +instanceof Array: true +Array.isArray: true +proto is Array.prototype: true +is bare: false +- Major type 0xa0-0xbf: map +typeof: object +instanceof Object: true +proto is Object.prototype: true +is bare: false +- Major type 0xc0-0xdf: tag +- Major type 0xe0-0xff: simple types, floating point numbers, break, etc +done +===*/ + +var ERROR = {}; + +function testOne(hexInput, expect, opts) { + opts = opts || {}; + var truncLimit = 255; + var prInput = (hexInput.length > truncLimit ? hexInput.substring(0, truncLimit) + '...' : hexInput); + var jxExpect = Duktape.enc('jx', expect); + var prExpect = (jxExpect.length > truncLimit ? jxExpect.substring(0, truncLimit) + '...' : jxExpect); + try { + var result = CBOR.decode(Duktape.dec('hex', hexInput).buffer); + var jxResult = Duktape.enc('jx', result); + var prResult = (jxResult.length > truncLimit ? jxResult.substring(0, truncLimit) + '...' : jxResult); + if (!opts.silent) { + print(prInput, prResult); + } + if (expect === ERROR) { + print('MISMATCH, got ' + prResult + ', expected ERROR'); + } else if (jxResult !== jxExpect) { + print('MISMATCH, got ' + prResult + ', expected ' + prExpect); + } + } catch (e) { + if (!opts.silent) { + print(prInput, e.name); + } + if (expect !== ERROR) { + print('MISMATCH, got ' + String(e) + ', expected ' + prExpect); + } + } +} + +function getPad(bytelen) { + var u8 = new Uint8Array(bytelen); + for (var i = 0; i < bytelen; i++) { + // Padding is not deterministic, but this should not affect + // test result (= all paddings are invalid). + u8[i] = Math.random() * 256; + } + return Duktape.enc('hex', u8); +} + +function test(hexInput, expect) { + var bytelen = hexInput.length / 2; + var ntrunc = 10; + var npad = 10; + + // Change silent to false to get verbose output. + testOne(hexInput, expect, { silent: true }); + + // Truncation tests; any truncated input of a valid input is + // always invalid (converse is not true). + if (expect !== ERROR) { + for (var trunc = 1; trunc <= ntrunc; trunc++) { + var clip = 2 * (bytelen - trunc); + if (clip >= 0) { + var truncHexInput = hexInput.substring(0, clip); + testOne(truncHexInput, ERROR, { silent: true }); + } + } + } + + // Same for trailing garbage: any valid input with garbage added + // is always invalid (converse is again not true). + if (expect !== ERROR) { + for (var pad = 1; pad <= npad; pad++) { + var paddedHexInput = hexInput + getPad(pad); + testOne(paddedHexInput, ERROR, { silent: true }); + } + } + + // Any valid input remains valid when tagged. Because tags are + // ignored by the decoder, the expect value remains the same. + if (expect !== ERROR) { + var taggedHexInput = 'c4' + hexInput; + testOne(taggedHexInput, expect, { silent: true }); + } +} + +print('- Major type 0x00-0x1f: unsigned integer'); + +test('00', +0); +test('01', 1); +test('02', 2); +test('03', 3); +test('04', 4); +test('05', 5); +test('06', 6); +test('07', 7); +test('08', 8); +test('09', 9); +test('0a', 10); +test('0b', 11); +test('0c', 12); +test('0d', 13); +test('0e', 14); +test('0f', 15); +test('10', 16); +test('11', 17); +test('12', 18); +test('13', 19); +test('14', 20); +test('15', 21); +test('16', 22); +test('17', 23); +test('18', ERROR); +test('1800', +0); +test('1801', 1); +test('1816', 22); +test('1817', 23); +test('1818', 24); +test('18fe', 254); +test('18ff', 255); +test('19', ERROR); +test('1911', ERROR); +test('190000', +0); +test('1900ff', 255); +test('190100', 256); +test('191234', 4660); +test('19fedc', 65244); +test('19ffff', 65535); +test('1a', ERROR); +test('1a11', ERROR); +test('1a1122', ERROR); +test('1a112233', ERROR); +test('1a00000000', +0); +test('1a000000ff', 255); +test('1a0000ffff', 65535); +test('1a00010000', 65536); +test('1a12345678', 305419896); +test('1afedcba98', 4275878552); +test('1affffffff', 4294967295); +test('1b', ERROR); +test('1b11', ERROR); +test('1b1122', ERROR); +test('1b112233', ERROR); +test('1b11223344', ERROR); +test('1b1122334455', ERROR); +test('1b112233445566', ERROR); +test('1b11223344556677', ERROR); +test('1b0000000000000000', +0); +test('1b00000000000000ff', 255); +test('1b000000000000ffff', 65535); +test('1b00000000ffffffff', 4294967295); +test('1b001fffffffffffff', 9007199254740991); // 2^53-1, exact +test('1b0020000000000000', 9007199254740992); // 2^53, exact +test('1b0020000000000001', 9007199254740992); // rounds down +test('1b0020000000000002', 9007199254740994); // 2^53+2, exact +test('1b0020000000000003', 9007199254740996); // rounds up +test('1b0020000000000004', 9007199254740996); // 2^53+4, exact +test('1b0020000000000005', 9007199254740996); // rounds down +test('1b0020000000000006', 9007199254740998); // 2^53+6, exact +test('1b123456789abcdef0', 1311768467463790300); // not exact: 0x123456789abcdf00 +test('1bffeeddccbbaa9988', 18441921395520346000); +/* +>>> import cbor +>>> float(cbor.loads('1bfffffffffffff7ff'.decode('hex'))) +1.844674407370955e+19 +>>> float(cbor.loads('1bfffffffffffff800'.decode('hex'))) +1.844674407370955e+19 +>>> float(cbor.loads('1bfffffffffffffbfe'.decode('hex'))) +1.844674407370955e+19 +>>> float(cbor.loads('1bfffffffffffffbff'.decode('hex'))) +1.844674407370955e+19 +>>> float(cbor.loads('1bfffffffffffffc00'.decode('hex'))) +1.8446744073709552e+19 +*/ +test('1bfffffffffffff7ff', 18446744073709550000); // not exact: 0xfffffffffffff800 +test('1bfffffffffffff800', 18446744073709550000); // exact: 0xfffffffffffff800 +test('1bfffffffffffffbff', 18446744073709550000); // not exact: 0xfffffffffffff800 +test('1bfffffffffffffc00', 18446744073709552000); // not exact: 0x10000000000000000 +test('1bfffffffffffffffe', 18446744073709552000); // not exact: 0x10000000000000000 +test('1bffffffffffffffff', 18446744073709552000); // not exact: 0x10000000000000000 +test('1c', ERROR); +test('1c00', ERROR); +test('1cff', ERROR); +test('1d', ERROR); +test('1d00', ERROR); +test('1dff', ERROR); +test('1e', ERROR); +test('1e00', ERROR); +test('1eff', ERROR); +test('1f', ERROR); +test('1f00', ERROR); +test('1fff', ERROR); + +print('- Major type 0x20-0x3f: negative integer (not -0)'); + +test('20', -1); +test('21', -2); +test('22', -3); +test('23', -4); +test('24', -5); +test('25', -6); +test('26', -7); +test('27', -8); +test('28', -9); +test('29', -10); +test('2a', -11); +test('2b', -12); +test('2c', -13); +test('2d', -14); +test('2e', -15); +test('2f', -16); +test('30', -17); +test('31', -18); +test('32', -19); +test('33', -20); +test('34', -21); +test('35', -22); +test('36', -23); +test('37', -24); +test('38', ERROR); +test('3800', -1); +test('3801', -2); +test('3816', -23); +test('3817', -24); +test('3818', -25); +test('38fe', -255); +test('38ff', -256); +test('39', ERROR); +test('3911', ERROR); +test('390000', -1); +test('3900ff', -256); +test('390100', -257); +test('391234', -4661); +test('39fedc', -65245); +test('39ffff', -65536); +test('3a', ERROR); +test('3a11', ERROR); +test('3a1122', ERROR); +test('3a112233', ERROR); +test('3a00000000', -1); +test('3a000000ff', -256); +test('3a0000ffff', -65536); +test('3a00010000', -65537); +test('3a12345678', -305419897); +test('3afedcba98', -4275878553); +test('3affffffff', -4294967296); +test('3b', ERROR); +test('3b11', ERROR); +test('3b1122', ERROR); +test('3b112233', ERROR); +test('3b11223344', ERROR); +test('3b1122334455', ERROR); +test('3b112233445566', ERROR); +test('3b11223344556677', ERROR); +test('3b0000000000000000', -1); +test('3b00000000000000ff', -256); +test('3b000000000000ffff', -65536); +test('3b00000000ffffffff', -4294967296); +test('3b001ffffffffffffe', -9007199254740991); // -2^53-1, exact +test('3b001fffffffffffff', -9007199254740992); // -2^53, exact +test('3b0020000000000000', -9007199254740992); // rounds towards zero +test('3b0020000000000001', -9007199254740994); // 2^53+2, exact +test('3b0020000000000002', -9007199254740996); // rounds towards -inf +test('3b0020000000000003', -9007199254740996); // 2^53+4, exact +test('3b0020000000000004', -9007199254740996); // rounds towards zero +test('3b0020000000000005', -9007199254740998); // 2^53+6, exact +test('3b123456789abcdeef', -1311768467463790300); // not exact: -0x123456789abcdf00 +test('3bffeeddccbbaa9987', -18441921395520346000); +/* +>>> float(cbor.loads('3bfffffffffffff7fe'.decode('hex'))) +-1.844674407370955e+19 +>>> float(cbor.loads('3bfffffffffffff7ff'.decode('hex'))) +-1.844674407370955e+19 +>>> float(cbor.loads('3bfffffffffffff800'.decode('hex'))) +-1.844674407370955e+19 +>>> float(cbor.loads('3bfffffffffffffbfe'.decode('hex'))) +-1.844674407370955e+19 +>>> float(cbor.loads('3bfffffffffffffbff'.decode('hex'))) +-1.8446744073709552e+19 +>>> float(cbor.loads('3bfffffffffffffc00'.decode('hex'))) +-1.8446744073709552e+19 +*/ +test('3bfffffffffffff7fe', -18446744073709550000); // not exact +test('3bfffffffffffff7ff', -18446744073709550000); // exact: -0xfffffffffffff800 +test('3bfffffffffffff800', -18446744073709550000); // not exact: -0xfffffffffffff800 +test('3bfffffffffffffbfe', -18446744073709550000); // not exact: -0xfffffffffffff800 +test('3bfffffffffffffbff', -18446744073709552000); // not exact: -0x10000000000000000 +test('3bfffffffffffffc00', -18446744073709552000); // not exact: -0x10000000000000000 +test('3bfffffffffffffffe', -18446744073709552000); // not exact: -0x10000000000000000 +test('3bffffffffffffffff', -18446744073709552000); // exact: -0x10000000000000000 +test('3c', ERROR); +test('3c00', ERROR); +test('3cff', ERROR); +test('3d', ERROR); +test('3d00', ERROR); +test('3dff', ERROR); +test('3e', ERROR); +test('3e00', ERROR); +test('3eff', ERROR); +test('3f', ERROR); +test('3f00', ERROR); +test('3fff', ERROR); + +print('- Major type 0x40-0x5f: byte string'); + +try { + // Buffers decode as Uint8Arrays, matches cbor-js. + (function () { + var res = CBOR.decode(Duktape.dec('hex', '43112233').buffer); + print('typeof:', typeof res); + print('instanceof ByteArray:', res instanceof ArrayBuffer); + print('instanceof Uint8Array:', res instanceof Uint8Array); + print('proto is Uint8Array.prototype:', Object.getPrototypeOf(res) === Uint8Array.prototype); + print('is bare:', Object.getPrototypeOf(res) === null); + })(); +} catch (e) { + print(e.stack || e); +} + +function mkbuf(hexData) { + return Duktape.dec('hex', hexData).buffer; +} + +test('40', new Uint8Array([])); +test('4111', new Uint8Array([ 0x11 ])); +test('421122', new Uint8Array([ 0x11, 0x22 ])); +test('43112233', new Uint8Array([ 0x11, 0x22, 0x33 ])); +test('4411223344', new Uint8Array([ 0x11, 0x22, 0x33, 0x44 ])); +test('451122334455', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55 ])); +test('46112233445566', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 ])); +test('4711223344556677', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 ])); +test('47666f6f00666f6f', new Uint8Array([ 0x66, 0x6f, 0x6f, 0x00, 0x66, 0x6f, 0x6f ])); +test('481122334455667788', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 ])); +test('49112233445566778899', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 ])); +test('4a112233445566778899aa', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa ])); +test('4b112233445566778899aabb', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb ])); +test('4c112233445566778899aabbcc', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc ])); +test('4d112233445566778899aabbccdd', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd ])); +test('4e112233445566778899aabbccddee', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee ])); +test('4f112233445566778899aabbccddeeff', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff ])); +test('50112233445566778899aabbccddeeff00', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00 ])); +test('51112233445566778899aabbccddeeff0011', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11 ])); +test('52112233445566778899aabbccddeeff001122', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22 ])); +test('53112233445566778899aabbccddeeff00112233', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33 ])); +test('54112233445566778899aabbccddeeff0011223344', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44 ])); +test('55112233445566778899aabbccddeeff001122334455', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 ])); +test('56112233445566778899aabbccddeeff00112233445566', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 ])); +test('57112233445566778899aabbccddeeff0011223344556677', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 ])); +test('58', ERROR); +test('5800', new Uint8Array([])); +test('5801ff', new Uint8Array([ 0xff ])); +test('5817112233445566778899aabbccddeeff0011223344556677', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 ])); +test('5818112233445566778899aabbccddeeff001122334455667788', new Uint8Array([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 ])); +test('58ff' + 'fe'.repeat(255), mkbuf('fe'.repeat(255))); +test('59', ERROR); +test('5900', ERROR); +test('590000', new Uint8Array([])); +test('590001ff', new Uint8Array([ 0xff ])); +test('5900ff' + 'fe'.repeat(255), mkbuf('fe'.repeat(255))); +test('590100' + 'fe'.repeat(256), mkbuf('fe'.repeat(256))); +test('59fffe' + 'fe'.repeat(65534), mkbuf('fe'.repeat(65534))); +test('59ffff' + 'fe'.repeat(65535), mkbuf('fe'.repeat(65535))); +test('5a', ERROR); +test('5a00', ERROR); +test('5a0000', ERROR); +test('5a000000', ERROR); +test('5a00000000', new Uint8Array([])); +test('5a00000001ff', new Uint8Array([ 0xff ])); +test('5a000000ff' + 'fe'.repeat(255), mkbuf('fe'.repeat(255))); +test('5a0000fffe' + 'fe'.repeat(65534), mkbuf('fe'.repeat(65534))); +test('5a0000ffff' + 'fe'.repeat(65535), mkbuf('fe'.repeat(65535))); +// We'd like to test up to 4G but it's better to do as a separate test. +test('5a01000000' + 'fe'.repeat(0x1000000), mkbuf('fe'.repeat(0x1000000))); +test('5b', ERROR); +test('5b00', ERROR); +test('5b0000', ERROR); +test('5b000000', ERROR); +test('5b00000000', ERROR); +test('5b0000000000', ERROR); +test('5b000000000000', ERROR); +test('5b00000000000000', ERROR); +test('5b0000000000000000', new Uint8Array([])); +test('5b0000000000000001ff', new Uint8Array([ 0xff ])); +test('5b00000000000000ff' + 'fe'.repeat(255), mkbuf('fe'.repeat(255))); +test('5b000000000000fffe' + 'fe'.repeat(65534), mkbuf('fe'.repeat(65534))); +test('5b000000000000ffff' + 'fe'.repeat(65535), mkbuf('fe'.repeat(65535))); +test('5b0000000001000000' + 'fe'.repeat(0x1000000), mkbuf('fe'.repeat(0x1000000))); +test('5c', ERROR); +test('5c00', ERROR); +test('5cff', ERROR); +test('5d', ERROR); +test('5d00', ERROR); +test('5dff', ERROR); +test('5e', ERROR); +test('5e00', ERROR); +test('5eff', ERROR); +test('5f', ERROR); +test('5f00', ERROR); +test('5f00ff', ERROR); +test('5f01ff', ERROR); +test('5f20ff', ERROR); +test('5f21ff', ERROR); +test('5f40ff', new Uint8Array([])); +test('5f41abff', new Uint8Array([ 0xab ])); +test('5f' + '40' + '40' + '4111' + '5830' + '22'.repeat(48) + '40' + '590400' + '33'.repeat(1024) + '40' + + '5a00012345' + '44'.repeat(0x12345) + '5b0000000000023456' + '55'.repeat(0x23456) + 'ff', + mkbuf('11' + '22'.repeat(48) + '33'.repeat(1024) + '44'.repeat(0x12345) + '55'.repeat(0x23456))); +test('5f' + '40'.repeat(10000) + '43112233' + '40'.repeat(10000) + 'ff', mkbuf('112233')); +test('5f' + '43112233' + '6141' + 'ff', ERROR); +test('5f5fffff', ERROR); // nested indefinite length, prohibited +test('5f60ff', ERROR); +test('5f61ff', ERROR); +test('5f80ff', ERROR); +test('5f81ff', ERROR); +test('5fa0ff', ERROR); +test('5fa1ff', ERROR); +test('5fc0ff', ERROR); +test('5fc1ff', ERROR); +test('5fe0ff', ERROR); +test('5fe1ff', ERROR); +test('5fff', new Uint8Array([])); +test('5fffff', ERROR); + +print('- Major type 0x60-0x7f: text string'); + +test('60', ''); +test('6141', 'A'); +test('624142', 'AB'); +test('62dfbe', '\u07fe'); // two-byte UTF-8 +test('63dfbe41', '\u07feA'); +test('6441dfbe42', 'A\u07feB'); +test('6541efbb9c42', 'A\ufedcB'); // three-byte UTF-8 +test('6641efbb9c4243', 'A\ufedcBC'); +test('6741efbb9c424344', 'A\ufedcBCD'); +test('6841efbb9c42434445', 'A\ufedcBCDE'); +test('6941efbb9c4243444546', 'A\ufedcBCDEF'); +test('6a41efbb9c424344454647', 'A\ufedcBCDEFG'); +test('6b41efbb9c42434445464748', 'A\ufedcBCDEFGH'); +test('6c41efbb9c4243444546474849', 'A\ufedcBCDEFGHI'); +test('6d41efbb9c42434445464748494a', 'A\ufedcBCDEFGHIJ'); +test('6e41efbb9c42434445464748494a4b', 'A\ufedcBCDEFGHIJK'); +test('6f41efbb9c42434445464748494a4b4c', 'A\ufedcBCDEFGHIJKL'); +test('7041efbb9c42434445464748494a4b4c4d', 'A\ufedcBCDEFGHIJKLM'); +test('7141efbb9c42434445464748494a4b4c4d4e', 'A\ufedcBCDEFGHIJKLMN'); +test('7241efbb9c42434445464748494a4b4c4d4e4f', 'A\ufedcBCDEFGHIJKLMNO'); +test('7341efbb9c42434445464748494a4b4c4d4e4f50', 'A\ufedcBCDEFGHIJKLMNOP'); +test('7441efbb9c42434445464748494a4b4c4d4e4f5051', 'A\ufedcBCDEFGHIJKLMNOPQ'); +test('7541efbb9c42434445464748494a4b4c4d4e4f505152', 'A\ufedcBCDEFGHIJKLMNOPQR'); +test('7641efbb9c42434445464748494a4b4c4d4e4f50515253', 'A\ufedcBCDEFGHIJKLMNOPQRS'); +test('7741efbb9c42434445464748494a4b4c4d4e4f5051525354', 'A\ufedcBCDEFGHIJKLMNOPQRST'); +test('78', ERROR); +test('7800', ''); +test('78026162', 'ab'); +test('781741efbb9c42434445464748494a4b4c4d4e4f5051525354', 'A\ufedcBCDEFGHIJKLMNOPQRST'); +test('7818' + '41'.repeat(24), 'A'.repeat(24)); +test('78ff' + '41'.repeat(255), 'A'.repeat(255)); +test('79', ERROR); +test('7900', ERROR); +test('790000', ''); +test('79000141', 'A'); +test('7900ff' + '41'.repeat(255), 'A'.repeat(255)); +test('790100' + '41'.repeat(256), 'A'.repeat(256)); +test('79fffe' + '41'.repeat(65534), 'A'.repeat(65534)); +test('79ffff' + '41'.repeat(65535), 'A'.repeat(65535)); +test('7a', ERROR); +test('7a00', ERROR); +test('7a0000', ERROR); +test('7a000000', ERROR); +test('7a00000000', ''); +test('7a0000000141', 'A'); +test('7a000000ff' + '41'.repeat(255), 'A'.repeat(255)); +test('7a0000fffe' + '41'.repeat(65534), 'A'.repeat(65534)); +test('7a0000ffff' + '41'.repeat(65535), 'A'.repeat(65535)); +test('7a01000000' + '41'.repeat(0x1000000), 'A'.repeat(0x1000000)); +test('7b', ERROR); +test('7b00', ERROR); +test('7b0000', ERROR); +test('7b000000', ERROR); +test('7b00000000', ERROR); +test('7b0000000000', ERROR); +test('7b000000000000', ERROR); +test('7b00000000000000', ERROR); +test('7b0000000000000000', ''); +test('7b000000000000000141', 'A'); +test('7b00000000000000ff' + '41'.repeat(255), 'A'.repeat(255)); +test('7b000000000000fffe' + '41'.repeat(65534), 'A'.repeat(65534)); +test('7b000000000000ffff' + '41'.repeat(65535), 'A'.repeat(65535)); +test('7b0000000001000000' + '41'.repeat(0x1000000), 'A'.repeat(0x1000000)); +test('7c', ERROR); +test('7c00', ERROR); +test('7cff', ERROR); +test('7d', ERROR); +test('7d00', ERROR); +test('7dff', ERROR); +test('7e', ERROR); +test('7e00', ERROR); +test('7eff', ERROR); +test('7f', ERROR); +test('7f00', ERROR); +test('7f00ff', ERROR); +test('7f01ff', ERROR); +test('7f20ff', ERROR); +test('7f21ff', ERROR); +test('7f40ff', ERROR); +test('7f41ff', ERROR); +test('7f60ff', ''); +test('7f6141ff', 'A'); +test('7f' + '60' + '60' + '6142' + '7830' + '43'.repeat(48) + '60' + '790400' + '44'.repeat(1024) + '60' + + '7a00012345' + '45'.repeat(0x12345) + '7b0000000000023456' + '46'.repeat(0x23456) + 'ff', + 'B' + 'C'.repeat(48) + 'D'.repeat(1024) + 'E'.repeat(0x12345) + 'F'.repeat(0x23456)); +test('7f' + '60'.repeat(10000) + '63414243' + '60'.repeat(10000) + 'ff', 'ABC'); +test('7f' + '63414243' + '4141' + 'ff', ERROR); +test('7f7fffff', ERROR); // nested indefinite length, prohibited +test('7f80ff', ERROR); +test('7f81ff', ERROR); +test('7fa0ff', ERROR); +test('7fa1ff', ERROR); +test('7fc0ff', ERROR); +test('7fc1ff', ERROR); +test('7fe0ff', ERROR); +test('7fe1ff', ERROR); +test('7fff', ''); +test('7fffff', ERROR); +// Non-BMP and non-UTF-8 tests separately. + +print('- Major type 0x80-0x9f: array'); + +try { + (function () { + var res = CBOR.decode(Duktape.dec('hex', '83010203').buffer); + print('typeof:', typeof res); + print('instanceof Array:', res instanceof Array); + print('Array.isArray:', Array.isArray(res)); + print('proto is Array.prototype:', Object.getPrototypeOf(res) === Array.prototype); + print('is bare:', Object.getPrototypeOf(res) === null); + })(); +} catch (e) { + print(e.stack || e); +} + +function mkarrcbor(size) { + var res = []; + for (var i = 0; i < size; i++) { + var t1 = 'foo' + String(i); + var t1_cbor = (0x60 + t1.length).toString(16) + Duktape.enc('hex', t1); + res.push(t1_cbor); + } + return res.join(''); +} + +function mkarr(size) { + var res = []; + for (var i = 0; i < size; i++) { + var t1 = 'foo' + String(i); + res.push(t1); + } + return res; +} + +test('80', []); +test('8100', [0]); +test('8163414243', [ 'ABC' ]); +test('820001', [0,1]); +test('83000102', [0,1,2]); +test('8363666f6f607803626172', [ 'foo', '', 'bar' ]); +test('83820102810380', [ [1, 2], [3], [] ]); +test('8400010203', [0,1,2,3]); +test('850001020304', [0,1,2,3,4]); +test('86000102030405', [0,1,2,3,4,5]); +test('8700010203040506', [0,1,2,3,4,5,6]); +test('880001020304050607', [0,1,2,3,4,5,6,7]); +test('89000102030405060708', [0,1,2,3,4,5,6,7,8]); +test('8a00010203040506070809', [0,1,2,3,4,5,6,7,8,9]); +test('8b000102030405060708090a', [0,1,2,3,4,5,6,7,8,9,10]); +test('8c000102030405060708090a0b', [0,1,2,3,4,5,6,7,8,9,10,11]); +test('8d000102030405060708090a0b0c', [0,1,2,3,4,5,6,7,8,9,10,11,12]); +test('8e000102030405060708090a0b0c0d', [0,1,2,3,4,5,6,7,8,9,10,11,12,13]); +test('8f000102030405060708090a0b0c0d0e', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]); +test('90000102030405060708090a0b0c0d0e0f', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); +test('91000102030405060708090a0b0c0d0e0f10', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]); +test('92000102030405060708090a0b0c0d0e0f1011', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]); +test('93000102030405060708090a0b0c0d0e0f101112', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]); +test('94000102030405060708090a0b0c0d0e0f10111213', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]); +test('95000102030405060708090a0b0c0d0e0f1011121314', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]); +test('96000102030405060708090a0b0c0d0e0f101112131415', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]); +test('97000102030405060708090a0b0c0d0e0f10111213141516', [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22]); +test('98', ERROR); +test('9800', []); +test('980163666f6f', [ 'foo' ]); +test('9803' + mkarrcbor(3), mkarr(3)); +test('9880' + mkarrcbor(128), mkarr(128)); +test('98ff' + mkarrcbor(255), mkarr(255)); +test('99', ERROR); +test('9900', ERROR); +test('990000', []); +test('9900ff' + mkarrcbor(255), mkarr(255)); +test('99fedc' + mkarrcbor(0xfedc), mkarr(0xfedc)); +test('99ffff' + mkarrcbor(65535), mkarr(65535)); +test('9a', ERROR); +test('9a00', ERROR); +test('9a0000', ERROR); +test('9a000000', ERROR); +test('9a00000000', []); +test('9a000000ff' + mkarrcbor(255), mkarr(255)); +test('9a0000fedc' + mkarrcbor(0xfedc), mkarr(0xfedc)); +test('9a0000ffff' + mkarrcbor(65535), mkarr(65535)); +test('9a00023456' + mkarrcbor(0x23456), mkarr(0x23456)); +test('9b', ERROR); +test('9b00', ERROR); +test('9b0000', ERROR); +test('9b000000', ERROR); +test('9b00000000', ERROR); +test('9b0000000000', ERROR); +test('9b000000000000', ERROR); +test('9b00000000000000', ERROR); +test('9b0000000000000000', []); +test('9b00000000000000ff' + mkarrcbor(255), mkarr(255)); +test('9b000000000000fedc' + mkarrcbor(0xfedc), mkarr(0xfedc)); +test('9b000000000000ffff' + mkarrcbor(65535), mkarr(65535)); +test('9b0000000000023456' + mkarrcbor(0x23456), mkarr(0x23456)); +test('9c', ERROR); +test('9c00', ERROR); +test('9cff', ERROR); +test('9d', ERROR); +test('9d00', ERROR); +test('9dff', ERROR); +test('9e', ERROR); +test('9e00', ERROR); +test('9eff', ERROR); +test('9f', ERROR); +test('9f00', ERROR); +test('9fff', []); +test('9fffff', ERROR); + +print('- Major type 0xa0-0xbf: map'); + +try { + (function () { + var res = CBOR.decode(Duktape.dec('hex', 'a3010203040506').buffer); + print('typeof:', typeof res); + print('instanceof Object:', res instanceof Object); + print('proto is Object.prototype:', Object.getPrototypeOf(res) === Object.prototype); + print('is bare:', Object.getPrototypeOf(res) === null); + })(); +} catch (e) { + print(e.stack || e); +} + +function mkobjcbor(size) { + var res = []; + for (var i = 0; i < size; i++) { + var t1 = 'foo' + String(i); + var t1_cbor = (0x60 + t1.length).toString(16) + Duktape.enc('hex', t1); + var t2 = 'bar' + String(i); + var t2_cbor = (0x60 + t2.length).toString(16) + Duktape.enc('hex', t2); + res.push(t1_cbor + t2_cbor); + } + return res.join(''); +} + +function mkobj(size) { + var res = {}; + for (var i = 0; i < size; i++) { + var t1 = 'foo' + String(i); + var t2 = 'bar' + String(i); + res[t1] = t2; + } + return res; +} + +test('a0', {}); +test('a10001', {0:1}); +test('a16341424363434241', {ABC:'CBA'}); +test('a200010203', {0:1,2:3}); +test('a3000102030405', {0:1,2:3,4:5}); +test('a36141a2010203046142a105066143a0', { A: { 1:2, 3:4 }, B: { 5:6 }, C: {} }); +test('a40001020304050607', {0:1,2:3,4:5,6:7}); +test('a500010203040506070809', {0:1,2:3,4:5,6:7,8:9}); +test('a6000102030405060708090a0b', {0:1,2:3,4:5,6:7,8:9,10:11}); +test('a7000102030405060708090a0b0c0d', {0:1,2:3,4:5,6:7,8:9,10:11,12:13}); +test('a8000102030405060708090a0b0c0d0e0f', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15}); +test('a9000102030405060708090a0b0c0d0e0f1011', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17}); +test('aa000102030405060708090a0b0c0d0e0f10111213', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19}); +test('ab000102030405060708090a0b0c0d0e0f101112131415', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21}); +test('ac000102030405060708090a0b0c0d0e0f1011121314151617', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23}); +test('ad000102030405060708090a0b0c0d0e0f101112131415161718181819', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25}); +test('ae000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27}); +test('af000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29}); +test('b0000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31}); +test('b1000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f18201821', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31,32:33}); +test('b2000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f1820182118221823', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31,32:33,34:35}); +test('b3000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f182018211822182318241825', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31,32:33,34:35,36:37}); +test('b4000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f18201821182218231824182518261827', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31,32:33,34:35,36:37,38:39}); +test('b5000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f1820182118221823182418251826182718281829', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31,32:33,34:35,36:37,38:39,40:41}); +test('b6000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f1820182118221823182418251826182718281829182a182b', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31,32:33,34:35,36:37,38:39,40:41,42:43}); +test('b7000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f1820182118221823182418251826182718281829182a182b182c182d', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31,32:33,34:35,36:37,38:39,40:41,42:43,44:45}); +test('b8', ERROR); +test('b800', {}); +test('b80161416142', {A:'B'}); +test('b818000102030405060708090a0b0c0d0e0f101112131415161718181819181a181b181c181d181e181f1820182118221823182418251826182718281829182a182b182c182d182e182f', {0:1,2:3,4:5,6:7,8:9,10:11,12:13,14:15,16:17,18:19,20:21,22:23,24:25,26:27,28:29,30:31,32:33,34:35,36:37,38:39,40:41,42:43,44:45,46:47}); +test('b803' + mkobjcbor(3), mkobj(3)); +test('b880' + mkobjcbor(128), mkobj(128)); +test('b8ff' + mkobjcbor(255), mkobj(255)); +test('b9', ERROR); +test('b900', ERROR); +test('b90000', {}); +test('b900011011', {16:17}); +test('b900ff' + mkobjcbor(255), mkobj(255)); +test('b9fedc' + mkobjcbor(0xfedc), mkobj(0xfedc)); +test('b9ffff' + mkobjcbor(65535), mkobj(65535)); +test('ba', ERROR); +test('ba00', ERROR); +test('ba0000', ERROR); +test('ba000000', ERROR); +test('ba00000000', {}); +test('ba000000ff' + mkobjcbor(255), mkobj(255)); +test('ba0000fedc' + mkobjcbor(0xfedc), mkobj(0xfedc)); +test('ba0000ffff' + mkobjcbor(65535), mkobj(65535)); +test('ba00023456' + mkobjcbor(0x23456), mkobj(0x23456)); +test('bb', ERROR); +test('bb00', ERROR); +test('bb0000', ERROR); +test('bb000000', ERROR); +test('bb00000000', ERROR); +test('bb0000000000', ERROR); +test('bb000000000000', ERROR); +test('bb00000000000000', ERROR); +test('bb0000000000000000', {}); +test('bb00000000000000ff' + mkobjcbor(255), mkobj(255)); +test('bb000000000000fedc' + mkobjcbor(0xfedc), mkobj(0xfedc)); +test('bb000000000000ffff' + mkobjcbor(65535), mkobj(65535)); +test('bb0000000000023456' + mkobjcbor(0x23456), mkobj(0x23456)); +test('bc', ERROR); +test('bc00', ERROR); +test('bcff', ERROR); +test('bd', ERROR); +test('bd00', ERROR); +test('bdff', ERROR); +test('be', ERROR); +test('be00', ERROR); +test('beff', ERROR); +test('bf', ERROR); +test('bf00', ERROR); +test('bfff', {}); +test('bfffff', ERROR); + +print('- Major type 0xc0-0xdf: tag'); + +test('c0', ERROR); // tag alone is not valid +test('c012', 18); +test('c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c012', 18); // multiple tags are fine +test('c0c1c2c3c4c5c6c7c8c9cacbcccdcecdcf' + + 'd0d1d2d3d4d5d6d7' + 'd812d91234da12345678db123456789abcdef0' + '12', 18); +test('c112', 18); +test('c212', 18); +test('c312', 18); +test('c412', 18); +test('c512', 18); +test('c612', 18); +test('c712', 18); +test('c812', 18); +test('c912', 18); +test('ca12', 18); +test('cb12', 18); +test('cc12', 18); +test('cd12', 18); +test('ce12', 18); +test('cf12', 18); +test('d012', 18); +test('d112', 18); +test('d212', 18); +test('d312', 18); +test('d412', 18); +test('d512', 18); +test('d612', 18); +test('d712', 18); +test('d8', ERROR); +test('d800', ERROR); +test('d80012', 18); +test('d8dc'.repeat(100000) + '18fe', 254); +test('d9', ERROR); +test('d900', ERROR); +test('d90000', ERROR); +test('d9000012', 18); +test('da', ERROR); +test('da00', ERROR); +test('da0000', ERROR); +test('da000000', ERROR); +test('da00000000', ERROR); +test('da0000000012', 18); +test('db', ERROR); +test('db00', ERROR); +test('db0000', ERROR); +test('db000000', ERROR); +test('db00000000', ERROR); +test('db0000000000', ERROR); +test('db000000000000', ERROR); +test('db00000000000000', ERROR); +test('db0000000000000000', ERROR); +test('db000000000000000012', 18); +test('dc', ERROR); +test('dd', ERROR); +test('de', ERROR); +test('df', ERROR); +test('df00', ERROR); +test('dfff', ERROR); +test('dfffff', ERROR); + +print('- Major type 0xe0-0xff: simple types, floating point numbers, break, etc'); + +// 0xe0-0xf3: unassigned +test('e0', ERROR); +test('e1', ERROR); +test('e2', ERROR); +test('e3', ERROR); +test('e4', ERROR); +test('e5', ERROR); +test('e6', ERROR); +test('e7', ERROR); +test('e8', ERROR); +test('e9', ERROR); +test('ea', ERROR); +test('eb', ERROR); +test('ec', ERROR); +test('ed', ERROR); +test('ee', ERROR); +test('ef', ERROR); +test('f0', ERROR); +test('f1', ERROR); +test('f2', ERROR); +test('f3', ERROR); +test('f4', false); +test('f5', true); +test('f6', null); // CBOR null +test('f7', void 0); // CBOR undefined +// 0xf8: simple value, one byte follows, bytes 0-31 not allowed. +// See RFC 7049, Section 2.3. However, some bindings will decode +// such simple types, e.g. f815 as true. +test('f8', ERROR); +test('f800', ERROR); +test('f801', ERROR); +test('f802', ERROR); +test('f803', ERROR); +test('f804', ERROR); +test('f805', ERROR); +test('f806', ERROR); +test('f807', ERROR); +test('f808', ERROR); +test('f809', ERROR); +test('f80a', ERROR); +test('f80b', ERROR); +test('f80c', ERROR); +test('f80d', ERROR); +test('f80e', ERROR); +test('f80f', ERROR); +test('f810', ERROR); +test('f811', ERROR); +test('f812', ERROR); +test('f813', ERROR); +test('f814', ERROR); +test('f815', ERROR); +test('f816', ERROR); +test('f817', ERROR); +test('f818', ERROR); +test('f819', ERROR); +test('f81a', ERROR); +test('f81b', ERROR); +test('f81c', ERROR); +test('f81d', ERROR); +test('f81e', ERROR); +test('f81f', ERROR); +// 0xf9: half-float +/* +>>> cbor.loads('f90000'.decode('hex')) +0.0 +>>> cbor.loads('f90001'.decode('hex')) +5.960464477539063e-08 +>>> cbor.loads('f9c400'.decode('hex')) +-4.0 +>>> cbor.loads('f97c00'.decode('hex')) +inf +>>> cbor.loads('f97c01'.decode('hex')) +nan +>>> cbor.loads('f97fff'.decode('hex')) +nan +>>> cbor.loads('f98000'.decode('hex')) +-0.0 +>>> cbor.loads('f98001'.decode('hex')) +-5.960464477539063e-08 +>>> cbor.loads('f9fc00'.decode('hex')) +-inf +>>> cbor.loads('f9fc01'.decode('hex')) +nan +>>> cbor.loads('f9ffff'.decode('hex')) +nan +*/ +test('f90000', 0); +test('f90001', 5.960464477539063e-08); +test('f9c400', -4); +test('f97c00', 1 / 0); +test('f97c01', 0 / 0); +test('f97fff', 0 / 0); +test('f98000', -0); +test('f98001', -5.960464477539063e-08); +test('f9fc00', -1 / 0); +test('f9fc01', 0 / 0); +test('f9ffff', 0 / 0); +// 0xfa: single +/* +>>> cbor.loads('fa00000000'.decode('hex')) +0.0 +>>> cbor.loads('fa00000001'.decode('hex')) +1.401298464324817e-45 +>>> cbor.loads('fa7f800000'.decode('hex')) +inf +>>> cbor.loads('fa7f800001'.decode('hex')) +nan +>>> cbor.loads('fa7fffffff'.decode('hex')) +nan +>>> cbor.loads('fa80000000'.decode('hex')) +-0.0 +>>> cbor.loads('fa80000001'.decode('hex')) +-1.401298464324817e-45 +>>> cbor.loads('faff800000'.decode('hex')) +-inf +>>> cbor.loads('faff800001'.decode('hex')) +nan +>>> cbor.loads('faffffffff'.decode('hex')) +nan +*/ +test('fa00000000', 0); +test('fa00000001', 1.401298464324817e-45); +test('fa47c35000', 100000); +test('fa7f800000', 1 / 0); +test('fa7f800001', 0 / 0); +test('fa7fffffff', 0 / 0); +test('fa80000000', -0); +test('fa80000001', -1.401298464324817e-45); +test('faff800000', -1 / 0); +test('faff800001', 0 / 0); +test('fa7fffffff', 0 / 0); +// 0xfb: double +/* +>>> struct.pack('>d', math.pi).encode('hex') +'400921fb54442d18' +*/ +/* +>>> cbor.loads('fb0000000000000000'.decode('hex')) +0.0 +>>> cbor.loads('fb0000000000000001'.decode('hex')) +5e-324 +>>> cbor.loads('fb7ff0000000000000'.decode('hex')) +inf +>>> cbor.loads('fb7ff0000000000001'.decode('hex')) +nan +>>> cbor.loads('fb7fffffffffffffff'.decode('hex')) +nan +>>> cbor.loads('fb8000000000000000'.decode('hex')) +-0.0 +>>> cbor.loads('fb8000000000000001'.decode('hex')) +-5e-324 +>>> cbor.loads('fbfff0000000000000'.decode('hex')) +-inf +>>> cbor.loads('fbfff0000000000001'.decode('hex')) +nan +>>> cbor.loads('fbffffffffffffffff'.decode('hex')) +nan +*/ +test('fb0000000000000000', 0); +test('fb0000000000000001', 5e-324); +test('fb400921fb54442d18', Math.PI); +test('fb7ff0000000000000', 1 / 0); +test('fb7ff0000000000001', 0 / 0); +test('fb7fffffffffffffff', 0 / 0); +test('fb8000000000000000', -0); +test('fb8000000000000001', -5e-324); +test('fbc010666666666666', -4.1); +test('fbfff0000000000000', -1 / 0); +test('fbfff0000000000001', 0 / 0); +test('fbffffffffffffffff', 0 / 0); +test('fc', ERROR); // unassigned +test('fd', ERROR); // unassigned +test('fe', ERROR); // unassigned +// 0xff: break +test('ff', ERROR); // break, out of context +test('ff00', ERROR); +test('ffff', ERROR); +test('ffffff', ERROR); + +print('done'); diff --git a/tests/ecmascript/test-bi-cbor-enc-nonutf8.js b/tests/ecmascript/test-bi-cbor-enc-nonutf8.js new file mode 100644 index 00000000..38e56e35 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-enc-nonutf8.js @@ -0,0 +1,49 @@ +/* + * Test for default string encoding behavior: valid UTF-8 strings are + * encoded as CBOR text strings, other strings as CBOR byte strings. + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +66666f6f626172 +"foobar" +69666f6fe188b4626172 +"foo\u1234bar" +49666f6feda080626172 +|666f6feda080626172| +49666f6fedb080626172 +|666f6fedb080626172| +4d666f6fedb08064383030626172 +|666f6fedb08064383030626172| +4c666f6feda0bdedb2a9626172 +|666f6feda0bdedb2a9626172| +done +===*/ + +function test(val) { + var t = CBOR.encode(val); + print(Duktape.enc('hex', t)); + print(Duktape.enc('jx', CBOR.decode(t))); +} + +// Plain ASCII. +test('foobar'); + +// BMP. +test('foo\u1234bar'); + +// Unpaired surrogate. +test('foo\ud800bar'); +test('foo\udc00bar'); +test('foo\udc00d800bar'); + +// Paired surrogate. Currently CBOR.encode() does not combine the +// surrogate. +test('foo\ud83d\udca9bar'); + +print('done'); diff --git a/tests/ecmascript/test-bi-cbor-enc-proxy-side-effect.js b/tests/ecmascript/test-bi-cbor-enc-proxy-side-effect.js new file mode 100644 index 00000000..173dd299 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-enc-proxy-side-effect.js @@ -0,0 +1,48 @@ +/*--- +{ + "skip": true +} +---*/ + +/*=== +ownKeys +get: foo +get: bar +a263666f6f63464f4f6362617263424152 +{"foo":"FOO","bar":"BAR"} +done +===*/ + +function test() { + var O = { foo: 1, bar: 2 }; // no 'quux' in target + var P = new Proxy(O, { + ownKeys: function (targ) { + print('ownKeys'); + return [ 'foo', 'bar', 'quux' ]; + }, + get: function (targ, key, recv) { + print('get:', key); + if (key === 'foo') { + return 'FOO'; + } else if (key === 'bar') { + return 'BAR'; + } else if (key === 'quux') { + return 'QUUX'; + } else { + return void 0; + } + } + }); + + var res = CBOR.encode(P); + print(Duktape.enc('hex', res)); + print(JSON.stringify(CBOR.decode(res))); +} + +try { + test(); +} catch (e) { + print(e.stack || e); +} + +print('done'); diff --git a/tests/ecmascript/test-bi-cbor-enc-symbol.js b/tests/ecmascript/test-bi-cbor-enc-symbol.js new file mode 100644 index 00000000..afe64df4 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-enc-symbol.js @@ -0,0 +1,19 @@ +/* + * Test for Symbol encoding behavior; for now encoded as an empty object. + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +a0 +===*/ + +try { + print(Duktape.enc('hex', CBOR.encode(Symbol('foo')))); +} catch (e) { + print(e.stack || e); +} diff --git a/tests/ecmascript/test-bi-cbor-enc-types.js b/tests/ecmascript/test-bi-cbor-enc-types.js new file mode 100644 index 00000000..26b0498c --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-enc-types.js @@ -0,0 +1,211 @@ +/* + * Encode test for all major ECMAScript types. + * + * Encoding is not unique, so this demonstrates current output. + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +done +===*/ + +function test(val, expect) { + var res = Duktape.enc('hex', CBOR.encode(val)); + // print(res); + if (res !== expect) { + print('MISMATCH, got ' + res + ', expected ' + expect); + } +} + +// Primitive types. +test(void 0, 'f7'); +test(null, 'f6'); +test(true, 'f5'); +test(false, 'f4'); +test(123, '187b'); +/* +>>> cbor.dumps(123.1).encode('hex') +'fb405ec66666666666' +*/ +test(123.1, 'fb405ec66666666666'); +/* +>>> cbor.dumps(u'foo\u07fe\ucafebar').encode('hex') +'6b666f6fdfbeecabbe626172' +*/ +test('foo\u07fe\ucafebar', '6b666f6fdfbeecabbe626172'); + +// Object types. +test([ 'foo', 'bar', 1, 2, 3, [ 4, 5 ], 'quux' ], '8763666f6f636261720102038204056471757578'); +test({ foo: 'bar', quux: { baz: true } }, 'a263666f6f636261726471757578a16362617af5'); +test(new Uint8Array([ 1, 2, 3 ]), '43010203'); +test(function foo() {}, 'a0'); // ECMAScript function +test(Math.cos, 'a0'); // native function +test(Math.cos.bind(123, 234), 'a0'); // bound function +test(new Date(2019, 1, 2, 3, 4, 5), 'a0'); +test(/foobar/g, 'a0'); +test(new Proxy({}, {}), 'a0'); +// Cover null pointer only, encodes to "(null)" now. +// XXX: non-null pointers +test(Duktape.Pointer(null), '66286e756c6c29'); +// XXX: lightfunc + +// Buffer type details. +// For > 1-byte types expect string is little endian. +var buf = Uint8Array.allocPlain(4); +buf[2] = 0xfe; +test(buf, '440000fe00'); +test(new Uint8Array([ 1, 2, 3, 4 ]).buffer, '4401020304'); +test(new Uint8Array([ 0xfe, 1, 2, 3 ]), '44fe010203'); +test(new Uint8ClampedArray([ 0x10fe, -100, 1, 2 ]), '44ff000102'); +test(new Int8Array([ 0xfe, 1, 2, 3 ]), '44fe010203'); +test(new Uint16Array([ 0xfe, 1, 2, 3 ]), '48fe00010002000300'); +test(new Int16Array([ 0xfe, 1, 2, 3 ]), '48fe00010002000300'); +test(new Uint32Array([ 0xfe, 1, 2, 3 ]), '50fe000000010000000200000003000000'); +test(new Int32Array([ 0xfe, 1, 2, 3 ]), '50fe000000010000000200000003000000'); +test(new Float32Array([ 0xfe, 1, 2, 3 ]), '5000007e430000803f0000004000004040'); +test(new Float64Array([ 0xfe, 1, 2, 3 ]), '58200000000000c06f40000000000000f03f00000000000000400000000000000840'); +var dv = new DataView(new Uint8Array([ 1, 2, 3, 4, 5, 6 ]).buffer); +test(dv, '46010203040506'); + +// Gap in array, similar to undefined, now encodes the same. +var arr = new Array(1); +test(arr, '81f7'); +var arr = [ void 0 ]; +test(arr, '81f7'); + +// Integer tests. +/* +>>> cbor.loads('f98000'.decode('hex')) +-0.0 +*/ +test(-0, 'f98000'); +test(+0, '00'); +test(1, '01'); +test(23, '17'); +test(24, '1818'); +test(255, '18ff'); +test(256, '190100'); +test(65534, '19fffe'); +test(65535, '19ffff'); +test(65536, '1a00010000'); +test(0xfedcab98, '1afedcab98'); +test(0xffffffff, '1affffffff'); +// Currently 64-bit integers are never used, shortest float +// maintaining precision is used. No integers encode to +// half-float because 16-bit integer encodings are better +// and same size. +/* +>>> cbor.loads('fa4f800000'.decode('hex')) +4294967296.0 +>>> cbor.loads('fb41f0000000100000'.decode('hex')) +4294967297.0 +>>> cbor.loads('fb41f0000000200000'.decode('hex')) +4294967298.0 +>>> cbor.loads('fb41f0000000300000'.decode('hex')) +4294967299.0 +>>> cbor.loads('fb41f0000000400000'.decode('hex')) +4294967300.0 +>>> cbor.loads('fb41f0000000500000'.decode('hex')) +4294967301.0 +>>> cbor.loads('fb41f0000000600000'.decode('hex')) +4294967302.0 +*/ +test(0x100000000, 'fa4f800000'); // encodes as float +test(0x100000001, 'fb41f0000000100000'); // encodes as double +test(0x100000002, 'fb41f0000000200000'); +test(0x100000003, 'fb41f0000000300000'); +test(0x100000004, 'fb41f0000000400000'); +test(0x100000005, 'fb41f0000000500000'); +test(0x100000006, 'fb41f0000000600000'); +test(-1, '20'); +test(-2, '21'); +test(-23, '36'); +test(-24, '37'); +test(-25, '3818'); +test(-255, '38fe'); +test(-256, '38ff'); +test(-257, '390100'); +test(-65535, '39fffe'); +test(-65536, '39ffff'); +test(-65537, '3a00010000'); +test(-0xfedcab98, '3afedcab97'); +test(-0xffffffff, '3afffffffe'); +test(-0x100000000, '3affffffff'); +// Here 3b0000000100000000 would be fine, but Duktape CBOR uses floats. +test(-0x100000001, 'fbc1f0000000100000'); +test(-0x100000002, 'fbc1f0000000200000'); +test(-0x100000003, 'fbc1f0000000300000'); +test(-0x100000004, 'fbc1f0000000400000'); +test(-0x100000005, 'fbc1f0000000500000'); +test(-0x100000006, 'fbc1f0000000600000'); + +// Other number tests. +/* +>>> cbor.loads('f93800'.decode('hex')) +0.5 +>>> cbor.loads('f93e00'.decode('hex')) +1.5 +>>> cbor.loads('fa47800040'.decode('hex')) +65536.5 +>>> cbor.loads('fb400921fb54442d18'.decode('hex')) +3.141592653589793 +>>> cbor.loads('fbc00921fb54442d18'.decode('hex')) +-3.141592653589793 +>>> cbor.loads('f97c00'.decode('hex')) +inf +>>> cbor.loads('f97e00'.decode('hex')) +nan +>>> cbor.loads('f9fc00'.decode('hex')) +-inf +*/ +test(0.5, 'f93800'); // half-float +test(1.5, 'f93e00'); // half-float +test(65536.5, 'fa47800040'); // single float +test(Math.PI, 'fb400921fb54442d18'); +test(-Math.PI, 'fbc00921fb54442d18'); +test(1 / 0, 'f97c00'); // half-float +test(-1 / 0, 'f9fc00'); // half-float +test(0 / 0, 'f97e00'); // half-float + +// Number tests from CBOR spec Appendix A. +//test(1.0, 'f93c00'); // Encoded as 01. +test(1.0, '01'); +test(1.1, 'fb3ff199999999999a'); +test(1.5, 'f93e00'); +//test(65504.0, 'f97bff'); // Encoded as 19ffe0. +test(65504.0, '19ffe0'); +//test(100000.0, 'fa47c35000'); // Encoded as 1a000186a0. +test(100000.0, '1a000186a0'); +test(3.4028234663852886e+38, 'fa7f7fffff'); +test(1.0e+300, 'fb7e37e43c8800759c'); +//test(5.960464477539063e-8, 'f90001'); // Encoded as fa33800000, no denormal encoding support yet. +test(5.960464477539063e-8, 'fa33800000'); +test(0.00006103515625, 'f90400'); +//test(-4.0, 'f9c400'); // Encoded as 23. +test(-4.0, '23'); +test(-4.1, 'fbc010666666666666'); + +// String tests, surrogates etc. +test('', '60'); +test('foo', '63666f6f'); +/* +>>> u'\ucafe'.encode('utf-8') +'\xec\xab\xbe' +*/ +test('foo\ucafebar', '69666f6fecabbe626172'); +test('12345678901234567890123', '773132333435363738393031323334353637383930313233'); +test('123456789012345678901234', '7818313233343536373839303132333435363738393031323334'); +test('A'.repeat(255), '78ff' + '41'.repeat(255)); +test('A'.repeat(256), '790100' + '41'.repeat(256)); +test('B'.repeat(65535), '79ffff' + '42'.repeat(65535)); +test('B'.repeat(65536), '7a00010000' + '42'.repeat(65536)); +test('C'.repeat(655360), '7a000a0000' + '43'.repeat(655360)); + +// Non-UTF-8 strings covered in separate tests. + +print('done'); diff --git a/tests/ecmascript/test-bi-cbor-extras-tests.js b/tests/ecmascript/test-bi-cbor-extras-tests.js index 7d9f86e7..5a44a5e4 100644 --- a/tests/ecmascript/test-bi-cbor-extras-tests.js +++ b/tests/ecmascript/test-bi-cbor-extras-tests.js @@ -349,8 +349,8 @@ enc(new Uint16Array([ 1, 2, 3, 4 ]), '480100020003000400'); // Endian specific; "" 60 60 "foo" 63666f6f 63666f6f "foo\u20acbar" 69666f6fe282ac626172 69666f6fe282ac626172 -"foo\ud800bar" 69666f6feda080626172 69666f6feda080626172 -"foo\udc00bar" 69666f6fedb080626172 69666f6fedb080626172 +"foo\ud800bar" 49666f6feda080626172 49666f6feda080626172 +"foo\udc00bar" 49666f6fedb080626172 49666f6fedb080626172 "\u4321\u4321\u4321\u4321\u4321\u4321\u4321xy" 77e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca17879 77e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca17879 "\u4321\u4321\u4321\u4321\u4321\u4321\u4321xyz" 7818e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca178797a 7818e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca178797a "\u4321\u4321\u4321\u4321\u4321\u4321\u4321xyzw" 7819e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca178797a77 7819e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca178797a77 @@ -362,8 +362,8 @@ enc(new Uint16Array([ 1, 2, 3, 4 ]), '480100020003000400'); // Endian specific; enc('', '60'); enc('foo', '63666f6f'); enc('foo\u20acbar', '69666f6fe282ac626172'); -enc('foo\ud800bar', '69666f6feda080626172'); // Unpaired surrogate, this is technically an invalid encoding because CBOR strings must be UTF-8; could maybe be encoded as a byte string instead (perhaps with a tag indicating extended UTF-8) -enc('foo\udc00bar', '69666f6fedb080626172'); // Unpaired surrogate, technically invalid +enc('foo\ud800bar', '49666f6feda080626172'); // Unpaired surrogate, invalid UTF-8, encodes as byte string +enc('foo\udc00bar', '49666f6fedb080626172'); // Unpaired surrogate, same behavior enc('\u4321\u4321\u4321\u4321\u4321\u4321\u4321xy', '77e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca17879'); enc('\u4321\u4321\u4321\u4321\u4321\u4321\u4321xyz', '7818e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca178797a'); enc('\u4321\u4321\u4321\u4321\u4321\u4321\u4321xyzw', '7819e48ca1e48ca1e48ca1e48ca1e48ca1e48ca1e48ca178797a77'); diff --git a/tests/ecmascript/test-bi-cbor-gappy-array.js b/tests/ecmascript/test-bi-cbor-gappy-array.js new file mode 100644 index 00000000..3735088a --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-gappy-array.js @@ -0,0 +1,72 @@ +/*--- +{ + "skip": true +} +---*/ + +/*=== +,,,foo,,,,,bar, +10 +0: false +1: false +2: false +3: true +4: false +5: false +6: false +7: false +8: true +9: false +10: false +11: false +8af7f7f763666f6ff7f7f7f763626172f7 +,,,foo,,,,,bar, +10 +0: true +1: true +2: true +3: true +4: true +5: true +6: true +7: true +8: true +9: true +10: false +11: false +===*/ + +function test() { + var i; + + var arr = new Array(10); + arr[3] = 'foo'; + arr[8] = 'bar'; + + print(String(arr)); + print(arr.length); + for (i = 0; i < 12; i++) { + print(i + ': ' + (i in arr)); + } + + // CBOR does not distinguish between an 'undefined' and a missing + // value (gap). So the gaps get encoded as 'undefined' up to the + // array length (10). When decoded, the arrays comes out with length + // 10 and gaps replaced with 'undefined'. + + var enc = CBOR.encode(arr); + print(Duktape.enc('hex', enc)); + arr = CBOR.decode(enc); + + print(String(arr)); + print(arr.length); + for (i = 0; i < 12; i++) { + print(i + ': ' + (i in arr)); + } +} + +try { + test(); +} catch (e) { + print(e.stack || e); +} diff --git a/tests/ecmascript/test-bi-cbor-half-float-denormal.js b/tests/ecmascript/test-bi-cbor-half-float-denormal.js new file mode 100644 index 00000000..1bcd1559 --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-half-float-denormal.js @@ -0,0 +1,26 @@ +/* + * Handling of half-float denormals. + * + * Decoding is covered by full coverage decode test, so only encode needs + * testing here. + */ + +/*--- +{ + "skip": true +} +---*/ + +/*=== +5.960464477539063e-8 +fa33800000 +done +===*/ + +// Current behavior is not to support half-float subnormals. It's not +// required, but would be nice for completeness. + +print(CBOR.decode(new Uint8Array([ 0xf9, 0x00, 0x01 ]))); +print(Duktape.enc('hex', CBOR.encode(5.960464477539063e-8))); + +print('done'); diff --git a/tests/ecmascript/test-bi-cbor-input-output-types.js b/tests/ecmascript/test-bi-cbor-input-output-types.js new file mode 100644 index 00000000..e73a57ec --- /dev/null +++ b/tests/ecmascript/test-bi-cbor-input-output-types.js @@ -0,0 +1,69 @@ +/*--- +{ + "skip": true +} +---*/ + +/*=== +foo +foo +===*/ + +// CBOR.decode() accepts any buffer type now; cbor-js only accepts an +// ArrayBuffer. + +var t; + +try { + t = new Uint8Array([ 0x63, 0x66, 0x6f, 0x6f ]).buffer; + print(CBOR.decode(t)); +} catch (e) { + print(e.name); +} + +try { + t = new Uint8Array([ 0x63, 0x66, 0x6f, 0x6f ]); + print(CBOR.decode(t)); +} catch (e) { + print(e.name); +} + +/*=== +object +true +false +===*/ + +// CBOR.encode() results in an ArrayBuffer. +try { + t = CBOR.encode('foo'); + print(typeof t); + print(t instanceof ArrayBuffer); + print(t instanceof Uint8Array); +} catch (e) { + print(e.name); +} + +/*=== +object +false +true +===*/ + +// While ArrayBuffer is the preferred input/output type, buffer values still +// decode as Uint8Array in cbor-js and Duktape. + +try { + t = CBOR.decode(new Uint8Array([ 0x43, 0x11, 0x22, 0x33 ]).buffer); + print(typeof t); + print(t instanceof ArrayBuffer); + print(t instanceof Uint8Array); +} catch (e) { + print(e.name); +} + +/*=== +done +===*/ + +print('done'); diff --git a/tests/ecmascript/test-bi-json-enc-proxy-side-effect.js b/tests/ecmascript/test-bi-json-enc-proxy-side-effect.js new file mode 100644 index 00000000..00fe603f --- /dev/null +++ b/tests/ecmascript/test-bi-json-enc-proxy-side-effect.js @@ -0,0 +1,47 @@ +/*--- +{ + "skip": true +} +---*/ + +/*=== +get: toJSON +ownKeys +get: foo +get: bar +{"foo":"FOO","bar":"BAR"} +done +===*/ + +function test() { + var O = { foo: 1, bar: 2 }; // no 'quux' in target + var P = new Proxy(O, { + ownKeys: function (targ) { + print('ownKeys'); + return [ 'foo', 'bar', 'quux' ]; + }, + get: function (targ, key, recv) { + print('get:', key); + if (key === 'foo') { + return 'FOO'; + } else if (key === 'bar') { + return 'BAR'; + } else if (key === 'quux') { + return 'QUUX'; + } else { + return void 0; + } + } + }); + + var res = JSON.stringify(P); + print(res); +} + +try { + test(); +} catch (e) { + print(e.stack || e); +} + +print('done'); diff --git a/tests/perf/test-cbor-decode-1.js b/tests/perf/test-cbor-decode-1.js new file mode 100644 index 00000000..a7561c4f --- /dev/null +++ b/tests/perf/test-cbor-decode-1.js @@ -0,0 +1,37 @@ +if (typeof print !== 'function') { print = console.log; } + +function test() { + // Encoded data from test-cbor-encode-1.js. + var u8 = new Uint8Array([ + 0xa3, 0x67, 0x6a, 0x73, 0x6f, 0x6e, 0x72, 0x70, + 0x63, 0x63, 0x32, 0x2e, 0x30, 0x66, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x66, 0x46, 0x6f, 0x6f, + 0x42, 0x61, 0x72, 0x66, 0x70, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0xa3, 0x63, 0x66, 0x6f, 0x6f, 0x18, + 0x7b, 0x63, 0x62, 0x61, 0x72, 0x83, 0xf5, 0xf4, + 0xfb, 0x40, 0x5e, 0xdd, 0x2f, 0x1a, 0x9f, 0xbe, + 0x77, 0x64, 0x71, 0x75, 0x75, 0x78, 0xa2, 0x63, + 0x62, 0x61, 0x7a, 0xf5, 0x65, 0x71, 0x75, 0x75, + 0x75, 0x78, 0xf4 ]); + var buf = u8.buffer; + + for (var i = 0; i < 1e5; i++) { + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + } +} + +try { + test(); +} catch (e) { + print(e.stack || e); + throw e; +} diff --git a/tests/perf/test-cbor-decode-2.js b/tests/perf/test-cbor-decode-2.js new file mode 100644 index 00000000..3cf36dc6 --- /dev/null +++ b/tests/perf/test-cbor-decode-2.js @@ -0,0 +1,69 @@ +if (typeof print !== 'function') { print = console.log; } + +function test() { + // Encoded data from test-cbor-encode-2.js. + var u8 = new Uint8Array([ + 0xa3, 0x67, 0x6a, 0x73, 0x6f, 0x6e, 0x72, 0x70, + 0x63, 0x63, 0x32, 0x2e, 0x30, 0x66, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x66, 0x46, 0x6f, 0x6f, + 0x42, 0x61, 0x72, 0x66, 0x70, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0xab, 0x64, 0x61, 0x72, 0x67, 0x31, + 0x6a, 0x78, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, + 0x79, 0x79, 0x79, 0x64, 0x61, 0x72, 0x67, 0x32, + 0x74, 0x78, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, + 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x64, 0x61, 0x72, + 0x67, 0x33, 0x6a, 0x78, 0x78, 0x78, 0x78, 0x78, + 0x79, 0x79, 0x79, 0x79, 0x79, 0x64, 0x61, 0x72, + 0x67, 0x34, 0x74, 0x78, 0x78, 0x78, 0x78, 0x78, + 0x79, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, + 0x7a, 0x7a, 0x77, 0x77, 0x77, 0x77, 0x77, 0x64, + 0x61, 0x72, 0x67, 0x35, 0x6a, 0x78, 0x78, 0x78, + 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x64, + 0x61, 0x72, 0x67, 0x36, 0x74, 0x78, 0x78, 0x78, + 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7a, + 0x7a, 0x7a, 0x7a, 0x7a, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x64, 0x61, 0x72, 0x67, 0x37, 0x6a, 0x78, + 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, + 0x79, 0x64, 0x61, 0x72, 0x67, 0x38, 0x74, 0x78, + 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, + 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x64, 0x61, 0x72, 0x67, 0x39, + 0x6a, 0x78, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, + 0x79, 0x79, 0x79, 0x65, 0x61, 0x72, 0x67, 0x31, + 0x30, 0x74, 0x78, 0x78, 0x78, 0x78, 0x78, 0x79, + 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, + 0x7a, 0x77, 0x77, 0x77, 0x77, 0x77, 0x65, 0x61, + 0x72, 0x67, 0x31, 0x31, 0x8b, 0x01, 0xfb, 0x3f, + 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xfb, + 0x3f, 0xf3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + 0xfb, 0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcd, 0xfb, 0x3f, 0xf6, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0xf9, 0x3e, 0x00, 0xfb, 0x3f, 0xf9, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xfb, 0x3f, + 0xfb, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xfb, + 0x3f, 0xfc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, + 0xfb, 0x3f, 0xfe, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x02 ]); + var buf = u8.buffer; + + for (var i = 0; i < 1e5; i++) { + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + void CBOR.decode(buf); + } +} + +try { + test(); +} catch (e) { + print(e.stack || e); + throw e; +} diff --git a/tests/perf/test-cbor-decode-largeobj.js b/tests/perf/test-cbor-decode-largeobj.js new file mode 100644 index 00000000..cbe621d5 --- /dev/null +++ b/tests/perf/test-cbor-decode-largeobj.js @@ -0,0 +1,38 @@ +if (typeof print !== 'function') { print = console.log; } + +function build() { + var obj = {}; + + for (var i = 0; i < 3000; i++) { + var k = 'key' + i; + var v; + switch (i % 4) { + case 0: v = true; break; + case 1: v = 123.4; break; + case 2: v = { foo: 1, bar: 2, quux: 3, baz: 4, quuux: 5 }; break; + case 3: v = [ 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.12345 ]; break; + } + obj[k] = v; + } + return obj; +} + +function test() { + var obj; + var buf; + var i; + + obj = build(); + buf = CBOR.encode(obj); + + for (i = 0; i < 1e3; i++) { + void CBOR.decode(buf); + } +} + +try { + test(); +} catch (e) { + print(e.stack || e); + throw e; +} diff --git a/tests/perf/test-cbor-encode-1.js b/tests/perf/test-cbor-encode-1.js index c19d2ede..60f9c2db 100644 --- a/tests/perf/test-cbor-encode-1.js +++ b/tests/perf/test-cbor-encode-1.js @@ -14,6 +14,9 @@ function test() { } }; + // print(Duktape.enc('hex', CBOR.encode(msg))); + // a3676a736f6e72706363322e30666d6574686f6466466f6f42617266706172616d73a363666f6f187b6362617283f5f4fb405edd2f1a9fbe776471757578a26362617af5657175757578f4 + for (var i = 0; i < 1e5; i++) { void CBOR.encode(msg); void CBOR.encode(msg); diff --git a/tests/perf/test-cbor-encode-2.js b/tests/perf/test-cbor-encode-2.js index 7a91573a..be748132 100644 --- a/tests/perf/test-cbor-encode-2.js +++ b/tests/perf/test-cbor-encode-2.js @@ -19,6 +19,10 @@ function test() { } }; + // print(Duktape.enc('hex', CBOR.encode(msg))); + // a3676a736f6e72706363322e30666d6574686f6466466f6f42617266706172616d73ab64617267316a78787878787979797979646172673274787878787879797979797a7a7a7a7a777777777764617267336a78787878787979797979646172673474787878787879797979797a7a7a7a7a777777777764617267356a78787878787979797979646172673674787878787879797979797a7a7a7a7a777777777764617267376a78787878787979797979646172673874787878787879797979797a7a7a7a7a777777777764617267396a7878787878797979797965617267313074787878787879797979797a7a7a7a7a77777777776561726731318b01fb3ff199999999999afb3ff3333333333333fb3ff4cccccccccccdfb3ff6666666666666f93e00fb3ff999999999999afb3ffb333333333333fb3ffccccccccccccdfb3ffe66666666666602 + + for (var i = 0; i < 1e5; i++) { void CBOR.encode(msg); void CBOR.encode(msg); diff --git a/tests/perf/test-cbor-encode-largeobj.js b/tests/perf/test-cbor-encode-largeobj.js index 4ed38679..0a90a892 100644 --- a/tests/perf/test-cbor-encode-largeobj.js +++ b/tests/perf/test-cbor-encode-largeobj.js @@ -20,11 +20,10 @@ function build() { function test() { var obj; var i; - var ignore; obj = build(); for (i = 0; i < 1e3; i++) { - ignore = CBOR.encode(obj); + void CBOR.encode(obj); } } diff --git a/tests/perf/test-cbor-serialize.js b/tests/perf/test-cbor-encode-simple.js similarity index 100% rename from tests/perf/test-cbor-serialize.js rename to tests/perf/test-cbor-encode-simple.js diff --git a/tests/perf/test-json-serialize-largeobj.js b/tests/perf/test-json-serialize-largeobj.js new file mode 100644 index 00000000..29fa6de6 --- /dev/null +++ b/tests/perf/test-json-serialize-largeobj.js @@ -0,0 +1,36 @@ +if (typeof print !== 'function') { print = console.log; } + +function build() { + var obj = {}; + + for (var i = 0; i < 3000; i++) { + var k = 'key' + i; + var v; + switch (i % 4) { + case 0: v = true; break; + case 1: v = 123.4; break; + case 2: v = { foo: 1, bar: 2, quux: 3, baz: 4, quuux: 5 }; break; + case 3: v = [ 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.12345 ]; break; + } + obj[k] = v; + } + return obj; +} + +function test() { + var obj; + var i; + var ignore; + + obj = build(); + for (i = 0; i < 1e3; i++) { + ignore = JSON.stringify(obj); + } +} + +try { + test(); +} catch (e) { + print(e.stack || e); + throw e; +} diff --git a/tests/perf/test-json-serialize.js b/tests/perf/test-json-serialize-simple.js similarity index 100% rename from tests/perf/test-json-serialize.js rename to tests/perf/test-json-serialize-simple.js