mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 09:52:27 +00:00
74 lines
2.9 KiB
TypeScript
74 lines
2.9 KiB
TypeScript
import { mkdir, symlink, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { expect, it, onTestFinished } from "vitest";
|
|
|
|
import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js";
|
|
import { GpuCodeObjectsProvider } from "../../../src/gpu/GpuCodeObjectsProvider.js";
|
|
import { ModelArtifactProvider } from "../../../src/model/ModelArtifactProvider.js";
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
|
|
it.skipIf(process.platform === "win32")(
|
|
"explains rejected links and suggests only resolved regular-file targets",
|
|
async () => {
|
|
const root = await createTestTempDirectory("rea-rejected-links-");
|
|
const file = join(root, "file.bin");
|
|
const directory = join(root, "directory");
|
|
await writeFile(file, "fixture");
|
|
await mkdir(directory);
|
|
const links = [
|
|
{ path: join(root, "file-link"), target: file, kind: "file" },
|
|
{
|
|
path: join(root, "selected-directory"),
|
|
target: directory,
|
|
kind: "directory",
|
|
},
|
|
{
|
|
path: join(root, "selected-missing"),
|
|
target: join(root, "missing"),
|
|
kind: "missing",
|
|
},
|
|
] as const;
|
|
for (const link of links) await symlink(link.target, link.path);
|
|
const model = new ModelArtifactProvider();
|
|
const gpu = new GpuCodeObjectsProvider();
|
|
onTestFinished(async () => {
|
|
await model.close();
|
|
await gpu.close();
|
|
});
|
|
for (const link of links) {
|
|
const results = [
|
|
await model.inspect({ path: link.path, hash: "header" }),
|
|
await gpu.inspect({ path: link.path, analysis: "inventory" }),
|
|
];
|
|
for (const result of results) {
|
|
if (result.ok) throw new Error("symbolic link was admitted");
|
|
const projected = projectAnalysisError(result.error);
|
|
expect(projected.message, link.kind).toMatch(/symbolic link/iu);
|
|
expect(projected.message, link.kind).toContain(link.path);
|
|
if (link.kind === "file")
|
|
expect(projected.remediation.action).toContain(file);
|
|
else expect(projected.remediation.action).not.toContain(link.target);
|
|
}
|
|
}
|
|
},
|
|
);
|
|
|
|
it.skipIf(process.platform === "win32")(
|
|
"keeps a traversal loop distinct when the selected leaf cannot be inspected",
|
|
async () => {
|
|
const root = await createTestTempDirectory("rea-loop-links-");
|
|
const loop = join(root, "loop");
|
|
await symlink(loop, loop);
|
|
const path = join(loop, "selected");
|
|
const provider = new ModelArtifactProvider();
|
|
onTestFinished(() => provider.close());
|
|
const result = await provider.inspect({ path, hash: "header" });
|
|
if (result.ok) throw new Error("traversal loop was admitted");
|
|
const projected = projectAnalysisError(result.error);
|
|
expect(projected.message).toContain("ELOOP");
|
|
expect(projected.remediation.action).not.toContain(
|
|
"resolved regular file path",
|
|
);
|
|
},
|
|
);
|