feat: add multi-engine regex flavour support
This commit is contained in:
170
scripts/perl-engine-pack.test.ts
Normal file
170
scripts/perl-engine-pack.test.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
// @vitest-environment node
|
||||
|
||||
import { createHash } from "node:crypto";
|
||||
import {
|
||||
copyFile,
|
||||
cp,
|
||||
mkdir,
|
||||
mkdtemp,
|
||||
readFile,
|
||||
rm,
|
||||
writeFile,
|
||||
} from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildPerlPack,
|
||||
installPerlPack,
|
||||
PERL_ENGINE_LOCK,
|
||||
verifyPerlPack,
|
||||
} from "./perl-engine-pack.mjs";
|
||||
|
||||
const temporaryDirectories: string[] = [];
|
||||
const installedPack = path.resolve("public", "engines", "perl");
|
||||
const packFiles = [
|
||||
"LICENSE-Devel-StackTrace-Artistic-2.0.txt",
|
||||
"LICENSE-Emscripten.txt",
|
||||
"LICENSE-WebPerl-Artistic.txt",
|
||||
"LICENSE-WebPerl-GPL.txt",
|
||||
"NOTICE.txt",
|
||||
"SHA256SUMS",
|
||||
"emperl.data",
|
||||
"emperl.js",
|
||||
"emperl.wasm",
|
||||
"engine-metadata.json",
|
||||
"perl-runtime.worker.js",
|
||||
"regex_tools_bridge.pl",
|
||||
] as const;
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
temporaryDirectories
|
||||
.splice(0)
|
||||
.map((directory) => rm(directory, { recursive: true, force: true })),
|
||||
);
|
||||
});
|
||||
|
||||
async function digest(file: string): Promise<string> {
|
||||
return createHash("sha256")
|
||||
.update(await readFile(file))
|
||||
.digest("hex");
|
||||
}
|
||||
|
||||
async function makeExtractedPrebuilt(parent: string): Promise<string> {
|
||||
const prebuilt = path.join(parent, "webperl_prebuilt_v0.09-beta");
|
||||
await mkdir(prebuilt, { recursive: true });
|
||||
for (const name of ["emperl.data", "emperl.js", "emperl.wasm"]) {
|
||||
await copyFile(path.join(installedPack, name), path.join(prebuilt, name));
|
||||
}
|
||||
await copyFile(
|
||||
path.join(installedPack, "LICENSE-WebPerl-Artistic.txt"),
|
||||
path.join(prebuilt, "LICENSE_artistic.txt"),
|
||||
);
|
||||
await copyFile(
|
||||
path.join(installedPack, "LICENSE-WebPerl-GPL.txt"),
|
||||
path.join(prebuilt, "LICENSE_gpl.txt"),
|
||||
);
|
||||
return prebuilt;
|
||||
}
|
||||
|
||||
describe("Perl engine-pack gate", () => {
|
||||
it("verifies the installed closed WebPerl pack in a strict-CSP Chromium worker", async () => {
|
||||
await expect(verifyPerlPack(installedPack)).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
engineVersion: "5.28.1",
|
||||
status: "legacy-beta-compatibility-runtime",
|
||||
source: expect.objectContaining({
|
||||
tag: "v0.09-beta",
|
||||
commitSha1: "6f2173d29a2c2e3536e1de75ff5d291ae96ab348",
|
||||
}),
|
||||
bridge: expect.objectContaining({
|
||||
replacementOutputTransport: expect.stringContaining(
|
||||
"fixed MEMFS binary file",
|
||||
),
|
||||
limits: expect.objectContaining({
|
||||
maximumResponseJsonBytes: 8_388_608,
|
||||
outputChunkCharacters: 4_096,
|
||||
}),
|
||||
}),
|
||||
securityAudit: expect.objectContaining({
|
||||
generatedLoaderJavaScriptEvalSites: 1,
|
||||
generatedLoaderNewFunctionSites: 0,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}, 60_000);
|
||||
|
||||
it("pins the exact archive, runtime assets, and legacy identity", () => {
|
||||
expect(PERL_ENGINE_LOCK.engineVersion).toBe("5.28.1");
|
||||
expect(PERL_ENGINE_LOCK.webPerlVersion).toBe("0.09-beta");
|
||||
expect(PERL_ENGINE_LOCK.prebuilt.archiveSha256).toBe(
|
||||
"5f441249217e90ab378c666f473d4206ab4f44907f6bb0aa8d70834bc38c40dc",
|
||||
);
|
||||
expect(PERL_ENGINE_LOCK.prebuilt.files["emperl.wasm"]).toEqual(
|
||||
expect.objectContaining({
|
||||
bytes: 3_734_063,
|
||||
sha256:
|
||||
"f1d49c4514c7332a57992c4a2444fd6a56ae3b5e6651b4fd484852a641e5e4ec",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("builds byte-identical offline packs and installs one atomically", async () => {
|
||||
const directory = await mkdtemp(path.join(tmpdir(), "regex-perl-pack-"));
|
||||
temporaryDirectories.push(directory);
|
||||
const prebuilt = await makeExtractedPrebuilt(directory);
|
||||
const first = path.join(directory, "first");
|
||||
const second = path.join(directory, "second");
|
||||
|
||||
await buildPerlPack({ prebuiltDirectory: prebuilt, output: first });
|
||||
await buildPerlPack({ prebuiltDirectory: prebuilt, output: second });
|
||||
|
||||
for (const file of packFiles) {
|
||||
expect(await digest(path.join(first, file)), file).toBe(
|
||||
await digest(path.join(second, file)),
|
||||
);
|
||||
}
|
||||
|
||||
const fakeRoot = path.join(directory, "repository");
|
||||
await mkdir(path.join(fakeRoot, "engines"), { recursive: true });
|
||||
await cp(
|
||||
path.resolve("engines", "perl"),
|
||||
path.join(fakeRoot, "engines", "perl"),
|
||||
{ recursive: true },
|
||||
);
|
||||
const oldTarget = path.join(fakeRoot, "public", "engines", "perl");
|
||||
await mkdir(oldTarget, { recursive: true });
|
||||
await writeFile(path.join(oldTarget, "old-marker"), "old\n", "utf8");
|
||||
|
||||
const installed = await installPerlPack(first, fakeRoot);
|
||||
|
||||
expect(installed.output).toBe(oldTarget);
|
||||
await expect(
|
||||
readFile(path.join(oldTarget, "old-marker")),
|
||||
).rejects.toThrow();
|
||||
await expect(
|
||||
verifyPerlPack(oldTarget, fakeRoot, { smoke: false }),
|
||||
).resolves.toMatchObject({ engineVersion: "5.28.1" });
|
||||
}, 120_000);
|
||||
|
||||
it("rejects extra pack entries and drifted extracted inputs", async () => {
|
||||
const directory = await mkdtemp(path.join(tmpdir(), "regex-perl-reject-"));
|
||||
temporaryDirectories.push(directory);
|
||||
const pack = path.join(directory, "pack");
|
||||
await cp(installedPack, pack, { recursive: true });
|
||||
await writeFile(path.join(pack, "unexpected"), "not allowed\n", "utf8");
|
||||
await expect(
|
||||
verifyPerlPack(pack, path.resolve("."), { smoke: false }),
|
||||
).rejects.toThrow("must contain only");
|
||||
|
||||
const prebuilt = await makeExtractedPrebuilt(directory);
|
||||
await writeFile(path.join(prebuilt, "emperl.wasm"), "not wasm\n");
|
||||
await expect(
|
||||
buildPerlPack({
|
||||
prebuiltDirectory: prebuilt,
|
||||
output: path.join(directory, "rejected"),
|
||||
}),
|
||||
).rejects.toThrow("pinned WebPerl release");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user