1
0
mirror of https://gitlab.com/the-no-frauds-club/cosmonarchy-bw-prerelease.git synced 2026-09-26 08:41:35 +00:00
cosmonarchy-bw-prerelease/tools/tbl/test/roundtrip.test.ts

85 lines
3.6 KiB
TypeScript
Raw Normal View History

import { describe, expect, it } from "bun:test"
import * as Tbl from "../src/Tbl.ts"
import * as TblText from "../src/TblText.ts"
import { show, succeed } from "./helpers.ts"
const repo = `${import.meta.dir}/../../..`
const FIXTURES = [
"mpq/arr/images.tbl",
"mpq/arr/portdata.tbl",
"mpq/rez/gluHist.tbl",
"mpq/rez/help_txt.tbl",
"mpq/rez/network.tbl",
"mpq/rez/stat_txt.tbl",
"mpq/rez/tips.tbl",
"mpq/rez/unitnames.tbl"
]
describe("round trip against the shipped game data", () => {
for (const fixture of FIXTURES) {
it(`${fixture} survives .tbl -> .tbl.txt -> .tbl byte for byte`, async () => {
const original = new Uint8Array(await Bun.file(`${repo}/${fixture}`).arrayBuffer())
const table = await succeed(Tbl.decode(original))
const text = TblText.encode(table)
const reparsed = await succeed(TblText.decode(text))
const rebuilt = await succeed(Tbl.encode(reparsed))
expect(rebuilt.length).toBe(original.length)
expect(rebuilt).toEqual(original)
})
it(`${fixture} decompiles to pure ASCII`, async () => {
const original = new Uint8Array(await Bun.file(`${repo}/${fixture}`).arrayBuffer())
const text = TblText.encode(await succeed(Tbl.decode(original)))
const offender = [...text].find((char) => char.charCodeAt(0) > 0x7e)
expect(offender).toBeUndefined()
})
}
it("renders images.tbl as plain, unescaped GRP paths", async () => {
const original = new Uint8Array(await Bun.file(`${repo}/mpq/arr/images.tbl`).arrayBuffer())
const table = await succeed(Tbl.decode(original))
const lines = TblText.encode(table, { header: false }).split("\n")
expect(lines[0]).toBe("zerg\\avenger.grp")
expect(lines[1]).toBe("protoss\\mshield.los")
})
it("renders unitnames.tbl multi-part entries with <0> separators", async () => {
const original = new Uint8Array(await Bun.file(`${repo}/mpq/rez/unitnames.tbl`).arrayBuffer())
const table = await succeed(Tbl.decode(original))
const lines = TblText.encode(table, { header: false }).split("\n")
expect(lines[0]).toBe("Terran Maverick<0>*<0>Ground Units")
expect(lines[5]).toBe("Terran Phalanx<0>Tank Mode<0>Ground Units")
})
it("renders stat_txt.tbl colour codes and newlines as <N>", async () => {
const original = new Uint8Array(await Bun.file(`${repo}/mpq/rez/stat_txt.tbl`).arrayBuffer())
const table = await succeed(Tbl.decode(original))
const line = TblText.encode(table, { header: false }).split("\n")[338]!
expect(line).toBe(
"e<0><4>Tank Mode <1>(<3>E<1>)<10>Returns the Phalanx's weapon and mobility to normal."
)
})
it("dedupe reclaims stat_txt.tbl headroom without changing a single string", async () => {
const original = new Uint8Array(await Bun.file(`${repo}/mpq/rez/stat_txt.tbl`).arrayBuffer())
const table = await succeed(Tbl.decode(original))
const deduped = await succeed(Tbl.encode(table, { dedupe: true }))
expect(deduped.length).toBeLessThan(original.length)
expect(show(await succeed(Tbl.decode(deduped)))).toEqual(show(table))
})
it("reports how little offset headroom stat_txt.tbl has left", async () => {
const original = new Uint8Array(await Bun.file(`${repo}/mpq/rez/stat_txt.tbl`).arrayBuffer())
const view = new DataView(original.buffer)
const count = view.getUint16(0, true)
let highest = 0
for (let i = 0; i < count; i++) highest = Math.max(highest, view.getUint16(2 + i * 2, true))
expect(highest).toBeLessThanOrEqual(Tbl.MAX_OFFSET)
expect(Tbl.MAX_OFFSET - highest).toBeLessThan(64) // 26 bytes at time of writing
})
})