85 lines
4.0 KiB
TypeScript
85 lines
4.0 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const root = path.resolve(import.meta.dirname, "../../..");
|
|
const golden = JSON.parse(fs.readFileSync(path.join(root, "tests/golden/M11-09/sequencer-codec-probe.json"), "utf8")) as {
|
|
assets: Array<{
|
|
stripType: "IMAGE" | "SOUND" | "MOVIE";
|
|
mimeType: string;
|
|
path: string;
|
|
sourcePath: string;
|
|
byteLength: number;
|
|
sha256: string;
|
|
backend: string;
|
|
decoded: Record<string, number>;
|
|
}>;
|
|
movieGenerator: { path: string; sha256: string };
|
|
blockedCode: string;
|
|
};
|
|
|
|
test("M11-09 probes IMAGE, SOUND and MOVIE bytes at runtime without extension guessing", async ({ page }) => {
|
|
const assets = golden.assets.map((asset) => {
|
|
const bytes = fs.readFileSync(path.join(root, asset.path));
|
|
expect(bytes.byteLength).toBe(asset.byteLength);
|
|
expect(crypto.createHash("sha256").update(bytes).digest("hex")).toBe(asset.sha256);
|
|
return { ...asset, bytes: new Uint8Array(bytes) };
|
|
});
|
|
expect(crypto.createHash("sha256").update(fs.readFileSync(path.join(root, golden.movieGenerator.path))).digest("hex"))
|
|
.toBe(golden.movieGenerator.sha256);
|
|
await page.goto("/");
|
|
const result = await page.evaluate(async ({ assets }) => {
|
|
const [runtime, protocol] = await Promise.all([
|
|
import("/src/sequencer/SequencerCodecProbe.ts"),
|
|
import("/src/sequencer/SequencerTimeline.ts"),
|
|
]);
|
|
const ready = [];
|
|
for (const asset of assets) {
|
|
const request = runtime.createSequencerCodecProbeRequest(asset.stripType, asset.mimeType, asset.byteLength, asset.sha256);
|
|
const receipt = await runtime.probeSequencerCodec(request, asset.bytes.buffer);
|
|
const gate = protocol.gateSequencerCodec(request, receipt);
|
|
ready.push({ sourcePath: asset.sourcePath, receipt, gate: gate.status });
|
|
}
|
|
|
|
const source = assets[0];
|
|
const corrupted = source.bytes.slice();
|
|
corrupted.fill(0, 0, Math.min(32, corrupted.length));
|
|
const corruptedHash = Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256", corrupted.buffer)),
|
|
(byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
const corruptRequest = runtime.createSequencerCodecProbeRequest("IMAGE", "image/png", corrupted.byteLength, corruptedHash);
|
|
const corruptReceipt = await runtime.probeSequencerCodec(corruptRequest, corrupted.buffer);
|
|
const mismatchRequest = runtime.createSequencerCodecProbeRequest("IMAGE", "image/png", source.byteLength, source.sha256);
|
|
const mismatchReceipt = await runtime.probeSequencerCodec(mismatchRequest, corrupted.buffer);
|
|
const spoofRequest = runtime.createSequencerCodecProbeRequest("MOVIE", "video/mp4", source.byteLength, source.sha256);
|
|
const spoofReceipt = await runtime.probeSequencerCodec(spoofRequest, source.bytes.buffer);
|
|
const forgedReceipt = { ...ready[0].receipt, sourceSha256: "f".repeat(64) };
|
|
const forgedGate = protocol.gateSequencerCodec(mismatchRequest, forgedReceipt);
|
|
return {
|
|
ready,
|
|
corrupt: { status: corruptReceipt.status, reason: corruptReceipt.reason },
|
|
mismatch: { status: mismatchReceipt.status, reason: mismatchReceipt.reason },
|
|
spoof: { status: spoofReceipt.status, reason: spoofReceipt.reason },
|
|
forged: { status: forgedGate.status, code: forgedGate.issues[0]?.code },
|
|
};
|
|
}, { assets });
|
|
|
|
expect(result.ready.map((item) => ({
|
|
sourcePath: item.sourcePath,
|
|
status: item.receipt.status,
|
|
backend: item.receipt.backend,
|
|
decoded: item.receipt.decoded,
|
|
gate: item.gate,
|
|
}))).toEqual(golden.assets.map((asset) => ({
|
|
sourcePath: asset.sourcePath,
|
|
status: "READY",
|
|
backend: asset.backend,
|
|
decoded: asset.decoded,
|
|
gate: "READY",
|
|
})));
|
|
expect(result.corrupt).toEqual({ status: "BLOCKED", reason: "DECODE_FAILED" });
|
|
expect(result.mismatch).toEqual({ status: "BLOCKED", reason: "SOURCE_IDENTITY_MISMATCH" });
|
|
expect(result.spoof.status).toBe("BLOCKED");
|
|
expect(result.forged).toEqual({ status: "BLOCKED", code: golden.blockedCode });
|
|
});
|