import { expect, test } from "bun:test"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { ZipError, crc32, zipStore, type ZipEntry } from "../src/core/zip"; const text = (s: string) => new TextEncoder().encode(s); test("crc32 matches the standard check value", () => { expect(crc32(text("123456789"))).toBe(0xcbf43926); expect(crc32(new Uint8Array())).toBe(0); }); test("a stored archive passes unzip -t and gives back the exact bytes", async () => { const image = new Uint8Array(70_000).map((_, i) => (i * 31) & 0xff); const entries: ZipEntry[] = [ { name: "03_poster_zh-Hant_480x623.jpg", bytes: image, modified: new Date("2026-10-15T12:34:56Z") }, { name: "covers.txt", bytes: text("Tower of God — 탑\n"), modified: new Date("2026-10-15T12:34:56Z") }, ]; const zip = zipStore(entries); // General-purpose flag bit 11: names are UTF-8. expect(new DataView(zip.buffer, zip.byteOffset).getUint16(6, true) & 0x0800).toBe(0x0800); const path = join(mkdtempSync(join(tmpdir(), "mbseed-zip-")), "covers.zip"); await Bun.write(path, zip); const check = Bun.spawnSync(["unzip", "-t", path]); expect(check.exitCode).toBe(0); const out = Bun.spawnSync(["unzip", "-p", path, "03_poster_zh-Hant_480x623.jpg"]); expect(new Uint8Array(out.stdout)).toEqual(image); const txt = Bun.spawnSync(["unzip", "-p", path, "covers.txt"]); expect(new TextDecoder().decode(txt.stdout)).toBe("Tower of God — 탑\n"); }); test("refuses archives past 4 GiB instead of writing a broken one", () => { const huge = { length: 2 ** 32 } as unknown as Uint8Array; expect(() => zipStore([{ name: "big.jpg", bytes: huge, modified: new Date() }])).toThrow(ZipError); });