Skip to content

Commit af49ddc

Browse files
author
Enrico Steffinlongo
committed
Tests for incremental SMT2 solver enum support
1 parent e797942 commit af49ddc

File tree

3 files changed

+161
-5
lines changed

3 files changed

+161
-5
lines changed

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ SRC += analyses/ai/ai.cpp \
115115
solvers/smt2_incremental/smt_response_validation.cpp \
116116
solvers/smt2_incremental/smt_to_smt2_string.cpp \
117117
solvers/smt2_incremental/encoding/struct_encoding.cpp \
118+
solvers/smt2_incremental/encoding/enum_encoding.cpp \
118119
solvers/smt2_incremental/theories/smt_array_theory.cpp \
119120
solvers/smt2_incremental/theories/smt_bit_vector_theory.cpp \
120121
solvers/smt2_incremental/theories/smt_core_theory.cpp \

unit/solvers/smt2_incremental/construct_value_expr_from_smt.cpp

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,39 @@ static mp_integer max_int(const std::size_t bits)
3131
return power2(bits) - 1;
3232
}
3333

34+
static type_symbolt make_c_enum_type_symbol(std::size_t underlying_size)
35+
{
36+
const signedbv_typet underlying_type{underlying_size};
37+
c_enum_typet enum_type{underlying_type};
38+
39+
auto &members = enum_type.add(ID_body).get_sub();
40+
41+
for(unsigned int i = 0; i < 20; ++i)
42+
{
43+
c_enum_typet::c_enum_membert member;
44+
member.set_identifier("V" + std::to_string(i));
45+
member.set_base_name("V" + std::to_string(i));
46+
member.set_value(integer2bvrep(i, underlying_size));
47+
members.push_back(member);
48+
}
49+
return type_symbolt{"my_enum", enum_type, ID_C};
50+
}
51+
52+
static symbolt make_c_enum_tag_instance_symbol(const symbolt &enum_type_symbol)
53+
{
54+
const c_enum_tag_typet enum_tag{enum_type_symbol.name};
55+
return symbolt{"my_enum_value", enum_tag, ID_C};
56+
}
57+
3458
TEST_CASE("Value expr construction from smt.", "[core][smt2_incremental]")
3559
{
36-
const symbol_tablet symbol_table;
60+
symbol_tablet symbol_table;
3761
const namespacet ns{symbol_table};
62+
const symbolt enum_type_symbol = make_c_enum_type_symbol(42);
63+
const symbolt enum_tag_value_symbol =
64+
make_c_enum_tag_instance_symbol(enum_type_symbol);
65+
symbol_table.insert(enum_type_symbol);
66+
symbol_table.insert(enum_tag_value_symbol);
3867
optionalt<smt_termt> input_term;
3968
optionalt<exprt> expected_result;
4069

@@ -66,7 +95,7 @@ TEST_CASE("Value expr construction from smt.", "[core][smt2_incremental]")
6695
from_integer(-1, signedbv_typet{(bits)})}
6796
// clang-format on
6897

69-
std::tie(input_term, expected_result) = GENERATE(
98+
std::tie(input_term, expected_result) = GENERATE_REF(
7099
rowt{smt_bool_literal_termt{true}, true_exprt{}},
71100
rowt{smt_bool_literal_termt{false}, false_exprt{}},
72101
rowt{smt_bit_vector_constant_termt{0, 8}, from_integer(0, c_bool_typet(8))},
@@ -81,6 +110,9 @@ TEST_CASE("Value expr construction from smt.", "[core][smt2_incremental]")
81110
smt_bit_vector_constant_termt{12, 64},
82111
constant_exprt(
83112
integer2bvrep(12, 64), pointer_typet(void_type(), 64 /* bits */))},
113+
rowt{
114+
smt_bit_vector_constant_termt{2, 42},
115+
constant_exprt{"2", c_enum_tag_typet{enum_type_symbol.name}}},
84116
UNSIGNED_BIT_VECTOR_TESTS(8),
85117
SIGNED_BIT_VECTOR_TESTS(8),
86118
UNSIGNED_BIT_VECTOR_TESTS(16),
@@ -103,14 +135,19 @@ TEST_CASE(
103135
"Invariant violations in value expr construction from smt.",
104136
"[core][smt2_incremental]")
105137
{
106-
const symbol_tablet symbol_table;
138+
symbol_tablet symbol_table;
107139
const namespacet ns{symbol_table};
140+
const symbolt enum_type_symbol = make_c_enum_type_symbol(5);
141+
const symbolt enum_tag_value_symbol =
142+
make_c_enum_tag_instance_symbol(enum_type_symbol);
143+
symbol_table.insert(enum_type_symbol);
144+
symbol_table.insert(enum_tag_value_symbol);
108145
optionalt<smt_termt> input_term;
109146
optionalt<typet> input_type;
110147
std::string invariant_reason;
111148

112149
using rowt = std::tuple<smt_termt, typet, std::string>;
113-
std::tie(input_term, input_type, invariant_reason) = GENERATE(
150+
std::tie(input_term, input_type, invariant_reason) = GENERATE_REF(
114151
rowt{
115152
smt_bool_literal_termt{true},
116153
unsignedbv_typet{16},
@@ -147,7 +184,17 @@ TEST_CASE(
147184
rowt{
148185
smt_bit_vector_constant_termt{0, 16},
149186
pointer_typet{unsigned_int_type(), 0},
150-
"Width of smt bit vector term must match the width of pointer type"});
187+
"Width of smt bit vector term must match the width of pointer type"},
188+
rowt{
189+
smt_bit_vector_constant_termt{2, 42},
190+
c_enum_tag_typet{"foo"},
191+
"we are assuming that a name exists in the namespace when this function "
192+
"is called - identifier foo was not found"},
193+
rowt{
194+
smt_bit_vector_constant_termt{8796093022208ul, 64},
195+
enum_tag_value_symbol.type,
196+
"Width of smt bit vector term must match the width of bit vector "
197+
"underlying type of the original c_enum type."});
151198
SECTION(invariant_reason)
152199
{
153200
const cbmc_invariants_should_throwt invariants_throw;
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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/namespace.h>
7+
#include <util/symbol_table.h>
8+
9+
#include <solvers/smt2_incremental/encoding/enum_encoding.h>
10+
#include <testing-utils/use_catch.h>
11+
12+
static c_enum_typet make_c_enum_type(
13+
const unsignedbv_typet &underlying_type,
14+
unsigned int value_count)
15+
{
16+
c_enum_typet enum_type{underlying_type};
17+
18+
auto &members = enum_type.add(ID_body).get_sub();
19+
20+
for(unsigned int i = 0; i < value_count; ++i)
21+
{
22+
c_enum_typet::c_enum_membert member;
23+
member.set_identifier("V" + std::to_string(i));
24+
member.set_base_name("V" + std::to_string(i));
25+
member.set_value(integer2bvrep(i, underlying_type.get_width()));
26+
members.push_back(member);
27+
}
28+
return enum_type;
29+
}
30+
31+
constant_exprt create_enum_tag_typed_constant(
32+
const mp_integer &value,
33+
const c_enum_typet &enum_type,
34+
const c_enum_tag_typet &enum_tag_type)
35+
{
36+
constant_exprt constant = from_integer(value, enum_type);
37+
constant.type() = enum_tag_type;
38+
return constant;
39+
}
40+
41+
TEST_CASE("enum encoding of expressions", "[core][smt2_incremental]")
42+
{
43+
std::size_t size;
44+
int value_count;
45+
using rowt = std::pair<int, int>;
46+
std::tie(size, value_count) = GENERATE(
47+
rowt{32, 42},
48+
rowt{64, 42},
49+
rowt{42, 42},
50+
rowt{2, 42},
51+
rowt{1, 42},
52+
rowt{42, 1},
53+
rowt{42, 0});
54+
55+
INFO(
56+
"Checking enum of underlying size " + std::to_string(size) + " with " +
57+
std::to_string(value_count) + " elements");
58+
59+
const unsignedbv_typet enum_underlying_type{size};
60+
const c_enum_typet enum_type =
61+
make_c_enum_type(enum_underlying_type, value_count);
62+
const type_symbolt enum_symbol{"my_enum", enum_type, ID_C};
63+
symbol_tablet symbol_table;
64+
const namespacet ns{symbol_table};
65+
symbol_table.insert(enum_symbol);
66+
const c_enum_tag_typet enum_tag{enum_symbol.name};
67+
const symbolt enum_value_symbol{"my_enum_value", enum_tag, ID_C};
68+
symbol_table.insert(enum_value_symbol);
69+
const auto symbol_expr = enum_value_symbol.symbol_expr();
70+
const auto symbol_expr_as_bv =
71+
symbol_exprt{"my_enum_value", unsignedbv_typet{size}};
72+
73+
SECTION("enum lowering of non-enum type is a no-op")
74+
{
75+
constant_exprt expr = from_integer(10, signedbv_typet{42});
76+
REQUIRE(lower_enum(expr, ns) == expr);
77+
}
78+
79+
SECTION("enum_tag typed symbol expression")
80+
{
81+
REQUIRE(lower_enum(symbol_expr, ns) == symbol_expr_as_bv);
82+
}
83+
84+
SECTION("enum_tag equality expression")
85+
{
86+
const auto enum_equal = equal_exprt{symbol_expr, symbol_expr};
87+
const auto expected_bv_equal =
88+
equal_exprt{symbol_expr_as_bv, symbol_expr_as_bv};
89+
REQUIRE(lower_enum(enum_equal, ns) == expected_bv_equal);
90+
}
91+
92+
SECTION("enum_tag in array")
93+
{
94+
const array_typet original_array_type{
95+
enum_tag, from_integer(2, unsignedbv_typet{32})};
96+
const array_typet lowered_array_type{
97+
enum_underlying_type, from_integer(2, unsignedbv_typet{32})};
98+
const array_exprt original_array_expr{
99+
{create_enum_tag_typed_constant(3, enum_type, enum_tag),
100+
create_enum_tag_typed_constant(3, enum_type, enum_tag)},
101+
original_array_type};
102+
const array_exprt expected_array_expr{
103+
{from_integer(3, unsignedbv_typet{size}),
104+
from_integer(3, unsignedbv_typet{size})},
105+
lowered_array_type};
106+
REQUIRE(lower_enum(original_array_expr, ns) == expected_array_expr);
107+
}
108+
}

0 commit comments

Comments
 (0)