mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
408 lines
10 KiB
TypeScript
408 lines
10 KiB
TypeScript
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||
|
|
||
|
import { assertEquals, assertThrows } from "@std/assert";
|
||
|
import { concat } from "@std/bytes";
|
||
|
import { random } from "./_common_test.ts";
|
||
|
import { encodeCbor } from "./encode_cbor.ts";
|
||
|
import { CborTag } from "./tag.ts";
|
||
|
|
||
|
Deno.test("encodeCbor() encoding undefined", () => {
|
||
|
assertEquals(
|
||
|
encodeCbor(undefined),
|
||
|
new Uint8Array([0b111_10111]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding null", () => {
|
||
|
assertEquals(encodeCbor(null), new Uint8Array([0b111_10110]));
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding true", () => {
|
||
|
assertEquals(encodeCbor(true), new Uint8Array([0b111_10101]));
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding false", () => {
|
||
|
assertEquals(encodeCbor(false), new Uint8Array([0b111_10100]));
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding numbers as Uint", () => {
|
||
|
let num: number | bigint = random(0, 24);
|
||
|
assertEquals(encodeCbor(num), new Uint8Array([0b000_00000 + num]));
|
||
|
|
||
|
num = random(24, 2 ** 8);
|
||
|
assertEquals(encodeCbor(num), new Uint8Array([0b000_11000, num]));
|
||
|
|
||
|
num = random(2 ** 8, 2 ** 16);
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
new Uint8Array([0b000_11001, num >> 8 & 0xFF, num & 0xFF]),
|
||
|
);
|
||
|
|
||
|
num = random(2 ** 16, 2 ** 32);
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
new Uint8Array([
|
||
|
0b000_11010,
|
||
|
num >> 24 & 0xFF,
|
||
|
num >> 16 & 0xFF,
|
||
|
num >> 8 & 0xFF,
|
||
|
num & 0xFF,
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
// JavaScript fails at correctly bit-wising this many bits as a number.
|
||
|
num = BigInt(Number.MAX_SAFE_INTEGER);
|
||
|
assertEquals(
|
||
|
encodeCbor(Number.MAX_SAFE_INTEGER),
|
||
|
new Uint8Array(
|
||
|
[
|
||
|
0b000_11011,
|
||
|
num >> 56n & 0xFFn,
|
||
|
num >> 48n & 0xFFn,
|
||
|
num >> 40n & 0xFFn,
|
||
|
num >> 32n & 0xFFn,
|
||
|
num >> 24n & 0xFFn,
|
||
|
num >> 16n & 0xFFn,
|
||
|
num >> 8n & 0xFFn,
|
||
|
num & 0xFFn,
|
||
|
].map((x) => Number(x)),
|
||
|
),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding numbers as Int", () => {
|
||
|
const num = -random(1, 24); // -0 === 0
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
new Uint8Array([0b001_00000 + (-num - 1)]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding numbers as Float", () => {
|
||
|
const num = Math.random() * 2 ** 32;
|
||
|
const view = new DataView(new ArrayBuffer(8));
|
||
|
view.setFloat64(0, num);
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
concat([new Uint8Array([0b111_11011]), new Uint8Array(view.buffer)]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding bigints as Uint", () => {
|
||
|
let num = BigInt(random(0, 24));
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
new Uint8Array([0b000_00000 + Number(num)]),
|
||
|
);
|
||
|
|
||
|
num = BigInt(random(24, 2 ** 8));
|
||
|
assertEquals(encodeCbor(num), new Uint8Array([0b000_11000, Number(num)]));
|
||
|
|
||
|
num = BigInt(random(2 ** 8, 2 ** 16));
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
new Uint8Array([
|
||
|
0b000_11001,
|
||
|
Number(num >> 8n & 0xFFn),
|
||
|
Number(num & 0xFFn),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
num = BigInt(random(2 ** 16, 2 ** 32));
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
new Uint8Array([
|
||
|
0b000_11010,
|
||
|
Number(num >> 24n & 0xFFn),
|
||
|
Number(num >> 16n & 0xFFn),
|
||
|
Number(num >> 8n & 0xFFn),
|
||
|
Number(num & 0xFFn),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
num = BigInt(random(2 ** 32, 2 ** 64));
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
new Uint8Array([
|
||
|
0b000_11011,
|
||
|
Number(num >> 56n & 0xFFn),
|
||
|
Number(num >> 48n & 0xFFn),
|
||
|
Number(num >> 40n & 0xFFn),
|
||
|
Number(num >> 32n & 0xFFn),
|
||
|
Number(num >> 24n & 0xFFn),
|
||
|
Number(num >> 16n & 0xFFn),
|
||
|
Number(num >> 8n & 0xFFn),
|
||
|
Number(num & 0xFFn),
|
||
|
]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding bigints as Int", () => {
|
||
|
const num = -BigInt(random(1, 24)); // -0 === 0
|
||
|
assertEquals(
|
||
|
encodeCbor(num),
|
||
|
new Uint8Array([0b001_00000 + Number(-num - 1n)]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding strings", () => {
|
||
|
const decoder = new TextDecoder();
|
||
|
|
||
|
let bytes = new Uint8Array(random(0, 24)).map((_) => random(97, 123)); // Range: `a` - `z`
|
||
|
assertEquals(
|
||
|
encodeCbor(decoder.decode(bytes)),
|
||
|
new Uint8Array([0b011_00000 + bytes.length, ...bytes]),
|
||
|
);
|
||
|
|
||
|
bytes = new Uint8Array(random(24, 2 ** 8)).map((_) => random(97, 123)); // Range: `a` - `z`
|
||
|
assertEquals(
|
||
|
encodeCbor(decoder.decode(bytes)),
|
||
|
new Uint8Array([0b011_11000, bytes.length, ...bytes]),
|
||
|
);
|
||
|
|
||
|
bytes = new Uint8Array(random(2 ** 8, 2 ** 16)).map((_) => random(97, 123)); // Range: `a` - `z`
|
||
|
assertEquals(
|
||
|
encodeCbor(decoder.decode(bytes)),
|
||
|
new Uint8Array([
|
||
|
0b011_11001,
|
||
|
bytes.length >> 8 & 0xFF,
|
||
|
bytes.length & 0xFF,
|
||
|
...bytes,
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
bytes = new Uint8Array(random(2 ** 16, 2 ** 17)).map((_) => random(97, 123)); // Range: `a` - `z`
|
||
|
assertEquals(
|
||
|
encodeCbor(decoder.decode(bytes)),
|
||
|
new Uint8Array([
|
||
|
0b011_11010,
|
||
|
bytes.length >> 24 & 0xFF,
|
||
|
bytes.length >> 16 & 0xFF,
|
||
|
bytes.length >> 8 & 0xFF,
|
||
|
bytes.length & 0xFF,
|
||
|
...bytes,
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
// Can't test the next bracket up due to JavaScript limitations.
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding Uint8Arrays", () => {
|
||
|
let bytes = new Uint8Array(random(0, 24));
|
||
|
assertEquals(
|
||
|
encodeCbor(bytes),
|
||
|
new Uint8Array([0b010_00000 + bytes.length, ...bytes]),
|
||
|
);
|
||
|
|
||
|
bytes = new Uint8Array(random(24, 2 ** 8));
|
||
|
assertEquals(
|
||
|
encodeCbor(bytes),
|
||
|
new Uint8Array([0b010_11000, bytes.length, ...bytes]),
|
||
|
);
|
||
|
|
||
|
bytes = new Uint8Array(random(2 ** 8, 2 ** 16));
|
||
|
assertEquals(
|
||
|
encodeCbor(bytes),
|
||
|
new Uint8Array([
|
||
|
0b010_11001,
|
||
|
bytes.length >> 8 & 0xFF,
|
||
|
bytes.length & 0xFF,
|
||
|
...bytes,
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
bytes = new Uint8Array(random(2 ** 16, 2 ** 17));
|
||
|
assertEquals(
|
||
|
encodeCbor(bytes),
|
||
|
new Uint8Array([
|
||
|
0b010_11010,
|
||
|
bytes.length >> 24 & 0xFF,
|
||
|
bytes.length >> 16 & 0xFF,
|
||
|
bytes.length >> 8 & 0xFF,
|
||
|
bytes.length & 0xFF,
|
||
|
...bytes,
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
// Can't test the next bracket up due to JavaScript limitations.
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding Dates", () => {
|
||
|
const date = new Date();
|
||
|
assertEquals(
|
||
|
encodeCbor(date),
|
||
|
new Uint8Array([0b110_00001, ...encodeCbor(date.getTime() / 1000)]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding arrays", () => {
|
||
|
let array = new Array(random(0, 24)).fill(0);
|
||
|
assertEquals(
|
||
|
encodeCbor(array),
|
||
|
new Uint8Array([
|
||
|
0b100_00000 + array.length,
|
||
|
...array.map((x) => [...encodeCbor(x)]).flat(),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
array = new Array(random(24, 2 ** 8)).fill(0);
|
||
|
assertEquals(
|
||
|
encodeCbor(array),
|
||
|
new Uint8Array([
|
||
|
0b100_11000,
|
||
|
array.length,
|
||
|
...array.map((x) => [...encodeCbor(x)]).flat(),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
array = new Array(random(2 ** 8, 2 ** 16)).fill(0);
|
||
|
assertEquals(
|
||
|
encodeCbor(array),
|
||
|
new Uint8Array([
|
||
|
0b100_11001,
|
||
|
array.length >> 8 & 0xFF,
|
||
|
array.length & 0xFF,
|
||
|
...array.map((x) => [...encodeCbor(x)]).flat(),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
array = new Array(random(2 ** 16, 2 ** 17)).fill(0);
|
||
|
assertEquals(
|
||
|
encodeCbor(array),
|
||
|
new Uint8Array([
|
||
|
0b100_11010,
|
||
|
array.length >> 24 & 0xFF,
|
||
|
array.length >> 16 & 0xFF,
|
||
|
array.length >> 8 & 0xFF,
|
||
|
array.length & 0xFF,
|
||
|
...array.map((x) => [...encodeCbor(x)]).flat(),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
// Can't test the next bracket up due to JavaScript limitations.
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding objects", () => {
|
||
|
let pairs = random(0, 24);
|
||
|
let entries: [string, number][] = new Array(pairs).fill(0).map((
|
||
|
_,
|
||
|
i,
|
||
|
) => [i.toString(), i]);
|
||
|
assertEquals(
|
||
|
encodeCbor(Object.fromEntries(entries)),
|
||
|
new Uint8Array([
|
||
|
0b101_00000 + pairs,
|
||
|
...entries.map(([k, v]) => [...encodeCbor(k), ...encodeCbor(v)])
|
||
|
.flat(),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
pairs = random(24, 2 ** 8);
|
||
|
entries = new Array(pairs).fill(0).map((_, i) => [i.toString(), i]);
|
||
|
assertEquals(
|
||
|
encodeCbor(Object.fromEntries(entries)),
|
||
|
new Uint8Array([
|
||
|
0b101_11000,
|
||
|
pairs,
|
||
|
...entries.map(([k, v]) => [...encodeCbor(k), ...encodeCbor(v)])
|
||
|
.flat(),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
pairs = random(2 ** 8, 2 ** 16);
|
||
|
entries = new Array(pairs).fill(0).map((_, i) => [i.toString(), i]);
|
||
|
assertEquals(
|
||
|
encodeCbor(Object.fromEntries(entries)),
|
||
|
new Uint8Array([
|
||
|
0b101_11001,
|
||
|
pairs >> 8 & 0xFF,
|
||
|
pairs & 0xFF,
|
||
|
...entries.map(([k, v]) => [...encodeCbor(k), ...encodeCbor(v)])
|
||
|
.flat(),
|
||
|
]),
|
||
|
);
|
||
|
|
||
|
// Can't test the next two bracket up due to JavaScript limitations.
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() encoding CborTag()", () => {
|
||
|
const bytes = new Uint8Array(random(0, 24)).map((_) => random(0, 256));
|
||
|
assertEquals(
|
||
|
encodeCbor(new CborTag(2, bytes)),
|
||
|
new Uint8Array([0b110_00010, 0b010_00000 + bytes.length, ...bytes]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() rejecting numbers as Uint", () => {
|
||
|
const num = 2 ** 65;
|
||
|
assertThrows(
|
||
|
() => {
|
||
|
encodeCbor(num);
|
||
|
},
|
||
|
RangeError,
|
||
|
`Cannot encode number: It (${num}) exceeds 2 ** 64 - 1`,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() rejecting numbers as Int", () => {
|
||
|
const num = -(2 ** 65);
|
||
|
assertThrows(
|
||
|
() => {
|
||
|
encodeCbor(num);
|
||
|
},
|
||
|
RangeError,
|
||
|
`Cannot encode number: It (${num}) exceeds -2 ** 64 - 1`,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() rejecting bigints as Uint", () => {
|
||
|
const num = 2n ** 65n;
|
||
|
assertThrows(
|
||
|
() => {
|
||
|
encodeCbor(num);
|
||
|
},
|
||
|
RangeError,
|
||
|
`Cannot encode bigint: It (${num}) exceeds 2 ** 64 - 1`,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() rejecting bigints as Int", () => {
|
||
|
const num = -(2n ** 65n);
|
||
|
assertThrows(
|
||
|
() => {
|
||
|
encodeCbor(num);
|
||
|
},
|
||
|
RangeError,
|
||
|
`Cannot encode bigint: It (${num}) exceeds -2 ** 64 - 1`,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
Deno.test("encodeCbor() rejecting CborTag()", () => {
|
||
|
let num = -5;
|
||
|
assertThrows(
|
||
|
() => {
|
||
|
encodeCbor(
|
||
|
new CborTag(
|
||
|
num,
|
||
|
new Uint8Array(random(0, 24)).map((_) => random(0, 256)),
|
||
|
),
|
||
|
);
|
||
|
},
|
||
|
RangeError,
|
||
|
`Cannot encode Tag Item: Tag Number (${num}) is less than zero`,
|
||
|
);
|
||
|
num = 2 ** 65;
|
||
|
assertThrows(
|
||
|
() => {
|
||
|
encodeCbor(
|
||
|
new CborTag(
|
||
|
num,
|
||
|
new Uint8Array(random(0, 24)).map((_) => random(0, 256)),
|
||
|
),
|
||
|
);
|
||
|
},
|
||
|
RangeError,
|
||
|
`Cannot encode Tag Item: Tag Number (${num}) exceeds 2 ** 64 - 1`,
|
||
|
);
|
||
|
});
|