Path: blob/main/core/posix-node/src/unistd.test.ts
1067 views
import posix from "./index";1import { userInfo } from "os";23const isRoot = userInfo().username == "root";45if (!isRoot) {6// chroot7test("chroot raises an error", () => {8// this can only work as root, which we can't test here easily9expect(() => {10posix.chroot?.("/");11}).toThrow();12});13}1415// getegid1617test("getegid returns a nonnegative number", () => {18expect(posix.getegid?.()).toBeGreaterThanOrEqual(0);19});2021// geteuid2223test("geteuid returns a nonnegative number", () => {24expect(posix.geteuid?.()).toBeGreaterThanOrEqual(0);25});2627// gethostname2829test("gethostname returns a string of length at least 1", () => {30const hostname = posix.gethostname?.();31if (hostname == null) throw Error("fail");32expect(typeof hostname).toBe("string");33expect(hostname.length).toBeGreaterThan(0);34});3536// getpgid3738test("getpgid returns an integer", () => {39expect(posix.getpgid?.(1)).toBeGreaterThanOrEqual(0);40});4142test("getpgrp returns an integer", () => {43expect(posix.getpgrp?.()).toBeGreaterThanOrEqual(0);44});4546test("a special case of setpgid that should work", () => {47// @ts-ignore48expect(posix.setpgid(0, 0)).toEqual(undefined);49});5051test("a use of setpgid that should fail", () => {52expect(() => {53posix.setpgid?.(1, 2);54}).toThrow();55});5657// getppid58test("getppid returns an integer", () => {59expect(posix.getppid?.()).toBeGreaterThanOrEqual(0);60});6162test("that the security vulnerability CVE-2022-21211 does not impact posix-node", () => {63// @ts-ignore64expect(() => posix.setegid?.({ toString: 1 })).toThrow();65});6667if (!isRoot) {68// setegid69test("setegid throws an error (not as root)", () => {70expect(() => posix.setegid?.(10)).toThrow();71});7273// seteuid74test("seteuid throws an error (not as root)", () => {75expect(() => posix.seteuid?.(10)).toThrow();76});7778// sethostname79test("sethostname fails since we're not root", () => {80expect(() => posix.sethostname?.("example.com")).toThrow();81});8283// setregid84test("setregid throws an error (not as root)", () => {85expect(() => posix.setregid?.(10, 20)).toThrow();86});87// setsid88test("setsid throws an error (since process is already group leader)", () => {89expect(() => posix.setsid?.()).toThrow();90});91}9293// ttyname94test("ttyname of stdin, stdout, stderr works and starts with /dev/ -- or on some platforms, throws an error since testing", () => {95try {96for (const fd of [0, 1, 2]) {97const ttyname = posix.ttyname?.(fd);98expect(ttyname?.startsWith("/dev")).toBe(true);99}100} catch (_err) {101// this is also fine under testing, e.g., happens on linux, since not a tty.102}103});104105test("ttyname of an invalid fd throws an error", () => {106expect(() => {107posix.ttyname?.(999);108}).toThrow();109});110111test("ttyname with no inputs throws an error", () => {112expect(() => {113// @ts-ignore114posix.ttyname?.();115}).toThrow();116});117118test("ttyname with non-number input throws an error", () => {119expect(() => {120// @ts-ignore121posix.ttyname?.("xyz");122}).toThrow();123});124125// I think this should work with 'jest --runInBand'126// but it is NOT working, so commented out for now.127/*128test("sending ourselves an alarm signal", (cb) => {129console.log("isMainThread", isMainThread);130process.on("SIGALRM", () => {131console.log("got SIGALRM");132cb();133return 0;134});135posix.alarm?.(1);136});137*/138139// create a pipe140test("create a pipe", () => {141const x = posix.pipe?.();142if (x == null) throw Error("pipe must work");143const { readfd, writefd } = x;144expect(readfd).toBeGreaterThan(0);145expect(writefd).toBeGreaterThan(0);146});147148test("pipe2 on linux", () => {149if (process.platform == "linux") {150const x = posix.pipe2?.(0);151if (x == null) throw Error("pipe2 must work on linux");152const { readfd, writefd } = x;153expect(readfd).toBeGreaterThan(0);154expect(writefd).toBeGreaterThan(0);155}156});157158test("chdir and getcwd", () => {159// they start at the same160const orig = process.cwd();161expect(orig).toEqual(posix.getcwd?.());162// change at the library level:163posix.chdir?.("/");164expect(posix.getcwd?.()).toEqual("/");165// node version didn't change:166expect(process.cwd()).toEqual(orig);167});168169const { readSync } = require("fs");170171test("Use the full standard fork, dup, execv song and dance to do 'Hello world'", () => {172const { dup2, execv, fork, waitpid, pipe } = posix;173if (174// for typescript175dup2 == null ||176execv == null ||177fork == null ||178waitpid == null ||179pipe == null180) {181throw Error("bug");182}183184const stdin = pipe();185const stdout = pipe();186const pid = fork();187188const HELLO = "Hello there from Posix-node!";189if (pid == 0) {190// child191// connect up stdin and stdout192dup2(stdin.readfd, 0);193dup2(stdout.writefd, 1);194// replace with echo and output hello world to the pipe195execv("/bin/echo", ["/bin/echo", HELLO]);196} else {197let b = Buffer.alloc(10000);198// read output from the child199readSync(stdout.readfd, b);200const s = b.toString("utf8", 0, HELLO.length);201expect(s).toEqual(HELLO);202const { wstatus, ret } = waitpid(pid, 0);203expect(wstatus).toBe(0);204expect(ret).toBe(pid);205}206});207208209test("Use execvp", () => {210const { dup2, execvp, fork, waitpid, pipe } = posix;211if (212// for typescript213dup2 == null ||214execvp == null ||215fork == null ||216waitpid == null ||217pipe == null218) {219throw Error("bug");220}221222const stdin = pipe();223const stdout = pipe();224const pid = fork();225226const HELLO = "Hello there from Posix-node!";227if (pid == 0) {228dup2(stdin.readfd, 0);229dup2(stdout.writefd, 1);230execvp("echo", ["echo", HELLO]);231} else {232let b = Buffer.alloc(10000);233readSync(stdout.readfd, b);234const s = b.toString("utf8", 0, HELLO.length);235expect(s).toEqual(HELLO);236const { wstatus, ret } = waitpid(pid, 0);237expect(wstatus).toBe(0);238expect(ret).toBe(pid);239}240});241242243