// 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)", ); });