Add comprehensive installation and setup documentation

- Add GETTING_STARTED.md with quick start guide and development modes
- Add INSTALL.sh automated installation script
- Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md
- Add QUICK_REFERENCE.md for common commands
- Add SETUP_GUIDE.md with detailed setup instructions
- Update README.md with improved project overview
- Add did-wallet app dependencies and node_modules
This commit is contained in:
Dorian
2026-01-27 17:18:21 +00:00
parent a81f655133
commit 0d073fa89e
22658 changed files with 4494151 additions and 6 deletions
+643
View File
@@ -0,0 +1,643 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const fixtures = [
{
cbor: 'AA==',
hex: '00',
roundtrip: true,
decoded: 0
},
{
cbor: 'AQ==',
hex: '01',
roundtrip: true,
decoded: 1
},
{
cbor: 'Cg==',
hex: '0a',
roundtrip: true,
decoded: 10
},
{
cbor: 'Fw==',
hex: '17',
roundtrip: true,
decoded: 23
},
{
cbor: 'GBg=',
hex: '1818',
roundtrip: true,
decoded: 24
},
{
cbor: 'GBk=',
hex: '1819',
roundtrip: true,
decoded: 25
},
{
cbor: 'GGQ=',
hex: '1864',
roundtrip: true,
decoded: 100
},
{
cbor: 'GQPo',
hex: '1903e8',
roundtrip: true,
decoded: 1000
},
{
cbor: 'GgAPQkA=',
hex: '1a000f4240',
roundtrip: true,
decoded: 1000000
},
{
cbor: 'GwAAAOjUpRAA',
hex: '1b000000e8d4a51000',
roundtrip: true,
decoded: 1000000000000
},
{
cbor: 'G///////////',
hex: '1bffffffffffffffff',
roundtrip: true,
decoded: BigInt('18446744073709551615')
},
{
cbor: 'wkkBAAAAAAAAAAA=',
hex: 'c249010000000000000000',
roundtrip: true,
decoded: BigInt('18446744073709551616'),
noTagDecodeError: /tag not supported \(2\)/,
noTagEncodeError: /BigInt larger than allowable range/
},
{
cbor: 'O///////////',
hex: '3bffffffffffffffff',
roundtrip: true,
decoded: BigInt('-18446744073709551616')
},
{
cbor: 'w0kBAAAAAAAAAAA=',
hex: 'c349010000000000000000',
roundtrip: true,
decoded: BigInt('-18446744073709551617'),
noTagDecodeError: /tag not supported \(3\)/,
noTagEncodeError: /BigInt larger than allowable range/
},
{
cbor: 'IA==',
hex: '20',
roundtrip: true,
decoded: -1
},
{
cbor: 'KQ==',
hex: '29',
roundtrip: true,
decoded: -10
},
{
cbor: 'OGM=',
hex: '3863',
roundtrip: true,
decoded: -100
},
{
cbor: 'OQPn',
hex: '3903e7',
roundtrip: true,
decoded: -1000
},
{
cbor: '+QAA',
hex: 'f90000',
roundtrip: false,
decoded: 0
},
{
cbor: '+YAA',
hex: 'f98000',
roundtrip: false,
decoded: -0
},
{
cbor: '+TwA',
hex: 'f93c00',
roundtrip: false,
decoded: 1
},
{
cbor: '+z/xmZmZmZma',
hex: 'fb3ff199999999999a',
roundtrip: true,
decoded: 1.1
},
{
cbor: '+T4A',
hex: 'f93e00',
roundtrip: true,
decoded: 1.5
},
{
cbor: '+Xv/',
hex: 'f97bff',
roundtrip: false,
decoded: 65504
},
{
cbor: '+kfDUAA=',
hex: 'fa47c35000',
roundtrip: false,
decoded: 100000
},
{
cbor: '+n9///8=',
hex: 'fa7f7fffff',
roundtrip: true,
decoded: 3.4028234663852886e+38
},
{
cbor: '+3435DyIAHWc',
hex: 'fb7e37e43c8800759c',
roundtrip: true,
decoded: 1e+300
},
{
cbor: '+QAB',
hex: 'f90001',
roundtrip: true,
decoded: 5.960464477539063e-8
},
{
cbor: '+QQA',
hex: 'f90400',
roundtrip: true,
decoded: 0.00006103515625
},
{
cbor: '+cQA',
hex: 'f9c400',
roundtrip: false,
decoded: -4
},
{
cbor: '+8AQZmZmZmZm',
hex: 'fbc010666666666666',
roundtrip: true,
decoded: -4.1
},
{
cbor: '+XwA',
hex: 'f97c00',
roundtrip: true,
diagnostic: Infinity
},
{
cbor: '+X4A',
hex: 'f97e00',
roundtrip: true,
diagnostic: NaN
},
{
cbor: '+fwA',
hex: 'f9fc00',
roundtrip: true,
diagnostic: -Infinity
},
{
cbor: '+n+AAAA=',
hex: 'fa7f800000',
roundtrip: false,
diagnostic: Infinity
},
{
cbor: '+n/AAAA=',
hex: 'fa7fc00000',
roundtrip: false,
diagnostic: NaN
},
{
cbor: '+v+AAAA=',
hex: 'faff800000',
roundtrip: false,
diagnostic: -Infinity
},
{
cbor: '+3/wAAAAAAAA',
hex: 'fb7ff0000000000000',
roundtrip: false,
diagnostic: Infinity
},
{
cbor: '+3/4AAAAAAAA',
hex: 'fb7ff8000000000000',
roundtrip: false,
diagnostic: NaN
},
{
cbor: '+//wAAAAAAAA',
hex: 'fbfff0000000000000',
roundtrip: false,
diagnostic: -Infinity
},
{
cbor: '9A==',
hex: 'f4',
roundtrip: true,
decoded: false
},
{
cbor: '9Q==',
hex: 'f5',
roundtrip: true,
decoded: true
},
{
cbor: '9g==',
hex: 'f6',
roundtrip: true,
decoded: null
},
{
cbor: '9w==',
hex: 'f7',
roundtrip: true,
diagnostic: undefined
},
{
cbor: '8A==',
hex: 'f0',
roundtrip: true,
diagnostic: 'simple(16)',
error: /simple values are not supported/
},
{
cbor: '+Bg=',
hex: 'f818',
roundtrip: true,
diagnostic: 'simple(24)',
error: /simple values are not supported/
},
{
cbor: '+P8=',
hex: 'f8ff',
roundtrip: true,
diagnostic: 'simple(255)',
error: /simple values are not supported/
},
{
cbor: 'wHQyMDEzLTAzLTIxVDIwOjA0OjAwWg==',
hex: 'c074323031332d30332d32315432303a30343a30305a',
roundtrip: false,
diagnostic: '0("2013-03-21T20:04:00Z")'
},
{
cbor: 'wRpRS2ew',
hex: 'c11a514b67b0',
roundtrip: false,
diagnostic: '1(1363896240)'
},
{
cbor: 'wftB1FLZ7CAAAA==',
hex: 'c1fb41d452d9ec200000',
roundtrip: false,
diagnostic: '1(1363896240.5)'
},
{
cbor: '10QBAgME',
hex: 'd74401020304',
roundtrip: false,
diagnostic: '23(h\'01020304\')'
},
{
cbor: '2BhFZElFVEY=',
hex: 'd818456449455446',
roundtrip: false,
diagnostic: '24(h\'6449455446\')'
},
{
cbor: '2CB2aHR0cDovL3d3dy5leGFtcGxlLmNvbQ==',
hex: 'd82076687474703a2f2f7777772e6578616d706c652e636f6d',
roundtrip: false,
diagnostic: '32("http://www.example.com")'
},
{
cbor: 'QA==',
hex: '40',
roundtrip: true,
diagnostic: 'h\'\''
},
{
cbor: 'RAECAwQ=',
hex: '4401020304',
roundtrip: true,
diagnostic: 'h\'01020304\''
},
{
cbor: 'YA==',
hex: '60',
roundtrip: true,
decoded: ''
},
{
cbor: 'YWE=',
hex: '6161',
roundtrip: true,
decoded: 'a'
},
{
cbor: 'ZElFVEY=',
hex: '6449455446',
roundtrip: true,
decoded: 'IETF'
},
{
cbor: 'YiJc',
hex: '62225c',
roundtrip: true,
decoded: '"\\'
},
{
cbor: 'YsO8',
hex: '62c3bc',
roundtrip: true,
decoded: 'ü'
},
{
cbor: 'Y+awtA==',
hex: '63e6b0b4',
roundtrip: true,
decoded: '水'
},
{
cbor: 'ZPCQhZE=',
hex: '64f0908591',
roundtrip: true,
decoded: '\uD800\uDD51'
},
{
cbor: 'gA==',
hex: '80',
roundtrip: true,
decoded: []
},
{
cbor: 'gwECAw==',
hex: '83010203',
roundtrip: true,
decoded: [
1,
2,
3
]
},
{
cbor: 'gwGCAgOCBAU=',
hex: '8301820203820405',
roundtrip: true,
decoded: [
1,
[
2,
3
],
[
4,
5
]
]
},
{
cbor: 'mBkBAgMEBQYHCAkKCwwNDg8QERITFBUWFxgYGBk=',
hex: '98190102030405060708090a0b0c0d0e0f101112131415161718181819',
roundtrip: true,
decoded: [
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
]
},
{
cbor: 'oA==',
hex: 'a0',
roundtrip: true,
decoded: {}
},
{
cbor: 'ogECAwQ=',
hex: 'a201020304',
roundtrip: true,
diagnostic: '{1: 2, 3: 4}',
error: /non-string keys not supported/
},
{
cbor: 'omFhAWFiggID',
hex: 'a26161016162820203',
roundtrip: true,
decoded: {
a: 1,
b: [
2,
3
]
}
},
{
cbor: 'gmFhoWFiYWM=',
hex: '826161a161626163',
roundtrip: true,
decoded: [
'a',
{ b: 'c' }
]
},
{
cbor: 'pWFhYUFhYmFCYWNhQ2FkYURhZWFF',
hex: 'a56161614161626142616361436164614461656145',
roundtrip: true,
decoded: {
a: 'A',
b: 'B',
c: 'C',
d: 'D',
e: 'E'
}
},
{
cbor: 'X0IBAkMDBAX/',
hex: '5f42010243030405ff',
roundtrip: false,
diagnostic: '(_ h\'0102\', h\'030405\')',
error: /indefinite length bytes\/strings are not supported/
},
{
cbor: 'f2VzdHJlYWRtaW5n/w==',
hex: '7f657374726561646d696e67ff',
roundtrip: false,
decoded: 'streaming',
error: /indefinite length bytes\/strings are not supported/
},
{
cbor: 'n/8=',
hex: '9fff',
roundtrip: false,
decoded: []
},
{
cbor: 'nwGCAgOfBAX//w==',
hex: '9f018202039f0405ffff',
roundtrip: false,
decoded: [
1,
[
2,
3
],
[
4,
5
]
]
},
{
cbor: 'nwGCAgOCBAX/',
hex: '9f01820203820405ff',
roundtrip: false,
decoded: [
1,
[
2,
3
],
[
4,
5
]
]
},
{
cbor: 'gwGCAgOfBAX/',
hex: '83018202039f0405ff',
roundtrip: false,
decoded: [
1,
[
2,
3
],
[
4,
5
]
]
},
{
cbor: 'gwGfAgP/ggQF',
hex: '83019f0203ff820405',
roundtrip: false,
decoded: [
1,
[
2,
3
],
[
4,
5
]
]
},
{
cbor: 'nwECAwQFBgcICQoLDA0ODxAREhMUFRYXGBgYGf8=',
hex: '9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff',
roundtrip: false,
decoded: [
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
]
},
{
cbor: 'v2FhAWFinwID//8=',
hex: 'bf61610161629f0203ffff',
roundtrip: false,
decoded: {
a: 1,
b: [
2,
3
]
}
},
{
cbor: 'gmFhv2FiYWP/',
hex: '826161bf61626163ff',
roundtrip: false,
decoded: [
'a',
{ b: 'c' }
]
},
{
cbor: 'v2NGdW71Y0FtdCH/',
hex: 'bf6346756ef563416d7421ff',
roundtrip: false,
decoded: {
Fun: true,
Amt: -2
}
}
];
exports.fixtures = fixtures;
+24
View File
@@ -0,0 +1,24 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var token = require('../lib/token.js');
function dateDecoder(obj) {
if (typeof obj !== 'string') {
throw new Error('expected string for tag 1');
}
return new Date(obj);
}
function dateEncoder(obj) {
if (!(obj instanceof Date)) {
throw new Error('expected Date for "Date" encoder');
}
return [
new token.Token(token.Type.tag, 0),
new token.Token(token.Type.string, obj.toISOString().replace(/\.000Z$/, 'Z'))
];
}
exports.dateDecoder = dateDecoder;
exports.dateEncoder = dateEncoder;
+348
View File
@@ -0,0 +1,348 @@
'use strict';
var chai = require('chai');
var child_process = require('child_process');
var process = require('process');
var path = require('path');
var os = require('os');
var url = require('url');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
var process__default = /*#__PURE__*/_interopDefaultLegacy(process);
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
const {assert} = chai__default["default"];
const fixture1JsonString = '{"a":1,"b":[2,3],"smile":"\uD83D\uDE00"}';
const fixture1JsonPrettyString = `{
"a": 1,
"b": [
2,
3
],
"smile": "😀"
}
`;
const fixture1HexString = 'a3616101616282020365736d696c6564f09f9880';
const fixture1Bin = fromHex(fixture1HexString);
const fixture1BinString = new TextDecoder().decode(fixture1Bin);
const fixture1DiagnosticString = `a3 # map(3)
61 # string(1)
61 # "a"
01 # uint(1)
61 # string(1)
62 # "b"
82 # array(2)
02 # uint(2)
03 # uint(3)
65 # string(5)
736d696c65 # "smile"
64 # string(2)
f09f9880 # "😀"
`;
const fixture2HexString = 'a4616101616282020363627566440102036165736d696c6564f09f9880';
const fixture2DiagnosticString = `a4 # map(4)
61 # string(1)
61 # "a"
01 # uint(1)
61 # string(1)
62 # "b"
82 # array(2)
02 # uint(2)
03 # uint(3)
63 # string(3)
627566 # "buf"
44 # bytes(4)
01020361 # "\\x01\\x02\\x03a"
65 # string(5)
736d696c65 # "smile"
64 # string(2)
f09f9880 # "😀"
`;
const binPath = path__default["default"].join(path__default["default"].dirname(url.fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('node-test/node-test-bin.js', document.baseURI).href)))), '../lib/bin.js');
function fromHex(hex) {
return new Uint8Array(hex.split('').map((c, i, d) => i % 2 === 0 ? `0x${ c }${ d[i + 1] }` : '').filter(Boolean).map(e => parseInt(e, 16)));
}
async function execBin(cmd, stdin) {
return new Promise((resolve, reject) => {
const cp = child_process.exec(`"${ process__default["default"].execPath }" "${ binPath }" ${ cmd }`, (err, stdout, stderr) => {
if (err) {
err.stdout = stdout;
err.stderr = stderr;
return reject(err);
}
resolve({
stdout,
stderr
});
});
if (stdin != null) {
cp.on('spawn', () => {
cp.stdin.write(stdin);
cp.stdin.end();
});
}
});
}
describe('Bin', () => {
it('usage', async () => {
try {
await execBin('');
assert.fail('should have errored');
} catch (e) {
assert.strictEqual(e.stdout, '');
assert.strictEqual(e.stderr, `Usage: cborg <command> <args>
Valid commands:
\tbin2diag [binary input]
\tbin2hex [binary input]
\tbin2json [--pretty] [binary input]
\tdiag2bin [diagnostic input]
\tdiag2hex [diagnostic input]
\tdiag2json [--pretty] [diagnostic input]
\thex2bin [hex input]
\thex2diag [hex input]
\thex2json [--pretty] [hex input]
\tjson2bin '[json input]'
\tjson2diag '[json input]'
\tjson2hex '[json input]'
Input may either be supplied as an argument or piped via stdin
`);
}
});
it('bad cmd', async () => {
try {
await execBin('blip');
assert.fail('should have errored');
} catch (e) {
assert.strictEqual(e.stdout, '');
assert.strictEqual(e.stderr, `Unknown command: 'blip'
Usage: cborg <command> <args>
Valid commands:
\tbin2diag [binary input]
\tbin2hex [binary input]
\tbin2json [--pretty] [binary input]
\tdiag2bin [diagnostic input]
\tdiag2hex [diagnostic input]
\tdiag2json [--pretty] [diagnostic input]
\thex2bin [hex input]
\thex2diag [hex input]
\thex2json [--pretty] [hex input]
\tjson2bin '[json input]'
\tjson2diag '[json input]'
\tjson2hex '[json input]'
Input may either be supplied as an argument or piped via stdin
`);
}
});
it('help', async () => {
const {stdout, stderr} = await execBin('help');
assert.strictEqual(stdout, '');
assert.strictEqual(stderr, `Usage: cborg <command> <args>
Valid commands:
\tbin2diag [binary input]
\tbin2hex [binary input]
\tbin2json [--pretty] [binary input]
\tdiag2bin [diagnostic input]
\tdiag2hex [diagnostic input]
\tdiag2json [--pretty] [diagnostic input]
\thex2bin [hex input]
\thex2diag [hex input]
\thex2json [--pretty] [hex input]
\tjson2bin '[json input]'
\tjson2diag '[json input]'
\tjson2hex '[json input]'
Input may either be supplied as an argument or piped via stdin
`);
});
it('bin2diag (stdin)', async () => {
const {stdout, stderr} = await execBin('bin2diag', fixture1Bin);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture1DiagnosticString);
});
it('bin2hex (stdin)', async () => {
const {stdout, stderr} = await execBin('bin2hex', fixture1Bin);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `${ fixture1HexString }\n`);
});
it('bin2json (stdin)', async () => {
const {stdout, stderr} = await execBin('bin2json', fixture1Bin);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `${ fixture1JsonString }\n`);
});
it('bin2json pretty (stdin)', async () => {
const {stdout, stderr} = await execBin('bin2json --pretty', fixture1Bin);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture1JsonPrettyString);
});
for (const stdin of [
true,
false
]) {
if (os.platform() !== 'win32' || stdin) {
it(`diag2bin${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`diag2bin '${ fixture1DiagnosticString }'`) : await execBin('diag2bin', fixture1DiagnosticString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture1BinString);
});
it(`diag2hex${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`diag2hex '${ fixture1DiagnosticString }'`) : await execBin('diag2hex', fixture1DiagnosticString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `${ fixture1HexString }\n`);
});
it(`diag2json${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`diag2json '${ fixture1DiagnosticString }'`) : await execBin('diag2json', fixture1DiagnosticString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `${ fixture1JsonString }\n`);
});
it(`diag2json pretty${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`diag2json --pretty '${ fixture1DiagnosticString }'`) : await execBin('diag2json --pretty', fixture1DiagnosticString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture1JsonPrettyString);
});
}
it(`hex2bin${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`hex2bin ${ fixture1HexString }`) : await execBin('hex2bin', fixture1HexString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture1BinString);
});
it(`hex2diag${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`hex2diag ${ fixture2HexString }`) : await execBin('hex2diag', fixture2HexString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture2DiagnosticString);
});
it(`hex2json${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`hex2json ${ fixture1HexString }`) : await execBin('hex2json', fixture1HexString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `${ fixture1JsonString }\n`);
});
it(`hex2json pretty${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`hex2json --pretty ${ fixture1HexString }`) : await execBin('hex2json --pretty', fixture1HexString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture1JsonPrettyString);
});
it(`json2bin${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin('json2bin "{\\"a\\":1,\\"b\\":[2,3],\\"smile\\":\\"\uD83D\uDE00\\"}"') : await execBin('json2bin', fixture1JsonString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture1BinString);
});
it(`json2diag${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin('json2diag "{\\"a\\":1,\\"b\\":[2,3],\\"smile\\":\\"\uD83D\uDE00\\"}"') : await execBin('json2diag', fixture1JsonString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, fixture1DiagnosticString);
});
it(`json2hex${ stdin ? ' (stdin)' : '' }`, async () => {
const {stdout, stderr} = !stdin ? await execBin(`json2hex "${ fixture1JsonString.replace(/"/g, '\\"') }"`) : await execBin('json2hex', fixture1JsonString);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `${ fixture1HexString }\n`);
});
}
it('diag indenting', async () => {
const {stdout, stderr} = await execBin('json2diag', '{"a":[],"b":{},"c":{"a":1,"b":{"a":{"a":{}}}},"d":{"a":{"a":{"a":1},"b":2,"c":[]}},"e":[[[[{"a":{}}]]]],"f":1}');
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `a6 # map(6)
61 # string(1)
61 # "a"
80 # array(0)
61 # string(1)
62 # "b"
a0 # map(0)
61 # string(1)
63 # "c"
a2 # map(2)
61 # string(1)
61 # "a"
01 # uint(1)
61 # string(1)
62 # "b"
a1 # map(1)
61 # string(1)
61 # "a"
a1 # map(1)
61 # string(1)
61 # "a"
a0 # map(0)
61 # string(1)
64 # "d"
a1 # map(1)
61 # string(1)
61 # "a"
a3 # map(3)
61 # string(1)
61 # "a"
a1 # map(1)
61 # string(1)
61 # "a"
01 # uint(1)
61 # string(1)
62 # "b"
02 # uint(2)
61 # string(1)
63 # "c"
80 # array(0)
61 # string(1)
65 # "e"
81 # array(1)
81 # array(1)
81 # array(1)
81 # array(1)
a1 # map(1)
61 # string(1)
61 # "a"
a0 # map(0)
61 # string(1)
66 # "f"
01 # uint(1)
`);
});
describe('diag length bytes', () => {
it('compact', async () => {
const {stdout, stderr} = await execBin('json2diag', '"aaaaaaaaaaaaaaaaaaaaaaa"');
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `77 # string(23)
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
`);
});
it('1-byte', async () => {
const {stdout, stderr} = await execBin('json2diag', '"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"');
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `78 23 # string(35)
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
616161616161616161616161 # "aaaaaaaaaaaa"
`);
});
it('2-byte', async () => {
const {stdout, stderr} = await execBin('json2diag', '"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"');
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `79 0100 # string(256)
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
616161 # "aaa"
`);
});
});
it('diag non-utf8 and non-printable ascii', async () => {
const input = '7864f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c11e756338bd93865e645f1adec9b9c99ef407fbd4fc6859e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82f9f18c3d03418e35';
let {stdout, stderr} = await execBin(`hex2diag ${ input }`);
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `78 64 # string(86)
f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b # "õ_øñ%\\x08¶>ò¿ì§Uzé\\x0dö1\\x1a^Ác\\x1b"
4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c # "J\\x1f¨C1\\x0bÙç\\x10ê¬å¡½×*пàIw\\x1c"
11e756338bd93865e645f1adec9b9c99ef407fbd4fc685 # "\\x11çV3\\x8bÙ8eæEñ\\xadì\\x9b\\x9c\\x99ï@\\x7f½OÆ\\x85"
9e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82 # "\\x9ey\\x04Å\\xad}ɽ\\x10¥Ì\\x16\\x97=[(ì\\x1amÔ=\\x9f\\x82"
f9f18c3d03418e35 # "ùñ\\x8c=\\x03A\\x8e5"
`);
({stdout, stderr} = await execBin('diag2hex', stdout));
assert.strictEqual(stderr, '');
assert.strictEqual(stdout, `${ input }\n`);
});
});
+4
View File
@@ -0,0 +1,4 @@
'use strict';
require('../lib/bin.js');
+158
View File
@@ -0,0 +1,158 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var decode = require('../lib/decode.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
const fixtures = [
{
data: '00',
expected: 0,
type: 'uint8'
},
{
data: '02',
expected: 2,
type: 'uint8'
},
{
data: '18ff',
expected: 255,
type: 'uint8'
},
{
data: '1901f4',
expected: 500,
type: 'uint16'
},
{
data: '1900ff',
expected: 255,
type: 'uint16',
strict: false
},
{
data: '19ffff',
expected: 65535,
type: 'uint16'
},
{
data: '1a000000ff',
expected: 255,
type: 'uint32',
strict: false
},
{
data: '1a00010000',
expected: 65536,
type: 'uint32'
},
{
data: '1a000f4240',
expected: 1000000,
type: 'uint32'
},
{
data: '1aa5f702b3',
expected: 2784428723,
type: 'uint32'
},
{
data: '1b00000000000000ff',
expected: 255,
type: 'uint64',
strict: false
},
{
data: '1b0016db6db6db6db7',
expected: Number.MAX_SAFE_INTEGER / 1.4,
type: 'uint64'
},
{
data: '1b001fffffffffffff',
expected: Number.MAX_SAFE_INTEGER,
type: 'uint64'
},
{
data: '1ba5f702b3a5f702b3',
expected: BigInt('11959030306112471731'),
type: 'uint64'
},
{
data: '1bffffffffffffffff',
expected: BigInt('18446744073709551615'),
type: 'uint64'
}
];
describe('uint', () => {
describe('decode', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
it(`should decode ${ fixture.type }=${ fixture.expected }`, () => {
assert.ok(decode.decode(data) === fixture.expected, `decode ${ fixture.type } ${ decode.decode(data) } != ${ fixture.expected }`);
if (fixture.strict === false) {
assert.throws(() => decode.decode(data, { strict: true }), Error, 'CBOR decode error: integer encoded in more bytes than necessary (strict decode)');
} else {
assert.ok(decode.decode(data, { strict: true }) === fixture.expected, `decode ${ fixture.type }`);
}
});
}
});
it('should throw error', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('1ca5f702b3a5f702b3')), Error, 'CBOR decode error: encountered invalid minor (28) for major 0');
assert.throws(() => decode.decode(byteUtils.fromHex('1ba5f702b3a5f702')), Error, 'CBOR decode error: not enough data for type');
});
describe('encode', () => {
for (const fixture of fixtures) {
it(`should encode ${ fixture.type }=${ fixture.expected }`, () => {
if (fixture.strict === false) {
assert.notStrictEqual(byteUtils.toHex(encode.encode(fixture.expected)), fixture.data, `encode ${ fixture.type } !strict`);
} else {
assert.strictEqual(byteUtils.toHex(encode.encode(fixture.expected)), fixture.data, `encode ${ fixture.type }`);
}
});
}
});
describe('roundtrip', () => {
for (const fixture of fixtures) {
if (fixture.strict !== false) {
it(`should roundtrip ${ fixture.type }=${ fixture.expected }`, () => {
assert.ok(decode.decode(encode.encode(fixture.expected)) === fixture.expected, `roundtrip ${ fixture.type }`);
});
}
}
});
describe('toobig', () => {
it('bigger than 64-bit', () => {
assert.doesNotThrow(() => encode.encode(BigInt('18446744073709551615')));
assert.throws(() => encode.encode(BigInt('18446744073709551616')), /BigInt larger than allowable range/);
});
it('disallow BigInt', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
if (!Number.isSafeInteger(fixture.expected)) {
assert.throws(() => decode.decode(data, { allowBigInt: false }), /safe integer range/);
} else {
assert.ok(decode.decode(data, { allowBigInt: false }) === fixture.expected, `decode ${ fixture.type }`);
}
}
});
});
describe('toosmall', () => {
for (const fixture of fixtures) {
if (fixture.strict !== false && typeof fixture.expected === 'number') {
const small = BigInt(fixture.expected);
it(`should encode ${ small }n`, () => {
assert.strictEqual(byteUtils.toHex(encode.encode(BigInt(small))), fixture.data, `encode ${ small }`);
});
}
}
});
});
+152
View File
@@ -0,0 +1,152 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var decode = require('../lib/decode.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
const fixtures = [
{
data: '20',
expected: -1,
type: 'negint8'
},
{
data: '22',
expected: -3,
type: 'negint8'
},
{
data: '3863',
expected: -100,
type: 'negint8'
},
{
data: '38ff',
expected: -256,
type: 'negint8'
},
{
data: '3900ff',
expected: -256,
type: 'negint16',
strict: false
},
{
data: '3901f4',
expected: -501,
type: 'negint16'
},
{
data: '3a000000ff',
expected: -256,
type: 'negint32',
strict: false
},
{
data: '3aa5f702b3',
expected: -2784428724,
type: 'negint32'
},
{
data: '3b00000000000000ff',
expected: -256,
type: 'negint32',
strict: false
},
{
data: '3b0016db6db6db6db7',
expected: Number.MIN_SAFE_INTEGER / 1.4 - 1,
type: 'negint64'
},
{
data: '3b001ffffffffffffe',
expected: Number.MIN_SAFE_INTEGER,
type: 'negint64'
},
{
data: '3b001fffffffffffff',
expected: BigInt('-9007199254740992'),
type: 'negint64'
},
{
data: '3b0020000000000000',
expected: BigInt('-9007199254740993'),
type: 'negint64'
},
{
data: '3ba5f702b3a5f702b3',
expected: BigInt('-11959030306112471732'),
type: 'negint64'
},
{
data: '3bffffffffffffffff',
expected: BigInt('-18446744073709551616'),
type: 'negint64'
}
];
describe('negint', () => {
describe('decode', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
it(`should decode ${ fixture.type }=${ fixture.expected }`, () => {
assert.ok(decode.decode(data) === fixture.expected, `decode ${ fixture.type } (${ decode.decode(data) } != ${ fixture.expected })`);
if (fixture.strict === false) {
assert.throws(() => decode.decode(data, { strict: true }), Error, 'CBOR decode error: integer encoded in more bytes than necessary (strict decode)');
} else {
assert.strictEqual(decode.decode(data, { strict: true }), fixture.expected, `decode ${ fixture.type }`);
}
});
}
});
describe('encode', () => {
for (const fixture of fixtures) {
it(`should encode ${ fixture.type }=${ fixture.expected }`, () => {
if (fixture.strict === false) {
assert.notStrictEqual(byteUtils.toHex(encode.encode(fixture.expected)), fixture.data, `encode ${ fixture.type } !strict`);
} else {
assert.strictEqual(byteUtils.toHex(encode.encode(fixture.expected)), fixture.data, `encode ${ fixture.type }`);
}
});
}
});
describe('roundtrip', () => {
for (const fixture of fixtures) {
it(`should roundtrip ${ fixture.type }=${ fixture.expected }`, () => {
assert.ok(decode.decode(encode.encode(fixture.expected)) === fixture.expected, `roundtrip ${ fixture.type }`);
});
}
});
describe('toobig', () => {
it('bigger than 64-bit', () => {
assert.doesNotThrow(() => encode.encode(BigInt('-18446744073709551616')));
assert.throws(() => encode.encode(BigInt('-18446744073709551617')), /BigInt larger than allowable range/);
});
it('disallow BigInt', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
if (!Number.isSafeInteger(fixture.expected)) {
assert.throws(() => decode.decode(data, { allowBigInt: false }), /safe integer range/);
} else {
assert.ok(decode.decode(data, { allowBigInt: false }) === fixture.expected, `decode ${ fixture.type }`);
}
}
});
});
describe('toosmall', () => {
for (const fixture of fixtures) {
if (fixture.strict !== false && typeof fixture.expected === 'number') {
const small = BigInt(fixture.expected);
it(`should encode ${ small }n`, () => {
assert.strictEqual(byteUtils.toHex(encode.encode(BigInt(small))), fixture.data, `encode ${ small }`);
});
}
}
});
});
+254
View File
@@ -0,0 +1,254 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var decode = require('../lib/decode.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
const fixtures = [
{
data: '40',
expected: '',
type: 'bytes'
},
{
data: '41a1',
expected: 'a1',
type: 'bytes'
},
{
data: '5801a1',
expected: 'a1',
type: 'bytes',
strict: false
},
{
data: '58ff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe',
expected: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe',
type: 'bytes',
label: 'long bytes, 8-bit length'
},
{
data: '5900ff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe',
expected: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe',
type: 'bytes',
label: 'long bytes, 16-bit length',
strict: false
},
{
data: '5a000000ff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe',
expected: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe',
type: 'bytes',
label: 'long bytes, 32-bit length',
strict: false
},
{
data: '5b00000000000000ff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe',
expected: '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe',
type: 'bytes',
label: 'long bytes, 64-bit length',
strict: false
}
];
(() => {
function rnd(length) {
return new Uint8Array(Array.from({ length }, () => Math.floor(Math.random() * 255)));
}
const expected16 = rnd(256);
fixtures.push({
data: new Uint8Array([
...byteUtils.fromHex('590100'),
...expected16
]),
expected: expected16,
type: 'bytes',
label: 'long bytes, 16-bit length strict-compat'
});
const expected32 = rnd(65536);
fixtures.push({
data: new Uint8Array([
...byteUtils.fromHex('5a00010000'),
...expected32
]),
expected: expected32,
type: 'bytes',
label: 'long bytes, 32-bit length strict-compat'
});
})();
describe('bytes', () => {
describe('decode', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
it(`should decode ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
let actual = decode.decode(data);
assert.strictEqual(byteUtils.toHex(actual), byteUtils.toHex(byteUtils.fromHex(fixture.expected)), `decode ${ fixture.type }`);
if (fixture.strict === false) {
assert.throws(() => decode.decode(data, { strict: true }), Error, 'CBOR decode error: integer encoded in more bytes than necessary (strict decode)');
} else {
actual = decode.decode(data, { strict: true });
assert.strictEqual(byteUtils.toHex(actual), byteUtils.toHex(byteUtils.fromHex(fixture.expected)), `decode ${ fixture.type } strict`);
}
});
it('should fail to decode very large length', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('5ba5f702b3a5f702b3000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe')), /CBOR decode error: 64-bit integer bytes lengths not supported/);
});
}
});
describe('encode', () => {
for (const fixture of fixtures) {
if (fixture.data.length >= 100000000) {
it.skip(`(TODO) skipping encode of very large bytes ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
});
continue;
}
const data = byteUtils.fromHex(fixture.expected);
const expectedHex = byteUtils.toHex(fixture.data);
it(`should encode ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
if (fixture.unsafe) {
assert.throws(() => encode.encode(data), Error, /^CBOR encode error: number too large to encode \(-\d+\)$/);
} else if (fixture.strict === false) {
assert.notStrictEqual(byteUtils.toHex(encode.encode(data)), expectedHex, `encode ${ fixture.type } !strict`);
} else {
assert.strictEqual(byteUtils.toHex(encode.encode(data)), expectedHex, `encode ${ fixture.type }`);
}
});
}
});
describe('typedarrays', () => {
const cases = [
{
obj: Uint8Array.from([
1,
2,
3
]),
hex: '43010203'
},
{
obj: Uint8ClampedArray.from([
1,
2,
3
]),
hex: '43010203'
},
{
obj: Uint16Array.from([
1,
2,
3
]),
hex: '46010002000300'
},
{
obj: Uint32Array.from([
1,
2,
3
]),
hex: '4c010000000200000003000000'
},
{
obj: Int8Array.from([
1,
2,
-3
]),
hex: '430102fd'
},
{
obj: Int16Array.from([
1,
2,
-3
]),
hex: '4601000200fdff'
},
{
obj: Int32Array.from([
1,
2,
-3
]),
hex: '4c0100000002000000fdffffff'
},
{
obj: Float32Array.from([
1,
2,
-3
]),
hex: '4c0000803f00000040000040c0'
},
{
obj: Float64Array.from([
1,
2,
-3
]),
hex: '5818000000000000f03f000000000000004000000000000008c0'
},
{
obj: BigUint64Array.from([
BigInt(1),
BigInt(2),
BigInt(3)
]),
hex: '5818010000000000000002000000000000000300000000000000'
},
{
obj: BigInt64Array.from([
BigInt(1),
BigInt(2),
BigInt(-3)
]),
hex: '581801000000000000000200000000000000fdffffffffffffff'
},
{
obj: new DataView(Uint8Array.from([
1,
2,
3
]).buffer),
hex: '43010203'
},
{
obj: Uint8Array.from([
1,
2,
3
]).buffer,
hex: '43010203'
}
];
for (const testCase of cases) {
it(testCase.obj.constructor.name, () => {
assert.equal(byteUtils.toHex(encode.encode(testCase.obj)), testCase.hex);
const decoded = decode.decode(byteUtils.fromHex(testCase.hex));
assert.instanceOf(decoded, Uint8Array);
assert.equal(byteUtils.toHex(decoded), byteUtils.toHex(testCase.obj));
});
}
});
if (byteUtils.useBuffer) {
describe('buffer', () => {
it('can encode Node.js Buffers', () => {
const obj = global.Buffer.from([
1,
2,
3
]);
assert.equal(byteUtils.toHex(encode.encode(obj)), '43010203');
const decoded = decode.decode(byteUtils.fromHex('43010203'));
assert.instanceOf(decoded, Uint8Array);
assert.equal(byteUtils.toHex(decoded), byteUtils.toHex(obj));
});
});
}
});
+144
View File
@@ -0,0 +1,144 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var decode = require('../lib/decode.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
const fixtures = [
{
data: '60',
expected: '',
type: 'string'
},
{
data: '6161',
expected: 'a',
type: 'string'
},
{
data: '780161',
expected: 'a',
type: 'string',
strict: false
},
{
data: '6c48656c6c6f20776f726c6421',
expected: 'Hello world!',
type: 'string'
},
{
data: '6fc48c6175657320c39f76c49b746521',
expected: 'Čaues ßvěte!',
type: 'string'
},
{
data: '78964c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20446f6e6563206d692074656c6c75732c20696163756c6973206e656320766573746962756c756d20717569732c206665726d656e74756d206e6f6e2066656c69732e204d616563656e6173207574206a7573746f20706f73756572652e',
expected: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.',
type: 'string',
label: 'long string, 8-bit length'
},
{
data: '7900964c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20446f6e6563206d692074656c6c75732c20696163756c6973206e656320766573746962756c756d20717569732c206665726d656e74756d206e6f6e2066656c69732e204d616563656e6173207574206a7573746f20706f73756572652e',
expected: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.',
type: 'string',
label: 'long string, 16-bit length',
strict: false
},
{
data: '7a000000964c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20446f6e6563206d692074656c6c75732c20696163756c6973206e656320766573746962756c756d20717569732c206665726d656e74756d206e6f6e2066656c69732e204d616563656e6173207574206a7573746f20706f73756572652e',
expected: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.',
type: 'string',
label: 'long string, 32-bit length',
strict: false
},
{
data: '7b00000000000000964c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20446f6e6563206d692074656c6c75732c20696163756c6973206e656320766573746962756c756d20717569732c206665726d656e74756d206e6f6e2066656c69732e204d616563656e6173207574206a7573746f20706f73756572652e',
expected: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec mi tellus, iaculis nec vestibulum quis, fermentum non felis. Maecenas ut justo posuere.',
type: 'string',
label: 'long string, 64-bit length',
strict: false
}
];
(() => {
function rnd(length) {
const sa = [];
let l = 0;
while (l < length) {
const ascii = length - l < 3;
const base = ascii ? 32 : 126976;
const max = ascii ? 126 : 130816;
const cc = Math.floor(Math.random() * (max - base)) + base;
const s = String.fromCharCode(cc);
l += new TextEncoder().encode(s).length;
sa.push(s);
}
return sa.join('');
}
const expected16 = rnd(256);
fixtures.push({
data: new Uint8Array([
...byteUtils.fromHex('790100'),
...new TextEncoder().encode(expected16)
]),
expected: expected16,
type: 'string',
label: 'long string, 16-bit length strict-compat'
});
const expected32 = rnd(65536);
fixtures.push({
data: new Uint8Array([
...byteUtils.fromHex('7a00010000'),
...new TextEncoder().encode(expected32)
]),
expected: expected32,
type: 'string',
label: 'long string, 32-bit length strict-compat'
});
})();
describe('string', () => {
describe('decode', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
it(`should decode ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
let actual = decode.decode(data);
assert.strictEqual(actual, fixture.expected, `decode ${ fixture.type }`);
if (fixture.strict === false) {
assert.throws(() => decode.decode(data, { strict: true }), Error, 'CBOR decode error: integer encoded in more bytes than necessary (strict decode)');
} else {
actual = decode.decode(data, { strict: true });
assert.strictEqual(actual, fixture.expected, `decode ${ fixture.type } strict`);
}
});
it('should fail to decode very large length', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('7ba5f702b3a5f702b34c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20446f6e6563206d692074656c6c75732c20696163756c6973206e656320766573746962756c756d20717569732c206665726d656e74756d206e6f6e2066656c69732e204d616563656e6173207574206a7573746f20706f73756572652e')), /CBOR decode error: 64-bit integer string lengths not supported/);
});
}
});
describe('encode', () => {
for (const fixture of fixtures) {
if (fixture.data.length >= 100000000) {
it.skip(`(TODO) skipping encode of very large string ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
});
continue;
}
const data = fixture.expected;
const expectedHex = byteUtils.toHex(fixture.data);
it(`should encode ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
if (fixture.unsafe) {
assert.throws(() => encode.encode(data), Error, /^CBOR encode error: number too large to encode \(-\d+\)$/);
} else if (fixture.strict === false) {
assert.notStrictEqual(byteUtils.toHex(encode.encode(data)), expectedHex, `encode ${ fixture.type } !strict`);
} else {
assert.strictEqual(byteUtils.toHex(encode.encode(data)), expectedHex, `encode ${ fixture.type }`);
}
});
}
});
});
+200
View File
@@ -0,0 +1,200 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var decode = require('../lib/decode.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
const fixtures = [
{
data: '80',
expected: [],
type: 'array empty'
},
{
data: '8102',
expected: [2],
type: 'array 1 compact uint'
},
{
data: '8118ff',
expected: [255],
type: 'array 1 uint8'
},
{
data: '811901f4',
expected: [500],
type: 'array 1 uint16'
},
{
data: '811a00010000',
expected: [65536],
type: 'array 1 uint32'
},
{
data: '811b00000000000000ff',
expected: [255],
type: 'array 1 uint64',
strict: false
},
{
data: '811b0016db6db6db6db7',
expected: [Number.MAX_SAFE_INTEGER / 1.4],
type: 'array 1 uint64'
},
{
data: '811b001fffffffffffff',
expected: [Number.MAX_SAFE_INTEGER],
type: 'array 1 uint64'
},
{
data: '8403040506',
expected: [
3,
4,
5,
6
],
type: 'array 4 ints'
},
{
data: '8c1b0016db6db6db6db71a000100001901f40200202238ff3aa5f702b33b0016db6db6db6db74261316fc48c6175657320c39f76c49b746521',
expected: [
Number.MAX_SAFE_INTEGER / 1.4,
65536,
500,
2,
0,
-1,
-3,
-256,
-2784428724,
Number.MIN_SAFE_INTEGER / 1.4 - 1,
new TextEncoder().encode('a1'),
'Čaues ßvěte!'
],
type: 'array mixed terminals',
label: '[]'
},
{
data: '8265617272617982626f66820582666e657374656482666172726179736121',
expected: [
'array',
[
'of',
[
5,
[
'nested',
[
'arrays',
'!'
]
]
]
]
],
type: 'array nested'
},
{
data: '980403040506',
expected: [
3,
4,
5,
6
],
type: 'array 4 ints, length8',
strict: false
},
{
data: '99000403040506',
expected: [
3,
4,
5,
6
],
type: 'array 4 ints, length16',
strict: false
},
{
data: '9a0000000403040506',
expected: [
3,
4,
5,
6
],
type: 'array 4 ints, length32',
strict: false
},
{
data: '9b000000000000000403040506',
expected: [
3,
4,
5,
6
],
type: 'array 4 ints, length64',
strict: false
}
];
describe('array', () => {
describe('decode', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
it(`should decode ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
assert.deepStrictEqual(decode.decode(data), fixture.expected, `decode ${ fixture.type }`);
if (fixture.strict === false) {
assert.throws(() => decode.decode(data, { strict: true }), Error, 'CBOR decode error: integer encoded in more bytes than necessary (strict decode)');
} else {
assert.deepStrictEqual(decode.decode(data, { strict: true }), fixture.expected, `decode ${ fixture.type }`);
}
});
it('should fail to decode very large length', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('9ba5f702b3a5f7020403040506')), /CBOR decode error: 64-bit integer array lengths not supported/);
});
}
});
describe('encode', () => {
for (const fixture of fixtures) {
it(`should encode ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
if (fixture.unsafe) {
assert.throws(encode.encode.bind(null, fixture.expected), Error, /^CBOR encode error: number too large to encode \(\d+\)$/);
} else if (fixture.strict === false) {
assert.notDeepEqual(byteUtils.toHex(encode.encode(fixture.expected)), fixture.data, `encode ${ fixture.type } !strict`);
} else {
assert.strictEqual(byteUtils.toHex(encode.encode(fixture.expected)), fixture.data, `encode ${ fixture.type }`);
}
});
}
});
describe('roundtrip', () => {
for (const fixture of fixtures) {
if (!fixture.unsafe && fixture.strict !== false) {
it(`should roundtrip ${ fixture.type }=${ fixture.label || fixture.expected }`, () => {
assert.deepStrictEqual(decode.decode(encode.encode(fixture.expected)), fixture.expected, `roundtrip ${ fixture.type }`);
});
}
}
});
describe('specials', () => {
it('can decode indefinite length items', () => {
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('9f616f6174ff')), [
'o',
't'
]);
});
it('can switch off indefinite length support', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('9f616f6174ff'), { allowIndefinite: false }), /indefinite/);
});
});
});
+667
View File
@@ -0,0 +1,667 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var decode = require('../lib/decode.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
const fixtures = [
{
data: 'a0',
expected: {},
type: 'map empty'
},
{
data: 'a0',
expected: new Map(),
type: 'map empty (useMaps)',
useMaps: true
},
{
data: 'a1616101',
expected: { a: 1 },
type: 'map 1 pair'
},
{
data: 'a161316161',
expected: { 1: 'a' },
type: 'map 1 pair (rev)'
},
{
data: 'a1016161',
expected: toMap([[
1,
'a'
]]),
type: 'map 1 pair (int key as Map w/ useMaps)',
useMaps: true
},
{
data: 'a243010203633132334302030463323334',
expected: toMap([
[
Uint8Array.from([
1,
2,
3
]),
'123'
],
[
Uint8Array.from([
2,
3,
4
]),
'234'
]
]),
type: 'map 2 pair (bytes keys Map w/ useMaps)',
useMaps: true
},
{
data: 'a1666f626a656374a16477697468a26134666e6573746564676f626a65637473a161216121',
expected: {
object: {
with: {
4: 'nested',
objects: { '!': '!' }
}
}
},
type: 'map nested'
},
{
data: 'a1666f626a656374a16477697468a204666e6573746564676f626a65637473a161216121',
expected: toMap([[
'object',
toMap([[
'with',
toMap([
[
4,
'nested'
],
[
'objects',
toMap([[
'!',
'!'
]])
]
])
]])
]]),
type: 'map nested w/ useMaps',
useMaps: true
},
{
data: 'ae636f6e651b0016db6db6db6db763736978206374656e3b0016db6db6db6db76374776f1a0001000064666976650064666f757202646e696e653aa5f702b365656967687438ff65736576656e226574687265651901f466656c6576656e426131667477656c76656fc48c6175657320c39f76c49b74652168666f75727465656ea4616664666f7572616f016174026274680368746869727465656e840203046466697665',
encode: {
one: Number.MAX_SAFE_INTEGER / 1.4,
two: 65536,
three: 500,
four: 2,
five: 0,
six: -1,
seven: -3,
eight: -256,
nine: -2784428724,
ten: Number.MIN_SAFE_INTEGER / 1.4 - 1,
eleven: new TextEncoder().encode('a1'),
twelve: 'Čaues ßvěte!',
thirteen: [
2,
3,
4,
'five'
],
fourteen: {
o: 1,
t: 2,
th: 3,
f: 'four'
}
},
expected: {
one: Number.MAX_SAFE_INTEGER / 1.4,
six: -1,
ten: Number.MIN_SAFE_INTEGER / 1.4 - 1,
two: 65536,
five: 0,
four: 2,
nine: -2784428724,
eight: -256,
seven: -3,
three: 500,
eleven: new TextEncoder().encode('a1'),
twelve: 'Čaues ßvěte!',
fourteen: {
f: 'four',
o: 1,
t: 2,
th: 3
},
thirteen: [
2,
3,
4,
'five'
]
},
type: 'map with complex entries',
label: '{}'
},
{
data: 'ad01636f6e65026374776f1901f46c666976652068756e647265641902586b7369782068756e647265641a00010000636269671b0016db6db6db6db76662696767657220696d696e7573206f6e6521696d696e75732074776f38ff781f6d696e75732074776f2068756e6472656420616e64206669667479207369783901f4781a6d696e757820666976652068756e6472656420616e64206f6e653901f5781a6d696e757820666976652068756e6472656420616e642074776f3aa5f702b367626967206e65673b0016db6db6db6db76a626967676572206e6567',
encode: toMap([
[
2,
'two'
],
[
1,
'one'
],
[
-2,
'minus two'
],
[
-1,
'minus one'
],
[
600,
'six hundred'
],
[
500,
'five hundred'
],
[
-256,
'minus two hundred and fifty six'
],
[
-502,
'minux five hundred and two'
],
[
-501,
'minux five hundred and one'
],
[
65536,
'big'
],
[
-2784428724,
'big neg'
],
[
6433713753386423,
'bigger'
],
[
-6433713753386424,
'bigger neg'
]
]),
expected: toMap([
[
1,
'one'
],
[
2,
'two'
],
[
500,
'five hundred'
],
[
600,
'six hundred'
],
[
65536,
'big'
],
[
6433713753386423,
'bigger'
],
[
-1,
'minus one'
],
[
-2,
'minus two'
],
[
-256,
'minus two hundred and fifty six'
],
[
-501,
'minux five hundred and one'
],
[
-502,
'minux five hundred and two'
],
[
-2784428724,
'big neg'
],
[
-6433713753386424,
'bigger neg'
]
]),
type: 'map with ints and negints',
useMaps: true
},
{
data: 'a44104636f6e65430102026374776f430102036574687265654301020464666f7572',
encode: toMap([
[
Uint8Array.from([
1,
2,
3
]),
'three'
],
[
Uint8Array.from([4]),
'one'
],
[
Uint8Array.from([
1,
2,
4
]),
'four'
],
[
Uint8Array.from([
1,
2,
2
]),
'two'
]
]),
expected: toMap([
[
Uint8Array.from([4]),
'one'
],
[
Uint8Array.from([
1,
2,
2
]),
'two'
],
[
Uint8Array.from([
1,
2,
3
]),
'three'
],
[
Uint8Array.from([
1,
2,
4
]),
'four'
]
]),
type: 'map with bytes keys',
useMaps: true
},
{
data: 'b801616101',
expected: { a: 1 },
type: 'map 1 pair, length8',
strict: false
},
{
data: 'b90001616101',
expected: { a: 1 },
type: 'map 1 pair, length16',
strict: false
},
{
data: 'ba00000001616101',
expected: { a: 1 },
type: 'map 1 pair, length32',
strict: false
},
{
data: 'bb0000000000000001616101',
expected: { a: 1 },
type: 'map 1 pair, length64',
strict: false
}
];
function toMap(arr) {
const m = new Map();
for (const [key, value] of arr) {
m.set(key, value);
}
return m;
}
function entries(map) {
function nest(a) {
for (const e of a) {
e[0] = entries(e[0]);
e[1] = entries(e[1]);
}
return a;
}
if (Object.getPrototypeOf(map) === Map.prototype) {
return nest([...map.entries()]);
}
if (typeof map === 'object') {
return nest([...Object.entries(map)]);
}
return map;
}
describe('map', () => {
describe('decode', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
it(`should decode ${ fixture.type }=${ fixture.label || JSON.stringify(fixture.expected) }`, () => {
let options = fixture.useMaps ? { useMaps: true } : undefined;
const decoded = decode.decode(data, options);
if (fixture.useMaps) {
assert.strictEqual(Object.getPrototypeOf(decoded), Map.prototype, 'is Map');
} else {
assert.isObject(decoded, 'is object');
}
assert.deepStrictEqual(entries(decoded), entries(fixture.expected), `decode ${ fixture.type }`);
options = Object.assign({ strict: true }, options);
if (fixture.strict === false) {
assert.throws(() => decode.decode(data, options), Error, 'CBOR decode error: integer encoded in more bytes than necessary (strict decode)');
} else {
assert.deepStrictEqual(entries(decode.decode(data, options)), entries(fixture.expected), `decode ${ fixture.type }`);
}
});
it('should fail to decode very large length', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('bba5f702b3a5f70201616101')), /CBOR decode error: 64-bit integer map lengths not supported/);
});
}
it('errors', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('a1016161')), /non-string keys not supported \(got number\)/);
});
});
describe('encode', () => {
for (const fixture of fixtures) {
it(`should encode ${ fixture.type }=${ fixture.label || JSON.stringify(fixture.expected) }`, () => {
const toEncode = fixture.encode || fixture.expected;
if (fixture.unsafe) {
assert.throws(encode.encode.bind(null, toEncode), Error, /^CBOR encode error: number too large to encode \(\d+\)$/);
} else if (fixture.strict === false || fixture.roundtrip === false) {
assert.notDeepEqual(byteUtils.toHex(encode.encode(toEncode)), fixture.data, `encode ${ fixture.type } !strict`);
} else {
assert.strictEqual(byteUtils.toHex(encode.encode(toEncode)), fixture.data, `encode ${ fixture.type }`);
}
});
}
});
describe('roundtrip', () => {
for (const fixture of fixtures) {
if (!fixture.unsafe && fixture.strict !== false && fixture.roundtrip !== false) {
it(`should roundtrip ${ fixture.type }=${ fixture.label || JSON.stringify(fixture.expected) }`, () => {
const toEncode = fixture.encode || fixture.expected;
const options = fixture.useMaps ? { useMaps: true } : undefined;
const rt = decode.decode(encode.encode(toEncode), options);
if (fixture.useMaps) {
assert.strictEqual(Object.getPrototypeOf(rt), Map.prototype, 'is Map');
} else {
assert.isObject(rt, 'is object');
}
assert.deepStrictEqual(entries(rt), entries(fixture.expected), `roundtrip ${ fixture.type }`);
});
}
}
});
describe('specials', () => {
it('can decode indefinite length items', () => {
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('bf616f01617402ff')), {
o: 1,
t: 2
});
});
it('can switch off indefinite length support', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('bf616f01617402ff'), { allowIndefinite: false }), /indefinite/);
});
});
describe('sorting', () => {
it('sorts int map keys', () => {
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
1,
1
],
[
2,
2
]
]))), 'a201010202');
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
2,
1
],
[
1,
2
]
]))), 'a201020201');
});
it('sorts negint map keys', () => {
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
-1,
1
],
[
-2,
2
]
]))), 'a220012102');
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
-2,
1
],
[
-1,
2
]
]))), 'a220022101');
});
it('sorts bytes map keys', () => {
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
Uint8Array.from([
1,
2
]),
1
],
[
Uint8Array.from([
2,
1
]),
2
]
]))), 'a24201020142020102');
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
Uint8Array.from([
2,
1
]),
1
],
[
Uint8Array.from([
1,
2
]),
2
]
]))), 'a24201020242020101');
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
Uint8Array.from([
1,
2
]),
1
],
[
Uint8Array.from([
2,
1
]),
2
],
[
Uint8Array.from([200]),
3
]
]))), 'a341c8034201020142020102');
});
it('sorts bytes map keys', () => {
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
Uint8Array.from([
1,
2
]),
1
],
[
Uint8Array.from([
2,
1
]),
2
]
]))), 'a24201020142020102');
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
Uint8Array.from([
2,
1
]),
1
],
[
Uint8Array.from([
1,
2
]),
2
]
]))), 'a24201020242020101');
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
Uint8Array.from([
1,
2
]),
1
],
[
Uint8Array.from([
2,
1
]),
2
],
[
Uint8Array.from([200]),
3
]
]))), 'a341c8034201020142020102');
});
it('sorts array map keys (length only)', () => {
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
[1],
1
],
[
[
1,
1
],
2
]
]))), 'a281010182010102');
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
[
1,
1
],
1
],
[
[1],
2
]
]))), 'a281010282010101');
});
it('sorts map map keys (length only)', () => {
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
{ a: 1 },
1
],
[
{
a: 1,
b: 1
},
2
]
]))), 'a2a161610101a261610161620102');
assert.strictEqual(byteUtils.toHex(encode.encode(new Map([
[
{
a: 1,
b: 1
},
1
],
[
{ a: 1 },
2
]
]))), 'a2a161610102a261610161620101');
});
});
});
+75
View File
@@ -0,0 +1,75 @@
'use strict';
var chai = require('chai');
var token = require('../lib/token.js');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var common = require('./common.js');
var encode = require('../lib/encode.js');
var decode = require('../lib/decode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
function Uint16ArrayDecoder(obj) {
if (typeof obj !== 'string') {
throw new Error('expected string for tag 23');
}
const u8a = byteUtils.fromHex(obj);
return new Uint16Array(u8a.buffer, u8a.byteOffset, u8a.length / 2);
}
function Uint16ArrayEncoder(obj) {
if (!(obj instanceof Uint16Array)) {
throw new Error('expected Uint16Array for "Uint16Array" encoder');
}
return [
new token.Token(token.Type.tag, 23),
new token.Token(token.Type.string, byteUtils.toHex(obj))
];
}
describe('tag', () => {
it('date', () => {
assert.throws(() => encode.encode({ d: new Date() }), /unsupported type: Date/);
assert.equal(byteUtils.toHex(encode.encode(new Date('2013-03-21T20:04:00Z'), { typeEncoders: { Date: common.dateEncoder } })), 'c074323031332d30332d32315432303a30343a30305a');
const decodedDate = decode.decode(byteUtils.fromHex('c074323031332d30332d32315432303a30343a30305a'), { tags: { 0: common.dateDecoder } });
assert.instanceOf(decodedDate, Date);
assert.equal(decodedDate.toISOString(), new Date('2013-03-21T20:04:00Z').toISOString());
});
it('Uint16Array as hex/23 (overide existing type)', () => {
assert.equal(byteUtils.toHex(encode.encode(Uint16Array.from([
1,
2,
3
]), { typeEncoders: { Uint16Array: Uint16ArrayEncoder } })), 'd76c303130303032303030333030');
const decoded = decode.decode(byteUtils.fromHex('d76c303130303032303030333030'), { tags: { 23: Uint16ArrayDecoder } });
assert.instanceOf(decoded, Uint16Array);
assert.equal(byteUtils.toHex(decoded), byteUtils.toHex(Uint16Array.from([
1,
2,
3
])));
});
it('tag int too large', () => {
const verify = (hex, strict) => {
if (!strict) {
assert.throws(() => decode.decode(byteUtils.fromHex(hex), {
tags: { 8: common.dateDecoder },
strict: true
}), /integer encoded in more bytes than necessary/);
}
const decodedDate = decode.decode(byteUtils.fromHex(hex), {
tags: { 8: common.dateDecoder },
strict
});
assert.instanceOf(decodedDate, Date);
assert.equal(decodedDate.toISOString(), new Date('2013-03-21T20:04:00Z').toISOString());
};
verify('c874323031332d30332d32315432303a30343a30305a', true);
verify('d80874323031332d30332d32315432303a30343a30305a', false);
verify('d9000874323031332d30332d32315432303a30343a30305a', false);
verify('da0000000874323031332d30332d32315432303a30343a30305a', false);
verify('db000000000000000874323031332d30332d32315432303a30343a30305a', false);
});
});
+253
View File
@@ -0,0 +1,253 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var decode = require('../lib/decode.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
const fixtures = [
{
data: '8601f5f4f6f720',
expected: [
1,
true,
false,
null,
undefined,
-1
],
type: 'array of float specials'
},
{
data: 'f93800',
expected: 0.5,
type: 'float16'
},
{
data: 'f9b800',
expected: -0.5,
type: 'float16'
},
{
data: 'fa33c00000',
expected: 8.940696716308594e-8,
type: 'float32'
},
{
data: 'fab3c00000',
expected: -8.940696716308594e-8,
type: 'float32'
},
{
data: 'fb3ff199999999999a',
expected: 1.1,
type: 'float64'
},
{
data: 'fbbff199999999999a',
expected: -1.1,
type: 'float64'
},
{
data: 'fb3ff1c71c71c71c72',
expected: 1.1111111111111112,
type: 'float64'
},
{
data: 'fb0000000000000002',
expected: 1e-323,
type: 'float64'
},
{
data: 'fb8000000000000002',
expected: -1e-323,
type: 'float64'
},
{
data: 'fb3fefffffffffffff',
expected: 0.9999999999999999,
type: 'float64'
},
{
data: 'fbbfefffffffffffff',
expected: -0.9999999999999999,
type: 'float64'
},
{
data: 'f97c00',
expected: Infinity,
type: 'Infinity'
},
{
data: 'fb7ff0000000000000',
expected: Infinity,
type: 'Infinity',
strict: false
},
{
data: 'f9fc00',
expected: -Infinity,
type: '-Infinity'
},
{
data: 'fbfff0000000000000',
expected: -Infinity,
type: '-Infinity',
strict: false
},
{
data: 'f97e00',
expected: NaN,
type: 'NaN'
},
{
data: 'f97ff8',
expected: NaN,
type: 'NaN',
strict: false
},
{
data: 'fa7ff80000',
expected: NaN,
type: 'NaN',
strict: false
},
{
data: 'fb7ff8000000000000',
expected: NaN,
type: 'NaN',
strict: false
},
{
data: 'fb7ff8cafedeadbeef',
expected: NaN,
type: 'NaN',
strict: false
},
{
data: 'fb40f4241a31a5a515',
expected: 82497.63712086187,
type: 'float64'
}
];
describe('float', () => {
describe('decode', () => {
for (const fixture of fixtures) {
const data = byteUtils.fromHex(fixture.data);
it(`should decode ${ fixture.type }=${ fixture.expected }`, () => {
assert.deepStrictEqual(decode.decode(data), fixture.expected, `decode ${ fixture.type }`);
assert.deepStrictEqual(decode.decode(data, { strict: true }), fixture.expected, `decode ${ fixture.type }`);
});
}
});
it('error', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('f80000')), Error, 'simple values are not supported');
assert.throws(() => decode.decode(byteUtils.fromHex('f900')), Error, 'not enough data for float16');
assert.throws(() => decode.decode(byteUtils.fromHex('fa0000')), Error, 'not enough data for float32');
assert.throws(() => decode.decode(byteUtils.fromHex('fb00000000')), Error, 'not enough data for float64');
});
describe('encode', () => {
for (const fixture of fixtures) {
if (fixture.strict !== false) {
it(`should encode ${ fixture.type }=${ fixture.expected }`, () => {
assert.strictEqual(byteUtils.toHex(encode.encode(fixture.expected)), fixture.data, `encode ${ fixture.type }`);
});
}
}
});
describe('encode float64', () => {
for (const fixture of fixtures) {
if (fixture.type.startsWith('float')) {
it(`should encode ${ fixture.type }=${ fixture.expected }`, () => {
const encoded = encode.encode(fixture.expected, { float64: true });
assert.strictEqual(encoded.length, 9);
assert.strictEqual(encoded[0], 251);
assert.strictEqual(decode.decode(encoded), fixture.expected, `encode float64 ${ fixture.type }`);
});
}
}
});
describe('roundtrip', () => {
for (const fixture of fixtures) {
if (!fixture.unsafe && fixture.strict !== false) {
it(`should roundtrip ${ fixture.type }=${ fixture.expected }`, () => {
assert.deepStrictEqual(decode.decode(encode.encode(fixture.expected)), fixture.expected, `roundtrip ${ fixture.type }`);
});
}
}
});
describe('specials', () => {
it('indefinite length switch fails on BREAK', () => {
assert.throws(() => decode.decode(Uint8Array.from([
131,
1,
2,
255
])), /unexpected break to lengthed array/);
assert.throws(() => decode.decode(Uint8Array.from([
131,
1,
2,
255
]), { allowIndefinite: false }), /indefinite/);
});
it('can switch off undefined support', () => {
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('f7')), undefined);
assert.throws(() => decode.decode(byteUtils.fromHex('f7'), { allowUndefined: false }), /undefined/);
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('830102f7')), [
1,
2,
undefined
]);
assert.throws(() => decode.decode(byteUtils.fromHex('830102f7'), { allowUndefined: false }), /undefined/);
});
it('can coerce undefined to null', () => {
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('f7'), { coerceUndefinedToNull: false }), undefined);
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('f7'), { coerceUndefinedToNull: true }), null);
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('830102f7'), { coerceUndefinedToNull: false }), [
1,
2,
undefined
]);
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('830102f7'), { coerceUndefinedToNull: true }), [
1,
2,
null
]);
});
it('can switch off Infinity support', () => {
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('830102f97c00')), [
1,
2,
Infinity
]);
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('830102f9fc00')), [
1,
2,
-Infinity
]);
assert.throws(() => decode.decode(byteUtils.fromHex('830102f97c00'), { allowInfinity: false }), /Infinity/);
assert.throws(() => decode.decode(byteUtils.fromHex('830102f9fc00'), { allowInfinity: false }), /Infinity/);
for (const fixture of fixtures.filter(f => f.type.endsWith('Infinity'))) {
assert.throws(() => decode.decode(byteUtils.fromHex(fixture.data), { allowInfinity: false }), /Infinity/);
}
});
it('can switch off NaN support', () => {
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('830102f97e00')), [
1,
2,
NaN
]);
assert.throws(() => decode.decode(byteUtils.fromHex('830102f97e00'), { allowNaN: false }), /NaN/);
for (const fixture of fixtures.filter(f => f.type === 'NaN')) {
assert.throws(() => decode.decode(byteUtils.fromHex(fixture.data), { allowNaN: false }), /NaN/);
}
});
});
});
+91
View File
@@ -0,0 +1,91 @@
'use strict';
var chai = require('chai');
var bl = require('../lib/bl.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
describe('Internal bytes list', () => {
describe('push', () => {
it('push bits', () => {
const bl$1 = new bl.Bl(10);
const expected = [];
for (let i = 0; i < 25; i++) {
bl$1.push([i + 1]);
expected.push(i + 1);
}
assert.deepEqual([...bl$1.toBytes()], expected);
});
for (let i = 4; i < 21; i++) {
it(`push Bl(${ i })`, () => {
const bl$1 = new bl.Bl(i);
const expected = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
100,
110,
120,
11,
12,
130,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23
];
for (let i = 0; i < 5; i++) {
bl$1.push([i + 1]);
}
bl$1.push(Uint8Array.from([
6,
7,
8,
9,
10
]));
bl$1.push([100]);
bl$1.push(Uint8Array.from([
110,
120
]));
bl$1.push(Uint8Array.from([
11,
12
]));
bl$1.push([130]);
bl$1.push(Uint8Array.from([
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23
]));
assert.deepEqual([...bl$1.toBytes()], expected);
});
}
});
});
+98
View File
@@ -0,0 +1,98 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var taglib = require('../taglib.js');
var byteUtils = require('../lib/byte-utils.js');
var appendix_a = require('./appendix_a.js');
var decode = require('../lib/decode.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
const tags = [];
const typeEncoders = {};
tags[0] = function (obj) {
if (typeof obj !== 'string') {
throw new Error('expected string for tag 1');
}
return `0("${ new Date(obj).toISOString().replace(/\.000Z$/, 'Z') }")`;
};
tags[1] = function (obj) {
if (typeof obj !== 'number') {
throw new Error('expected number for tag 1');
}
return `1(${ obj })`;
};
tags[2] = taglib.bigIntDecoder;
typeEncoders.bigint = taglib.bigIntEncoder;
tags[3] = taglib.bigNegIntDecoder;
tags[23] = function (obj) {
if (!(obj instanceof Uint8Array)) {
throw new Error('expected byte array for tag 23');
}
return `23(h'${ byteUtils.toHex(obj) }')`;
};
tags[24] = function (obj) {
return tags[23](obj).replace(/^23/, '24');
};
tags[32] = function (obj) {
if (typeof obj !== 'string') {
throw new Error('expected string for tag 32');
}
;
(() => new URL(obj))();
return `32("${ obj }")`;
};
describe('cbor/test-vectors', () => {
let i = 0;
for (const fixture of appendix_a.fixtures) {
const u8a = byteUtils.fromHex(fixture.hex);
let expected = fixture.decoded !== undefined ? fixture.decoded : fixture.diagnostic;
if (typeof expected === 'string' && expected.startsWith('h\'')) {
expected = byteUtils.fromHex(expected.replace(/(^h)'|('$)/g, ''));
}
it(`test vector #${ i }: ${ inspect(expected).replace(/\n\s*/g, '') }`, () => {
if (fixture.error) {
assert.throws(() => decode.decode(u8a, { tags }), fixture.error);
} else {
if (fixture.noTagDecodeError) {
assert.throws(() => decode.decode(u8a), fixture.noTagDecodeError);
}
let actual = decode.decode(u8a, { tags });
if (typeof actual === 'bigint') {
actual = inspect(actual);
}
if (typeof expected === 'bigint') {
expected = inspect(expected);
}
assert.deepEqual(actual, expected);
if (fixture.roundtrip) {
if (fixture.noTagEncodeError) {
assert.throws(() => encode.encode(decode.decode(u8a, { tags })), fixture.noTagEncodeError);
}
const reencoded = encode.encode(decode.decode(u8a, { tags }), { typeEncoders });
assert.equal(byteUtils.toHex(reencoded), fixture.hex);
}
}
});
i++;
}
it.skip('encode w/ tags', () => {
});
});
function inspect(o) {
if (typeof o === 'string') {
return `'${ o }'`;
}
if (o instanceof Uint8Array) {
return `Uint8Array<${ o.join(',') }>`;
}
if (o == null || typeof o !== 'object') {
return String(o);
}
return JSON.stringify(o);
}
+77
View File
@@ -0,0 +1,77 @@
'use strict';
var chai = require('chai');
require('../cborg.js');
var byteUtils = require('../lib/byte-utils.js');
var decode = require('../lib/decode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
describe('decode errors', () => {
it('not Uint8Array', () => {
for (const arg of [
true,
false,
null,
undefined,
'string',
{ obj: 'ect' },
{},
['array'],
[],
[
1,
2,
3
],
0,
100,
1.1,
-1,
Symbol.for('nope')
]) {
assert.throws(() => decode.decode(arg), /CBOR decode error.*must be a Uint8Array/);
}
});
it('no data', () => {
assert.throws(() => decode.decode(new Uint8Array('')), /CBOR decode error.*content/);
});
it('break only', () => {
assert.throws(() => decode.decode(new Uint8Array([255])), /CBOR decode error.*break/);
});
it('not enough map entries (value)', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('a2616f016174')), /map.*not enough entries.*value/);
});
it('not enough map entries (key)', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('a2616f01')), /map.*not enough entries.*key/);
});
it('break in lengthed map', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('a2616f01ff740f')), /unexpected break to lengthed map/);
});
it('not enough array entries', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('82616f')), /array.*not enough entries/);
});
it('break in lengthed array', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('82ff')), /unexpected break to lengthed array/);
});
it('no such decoder', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('82ff')), /unexpected break to lengthed array/);
});
it('too many terminals', () => {
assert.throws(() => decode.decode(byteUtils.fromHex('0101')), /too many terminals/);
});
it('rejectDuplicateMapKeys enabled on duplicate keys', () => {
assert.deepStrictEqual(decode.decode(byteUtils.fromHex('a3636261720363666f6f0163666f6f02')), {
foo: 2,
bar: 3
});
assert.throws(() => decode.decode(byteUtils.fromHex('a3636261720363666f6f0163666f6f02'), { rejectDuplicateMapKeys: true }), /CBOR decode error: found repeat map key "foo"/);
assert.throws(() => decode.decode(byteUtils.fromHex('a3636261720363666f6f0163666f6f02'), {
useMaps: true,
rejectDuplicateMapKeys: true
}), /CBOR decode error: found repeat map key "foo"/);
});
});
+56
View File
@@ -0,0 +1,56 @@
'use strict';
var ipldGarbage = require('ipld-garbage');
require('../cborg.js');
var chai = require('chai');
var encode = require('../lib/encode.js');
var decode = require('../lib/decode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
describe('Fuzz round-trip', () => {
it('random objects', function () {
this.timeout(5000);
for (let i = 0; i < 1000; i++) {
const obj = ipldGarbage.garbage(300, { weights: { CID: 0 } });
const byts = encode.encode(obj);
const decoded = decode.decode(byts);
assert.deepEqual(decoded, obj);
}
});
it('circular references error', () => {
let obj = {};
obj.obj = obj;
assert.throws(() => encode.encode(obj), /circular references/);
obj = {
blip: [
1,
2,
{ blop: {} }
]
};
obj.blip[2].blop.boop = obj;
assert.throws(() => encode.encode(obj), /circular references/);
obj = {
blip: [
1,
2,
{ blop: {} }
]
};
obj.blip[2].blop.boop = obj.blip;
assert.throws(() => encode.encode(obj), /circular references/);
obj = {
blip: {},
bloop: {}
};
obj.bloop = obj.blip;
assert.doesNotThrow(() => encode.encode(obj));
const arr = [];
arr[0] = arr;
assert.throws(() => encode.encode(arr), /circular references/);
});
});
+281
View File
@@ -0,0 +1,281 @@
'use strict';
var chai = require('chai');
require('../lib/json/json.js');
var encode = require('../lib/json/encode.js');
var decode = require('../lib/json/decode.js');
const toBytes = str => new TextEncoder().encode(str);
function verifyRoundTrip(obj, sorting) {
const encoded = new TextDecoder().decode(encode.encode(obj, sorting === false ? { mapSorter: null } : undefined));
const json = JSON.stringify(obj);
chai.assert.strictEqual(encoded, json);
const decoded = decode.decode(toBytes(JSON.stringify(obj)));
chai.assert.deepStrictEqual(decoded, obj);
}
function verifyEncodedForm(testCase) {
const obj = JSON.parse(testCase);
const encoded = encode.encode(obj);
chai.assert.strictEqual(new TextDecoder().decode(encoded), JSON.stringify(obj));
const decoded = decode.decode(encoded);
chai.assert.deepStrictEqual(decoded, obj);
const decoded2 = decode.decode(toBytes(testCase));
chai.assert.deepStrictEqual(decoded2, obj);
}
describe('json basics', () => {
it('can round-trip basic literals', () => {
const testCases = [
'null',
'true',
'false',
'0',
'9007199254740991',
'-9007199254740991',
JSON.stringify(Number.MAX_VALUE),
JSON.stringify(Number.MIN_VALUE)
];
for (const testCase of testCases) {
verifyEncodedForm(testCase);
}
chai.assert.strictEqual(decode.decode(toBytes('1E1')), 10);
chai.assert.strictEqual(decode.decode(toBytes('0.1e1')), 1);
chai.assert.strictEqual(decode.decode(toBytes('1e-1')), 0.1);
chai.assert.strictEqual(decode.decode(toBytes('1e+00')), 1);
chai.assert.strictEqual(decode.decode(toBytes('10.0')), 10);
chai.assert.deepStrictEqual(decode.decode(toBytes('[-10.0,1.0,0.0,100.0]')), [
-10,
1,
0,
100
]);
verifyRoundTrip(true);
verifyRoundTrip(false);
verifyRoundTrip(null);
verifyRoundTrip(100);
verifyRoundTrip(-100);
verifyRoundTrip(1.11);
verifyRoundTrip(-100.11111);
verifyRoundTrip(11100000000);
verifyRoundTrip(1.0011111e-18);
});
it('handles large integers as BigInt', () => {
const verify = (inp, str) => {
if (str === undefined) {
str = String(inp);
}
chai.assert.strictEqual(decode.decode(toBytes(str), { allowBigInt: true }), inp);
chai.assert.strictEqual(decode.decode(toBytes(str)), parseFloat(str));
};
verify(Number.MAX_SAFE_INTEGER);
verify(-Number.MAX_SAFE_INTEGER);
verify(BigInt('9007199254740992'));
verify(BigInt('9007199254740993'));
verify(BigInt('11959030306112471731'));
verify(BigInt('18446744073709551615'));
verify(BigInt('9223372036854775807'));
verify(BigInt('-9007199254740992'));
verify(BigInt('-9007199254740993'));
verify(BigInt('-9223372036854776000'));
verify(BigInt('-11959030306112471732'));
verify(BigInt('-18446744073709551616'));
verify(-9007199254740992, '-9007199254740992.0');
verify(-9223372036854776000, '-9223372036854776000.0');
verify(-18446744073709552000, '-18446744073709551616.0');
});
it('can round-trip string literals', () => {
const testCases = [
JSON.stringify(''),
JSON.stringify(' '),
JSON.stringify('"'),
JSON.stringify('\\'),
JSON.stringify('\b\f\n\r\t'),
JSON.stringify('"'),
JSON.stringify('&#34; %22 0x22 034 &#x22;'),
'"\uD83D\uDE00"'
];
for (const testCase of testCases) {
verifyEncodedForm(testCase);
}
chai.assert.strictEqual(decode.decode(toBytes('"/ & \\/"')), '/ & /');
verifyRoundTrip('this is a string');
verifyRoundTrip('this \uD834\uDD1E is a \u263A\u263A \u2663 string ̐ ̀\n\r');
verifyRoundTrip('');
verifyRoundTrip('foo\\bar\nbaz\tbop\rbing"bip\'bang');
});
it('can round-trip array literals', () => {
const testCases = [
'[]',
'[null]',
'[true, false]',
'[ \n 0,1, 2\n , 3,\n4] \n ',
'[-10.0, 1.0, 0.0, 100.0]',
'[["2 deep"]]'
];
for (const testCase of testCases) {
verifyEncodedForm(testCase);
}
verifyRoundTrip([
1,
2,
3,
'string',
true,
4
]);
verifyRoundTrip([
1,
2,
3,
'string',
true,
[
'and',
'a',
'nested',
'array',
true
],
4
]);
});
it('can round-trip object literals', () => {
const testCases = [
'{}',
'\n {\n "\\b"\n :\n""\n }\n ',
'{"":""}',
'{"1":{"2":0,"3":"deep"}}'
];
for (const testCase of testCases) {
verifyEncodedForm(testCase);
}
});
it('will sort map keys', () => {
const unsorted = {
one: 1,
two: 2,
three: 3.1,
str: 'string',
bool: true,
four: 4
};
verifyRoundTrip(unsorted, false);
chai.assert.strictEqual(new TextDecoder().decode(encode.encode(unsorted)), '{"bool":true,"four":4,"one":1,"str":"string","three":3.1,"two":2}');
});
it('can handle novel cases', () => {
chai.assert.strictEqual(decode.decode(toBytes('"this \\uD834\\uDD1E is a \\u263a\\u263a string"')), 'this \uD834\uDD1E is a \u263A\u263A string');
verifyRoundTrip({
one: 1,
two: 2,
three: 3.1,
str: 'string',
arr: [
'and',
'a',
'nested',
[],
'array',
[
true,
1
],
false
],
bool: true,
obj: {
nested: 'object',
a: [],
o: {}
},
four: 4
}, false);
verifyRoundTrip([
false,
[
{
'#nFzU': {},
'\\w>': -0.9441451951197325,
'\t\'': '\'JB+2Wg\tw"IrM*#e^L/d&4rrzUuwq(1mH6aVRredB&Bfs]S"KqK(Tz1Q"URBAfw',
'\n@FrfM': 'M[D]q&'
},
'J4>\'Xdc+u2$%',
4227406737130333
]
], false);
verifyRoundTrip([
0.12995619865708727,
-4973404279772543,
{
drG2: [true],
';#K^Qf>V': null,
'`2=': 'ecc<e/$+-.;U>Gr5RdZDJ\n5+:{=QHNN.tVVN~dX$FWFwu`6>"&=tW!*1*^\u263A)JFM1p|}&X.B|${*\\f@!w2\u263A+'
}
], false);
chai.assert.strictEqual(`${ decode.decode(encode.encode(9007199254740991)) }`, '9007199254740991');
chai.assert.strictEqual(`${ decode.decode(encode.encode(9007199254740992)) }`, '9007199254740992');
chai.assert.strictEqual(`${ decode.decode(encode.encode(900719925474099100n)) }`, '900719925474099100');
});
it('should throw on bad types', () => {
chai.assert.throws(() => encode.encode(new Uint8Array([
1,
2
])), /CBOR encode error: unsupported type: Uint8Array/);
chai.assert.throws(() => encode.encode({
boop: new Uint8Array([
1,
2
])
}), /CBOR encode error: unsupported type: Uint8Array/);
chai.assert.throws(() => encode.encode(undefined), /CBOR encode error: unsupported type: undefined/);
chai.assert.throws(() => encode.encode(new Map([
[
1,
2
],
[
2,
3
]
])), /CBOR encode error: non-string map keys are not supported/);
chai.assert.throws(() => encode.encode(new Map([
[
[
'foo',
'bar'
],
2
],
[
[
'bar',
'foo'
],
3
]
])), /CBOR encode error: complex map keys are not supported/);
});
it('should throw on bad decode failure modes', () => {
chai.assert.throws(() => decode.decode(toBytes('{"a":1 & "b":2}')), 'CBOR decode error: unexpected character at position 7, was expecting object delimiter but found \'&\'');
chai.assert.throws(() => decode.decode(toBytes('{"a":1,"b"!2}')), 'CBOR decode error: unexpected character at position 10, was expecting key/value delimiter \':\' but found \'!\'');
chai.assert.throws(() => decode.decode(toBytes('[1,2&3]')), 'CBOR decode error: unexpected character at position 4, was expecting array delimiter but found \'&\'');
chai.assert.throws(() => decode.decode(toBytes('{"a":!}')), 'CBOR decode error: unexpected character at position 5');
chai.assert.throws(() => decode.decode(toBytes('"abc')), 'CBOR decode error: unexpected end of string at position 4');
chai.assert.throws(() => decode.decode(toBytes('"ab\\xc"')), 'CBOR decode error: unexpected string escape character at position 5');
chai.assert.throws(() => decode.decode(toBytes('"ab\x1Ec"')), 'CBOR decode error: invalid control character at position 3');
chai.assert.throws(() => decode.decode(toBytes('"ab\\')), 'CBOR decode error: unexpected string termination at position 4');
chai.assert.throws(() => decode.decode(toBytes('"\u263A').subarray(0, 3)), 'CBOR decode error: unexpected unicode sequence at position 1');
chai.assert.throws(() => decode.decode(toBytes('"\\uxyza"')), 'CBOR decode error: unexpected unicode escape character at position 3');
chai.assert.throws(() => decode.decode(toBytes('"\\u11"')), 'CBOR decode error: unexpected end of unicode escape sequence at position 3');
chai.assert.throws(() => decode.decode(toBytes('-boop')), 'CBOR decode error: unexpected token at position 1');
chai.assert.throws(() => decode.decode(toBytes('{"v":nope}')), 'CBOR decode error: unexpected token at position 7, expected to find \'null\'');
chai.assert.throws(() => decode.decode(toBytes('[n]')), 'CBOR decode error: unexpected end of input at position 1');
chai.assert.throws(() => decode.decode(toBytes('{"v":truu}')), 'CBOR decode error: unexpected token at position 9, expected to find \'true\'');
chai.assert.throws(() => decode.decode(toBytes('[tr]')), 'CBOR decode error: unexpected end of input at position 1');
chai.assert.throws(() => decode.decode(toBytes('{"v":flase}')), 'CBOR decode error: unexpected token at position 7, expected to find \'false\'');
chai.assert.throws(() => decode.decode(toBytes('[fa]')), 'CBOR decode error: unexpected end of input at position 1');
chai.assert.throws(() => decode.decode(toBytes('-0..1')), 'CBOR decode error: unexpected token at position 3');
});
it('should throw when rejectDuplicateMapKeys enabled on duplicate keys', () => {
chai.assert.deepStrictEqual(decode.decode(toBytes('{"foo":1,"foo":2}')), { foo: 2 });
chai.assert.throws(() => decode.decode(toBytes('{"foo":1,"foo":2}'), { rejectDuplicateMapKeys: true }), /CBOR decode error: found repeat map key "foo"/);
});
});
+63
View File
@@ -0,0 +1,63 @@
'use strict';
var chai = require('chai');
var ipldGarbage = require('ipld-garbage');
var _0uint = require('../lib/0uint.js');
require('../cborg.js');
var length = require('../lib/length.js');
var common = require('./common.js');
var encode = require('../lib/encode.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var chai__default = /*#__PURE__*/_interopDefaultLegacy(chai);
const {assert} = chai__default["default"];
function verifyLength(object, options) {
const len = length.encodedLength(object, options);
const encoded = encode.encode(object, options);
const actual = encoded.length;
assert.strictEqual(actual, len, JSON.stringify(object));
}
describe('encodedLength', () => {
it('int boundaries', () => {
for (let ii = 0; ii < 4; ii++) {
verifyLength(_0uint.uintBoundaries[ii]);
verifyLength(_0uint.uintBoundaries[ii] - 1);
verifyLength(_0uint.uintBoundaries[ii] + 1);
verifyLength(-1 * _0uint.uintBoundaries[ii]);
verifyLength(-1 * _0uint.uintBoundaries[ii] - 1);
verifyLength(-1 * _0uint.uintBoundaries[ii] + 1);
}
});
it('tags', () => {
verifyLength({ date: new Date('2013-03-21T20:04:00Z') }, { typeEncoders: { Date: common.dateEncoder } });
});
it('floats', () => {
verifyLength(0.5);
verifyLength(0.5, { float64: true });
verifyLength(8.940696716308594e-8);
verifyLength(8.940696716308594e-8, { float64: true });
});
it('small garbage', function () {
this.timeout(10000);
for (let ii = 0; ii < 1000; ii++) {
const gbg = ipldGarbage.garbage(1 << 6, { weights: { CID: 0 } });
verifyLength(gbg);
}
});
it('medium garbage', function () {
this.timeout(10000);
for (let ii = 0; ii < 100; ii++) {
const gbg = ipldGarbage.garbage(1 << 16, { weights: { CID: 0 } });
verifyLength(gbg);
}
});
it('large garbage', function () {
this.timeout(10000);
for (let ii = 0; ii < 10; ii++) {
const gbg = ipldGarbage.garbage(1 << 20, { weights: { CID: 0 } });
verifyLength(gbg);
}
});
});