* fix(call-path): keep caller-only unknown coverage from blocking not_found build_call_path expands only callee edges, so relationship coverage that is unknown solely because callers are unobservable (the modern headless IDA profile) no longer marks the searched callee closure incomplete. The caller caveat stays visible in limitations, and callee-side unknowns still yield unknown. Fixes #2322. * test(call-path): cover IDA-capped callees beside unknown callers Greptile review noted the poll-timing coverage only exercised unknown callees, leaving the partial callees IDA returns at its 500-result cap untested. Add the combined unknown-callers/partial-callees case: isCallerOnlyUnknownCoverage must stay false and buildCallPath must keep search_scope.exhaustive false, so a future change cannot silently report not_found when IDA has omitted callees.
65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
combineFunctionRelationshipCoverage,
|
|
isCallerOnlyUnknownCoverage,
|
|
} from "./functionCallCoverage.js";
|
|
import type { RelationshipCoverage } from "./relationshipCoverage.js";
|
|
|
|
const unknownCallers: RelationshipCoverage = {
|
|
status: "unknown",
|
|
reason: "Upstream xrefs do not establish direct caller relationships.",
|
|
};
|
|
const unknownCallees: RelationshipCoverage = {
|
|
status: "unknown",
|
|
reason: "Upstream callees are not observed in this profile.",
|
|
};
|
|
const cappedCallees: RelationshipCoverage = {
|
|
status: "partial",
|
|
limitations: [
|
|
"Upstream callees capped results at 500; additional callees remain unknown.",
|
|
],
|
|
};
|
|
const complete: RelationshipCoverage = { status: "complete" };
|
|
|
|
describe("isCallerOnlyUnknownCoverage", () => {
|
|
it("detects unknown callers beside complete callees", () => {
|
|
const combined = combineFunctionRelationshipCoverage(
|
|
unknownCallers,
|
|
complete,
|
|
);
|
|
expect(combined.status).toBe("unknown");
|
|
expect(isCallerOnlyUnknownCoverage(combined)).toBe(true);
|
|
});
|
|
|
|
it("rejects unknown callees beside complete callers", () => {
|
|
const combined = combineFunctionRelationshipCoverage(
|
|
complete,
|
|
unknownCallees,
|
|
);
|
|
expect(isCallerOnlyUnknownCoverage(combined)).toBe(false);
|
|
});
|
|
|
|
it("rejects unknown coverage on both sides", () => {
|
|
const combined = combineFunctionRelationshipCoverage(
|
|
unknownCallers,
|
|
unknownCallees,
|
|
);
|
|
expect(isCallerOnlyUnknownCoverage(combined)).toBe(false);
|
|
});
|
|
|
|
it("rejects unknown callers beside IDA-capped callees", () => {
|
|
const combined = combineFunctionRelationshipCoverage(
|
|
unknownCallers,
|
|
cappedCallees,
|
|
);
|
|
expect(combined.status).toBe("unknown");
|
|
expect(isCallerOnlyUnknownCoverage(combined)).toBe(false);
|
|
});
|
|
|
|
it("rejects complete coverage", () => {
|
|
const combined = combineFunctionRelationshipCoverage(complete, complete);
|
|
expect(isCallerOnlyUnknownCoverage(combined)).toBe(false);
|
|
});
|
|
});
|