@@ -11,6 +11,7 @@ Module: Unit test for call graph generation
11
11
#include < testing-utils/catch.hpp>
12
12
13
13
#include < analyses/call_graph.h>
14
+ #include < analyses/call_graph_helpers.h>
14
15
15
16
#include < util/symbol_table.h>
16
17
#include < util/std_code.h>
@@ -160,12 +161,24 @@ SCENARIO("call_graph",
160
161
}
161
162
}
162
163
164
+ WHEN (" A call-graph is constructed rooted at B" )
165
+ {
166
+ call_grapht call_graph_from_b =
167
+ call_grapht::create_from_root_function (goto_model, " B" , false );
168
+ THEN (" We expect only B -> C and B -> D in the resulting graph" )
169
+ {
170
+ const auto &check_graph=call_graph_from_b.graph ;
171
+ REQUIRE (check_graph.size ()==2 );
172
+ REQUIRE (multimap_key_matches (check_graph, " B" , {" C" , " D" }));
173
+ }
174
+ }
175
+
163
176
WHEN (" The call graph is exported as a grapht" )
164
177
{
165
- call_grapht::directed_call_grapht exported=
178
+ call_grapht::directed_grapht exported=
166
179
call_graph_from_goto_functions.get_directed_graph ();
167
180
168
- typedef call_grapht::directed_call_grapht ::node_indext node_indext;
181
+ typedef call_grapht::directed_grapht ::node_indext node_indext;
169
182
std::map<irep_idt, node_indext> nodes_by_name;
170
183
for (node_indext i=0 ; i<exported.size (); ++i)
171
184
nodes_by_name[exported[i].function ]=i;
@@ -179,15 +192,51 @@ SCENARIO("call_graph",
179
192
REQUIRE (exported.has_edge (nodes_by_name[" B" ], nodes_by_name[" C" ]));
180
193
REQUIRE (exported.has_edge (nodes_by_name[" B" ], nodes_by_name[" D" ]));
181
194
}
195
+
196
+ THEN (" We expect A to have successors {A, B}" )
197
+ {
198
+ std::set<irep_idt> successors = get_callees (exported, " A" );
199
+ REQUIRE (successors.size () == 2 );
200
+ REQUIRE (successors.count (" A" ));
201
+ REQUIRE (successors.count (" B" ));
202
+ }
203
+
204
+ THEN (" We expect C to have predecessors {B}" )
205
+ {
206
+ std::set<irep_idt> predecessors = get_callers (exported, " C" );
207
+ REQUIRE (predecessors.size () == 1 );
208
+ REQUIRE (predecessors.count (" B" ));
209
+ }
210
+
211
+ THEN (" We expect all of {A, B, C, D} to be reachable from A" )
212
+ {
213
+ std::set<irep_idt> successors =
214
+ get_reachable_functions (exported, " A" );
215
+ REQUIRE (successors.size () == 4 );
216
+ REQUIRE (successors.count (" A" ));
217
+ REQUIRE (successors.count (" B" ));
218
+ REQUIRE (successors.count (" C" ));
219
+ REQUIRE (successors.count (" D" ));
220
+ }
221
+
222
+ THEN (" We expect {D, B, A} to be able to reach D" )
223
+ {
224
+ std::set<irep_idt> predecessors =
225
+ get_reaching_functions (exported, " D" );
226
+ REQUIRE (predecessors.size () == 3 );
227
+ REQUIRE (predecessors.count (" A" ));
228
+ REQUIRE (predecessors.count (" B" ));
229
+ REQUIRE (predecessors.count (" D" ));
230
+ }
182
231
}
183
232
184
233
WHEN (" The call graph, with call sites, is exported as a grapht" )
185
234
{
186
235
call_grapht call_graph_from_goto_functions (goto_model, true );
187
- call_grapht::directed_call_grapht exported=
236
+ call_grapht::directed_grapht exported=
188
237
call_graph_from_goto_functions.get_directed_graph ();
189
238
190
- typedef call_grapht::directed_call_grapht ::node_indext node_indext;
239
+ typedef call_grapht::directed_grapht ::node_indext node_indext;
191
240
std::map<irep_idt, node_indext> nodes_by_name;
192
241
for (node_indext i=0 ; i<exported.size (); ++i)
193
242
nodes_by_name[exported[i].function ]=i;
0 commit comments