1
1
// Author: Diffblue Ltd.
2
2
3
3
#include < util/arith_tools.h>
4
+ #include < util/bitvector_expr.h>
4
5
#include < util/bitvector_types.h>
5
6
#include < util/c_types.h>
7
+ #include < util/config.h>
6
8
#include < util/expr_initializer.h>
7
9
#include < util/namespace.h>
8
10
#include < util/std_code.h>
9
11
#include < util/symbol_table.h>
10
12
13
+ #include < testing-utils/invariant.h>
11
14
#include < testing-utils/use_catch.h>
12
15
16
+ #include < iomanip>
17
+ #include < sstream>
18
+
13
19
// / Helper struct to hold useful test components.
14
20
struct expr_initializer_test_environmentt
15
21
{
@@ -19,6 +25,10 @@ struct expr_initializer_test_environmentt
19
25
20
26
static expr_initializer_test_environmentt make ()
21
27
{
28
+ // These config lines are necessary before construction because char size
29
+ // depend on the global configuration.
30
+ config.ansi_c .mode = configt::ansi_ct::flavourt::GCC;
31
+ config.ansi_c .set_arch_spec_x86_64 ();
22
32
return {};
23
33
}
24
34
@@ -68,24 +78,217 @@ create_tag_populate_env(const typet &type, symbol_tablet &symbol_table)
68
78
UNREACHABLE;
69
79
}
70
80
71
- TEST_CASE (" nondet_initializer boolean" , " [core][util][expr_initializer]" )
81
+ exprt replicate_expression (
82
+ const exprt &expr,
83
+ const typet &output_type,
84
+ std::size_t times)
85
+ {
86
+ if (times == 1 )
87
+ {
88
+ return expr;
89
+ }
90
+ exprt::operandst operands;
91
+ operands.push_back (expr);
92
+ for (std::size_t i = 1 ; i < times; ++i)
93
+ {
94
+ operands.push_back (
95
+ shl_exprt{expr, from_integer (config.ansi_c .char_width * i, size_type ())});
96
+ }
97
+ return multi_ary_exprt{ID_bitor, operands, output_type};
98
+ }
99
+
100
+ TEST_CASE (
101
+ " duplicate_per_byte precondition works" ,
102
+ " [core][util][duplicate_per_byte]" )
103
+ {
104
+ auto test = expr_initializer_test_environmentt::make ();
105
+ typet input_type = signedbv_typet{8 };
106
+
107
+ SECTION (" duplicate_per_byte fails when init type is not a bitvector" )
108
+ {
109
+ const array_typet array_type{
110
+ bool_typet{}, from_integer (3 , signedbv_typet{8 })};
111
+
112
+ const cbmc_invariants_should_throwt invariants_throw;
113
+
114
+ REQUIRE_THROWS_MATCHES (
115
+ duplicate_per_byte (array_of_exprt{true_exprt{}, array_type}, input_type),
116
+ invariant_failedt,
117
+ invariant_failure_containing (
118
+ " Condition: (init_type_as_bitvector && "
119
+ " init_type_as_bitvector->get_width() <= config.ansi_c.char_width) || "
120
+ " init_byte_expr.type().id() == ID_bool" ));
121
+ }
122
+
123
+ SECTION (
124
+ " duplicate_per_byte fails when init type is a bitvector larger than "
125
+ " char_width bits" )
126
+ {
127
+ const cbmc_invariants_should_throwt invariants_throw;
128
+
129
+ REQUIRE_THROWS_MATCHES (
130
+ duplicate_per_byte (from_integer (0 , unsignedbv_typet{10 }), input_type),
131
+ invariant_failedt,
132
+ invariant_failure_containing (
133
+ " init_type_as_bitvector->get_width() <= config.ansi_c.char_width" ));
134
+ }
135
+ }
136
+
137
+ std::string to_hex (unsigned int value)
138
+ {
139
+ std::stringstream ss;
140
+ ss << " 0x" << std::hex << value;
141
+ return ss.str ();
142
+ }
143
+
144
+ TEST_CASE (
145
+ " duplicate_per_byte on unsigned_bv with constant" ,
146
+ " [core][util][duplicate_per_byte]" )
147
+ {
148
+ auto test = expr_initializer_test_environmentt::make ();
149
+ // elements are init_expr_value, init_expr_size, output_expected_value, output_size
150
+ using rowt = std::tuple<std::size_t , unsigned int , std::size_t , unsigned int >;
151
+ unsigned int init_expr_value, output_expected_value;
152
+ std::size_t output_size, init_expr_size;
153
+ std::tie (
154
+ init_expr_value, init_expr_size, output_expected_value, output_size) =
155
+ GENERATE (
156
+ rowt{0xFF , 8 , 0xFF , 8 }, // same-type constant
157
+ rowt{0x2 , 2 , 0x02 , 8 }, // smaller-type constant gets promoted
158
+ rowt{0x11 , 5 , 0x11 , 5 }, // same-type constant
159
+ rowt{0x21 , 8 , 0x01 , 5 }, // bigger-type constant gets truncated
160
+ rowt{0x2 , 3 , 0x02 , 5 }, // smaller-type constant gets promoted
161
+ rowt{0xAB , 8 , 0xABAB , 16 }, // smaller-type constant gets replicated
162
+ rowt{0xAB , 8 , 0xBABAB , 20 } // smaller-type constant gets replicated
163
+ );
164
+ SECTION (
165
+ " Testing with output size " + std::to_string (output_size) + " init value " +
166
+ to_hex (init_expr_value) + " of size " + std::to_string (init_expr_size))
167
+ {
168
+ typet output_type = unsignedbv_typet{output_size};
169
+ const auto result = duplicate_per_byte (
170
+ from_integer (init_expr_value, unsignedbv_typet{init_expr_size}),
171
+ output_type);
172
+ const auto expected =
173
+ from_integer (output_expected_value, unsignedbv_typet{output_size});
174
+ REQUIRE (result == expected);
175
+
176
+ // Check that signed-bv values are replicated including the sign bit.
177
+ const auto result_with_signed_init_type = duplicate_per_byte (
178
+ from_integer (init_expr_value, signedbv_typet{init_expr_size}),
179
+ output_type);
180
+ REQUIRE (result_with_signed_init_type == result);
181
+ }
182
+ }
183
+
184
+ TEST_CASE (
185
+ " duplicate_per_byte on unsigned_bv with non-constant expr" ,
186
+ " [core][util][duplicate_per_byte]" )
187
+ {
188
+ auto test = expr_initializer_test_environmentt::make ();
189
+ // elements are init_expr_size, output_size, replication_count
190
+ using rowt = std::tuple<std::size_t , std::size_t , std::size_t >;
191
+ std::size_t init_expr_size, output_size, replication_count;
192
+ std::tie (init_expr_size, output_size, replication_count) = GENERATE (
193
+ rowt{8 , 8 , 1 }, // same-type expr no-cast
194
+ rowt{2 , 2 , 1 }, // same-type expr no-cast
195
+ rowt{3 , 8 , 1 }, // smaller-type gets promoted
196
+ rowt{8 , 2 , 1 }, // bigger type gets truncated
197
+ rowt{8 , 16 , 2 }, // replicated twice
198
+ rowt{8 , 20 , 3 }); // replicated three times and truncated
199
+ SECTION (
200
+ " Testing with output size " + std::to_string (output_size) + " init size " +
201
+ std::to_string (init_expr_size))
202
+ {
203
+ typet output_type = signedbv_typet{output_size};
204
+
205
+ const auto init_expr = plus_exprt{
206
+ from_integer (1 , unsignedbv_typet{init_expr_size}),
207
+ from_integer (2 , unsignedbv_typet{init_expr_size})};
208
+ const auto result = duplicate_per_byte (init_expr, output_type);
209
+
210
+ const auto casted_init_expr =
211
+ typecast_exprt::conditional_cast (init_expr, output_type);
212
+ const auto expected =
213
+ replicate_expression (casted_init_expr, output_type, replication_count);
214
+
215
+ REQUIRE (result == expected);
216
+ }
217
+ }
218
+
219
+ TEST_CASE (" expr_initializer boolean" , " [core][util][expr_initializer]" )
72
220
{
73
221
auto test = expr_initializer_test_environmentt::make ();
74
222
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);
223
+ SECTION (" nondet_initializer" )
224
+ {
225
+ const auto result = nondet_initializer (input, test.loc , test.ns );
226
+ REQUIRE (result.has_value ());
227
+ const auto expected = side_effect_expr_nondett{bool_typet{}, test.loc };
228
+ REQUIRE (result.value () == expected);
229
+ }
230
+ SECTION (" zero_initializer" )
231
+ {
232
+ const auto result = zero_initializer (input, test.loc , test.ns );
233
+ REQUIRE (result.has_value ());
234
+ const auto expected = from_integer (0 , bool_typet ());
235
+ ;
236
+ REQUIRE (result.value () == expected);
237
+ }
238
+ SECTION (" expr_initializer with same-type constant" )
239
+ {
240
+ const auto result =
241
+ expr_initializer (input, test.loc , test.ns , true_exprt{});
242
+ REQUIRE (result.has_value ());
243
+ const auto expected = true_exprt{};
244
+ REQUIRE (result.value () == expected);
245
+ }
246
+ SECTION (" expr_initializer with other-type constant" )
247
+ {
248
+ const auto result = expr_initializer (
249
+ input, test.loc , test.ns , from_integer (1 , signedbv_typet{8 }));
250
+ REQUIRE (result.has_value ());
251
+ const auto expected =
252
+ typecast_exprt{from_integer (1 , signedbv_typet{8 }), bool_typet{}};
253
+ REQUIRE (result.value () == expected);
254
+ }
255
+ SECTION (" expr_initializer with non-constant expr" )
256
+ {
257
+ const auto result = expr_initializer (
258
+ input, test.loc , test.ns , or_exprt{true_exprt (), true_exprt{}});
259
+ REQUIRE (result.has_value ());
260
+ const auto expected = or_exprt{true_exprt{}, true_exprt{}};
261
+ REQUIRE (result.value () == expected);
262
+ }
79
263
}
80
264
81
- TEST_CASE (" nondet_initializer signed_bv" , " [core][util][expr_initializer]" )
265
+ TEST_CASE (
266
+ " nondet_initializer 8-bit signed_bv" ,
267
+ " [core][util][expr_initializer]" )
82
268
{
83
269
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);
270
+ const std::size_t input_type_size = 8 ;
271
+ typet input_type = signedbv_typet{input_type_size};
272
+ SECTION (" nondet_initializer" )
273
+ {
274
+ const auto result = nondet_initializer (input_type, test.loc , test.ns );
275
+ REQUIRE (result.has_value ());
276
+ const auto expected =
277
+ side_effect_expr_nondett{signedbv_typet{input_type_size}, test.loc };
278
+ REQUIRE (result.value () == expected);
279
+ }
280
+ SECTION (" zero_initializer" )
281
+ {
282
+ const auto result = zero_initializer (input_type, test.loc , test.ns );
283
+ REQUIRE (result.has_value ());
284
+ const auto expected = from_integer (0 , signedbv_typet{input_type_size});
285
+ REQUIRE (result.value () == expected);
286
+ }
287
+ SECTION (" expr_initializer calls duplicate_per_byte" )
288
+ {
289
+ // TODO: duplicate_per_byte is tested separately. Here we should check that
290
+ // expr_initializer calls duplicate_per_byte.
291
+ }
89
292
}
90
293
91
294
TEST_CASE (" nondet_initializer c_enum" , " [core][util][expr_initializer]" )
0 commit comments