1
0

test: enforce simulation and render budgets

This commit is contained in:
2026-08-11 22:02:29 -07:00
parent 19f022f71a
commit 655c383061
9 changed files with 822 additions and 6 deletions
+4 -2
View File
@@ -28,7 +28,8 @@ const PROVIDER_CREDENTIAL: ScreenShareCredential = {
sessionId: "opaque-session", participantId: "opaque-participant", role: "presenter", grantToken: "opaque-grant-token-value",
};
const iceRequest = (credential: ScreenShareCredential = PROVIDER_CREDENTIAL, binding: ScreenShareBinding = BINDING) => ({
type: "ice-config-request", protocolVersion: 1, requestId: "ice-request-1", binding, credential,
type: "ice-config-request", protocolVersion: 1, requestId: "ice-request-1",
binding: { ...binding }, credential: { ...credential },
} as const);
const request = iceRequest();
const rateKeys = (subject = "auth-subject", trustedIp = "203.0.113.8") => ({ subject, trustedIp });
@@ -221,7 +222,8 @@ describe("authenticated ICE route", () => {
const missing = { ...iceRequest(presenter) } as Record<string, unknown>;
delete missing.credential;
assert.equal((await app.inject({ method: "POST", url: "/api/v1/media/ice", headers: bearer("presenter"), payload: missing })).statusCode, 400);
assert.equal((await app.inject({ method: "POST", url: "/api/v1/media/ice", headers: bearer("thief"), payload: iceRequest(presenter) })).statusCode, 401);
const stolen = await app.inject({ method: "POST", url: "/api/v1/media/ice", headers: bearer("thief"), payload: iceRequest(presenter) });
assert.equal(stolen.statusCode, 401, stolen.body);
assert.equal((await app.inject({ method: "POST", url: "/api/v1/media/ice", headers: bearer("presenter"), payload: iceRequest(presenter, SECOND_BINDING) })).statusCode, 401);
const joined = await app.inject({ method: "POST", url: "/api/v1/media/join", headers: bearer("viewer"), payload: {
+262
View File
@@ -0,0 +1,262 @@
/**
* Fast deterministic lifecycle soak for the in-memory realtime/media services.
* It intentionally uses fake clocks and direct service APIs: no sockets, sleeps,
* filesystem writes, or environment-specific infrastructure.
*/
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import type { ActorPoseSnapshot, ResumeRequest } from "../../../src/realtime/types.ts";
import type {
ScreenShareBinding,
ScreenShareCredential,
ScreenShareCreateRequest,
ScreenShareJoinRequest,
} from "../../../src/media/signalingTypes.ts";
import type { IceConfigRequest } from "../../../src/media/iceTypes.ts";
import type { IceConfig } from "../config.ts";
import { createIceCredentialProvider, createMediaSignalService } from "../media/index.ts";
import { createRealtimeService } from "../realtime/index.ts";
const MEDIA_SESSIONS = 32;
const VIEWERS_PER_SHARE = 3;
const REALTIME_SESSIONS = 128;
describe("bounded in-memory service soak", () => {
it("rotates media grants, releases listeners/queues, and drains every session", () => {
let now = 1_000_000;
const service = createMediaSignalService({
now: () => now,
maximumSessions: MEDIA_SESSIONS,
maximumParticipantsPerSession: VIEWERS_PER_SHARE + 1,
maximumQueuedMessagesPerParticipant: 8,
maximumSignalsPerWindow: 16,
grantTtlMs: 90_000,
});
const credentials: Array<{ credential: ScreenShareCredential; subject: string }> = [];
const unsubscribedDeliveries: number[] = [];
const presenters: Array<{
binding: ScreenShareBinding;
subject: string;
credential: ScreenShareCredential<"presenter">;
}> = [];
for (let sessionIndex = 0; sessionIndex < MEDIA_SESSIONS; sessionIndex += 1) {
const binding = mediaBinding(sessionIndex);
const presenterSubject = `presenter-subject-${sessionIndex}`;
const created = service.join(mediaCreate(binding, sessionIndex), presenterSubject);
assert.ok(created.ok && created.value.type === "screen-share-create-grant");
if (!created.ok || created.value.type !== "screen-share-create-grant") continue;
let presenterCredential = created.value.grant.credential;
const viewers: Array<{ subject: string; credential: ScreenShareCredential; sequence: number }> = [];
for (let viewerIndex = 0; viewerIndex < VIEWERS_PER_SHARE; viewerIndex += 1) {
const subject = `viewer-subject-${sessionIndex}-${viewerIndex}`;
const joined = service.join(mediaJoin(binding, sessionIndex, viewerIndex), subject);
assert.ok(joined.ok && joined.value.type === "screen-share-join-grant");
if (!joined.ok || joined.value.type !== "screen-share-join-grant") continue;
viewers.push({ subject, credential: joined.value.grant.credential, sequence: joined.value.sequence });
}
assert.equal(viewers.length, VIEWERS_PER_SHARE);
const presenterResume = service.resume({
type: "screen-share-resume-request", protocolVersion: 1,
requestId: `presenter-resume-${sessionIndex}`, sequence: 2, timestampMs: now,
binding, credential: presenterCredential, lastReceivedSequence: created.value.sequence,
}, presenterSubject);
assert.equal(presenterResume.ok, true);
if (!presenterResume.ok) continue;
assert.notEqual(presenterResume.value.grant.credential.grantToken, presenterCredential.grantToken);
assert.equal(presenterResume.value.grant.credential.role, "presenter");
if (presenterResume.value.grant.credential.role !== "presenter") continue;
presenterCredential = presenterResume.value.grant.credential as ScreenShareCredential<"presenter">;
credentials.push({ credential: presenterCredential, subject: presenterSubject });
for (const [viewerIndex, viewer] of viewers.entries()) {
const resumed = service.resume({
type: "screen-share-resume-request", protocolVersion: 1,
requestId: `viewer-resume-${sessionIndex}-${viewerIndex}`, sequence: 2, timestampMs: now,
binding, credential: viewer.credential, lastReceivedSequence: viewer.sequence,
}, viewer.subject);
assert.equal(resumed.ok, true);
if (!resumed.ok) continue;
const rotated = resumed.value.grant.credential;
credentials.push({ credential: rotated, subject: viewer.subject });
let deliveries = 0;
const subscription = service.subscribe(rotated, viewer.subject, () => { deliveries += 1; });
assert.equal(subscription.ok, true);
if (!subscription.ok) continue;
subscription.value();
const before = deliveries;
const offered = service.signal({
type: "screen-share-signal-request", protocolVersion: 1, sequence: 3 + viewerIndex, timestampMs: now,
binding, credential: presenterCredential, targetParticipantId: rotated.participantId,
signal: { kind: "sdp", descriptionType: "offer", sdp: "v=0" },
}, presenterSubject);
assert.equal(offered.ok, true);
unsubscribedDeliveries.push(deliveries - before);
}
presenters.push({ binding, subject: presenterSubject, credential: presenterCredential });
now += 1;
}
assert.equal(service.sessionCount(), MEDIA_SESSIONS);
assert.equal(credentials.length, MEDIA_SESSIONS * (VIEWERS_PER_SHARE + 1));
for (const [index, presenter] of presenters.entries()) {
const stopped = service.leave({
type: "screen-share-stop-request", protocolVersion: 1,
requestId: `stop-${index}`, sequence: 3 + VIEWERS_PER_SHARE,
timestampMs: now, binding: presenter.binding,
credential: presenter.credential, reason: "presenter-stopped",
}, presenter.subject, false);
assert.equal(stopped.ok, true);
}
assert.ok(unsubscribedDeliveries.every((count) => count === 0), "unsubscribed listeners receive no later offers");
assert.equal(service.sessionCount(), 0);
assert.ok(credentials.every(({ credential, subject }) =>
!service.revalidate(credential, subject).ok
), "destroyed sessions retain no usable grant for its original owner");
});
it("rotates realtime tokens, disconnects listeners, rate-limits, and expires all sessions", () => {
let now = 2_000_000;
const service = createRealtimeService({
now: () => now,
maximumSessions: REALTIME_SESSIONS,
maximumSessionsPerCell: REALTIME_SESSIONS,
maximumPoseUpdatesPerWindow: 4,
rateWindowMs: 10_000,
disconnectGraceMs: 500,
sessionTtlMs: 30_000,
});
const sessions: Array<{ sessionId: string; token: string; actorId: string; subject: string }> = [];
let disconnectedDeliveries = 0;
for (let index = 0; index < REALTIME_SESSIONS; index += 1) {
const actorId = `soak-actor-${index}`;
const subject = `soak-subject-${index}`;
const joined = service.join({
requestId: `soak-join-${index}`, actorId, subject, role: "member",
interests: [{ kind: "floor", officeId: "lumbridge-hq", floorId: "level-1" }],
});
assert.equal(joined.ok, true);
if (!joined.ok) continue;
let token = joined.value.token;
const connected = service.connect(joined.value.sessionId, token, () => { disconnectedDeliveries += 1; });
assert.equal(connected.ok, true);
if (connected.ok) connected.value.disconnect();
for (let rotation = 0; rotation < 3; rotation += 1) {
const request: ResumeRequest = {
type: "resume-request", protocolVersion: 1,
requestId: `soak-resume-${index}-${rotation}`,
sessionId: joined.value.sessionId, resumeToken: token,
serverEpoch: joined.value.grant.serverEpoch, lastReceivedSequence: 0,
interests: joined.value.grant.interests,
};
const resumed = service.resume(request, subject);
assert.equal(resumed.ok, true);
if (!resumed.ok) break;
assert.notEqual(resumed.value.resumeToken, token);
token = resumed.value.resumeToken;
}
sessions.push({ sessionId: joined.value.sessionId, token, actorId, subject });
}
assert.equal(sessions.length, REALTIME_SESSIONS);
assert.equal(service.sessionCount(), REALTIME_SESSIONS);
const publisher = sessions[0] as (typeof sessions)[number];
for (let sequence = 1; sequence <= 5; sequence += 1) {
now += 100;
const result = service.submitPose(
publisher.sessionId,
publisher.token,
actorPose(publisher.actorId, sequence, now, sequence / 100),
);
assert.equal(result.ok, sequence <= 4);
if (sequence === 5 && !result.ok) assert.equal(result.code, "rate-limited");
}
assert.equal(disconnectedDeliveries, 0, "disconnected realtime listeners receive no broadcast");
for (let index = 0; index < sessions.length / 2; index += 1) {
const session = sessions[index] as (typeof sessions)[number];
assert.equal(service.leave(session.sessionId, session.token).ok, true);
}
assert.equal(service.sessionCount(), REALTIME_SESSIONS / 2);
now += 501;
assert.equal(service.cleanup(), REALTIME_SESSIONS / 2);
assert.equal(service.sessionCount(), 0);
assert.ok(sessions.every((session) => !service.authenticate(session.sessionId, session.token).ok));
});
it("bounds ICE issuance across subject and address churn without retaining credentials", () => {
let now = 3_000_000;
const provider = createIceCredentialProvider(iceConfig(), { now: () => now });
const credential: ScreenShareCredential = {
sessionId: "soak-media-session", participantId: "soak-participant",
role: "presenter", grantToken: "soak-private-grant-token",
};
const binding = mediaBinding(999);
const request: IceConfigRequest = {
type: "ice-config-request", protocolVersion: 1, requestId: "soak-ice",
binding, credential,
};
for (let attempt = 1; attempt <= 5; attempt += 1) {
const result = provider.issue(request, {
subject: "same-subject",
trustedIp: `203.0.113.${attempt}`,
}, now + 90_000);
assert.equal(result.ok, attempt <= 4, "subject limit survives address rotation");
}
now += 10_000;
for (let attempt = 1; attempt <= 5; attempt += 1) {
const result = provider.issue(request, {
subject: `rotating-subject-${attempt}`,
trustedIp: "198.51.100.10",
}, now + 90_000);
assert.equal(result.ok, attempt <= 4, "address limit survives subject rotation");
}
});
});
function mediaBinding(index: number): ScreenShareBinding {
return { officeId: "soak-office", levelId: "level-1", roomId: "room", screenId: `screen-${index}` };
}
function mediaCreate(binding: ScreenShareBinding, index: number): ScreenShareCreateRequest {
return {
type: "screen-share-create-request", protocolVersion: 1, requestId: `create-${index}`,
sequence: 1, timestampMs: 1_000_000, binding, role: "presenter",
};
}
function mediaJoin(binding: ScreenShareBinding, session: number, viewer: number): ScreenShareJoinRequest {
return {
type: "screen-share-join-request", protocolVersion: 1, requestId: `join-${session}-${viewer}`,
sequence: 1, timestampMs: 1_000_000, binding, role: "viewer", viewerOptIn: true,
};
}
function actorPose(actorId: string, sequence: number, timestampMs: number, xM: number): ActorPoseSnapshot {
return {
entity: "actor", actorId, kind: "humanoid", sequence, timestampMs,
pose: {
space: "local", cell: { kind: "floor", officeId: "lumbridge-hq", floorId: "level-1" },
xM, yM: 0, zM: 0, headingDeg: 0, pitchDeg: 0,
},
velocity: { xMps: 0.1, yMps: 0, zMps: 0, yawDegPerSec: 0 },
};
}
function iceConfig(): IceConfig {
return {
configured: true,
urls: ["turn:relay.example.test:3478"],
sharedSecret: "soak-turn-shared-secret-with-at-least-thirty-two-bytes",
credentialTtlSeconds: 60,
rateAttempts: 4,
rateWindowSeconds: 10,
};
}