Skip to main content
Module

std/node/process_test.ts

Deno standard library
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
// deno-lint-ignore-file no-undef// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import "./global.ts";import { assert, assertEquals, assertFalse, assertObjectMatch, assertStrictEquals, assertThrows,} from "../testing/asserts.ts";import { stripColor } from "../fmt/colors.ts";import { deferred } from "../async/deferred.ts";import * as path from "../path/mod.ts";import { delay } from "../async/delay.ts";import { argv, env } from "./process.ts";
Deno.test({ name: "process.cwd and process.chdir success", fn() { assertEquals(process.cwd(), Deno.cwd());
const currentDir = Deno.cwd();
const tempDir = Deno.makeTempDirSync(); process.chdir(tempDir); assertEquals( Deno.realPathSync(process.cwd()), Deno.realPathSync(tempDir), );
process.chdir(currentDir); },});
Deno.test({ name: "process.chdir failure", fn() { assertThrows( () => { process.chdir("non-existent-directory-name"); }, Deno.errors.NotFound, "file", // On every OS Deno returns: "No such file" except for Windows, where it's: // "The system cannot find the file specified. (os error 2)" so "file" is // the only common string here. ); },});
Deno.test({ name: "process.version", fn() { assertEquals(typeof process, "object"); assertEquals(typeof process.version, "string"); assertEquals(typeof process.versions, "object"); assertEquals(typeof process.versions.node, "string"); assertEquals(typeof process.versions.v8, "string"); assertEquals(typeof process.versions.uv, "string"); assertEquals(typeof process.versions.zlib, "string"); assertEquals(typeof process.versions.brotli, "string"); assertEquals(typeof process.versions.ares, "string"); assertEquals(typeof process.versions.modules, "string"); assertEquals(typeof process.versions.nghttp2, "string"); assertEquals(typeof process.versions.napi, "string"); assertEquals(typeof process.versions.llhttp, "string"); assertEquals(typeof process.versions.openssl, "string"); assertEquals(typeof process.versions.cldr, "string"); assertEquals(typeof process.versions.icu, "string"); assertEquals(typeof process.versions.tz, "string"); assertEquals(typeof process.versions.unicode, "string"); // These two are not present in `process.versions` in Node, but we // add them anyway assertEquals(typeof process.versions.deno, "string"); assertEquals(typeof process.versions.typescript, "string"); },});
Deno.test({ name: "process.platform", fn() { assertEquals(typeof process.platform, "string"); },});
Deno.test({ name: "process.mainModule", fn() { assertEquals(process.mainModule, undefined); // Check that it is writable process.mainModule = "foo"; assertEquals(process.mainModule, "foo"); },});
Deno.test({ name: "process.arch", fn() { assertEquals(typeof process.arch, "string"); if (Deno.build.arch == "x86_64") { assertEquals(process.arch, "x64"); } else if (Deno.build.arch == "aarch64") { assertEquals(process.arch, "arm64"); } else { throw new Error("unreachable"); } },});
Deno.test({ name: "process.pid", fn() { assertEquals(typeof process.pid, "number"); assertEquals(process.pid, Deno.pid); },});
Deno.test({ name: "process.on", async fn() { assertEquals(typeof process.on, "function");
let triggered = false; process.on("exit", () => { triggered = true; }); process.emit("exit"); assert(triggered);
const cwd = path.dirname(path.fromFileUrl(import.meta.url));
const command = new Deno.Command(Deno.execPath(), { args: [ "run", "--quiet", "--unstable", "./testdata/process_exit.ts", ], cwd, }); const { stdout } = await command.output();
const decoder = new TextDecoder(); assertEquals(stripColor(decoder.decode(stdout).trim()), "1\n2"); },});
Deno.test({ name: "process.on signal", ignore: Deno.build.os == "windows", async fn() { const promise = deferred(); let c = 0; const listener = () => { c += 1; }; process.on("SIGINT", listener); setTimeout(async () => { // Sends SIGINT 3 times. for (const _ of Array(3)) { await delay(20); Deno.kill(Deno.pid, "SIGINT"); } await delay(20); Deno.removeSignalListener("SIGINT", listener); promise.resolve(); }); await promise; assertEquals(c, 3); },});
Deno.test({ name: "process.off signal", ignore: Deno.build.os == "windows", async fn() { const promise = deferred(); let c = 0; const listener = () => { c += 1; process.off("SIGINT", listener); }; process.on("SIGINT", listener); setTimeout(async () => { // Sends SIGINT 3 times. for (const _ of Array(3)) { await delay(20); Deno.kill(Deno.pid, "SIGINT"); } await delay(20); promise.resolve(); }); await promise; assertEquals(c, 1); },});
Deno.test({ name: "process.on SIGBREAK doesn't throw", fn() { const listener = () => {}; process.on("SIGBREAK", listener); process.off("SIGBREAK", listener); },});
Deno.test({ name: "process.on SIGTERM doesn't throw on windows", ignore: Deno.build.os !== "windows", fn() { const listener = () => {}; process.on("SIGTERM", listener); process.off("SIGTERM", listener); },});
Deno.test({ name: "process.argv", fn() { assert(Array.isArray(argv)); assert(Array.isArray(process.argv)); assert( process.argv[0].match(/[^/\\]*deno[^/\\]*$/), "deno included in the file name of argv[0]", ); assertEquals( process.argv[1], path.fromFileUrl(Deno.mainModule), ); // argv supports array methods. assert(Array.isArray(process.argv.slice(2))); assertEquals(process.argv.indexOf(Deno.execPath()), 0); assertEquals(process.argv.indexOf(path.fromFileUrl(Deno.mainModule)), 1); },});
Deno.test({ name: "process.execArgv", fn() { assert(Array.isArray(process.execArgv)); assert(process.execArgv.length == 0); // execArgv supports array methods. assert(Array.isArray(process.argv.slice(0))); assertEquals(process.argv.indexOf("foo"), -1); },});
Deno.test({ name: "process.env", fn() { Deno.env.set("HELLO", "WORLD");
assertObjectMatch(process.env, Deno.env.toObject());
assertEquals(typeof (process.env.HELLO), "string"); assertEquals(process.env.HELLO, "WORLD");
assertEquals(typeof env.HELLO, "string"); assertEquals(env.HELLO, "WORLD");
assert(Object.getOwnPropertyNames(process.env).includes("HELLO")); assert(Object.keys(process.env).includes("HELLO"));
assert(Object.prototype.hasOwnProperty.call(process.env, "HELLO")); assert( !Object.prototype.hasOwnProperty.call( process.env, "SURELY_NON_EXISTENT_VAR", ), );
// deno-lint-ignore no-prototype-builtins assert(process.env.hasOwnProperty("HELLO")); assert("HELLO" in process.env); assert(Object.keys(process.env.valueOf()).includes("HELLO"));
assertEquals(process.env.toString(), "[object Object]"); assertEquals(process.env.toLocaleString(), "[object Object]");
// should not error when assigning false to an env var process.env.HELLO = false as unknown as string; assertEquals(process.env.HELLO, "false"); process.env.HELLO = "WORLD"; assertEquals(process.env.HELLO, "WORLD"); },});
Deno.test({ name: "process.env requires scoped env permission", permissions: { env: ["FOO"] }, fn() { Deno.env.set("FOO", "1"); assert("FOO" in process.env); assertThrows(() => { "BAR" in process.env; }); assert(Object.hasOwn(process.env, "FOO")); assertThrows(() => { Object.hasOwn(process.env, "BAR"); }); },});
Deno.test({ name: "process.env doesn't throw with invalid env var names", fn() { assertEquals(process.env[""], undefined); assertEquals(process.env["\0"], undefined); assertEquals(process.env["=c:"], undefined); assertFalse(Object.hasOwn(process.env, "")); assertFalse(Object.hasOwn(process.env, "\0")); assertFalse(Object.hasOwn(process.env, "=c:")); assertFalse("" in process.env); assertFalse("\0" in process.env); assertFalse("=c:" in process.env); },});
Deno.test({ name: "process.stdin", fn() { assertEquals(process.stdin.fd, Deno.stdin.rid); assertEquals(process.stdin.isTTY, Deno.isatty(Deno.stdin.rid)); },});
Deno.test({ name: "process.stdin readable with a TTY", // TODO(PolarETech): Run this test even in non tty environment ignore: !Deno.isatty(Deno.stdin.rid), async fn() { const promise = deferred(); const expected = ["foo", "bar", null, "end"]; const data: (string | null)[] = [];
process.stdin.setEncoding("utf8"); process.stdin.on("readable", () => { data.push(process.stdin.read()); }); process.stdin.on("end", () => { data.push("end"); });
process.stdin.push("foo"); process.nextTick(() => { process.stdin.push("bar"); process.nextTick(() => { process.stdin.push(null); promise.resolve(); }); });
await promise; assertEquals(process.stdin.readableHighWaterMark, 0); assertEquals(data, expected); },});
Deno.test({ name: "process.stdin readable with piping a file", async fn() { const expected = ["65536", "foo", "bar", "null", "end"]; const scriptPath = "./node/testdata/process_stdin.ts"; const filePath = "./node/testdata/process_stdin_dummy.txt";
const shell = Deno.build.os === "windows" ? "cmd.exe" : "/bin/sh"; const cmd = `"${Deno.execPath()}" run ${scriptPath} < ${filePath}`; const args = Deno.build.os === "windows" ? ["/d", "/c", cmd] : ["-c", cmd];
const p = new Deno.Command(shell, { args, stdin: "null", stdout: "piped", stderr: "null", windowsRawArguments: true, });
const { stdout } = await p.output(); const data = new TextDecoder().decode(stdout).trim().split("\n"); assertEquals(data, expected); },});
Deno.test({ name: "process.stdin readable with piping a stream", async fn() { const expected = ["16384", "foo", "bar", "null", "end"]; const scriptPath = "./node/testdata/process_stdin.ts";
const command = new Deno.Command(Deno.execPath(), { args: ["run", scriptPath], stdin: "piped", stdout: "piped", stderr: "null", }); const child = command.spawn();
const writer = await child.stdin.getWriter(); writer.ready .then(() => writer.write(new TextEncoder().encode("foo\nbar"))) .then(() => writer.releaseLock()) .then(() => child.stdin.close());
const { stdout } = await child.output(); const data = new TextDecoder().decode(stdout).trim().split("\n"); assertEquals(data, expected); },});
Deno.test({ name: "process.stdin readable with piping a socket", ignore: Deno.build.os === "windows", async fn() { const expected = ["16384", "foo", "bar", "null", "end"]; const scriptPath = "./node/testdata/process_stdin.ts";
const listener = Deno.listen({ hostname: "127.0.0.1", port: 9000 }); listener.accept().then(async (conn) => { await conn.write(new TextEncoder().encode("foo\nbar")); conn.close(); listener.close(); });
const shell = "/bin/bash"; const cmd = `"${Deno.execPath()}" run ${scriptPath} < /dev/tcp/127.0.0.1/9000`; const args = ["-c", cmd];
const p = new Deno.Command(shell, { args, stdin: "null", stdout: "piped", stderr: "null", });
const { stdout } = await p.output(); const data = new TextDecoder().decode(stdout).trim().split("\n"); assertEquals(data, expected); },});
Deno.test({ name: "process.stdin readable with null", async fn() { const expected = ["65536", "null", "end"]; const scriptPath = "./node/testdata/process_stdin.ts";
const command = new Deno.Command(Deno.execPath(), { args: ["run", scriptPath], stdin: "null", stdout: "piped", stderr: "null", });
const { stdout } = await command.output(); const data = new TextDecoder().decode(stdout).trim().split("\n"); assertEquals(data, expected); },});
Deno.test({ name: "process.stdin readable with unsuitable stdin", // TODO(PolarETech): Prepare a similar test that can be run on Windows ignore: Deno.build.os === "windows", async fn() { const expected = ["16384", "null", "end"]; const scriptPath = "./node/testdata/process_stdin.ts"; const directoryPath = "./node/testdata/";
const shell = "/bin/bash"; const cmd = `"${Deno.execPath()}" run ${scriptPath} < ${directoryPath}`; const args = ["-c", cmd];
const p = new Deno.Command(shell, { args, stdin: "null", stdout: "piped", stderr: "null", windowsRawArguments: true, });
const { stdout } = await p.output(); const data = new TextDecoder().decode(stdout).trim().split("\n"); assertEquals(data, expected); },});
Deno.test({ name: "process.stdout", fn() { assertEquals(process.stdout.fd, Deno.stdout.rid); const isTTY = Deno.isatty(Deno.stdout.rid); assertEquals(process.stdout.isTTY, isTTY); const consoleSize = isTTY ? Deno.consoleSize() : undefined; assertEquals(process.stdout.columns, consoleSize?.columns); assertEquals(process.stdout.rows, consoleSize?.rows); assertEquals( `${process.stdout.getWindowSize()}`, `${consoleSize && [consoleSize.columns, consoleSize.rows]}`, );
if (isTTY) { assertStrictEquals(process.stdout.cursorTo(1, 2, () => {}), true); assertStrictEquals(process.stdout.moveCursor(3, 4, () => {}), true); assertStrictEquals(process.stdout.clearLine(1, () => {}), true); assertStrictEquals(process.stdout.clearScreenDown(() => {}), true); } else { assertStrictEquals(process.stdout.cursorTo, undefined); assertStrictEquals(process.stdout.moveCursor, undefined); assertStrictEquals(process.stdout.clearLine, undefined); assertStrictEquals(process.stdout.clearScreenDown, undefined); } },});
Deno.test({ name: "process.stderr", fn() { assertEquals(process.stderr.fd, Deno.stderr.rid); const isTTY = Deno.isatty(Deno.stderr.rid); assertEquals(process.stderr.isTTY, isTTY); const consoleSize = isTTY ? Deno.consoleSize() : undefined; assertEquals(process.stderr.columns, consoleSize?.columns); assertEquals(process.stderr.rows, consoleSize?.rows); assertEquals( `${process.stderr.getWindowSize()}`, `${consoleSize && [consoleSize.columns, consoleSize.rows]}`, );
if (isTTY) { assertStrictEquals(process.stderr.cursorTo(1, 2, () => {}), true); assertStrictEquals(process.stderr.moveCursor(3, 4, () => {}), true); assertStrictEquals(process.stderr.clearLine(1, () => {}), true); assertStrictEquals(process.stderr.clearScreenDown(() => {}), true); } else { assertStrictEquals(process.stderr.cursorTo, undefined); assertStrictEquals(process.stderr.moveCursor, undefined); assertStrictEquals(process.stderr.clearLine, undefined); assertStrictEquals(process.stderr.clearScreenDown, undefined); } },});
Deno.test({ name: "process.nextTick", async fn() { let withoutArguments = false; process.nextTick(() => { withoutArguments = true; });
const expected = 12; let result; process.nextTick((x: number) => { result = x; }, 12);
await delay(10); assert(withoutArguments); assertEquals(result, expected); },});
Deno.test({ name: "process.hrtime", // TODO(kt3k): Enable this test ignore: true, fn() { const [sec0, nano0] = process.hrtime(); // seconds and nano seconds are positive integers. assert(sec0 > 0); assert(Number.isInteger(sec0)); assert(nano0 > 0); assert(Number.isInteger(nano0));
const [sec1, nano1] = process.hrtime(); // the later call returns bigger value assert(sec1 >= sec0); assert(nano1 > nano0);
const [sec2, nano2] = process.hrtime([sec1, nano1]); // the difference of the 2 calls is a small positive value. assertEquals(sec2, 0); assert(nano2 > 0); },});
Deno.test({ name: "process.hrtime.bigint", fn() { const time = process.hrtime.bigint(); assertEquals(typeof time, "bigint"); assert(time > 0n); },});
Deno.test("process.on, process.off, process.removeListener doesn't throw on unimplemented events", () => { const events = [ "beforeExit", "disconnect", "message", "multipleResolves", "rejectionHandled", "uncaughtException", "uncaughtExceptionMonitor", "unhandledRejection", "worker", ]; const handler = () => {}; events.forEach((ev) => { process.on(ev, handler); assertEquals(process.listenerCount(ev), 1); process.off(ev, handler); assertEquals(process.listenerCount(ev), 0); process.on(ev, handler); assertEquals(process.listenerCount(ev), 1); process.removeListener(ev, handler); assertEquals(process.listenerCount(ev), 0); });});
Deno.test("process.memoryUsage()", () => { const mem = process.memoryUsage(); assert(typeof mem.rss === "number"); assert(typeof mem.heapTotal === "number"); assert(typeof mem.heapUsed === "number"); assert(typeof mem.external === "number"); assert(typeof mem.arrayBuffers === "number"); assertEquals(mem.arrayBuffers, 0);});
Deno.test("process.memoryUsage.rss()", () => { const rss = process.memoryUsage.rss(); assert(typeof rss === "number");});
Deno.test("process in worker", async () => { const promise = deferred();
const worker = new Worker( new URL("./testdata/process_worker.ts", import.meta.url).href, { type: "module" }, ); worker.addEventListener("message", (e) => { assertEquals(e.data, "hello"); promise.resolve(); });
await promise; worker.terminate();});
Deno.test("process.exitCode", () => { assert(process.exitCode === undefined); process.exitCode = 127; assert(process.exitCode === 127);});
Deno.test("process.config", () => { assert(process.config !== undefined); assert(process.config.target_defaults !== undefined); assert(process.config.variables !== undefined);});
Deno.test("process._exiting", () => { assert(process._exiting === false);});
Deno.test("process.execPath", () => { assertEquals(process.execPath, process.argv[0]);});
Deno.test("process.execPath is writable", () => { // pnpm writes to process.execPath // https://github.com/pnpm/pnpm/blob/67d8b65d2e8da1df3725034b8c5b1fcf3af4ad81/packages/config/src/index.ts#L175 const originalExecPath = process.execPath; try { process.execPath = "/path/to/node"; assertEquals(process.execPath, "/path/to/node"); } finally { process.execPath = originalExecPath; }});
Deno.test("process.getgid", () => { if (Deno.build.os === "windows") { assertEquals(process.getgid, undefined); } else { assertEquals(process.getgid?.(), Deno.gid()); }});
Deno.test("process.getuid", () => { if (Deno.build.os === "windows") { assertEquals(process.getuid, undefined); } else { assertEquals(process.getuid?.(), Deno.uid()); }});
Deno.test({ name: "process.exit", async fn() { const cwd = path.dirname(path.fromFileUrl(import.meta.url));
const command = new Deno.Command(Deno.execPath(), { args: [ "run", "--quiet", "--unstable", "./testdata/process_exit2.ts", ], cwd, }); const { stdout } = await command.output();
const decoder = new TextDecoder(); assertEquals(stripColor(decoder.decode(stdout).trim()), "exit"); },});