Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions test/fixtures/tier3-render-checksums.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,33 @@
"wide, offset | rocks": "0x9d67c26e606466f2",
"wide, offset | terrain": "0x4babfc28a8b1e8c2",
"wide, offset | trees": "0x98d9f0592e35f2af"
},
"vulcanus:render": {
"coarse, all four entries | resources": "0xed733e24441722d2",
"fine, far field | all": "0x8fddaf34cfe294b9",
"fine, far field | cliffs": "0xb82d2e38be144659",
"fine, far field | rocks": "0x060e9f2448decb11",
"fine, far field | terrain": "0x99448f85a6c82c51",
"fine, fractional origin | resources": "0xcd65b95f7a66a95d",
"routes all | all": "0x6f85c24f8f751e7c",
"routes cliffs | cliffs": "0x64487f9330ae3acd",
"routes resources | resources": "0x30e6f99f8120a068",
"routes rocks | rocks": "0x8c3b15b002ab2cc4",
"routes terrain | terrain": "0x30e6f99f8120a068",
"square at origin | all": "0x6f85c24f8f751e7c",
"square at origin | cliffs": "0x64487f9330ae3acd",
"square at origin | rocks": "0x8c3b15b002ab2cc4",
"square at origin | terrain": "0x30e6f99f8120a068",
"square on a coal patch | resources": "0x7f43991be2199bd6",
"tall, coarse | all": "0xa2a15e3cfbd84bf0",
"tall, coarse | cliffs": "0x4b4cbe1b6f0b52dc",
"tall, coarse | resources": "0x5905256a2edce517",
"tall, coarse | rocks": "0x6f6227bf751044da",
"tall, coarse | terrain": "0xec7b122399c8e8d3",
"wide, offset | all": "0xe0e4f025147ce7e2",
"wide, offset | cliffs": "0xb6e42d366a8884a0",
"wide, offset | resources": "0x380c73e2d55f5b91",
"wide, offset | rocks": "0x8842b641dd4c5f05",
"wide, offset | terrain": "0x909cf2ad51797bcb"
}
}
70 changes: 69 additions & 1 deletion test/wasmVulcanusRenderParity.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { inflateSync } from "node:zlib";
import { describe, expect, it } from "vite-plus/test";
import { afterAll, describe, expect, it } from "vite-plus/test";

import {
RECORDING,
consultedCount,
expectFrozen,
expectRecordedRows,
flushRecording,
foldPixels,
frozenCount,
} from "./tier3Frozen";

import { withDiffArtifacts } from "./diffArtifacts";
import { decodePng } from "./oracle/decodePng";
Expand Down Expand Up @@ -39,6 +49,38 @@ import {
const FIXTURES = join(import.meta.dirname, "fixtures");
const SIZE = 1024;

/**
* The tier-3 freeze section for this spec. See `tier3Frozen.ts`.
*
* Every Rust-against-TypeScript render below is ALSO checked against a frozen
* checksum, so the assertion survives #227 deleting the TypeScript arm. Without
* it, `runRenderRequest(req)` with the engine left off stops being an
* independent arm the moment the Vulcanus branch goes, and the comparison would
* pass while grading nothing.
*/
const SECTION = "vulcanus:render";

/**
* Rows this spec must record, as a literal - the same guard tier 2 documents:
* adding a case makes a record run DROP the section until this is updated.
*
* 4 terrain windows + 5 routed views + 4 rocks + 5 resources + 4 composite
* + 4 cliffs.
*
* The three `renderTiled` helpers are NOT here: every one of their calls passes
* the engine, so they compare tiled against whole rather than Rust against
* TypeScript, and the deletion leaves them intact.
*/
const ROWS = 26;

expectRecordedRows(SECTION, ROWS);
afterAll(flushRecording);

/** Freeze one render, and compare the two arms while both exist. */
function freeze(label: string, name: string, wasm: ArrayLike<number>, ts: ArrayLike<number>): void {
expectFrozen(SECTION, label, name, foldPixels(wasm), foldPixels(ts));
}

/** `surfaceSeedForPlanet("vulcanus", 123456)`. */
const VULCANUS_SURFACE_SEED = 1249936247;

Expand Down Expand Up @@ -175,6 +217,7 @@ describe("the WASM engine renders Vulcanus terrain exactly as the TypeScript doe
const ts = new Uint8ClampedArray(runRenderRequest(req).buffer);
expect(wasm.length, `${w.label}: length`).toBe(w.width * w.height * 4);
expect(Array.from(wasm), `${w.label}: pixels`).toEqual(Array.from(ts));
freeze(w.label, "terrain", wasm, ts);
}
}, 300000);

Expand Down Expand Up @@ -219,6 +262,9 @@ describe("the WASM engine renders Vulcanus terrain exactly as the TypeScript doe
const withEngine = new Uint8ClampedArray(runRenderRequest(composite, e).buffer);
const withoutEngine = new Uint8ClampedArray(runRenderRequest(composite).buffer);
expect(Array.from(withEngine), `${view}: engine vs none`).toEqual(Array.from(withoutEngine));
// Prefixed: this block sweeps WINDOWS[0] through every view, so a bare
// window label would collide with the per-view blocks below.
freeze(`routes ${view}`, view, withEngine, withoutEngine);
}

// And `all` really does differ from bare terrain here, so the assertion
Expand Down Expand Up @@ -268,6 +314,7 @@ describe("the WASM engine renders the Vulcanus rock overlay exactly as the TypeS
const ts = new Uint8ClampedArray(runRenderRequest(req).buffer);
expect(wasm.length, `${w.label}: length`).toBe(w.width * w.height * 4);
expect(Array.from(wasm), `${w.label}: pixels`).toEqual(Array.from(ts));
freeze(w.label, "rocks", wasm, ts);
}
}, 300000);

Expand Down Expand Up @@ -442,6 +489,7 @@ describe("the WASM engine renders the Vulcanus resource overlay exactly as the T
const ts = new Uint8ClampedArray(runRenderRequest(req).buffer);
expect(wasm.length, `${w.label}: length`).toBe(w.width * w.height * 4);
expect(Array.from(wasm), `${w.label}: pixels`).toEqual(Array.from(ts));
freeze(w.label, "resources", wasm, ts);
}
}, 300000);

Expand Down Expand Up @@ -543,6 +591,7 @@ describe("the WASM engine renders the Vulcanus composite exactly as the TypeScri
const wasm = new Uint8ClampedArray(runRenderRequest(req, e).buffer);
const ts = new Uint8ClampedArray(runRenderRequest(req).buffer);
expect(Array.from(wasm), `${w.label}: pixels`).toEqual(Array.from(ts));
freeze(w.label, "all", wasm, ts);
counts.push(paintedOver(wasm, new Uint8ClampedArray(runRenderRequest(request(w), e).buffer)));
}
expect(counts).toEqual(ALL_PIXELS_PER_WINDOW);
Expand Down Expand Up @@ -622,6 +671,7 @@ describe("the WASM engine renders Vulcanus cliffs exactly as the TypeScript does
const ts = new Uint8ClampedArray(runRenderRequest(req).buffer);
expect(wasm.length, `${w.label}: length`).toBe(w.width * w.height * 4);
expect(Array.from(wasm), `${w.label}: pixels`).toEqual(Array.from(ts));
freeze(w.label, "cliffs", wasm, ts);
}
}, 300000);

Expand Down Expand Up @@ -837,3 +887,21 @@ describe("the WASM engine agrees with the game's own Vulcanus preview PNG", () =
expect(differing).toBeGreaterThan(DIFFERING_PX * 10);
}, 300000);
});

describe("the tier-3 freeze covers this spec rather than merely existing", () => {
// Declared last on purpose: tests run in declaration order within a file, so
// this sees every `freeze` call the run made. See the same guard on
// `wasmNauvisRenderParity.spec.ts`, where deleting one call site left all 37
// other tests green.
//
// `expectRecordedRows` guards only a RECORD run, so without this a deleted
// `freeze` call site would leave its row in the table un-consulted while
// every gate stayed green. Both numbers are asserted because they fail on
// opposite mistakes: the table count catches a re-record that wrote a
// different surface, the consulted count catches a call site that stopped
// asking.
it.skipIf(RECORDING)("consults every frozen row exactly once", () => {
expect(frozenCount(SECTION), "rows in the committed table").toBe(ROWS);
expect(consultedCount(SECTION), "distinct rows this run looked up").toBe(ROWS);
});
});