Skip to content

Commit a59dea6

Browse files
committed
Add unit test checking dependence graph consistency
This ensures that the dependence graph's internal representation has been accurately transcribed to its grapht external interface, and exposes the particular case of control dependencies being preserved across callsites.
1 parent 1abc75e commit a59dea6

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed

src/analyses/dependence_graph.h

+5
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ class dep_graph_domaint:public ai_domain_baset
164164
typedef std::set<goto_programt::const_targett> depst;
165165
depst control_deps, data_deps;
166166

167+
friend const depst &
168+
dependence_graph_test_get_control_deps(const dep_graph_domaint &);
169+
friend const depst &
170+
dependence_graph_test_get_data_deps(const dep_graph_domaint &);
171+
167172
void control_dependencies(
168173
goto_programt::const_targett from,
169174
goto_programt::const_targett to,

unit/analyses/dependence_graph.cpp

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*******************************************************************\
2+
3+
Module: Unit test for dependence_graph.h
4+
5+
Author: Chris Smowton, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include <iostream>
10+
11+
#include <testing-utils/catch.hpp>
12+
#include <analyses/dependence_graph.h>
13+
#include <util/symbol_table.h>
14+
#include <util/std_code.h>
15+
#include <util/c_types.h>
16+
#include <util/arith_tools.h>
17+
#include <goto-programs/goto_convert_functions.h>
18+
#include <langapi/mode.h>
19+
#include <java_bytecode/java_bytecode_language.h>
20+
21+
static symbolt create_void_function_symbol(
22+
const irep_idt &name,
23+
const codet &code)
24+
{
25+
code_typet void_function_type;
26+
symbolt function;
27+
function.name = name;
28+
function.type = void_function_type;
29+
function.mode = ID_java;
30+
function.value = code;
31+
return function;
32+
}
33+
34+
const std::set<goto_programt::const_targett>&
35+
dependence_graph_test_get_control_deps(const dep_graph_domaint &domain)
36+
{
37+
return domain.control_deps;
38+
}
39+
40+
const std::set<goto_programt::const_targett>&
41+
dependence_graph_test_get_data_deps(const dep_graph_domaint &domain)
42+
{
43+
return domain.data_deps;
44+
}
45+
46+
SCENARIO("dependence_graph", "[core][analyses][dependence_graph]")
47+
{
48+
GIVEN("A call under a control dependency")
49+
{
50+
// Create code like:
51+
// void __CPROVER__start() {
52+
// int x;
53+
// if(NONDET(int) == 0) {
54+
// b();
55+
// x = 1;
56+
// }
57+
// }
58+
// void b() { }
59+
60+
register_language(new_java_bytecode_language);
61+
62+
goto_modelt goto_model;
63+
namespacet ns(goto_model.symbol_table);
64+
65+
typet int_type = signed_int_type();
66+
67+
symbolt x_symbol;
68+
x_symbol.name = id2string(goto_functionst::entry_point()) + "::x";
69+
x_symbol.base_name = "x";
70+
x_symbol.type = int_type;
71+
x_symbol.is_lvalue = true;
72+
x_symbol.is_state_var = true;
73+
x_symbol.is_thread_local = true;
74+
x_symbol.is_file_local = true;
75+
goto_model.symbol_table.add(x_symbol);
76+
77+
code_typet void_function_type;
78+
79+
code_blockt a_body;
80+
code_declt declare_x(x_symbol.symbol_expr());
81+
a_body.move_to_operands(declare_x);
82+
83+
code_ifthenelset if_block;
84+
85+
if_block.cond() =
86+
equal_exprt(
87+
side_effect_expr_nondett(int_type),
88+
from_integer(0, int_type));
89+
90+
code_blockt then_block;
91+
code_function_callt call;
92+
call.function() = symbol_exprt("b", void_function_type);
93+
then_block.move_to_operands(call);
94+
code_assignt assign_x(
95+
x_symbol.symbol_expr(), from_integer(1, int_type));
96+
then_block.move_to_operands(assign_x);
97+
98+
if_block.then_case() = then_block;
99+
100+
a_body.move_to_operands(if_block);
101+
102+
goto_model.symbol_table.add(
103+
create_void_function_symbol(goto_functionst::entry_point(), a_body));
104+
goto_model.symbol_table.add(
105+
create_void_function_symbol("b", code_skipt()));
106+
107+
stream_message_handlert msg(std::cerr);
108+
goto_convert(goto_model, msg);
109+
110+
WHEN("Constructing a dependence graph")
111+
{
112+
dependence_grapht dep_graph(ns);
113+
dep_graph(goto_model.goto_functions, ns);
114+
115+
THEN("The function call and assignment instructions "
116+
"should have a control dependency")
117+
{
118+
for(std::size_t node_idx = 0; node_idx < dep_graph.size(); ++node_idx)
119+
{
120+
const dep_nodet &node = dep_graph[node_idx];
121+
const dep_graph_domaint &node_domain = dep_graph[node.PC];
122+
if(node.PC->is_assign() || node.PC->is_function_call())
123+
{
124+
REQUIRE(
125+
dependence_graph_test_get_control_deps(node_domain).size() == 1);
126+
}
127+
}
128+
}
129+
130+
THEN("The graph's domain and its grapht representation "
131+
"should be consistent")
132+
{
133+
for(std::size_t node_idx = 0; node_idx < dep_graph.size(); ++node_idx)
134+
{
135+
const dep_nodet &node = dep_graph[node_idx];
136+
const dep_graph_domaint &node_domain = dep_graph[node.PC];
137+
const std::set<goto_programt::const_targett> &control_deps =
138+
dependence_graph_test_get_control_deps(node_domain);
139+
const std::set<goto_programt::const_targett> &data_deps =
140+
dependence_graph_test_get_data_deps(node_domain);
141+
142+
std::size_t domain_dep_count =
143+
control_deps.size() + data_deps.size();
144+
145+
REQUIRE(domain_dep_count == node.in.size());
146+
147+
for(const auto &dep_edge : node.in)
148+
{
149+
if(dep_edge.second.get() == dep_edget::kindt::CTRL)
150+
REQUIRE(control_deps.count(dep_graph[dep_edge.first].PC));
151+
else if(dep_edge.second.get() == dep_edget::kindt::DATA)
152+
REQUIRE(data_deps.count(dep_graph[dep_edge.first].PC));
153+
}
154+
}
155+
}
156+
}
157+
}
158+
}

0 commit comments

Comments
 (0)