59 lines
3.2 KiB
JavaScript
59 lines
3.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import { cleanupServerJobDirectory, createServerJobDirectory, prepareServerJobWorkspace } from "../../../tools/web/server-job-isolation.mjs";
|
|
|
|
test("M13-04A creates unpredictable one-shot directories and cleans them once", async () => {
|
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), "m13-04a-job-root-"));
|
|
try {
|
|
const first = await createServerJobDirectory(root, "server:job-one");
|
|
const second = await createServerJobDirectory(root, "server:job-two");
|
|
assert.notEqual(first.directoryName, second.directoryName);
|
|
assert.notEqual(first.directoryName, first.jobId);
|
|
assert.match(first.directoryName, /^\.blender-job-[0-9a-f-]+-[A-Za-z0-9]+$/);
|
|
assert.equal((await fs.stat(first.path)).mode & 0o777, 0o700);
|
|
assert.equal((await fs.stat(second.path)).mode & 0o777, 0o700);
|
|
const cleanedFirst = await cleanupServerJobDirectory(first);
|
|
const cleanedSecond = await cleanupServerJobDirectory(second);
|
|
assert.equal(cleanedFirst.state, "CLEANED");
|
|
assert.equal(cleanedFirst.cleanupCount, 1);
|
|
assert.equal(cleanedSecond.cleanupCount, 1);
|
|
await assert.rejects(fs.stat(first.path), { code: "ENOENT" });
|
|
await assert.rejects(fs.stat(second.path), { code: "ENOENT" });
|
|
assert.equal((await cleanupServerJobDirectory(cleanedFirst)).cleanupCount, 1);
|
|
} finally {
|
|
await fs.rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("M13-04A rejects unsafe roots, IDs and cleanup escapes", async () => {
|
|
await assert.rejects(createServerJobDirectory("relative-root", "server:job"), /SERVER_JOB_DIRECTORY_INVALID/);
|
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), "m13-04a-invalid-root-"));
|
|
try {
|
|
await assert.rejects(createServerJobDirectory(root, "../escape"), /SERVER_JOB_DIRECTORY_INVALID/);
|
|
await assert.rejects(cleanupServerJobDirectory({ schemaVersion: 1, root, path: path.join(root, "other"), state: "ALLOCATED" }), /SERVER_JOB_DIRECTORY_INVALID/);
|
|
} finally {
|
|
await fs.rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("M13-04B isolates read-only source from writable output", async () => {
|
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), "m13-04b-workspace-"));
|
|
try {
|
|
const job = await createServerJobDirectory(root, "server:job-mount");
|
|
const workspace = await prepareServerJobWorkspace(job, new Uint8Array([1, 2, 3]));
|
|
assert.notEqual(path.dirname(workspace.sourcePath), workspace.outputDirectory);
|
|
assert.equal((await fs.stat(workspace.sourceDirectory)).mode & 0o777, 0o555);
|
|
assert.equal((await fs.stat(workspace.sourcePath)).mode & 0o777, 0o444);
|
|
assert.equal((await fs.stat(workspace.outputDirectory)).mode & 0o777, 0o700);
|
|
await assert.rejects(fs.writeFile(workspace.sourcePath, new Uint8Array([9])), { code: "EACCES" });
|
|
await fs.writeFile(path.join(workspace.outputDirectory, "result.bin"), new Uint8Array([4, 5]));
|
|
assert.deepEqual([...await fs.readFile(path.join(workspace.outputDirectory, "result.bin"))], [4, 5]);
|
|
await cleanupServerJobDirectory(job);
|
|
} finally {
|
|
await fs.rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|