mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-05-12 13:44:43 +00:00
132 lines
5.5 KiB
JavaScript
132 lines
5.5 KiB
JavaScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
WASM_FILENAME,
|
|
clearMicronWasmRuntimeOverride,
|
|
computeWasmSriSha384,
|
|
fetchWasmFromGitHubReleaseVerified,
|
|
getMicronWasmRuntimeOverride,
|
|
parseShasums256ForFilename,
|
|
setMicronWasmRuntimeOverride,
|
|
sha256HexOfBuffer,
|
|
} from "../../meshchatx/src/frontend/js/MicronWasmRuntimeOverride.js";
|
|
import {
|
|
invalidateNomadMicronWasmPreload,
|
|
refreshMicronWasmRuntimeOverrideCache,
|
|
} from "../../meshchatx/src/frontend/js/MicronWasmLoader.js";
|
|
|
|
describe("MicronWasmRuntimeOverride.js", () => {
|
|
beforeEach(async () => {
|
|
await clearMicronWasmRuntimeOverride();
|
|
refreshMicronWasmRuntimeOverrideCache();
|
|
invalidateNomadMicronWasmPreload();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await clearMicronWasmRuntimeOverride();
|
|
refreshMicronWasmRuntimeOverrideCache();
|
|
invalidateNomadMicronWasmPreload();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("parseShasums256ForFilename reads hex line", () => {
|
|
const text = "c2b0f7de7f241719b54f99b12dc8215e262bdbecb8a5b2a25de3848408aa44cb micron-parser-go.wasm\n";
|
|
expect(parseShasums256ForFilename(text, WASM_FILENAME)).toBe(
|
|
"c2b0f7de7f241719b54f99b12dc8215e262bdbecb8a5b2a25de3848408aa44cb"
|
|
);
|
|
});
|
|
|
|
it("parseShasums256ForFilename supports BSD asterisk prefix", () => {
|
|
const text = "aa".repeat(32) + " *micron-parser-go.wasm\n";
|
|
expect(parseShasums256ForFilename(text, WASM_FILENAME)).toBe("aa".repeat(32));
|
|
});
|
|
|
|
it("parseShasums256ForFilename returns null when filename missing", () => {
|
|
expect(parseShasums256ForFilename("abcd".repeat(16) + " other.bin\n", WASM_FILENAME)).toBe(null);
|
|
});
|
|
|
|
it("setMicronWasmRuntimeOverride round-trips via IndexedDB", async () => {
|
|
const wasmBytes = new Uint8Array(5000).fill(7).buffer;
|
|
const wasmSri = await computeWasmSriSha384(wasmBytes);
|
|
await setMicronWasmRuntimeOverride({
|
|
source: "upload",
|
|
releaseTag: "test.wasm",
|
|
wasmSri,
|
|
wasmBytes,
|
|
expectedSha256Hex: null,
|
|
});
|
|
const got = await getMicronWasmRuntimeOverride();
|
|
expect(got).not.toBeNull();
|
|
expect(got.source).toBe("upload");
|
|
expect(got.releaseTag).toBe("test.wasm");
|
|
expect(got.wasmSri).toBe(wasmSri);
|
|
expect(got.wasmBytes.byteLength).toBe(5000);
|
|
});
|
|
|
|
it("fetchWasmFromGitHubReleaseVerified rejects hash mismatch", async () => {
|
|
const wasmBytes = new Uint8Array(5000).fill(9).buffer;
|
|
const expectedHex = await sha256HexOfBuffer(wasmBytes);
|
|
const wrongHex = "0".repeat(64);
|
|
const sums = `${wrongHex} ${WASM_FILENAME}\n`;
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn((url) => {
|
|
const u = String(url);
|
|
if (u.includes("micron-parser-go-release") && u.includes("asset=SHASUMS256.txt")) {
|
|
return Promise.resolve(new Response(sums, { status: 200 }));
|
|
}
|
|
if (u.includes("micron-parser-go-release") && u.includes("asset=micron-parser-go.wasm")) {
|
|
return Promise.resolve(new Response(wasmBytes, { status: 200 }));
|
|
}
|
|
return Promise.resolve(new Response("", { status: 404 }));
|
|
})
|
|
);
|
|
await expect(fetchWasmFromGitHubReleaseVerified("v9.9.9")).rejects.toThrow(/SHA-256 mismatch/);
|
|
});
|
|
|
|
it("fetchWasmFromGitHubReleaseVerified succeeds when SHASUMS matches WASM", async () => {
|
|
const wasmBytes = new Uint8Array(5000).fill(3).buffer;
|
|
const expectedHex = await sha256HexOfBuffer(wasmBytes);
|
|
const sums = `${expectedHex} ${WASM_FILENAME}\n`;
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn((url) => {
|
|
const u = String(url);
|
|
if (u.includes("micron-parser-go-release") && u.includes("asset=SHASUMS256.txt")) {
|
|
return Promise.resolve(new Response(sums, { status: 200 }));
|
|
}
|
|
if (u.includes("micron-parser-go-release") && u.includes("asset=micron-parser-go.wasm")) {
|
|
return Promise.resolve(new Response(wasmBytes, { status: 200 }));
|
|
}
|
|
return Promise.resolve(new Response("", { status: 404 }));
|
|
})
|
|
);
|
|
const rec = await fetchWasmFromGitHubReleaseVerified("v1.0.0");
|
|
expect(rec.source).toBe("github");
|
|
expect(rec.releaseTag).toBe("v1.0.0");
|
|
expect(rec.expectedSha256Hex).toBe(expectedHex);
|
|
expect(rec.wasmBytes.byteLength).toBe(5000);
|
|
expect(rec.wasmSri).toMatch(/^sha384-/);
|
|
});
|
|
|
|
it("fetchWasmFromGitHubReleaseVerified maps network failure to readable error", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(() => Promise.reject(new TypeError("Failed to fetch")))
|
|
);
|
|
await expect(fetchWasmFromGitHubReleaseVerified("v1.0.0")).rejects.toThrow(/could not fetch release metadata/i);
|
|
});
|
|
|
|
it("fetchWasmFromGitHubReleaseVerified handles missing SHASUMS line", async () => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn((url) => {
|
|
if (String(url).includes("asset=SHASUMS256.txt")) {
|
|
return Promise.resolve(new Response("deadbeef\n", { status: 200 }));
|
|
}
|
|
return Promise.resolve(new Response("", { status: 404 }));
|
|
})
|
|
);
|
|
await expect(fetchWasmFromGitHubReleaseVerified("v1.0.0")).rejects.toThrow(/not listed/);
|
|
});
|
|
});
|