test: align boundary fixtures with producer contracts

Model GDB console completion, use real directory reads and cleanup for late-enumeration failures, and distinguish supported PTX pointer qualifiers from unknown declarations. Preserve original assertion and cleanup failures through scoped test finalizers.
This commit is contained in:
morluto
2026-10-23 21:22:52 +08:00
parent 76b56957e9
commit bc411c24be
3 changed files with 119 additions and 103 deletions
@@ -1,4 +1,3 @@
import type { Dir, Dirent } from "node:fs";
import { mkdir, symlink, writeFile } from "node:fs/promises";
import { join } from "node:path";
@@ -7,30 +6,42 @@ import { expect, it, vi } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { importReferenceSource } from "../../support/referenceSourceResourceScope.js";
const { opendirMock } = vi.hoisted(() => ({ opendirMock: vi.fn() }));
vi.mock("node:fs/promises", async (importOriginal) => ({
...(await importOriginal<typeof import("node:fs/promises")>()),
opendir: opendirMock,
const injectedReadFailure = vi.hoisted(() => ({
path: undefined as string | undefined,
error: undefined as Error | undefined,
}));
const directoryHandle = (items: readonly (string | Error | null)[]): Dir => {
let index = 0;
vi.mock("node:fs/promises", async (importOriginal) => {
const actual = await importOriginal<typeof import("node:fs/promises")>();
return {
async read() {
const item = items[index++];
if (item instanceof Error) throw item;
return item === null || item === undefined
? null
: ({ name: item } as Dirent);
...actual,
opendir: async (...args: Parameters<typeof actual.opendir>) => {
const handle = await actual.opendir(...args);
const [path] = args;
const { path: failingPath, error } = injectedReadFailure;
if (path !== failingPath || error === undefined) return handle;
const read = handle.read.bind(handle);
let failureInjected = false;
Object.defineProperty(handle, "read", {
configurable: true,
value: async () => {
const entry = await read();
if (entry === null && !failureInjected) {
failureInjected = true;
throw error;
}
return entry;
},
});
return handle;
},
async close() {},
} as unknown as Dir;
};
};
});
it.skipIf(process.platform === "win32")(
"traverses directories lstat-observed before their parent enumeration failed",
async () => {
async ({ onTestFinished }) => {
const root = await createTestTempDirectory(
"rea-queued-source-directories-",
);
@@ -46,18 +57,11 @@ it.skipIf(process.platform === "win32")(
new Error("injected directory read failure"),
{ code: "EIO" },
);
opendirMock.mockImplementation(async (path: string) => {
if (path === root) return directoryHandle(["container", null]);
if (path === container)
return directoryHandle([
"visible.txt",
"hidden",
"alias-file.txt",
"alias-directory",
readFailure,
]);
if (path === hidden) return directoryHandle(["target.txt", null]);
throw new Error(`Unexpected directory traversal: ${path}`);
injectedReadFailure.path = container;
injectedReadFailure.error = readFailure;
onTestFinished(() => {
injectedReadFailure.path = undefined;
injectedReadFailure.error = undefined;
});
const imported = await importReferenceSource({
@@ -73,6 +77,7 @@ it.skipIf(process.platform === "win32")(
path: "container",
kind: "directory",
tree_state: "unreadable",
limitations: [expect.stringContaining(readFailure.message)],
}),
expect.objectContaining({
path: "container/hidden",
+19 -1
View File
@@ -429,7 +429,7 @@ it.each([
]);
});
it.each([
["parameter", ".u64 output", ".u64 .ptr .global output"],
["parameter", ".u64 output", ".u64 .vendor_specific output"],
["shared", "scratch[32]", "scratch[]"],
] as const)(
"marks unknown PTX %s declarations partial while retaining known facts",
@@ -459,6 +459,24 @@ it.each([
}
},
);
it("keeps supported PTX pointer qualifiers complete through the provider", async () => {
const bytes = Buffer.from(
ptxFixture.replace(".u64 output", ".u64 .ptr .global output"),
);
const result = await inspect(bytes);
if (!result.ok) throw result.error;
expect(result.value.objects[0]!.inspection).toBe("complete");
expect(result.value.coverage.payloads).toBe("complete");
expect(result.value.ptx_artifacts[0]!.text).toBe(bytes.toString());
expect(result.value.kernels[0]).toMatchObject({
parameter_count: 2,
parameter_bytes: 12,
parameters: [
{ name: "output", offset: 0, size: 8 },
{ name: "value", offset: 8, size: 4 },
],
});
});
it.each(["whitespace", "comment"] as const)(
"recognizes standalone PTX after more than 64 KiB of leading %s",
async (kind) => {
+65 -72
View File
@@ -1,12 +1,12 @@
import { randomUUID } from "node:crypto";
import { chmod, mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { chmod, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
import { McpServer } from "@modelcontextprotocol/server";
import { expect, it } from "vitest";
import { expect, it, onTestFinished } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { toolContract } from "../../../src/contracts/toolContracts.js";
import { GdbSessionManager } from "../../../src/gdb/GdbSessionManager.js";
import { silentLogger } from "../../../src/logger.js";
@@ -16,7 +16,7 @@ import { createToolResultDelivery } from "../../../src/server/toolResult.js";
it.skipIf(process.platform === "win32").each(["kill", "detach"])(
"retains a valid GDB session through disposition refusal and explicit %s recovery",
async (disposition) => {
const directory = await mkdtemp(join(tmpdir(), "rea-gdb-disposition-"));
const directory = await createTestTempDirectory("rea-gdb-disposition-");
const provider = join(directory, "fake-gdb.mjs");
await writeFile(
provider,
@@ -33,6 +33,10 @@ createInterface({ input: process.stdin }).on('line', line => {
process.stdout.write(token + '^running\\n*stopped,reason="breakpoint-hit",thread-id="1"\\n(gdb)\\n');
return;
}
if (command === '-gdb-show mi-async') {
process.stdout.write(token + '^done,value="off"\\n(gdb)\\n');
return;
}
const disposition = command === '-interpreter-exec console "kill"' || command === '-interpreter-exec console "detach"';
if (disposition) live = false;
const result = command === '-list-thread-groups --recurse 1'
@@ -50,10 +54,12 @@ createInterface({ input: process.stdin }).on('line', line => {
platform: "linux",
environment: { REA_GDB_COMMAND: provider },
});
onTestFinished(() => manager.closeAll());
const server = new McpServer({
name: "gdb-disposition-test",
version: "1",
});
onTestFinished(() => server.close());
registerGdbTools(
server,
manager,
@@ -61,80 +67,67 @@ createInterface({ input: process.stdin }).on('line', line => {
createToolResultDelivery(undefined),
);
const client = new Client({ name: "gdb-disposition-test", version: "1" });
onTestFinished(() => client.close());
const [clientTransport, serverTransport] =
InMemoryTransport.createLinkedPair();
let sessionId: string | undefined;
try {
await server.connect(serverTransport);
await client.connect(clientTransport);
const started = await client.callTool({
name: "start_gdb_session",
arguments: {},
});
sessionId = toolContract("start_gdb_session").outputSchema.parse(
started.structuredContent,
).session_id;
const running = await client.callTool({
name: "gdb_console",
arguments: { session_id: sessionId, command: "run" },
});
expect(running.isError).not.toBe(true);
for (let attempt = 0; attempt < 2; attempt += 1) {
const refusal = await client.callTool({
name: "close_gdb_session",
arguments: { session_id: sessionId },
});
expect(refusal.isError).toBe(true);
expect(refusal.structuredContent).toMatchObject({
error: {
code: "capability_unavailable",
category: "unavailable",
retryable: true,
remediation: { action: expect.stringContaining("gdb_console") },
details: {
provider_id: "gnu.gdb",
operation: "close_gdb_session",
reason: expect.stringContaining("inferior"),
},
},
});
expect(JSON.stringify(refusal.structuredContent)).not.toContain(
"invalid_value",
);
expect(manager.status(sessionId)?.state).toBe("ready");
}
const disposed = await client.callTool({
name: "gdb_console",
arguments: { session_id: sessionId, command: disposition },
});
expect(disposed.isError).not.toBe(true);
const closed = await client.callTool({
await server.connect(serverTransport);
await client.connect(clientTransport);
const started = await client.callTool({
name: "start_gdb_session",
arguments: {},
});
const sessionId = toolContract("start_gdb_session").outputSchema.parse(
started.structuredContent,
).session_id;
const running = await client.callTool({
name: "gdb_console",
arguments: { session_id: sessionId, command: "run" },
});
expect(running.isError).not.toBe(true);
for (let attempt = 0; attempt < 2; attempt += 1) {
const refusal = await client.callTool({
name: "close_gdb_session",
arguments: { session_id: sessionId },
});
expect(closed.isError).not.toBe(true);
expect(closed.structuredContent).toMatchObject({
target_state: "none_observed",
expect(refusal.isError).toBe(true);
expect(refusal.structuredContent).toMatchObject({
error: {
code: "capability_unavailable",
category: "unavailable",
retryable: true,
remediation: { action: expect.stringContaining("gdb_console") },
details: {
provider_id: "gnu.gdb",
operation: "close_gdb_session",
reason: expect.stringContaining("inferior"),
},
},
});
expect(manager.status(sessionId)).toBeUndefined();
const unknown = await client.callTool({
name: "close_gdb_session",
arguments: { session_id: randomUUID() },
});
expect(unknown.structuredContent).toMatchObject({
error: { code: "invalid_request", category: "invalid_input" },
});
} finally {
if (sessionId !== undefined && manager.status(sessionId) !== undefined) {
const disposed = await manager.execute(sessionId, "kill");
if (!disposed.ok) throw disposed.error;
const closed = await manager.close(sessionId);
if (!closed.ok) throw closed.error;
}
await client.close();
await server.close();
await manager.closeAll();
await rm(directory, { recursive: true, force: true });
expect(JSON.stringify(refusal.structuredContent)).not.toContain(
"invalid_value",
);
expect(manager.status(sessionId)?.state).toBe("ready");
}
const disposed = await client.callTool({
name: "gdb_console",
arguments: { session_id: sessionId, command: disposition },
});
expect(disposed.isError).not.toBe(true);
const closed = await client.callTool({
name: "close_gdb_session",
arguments: { session_id: sessionId },
});
expect(closed.isError).not.toBe(true);
expect(closed.structuredContent).toMatchObject({
target_state: "none_observed",
});
expect(manager.status(sessionId)).toBeUndefined();
const unknown = await client.callTool({
name: "close_gdb_session",
arguments: { session_id: randomUUID() },
});
expect(unknown.structuredContent).toMatchObject({
error: { code: "invalid_request", category: "invalid_input" },
});
},
);