perf(test): use prebuilt hook install fixtures
This commit is contained in:
+10
-166
@@ -1,50 +1,27 @@
|
||||
import JSZip from "jszip";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import fsPromises from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import * as tar from "tar";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const fixtureRoot = path.join(os.tmpdir(), `openclaw-hook-install-${randomUUID()}`);
|
||||
let tempDirIndex = 0;
|
||||
|
||||
let zipHooksBuffer: Buffer;
|
||||
let zipTraversalBuffer: Buffer;
|
||||
let tarHooksBuffer: Buffer;
|
||||
let tarTraversalBuffer: Buffer;
|
||||
let tarEvilIdBuffer: Buffer;
|
||||
let tarReservedIdBuffer: Buffer;
|
||||
let npmPackHooksBuffer: Buffer;
|
||||
const fixturesDir = path.resolve(process.cwd(), "test", "fixtures", "hooks-install");
|
||||
const zipHooksBuffer = fs.readFileSync(path.join(fixturesDir, "zip-hooks.zip"));
|
||||
const zipTraversalBuffer = fs.readFileSync(path.join(fixturesDir, "zip-traversal.zip"));
|
||||
const tarHooksBuffer = fs.readFileSync(path.join(fixturesDir, "tar-hooks.tar"));
|
||||
const tarTraversalBuffer = fs.readFileSync(path.join(fixturesDir, "tar-traversal.tar"));
|
||||
const tarEvilIdBuffer = fs.readFileSync(path.join(fixturesDir, "tar-evil-id.tar"));
|
||||
const tarReservedIdBuffer = fs.readFileSync(path.join(fixturesDir, "tar-reserved-id.tar"));
|
||||
const npmPackHooksBuffer = fs.readFileSync(path.join(fixturesDir, "npm-pack-hooks.tgz"));
|
||||
|
||||
vi.mock("../process/exec.js", () => ({
|
||||
runCommandWithTimeout: vi.fn(),
|
||||
}));
|
||||
|
||||
async function packToArchive({
|
||||
pkgDir,
|
||||
outDir,
|
||||
outName,
|
||||
}: {
|
||||
pkgDir: string;
|
||||
outDir: string;
|
||||
outName: string;
|
||||
}) {
|
||||
const dest = path.join(outDir, outName);
|
||||
fs.rmSync(dest, { force: true });
|
||||
await tar.c(
|
||||
{
|
||||
gzip: true,
|
||||
file: dest,
|
||||
cwd: path.dirname(pkgDir),
|
||||
},
|
||||
[path.basename(pkgDir)],
|
||||
);
|
||||
return dest;
|
||||
}
|
||||
|
||||
function makeTempDir() {
|
||||
fs.mkdirSync(fixtureRoot, { recursive: true });
|
||||
const dir = path.join(fixtureRoot, `case-${tempDirIndex++}`);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
return dir;
|
||||
@@ -54,139 +31,6 @@ const { runCommandWithTimeout } = await import("../process/exec.js");
|
||||
const { installHooksFromArchive, installHooksFromNpmSpec, installHooksFromPath } =
|
||||
await import("./install.js");
|
||||
|
||||
beforeAll(async () => {
|
||||
fs.mkdirSync(fixtureRoot, { recursive: true });
|
||||
|
||||
const zipHooks = new JSZip();
|
||||
zipHooks.file(
|
||||
"package/package.json",
|
||||
JSON.stringify({
|
||||
name: "@openclaw/zip-hooks",
|
||||
version: "0.0.1",
|
||||
openclaw: { hooks: ["./hooks/zip-hook"] },
|
||||
}),
|
||||
);
|
||||
zipHooks.file(
|
||||
"package/hooks/zip-hook/HOOK.md",
|
||||
[
|
||||
"---",
|
||||
"name: zip-hook",
|
||||
"description: Zip hook",
|
||||
'metadata: {"openclaw":{"events":["command:new"]}}',
|
||||
"---",
|
||||
"",
|
||||
"# Zip Hook",
|
||||
].join("\n"),
|
||||
);
|
||||
zipHooks.file("package/hooks/zip-hook/handler.ts", "export default async () => {};\n");
|
||||
zipHooksBuffer = await zipHooks.generateAsync({ type: "nodebuffer" });
|
||||
|
||||
const zipTraversal = new JSZip();
|
||||
zipTraversal.file("../pwned.txt", "nope\n");
|
||||
zipTraversalBuffer = await zipTraversal.generateAsync({ type: "nodebuffer" });
|
||||
|
||||
const makeTarWithPackage = async (params: {
|
||||
packageName: string;
|
||||
hookName: string;
|
||||
}): Promise<Buffer> => {
|
||||
const workDir = makeTempDir();
|
||||
const archivePath = path.join(workDir, "hooks.tar");
|
||||
const pkgDir = path.join(workDir, "package");
|
||||
fs.mkdirSync(path.join(pkgDir, "hooks", params.hookName), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: params.packageName,
|
||||
version: "0.0.1",
|
||||
openclaw: { hooks: [`./hooks/${params.hookName}`] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "hooks", params.hookName, "HOOK.md"),
|
||||
[
|
||||
"---",
|
||||
`name: ${params.hookName}`,
|
||||
`description: ${params.hookName}`,
|
||||
'metadata: {"openclaw":{"events":["command:new"]}}',
|
||||
"---",
|
||||
"",
|
||||
"# Hook",
|
||||
].join("\n"),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "hooks", params.hookName, "handler.ts"),
|
||||
"export default async () => {};\n",
|
||||
"utf-8",
|
||||
);
|
||||
await tar.c({ cwd: workDir, file: archivePath }, ["package"]);
|
||||
return await fsPromises.readFile(archivePath);
|
||||
};
|
||||
|
||||
tarHooksBuffer = await makeTarWithPackage({
|
||||
packageName: "@openclaw/tar-hooks",
|
||||
hookName: "tar-hook",
|
||||
});
|
||||
tarEvilIdBuffer = await makeTarWithPackage({ packageName: "@evil/..", hookName: "evil-hook" });
|
||||
tarReservedIdBuffer = await makeTarWithPackage({
|
||||
packageName: "@evil/.",
|
||||
hookName: "reserved-hook",
|
||||
});
|
||||
|
||||
const makeTraversalTar = async (): Promise<Buffer> => {
|
||||
const workDir = makeTempDir();
|
||||
const insideDir = path.join(workDir, "inside");
|
||||
fs.mkdirSync(insideDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(workDir, "outside.txt"), "nope\n", "utf-8");
|
||||
const archivePath = path.join(workDir, "traversal.tar");
|
||||
await tar.c({ cwd: insideDir, file: archivePath }, ["../outside.txt"]);
|
||||
return await fsPromises.readFile(archivePath);
|
||||
};
|
||||
|
||||
tarTraversalBuffer = await makeTraversalTar();
|
||||
|
||||
const makeNpmPackTgz = async (): Promise<Buffer> => {
|
||||
const workDir = makeTempDir();
|
||||
const packedName = "test-hooks-0.0.1.tgz";
|
||||
const pkgDir = path.join(workDir, "package");
|
||||
fs.mkdirSync(path.join(pkgDir, "hooks", "one-hook"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@openclaw/test-hooks",
|
||||
version: "0.0.1",
|
||||
openclaw: { hooks: ["./hooks/one-hook"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "hooks", "one-hook", "HOOK.md"),
|
||||
[
|
||||
"---",
|
||||
"name: one-hook",
|
||||
"description: One hook",
|
||||
'metadata: {"openclaw":{"events":["command:new"]}}',
|
||||
"---",
|
||||
"",
|
||||
"# One Hook",
|
||||
].join("\n"),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "hooks", "one-hook", "handler.ts"),
|
||||
"export default async () => {};\n",
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const packTmpDir = makeTempDir();
|
||||
const archivePath = await packToArchive({ pkgDir, outDir: packTmpDir, outName: packedName });
|
||||
return await fsPromises.readFile(archivePath);
|
||||
};
|
||||
|
||||
npmPackHooksBuffer = await makeNpmPackTgz();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
try {
|
||||
fs.rmSync(fixtureRoot, { recursive: true, force: true });
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user