Advance M8-M11 parity workflows
This commit is contained in:
84
web/tests/e2e/sequencer-codec-probe.spec.ts
Normal file
84
web/tests/e2e/sequencer-codec-probe.spec.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
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 });
|
||||
});
|
||||
Reference in New Issue
Block a user