2024-01-01 21:11:32 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2020-09-25 12:57:31 +00:00
|
|
|
import { delay } from "./delay.ts";
|
2023-07-14 05:03:05 +00:00
|
|
|
import {
|
|
|
|
assert,
|
2024-04-11 21:23:54 +00:00
|
|
|
assertEquals,
|
2023-07-14 05:03:05 +00:00
|
|
|
assertInstanceOf,
|
|
|
|
assertRejects,
|
|
|
|
assertStrictEquals,
|
2024-04-29 02:57:30 +00:00
|
|
|
} from "@std/assert";
|
|
|
|
import { assertSpyCalls, stub } from "@std/testing/mock";
|
2023-07-14 05:03:05 +00:00
|
|
|
|
|
|
|
// https://dom.spec.whatwg.org/#interface-AbortSignal
|
|
|
|
function assertIsDefaultAbortReason(reason: unknown) {
|
|
|
|
assertInstanceOf(reason, DOMException);
|
|
|
|
assertStrictEquals(reason.name, "AbortError");
|
|
|
|
}
|
2020-09-25 12:57:31 +00:00
|
|
|
|
2024-04-11 21:23:54 +00:00
|
|
|
Deno.test("delay()", async () => {
|
2020-09-25 12:57:31 +00:00
|
|
|
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);
|
|
|
|
});
|
2021-08-17 05:04:21 +00:00
|
|
|
|
2024-04-11 21:23:54 +00:00
|
|
|
Deno.test("delay() handles abort", async () => {
|
2021-08-17 05:04:21 +00:00
|
|
|
const start = new Date();
|
|
|
|
const abort = new AbortController();
|
|
|
|
const { signal } = abort;
|
|
|
|
const delayedPromise = delay(100, { signal });
|
|
|
|
setTimeout(() => abort.abort(), 0);
|
2023-07-14 05:03:05 +00:00
|
|
|
const cause = await assertRejects(() => delayedPromise);
|
2021-08-17 05:04:21 +00:00
|
|
|
const diff = new Date().getTime() - start.getTime();
|
|
|
|
assert(diff < 100);
|
2023-07-14 05:03:05 +00:00
|
|
|
assertIsDefaultAbortReason(cause);
|
|
|
|
});
|
|
|
|
|
2024-04-11 21:23:54 +00:00
|
|
|
Deno.test("delay() checks abort reason", async (ctx) => {
|
2023-07-14 05:03:05 +00:00
|
|
|
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);
|
|
|
|
});
|
2021-08-17 05:04:21 +00:00
|
|
|
});
|
|
|
|
|
2024-04-11 21:23:54 +00:00
|
|
|
Deno.test("delay() handles non-aborted signal", async () => {
|
2021-08-17 05:04:21 +00:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
|
2024-04-11 21:23:54 +00:00
|
|
|
Deno.test("delay() handles aborted signal after delay", async () => {
|
2021-08-17 05:04:21 +00:00
|
|
|
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);
|
|
|
|
});
|
2021-10-08 04:38:20 +00:00
|
|
|
|
2024-04-11 21:23:54 +00:00
|
|
|
Deno.test("delay() handles already aborted signal", async () => {
|
2021-10-08 04:38:20 +00:00
|
|
|
const start = new Date();
|
|
|
|
const abort = new AbortController();
|
|
|
|
abort.abort();
|
|
|
|
const { signal } = abort;
|
|
|
|
const delayedPromise = delay(100, { signal });
|
2023-07-14 05:03:05 +00:00
|
|
|
const cause = await assertRejects(() => delayedPromise);
|
2021-10-08 04:38:20 +00:00
|
|
|
const diff = new Date().getTime() - start.getTime();
|
|
|
|
assert(diff < 100);
|
2023-07-14 05:03:05 +00:00
|
|
|
assertIsDefaultAbortReason(cause);
|
2021-10-08 04:38:20 +00:00
|
|
|
});
|
2024-04-11 21:23:54 +00:00
|
|
|
|
|
|
|
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,
|
|
|
|
});
|