94 lines
3.1 KiB
TypeScript
94 lines
3.1 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { generateBuildMutex, sanitizeMutex, sanitizeOutputName } from "./build-utils";
|
|
|
|
describe("generateBuildMutex", () => {
|
|
test("returns string of requested length", () => {
|
|
expect(generateBuildMutex(24)).toHaveLength(24);
|
|
expect(generateBuildMutex(1)).toHaveLength(1);
|
|
expect(generateBuildMutex(64)).toHaveLength(64);
|
|
});
|
|
|
|
test("defaults to length 24", () => {
|
|
expect(generateBuildMutex()).toHaveLength(24);
|
|
});
|
|
|
|
test("only uses allowed alphabet characters", () => {
|
|
const value = generateBuildMutex(256);
|
|
expect(value).toMatch(/^[A-Za-z0-9._-]+$/);
|
|
});
|
|
|
|
test("produces different values across calls", () => {
|
|
const a = generateBuildMutex(24);
|
|
const b = generateBuildMutex(24);
|
|
expect(a).not.toBe(b);
|
|
});
|
|
|
|
test("result passes sanitizeMutex", () => {
|
|
expect(sanitizeMutex(generateBuildMutex(24))).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe("sanitizeMutex", () => {
|
|
test("returns undefined for falsy input", () => {
|
|
expect(sanitizeMutex(undefined)).toBeUndefined();
|
|
expect(sanitizeMutex("")).toBeUndefined();
|
|
});
|
|
|
|
test("returns undefined for whitespace-only input", () => {
|
|
expect(sanitizeMutex(" ")).toBeUndefined();
|
|
expect(sanitizeMutex("\t\n")).toBeUndefined();
|
|
});
|
|
|
|
test("trims surrounding whitespace", () => {
|
|
expect(sanitizeMutex(" abc ")).toBe("abc");
|
|
});
|
|
|
|
test("accepts allowed characters", () => {
|
|
expect(sanitizeMutex("Abc.123_-xyz")).toBe("Abc.123_-xyz");
|
|
});
|
|
|
|
test("rejects spaces inside the value", () => {
|
|
expect(() => sanitizeMutex("ab cd")).toThrow(/Mutex must be/);
|
|
});
|
|
|
|
test("rejects disallowed punctuation", () => {
|
|
expect(() => sanitizeMutex("abc/def")).toThrow();
|
|
expect(() => sanitizeMutex("abc@def")).toThrow();
|
|
expect(() => sanitizeMutex("abc#def")).toThrow();
|
|
});
|
|
|
|
test("enforces max length of 64", () => {
|
|
expect(sanitizeMutex("a".repeat(64))).toBe("a".repeat(64));
|
|
expect(() => sanitizeMutex("a".repeat(65))).toThrow();
|
|
});
|
|
});
|
|
|
|
describe("sanitizeOutputName", () => {
|
|
test("accepts plain filenames", () => {
|
|
expect(sanitizeOutputName("agent.exe")).toBe("agent.exe");
|
|
expect(sanitizeOutputName("my-build_v2.0.bin")).toBe("my-build_v2.0.bin");
|
|
});
|
|
|
|
test("strips path components from traversal attempts", () => {
|
|
// path.basename removes the directory portion, neutralizing traversal.
|
|
// The returned value still has to match the allowed-character set.
|
|
expect(sanitizeOutputName("../etc/passwd")).toBe("passwd");
|
|
expect(sanitizeOutputName("/etc/shadow")).toBe("shadow");
|
|
});
|
|
|
|
test("rejects when basename itself contains a disallowed character", () => {
|
|
expect(() => sanitizeOutputName("bad name")).toThrow(/Invalid output filename/);
|
|
expect(() => sanitizeOutputName("weird$.bin")).toThrow();
|
|
});
|
|
|
|
test("rejects names with disallowed characters", () => {
|
|
expect(() => sanitizeOutputName("agent name.exe")).toThrow();
|
|
expect(() => sanitizeOutputName("agent$.exe")).toThrow();
|
|
expect(() => sanitizeOutputName("agent*.exe")).toThrow();
|
|
});
|
|
|
|
test("rejects empty result", () => {
|
|
expect(() => sanitizeOutputName("")).toThrow();
|
|
});
|
|
});
|