Files
diegosouzapw--omniroute/tests/unit/headroom-proxy-lifecycle.test.ts
2026-07-13 13:39:12 +08:00

98 lines
5.1 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import {
DEFAULT_HEADROOM_URL,
isLoopbackHeadroomUrl,
parsePortFromHeadroomUrl,
buildHeadroomStatus,
} from "../../src/lib/headroom/detect";
import { getManagedPid, isPidAlive } from "../../src/lib/headroom/process";
import { isLocalOnlyPath } from "../../src/server/authz/routeGuard";
// ──────────────────────────────────────────────────────────────────────────────
// 1. Route guard: /api/headroom/{start,stop} MUST be classified LOCAL_ONLY
// so a tunneled JWT cannot trigger child-process spawning (Hard Rule #15).
// ──────────────────────────────────────────────────────────────────────────────
test("isLocalOnlyPath gates /api/headroom/start and /stop", () => {
assert.equal(isLocalOnlyPath("/api/headroom/start"), true);
assert.equal(isLocalOnlyPath("/api/headroom/stop"), true);
// status is a read-only probe — keep it accessible (matches upstream b55cf36d).
assert.equal(isLocalOnlyPath("/api/headroom/status"), false);
});
// ──────────────────────────────────────────────────────────────────────────────
// 2. URL helpers — pure functions, no side effects.
// ──────────────────────────────────────────────────────────────────────────────
test("DEFAULT_HEADROOM_URL falls back to localhost:8787", () => {
assert.ok(DEFAULT_HEADROOM_URL.startsWith("http"));
assert.ok(/:8787$/.test(DEFAULT_HEADROOM_URL) || /HEADROOM_URL/.test(DEFAULT_HEADROOM_URL));
});
test("isLoopbackHeadroomUrl recognizes loopback hosts", () => {
assert.equal(isLoopbackHeadroomUrl("http://localhost:8787"), true);
assert.equal(isLoopbackHeadroomUrl("http://127.0.0.1:8787"), true);
assert.equal(isLoopbackHeadroomUrl("http://[::1]:8787"), true);
assert.equal(isLoopbackHeadroomUrl("http://headroom:8787"), false);
assert.equal(isLoopbackHeadroomUrl("http://10.0.0.5:8787"), false);
assert.equal(isLoopbackHeadroomUrl("not-a-url"), false);
});
test("parsePortFromHeadroomUrl extracts valid port or returns null", () => {
assert.equal(parsePortFromHeadroomUrl("http://localhost:8787"), 8787);
assert.equal(parsePortFromHeadroomUrl("http://localhost"), null);
assert.equal(parsePortFromHeadroomUrl("bogus"), null);
// Pair-port 50ed79fe: Docker sidecar with non-standard port.
assert.equal(parsePortFromHeadroomUrl("http://headroom:9090"), 9090);
});
// ──────────────────────────────────────────────────────────────────────────────
// 3. buildHeadroomStatus — pure shape assembly (mockable inputs).
// Pair commit 50ed79fe: a reachable external proxy must report
// running=true and canStart=false even without a local CLI.
// ──────────────────────────────────────────────────────────────────────────────
test("buildHeadroomStatus: local CLI present + proxy running → canStart=true", () => {
const status = buildHeadroomStatus({
url: "http://localhost:8787",
binaryPath: "/usr/local/bin/headroom",
python: "python3.12",
proxyReachable: true,
});
assert.equal(status.installed, true);
assert.equal(status.running, true);
assert.equal(status.localUrl, true);
assert.equal(status.canStart, true);
assert.equal(status.python, "python3.12");
});
test("buildHeadroomStatus: external proxy reachable, no local CLI → running=true, canStart=false (Docker sidecar)", () => {
const status = buildHeadroomStatus({
url: "http://headroom:8787",
binaryPath: null,
python: null,
proxyReachable: true,
});
assert.equal(status.installed, false);
assert.equal(status.running, true);
assert.equal(status.localUrl, false);
assert.equal(status.canStart, false);
});
test("buildHeadroomStatus: nothing installed and proxy unreachable → all false", () => {
const status = buildHeadroomStatus({
url: "http://localhost:8787",
binaryPath: null,
python: null,
proxyReachable: false,
});
assert.equal(status.installed, false);
assert.equal(status.running, false);
assert.equal(status.localUrl, true);
assert.equal(status.canStart, false);
});
test("process status helpers are safe for absent managed processes", () => {
assert.equal(isPidAlive(null), false);
assert.equal(isPidAlive(undefined), false);
assert.equal(getManagedPid(), null);
});