fold/tests/unit/test_project_call_graph.cpp

47 lines
2.2 KiB
C++

#include <algorithm>
#include <catch2/catch_test_macros.hpp>
#include <limits>
#include <string>
#include <vector>
#include "fold/ir/call_graph.hpp"
TEST_CASE("project graph keeps overloads distinct by semantic identity", "[call-graph][identity]") {
fold::ir::ProjectCallGraph graph;
graph.addFunction("usr:f:int", "f", "a.cpp", true, "body-int");
graph.addFunction("usr:f:double", "f", "a.cpp", true, "body-double");
graph.addFunction("usr:caller", "caller", "a.cpp", true);
graph.addCallEdge("usr:caller", "usr:f:int");
CHECK(graph.nodeCount() == 3);
CHECK(graph.getNode("usr:f:int")->body_hash == "body-int");
CHECK(graph.getNode("usr:f:double")->body_hash == "body-double");
CHECK(graph.getNode("f") == nullptr); // ambiguous names fail closed
CHECK(graph.getSccId("f") == std::numeric_limits<unsigned>::max());
CHECK(graph.getCallees("caller") == std::vector<std::string>{"f"});
CHECK(graph.getCalleeIds("usr:caller") == std::vector<std::string>{"usr:f:int"});
}
TEST_CASE("project graph retains strongest typed edge and deterministic SCC identities",
"[call-graph][edge-kind]") {
fold::ir::ProjectCallGraph graph;
graph.addFunction("usr:a", "a", "a.cpp", true, {}, true);
graph.addFunction("usr:b", "b", "b.cpp", true);
graph.addFunction("unknown:usr:a", "<unknown-call>", {}, false);
graph.addCallEdge("usr:a", "usr:b", fold::ir::CallGraphEdgeKind::Conservative, 0.5);
graph.addCallEdge("usr:a", "usr:b", fold::ir::CallGraphEdgeKind::Direct, 1.0);
graph.addCallEdge("usr:b", "usr:a", fold::ir::CallGraphEdgeKind::Direct, 1.0);
graph.addCallEdge("usr:a", "unknown:usr:a", fold::ir::CallGraphEdgeKind::Unknown, 0.0);
graph.computeSCCs();
CHECK(graph.edgeCount() == 3);
CHECK(graph.edgeCount(fold::ir::CallGraphEdgeKind::Direct) == 2);
CHECK(graph.edgeCount(fold::ir::CallGraphEdgeKind::Conservative) == 0);
CHECK(graph.edgeCount(fold::ir::CallGraphEdgeKind::Unknown) == 1);
CHECK(graph.unresolvedNodeCount() == 1);
CHECK(graph.getNode("usr:a")->escapes);
const unsigned scc = graph.getSccId("usr:a");
CHECK(scc == graph.getSccId("usr:b"));
CHECK(graph.getSccFunctionIds(scc) == std::vector<std::string>{"usr:a", "usr:b"});
}