mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
perf(test): use prebuilt hook install fixtures
This commit is contained in:
@@ -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
test/fixtures/hooks-install/npm-pack-hooks.tgz
vendored
Normal file
BIN
test/fixtures/hooks-install/npm-pack-hooks.tgz
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/hooks-install/tar-evil-id.tar
vendored
Normal file
BIN
test/fixtures/hooks-install/tar-evil-id.tar
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/hooks-install/tar-hooks.tar
vendored
Normal file
BIN
test/fixtures/hooks-install/tar-hooks.tar
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/hooks-install/tar-reserved-id.tar
vendored
Normal file
BIN
test/fixtures/hooks-install/tar-reserved-id.tar
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/hooks-install/tar-traversal.tar
vendored
Normal file
BIN
test/fixtures/hooks-install/tar-traversal.tar
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/hooks-install/zip-hooks.zip
vendored
Normal file
BIN
test/fixtures/hooks-install/zip-hooks.zip
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/hooks-install/zip-traversal.zip
vendored
Normal file
BIN
test/fixtures/hooks-install/zip-traversal.zip
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user