std/cbor/decode_cbor_test.ts

656 lines
16 KiB
TypeScript

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { assertEquals, assertThrows } from "@std/assert";
import { random } from "./_common_test.ts";
import { decodeCbor } from "./decode_cbor.ts";
import { encodeCbor } from "./encode_cbor.ts";
import { CborTag } from "./tag.ts";
Deno.test("decodeCbor() decoding undefined", () => {
assertEquals(decodeCbor(encodeCbor(undefined)), undefined);
});
Deno.test("decodeCbor() decoding null", () => {
assertEquals(decodeCbor(encodeCbor(null)), null);
});
Deno.test("decodeCbor() decoding true", () => {
assertEquals(decodeCbor(encodeCbor(true)), true);
});
Deno.test("decodeCbor() decoding false", () => {
assertEquals(decodeCbor(encodeCbor(false)), false);
});
Deno.test("decodeCbor() decoding integers", () => {
let num = random(0, 24);
assertEquals(decodeCbor(encodeCbor(num)), num);
assertEquals(decodeCbor(encodeCbor(BigInt(num))), num);
num = random(24, 2 ** 8);
assertEquals(decodeCbor(encodeCbor(num)), num);
assertEquals(decodeCbor(encodeCbor(BigInt(num))), num);
num = random(2 ** 8, 2 ** 16);
assertEquals(decodeCbor(encodeCbor(num)), num);
assertEquals(decodeCbor(encodeCbor(BigInt(num))), num);
num = random(2 ** 16, 2 ** 32);
assertEquals(decodeCbor(encodeCbor(num)), num);
assertEquals(decodeCbor(encodeCbor(BigInt(num))), num);
num = random(2 ** 32, Number.MAX_SAFE_INTEGER);
assertEquals(decodeCbor(encodeCbor(num)), BigInt(num));
assertEquals(decodeCbor(encodeCbor(BigInt(num))), BigInt(num));
num = -random(0, 24);
assertEquals(decodeCbor(encodeCbor(num)), num);
assertEquals(decodeCbor(encodeCbor(BigInt(num))), num);
num = -random(24, 2 ** 8);
assertEquals(decodeCbor(encodeCbor(num)), num);
assertEquals(decodeCbor(encodeCbor(BigInt(num))), num);
num = -random(2 ** 8, 2 ** 16);
assertEquals(decodeCbor(encodeCbor(num)), num);
assertEquals(decodeCbor(encodeCbor(BigInt(num))), num);
num = -random(2 ** 16, 2 ** 32);
assertEquals(decodeCbor(encodeCbor(num)), num);
assertEquals(decodeCbor(encodeCbor(BigInt(num))), num);
num = -random(2 ** 32, Number.MAX_SAFE_INTEGER);
assertEquals(decodeCbor(encodeCbor(num)), BigInt(num));
assertEquals(decodeCbor(encodeCbor(BigInt(num))), BigInt(num));
});
Deno.test("decodeCbor() decoding strings", () => {
const textDecoder = new TextDecoder();
let text = textDecoder.decode(
new Uint8Array(random(0, 24)).map((_) => random(97, 123)),
); // Range: `a` - `z`
assertEquals(decodeCbor(encodeCbor(text)), text);
text = textDecoder.decode(
new Uint8Array(random(24, 2 ** 8)).map((_) => random(97, 123)),
); // Range: `a` - `z`
assertEquals(decodeCbor(encodeCbor(text)), text);
text = textDecoder.decode(
new Uint8Array(random(2 ** 8, 2 ** 16)).map((_) => random(97, 123)),
); // Range: `a` - `z`
assertEquals(decodeCbor(encodeCbor(text)), text);
text = textDecoder.decode(
new Uint8Array(random(2 ** 16, 2 ** 17)).map((_) => random(97, 123)),
); // Range: `a` - `z`
assertEquals(decodeCbor(encodeCbor(text)), text);
// Can't test the next bracket up due to JavaScript limitations.
});
Deno.test("decodeCbor() decoding Uint8Arrays", () => {
let bytes = new Uint8Array(random(0, 24)).map((_) => random(0, 256));
assertEquals(decodeCbor(encodeCbor(bytes)), bytes);
bytes = new Uint8Array(random(24, 2 ** 8)).map((_) => random(0, 256));
assertEquals(decodeCbor(encodeCbor(bytes)), bytes);
bytes = new Uint8Array(random(2 ** 8, 2 ** 16)).map((_) => random(0, 256));
assertEquals(decodeCbor(encodeCbor(bytes)), bytes);
bytes = new Uint8Array(random(2 ** 16, 2 ** 17)).map((_) => random(0, 256));
assertEquals(decodeCbor(encodeCbor(bytes)), bytes);
// Can't test the next bracket up due to JavaScript limitations.
});
Deno.test("decodeCbor() decoding Dates", () => {
const date = new Date();
assertEquals(decodeCbor(encodeCbor(date)), date);
});
Deno.test("decodeCbor() decoding arrays", () => {
let array = new Array(random(0, 24)).fill(0).map((_) => random(0, 2 ** 32));
assertEquals(decodeCbor(encodeCbor(array)), array);
array = new Array(random(24, 2 ** 8)).fill(0).map((_) => random(0, 2 ** 32));
assertEquals(decodeCbor(encodeCbor(array)), array);
array = new Array(random(2 ** 8, 2 ** 16)).fill(0).map((_) =>
random(0, 2 ** 32)
);
assertEquals(decodeCbor(encodeCbor(array)), array);
array = new Array(random(2 ** 16, 2 ** 17)).fill(0).map((_) =>
random(0, 2 ** 32)
);
assertEquals(decodeCbor(encodeCbor(array)), array);
// Can't test the next bracket up due to JavaScript limitations.
});
Deno.test("decodeCbor() decoding objects", () => {
let pairs = random(0, 24);
let object = Object.fromEntries(
new Array(pairs).fill(0).map((_, i) => [i, i]),
);
assertEquals(decodeCbor(encodeCbor(object)), object);
pairs = random(24, 2 ** 8);
object = Object.fromEntries(new Array(pairs).fill(0).map((_, i) => [i, i]));
assertEquals(decodeCbor(encodeCbor(object)), object);
pairs = random(2 ** 8, 2 ** 16);
object = Object.fromEntries(new Array(pairs).fill(0).map((_, i) => [i, i]));
assertEquals(decodeCbor(encodeCbor(object)), object);
pairs = random(2 ** 16, 2 ** 17);
object = Object.fromEntries(new Array(pairs).fill(0).map((_, i) => [i, i]));
assertEquals(decodeCbor(encodeCbor(object)), object);
// Can't test the next bracket up due to JavaScript limitations.
});
Deno.test("decodeCbor() decoding CborTag()", () => {
const tag = new CborTag(
2,
new Uint8Array(random(0, 24)).map((_) => random(0, 256)),
);
assertEquals(decodeCbor(encodeCbor(tag)), tag);
});
Deno.test("decodeCbor() rejecting empty encoded data", () => {
assertThrows(
() => {
decodeCbor(new Uint8Array(0));
},
RangeError,
"Cannot decode empty Uint8Array",
);
});
Deno.test("decodeCbor() rejecting majorType 0 due to additional information", () => {
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b000_11100,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b000_11100)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b000_11101,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b000_11101)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b000_11110,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b000_11110)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b000_11111,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b000_11111)",
);
});
Deno.test("decodeCbor() rejecting majorType 1 due to additional information", () => {
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b001_11100,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b001_11100)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b001_11101,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b001_11101)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b001_11110,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b001_11110)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b001_11111,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b001_11111)",
);
});
Deno.test("decodeCbor() rejecting majorType 2 due to additional information", () => {
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b010_11100,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b010_11100)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b010_11101,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b010_11101)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b010_11110,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b010_11110)",
);
});
Deno.test("decodeCbor() rejecting majorType 2 due to invalid indefinite length byte string", () => {
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b010_11111]));
},
RangeError,
"More bytes were expected",
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b010_11111, 0b000_00000]));
},
TypeError,
"Cannot decode value (0b000_00000) inside an indefinite length byte string",
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b010_11111, 0b010_11111]));
},
TypeError,
"Indefinite length byte strings cannot contain indefinite length byte strings",
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b010_11111, 0b010_00000]));
},
RangeError,
"More bytes were expected",
);
});
Deno.test("decodeCbor() rejecting majorType 3 due to additional information", () => {
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b011_11100,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b011_11100)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b011_11101,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b011_11101)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b011_11110,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b011_11110)",
);
});
Deno.test("decodeCbor() rejecting majorType 3 due to invalid indefinite length text string", () => {
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b011_11111]));
},
RangeError,
"More bytes were expected",
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b011_11111, 0b000_00000]));
},
TypeError,
"Cannot decode value (0b000_00000) inside an indefinite length text string",
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b011_11111, 0b011_11111]));
},
TypeError,
"Indefinite length text strings cannot contain indefinite length text strings",
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b011_11111, 0b011_00000]));
},
RangeError,
"More bytes were expected",
);
});
Deno.test("decodeCbor() rejecting majorType 4 due to additional information", () => {
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b100_11100,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b100_11100)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b100_11101,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b100_11101)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b100_11110,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b100_11110)",
);
});
Deno.test("decodeCbor() rejecting majorType 4 due to invalid indefinite length arrays", () => {
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b100_11111]));
},
RangeError,
"More bytes were expected",
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b100_11111, 0b000_00000]));
},
RangeError,
"More bytes were expected",
);
});
Deno.test("decodeCbor() rejecting majorType 5 due to additional information", () => {
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b101_11100,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b101_11100)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b101_11101,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b101_11101)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b101_11110,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b101_11110)",
);
});
Deno.test("decodeCbor() rejecting majorType 5 due to maps having invalid keys", () => {
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b101_00001, 0b000_00000, 0b000_00000]));
},
TypeError,
'Cannot decode key of type (number): This implementation only supports "text string" keys',
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b101_00010,
0b011_00001,
48,
0b000_00000,
0b011_00001,
48,
0b000_00001,
]),
);
},
TypeError,
"A Map cannot have duplicate keys: Key (0) already exists",
);
});
Deno.test("decodeCbor() rejecting majorType 5 due to invalid indefinite length maps", () => {
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b101_11111]));
},
RangeError,
"More bytes were expected",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([0b101_11111, 0b000_00000, 0b000_00000, 0b111_11111]),
);
},
TypeError,
'Cannot decode key of type (number): This implementation only supports "text string" keys',
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b101_11111,
0b011_00001,
48,
0b000_00000,
0b011_00001,
48,
0b000_00001,
0b111_11111,
]),
);
},
TypeError,
"A Map cannot have duplicate keys: Key (0) already exists",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b101_11111,
0b011_00001,
48,
0b000_00000,
]),
);
},
RangeError,
"More bytes were expected",
);
});
Deno.test("decodeCbor() rejecting majorType 6 due to additional information", () => {
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b110_11100,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b110_11100)",
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b110_00000, 0b000_00000]));
},
TypeError,
'Invalid TagItem: Expected a "text string"',
);
assertThrows(
() => {
decodeCbor(Uint8Array.from([0b110_00001, 0b010_00000]));
},
TypeError,
'Invalid TagItem: Expected a "integer" or "float"',
);
});
Deno.test("decodeCbor() rejecting majorType 7 due to additional information", () => {
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b111_11100,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b111_11100)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b111_11101,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b111_11101)",
);
assertThrows(
() => {
decodeCbor(
Uint8Array.from([
0b111_11110,
...new Array(random(0, 64)).fill(0).map((_) => random(0, 256)),
]),
);
},
RangeError,
"Cannot decode value (0b111_11110)",
);
});