manifest.test.js

2.9 kB · javascript · 76 lines

1import { expect, test } from "bun:test";23const manifest = await Bun.file(new URL("../../bridge/manifest.json", import.meta.url)).json();4const units = (await Bun.file(new URL("../../bridge/units.txt", import.meta.url)).text())5    .split("\n")6    .map((line) => line.trim())7    .filter(Boolean);8const pkg = await Bun.file(new URL("./package.json", import.meta.url)).json();9const kinds = new Map(manifest.types.map((t) => [t.path, t.cross.kind]));1011function parent(path) {12    const at = path.lastIndexOf("::");13    return at < 0 ? "" : path.slice(0, at);14}1516function relative(unit, path) {17    return unit === "all" ? path : path.slice(unit.length + 2);18}1920function walk(mod, path) {21    let node = mod;22    for (const seg of path.split("::").filter(Boolean)) {23        if (node === undefined || node === null) return undefined;24        node = node[seg];25    }26    return node;27}2829function holds(unit, path) {30    return unit === "all" || path.split("::")[0] === unit;31}3233function check(mod, unit, f) {34    const kind = f.owner ? kinds.get(f.owner) : undefined;35    if (kind === "class") {36        const cls = walk(mod, relative(unit, f.owner));37        if (typeof cls !== "function") return false;38        if (f.self_kind === null && f.name === "new") return true;39        if (f.self_kind === null) return typeof cls[f.name] === "function";40        return typeof cls.prototype[f.name] === "function";41    }42    if (kind === "plain" || kind === "enum") {43        const holder = walk(mod, relative(unit, f.owner));44        return typeof holder === "function" && typeof holder[f.name] === "function";45    }46    return typeof walk(mod, relative(unit, f.path)) === "function";47}4849for (const unit of units) {50    test(`${unit} exports every ok name`, async () => {51        expect(pkg.exports[unit === "all" ? "." : `./${unit}`]).toBeDefined();52        const mod = await import(`./${unit}.js`);53        const bytes = await Bun.file(new URL(`./pkg/${unit}/mrlyjs_${unit}_bg.wasm`, import.meta.url)).arrayBuffer();54        mod.initSync({ module: bytes });55        expect(typeof mod.Rng).toBe("function");56        const missing = [];57        const names = new Set();58        for (const f of manifest.functions) {59            if (f.cross.status !== "ok" || !holds(unit, f.module)) continue;60            names.add(f.path);61            if (!check(mod, unit, f)) missing.push(f.path);62        }63        for (const c of manifest.consts) {64            if (c.cross.status !== "ok" || !holds(unit, c.path)) continue;65            names.add(c.path);66            if (typeof walk(mod, relative(unit, c.path)) !== "function") missing.push(c.path);67        }68        for (const t of manifest.types) {69            if (t.cross.kind !== "class" || !holds(unit, t.path)) continue;70            names.add(t.path);71            if (typeof walk(mod, relative(unit, t.path)) !== "function") missing.push(t.path);72        }73        expect(missing).toEqual([]);74        console.log(`${unit}: ${names.size} names`);75    });76}