Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(crypto): improve test coverage #4620

Merged
merged 9 commits into from
Apr 22, 2024
29 changes: 29 additions & 0 deletions crypto/_fnv/mod_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { assertEquals, assertThrows } from "../../assert/mod.ts";
import { fnv } from "./mod.ts";

Deno.test("fnv()", function () {
const encoder = new TextEncoder();
const input = encoder.encode("a");
const fixtures = [
["FNV32", new ArrayBuffer(4)],
["FNV32A", new ArrayBuffer(4)],
["FNV64", new ArrayBuffer(8)],
["FNV64A", new ArrayBuffer(8)],
] as const;
for (const [name, expected] of fixtures) {
assertEquals(fnv(name, input), expected);
}
});

Deno.test("fnv() throws when no data is provided", function () {
assertThrows(() => fnv("FNV32"), TypeError, "no data provided for hashing");
});

Deno.test("fnv() throws when an unsupported digest is provided", function () {
assertThrows(
() => fnv("FNV128", new Uint8Array()),
TypeError,
"unsupported fnv digest: FNV128",
);
});
69 changes: 68 additions & 1 deletion crypto/crypto_test.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i've tried by stubbing webCrypto to be able to get into the remaining else block, but no luck so far.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, that last else clause might be redundant. I'll handle this in a separate PR.

Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { assert, assertEquals, assertInstanceOf, fail } from "../assert/mod.ts";
import {
assert,
assertEquals,
assertInstanceOf,
assertRejects,
assertThrows,
fail,
} from "../assert/mod.ts";
import {
crypto as stdCrypto,
DIGEST_ALGORITHM_NAMES,
Expand Down Expand Up @@ -260,6 +267,66 @@ Deno.test("digest() keeps memory usage reasonable with many calls", async () =>
);
});

Deno.test("digest() throws on invalid input", async () => {
const inputString = "taking the hobbits to isengard";
const inputBytes = new TextEncoder().encode(inputString);

await assertRejects(
async () => await stdCrypto.subtle.digest("BLAKE2B", {} as Iterable<never>),
TypeError,
"data must be a BufferSource or [Async]Iterable<BufferSource>",
);

await assertRejects(
async () =>
await stdCrypto.subtle.digest(
"BLAKE2B",
(async function* () {
yield undefined;
})() as AsyncIterable<BufferSource>,
),
TypeError,
"data contained chunk of the wrong type",
);

await assertRejects(
async () =>
await stdCrypto.subtle.digest("BLAK" as DigestAlgorithmName, inputBytes),
DOMException,
"Unrecognized algorithm name",
);
});

Deno.test("digestSync() throws on invalid input", () => {
const inputString = "taking the hobbits to isengard";
const inputBytes = new TextEncoder().encode(inputString);

assertThrows(
() => stdCrypto.subtle.digestSync("BLAKE2B", {} as Iterable<never>),
TypeError,
"data must be a BufferSource or Iterable<BufferSource>",
);

assertThrows(
() =>
stdCrypto.subtle.digestSync(
"BLAKE2B",
(function* () {
yield undefined;
})() as Iterable<BufferSource>,
),
TypeError,
"data contained chunk of the wrong type",
);

assertThrows(
() =>
stdCrypto.subtle.digestSync("BLAK" as DigestAlgorithmName, inputBytes),
TypeError,
"unsupported algorithm",
);
});

// Simple periodic data, but the periods shouldn't line up with any block
// or chunk sizes.
const aboutAMeg = repeat(
Expand Down
20 changes: 20 additions & 0 deletions crypto/timing_safe_equal_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ Deno.test({
},
});

Deno.test({
name:
"timingSafeEqual() handles Uint8Array with different byte lengths (a > b)",
fn() {
const a = new Uint8Array([212, 213]);
const b = new Uint8Array([212]);
assert(!timingSafeEqual(a, b));
},
});

Deno.test({
name:
"timingSafeEqual() handles Uint8Array with different byte lengths (a < b)",
fn() {
const a = new Uint8Array([212]);
const b = new Uint8Array([212, 213]);
assert(!timingSafeEqual(a, b));
},
});

Deno.test({
name:
"timingSafeEqual() handles Uint8Array with different buffer sizes (a > b)",
Expand Down
27 changes: 25 additions & 2 deletions crypto/unstable_keystack_test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

import { assert, assertEquals } from "../assert/mod.ts";
import { assert, assertEquals, assertThrows } from "../assert/mod.ts";

import { KeyStack } from "./unstable_keystack.ts";

Deno.test({
name: "KeyStack() throws on empty keys",
fn() {
assertThrows(
() => new KeyStack([]),
TypeError,
"keys must contain at least one value",
);
},
});

Deno.test({
name: "keyStack.sign() handles single key",
async fn() {
Expand Down Expand Up @@ -223,11 +234,23 @@ Deno.test({
});

Deno.test({
name: "KeyStack() handles inspection",
name: "KeyStack() handles inspection in Deno",
fn() {
assertEquals(
Deno.inspect(new KeyStack(["abcdef"])),
`KeyStack { length: 1 }`,
);
},
});

Deno.test({
name: "KeyStack() handles inspection in Node",
async fn() {
const { inspect } = await import("node:util");

assertEquals(
inspect(new KeyStack(["abcdef"])),
`KeyStack { length: 1 }`,
);
},
});
4 changes: 2 additions & 2 deletions testing/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function fakeSetTimeout(
return setTimer(callback, delay, args, false);
}

function fakeClearTimeout(id?: number) {
function fakeClearTimeout(id?: unknown) {
if (!time) throw new TimeError("no fake time");
if (typeof id === "number" && dueNodes.has(id)) {
dueNodes.delete(id);
Expand All @@ -102,7 +102,7 @@ function fakeSetInterval(
return setTimer(callback, delay, args, true);
}

function fakeClearInterval(id?: number) {
function fakeClearInterval(id?: unknown) {
if (!time) throw new TimeError("no fake time");
if (typeof id === "number" && dueNodes.has(id)) {
dueNodes.delete(id);
Expand Down