forked from phenom/healer-man
99 lines
4.6 KiB
JavaScript
99 lines
4.6 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { buildOriginNativeMaterialProvenance } from "./origin-native-material-provenance.mjs";
|
|
|
|
const resources = [
|
|
"model\\dungeon\\the_origin\\act_precipice_01.ros",
|
|
"model\\dungeon\\the_origin\\act_precipice_02.ros",
|
|
"model\\element\\wailing_mountains\\prop\\waterfall\\act_waterfall02.ros",
|
|
"model\\element\\elves_island\\vegetation\\gaint_tree_a.ros",
|
|
"model\\element\\weeping_coast\\vegetation\\n_tree_02.ros",
|
|
"model\\dungeon\\the_origin\\tree_01_01.ros",
|
|
"model\\dungeon\\the_origin\\act_cocoon_01.ros",
|
|
];
|
|
|
|
function fixture() {
|
|
const conversionReports = new Map();
|
|
const stagedOverrides = resources.map((resource, index) => {
|
|
const sha256 = String(index + 1).padStart(64, "0");
|
|
conversionReports.set(resource.toLowerCase(), {
|
|
source: { model: resource, resourceSha256: sha256 },
|
|
visual: {
|
|
materials: {
|
|
nativeAlpha: {
|
|
sourceModel: resource,
|
|
sourceResourceSha256: sha256,
|
|
materials: [{ sourceModel: resource, sourceResourceSha256: sha256, materialIndex: 1 }],
|
|
},
|
|
},
|
|
},
|
|
});
|
|
return { resource, file: `staging/${index}/visual.glb`, placements: index + 1 };
|
|
});
|
|
return {
|
|
conversionReports,
|
|
assembly: {
|
|
sourceWdbSha256: "a".repeat(64),
|
|
sourceWdbReportSha256: "b".repeat(64),
|
|
primaryResource: "model\\dungeon\\the_origin\\cathedral_01_b.ros",
|
|
primarySourceSha256: "c".repeat(64),
|
|
staticPlacementCount: 693,
|
|
uniqueResourceCount: 220,
|
|
dynamicPlacementCount: 0,
|
|
resources: stagedOverrides.map((override, index) => ({
|
|
resource: override.resource.replaceAll("\\", "/"),
|
|
placementCount: override.placements,
|
|
sourceSha256: String(index + 1).padStart(64, "0"),
|
|
})),
|
|
stagedOverrides,
|
|
assembledVisual: { sha256: "d".repeat(64) },
|
|
},
|
|
semantics: {
|
|
khrMaterialsUnlit: [{ sourceModel: resources[2], sourceResourceSha256: String(3).padStart(64, "0") }],
|
|
nativeAdditiveMaterials: [{ sourceModel: resources[0], sourceResourceSha256: String(1).padStart(64, "0"), alphaMode: "BLEND" }],
|
|
materialCounts: { total: 2 },
|
|
sharedMapLightingPair: { note: "same map, different native lighting identity" },
|
|
},
|
|
metadata: {
|
|
title: "The Origin",
|
|
entry: { x: 1, y: 2, z: 3 },
|
|
sourceTerrain: { resource: "terrain/source.wdb", chunkCount: 4 },
|
|
nativeTerrain: { report: "terrain-report.json", sourceSha256: "e".repeat(64) },
|
|
assets: [{ role: "visual", sha256: "old-visual-hash" }],
|
|
nativeMaterialAlpha: { report: "old-report.json", resources: [] },
|
|
},
|
|
};
|
|
}
|
|
|
|
test("joins staged Origin overrides by authoritative native ROS identity while retaining current metadata", () => {
|
|
const data = fixture();
|
|
const originalEntry = structuredClone(data.metadata.entry);
|
|
const originalSourceTerrain = structuredClone(data.metadata.sourceTerrain);
|
|
const originalNativeTerrain = structuredClone(data.metadata.nativeTerrain);
|
|
const originalAssets = structuredClone(data.metadata.assets);
|
|
const output = buildOriginNativeMaterialProvenance(data);
|
|
assert.equal(output.alphaReport.resources.length, resources.length);
|
|
assert.equal(output.alphaReport.resources[2].nativeAlpha.materials[0].sourceModel, resources[2]);
|
|
assert.equal(output.metadata.nativeMaterialAlpha.resources[6].placements, 7);
|
|
assert.equal(output.metadata.nativeMaterialSemantics.unlitMaterialCount, 1);
|
|
assert.equal(output.metadata.nativeMaterialSemantics.additiveMaterialCount, 1);
|
|
assert.deepEqual(output.metadata.entry, originalEntry);
|
|
assert.deepEqual(output.metadata.sourceTerrain, originalSourceTerrain);
|
|
assert.deepEqual(output.metadata.nativeTerrain, originalNativeTerrain);
|
|
assert.deepEqual(output.metadata.assets, originalAssets);
|
|
assert.equal(data.metadata.nativeMaterialAlpha.report, "old-report.json");
|
|
});
|
|
|
|
test("rejects conversion evidence whose ROS identity or source hash does not match its placement override", () => {
|
|
const data = fixture();
|
|
const first = data.assembly.stagedOverrides[0].resource.toLowerCase();
|
|
data.conversionReports.get(first).visual.materials.nativeAlpha.sourceResourceSha256 = "not-a-sha";
|
|
assert.throws(() => buildOriginNativeMaterialProvenance(data), /Invalid native source hash/);
|
|
});
|
|
|
|
test("rejects staged source hashes that disagree with authoritative assembly resource rows", () => {
|
|
const data = fixture();
|
|
data.assembly.resources[0].sourceSha256 = "f".repeat(64);
|
|
assert.throws(() => buildOriginNativeMaterialProvenance(data), /does not match the authoritative assembly row/);
|
|
});
|