Skip to content

Commit a49341a

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

File tree

1 file changed

+275
-0
lines changed

1 file changed

+275
-0
lines changed

unit/util/expr_initializer.cpp

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

0 commit comments

Comments
 (0)