clone

an endless marble-race generator in the browser; the url is the seed, so every track can be shared

main
marbles / tests / endless_golden_test.ts
endless_golden_test.ts 2.3K
1/**2 * Endless stream goldens: per-segment hashes for fixed seeds.3 *4 * The stream is a pure function of the seed (culling is generation-driven,5 * KEEP_SEGMENTS — never marble-driven), so segment k of seed X must be6 * bit-stable across refactors. Canonicalization and hashing live in7 * tools/pin_endless.ts — this test and the pin tool share one code path.8 */9import { assert, assertEquals } from "@std/assert";10import {11 computeEndlessGoldens,12 GOLDEN_SEEDS,13 GOLDEN_SEGMENTS,14} from "../tools/pin_endless.ts";1516const REGEN_HINT = "If this reshuffle is INTENTIONAL, regenerate the pins:\n" +17 " deno run --allow-read --allow-write tools/pin_endless.ts\n" +18 "and commit tests/golden_endless.json. If it is NOT intentional, your " +19 "change perturbed the endless stream (planner/WFC/island/rng order) — " +20 "existing seeds in the wild would silently change.";2122Deno.test("endless golden: pinned per-segment hashes for fixed seeds", () => {23 const goldenFile = new URL("./golden_endless.json", import.meta.url);24 let expected: Record<string, string | string[]>;25 try {26 expected = JSON.parse(Deno.readTextFileSync(goldenFile));27 } catch {28 throw new Error(29 "tests/golden_endless.json missing — generate it:\n" +30 " deno run --allow-read --allow-write tools/pin_endless.ts",31 );32 }33 const actual = computeEndlessGoldens();3435 // Compare seed-by-seed, segment-by-segment: the FIRST diverging segment36 // is the diagnosis (everything after it inherits the reshuffle).37 assertEquals(38 actual.__version,39 expected.__version,40 `generator version changed (${expected.__version} → ${actual.__version}` +41 `) — the finite pipeline shifted too.\n${REGEN_HINT}`,42 );43 for (const seed of GOLDEN_SEEDS) {44 const want = expected[seed];45 assert(46 Array.isArray(want) && want.length === GOLDEN_SEGMENTS,47 `golden file has no ${GOLDEN_SEGMENTS}-segment pin for seed ` +48 `"${seed}" — stale file?\n${REGEN_HINT}`,49 );50 const got = actual[seed] as string[];51 for (let i = 0; i < GOLDEN_SEGMENTS; i++) {52 assertEquals(53 got[i],54 want[i],55 `endless stream reshuffled: seed "${seed}" diverges at segment ` +56 `${i} (pinned ${want[i]}, got ${got[i]}).\n${REGEN_HINT}`,57 );58 }59 }60});