mirror of
https://gitlab.com/the-no-frauds-club/cosmonarchy-bw-prerelease.git
synced 2026-09-26 08:41:35 +00:00
85 lines
3.6 KiB
TypeScript
85 lines
3.6 KiB
TypeScript
|
|
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
|
||
|
|
})
|
||
|
|
})
|