test(pe): bind acceptance calls to advertised MCP definitions
Pass the exact named tool descriptors to SDK callTool for PE resource inspection and session inventory. Avoid full-catalog validator compilation while retaining SDK output validation, every CLI/MCP scenario, cleanup, and the unchanged 30-second deadline. The complete focused test passed locally in 7.1 seconds versus 11.0 seconds before this change; host load and CPU/memory costs were not controlled or measured. check:ci passes.
This commit is contained in:
1 parent
c324d31b45
commit
c76edbebbe
1 file changed
+43
-64
@@ -11,14 +11,17 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
import { parseMcpToolError } from "../../fixtures/mcpToolError.js";
|
||||
import { cliTest, type TestCli } from "../../support/cli/cliFixture.js";
|
||||
|
||||
type PeResourceCall = (
|
||||
arguments_: Record<string, unknown>,
|
||||
) => ReturnType<Client["callTool"]>;
|
||||
|
||||
const expectPeInputFailureAcrossAdapters = async (input: {
|
||||
readonly cli: TestCli;
|
||||
readonly client: Client;
|
||||
readonly toolName: string;
|
||||
readonly call: PeResourceCall;
|
||||
readonly path: string;
|
||||
readonly reason: "invalid_format" | "invalid_value";
|
||||
}) => {
|
||||
const { cli, client, toolName, path, reason } = input;
|
||||
const { cli, call, path, reason } = input;
|
||||
const result = await cli.run({
|
||||
arguments: ["inspect-pe-resources", path, "--json"],
|
||||
});
|
||||
@@ -31,21 +34,17 @@ const expectPeInputFailureAcrossAdapters = async (input: {
|
||||
issues: [{ path: ["path"], reason }],
|
||||
},
|
||||
});
|
||||
const response = await client.callTool({
|
||||
name: toolName,
|
||||
arguments: { path },
|
||||
});
|
||||
const response = await call({ path });
|
||||
expect(response.isError).toBe(true);
|
||||
expect(parseMcpToolError(response)).toEqual({ error: result.json });
|
||||
};
|
||||
|
||||
const expectPePaddingFailureAcrossAdapters = async (input: {
|
||||
readonly cli: TestCli;
|
||||
readonly client: Client;
|
||||
readonly toolName: string;
|
||||
readonly call: PeResourceCall;
|
||||
readonly path: string;
|
||||
}) => {
|
||||
const { cli, client, toolName, path } = input;
|
||||
const { cli, call, path } = input;
|
||||
const fixture = peResourceFixture();
|
||||
const virtualSize = fixture.bytes.readUInt32LE(fixture.sectionAt + 8);
|
||||
fixture.bytes.writeUInt32LE(
|
||||
@@ -58,10 +57,7 @@ const expectPePaddingFailureAcrossAdapters = async (input: {
|
||||
arguments: ["inspect-pe-resources", path, "--json"],
|
||||
});
|
||||
expect(cliResult.exitCode).not.toBe(0);
|
||||
const mcpResult = await client.callTool({
|
||||
name: toolName,
|
||||
arguments: { path },
|
||||
});
|
||||
const mcpResult = await call({ path });
|
||||
expect(mcpResult.isError).toBe(true);
|
||||
expect(peResourcesSchema.safeParse(mcpResult.structuredContent).success).toBe(
|
||||
false,
|
||||
@@ -70,11 +66,10 @@ const expectPePaddingFailureAcrossAdapters = async (input: {
|
||||
|
||||
const expectPeInputFailuresAcrossAdapters = async (input: {
|
||||
readonly cli: TestCli;
|
||||
readonly client: Client;
|
||||
readonly toolName: string;
|
||||
readonly call: PeResourceCall;
|
||||
readonly root: string;
|
||||
}) => {
|
||||
const { cli, client, toolName, root } = input;
|
||||
const { cli, call, root } = input;
|
||||
const malformedPath = join(root, "malformed.exe");
|
||||
await writeFile(malformedPath, Buffer.from("not a PE image"));
|
||||
for (const [path, reason] of [
|
||||
@@ -83,8 +78,7 @@ const expectPeInputFailuresAcrossAdapters = async (input: {
|
||||
] as const)
|
||||
await expectPeInputFailureAcrossAdapters({
|
||||
cli,
|
||||
client,
|
||||
toolName,
|
||||
call,
|
||||
path,
|
||||
reason,
|
||||
});
|
||||
@@ -94,13 +88,10 @@ const contract = toolContract("inspect_pe_resources");
|
||||
|
||||
const expectPeWordAlignedRecordsAcrossAdapters = async (input: {
|
||||
readonly cli: TestCli;
|
||||
readonly client: Client;
|
||||
readonly call: PeResourceCall;
|
||||
readonly root: string;
|
||||
readonly definition: Awaited<
|
||||
ReturnType<Client["listTools"]>
|
||||
>["tools"][number];
|
||||
}): Promise<void> => {
|
||||
const { cli, client, root, definition } = input;
|
||||
const { cli, call, root } = input;
|
||||
for (const plus of [false, true]) {
|
||||
for (const [index, identities] of [
|
||||
{ type: 10, name: 1, language: "AB" },
|
||||
@@ -131,10 +122,7 @@ const expectPeWordAlignedRecordsAcrossAdapters = async (input: {
|
||||
expect(report.resources[0]?.payload.sha256).toBe(
|
||||
createHash("sha256").update("opaque resource").digest("hex"),
|
||||
);
|
||||
const response = await client.callTool(
|
||||
{ name: definition.name, arguments: { path } },
|
||||
{ toolDefinition: definition },
|
||||
);
|
||||
const response = await call({ path });
|
||||
expect(response.isError).not.toBe(true);
|
||||
expect(
|
||||
contract.outputSchema.parse(response.structuredContent)
|
||||
@@ -147,7 +135,7 @@ const expectPeWordAlignedRecordsAcrossAdapters = async (input: {
|
||||
|
||||
const expectPeMappingOwnershipAcrossAdapters = async (
|
||||
cli: TestCli,
|
||||
client: Client,
|
||||
call: PeResourceCall,
|
||||
root: string,
|
||||
): Promise<void> => {
|
||||
for (const { name, payloadRva, payloadBytes, section, expectedOffset } of [
|
||||
@@ -202,8 +190,7 @@ const expectPeMappingOwnershipAcrossAdapters = async (
|
||||
if (expectedOffset === null) {
|
||||
await expectPeInputFailureAcrossAdapters({
|
||||
cli,
|
||||
client,
|
||||
toolName: contract.name,
|
||||
call,
|
||||
path,
|
||||
reason: "invalid_format",
|
||||
});
|
||||
@@ -214,10 +201,7 @@ const expectPeMappingOwnershipAcrossAdapters = async (
|
||||
});
|
||||
expect(result.exitCode, name).toBe(0);
|
||||
const evidence = contract.outputSchema.parse(result.json);
|
||||
const response = await client.callTool({
|
||||
name: contract.name,
|
||||
arguments: { path },
|
||||
});
|
||||
const response = await call({ path });
|
||||
expect(response.isError, name).not.toBe(true);
|
||||
const mcp = contract.outputSchema.parse(response.structuredContent);
|
||||
expect(mcp.subject).toEqual(evidence.subject);
|
||||
@@ -245,7 +229,7 @@ const expectPeMappingOwnershipAcrossAdapters = async (
|
||||
|
||||
const expectPeInventoriesAcrossAdapters = async (
|
||||
cli: TestCli,
|
||||
client: Client,
|
||||
call: PeResourceCall,
|
||||
root: string,
|
||||
): Promise<void> => {
|
||||
for (const [plus, empty] of [
|
||||
@@ -304,10 +288,7 @@ const expectPeInventoriesAcrossAdapters = async (
|
||||
same_language_resource_index: null,
|
||||
},
|
||||
]);
|
||||
const response = await client.callTool({
|
||||
name: contract.name,
|
||||
arguments: { path },
|
||||
});
|
||||
const response = await call({ path });
|
||||
expect(response.isError).not.toBe(true);
|
||||
const mcp = contract.outputSchema.parse(response.structuredContent);
|
||||
expect(mcp.subject).toEqual(evidence.subject);
|
||||
@@ -351,41 +332,45 @@ cliTest(
|
||||
}),
|
||||
}),
|
||||
);
|
||||
const session = await client.callTool({
|
||||
name: "binary_session",
|
||||
arguments: {},
|
||||
});
|
||||
const call: PeResourceCall = (arguments_) =>
|
||||
client.callTool(
|
||||
{ name: definition.name, arguments: arguments_ },
|
||||
{ toolDefinition: definition },
|
||||
);
|
||||
const sessionDefinition = inventory.tools.find(
|
||||
({ name }) => name === "binary_session",
|
||||
);
|
||||
if (sessionDefinition === undefined)
|
||||
throw new Error("Missing binary_session tool contract");
|
||||
const session = await client.callTool(
|
||||
{ name: sessionDefinition.name, arguments: {} },
|
||||
{ toolDefinition: sessionDefinition },
|
||||
);
|
||||
expect(JSON.stringify(session.structuredContent)).toContain(
|
||||
"inspect_pe_resources",
|
||||
);
|
||||
await expectPeInventoriesAcrossAdapters(cli, client, root);
|
||||
await expectPeInventoriesAcrossAdapters(cli, call, root);
|
||||
await expectPeWordAlignedRecordsAcrossAdapters({
|
||||
cli,
|
||||
client,
|
||||
call,
|
||||
root,
|
||||
definition,
|
||||
});
|
||||
await expectPeMappingOwnershipAcrossAdapters(cli, client, root);
|
||||
await expectPeMappingOwnershipAcrossAdapters(cli, call, root);
|
||||
await expectPePaddingFailureAcrossAdapters({
|
||||
cli,
|
||||
client,
|
||||
toolName: contract.name,
|
||||
call,
|
||||
path: join(root, "raw-padding.exe"),
|
||||
});
|
||||
await expectPeInputFailuresAcrossAdapters({
|
||||
cli,
|
||||
client,
|
||||
toolName: contract.name,
|
||||
call,
|
||||
root,
|
||||
});
|
||||
const absent = peResourceFixture();
|
||||
absent.bytes.fill(0, absent.directoryAt, absent.directoryAt + 8);
|
||||
const path = join(root, "absent.exe");
|
||||
await writeFile(path, absent.bytes);
|
||||
const empty = await client.callTool({
|
||||
name: contract.name,
|
||||
arguments: { path },
|
||||
});
|
||||
const empty = await call({ path });
|
||||
expect(empty.isError).not.toBe(true);
|
||||
expect(
|
||||
contract.outputSchema.parse(empty.structuredContent).normalized_result,
|
||||
@@ -399,10 +384,7 @@ cliTest(
|
||||
{ path: "relative.exe" },
|
||||
{ path, extra: true },
|
||||
]) {
|
||||
const rejected = await client.callTool({
|
||||
name: contract.name,
|
||||
arguments: arguments_,
|
||||
});
|
||||
const rejected = await call(arguments_);
|
||||
expect(rejected.isError).toBe(true);
|
||||
expect(
|
||||
contract.outputSchema.safeParse(rejected.structuredContent).success,
|
||||
@@ -412,10 +394,7 @@ cliTest(
|
||||
damaged.bytes.writeUInt32LE(17, damaged.directoryAt + 4);
|
||||
const badPath = join(root, "damaged.exe");
|
||||
await writeFile(badPath, damaged.bytes);
|
||||
const rejected = await client.callTool({
|
||||
name: contract.name,
|
||||
arguments: { path: badPath },
|
||||
});
|
||||
const rejected = await call({ path: badPath });
|
||||
expect(rejected.isError).toBe(true);
|
||||
expect(
|
||||
contract.outputSchema.safeParse(rejected.structuredContent).success,
|
||||
|
||||
Reference in new issue
Block a user