Skip to content

Commit 411e654

Browse files
Unit tests for dependency graph
1 parent c4ba7b4 commit 411e654

File tree

2 files changed

+195
-0
lines changed

2 files changed

+195
-0
lines changed

unit/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ SRC += unit_tests.cpp \
3333
solvers/refinement/string_constraint_generator_valueof/is_digit_with_radix.cpp \
3434
solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp \
3535
solvers/refinement/string_refinement/concretize_array.cpp \
36+
solvers/refinement/string_refinement/dependency_graph.cpp \
3637
solvers/refinement/string_refinement/has_subtype.cpp \
3738
solvers/refinement/string_refinement/substitute_array_list.cpp \
3839
solvers/refinement/string_refinement/string_symbol_resolution.cpp \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for dependency graph
4+
solvers/refinement/string_refinement.cpp
5+
6+
Author: DiffBlue Limited. All rights reserved.
7+
8+
\*******************************************************************/
9+
10+
#include <testing-utils/catch.hpp>
11+
12+
#include <util/arith_tools.h>
13+
#include <util/std_types.h>
14+
#include <util/std_expr.h>
15+
#include <java_bytecode/java_types.h>
16+
#include <solvers/refinement/string_refinement_util.h>
17+
18+
#ifdef DEBUG
19+
#include <iostream>
20+
#include <java_bytecode/java_bytecode_language.h>
21+
#include <langapi/mode.h>
22+
#include <util/symbol_table.h>
23+
#endif
24+
25+
typet length_type()
26+
{
27+
return signedbv_typet(32);
28+
}
29+
30+
/// Make a struct with a pointer content and an integer length
31+
struct_exprt make_string_argument(std::string name)
32+
{
33+
struct_typet type;
34+
const array_typet char_array(char_type(), infinity_exprt(length_type()));
35+
type.components().emplace_back("length", length_type());
36+
type.components().emplace_back("content", pointer_type(char_array));
37+
38+
const symbol_exprt length(name + "_length", length_type());
39+
const symbol_exprt content(name + "_content", pointer_type(java_char_type()));
40+
struct_exprt expr(type);
41+
expr.operands().push_back(length);
42+
expr.operands().push_back(content);
43+
return expr;
44+
}
45+
46+
SCENARIO("dependency_graph", "[core][solvers][refinement][string_refinement]")
47+
{
48+
GIVEN("dependency graph")
49+
{
50+
string_dependencest dependences;
51+
refined_string_typet string_type(java_char_type(), java_int_type());
52+
const exprt string1 = make_string_argument("string1");
53+
const exprt string2 = make_string_argument("string2");
54+
const exprt string3 = make_string_argument("string3");
55+
const exprt string4 = make_string_argument("string4");
56+
const exprt string5 = make_string_argument("string5");
57+
const exprt string6 = make_string_argument("string6");
58+
const symbol_exprt lhs("lhs", unsignedbv_typet(32));
59+
const symbol_exprt lhs2("lhs2", unsignedbv_typet(32));
60+
const symbol_exprt lhs3("lhs3", unsignedbv_typet(32));
61+
code_typet fun_type;
62+
63+
// fun1 is s3 = s1.concat(s2)
64+
function_application_exprt fun1(fun_type);
65+
fun1.function() = symbol_exprt(ID_cprover_string_concat_func);
66+
fun1.arguments().push_back(string3.op0());
67+
fun1.arguments().push_back(string3.op1());
68+
fun1.arguments().push_back(string1);
69+
fun1.arguments().push_back(string2);
70+
71+
// fun2 is s5 = s3.concat(s4)
72+
function_application_exprt fun2(fun_type);
73+
fun2.function() = symbol_exprt(ID_cprover_string_concat_func);
74+
fun2.arguments().push_back(string5.op0());
75+
fun2.arguments().push_back(string5.op1());
76+
fun2.arguments().push_back(string3);
77+
fun2.arguments().push_back(string4);
78+
79+
// fun3 is s6 = s5.concat(s2)
80+
function_application_exprt fun3(fun_type);
81+
fun3.function() = symbol_exprt(ID_cprover_string_concat_func);
82+
fun3.arguments().push_back(string6.op0());
83+
fun3.arguments().push_back(string6.op1());
84+
fun3.arguments().push_back(string5);
85+
fun3.arguments().push_back(string2);
86+
87+
const equal_exprt equation1(lhs, fun1);
88+
const equal_exprt equation2(lhs2, fun2);
89+
const equal_exprt equation3(lhs3, fun3);
90+
91+
WHEN("We add dependencies")
92+
{
93+
symbol_generatort generator;
94+
array_poolt array_pool(generator);
95+
96+
bool success = add_node(dependences, equation1, array_pool);
97+
REQUIRE(success);
98+
success = add_node(dependences, equation2, array_pool);
99+
REQUIRE(success);
100+
success = add_node(dependences, equation3, array_pool);
101+
REQUIRE(success);
102+
103+
#ifdef DEBUG // useful output for visualizing the graph
104+
{
105+
register_language(new_java_bytecode_language);
106+
symbol_tablet symbol_table;
107+
namespacet ns(symbol_table);
108+
dependencies.output_dot(std::cerr, [&](const exprt &expr) { // NOLINT
109+
return from_expr(ns, "", expr);
110+
});
111+
}
112+
#endif
113+
114+
// The dot output of the graph would look like:
115+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116+
// digraph dependencies {
117+
// "string_refinement#char_array_symbol#3" -> primitive0;
118+
// "string_refinement#char_array_symbol#6" -> primitive1;
119+
// "string_refinement#char_array_symbol#9" -> primitive2;
120+
// primitive0 -> "string_refinement#char_array_symbol#1";
121+
// primitive0 -> "string_refinement#char_array_symbol#2";
122+
// primitive1 -> "string_refinement#char_array_symbol#3";
123+
// primitive1 -> "string_refinement#char_array_symbol#5";
124+
// primitive2 -> "string_refinement#char_array_symbol#6";
125+
// primitive2 -> "string_refinement#char_array_symbol#2";
126+
// }
127+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128+
129+
const array_string_exprt char_array1 =
130+
array_pool.find(string1.op1(), string1.op0());
131+
const array_string_exprt char_array2 =
132+
array_pool.find(string2.op1(), string2.op0());
133+
const array_string_exprt char_array3 =
134+
array_pool.find(string3.op1(), string3.op0());
135+
const array_string_exprt char_array4 =
136+
array_pool.find(string4.op1(), string4.op0());
137+
const array_string_exprt char_array5 =
138+
array_pool.find(string5.op1(), string5.op0());
139+
const array_string_exprt char_array6 =
140+
array_pool.find(string6.op1(), string6.op0());
141+
142+
THEN("string3 depends on primitive0")
143+
{
144+
const auto &node = dependences.get_node(char_array3);
145+
const std::vector<string_dependencest::builtin_function_nodet>
146+
&depends = dependences.dependencies(node);
147+
REQUIRE(depends.size() == 1);
148+
const auto &primitive0 = dependences.get_builtin_function(depends[0]);
149+
150+
THEN("primitive0 depends on string1 and string2")
151+
{
152+
const auto &depends2 = primitive0.string_arguments();
153+
REQUIRE(depends2.size() == 2);
154+
REQUIRE(depends2[0] == char_array1);
155+
REQUIRE(depends2[1] == char_array2);
156+
}
157+
}
158+
159+
THEN("string5 depends on primitive1")
160+
{
161+
const auto &node = dependences.get_node(char_array5);
162+
const std::vector<string_dependencest::builtin_function_nodet>
163+
&depends = dependences.dependencies(node);
164+
REQUIRE(depends.size() == 1);
165+
const auto &primitive1 = dependences.get_builtin_function(depends[0]);
166+
167+
THEN("primitive1 depends on string3 and string4")
168+
{
169+
const auto &depends2 = primitive1.string_arguments();
170+
REQUIRE(depends2.size() == 2);
171+
REQUIRE(depends2[0] == char_array3);
172+
REQUIRE(depends2[1] == char_array4);
173+
}
174+
}
175+
176+
THEN("string6 depends on primitive2")
177+
{
178+
const auto &node = dependences.get_node(char_array6);
179+
const std::vector<string_dependencest::builtin_function_nodet>
180+
&depends = dependences.dependencies(node);
181+
REQUIRE(depends.size() == 1);
182+
const auto &primitive2 = dependences.get_builtin_function(depends[0]);
183+
184+
THEN("primitive2 depends on string5 and string2")
185+
{
186+
const auto &depends2 = primitive2.string_arguments();
187+
REQUIRE(depends2.size() == 2);
188+
REQUIRE(depends2[0] == char_array5);
189+
REQUIRE(depends2[1] == char_array2);
190+
}
191+
}
192+
}
193+
}
194+
}

0 commit comments

Comments
 (0)