test(mcp): retain uncertainty for empty capped IDA reference pages

Exercise the empty-but-truncated reference page through trace_feature, preserving unknown coverage without fabricating a reference row.

Fixes #2558.
This commit is contained in:
morluto committed 2026-10-14 16:10:47 +08:00
1 parent 12b3cdb804
commit ccd748635c
1 file changed
+22 -2
@@ -24,6 +24,8 @@ interface Behavior {
readonly limitations?: readonly string[];
/** Also report the first string match as a procedure match. */
readonly duplicateProcedure?: boolean;
/** Return no reference rows for this address while preserving cap metadata. */
readonly emptyXrefsOf?: string;
/** Fail the references read of this address. */
readonly failXrefsOf?: string;
readonly calls?: string[];
@@ -70,7 +72,9 @@ const provider = (behavior: Behavior = {}): AnalysisOperationPort => ({
const reported = behavior.coverage?.[address];
return ok(
createAnalysisExecution(
[address === "0x10" ? "0x20" : "0x21"],
address === behavior.emptyXrefsOf
? []
: [address === "0x10" ? "0x20" : "0x21"],
PROVIDER,
{
limitations: behavior.limitations ?? [],
@@ -92,6 +96,7 @@ const provider = (behavior: Behavior = {}): AnalysisOperationPort => ({
const expectedTrace = (
residual: readonly string[],
extraMatches: readonly object[] = [],
emptyReferenceTargets: readonly string[] = [],
) => ({
query: "hello",
search_mode: "literal",
@@ -116,7 +121,9 @@ const expectedTrace = (
source_address: "0x20",
containing_procedure: containing("0x20"),
})),
],
].filter(
({ target_address }) => !emptyReferenceTargets.includes(target_address),
),
truncated: residual.length > 0,
residual_unknowns: residual,
});
@@ -146,6 +153,19 @@ describe("trace_feature reference coverage", () => {
).toEqual(expectedTrace([unknownFor("0x10")]));
});
it("keeps an empty capped reference page as an unknown, not proof of absence", async () => {
const output = await trace(
provider({
coverage: { "0x10": true, "0x11": false },
emptyXrefsOf: "0x10",
}),
);
expect(output.normalized_result).toEqual(
expectedTrace([unknownFor("0x10")], [], ["0x10"]),
);
});
it("does not carry a truncation over to the next target that reports nothing", async () => {
const output = await trace(provider({ coverage: { "0x10": true } }));