test: require media process handles

This commit is contained in:
Peter Steinberger
2026-05-08 17:55:06 +01:00
parent b13e8b2ed7
commit ceb0385d29
3 changed files with 33 additions and 13 deletions

View File

@@ -16,6 +16,8 @@ import {
type MemoryMultimodalSettings,
} from "./multimodal.js";
type FileEntry = NonNullable<Awaited<ReturnType<typeof buildFileEntry>>>;
let sharedTempRoot = "";
let sharedTempId = 0;
@@ -38,6 +40,13 @@ function setupTempDirLifecycle(prefix: string): () => string {
return () => tmpDir;
}
function expectFileEntry(entry: Awaited<ReturnType<typeof buildFileEntry>>): FileEntry {
if (!entry) {
throw new Error("Expected file entry to be built");
}
return entry;
}
const multimodal: MemoryMultimodalSettings = {
enabled: true,
modalities: ["image", "audio"],
@@ -108,15 +117,15 @@ describe("memory host SDK package internals", () => {
const imagePath = path.join(tmpDir, "diagram.png");
fsSync.writeFileSync(imagePath, Buffer.from("png"));
const entry = await buildFileEntry(imagePath, tmpDir, multimodal);
const built = await buildMultimodalChunkForIndexing(entry!);
const entry = expectFileEntry(await buildFileEntry(imagePath, tmpDir, multimodal));
const built = await buildMultimodalChunkForIndexing(entry);
expect(built?.chunk.embeddingInput?.parts).toEqual([
{ type: "text", text: "Image file: diagram.png" },
expect.objectContaining({ type: "inline-data", mimeType: "image/png" }),
]);
fsSync.writeFileSync(imagePath, Buffer.alloc(entry!.size + 32, 1));
await expect(buildMultimodalChunkForIndexing(entry!)).resolves.toBeNull();
fsSync.writeFileSync(imagePath, Buffer.alloc(entry.size + 32, 1));
await expect(buildMultimodalChunkForIndexing(entry)).resolves.toBeNull();
});
it("chunks mixed text and preserves surrogate pairs", () => {

View File

@@ -23,12 +23,14 @@ describe("transcodeAudioBufferToOpus", () => {
runFfmpegMock.mockImplementationOnce(async (args: string[]) => {
capturedInputPath = args[args.indexOf("-i") + 1];
capturedOutputPath = args.at(-1);
if (!capturedInputPath || !capturedOutputPath) {
const inputPath = capturedInputPath;
const outputPath = capturedOutputPath;
if (!inputPath || !outputPath) {
throw new Error("missing ffmpeg paths");
}
await expect(readFile(capturedInputPath)).resolves.toEqual(Buffer.from("source-mp3"));
await expect(readFile(inputPath)).resolves.toEqual(Buffer.from("source-mp3"));
await import("node:fs/promises").then((fs) =>
fs.writeFile(capturedOutputPath!, Buffer.from("opus-output")),
fs.writeFile(outputPath, Buffer.from("opus-output")),
);
});
@@ -76,14 +78,15 @@ describe("transcodeAudioBufferToOpus", () => {
runFfmpegMock.mockImplementationOnce(async (args: string[]) => {
capturedInputPath = args[args.indexOf("-i") + 1];
capturedOutputPath = args.at(-1);
if (!capturedOutputPath) {
const outputPath = capturedOutputPath;
if (!outputPath) {
throw new Error("missing ffmpeg output path");
}
const outputBaseName = path.basename(capturedOutputPath);
const outputBaseName = path.basename(outputPath);
expect(outputBaseName).toContain("escape.opus");
expect(outputBaseName).toMatch(/\.part$/);
await import("node:fs/promises").then((fs) =>
fs.writeFile(capturedOutputPath!, Buffer.from("opus-output")),
fs.writeFile(outputPath, Buffer.from("opus-output")),
);
});

View File

@@ -9,6 +9,13 @@ import { createScriptTestHarness } from "./test-helpers.js";
const { createTempDir } = createScriptTestHarness();
function expectProcessPid(pid: number | undefined): number {
if (pid == null) {
throw new Error("Expected spawned process to expose a pid");
}
return pid;
}
describe("managed-child-process", () => {
it("maps forwarded signals to shell-compatible exit codes", () => {
expect(signalExitCode("SIGHUP")).toBe(129);
@@ -56,6 +63,7 @@ process.exitCode = await runManagedCommand({
const runner = spawn(process.execPath, [runnerPath], {
stdio: "ignore",
});
const runnerPid = expectProcessPid(runner.pid);
let childPid = 0;
try {
@@ -65,14 +73,14 @@ process.exitCode = await runManagedCommand({
expect(Number.isInteger(childPid)).toBe(true);
expect(isProcessAlive(childPid)).toBe(true);
process.kill(runner.pid!, "SIGTERM");
process.kill(runnerPid, "SIGTERM");
const result = await waitForClose(runner);
expect(result).toEqual({ code: 143, signal: null });
await waitFor(() => !isProcessAlive(childPid), 10_000);
} finally {
if (runner.pid && isProcessAlive(runner.pid)) {
process.kill(runner.pid, "SIGKILL");
if (isProcessAlive(runnerPid)) {
process.kill(runnerPid, "SIGKILL");
}
if (childPid && isProcessAlive(childPid)) {
process.kill(childPid, "SIGKILL");