Skip to content

Commit e0f1172

Browse files
NlightNFotispetr-bauch
authored andcommitted
Add tests for listing potential targets and remove/restore returns
And update the unit makefile. Also fix sharing_map unit test Suddenly, the ordering on dstrings became unpredictable: in this commit the numbers are as follows i => 796 j => 992 k => 1019 l => 833 I guess the sorting is not the focus of this tests so I made this change; it should work regardless the ordering.
1 parent b4263c5 commit e0f1172

File tree

4 files changed

+237
-1
lines changed

4 files changed

+237
-1
lines changed

unit/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ SRC += analyses/ai/ai.cpp \
1414
analyses/does_remove_const/does_expr_lose_const.cpp \
1515
analyses/does_remove_const/does_type_preserve_const_correctness.cpp \
1616
analyses/does_remove_const/is_type_at_least_as_const_as.cpp \
17+
analyses/remove_function_pointers.cpp \
18+
analyses/remove_returns.cpp \
1719
big-int/big-int.cpp \
1820
compound_block_locations.cpp \
1921
goto-instrument/cover/cover_only.cpp \
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*******************************************************************\
2+
Module: Unit tests for module remove_function_pointers
3+
4+
Author: Diffblue Ltd.
5+
6+
Date: Apr 2019
7+
8+
\*******************************************************************/
9+
10+
/// \file
11+
/// Unit tests for module remove_function_pointers
12+
13+
#include <testing-utils/message.h>
14+
#include <testing-utils/use_catch.h>
15+
16+
#include <util/arith_tools.h>
17+
#include <util/c_types.h>
18+
#include <util/std_code.h>
19+
20+
#include <goto-programs/goto_convert_functions.h>
21+
#include <goto-programs/goto_model.h>
22+
#include <goto-programs/remove_function_pointers.h>
23+
24+
SCENARIO(
25+
"List potential targets works reliable",
26+
"[core][goto-programs][list_potential_targets]")
27+
{
28+
goto_modelt goto_model;
29+
// create one instance of the function type, they are all
30+
// going to have the same signature
31+
typet func_type = code_typet{{}, empty_typet{}};
32+
// create an empty code block, to act as the functions' body
33+
code_blockt func_body = code_blockt{};
34+
35+
// void f(){};
36+
symbolt f;
37+
f.name = "f";
38+
f.mode = ID_C;
39+
f.type = func_type; // void, takes no params
40+
f.value = func_body;
41+
goto_model.symbol_table.add(f);
42+
43+
// void g(){};
44+
symbolt g;
45+
g.name = "g";
46+
g.mode = ID_C;
47+
g.type = func_type; // void, takes no params
48+
g.value = func_body;
49+
goto_model.symbol_table.add(g);
50+
51+
// void h(){};
52+
symbolt h;
53+
h.name = "h";
54+
h.mode = ID_C;
55+
h.type = func_type; // void, takes no params
56+
h.value = func_body;
57+
goto_model.symbol_table.add(h);
58+
59+
// void l(){};
60+
symbolt l;
61+
l.name = "l";
62+
l.mode = ID_C;
63+
l.type = func_type; // void, takes no params
64+
l.value = func_body;
65+
goto_model.symbol_table.add(l);
66+
67+
// create array with function pointer elements
68+
array_typet fp_array_type(
69+
pointer_typet{func_type, 64}, from_integer(4, signed_int_type()));
70+
array_exprt fp_array{{}, fp_array_type};
71+
72+
fp_array.copy_to_operands(address_of_exprt{f.symbol_expr()});
73+
fp_array.copy_to_operands(address_of_exprt{g.symbol_expr()});
74+
fp_array.copy_to_operands(address_of_exprt{h.symbol_expr()});
75+
fp_array.copy_to_operands(address_of_exprt{l.symbol_expr()});
76+
77+
// f = fparray {f1, f2, f3, f4};
78+
symbolt fpa;
79+
fpa.name = "f";
80+
fpa.mode = ID_C;
81+
fpa.type = fp_array_type;
82+
fpa.value = fp_array;
83+
84+
goto_model.symbol_table.add(fpa);
85+
86+
// pointer to fn call
87+
symbolt fn_ptr;
88+
fn_ptr.name = "fn_ptr";
89+
fn_ptr.mode = ID_C;
90+
fn_ptr.type = pointer_typet{func_type, 64};
91+
goto_model.symbol_table.add(fn_ptr);
92+
93+
// symbol for indexing the array
94+
symbolt z;
95+
z.name = "z";
96+
z.mode = ID_C;
97+
z.type = signed_int_type();
98+
goto_model.symbol_table.add(z);
99+
100+
// create function with pointer function call instruction
101+
102+
// void entry(){z; array; fn_ptr = array[z]; *fn_ptr()};
103+
symbolt entry;
104+
entry.name = "entry";
105+
entry.mode = ID_C;
106+
entry.type = func_type; // void, takes no params
107+
108+
code_blockt entry_body{
109+
{// fn_ptr = array[z];
110+
code_assignt{
111+
fn_ptr.symbol_expr(),
112+
index_exprt{fp_array, z.symbol_expr(), pointer_type(func_type)}},
113+
// *fn_ptr();
114+
code_function_callt{dereference_exprt{fn_ptr.symbol_expr()}}}};
115+
entry.value = entry_body;
116+
goto_model.symbol_table.add(entry);
117+
118+
WHEN("list_potential_targets is run")
119+
{
120+
goto_convert(goto_model, null_message_handler);
121+
auto target_map =
122+
get_function_pointer_targets(null_message_handler, goto_model);
123+
THEN("there should be 4 targets recognised")
124+
{
125+
REQUIRE(target_map.size() == 1);
126+
REQUIRE(target_map.begin()->second.size() == 4);
127+
}
128+
}
129+
}

unit/analyses/remove_returns.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*******************************************************************\
2+
Module: Unit tests for module remove_returns
3+
4+
Author: Diffblue Ltd.
5+
6+
Date: Apr 2019
7+
8+
\*******************************************************************/
9+
10+
/// \file
11+
/// Unit tests for module remove_returns
12+
/// This is testing the top level interfaces for now.
13+
14+
#include <testing-utils/message.h>
15+
#include <testing-utils/use_catch.h>
16+
17+
#include <util/arith_tools.h>
18+
#include <util/c_types.h>
19+
#include <util/std_code.h>
20+
21+
#include <goto-programs/goto_convert_functions.h>
22+
#include <goto-programs/goto_model.h>
23+
#include <goto-programs/remove_returns.h>
24+
25+
// scenario for testing remove returns
26+
27+
SCENARIO(
28+
"Remove returns is working reliably",
29+
"[core][goto-programs][remove_returns]")
30+
{
31+
goto_modelt goto_model;
32+
33+
// int f() { return 5; }
34+
symbolt f;
35+
f.name = "f";
36+
f.mode = ID_C;
37+
f.type = code_typet{{}, signed_int_type()};
38+
f.value = code_blockt{{code_returnt(from_integer(5, signed_int_type()))}};
39+
goto_model.symbol_table.add(f);
40+
41+
goto_convert(goto_model, null_message_handler);
42+
43+
WHEN("remove_returns is invoked")
44+
{
45+
remove_returns(
46+
null_message_handler, goto_model.symbol_table, goto_model.goto_functions);
47+
THEN("function f should not contain any return instructions")
48+
{
49+
const auto &goto_functions = goto_model.goto_functions;
50+
for(const auto &function_pair : goto_functions.function_map)
51+
{
52+
if(function_pair.first == "f")
53+
{
54+
const auto &instructions = function_pair.second.body.instructions;
55+
for(auto target = instructions.begin(); target != instructions.end();
56+
target++)
57+
{
58+
// make sure there are no return instructions.
59+
REQUIRE(!target->is_return());
60+
}
61+
}
62+
}
63+
}
64+
}
65+
66+
WHEN("restore_returns is invoked")
67+
{
68+
restore_returns(null_message_handler, goto_model);
69+
THEN("function f should have a skip instruction")
70+
{
71+
int number_of_returns = 0;
72+
const auto &goto_functions = goto_model.goto_functions;
73+
for(const auto &function_pair : goto_functions.function_map)
74+
{
75+
if(function_pair.first == "f")
76+
{
77+
const auto &instructions = function_pair.second.body.instructions;
78+
for(auto target = instructions.begin(); target != instructions.end();
79+
target++)
80+
{
81+
if(target->is_return())
82+
number_of_returns++;
83+
}
84+
}
85+
}
86+
87+
// ensure that there were only 1 return instructions in f
88+
REQUIRE(number_of_returns == 1);
89+
}
90+
}
91+
}
92+
93+
// scenario for testing restore returns

unit/util/sharing_map.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,19 @@ TEST_CASE("Sharing map views", "[core][util]")
318318

319319
sort_view();
320320

321-
REQUIRE((pairs[3] == pt("l", "3")));
321+
dstringt i("i");
322+
dstringt j("j");
323+
dstringt k("k");
324+
dstringt l("l");
325+
326+
size_t index = 0;
327+
if(i < l)
328+
index++;
329+
if(j < l)
330+
index++;
331+
if(k < l)
332+
index++;
333+
REQUIRE((pairs[index] == pt("l", "3")));
322334
}
323335

324336
SECTION("Delta view (no sharing, same keys)")

0 commit comments

Comments
 (0)