summaryrefslogtreecommitdiff
path: root/tests/unit_node
diff options
context:
space:
mode:
authorhaturau <135221985+haturatu@users.noreply.github.com>2024-11-20 01:20:47 +0900
committerGitHub <noreply@github.com>2024-11-20 01:20:47 +0900
commit85719a67e59c7aa45bead26e4942d7df8b1b42d4 (patch)
treeface0aecaac53e93ce2f23b53c48859bcf1a36ec /tests/unit_node
parent67697bc2e4a62a9670699fd18ad0dd8efc5bd955 (diff)
parent186b52731c6bb326c4d32905c5e732d082e83465 (diff)
Merge branch 'denoland:main' into main
Diffstat (limited to 'tests/unit_node')
-rw-r--r--tests/unit_node/_fs/_fs_stat_test.ts7
-rw-r--r--tests/unit_node/child_process_test.ts16
-rw-r--r--tests/unit_node/crypto/crypto_key_test.ts44
-rw-r--r--tests/unit_node/crypto/crypto_misc_test.ts10
-rw-r--r--tests/unit_node/fetch_test.ts18
-rw-r--r--tests/unit_node/fs_test.ts77
-rw-r--r--tests/unit_node/http2_test.ts5
-rw-r--r--tests/unit_node/http_test.ts108
-rw-r--r--tests/unit_node/perf_hooks_test.ts22
-rw-r--r--tests/unit_node/process_test.ts39
-rw-r--r--tests/unit_node/timers_test.ts151
-rw-r--r--tests/unit_node/tls_test.ts28
-rw-r--r--tests/unit_node/util_test.ts5
-rw-r--r--tests/unit_node/zlib_test.ts20
14 files changed, 516 insertions, 34 deletions
diff --git a/tests/unit_node/_fs/_fs_stat_test.ts b/tests/unit_node/_fs/_fs_stat_test.ts
index 02c620e2d..e42aa34a9 100644
--- a/tests/unit_node/_fs/_fs_stat_test.ts
+++ b/tests/unit_node/_fs/_fs_stat_test.ts
@@ -18,9 +18,11 @@ export function assertStats(actual: Stats, expected: Deno.FileInfo) {
assertEquals(actual.atime?.getTime(), expected.atime?.getTime());
assertEquals(actual.mtime?.getTime(), expected.mtime?.getTime());
assertEquals(actual.birthtime?.getTime(), expected.birthtime?.getTime());
+ assertEquals(actual.ctime?.getTime(), expected.ctime?.getTime());
assertEquals(actual.atimeMs ?? undefined, expected.atime?.getTime());
assertEquals(actual.mtimeMs ?? undefined, expected.mtime?.getTime());
assertEquals(actual.birthtimeMs ?? undefined, expected.birthtime?.getTime());
+ assertEquals(actual.ctimeMs ?? undefined, expected.ctime?.getTime());
assertEquals(actual.isFile(), expected.isFile);
assertEquals(actual.isDirectory(), expected.isDirectory);
assertEquals(actual.isSymbolicLink(), expected.isSymlink);
@@ -49,6 +51,7 @@ export function assertStatsBigInt(
assertEquals(actual.atime?.getTime(), expected.atime?.getTime());
assertEquals(actual.mtime?.getTime(), expected.mtime?.getTime());
assertEquals(actual.birthtime?.getTime(), expected.birthtime?.getTime());
+ assertEquals(actual.ctime?.getTime(), expected.ctime?.getTime());
assertEquals(
actual.atimeMs === null ? undefined : Number(actual.atimeMs),
expected.atime?.getTime(),
@@ -61,6 +64,10 @@ export function assertStatsBigInt(
actual.birthtimeMs === null ? undefined : Number(actual.birthtimeMs),
expected.birthtime?.getTime(),
);
+ assertEquals(
+ actual.ctimeMs === null ? undefined : Number(actual.ctimeMs),
+ expected.ctime?.getTime(),
+ );
assertEquals(actual.atimeNs === null, actual.atime === null);
assertEquals(actual.mtimeNs === null, actual.mtime === null);
assertEquals(actual.birthtimeNs === null, actual.birthtime === null);
diff --git a/tests/unit_node/child_process_test.ts b/tests/unit_node/child_process_test.ts
index f776fa4ac..0ea3c46cf 100644
--- a/tests/unit_node/child_process_test.ts
+++ b/tests/unit_node/child_process_test.ts
@@ -1045,3 +1045,19 @@ Deno.test(async function sendAfterClosedThrows() {
await timeout.promise;
});
+
+Deno.test(async function noWarningsFlag() {
+ const code = ``;
+ const file = await Deno.makeTempFile();
+ await Deno.writeTextFile(file, code);
+ const timeout = withTimeout<void>();
+ const child = CP.fork(file, [], {
+ execArgv: ["--no-warnings"],
+ stdio: ["inherit", "inherit", "inherit", "ipc"],
+ });
+ child.on("close", () => {
+ timeout.resolve();
+ });
+
+ await timeout.promise;
+});
diff --git a/tests/unit_node/crypto/crypto_key_test.ts b/tests/unit_node/crypto/crypto_key_test.ts
index 7995ce5d3..5d206acc7 100644
--- a/tests/unit_node/crypto/crypto_key_test.ts
+++ b/tests/unit_node/crypto/crypto_key_test.ts
@@ -656,3 +656,47 @@ z6TExWlQMjt66nV7R8cRAkzmABrG+NW3e8Zpac7Lkuv+zu0S+K7c
assertEquals(publicKey.type, "public");
assertEquals(publicKey.asymmetricKeyType, "rsa");
});
+
+// https://github.com/denoland/deno/issues/26188
+Deno.test("generateKeyPair large pem", function () {
+ const passphrase = "mypassphrase";
+ const cipher = "aes-256-cbc";
+ const modulusLength = 4096;
+
+ generateKeyPairSync("rsa", {
+ modulusLength,
+ publicKeyEncoding: {
+ type: "spki",
+ format: "pem",
+ },
+ privateKeyEncoding: {
+ type: "pkcs8",
+ format: "pem",
+ cipher,
+ passphrase,
+ },
+ });
+});
+
+Deno.test("generateKeyPair promisify", async () => {
+ const passphrase = "mypassphrase";
+ const cipher = "aes-256-cbc";
+ const modulusLength = 4096;
+
+ const { privateKey, publicKey } = await promisify(generateKeyPair)("rsa", {
+ modulusLength,
+ publicKeyEncoding: {
+ type: "spki",
+ format: "pem",
+ },
+ privateKeyEncoding: {
+ type: "pkcs8",
+ format: "pem",
+ cipher,
+ passphrase,
+ },
+ });
+
+ assert(publicKey.startsWith("-----BEGIN PUBLIC KEY-----"));
+ assert(privateKey.startsWith("-----BEGIN PRIVATE KEY-----"));
+});
diff --git a/tests/unit_node/crypto/crypto_misc_test.ts b/tests/unit_node/crypto/crypto_misc_test.ts
index 47a48b1bf..007009339 100644
--- a/tests/unit_node/crypto/crypto_misc_test.ts
+++ b/tests/unit_node/crypto/crypto_misc_test.ts
@@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-import { randomFillSync, randomUUID } from "node:crypto";
+import { randomFillSync, randomUUID, timingSafeEqual } from "node:crypto";
+import { Buffer } from "node:buffer";
import { assert, assertEquals } from "../../unit/test_util.ts";
import { assertNotEquals } from "@std/assert";
@@ -28,3 +29,10 @@ Deno.test("[node/crypto.randomFillSync] array buffer view", () => {
assertEquals(buf.subarray(0, 8), new Uint8Array(8));
assertEquals(buf.subarray(24, 32), new Uint8Array(8));
});
+
+Deno.test("[node/crypto.timingSafeEqual] compares equal Buffer with different byteOffset", () => {
+ const a = Buffer.from([212, 213]);
+ const b = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 212, 213]).subarray(8);
+
+ assert(timingSafeEqual(a, b));
+});
diff --git a/tests/unit_node/fetch_test.ts b/tests/unit_node/fetch_test.ts
new file mode 100644
index 000000000..399d6052a
--- /dev/null
+++ b/tests/unit_node/fetch_test.ts
@@ -0,0 +1,18 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+import { assertEquals } from "@std/assert";
+import { createReadStream } from "node:fs";
+
+Deno.test("fetch node stream", async () => {
+ const file = createReadStream("tests/testdata/assets/fixture.json");
+
+ const response = await fetch("http://localhost:4545/echo_server", {
+ method: "POST",
+ body: file,
+ });
+
+ assertEquals(
+ await response.text(),
+ await Deno.readTextFile("tests/testdata/assets/fixture.json"),
+ );
+});
diff --git a/tests/unit_node/fs_test.ts b/tests/unit_node/fs_test.ts
index 2d1465aec..631608d7c 100644
--- a/tests/unit_node/fs_test.ts
+++ b/tests/unit_node/fs_test.ts
@@ -1,11 +1,13 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-import { assert, assertEquals, assertThrows } from "@std/assert";
+/// <reference lib="deno.ns" />
+import { assert, assertEquals, assertRejects, assertThrows } from "@std/assert";
import { join } from "node:path";
import { tmpdir } from "node:os";
import {
closeSync,
constants,
+ copyFileSync,
createWriteStream,
existsSync,
lstatSync,
@@ -20,9 +22,11 @@ import {
} from "node:fs";
import {
constants as fsPromiseConstants,
+ copyFile,
cp,
FileHandle,
open,
+ stat,
writeFile,
} from "node:fs/promises";
import process from "node:process";
@@ -121,6 +125,48 @@ Deno.test(
);
Deno.test(
+ "[node/fs statSync] throw error with path information",
+ () => {
+ const file = "non-exist-file";
+ const fileUrl = new URL(file, import.meta.url);
+
+ assertThrows(() => {
+ statSync(file);
+ }, "Error: ENOENT: no such file or directory, stat 'non-exist-file'");
+
+ assertThrows(() => {
+ statSync(fileUrl);
+ }, `Error: ENOENT: no such file or directory, stat '${fileUrl.pathname}'`);
+ },
+);
+
+Deno.test(
+ "[node/fs/promises stat] throw error with path information",
+ async () => {
+ const file = "non-exist-file";
+ const fileUrl = new URL(file, import.meta.url);
+
+ try {
+ await stat(file);
+ } catch (error: unknown) {
+ assertEquals(
+ `${error}`,
+ "Error: ENOENT: no such file or directory, stat 'non-exist-file'",
+ );
+ }
+
+ try {
+ await stat(fileUrl);
+ } catch (error: unknown) {
+ assertEquals(
+ `${error}`,
+ `Error: ENOENT: no such file or directory, stat '${fileUrl.pathname}'`,
+ );
+ }
+ },
+);
+
+Deno.test(
"[node/fs/promises cp] copy file",
async () => {
const src = mkdtempSync(join(tmpdir(), "foo-")) + "/test.txt";
@@ -212,3 +258,32 @@ Deno.test("[node/fs] readSync works", () => {
assertEquals(bytesRead, 12);
closeSync(fd!);
});
+
+Deno.test("[node/fs] copyFile COPYFILE_EXCL works", async () => {
+ const dir = mkdtempSync(join(tmpdir(), "foo-"));
+ const src = join(dir, "src.txt");
+ const dest = join(dir, "dest.txt");
+ await writeFile(src, "");
+ await copyFile(src, dest, fsPromiseConstants.COPYFILE_EXCL);
+ assert(existsSync(dest));
+ await assertRejects(() =>
+ copyFile(src, dest, fsPromiseConstants.COPYFILE_EXCL)
+ );
+ const dest2 = join(dir, "dest2.txt");
+ copyFileSync(src, dest2, fsPromiseConstants.COPYFILE_EXCL);
+ assert(existsSync(dest2));
+ assertThrows(() =>
+ copyFileSync(src, dest2, fsPromiseConstants.COPYFILE_EXCL)
+ );
+});
+
+Deno.test("[node/fs] statSync throws ENOENT for invalid path containing colon in it", () => {
+ // deno-lint-ignore no-explicit-any
+ const err: any = assertThrows(() => {
+ // Note: Deno.stat throws ERROR_INVALID_NAME (os error 123) instead of
+ // ERROR_FILE_NOT_FOUND (os error 2) on windows. This case checks that
+ // ERROR_INVALID_NAME is mapped to ENOENT correctly on node compat layer.
+ statSync("jsr:@std/assert");
+ });
+ assertEquals(err.code, "ENOENT");
+});
diff --git a/tests/unit_node/http2_test.ts b/tests/unit_node/http2_test.ts
index 7473a487a..c540c90f7 100644
--- a/tests/unit_node/http2_test.ts
+++ b/tests/unit_node/http2_test.ts
@@ -10,6 +10,11 @@ import * as net from "node:net";
import { assert, assertEquals } from "@std/assert";
import { curlRequest } from "../unit/test_util.ts";
+// Increase the timeout for the auto select family to avoid flakiness
+net.setDefaultAutoSelectFamilyAttemptTimeout(
+ net.getDefaultAutoSelectFamilyAttemptTimeout() * 30,
+);
+
for (const url of ["http://localhost:4246", "https://localhost:4247"]) {
Deno.test(`[node/http2 client] ${url}`, {
ignore: Deno.build.os === "windows",
diff --git a/tests/unit_node/http_test.ts b/tests/unit_node/http_test.ts
index f85b1466b..2b3b8f509 100644
--- a/tests/unit_node/http_test.ts
+++ b/tests/unit_node/http_test.ts
@@ -3,10 +3,14 @@
// deno-lint-ignore-file no-console
import EventEmitter from "node:events";
-import http, { type RequestOptions, type ServerResponse } from "node:http";
+import http, {
+ IncomingMessage,
+ type RequestOptions,
+ ServerResponse,
+} from "node:http";
import url from "node:url";
import https from "node:https";
-import net from "node:net";
+import net, { Socket } from "node:net";
import fs from "node:fs";
import { text } from "node:stream/consumers";
@@ -1143,6 +1147,34 @@ Deno.test("[node/http] ServerResponse appendHeader set-cookie", async () => {
await promise;
});
+Deno.test("[node/http] ServerResponse header names case insensitive", async () => {
+ const { promise, resolve } = Promise.withResolvers<void>();
+ const server = http.createServer((_req, res) => {
+ res.setHeader("Content-Length", "12345");
+ res.removeHeader("content-length");
+ assertEquals(res.getHeader("Content-Length"), undefined);
+ assert(!res.hasHeader("Content-Length"));
+ res.appendHeader("content-length", "12345");
+ res.removeHeader("Content-Length");
+ assertEquals(res.getHeader("content-length"), undefined);
+ assert(!res.hasHeader("content-length"));
+ res.end("Hello World");
+ });
+
+ server.listen(async () => {
+ const { port } = server.address() as { port: number };
+ const res = await fetch(`http://localhost:${port}`);
+ assertEquals(res.headers.get("Content-Length"), null);
+ assertEquals(res.headers.get("content-length"), null);
+ assertEquals(await res.text(), "Hello World");
+ server.close(() => {
+ resolve();
+ });
+ });
+
+ await promise;
+});
+
Deno.test("[node/http] IncomingMessage override", () => {
const req = new http.IncomingMessage(new net.Socket());
// https://github.com/dougmoscrop/serverless-http/blob/3aaa6d0fe241109a8752efb011c242d249f32368/lib/request.js#L20-L30
@@ -1672,3 +1704,75 @@ Deno.test("[node/http] upgraded socket closes when the server closed without clo
await clientSocketClosed.promise;
await serverProcessClosed.promise;
});
+
+// deno-lint-ignore require-await
+Deno.test("[node/http] ServerResponse.call()", async () => {
+ function Wrapper(this: unknown, req: IncomingMessage) {
+ ServerResponse.call(this, req);
+ }
+ Object.setPrototypeOf(Wrapper.prototype, ServerResponse.prototype);
+
+ // deno-lint-ignore no-explicit-any
+ const wrapper = new (Wrapper as any)(new IncomingMessage(new Socket()));
+
+ assert(wrapper instanceof ServerResponse);
+});
+
+Deno.test("[node/http] ServerResponse _header", async () => {
+ const { promise, resolve } = Promise.withResolvers<void>();
+ const server = http.createServer((_req, res) => {
+ assert(Object.hasOwn(res, "_header"));
+ res.end();
+ });
+
+ server.listen(async () => {
+ const { port } = server.address() as { port: number };
+ const res = await fetch(`http://localhost:${port}`);
+ await res.body?.cancel();
+ server.close(() => {
+ resolve();
+ });
+ });
+
+ await promise;
+});
+
+Deno.test("[node/http] ServerResponse connection", async () => {
+ const { promise, resolve } = Promise.withResolvers<void>();
+ const server = http.createServer((_req, res) => {
+ assert(Object.hasOwn(res, "connection"));
+ assert(res.connection instanceof Socket);
+ res.end();
+ });
+
+ server.listen(async () => {
+ const { port } = server.address() as { port: number };
+ const res = await fetch(`http://localhost:${port}`);
+ await res.body?.cancel();
+ server.close(() => {
+ resolve();
+ });
+ });
+
+ await promise;
+});
+
+Deno.test("[node/http] ServerResponse socket", async () => {
+ const { promise, resolve } = Promise.withResolvers<void>();
+ const server = http.createServer((_req, res) => {
+ assert(Object.hasOwn(res, "socket"));
+ assert(res.socket instanceof Socket);
+ res.end();
+ });
+
+ server.listen(async () => {
+ const { port } = server.address() as { port: number };
+ const res = await fetch(`http://localhost:${port}`);
+ await res.body?.cancel();
+ server.close(() => {
+ resolve();
+ });
+ });
+
+ await promise;
+});
diff --git a/tests/unit_node/perf_hooks_test.ts b/tests/unit_node/perf_hooks_test.ts
index d5b900041..83d006222 100644
--- a/tests/unit_node/perf_hooks_test.ts
+++ b/tests/unit_node/perf_hooks_test.ts
@@ -1,7 +1,11 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import * as perfHooks from "node:perf_hooks";
-import { performance, PerformanceObserver } from "node:perf_hooks";
-import { assertEquals, assertThrows } from "@std/assert";
+import {
+ monitorEventLoopDelay,
+ performance,
+ PerformanceObserver,
+} from "node:perf_hooks";
+import { assert, assertEquals, assertThrows } from "@std/assert";
Deno.test({
name: "[perf_hooks] performance",
@@ -68,3 +72,17 @@ Deno.test("[perf_hooks]: eventLoopUtilization", () => {
assertEquals(typeof obj.active, "number");
assertEquals(typeof obj.utilization, "number");
});
+
+Deno.test("[perf_hooks]: monitorEventLoopDelay", async () => {
+ const e = monitorEventLoopDelay();
+ assertEquals(e.count, 0);
+ e.enable();
+
+ await new Promise((resolve) => setTimeout(resolve, 100));
+
+ assert(e.min > 0);
+ assert(e.minBigInt > 0n);
+ assert(e.count > 0);
+
+ e.disable();
+});
diff --git a/tests/unit_node/process_test.ts b/tests/unit_node/process_test.ts
index 0e0f169d6..49de2dce1 100644
--- a/tests/unit_node/process_test.ts
+++ b/tests/unit_node/process_test.ts
@@ -25,7 +25,6 @@ import {
assertThrows,
fail,
} from "@std/assert";
-import { assertSpyCall, assertSpyCalls, spy } from "@std/testing/mock";
import { stripAnsiCode } from "@std/fmt/colors";
import * as path from "@std/path";
import { delay } from "@std/async/delay";
@@ -239,33 +238,6 @@ Deno.test({
},
});
-Deno.test({
- name: "process.on - ignored signals on windows",
- ignore: Deno.build.os !== "windows",
- fn() {
- const ignoredSignals = ["SIGHUP", "SIGUSR1", "SIGUSR2"];
-
- for (const signal of ignoredSignals) {
- using consoleSpy = spy(console, "warn");
- const handler = () => {};
- process.on(signal, handler);
- process.off(signal, handler);
- assertSpyCall(consoleSpy, 0, {
- args: [`Ignoring signal "${signal}" on Windows`],
- });
- }
-
- {
- using consoleSpy = spy(console, "warn");
- const handler = () => {};
- process.on("SIGTERM", handler);
- process.off("SIGTERM", handler);
- // No warning is made for SIGTERM
- assertSpyCalls(consoleSpy, 0);
- }
- },
-});
-
Deno.test(
{ permissions: { run: true, read: true } },
async function processKill() {
@@ -1175,3 +1147,14 @@ Deno.test("process.cpuUsage()", () => {
assert(typeof cpuUsage.user === "number");
assert(typeof cpuUsage.system === "number");
});
+
+Deno.test("process.stdout.columns writable", () => {
+ process.stdout.columns = 80;
+ assertEquals(process.stdout.columns, 80);
+});
+
+Deno.test("getBuiltinModule", () => {
+ assert(process.getBuiltinModule("fs"));
+ assert(process.getBuiltinModule("node:fs"));
+ assertEquals(process.getBuiltinModule("something"), undefined);
+});
diff --git a/tests/unit_node/timers_test.ts b/tests/unit_node/timers_test.ts
index 868ba21d6..ddc6dc0d8 100644
--- a/tests/unit_node/timers_test.ts
+++ b/tests/unit_node/timers_test.ts
@@ -3,6 +3,7 @@
import { assert, fail } from "@std/assert";
import * as timers from "node:timers";
import * as timersPromises from "node:timers/promises";
+import { assertEquals } from "@std/assert";
Deno.test("[node/timers setTimeout]", () => {
{
@@ -108,3 +109,153 @@ Deno.test("[node/timers setImmediate returns Immediate object]", () => {
imm.hasRef();
clearImmediate(imm);
});
+
+Deno.test({
+ name: "setInterval yields correct values at expected intervals",
+ async fn() {
+ // Test configuration
+ const CONFIG = {
+ expectedValue: 42,
+ intervalMs: 100,
+ iterations: 3,
+ tolerancePercent: 50,
+ };
+
+ const { setInterval } = timersPromises;
+ const results: Array<{ value: number; timestamp: number }> = [];
+ const startTime = Date.now();
+
+ const iterator = setInterval(CONFIG.intervalMs, CONFIG.expectedValue);
+
+ for await (const value of iterator) {
+ results.push({
+ value,
+ timestamp: Date.now(),
+ });
+ if (results.length === CONFIG.iterations) {
+ break;
+ }
+ }
+
+ const values = results.map((r) => r.value);
+ assertEquals(
+ values,
+ Array(CONFIG.iterations).fill(CONFIG.expectedValue),
+ `Each iteration should yield ${CONFIG.expectedValue}`,
+ );
+
+ const intervals = results.slice(1).map((result, index) => ({
+ interval: result.timestamp - results[index].timestamp,
+ iterationNumber: index + 1,
+ }));
+
+ const toleranceMs = (CONFIG.tolerancePercent / 100) * CONFIG.intervalMs;
+ const expectedRange = {
+ min: CONFIG.intervalMs - toleranceMs,
+ max: CONFIG.intervalMs + toleranceMs,
+ };
+
+ intervals.forEach(({ interval, iterationNumber }) => {
+ const isWithinTolerance = interval >= expectedRange.min &&
+ interval <= expectedRange.max;
+
+ assertEquals(
+ isWithinTolerance,
+ true,
+ `Iteration ${iterationNumber}: Interval ${interval}ms should be within ` +
+ `${expectedRange.min}ms and ${expectedRange.max}ms ` +
+ `(${CONFIG.tolerancePercent}% tolerance of ${CONFIG.intervalMs}ms)`,
+ );
+ });
+
+ const totalDuration = results[results.length - 1].timestamp - startTime;
+ const expectedDuration = CONFIG.intervalMs * CONFIG.iterations;
+ const isDurationReasonable =
+ totalDuration >= (expectedDuration - toleranceMs) &&
+ totalDuration <= (expectedDuration + toleranceMs);
+
+ assertEquals(
+ isDurationReasonable,
+ true,
+ `Total duration ${totalDuration}ms should be close to ${expectedDuration}ms ` +
+ `(within ${toleranceMs}ms tolerance)`,
+ );
+
+ const timestamps = results.map((r) => r.timestamp);
+ const areTimestampsOrdered = timestamps.every((timestamp, i) =>
+ i === 0 || timestamp > timestamps[i - 1]
+ );
+
+ assertEquals(
+ areTimestampsOrdered,
+ true,
+ "Timestamps should be strictly increasing",
+ );
+ },
+});
+
+Deno.test({
+ name: "setInterval with AbortSignal stops after expected duration",
+ async fn() {
+ const INTERVAL_MS = 500;
+ const TOTAL_DURATION_MS = 3000;
+ const TOLERANCE_MS = 500;
+
+ const abortController = new AbortController();
+ const { setInterval } = timersPromises;
+
+ // Set up abort after specified duration
+ const abortTimeout = timers.setTimeout(() => {
+ abortController.abort();
+ }, TOTAL_DURATION_MS);
+
+ // Track iterations and timing
+ const startTime = Date.now();
+ const iterations: number[] = [];
+
+ try {
+ for await (
+ const _timestamp of setInterval(INTERVAL_MS, undefined, {
+ signal: abortController.signal,
+ })
+ ) {
+ iterations.push(Date.now() - startTime);
+ }
+ } catch (error) {
+ if (error instanceof Error && error.name !== "AbortError") {
+ throw error;
+ }
+ } finally {
+ timers.clearTimeout(abortTimeout);
+ }
+
+ // Validate timing
+ const totalDuration = iterations[iterations.length - 1];
+ const isWithinTolerance =
+ totalDuration >= (TOTAL_DURATION_MS - TOLERANCE_MS) &&
+ totalDuration <= (TOTAL_DURATION_MS + TOLERANCE_MS);
+
+ assertEquals(
+ isWithinTolerance,
+ true,
+ `Total duration ${totalDuration}ms should be within ±${TOLERANCE_MS}ms of ${TOTAL_DURATION_MS}ms`,
+ );
+
+ // Validate interval consistency
+ const intervalDeltas = iterations.slice(1).map((time, i) =>
+ time - iterations[i]
+ );
+
+ intervalDeltas.forEach((delta, i) => {
+ const isIntervalValid = delta >= (INTERVAL_MS - 50) &&
+ delta <= (INTERVAL_MS + 50);
+ assertEquals(
+ isIntervalValid,
+ true,
+ `Interval ${
+ i + 1
+ } duration (${delta}ms) should be within ±50ms of ${INTERVAL_MS}ms`,
+ );
+ });
+ },
+});
diff --git a/tests/unit_node/tls_test.ts b/tests/unit_node/tls_test.ts
index 93eacd5ec..43d6205b0 100644
--- a/tests/unit_node/tls_test.ts
+++ b/tests/unit_node/tls_test.ts
@@ -229,3 +229,31 @@ Deno.test("tls.rootCertificates is not empty", () => {
(tls.rootCertificates as string[]).push("new cert");
}, TypeError);
});
+
+Deno.test("TLSSocket.alpnProtocol is set for client", async () => {
+ const listener = Deno.listenTls({
+ hostname: "localhost",
+ port: 0,
+ key,
+ cert,
+ alpnProtocols: ["a"],
+ });
+ const outgoing = tls.connect({
+ host: "::1",
+ servername: "localhost",
+ port: listener.addr.port,
+ ALPNProtocols: ["a"],
+ secureContext: {
+ ca: rootCaCert,
+ // deno-lint-ignore no-explicit-any
+ } as any,
+ });
+
+ const conn = await listener.accept();
+ const handshake = await conn.handshake();
+ assertEquals(handshake.alpnProtocol, "a");
+ conn.close();
+ outgoing.destroy();
+ listener.close();
+ await new Promise((resolve) => outgoing.on("close", resolve));
+});
diff --git a/tests/unit_node/util_test.ts b/tests/unit_node/util_test.ts
index a47c231a1..6267018b1 100644
--- a/tests/unit_node/util_test.ts
+++ b/tests/unit_node/util_test.ts
@@ -353,3 +353,8 @@ Deno.test("[util] styleText()", () => {
const redText = util.styleText("red", "error");
assertEquals(redText, "\x1B[31merror\x1B[39m");
});
+
+Deno.test("[util] styleText() with array of formats", () => {
+ const colored = util.styleText(["red", "green"], "error");
+ assertEquals(colored, "\x1b[32m\x1b[31merror\x1b[39m\x1b[39m");
+});
diff --git a/tests/unit_node/zlib_test.ts b/tests/unit_node/zlib_test.ts
index 8bce5ce7d..de2d2450d 100644
--- a/tests/unit_node/zlib_test.ts
+++ b/tests/unit_node/zlib_test.ts
@@ -7,9 +7,11 @@ import {
brotliCompressSync,
brotliDecompressSync,
constants,
+ crc32,
createBrotliCompress,
createBrotliDecompress,
createDeflate,
+ gzip,
gzipSync,
unzipSync,
} from "node:zlib";
@@ -210,3 +212,21 @@ Deno.test("createBrotliCompress params", async () => {
);
assertEquals(output.length, input.length);
});
+
+Deno.test("gzip() and gzipSync() accept ArrayBuffer", async () => {
+ const deffered = Promise.withResolvers<void>();
+ const buf = new ArrayBuffer(0);
+ let output: Buffer;
+ gzip(buf, (_err, data) => {
+ output = data;
+ deffered.resolve();
+ });
+ await deffered.promise;
+ assert(output! instanceof Buffer);
+ const outputSync = gzipSync(buf);
+ assert(outputSync instanceof Buffer);
+});
+
+Deno.test("crc32()", () => {
+ assertEquals(crc32("hello world"), 222957957);
+});