std/async/delay_test.ts
2024-04-29 11:57:30 +09:00

140 lines
4.3 KiB
TypeScript

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { delay } from "./delay.ts";
import {
assert,
assertEquals,
assertInstanceOf,
assertRejects,
assertStrictEquals,
} from "@std/assert";
import { assertSpyCalls, stub } from "@std/testing/mock";
// https://dom.spec.whatwg.org/#interface-AbortSignal
function assertIsDefaultAbortReason(reason: unknown) {
assertInstanceOf(reason, DOMException);
assertStrictEquals(reason.name, "AbortError");
}
Deno.test("delay()", async () => {
const start = new Date();
const delayedPromise = delay(100);
const result = await delayedPromise;
const diff = new Date().getTime() - start.getTime();
assert(result === undefined);
assert(diff >= 100);
});
Deno.test("delay() handles abort", async () => {
const start = new Date();
const abort = new AbortController();
const { signal } = abort;
const delayedPromise = delay(100, { signal });
setTimeout(() => abort.abort(), 0);
const cause = await assertRejects(() => delayedPromise);
const diff = new Date().getTime() - start.getTime();
assert(diff < 100);
assertIsDefaultAbortReason(cause);
});
Deno.test("delay() checks abort reason", async (ctx) => {
async function assertRejectsReason(reason: unknown) {
const start = new Date();
const abort = new AbortController();
const { signal } = abort;
const delayedPromise = delay(100, { signal });
setTimeout(() => abort.abort(reason), 0);
const cause = await assertRejects(() => delayedPromise);
const diff = new Date().getTime() - start.getTime();
assert(diff < 100);
assertStrictEquals(cause, reason);
}
await ctx.step("not-undefined values", async () => {
await Promise.all([
null,
new Error("Timeout cancelled"),
new DOMException("Timeout cancelled", "AbortError"),
new DOMException("The signal has been aborted", "AbortError"),
].map(assertRejectsReason));
});
await ctx.step("undefined", async () => {
const start = new Date();
const abort = new AbortController();
const { signal } = abort;
const delayedPromise = delay(100, { signal });
setTimeout(() => abort.abort(), 0);
const cause = await assertRejects(() => delayedPromise);
const diff = new Date().getTime() - start.getTime();
assert(diff < 100);
assertIsDefaultAbortReason(cause);
});
});
Deno.test("delay() handles non-aborted signal", async () => {
const start = new Date();
const abort = new AbortController();
const { signal } = abort;
const delayedPromise = delay(100, { signal });
const result = await delayedPromise;
const diff = new Date().getTime() - start.getTime();
assert(result === undefined);
assert(diff >= 100);
});
Deno.test("delay() handles aborted signal after delay", async () => {
const start = new Date();
const abort = new AbortController();
const { signal } = abort;
const delayedPromise = delay(100, { signal });
const result = await delayedPromise;
abort.abort();
const diff = new Date().getTime() - start.getTime();
assert(result === undefined);
assert(diff >= 100);
});
Deno.test("delay() handles already aborted signal", async () => {
const start = new Date();
const abort = new AbortController();
abort.abort();
const { signal } = abort;
const delayedPromise = delay(100, { signal });
const cause = await assertRejects(() => delayedPromise);
const diff = new Date().getTime() - start.getTime();
assert(diff < 100);
assertIsDefaultAbortReason(cause);
});
Deno.test("delay() handles persitent option", async () => {
using unrefTimer = stub(Deno, "unrefTimer");
await delay(100, { persistent: false });
assertSpyCalls(unrefTimer, 1);
});
Deno.test("delay() handles persistent option with reference error", async () => {
using unrefTimer = stub(Deno, "unrefTimer", () => {
throw new ReferenceError();
});
await delay(100, { persistent: false });
assertSpyCalls(unrefTimer, 1);
});
Deno.test({
name: "delay() handles persistent option with error",
async fn() {
using unrefTimer = stub(Deno, "unrefTimer", () => {
throw new Error("Error!");
});
try {
await delay(100, { persistent: false });
} catch (e) {
assert(e instanceof Error);
assertEquals(e.message, "Error!");
assertSpyCalls(unrefTimer, 1);
}
},
sanitizeResources: false,
sanitizeOps: false,
});