UNPKG

posix-node

Version:

Missing Posix Functions for Node.js (via a native module written in Zig)

216 lines 6.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const index_1 = __importDefault(require("./index")); const os_1 = require("os"); const isRoot = (0, os_1.userInfo)().username == "root"; if (!isRoot) { // chroot test("chroot raises an error", () => { // this can only work as root, which we can't test here easily expect(() => { index_1.default.chroot?.("/"); }).toThrow(); }); } // getegid test("getegid returns a nonnegative number", () => { expect(index_1.default.getegid?.()).toBeGreaterThanOrEqual(0); }); // geteuid test("geteuid returns a nonnegative number", () => { expect(index_1.default.geteuid?.()).toBeGreaterThanOrEqual(0); }); // gethostname test("gethostname returns a string of length at least 1", () => { const hostname = index_1.default.gethostname?.(); if (hostname == null) throw Error("fail"); expect(typeof hostname).toBe("string"); expect(hostname.length).toBeGreaterThan(0); }); // getpgid test("getpgid returns an integer", () => { expect(index_1.default.getpgid?.(1)).toBeGreaterThanOrEqual(0); }); test("getpgrp returns an integer", () => { expect(index_1.default.getpgrp?.()).toBeGreaterThanOrEqual(0); }); test("a special case of setpgid that should work", () => { // @ts-ignore expect(index_1.default.setpgid(0, 0)).toEqual(undefined); }); test("a use of setpgid that should fail", () => { expect(() => { index_1.default.setpgid?.(1, 2); }).toThrow(); }); // getppid test("getppid returns an integer", () => { expect(index_1.default.getppid?.()).toBeGreaterThanOrEqual(0); }); test("that the security vulnerability CVE-2022-21211 does not impact posix-node", () => { // @ts-ignore expect(() => index_1.default.setegid?.({ toString: 1 })).toThrow(); }); if (!isRoot) { // setegid test("setegid throws an error (not as root)", () => { expect(() => index_1.default.setegid?.(10)).toThrow(); }); // seteuid test("seteuid throws an error (not as root)", () => { expect(() => index_1.default.seteuid?.(10)).toThrow(); }); // sethostname test("sethostname fails since we're not root", () => { expect(() => index_1.default.sethostname?.("example.com")).toThrow(); }); // setregid test("setregid throws an error (not as root)", () => { expect(() => index_1.default.setregid?.(10, 20)).toThrow(); }); // setsid test("setsid throws an error (since process is already group leader)", () => { expect(() => index_1.default.setsid?.()).toThrow(); }); } // ttyname test("ttyname of stdin, stdout, stderr works and starts with /dev/ -- or on some platforms, throws an error since testing", () => { try { for (const fd of [0, 1, 2]) { const ttyname = index_1.default.ttyname?.(fd); expect(ttyname?.startsWith("/dev")).toBe(true); } } catch (_err) { // this is also fine under testing, e.g., happens on linux, since not a tty. } }); test("ttyname of an invalid fd throws an error", () => { expect(() => { index_1.default.ttyname?.(999); }).toThrow(); }); test("ttyname with no inputs throws an error", () => { expect(() => { // @ts-ignore index_1.default.ttyname?.(); }).toThrow(); }); test("ttyname with non-number input throws an error", () => { expect(() => { // @ts-ignore index_1.default.ttyname?.("xyz"); }).toThrow(); }); // I think this should work with 'jest --runInBand' // but it is NOT working, so commented out for now. /* test("sending ourselves an alarm signal", (cb) => { console.log("isMainThread", isMainThread); process.on("SIGALRM", () => { console.log("got SIGALRM"); cb(); return 0; }); posix.alarm?.(1); }); */ // create a pipe test("create a pipe", () => { const x = index_1.default.pipe?.(); if (x == null) throw Error("pipe must work"); const { readfd, writefd } = x; expect(readfd).toBeGreaterThan(0); expect(writefd).toBeGreaterThan(0); }); test("pipe2 on linux", () => { if (process.platform == "linux") { const x = index_1.default.pipe2?.(0); if (x == null) throw Error("pipe2 must work on linux"); const { readfd, writefd } = x; expect(readfd).toBeGreaterThan(0); expect(writefd).toBeGreaterThan(0); } }); test("chdir and getcwd", () => { // they start at the same const orig = process.cwd(); expect(orig).toEqual(index_1.default.getcwd?.()); // change at the library level: index_1.default.chdir?.("/"); expect(index_1.default.getcwd?.()).toEqual("/"); // node version didn't change: expect(process.cwd()).toEqual(orig); }); const { readSync } = require("fs"); test("Use the full standard fork, dup, execv song and dance to do 'Hello world'", () => { const { dup2, execv, fork, waitpid, pipe } = index_1.default; if ( // for typescript dup2 == null || execv == null || fork == null || waitpid == null || pipe == null) { throw Error("bug"); } const stdin = pipe(); const stdout = pipe(); const pid = fork(); const HELLO = "Hello there from Posix-node!"; if (pid == 0) { // child // connect up stdin and stdout dup2(stdin.readfd, 0); dup2(stdout.writefd, 1); // replace with echo and output hello world to the pipe execv("/bin/echo", ["/bin/echo", HELLO]); } else { let b = Buffer.alloc(10000); // read output from the child readSync(stdout.readfd, b); const s = b.toString("utf8", 0, HELLO.length); expect(s).toEqual(HELLO); const { wstatus, ret } = waitpid(pid, 0); expect(wstatus).toBe(0); expect(ret).toBe(pid); } }); test("Use execvp", () => { const { dup2, execvp, fork, waitpid, pipe } = index_1.default; if ( // for typescript dup2 == null || execvp == null || fork == null || waitpid == null || pipe == null) { throw Error("bug"); } const stdin = pipe(); const stdout = pipe(); const pid = fork(); const HELLO = "Hello there from Posix-node!"; if (pid == 0) { dup2(stdin.readfd, 0); dup2(stdout.writefd, 1); execvp("echo", ["echo", HELLO]); } else { let b = Buffer.alloc(10000); readSync(stdout.readfd, b); const s = b.toString("utf8", 0, HELLO.length); expect(s).toEqual(HELLO); const { wstatus, ret } = waitpid(pid, 0); expect(wstatus).toBe(0); expect(ret).toBe(pid); } }); //# sourceMappingURL=unistd.test.js.map