48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
// Test support: the current user's IDs, a fresh temporary directory, and a
|
|
// plain command runner. It imports no source module, so the repository-level
|
|
// tests in tests/, which reach src/ only through `#testing`, never touch
|
|
// internals.
|
|
import { spawn } from "node:child_process";
|
|
import { once } from "node:events";
|
|
import { mkdtemp } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import process from "node:process";
|
|
import { text } from "node:stream/consumers";
|
|
|
|
export function currentUid(): number {
|
|
return process.getuid?.() ?? -1;
|
|
}
|
|
|
|
export function currentGid(): number {
|
|
return process.getgid?.() ?? -1;
|
|
}
|
|
|
|
// The isolation tests switch UIDs, which only root may do.
|
|
export const IS_ROOT: boolean = currentUid() === 0;
|
|
|
|
// Symlinks and POSIX modes, as these tests use them, need a Unix host.
|
|
export const IS_WINDOWS: boolean = process.platform === "win32";
|
|
|
|
export function makeTempDir(): Promise<string> {
|
|
return mkdtemp(join(tmpdir(), "bot-agents-test-"));
|
|
}
|
|
|
|
export interface CommandResult {
|
|
success: boolean;
|
|
stderr: string;
|
|
}
|
|
|
|
// Runs a command with stdin closed and only the given environment, and
|
|
// collects its stderr.
|
|
export async function runCommand(
|
|
command: string,
|
|
args: string[],
|
|
env: Record<string, string>,
|
|
): Promise<CommandResult> {
|
|
const child = spawn(command, args, { env, stdio: ["ignore", "ignore", "pipe"] });
|
|
const [stderr, closed] = await Promise.all([text(child.stderr), once(child, "close")]);
|
|
const exitCode: unknown = closed[0];
|
|
return { success: exitCode === 0, stderr };
|
|
}
|