mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
test(verifiers): assert shared command diagnostics and identity (#7002)
This commit is contained in:
@@ -78,8 +78,10 @@ export async function createPackageVerifierCommands(options) {
|
||||
packageCommands = await createActualCommands({
|
||||
...options,
|
||||
launcher: async (input) => {
|
||||
const nested = input.arguments.includes(nestedVerifier);
|
||||
if (nested) appendFileSync(process.env.OWNERSHIP_EVENTS, JSON.stringify({ kind: "command", runId: input.runId, inheritedRunId: process.env.REA_PROCESS_RUN_ID }) + "\\n");
|
||||
const acquired = await spawnOwnedProviderProcess(input);
|
||||
if (!input.arguments.includes(nestedVerifier)) return acquired;
|
||||
if (!nested) return acquired;
|
||||
return {
|
||||
...acquired,
|
||||
cleanup: async () => {
|
||||
@@ -192,11 +194,26 @@ if (cleanup !== undefined) {
|
||||
}]);
|
||||
`;
|
||||
|
||||
const expectRootCleanupAfterProcessExit = (
|
||||
const expectOwnedCleanup = (
|
||||
events: readonly Record<string, unknown>[],
|
||||
runtime: string,
|
||||
readyPids: readonly number[],
|
||||
): void => {
|
||||
const commands = events.filter(({ kind }) => kind === "command");
|
||||
expect(commands).toHaveLength(1);
|
||||
const command = commands[0]!;
|
||||
expect(command).toMatchObject({
|
||||
runId: expect.any(String),
|
||||
inheritedRunId: expect.any(String),
|
||||
});
|
||||
expect(command.runId).not.toBe("");
|
||||
expect(command.runId).not.toBe(command.inheritedRunId);
|
||||
expect(events.filter(({ kind }) => kind === "ready")).toEqual([
|
||||
expect.objectContaining({
|
||||
runId: command.runId,
|
||||
descendantRunId: command.runId,
|
||||
}),
|
||||
]);
|
||||
expect(events.filter(({ kind }) => kind === "root-close")).toEqual([
|
||||
{ kind: "root-close", runtime, rootExists: true, readyPids, livePids: [] },
|
||||
]);
|
||||
@@ -219,12 +236,7 @@ const expectHarnessFailureCleanup = async (
|
||||
.map((line) => JSON.parse(line));
|
||||
const ready = events.find(({ kind }) => kind === "ready");
|
||||
expect(ready).toBeDefined();
|
||||
expect(ready.runId).toMatch(/^rea-package-command-/);
|
||||
expect(ready.descendantRunId).toBe(ready.runId);
|
||||
expectRootCleanupAfterProcessExit(events, ready.runtime, [
|
||||
ready.leader,
|
||||
ready.descendant,
|
||||
]);
|
||||
expectOwnedCleanup(events, ready.runtime, [ready.leader, ready.descendant]);
|
||||
};
|
||||
|
||||
// Packaging, installation, and WABT are authored boundaries. The copied verifier,
|
||||
@@ -316,8 +328,6 @@ it.skipIf(process.platform === "win32").each([
|
||||
const observed = JSON.parse(await readFile(report, "utf8"));
|
||||
expect(observed.reason).toBe("timeout");
|
||||
expect(observed.pids).toHaveLength(2);
|
||||
expect(observed.runId).toMatch(/^rea-package-command-/);
|
||||
expect(observed.descendantRunId).toBe(observed.runId);
|
||||
expect(observed.rootExists).toBe(denied);
|
||||
expect(observed.livePids.sort()).toEqual(
|
||||
denied ? [...observed.pids].sort() : [],
|
||||
@@ -346,11 +356,7 @@ it.skipIf(process.platform === "win32").each([
|
||||
}),
|
||||
]);
|
||||
expect(recorded.filter(({ kind }) => kind === "install")).toHaveLength(1);
|
||||
expectRootCleanupAfterProcessExit(
|
||||
recorded,
|
||||
observed.runtime,
|
||||
observed.pids,
|
||||
);
|
||||
expectOwnedCleanup(recorded, observed.runtime, observed.pids);
|
||||
expect(
|
||||
recorded.filter(
|
||||
({ kind, denied: refusal }) =>
|
||||
|
||||
@@ -40,6 +40,19 @@ const hopper = packedFiles[0]!;
|
||||
const validSource =
|
||||
'# Unicode source: 雨\nraise RuntimeError("Packed source must never execute")\n';
|
||||
|
||||
const expectedPythonCommandFailure = (diagnostic: string | RegExp) => ({
|
||||
name: "VerifierCommandExitError",
|
||||
code: 1,
|
||||
snapshot: {
|
||||
stderr: {
|
||||
text:
|
||||
typeof diagnostic === "string"
|
||||
? expect.stringContaining(diagnostic)
|
||||
: expect.stringMatching(diagnostic),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
async function fixture(source: string = validSource, omitHopper = false) {
|
||||
const scratch = await createTestWorkspace("rea-packed-bridge-");
|
||||
const directory = scratch.root;
|
||||
@@ -115,7 +128,7 @@ try {
|
||||
await verifyPackedBridge({ ...JSON.parse(process.env.REA_PACKED_VERIFY_INPUT), commands });
|
||||
console.log(JSON.stringify({ accepted: true }));
|
||||
} catch (error) {
|
||||
console.log(JSON.stringify({ accepted: false, stderr: String(error.stderr) }));
|
||||
console.log(JSON.stringify({ accepted: false, name: error.name, code: error.code, stderr: error.snapshot?.stderr?.text }));
|
||||
}
|
||||
}, [() => commands === undefined ? root.close() : commands.close()]);`,
|
||||
],
|
||||
@@ -137,10 +150,17 @@ try {
|
||||
},
|
||||
);
|
||||
const observation = z
|
||||
.object({ accepted: z.boolean(), stderr: z.string().optional() })
|
||||
.object({
|
||||
accepted: z.boolean(),
|
||||
name: z.string().optional(),
|
||||
code: z.number().optional(),
|
||||
stderr: z.string().optional(),
|
||||
})
|
||||
.parse(JSON.parse(result.stdout));
|
||||
expect(observation).toMatchObject({
|
||||
accepted: false,
|
||||
name: "VerifierCommandExitError",
|
||||
code: 1,
|
||||
stderr: expect.stringContaining("SyntaxError"),
|
||||
});
|
||||
await expect(access(marker)).rejects.toMatchObject({ code: "ENOENT" });
|
||||
@@ -163,17 +183,17 @@ it.each(packedFiles)(
|
||||
|
||||
it("rejects a missing actual Python member even when the listing advertises it", async () => {
|
||||
const input = await fixture(validSource, true);
|
||||
await expect(verifyPackedBridge(input)).rejects.toMatchObject({
|
||||
stderr: expect.stringContaining(hopper),
|
||||
});
|
||||
await expect(verifyPackedBridge(input)).rejects.toMatchObject(
|
||||
expectedPythonCommandFailure(hopper),
|
||||
);
|
||||
expect(await readdir(input.workspace)).toEqual([]);
|
||||
});
|
||||
|
||||
it("reports invalid packed Python syntax with the member filename", async () => {
|
||||
const input = await fixture("def broken(:\n");
|
||||
await expect(verifyPackedBridge(input)).rejects.toMatchObject({
|
||||
stderr: expect.stringMatching(/hopper_bridge\.py[\s\S]*SyntaxError/u),
|
||||
});
|
||||
await expect(verifyPackedBridge(input)).rejects.toMatchObject(
|
||||
expectedPythonCommandFailure(/hopper_bridge\.py[\s\S]*SyntaxError/u),
|
||||
);
|
||||
expect(await readdir(input.workspace)).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -197,9 +217,9 @@ it.each(["valid", "invalid"] as const)(
|
||||
const parsed = verifyPackedBridge({ tarball, packedFiles, commands });
|
||||
if (kind === "valid") await parsed;
|
||||
else
|
||||
await expect(parsed).rejects.toMatchObject({
|
||||
stderr: expect.stringContaining("SyntaxError"),
|
||||
});
|
||||
await expect(parsed).rejects.toMatchObject(
|
||||
expectedPythonCommandFailure("SyntaxError"),
|
||||
);
|
||||
expect(await readdir(root.path)).toEqual(["pack"]);
|
||||
expect(await readFile(tarball)).toEqual(await readFile(input.tarball));
|
||||
}, [() => (commands === undefined ? root.close() : commands.close())]);
|
||||
@@ -230,9 +250,9 @@ it.each(["symlink", "hardlink", "directory"])(
|
||||
hopper,
|
||||
kind,
|
||||
]);
|
||||
await expect(verifyPackedBridge(input)).rejects.toMatchObject({
|
||||
stderr: expect.stringContaining(`${hopper} is not a regular file`),
|
||||
});
|
||||
await expect(verifyPackedBridge(input)).rejects.toMatchObject(
|
||||
expectedPythonCommandFailure(`${hopper} is not a regular file`),
|
||||
);
|
||||
expect(await readdir(input.workspace)).toEqual([]);
|
||||
},
|
||||
);
|
||||
@@ -240,8 +260,8 @@ it.each(["symlink", "hardlink", "directory"])(
|
||||
it("rejects malformed archives without writing to the caller's workspace", async () => {
|
||||
const input = await fixture();
|
||||
await writeFile(input.tarball, "not a tar archive\n");
|
||||
await expect(verifyPackedBridge(input)).rejects.toMatchObject({
|
||||
stderr: expect.stringContaining("ReadError"),
|
||||
});
|
||||
await expect(verifyPackedBridge(input)).rejects.toMatchObject(
|
||||
expectedPythonCommandFailure("ReadError"),
|
||||
);
|
||||
expect(await readdir(input.workspace)).toEqual([]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user