NODEDC_MISSION_CORE/apps/control-station/test/recordedSessionAdmission.te...

176 lines
5.7 KiB
JavaScript

import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { after, before, test } from "node:test";
import { createServer } from "vite";
let server;
let admission;
let rerunPresentationStatus;
let recordedMediaPresentationState;
before(async () => {
server = await createServer({
appType: "custom",
logLevel: "silent",
server: { middlewareMode: true },
});
admission = await server.ssrLoadModule(
"/src/core/observation/recordedSessionAdmission.ts",
);
({ rerunPresentationStatus } = await server.ssrLoadModule(
"/src/components/RerunViewport.tsx",
));
({ recordedMediaPresentationState } = await server.ssrLoadModule(
"/src/components/RecordedFmp4Player.tsx",
));
});
after(async () => {
await server?.close();
});
function camera(phase, byteLength = 1_024) {
return { phase, byteLength, message: null };
}
test("recorded session admits RRD and every declared camera as one atomic generation", () => {
const ids = ["camera.left", "camera.right"];
const oneCamera = {
"camera.left": camera("ready"),
"camera.right": camera("pending"),
};
const partialGate = admission.recordedSessionAdmissionPhase("ready", ids, oneCamera);
assert.equal(partialGate, "loading");
assert.equal(rerunPresentationStatus("ready", partialGate, true), "loading");
assert.equal(
recordedMediaPresentationState("ready", "generation", "generation", false, partialGate),
"loading",
);
const completeGate = admission.recordedSessionAdmissionPhase("ready", ids, {
...oneCamera,
"camera.right": camera("ready"),
});
assert.equal(completeGate, "ready");
assert.equal(rerunPresentationStatus("ready", completeGate, true), "ready");
assert.equal(
recordedMediaPresentationState("ready", "generation", "generation", false, completeGate),
"ready",
);
});
test("any RRD or camera failure closes the complete recorded session", () => {
const ids = ["camera.left", "camera.right"];
const cameras = {
"camera.left": camera("ready"),
"camera.right": camera("error"),
};
assert.equal(admission.recordedSessionAdmissionPhase("ready", ids, cameras), "error");
assert.equal(admission.recordedSessionAdmissionPhase("error", ids, {
...cameras,
"camera.right": camera("ready"),
}), "error");
assert.equal(rerunPresentationStatus("ready", "error", true), "error");
assert.equal(
recordedMediaPresentationState("ready", "generation", "generation", false, "error"),
"error",
);
});
test("camera admission enforces independent 16/256/512 MiB limits before fetching", () => {
const {
MAX_RECORDED_CAMERA_SOURCES,
MAX_RECORDED_MEDIA_SOURCE_BYTES,
MAX_RECORDED_SESSION_CAMERA_BYTES,
recordedCameraDescriptorPreflight,
} = admission;
assert.equal(MAX_RECORDED_CAMERA_SOURCES, 16);
assert.equal(MAX_RECORDED_MEDIA_SOURCE_BYTES, 256 * 1024 * 1024);
assert.equal(MAX_RECORDED_SESSION_CAMERA_BYTES, 512 * 1024 * 1024);
assert.equal(recordedCameraDescriptorPreflight(
Array.from({ length: 2 }, (_, index) => ({
id: `camera.${index}`,
byteLength: MAX_RECORDED_MEDIA_SOURCE_BYTES,
})),
), "ready");
assert.equal(recordedCameraDescriptorPreflight(
Array.from({ length: 17 }, (_, index) => ({ id: `camera.${index}`, byteLength: 1 })),
), "error");
assert.equal(recordedCameraDescriptorPreflight([
{ id: "camera.large", byteLength: MAX_RECORDED_MEDIA_SOURCE_BYTES + 1 },
]), "error");
assert.equal(recordedCameraDescriptorPreflight(
Array.from({ length: 5 }, (_, index) => ({
id: `camera.${index}`,
byteLength: 110 * 1024 * 1024,
})),
), "error");
assert.equal(recordedCameraDescriptorPreflight([
{ id: "camera.duplicate", byteLength: 1 },
{ id: "camera.duplicate", byteLength: 1 },
]), "error");
});
test("camera preparation remains single-flight and retains the loading permit", () => {
const ids = ["camera.first", "camera.preferred"];
const cameras = {
"camera.first": camera("loading"),
"camera.preferred": camera("pending"),
};
assert.deepEqual(
admission.nextRecordedCameraPreparationIds(
ids,
cameras,
new Set(["camera.preferred"]),
),
["camera.first"],
);
assert.deepEqual(
admission.nextRecordedCameraPreparationIds(ids, {
...cameras,
"camera.first": camera("ready"),
}),
["camera.preferred"],
);
});
test("new render workers close readiness and stale callbacks cannot reopen it", () => {
const ready = { ...camera("ready"), workerGeneration: 1 };
const remounted = admission.mergeRecordedCameraAdmission(ready, {
...camera("loading"),
workerGeneration: 2,
});
assert.equal(remounted.phase, "loading");
assert.equal(remounted.workerGeneration, 2);
assert.equal(admission.mergeRecordedCameraAdmission(remounted, {
...camera("ready"),
workerGeneration: 1,
}), remounted);
const admitted = admission.mergeRecordedCameraAdmission(remounted, {
...camera("ready"),
workerGeneration: 2,
});
assert.equal(admitted.phase, "ready");
const failed = admission.mergeRecordedCameraAdmission(admitted, {
...camera("error"),
workerGeneration: 2,
});
assert.equal(failed.phase, "error");
assert.equal(admission.mergeRecordedCameraAdmission(failed, {
...camera("loading"),
workerGeneration: 3,
}), failed);
});
test("recorded player is not mounted for a camera without a scheduler permit", async () => {
const source = await readFile(
new URL("../src/components/ObservationSources.tsx", import.meta.url),
"utf8",
);
const placeholder = source.indexOf("if (!prepareRecorded)");
const player = source.indexOf("<RecordedFmp4Player", placeholder);
assert.ok(placeholder >= 0 && player > placeholder);
assert.match(source.slice(placeholder, player), /return\s*\(/);
});