66 lines
2.9 KiB
JavaScript
66 lines
2.9 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import ts from "typescript";
|
|
|
|
const root = path.resolve(import.meta.dirname, "../../..");
|
|
const sourcePath = path.join(root, "web/protocol/render-image-comparison.ts");
|
|
const source = fs.readFileSync(sourcePath, "utf8").replace('import type { ErrorCode } from "./error";\n', "");
|
|
const transpiled = ts.transpileModule(source, {
|
|
compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 },
|
|
fileName: sourcePath,
|
|
reportDiagnostics: true,
|
|
});
|
|
assert.deepEqual(transpiled.diagnostics, []);
|
|
const comparison = await import("data:text/javascript;base64," + Buffer.from(transpiled.outputText).toString("base64"));
|
|
|
|
const thresholds = {
|
|
maxMeanAbsoluteError: 8,
|
|
maxRootMeanSquaredError: 16,
|
|
maxP95ChannelError: 16,
|
|
maxBadPixelRatio: 0.1,
|
|
badPixelChannelError: 32,
|
|
foregroundDeltaFromReferenceBackground: 32,
|
|
minForegroundIntersectionOverUnion: 0.8,
|
|
maxAlphaCoverageDeltaRatio: 0,
|
|
};
|
|
|
|
function frame(width = 4, height = 4) {
|
|
const pixels = new Uint8Array(width * height * 4);
|
|
for (let index = 0; index < pixels.length; index += 4) pixels.set([64, 64, 64, 255], index);
|
|
for (const pixel of [5, 6, 9, 10]) pixels.set([0, 0, 0, 255], pixel * 4);
|
|
return pixels;
|
|
}
|
|
|
|
test("M11-04 reports every explainable metric for identical SRGB8 frames", () => {
|
|
const reference = frame();
|
|
const report = comparison.compareRenderImages(reference, reference.slice(), 4, 4, thresholds);
|
|
assert.equal(report.status, "READY");
|
|
assert.deepEqual(
|
|
[report.meanAbsoluteError, report.rootMeanSquaredError, report.p95ChannelError, report.badPixelRatio],
|
|
[0, 0, 0, 0],
|
|
);
|
|
assert.equal(report.foregroundIntersectionOverUnion, 1);
|
|
assert.equal(report.checks.length, 6);
|
|
assert.equal(report.errorCode, null);
|
|
});
|
|
|
|
test("M11-04 rejects a non-empty but compositionally wrong frame", () => {
|
|
const reference = frame();
|
|
const wrong = frame();
|
|
for (let index = 0; index < wrong.length; index += 4) wrong.set([64, 64, 64, 255], index);
|
|
wrong.set([255, 0, 0, 255], 0);
|
|
const report = comparison.compareRenderImages(reference, wrong, 4, 4, thresholds);
|
|
assert.equal(report.status, "BLOCKED");
|
|
assert.equal(report.errorCode, "RENDER_REFERENCE_MISMATCH");
|
|
assert.ok(report.foregroundIntersectionOverUnion < thresholds.minForegroundIntersectionOverUnion);
|
|
assert.ok(report.checks.some((item) => !item.passed));
|
|
});
|
|
|
|
test("M11-04 rejects invalid dimensions, byte lengths and thresholds", () => {
|
|
assert.throws(() => comparison.compareRenderImages(frame(), frame(), 0, 4, thresholds), /INVALID_ARGUMENT/);
|
|
assert.throws(() => comparison.compareRenderImages(frame(), frame().subarray(1), 4, 4, thresholds), /INVALID_ARGUMENT/);
|
|
assert.throws(() => comparison.compareRenderImages(frame(), frame(), 4, 4, { ...thresholds, maxBadPixelRatio: 2 }), /INVALID_ARGUMENT/);
|
|
});
|