Skip to content

Commit 6a689f3

Browse files
author
Enrico Steffinlongo
authored
Merge pull request #7795 from esteffin/esteffin/expr-initializer-unit-test
Add unit test for expr_initializer.cpp
2 parents 5650fb9 + 5646669 commit 6a689f3

File tree

2 files changed

+264
-0
lines changed

2 files changed

+264
-0
lines changed

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ SRC += analyses/ai/ai.cpp \
135135
util/dense_integer_map.cpp \
136136
util/edit_distance.cpp \
137137
util/expr_cast/expr_cast.cpp \
138+
util/expr_initializer.cpp \
138139
util/expr.cpp \
139140
util/expr_iterator.cpp \
140141
util/file_util.cpp \

unit/util/expr_initializer.cpp

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

0 commit comments

Comments
 (0)