Skip to content

Commit d8a5fa6

Browse files
author
Enrico Steffinlongo
committed
Add unit test for expr_initializer
1 parent 5650fb9 commit d8a5fa6

File tree

1 file changed

+274
-0
lines changed

1 file changed

+274
-0
lines changed

unit/util/expr_initializer.cpp

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
// Author: Diffblue Ltd.
2+
3+
#include <util/arith_tools.h>
4+
#include <util/bitvector_types.h>
5+
#include <util/c_types.h>
6+
#include <util/expr_initializer.h>
7+
#include <util/namespace.h>
8+
#include <util/std_code.h>
9+
#include <util/symbol_table.h>
10+
11+
#include <testing-utils/use_catch.h>
12+
13+
/// Helper struct to hold useful test components.
14+
struct expr_initializer_test_environmentt
15+
{
16+
symbol_tablet symbol_table;
17+
namespacet ns{symbol_table};
18+
source_locationt loc{};
19+
20+
static expr_initializer_test_environmentt make()
21+
{
22+
return {};
23+
}
24+
25+
private:
26+
expr_initializer_test_environmentt() = default;
27+
};
28+
29+
/// Helper function to create and populate a c_enum_typet type.
30+
static c_enum_typet make_c_enum_type(
31+
const unsignedbv_typet &underlying_type,
32+
unsigned int value_count)
33+
{
34+
c_enum_typet enum_type{underlying_type};
35+
36+
auto &members = enum_type.members();
37+
members.reserve(value_count);
38+
39+
for(unsigned int i = 0; i < value_count; ++i)
40+
{
41+
c_enum_typet::c_enum_membert member;
42+
member.set_identifier("V" + std::to_string(i));
43+
member.set_base_name("V" + std::to_string(i));
44+
member.set_value(integer2bvrep(i, underlying_type.get_width()));
45+
members.push_back(member);
46+
}
47+
return enum_type;
48+
}
49+
50+
/// Create a type symbol, a type_tag and a symbol for the tag and populate with
51+
/// them the symbol_table in the environment.
52+
static symbolt create_tag_populate_env(
53+
const typet &type,
54+
expr_initializer_test_environmentt &env)
55+
{
56+
const type_symbolt symbol{"my_type_symbol", type, ID_C};
57+
symbolt tag_symbol = [&]() {
58+
if(can_cast_type<c_enum_typet>(type))
59+
{
60+
const c_enum_tag_typet c_enum_tag_type{symbol.name};
61+
return symbolt{"my_type_tag_symbol", c_enum_tag_type, ID_C};
62+
}
63+
else if(can_cast_type<struct_typet>(type))
64+
{
65+
const struct_tag_typet struct_tag_type{symbol.name};
66+
return symbolt{"my_type_tag_symbol", struct_tag_type, ID_C};
67+
}
68+
else if(can_cast_type<union_typet>(type))
69+
{
70+
const union_tag_typet union_tag_type{symbol.name};
71+
return symbolt{"my_type_tag_symbol", union_tag_type, ID_C};
72+
}
73+
UNREACHABLE;
74+
}();
75+
env.symbol_table.insert(symbol);
76+
env.symbol_table.insert(tag_symbol);
77+
return tag_symbol;
78+
}
79+
80+
TEST_CASE("nondet_initializer boolean", "[core][util][expr_initializer]")
81+
{
82+
auto test = expr_initializer_test_environmentt::make();
83+
typet input = bool_typet{};
84+
const auto result = nondet_initializer(input, test.loc, test.ns);
85+
REQUIRE(result.has_value());
86+
const auto expected = side_effect_expr_nondett{bool_typet{}, test.loc};
87+
REQUIRE(result.value() == expected);
88+
}
89+
90+
TEST_CASE("nondet_initializer signed_bv", "[core][util][expr_initializer]")
91+
{
92+
auto test = expr_initializer_test_environmentt::make();
93+
typet input = signedbv_typet{8};
94+
const auto result = nondet_initializer(input, test.loc, test.ns);
95+
REQUIRE(result.has_value());
96+
const auto expected = side_effect_expr_nondett{signedbv_typet{8}, test.loc};
97+
REQUIRE(result.value() == expected);
98+
}
99+
100+
TEST_CASE("nondet_initializer c_enum", "[core][util][expr_initializer]")
101+
{
102+
auto test = expr_initializer_test_environmentt::make();
103+
const unsignedbv_typet enum_underlying_type{8};
104+
const auto enum_type = make_c_enum_type(enum_underlying_type, 3);
105+
const auto result = nondet_initializer(enum_type, test.loc, test.ns);
106+
REQUIRE(result.has_value());
107+
const auto expected = side_effect_expr_nondett{enum_type, test.loc};
108+
REQUIRE(result.value() == expected);
109+
110+
// Repeat with the c_enum_tag_typet instead of the c_enum_typet it points to
111+
const symbolt symbol = create_tag_populate_env(enum_type, test);
112+
const auto tag_result = nondet_initializer(symbol.type, test.loc, test.ns);
113+
REQUIRE(tag_result.has_value());
114+
const auto expected_tag = side_effect_expr_nondett{symbol.type, test.loc};
115+
REQUIRE(tag_result.value() == expected_tag);
116+
}
117+
118+
TEST_CASE(
119+
"nondet_initializer simple array_type",
120+
"[core][util][expr_initializer]")
121+
{
122+
auto test = expr_initializer_test_environmentt::make();
123+
typet inner_type = signedbv_typet{8};
124+
const std::size_t elem_count = 3;
125+
typet array_type =
126+
array_typet{inner_type, from_integer(elem_count, signedbv_typet{8})};
127+
const auto result = nondet_initializer(array_type, test.loc, test.ns);
128+
REQUIRE(result.has_value());
129+
std::vector<exprt> array_values{
130+
elem_count, side_effect_expr_nondett{signedbv_typet{8}, test.loc}};
131+
const auto expected = array_exprt{
132+
array_values,
133+
array_typet{
134+
signedbv_typet{8}, from_integer(elem_count, signedbv_typet{8})}};
135+
REQUIRE(result.value() == expected);
136+
}
137+
138+
TEST_CASE(
139+
"nondet_initializer on array_type with nondet size",
140+
"[core][util][expr_initializer]")
141+
{
142+
auto test = expr_initializer_test_environmentt::make();
143+
typet inner_type = signedbv_typet{8};
144+
typet array_type = array_typet{
145+
inner_type, side_effect_expr_nondett{signedbv_typet{8}, test.loc}};
146+
const auto result = nondet_initializer(array_type, test.loc, test.ns);
147+
REQUIRE(result.has_value());
148+
const auto expected = side_effect_expr_nondett{
149+
array_typet{
150+
inner_type, side_effect_expr_nondett{signedbv_typet{8}, test.loc}},
151+
test.loc};
152+
REQUIRE(result.value() == expected);
153+
}
154+
155+
TEST_CASE(
156+
"nondet_initializer double array_type",
157+
"[core][util][expr_initializer]")
158+
{
159+
auto test = expr_initializer_test_environmentt::make();
160+
typet inner_type = signedbv_typet{8};
161+
const std::size_t elem_count = 3;
162+
typet inner_array_type =
163+
array_typet{inner_type, from_integer(elem_count, signedbv_typet{8})};
164+
typet array_type =
165+
array_typet{inner_array_type, from_integer(elem_count, signedbv_typet{8})};
166+
const auto result = nondet_initializer(array_type, test.loc, test.ns);
167+
REQUIRE(result.has_value());
168+
std::vector<exprt> inner_array_values{
169+
elem_count, side_effect_expr_nondett{signedbv_typet{8}, test.loc}};
170+
const auto inner_expected = array_exprt{
171+
inner_array_values,
172+
array_typet{
173+
signedbv_typet{8}, from_integer(elem_count, signedbv_typet{8})}};
174+
std::vector<exprt> array_values{elem_count, inner_expected};
175+
const auto expected = array_exprt{
176+
array_values,
177+
array_typet{
178+
array_typet{
179+
signedbv_typet{8}, from_integer(elem_count, signedbv_typet{8})},
180+
from_integer(elem_count, signedbv_typet{8})}};
181+
REQUIRE(result.value() == expected);
182+
}
183+
184+
TEST_CASE(
185+
"nondet_initializer nested struct type",
186+
"[core][util][expr_initializer]")
187+
{
188+
auto test = expr_initializer_test_environmentt::make();
189+
const struct_union_typet::componentst inner_struct_components{
190+
{"foo", signedbv_typet{32}}, {"bar", unsignedbv_typet{16}}};
191+
const struct_typet inner_struct_type{inner_struct_components};
192+
const struct_union_typet::componentst struct_components{
193+
{"fizz", bool_typet{}}, {"bar", inner_struct_type}};
194+
const struct_typet struct_type{struct_components};
195+
const auto result = nondet_initializer(struct_type, test.loc, test.ns);
196+
REQUIRE(result.has_value());
197+
const exprt::operandst expected_inner_struct_operands{
198+
side_effect_expr_nondett{signedbv_typet{32}, test.loc},
199+
side_effect_expr_nondett{unsignedbv_typet{16}, test.loc}};
200+
const struct_exprt expected_inner_struct_expr{
201+
expected_inner_struct_operands, inner_struct_type};
202+
const exprt::operandst expected_struct_operands{
203+
side_effect_expr_nondett{bool_typet{}, test.loc},
204+
expected_inner_struct_expr};
205+
const struct_exprt expected_struct_expr{
206+
expected_struct_operands, struct_type};
207+
REQUIRE(result.value() == expected_struct_expr);
208+
209+
const symbolt inner_struct_tag_symbol =
210+
create_tag_populate_env(inner_struct_type, test);
211+
const auto tag_result =
212+
nondet_initializer(inner_struct_tag_symbol.type, test.loc, test.ns);
213+
REQUIRE(tag_result.has_value());
214+
const struct_exprt expected_inner_struct_tag_expr{
215+
expected_inner_struct_operands, inner_struct_tag_symbol.type};
216+
REQUIRE(tag_result.value() == expected_inner_struct_tag_expr);
217+
}
218+
219+
TEST_CASE("nondet_initializer union type", "[core][util][expr_initializer]")
220+
{
221+
auto test = expr_initializer_test_environmentt::make();
222+
const struct_union_typet::componentst inner_struct_components{
223+
{"foo", signedbv_typet{32}}, {"bar", unsignedbv_typet{16}}};
224+
const struct_typet inner_struct_type{inner_struct_components};
225+
const struct_union_typet::componentst union_components{
226+
{"foo", signedbv_typet{256}},
227+
{"bar", unsignedbv_typet{16}},
228+
{"fizz", bool_typet{}},
229+
{"array",
230+
array_typet{signedbv_typet{8}, from_integer(8, signedbv_typet{8})}},
231+
{"struct", inner_struct_type}};
232+
const union_typet union_type{union_components};
233+
const auto result = nondet_initializer(union_type, test.loc, test.ns);
234+
REQUIRE(result.has_value());
235+
const union_exprt expected_union{
236+
"foo", side_effect_expr_nondett{signedbv_typet{256}, test.loc}, union_type};
237+
REQUIRE(result.value() == expected_union);
238+
239+
const symbolt union_tag_symbol = create_tag_populate_env(union_type, test);
240+
const auto tag_result =
241+
nondet_initializer(union_tag_symbol.type, test.loc, test.ns);
242+
REQUIRE(tag_result.has_value());
243+
const union_exprt expected_union_tag{
244+
"foo",
245+
side_effect_expr_nondett{signedbv_typet{256}, test.loc},
246+
union_tag_symbol.type};
247+
REQUIRE(tag_result.value() == expected_union_tag);
248+
}
249+
250+
TEST_CASE(
251+
"nondet_initializer union type with nondet sized array (fails)",
252+
"[core][util][expr_initializer]")
253+
{
254+
auto test = expr_initializer_test_environmentt::make();
255+
const struct_union_typet::componentst union_components{
256+
{"foo", signedbv_typet{256}},
257+
{"array",
258+
array_typet{
259+
signedbv_typet{8},
260+
side_effect_expr_nondett{signedbv_typet{8}, test.loc}}}};
261+
const union_typet union_type{union_components};
262+
const auto result = nondet_initializer(union_type, test.loc, test.ns);
263+
REQUIRE(!result.has_value());
264+
}
265+
266+
TEST_CASE("nondet_initializer string type", "[core][util][expr_initializer]")
267+
{
268+
auto test = expr_initializer_test_environmentt::make();
269+
const string_typet string_type{};
270+
const auto result = nondet_initializer(string_type, test.loc, test.ns);
271+
REQUIRE(result.has_value());
272+
const side_effect_expr_nondett expected_string{string_typet{}, test.loc};
273+
REQUIRE(result.value() == expected_string);
274+
}

0 commit comments

Comments
 (0)