Skip to content

Commit 0744710

Browse files
committed
Add unit tests for the restrict function pointers by name feature
1 parent 0e659f9 commit 0744710

File tree

1 file changed

+145
-6
lines changed

1 file changed

+145
-6
lines changed

unit/goto-programs/restrict_function_pointers.cpp

Lines changed: 145 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ Author: Daniel Poetzl
66
77
\*******************************************************************/
88

9+
#include <testing-utils/get_goto_model_from_c.h>
910
#include <testing-utils/message.h>
1011
#include <testing-utils/use_catch.h>
1112

13+
#include <goto-programs/label_function_pointer_call_sites.h>
1214
#include <goto-programs/restrict_function_pointers.h>
1315

1416
#include <json/json_parser.h>
@@ -17,23 +19,22 @@ class fp_restrictionst : public function_pointer_restrictionst
1719
{
1820
friend void restriction_parsing_test();
1921
friend void merge_restrictions_test();
22+
friend void get_function_pointer_by_name_restrictions_test();
2023
};
2124

2225
void restriction_parsing_test()
2326
{
2427
{
25-
const auto res =
26-
fp_restrictionst::parse_function_pointer_restriction(
27-
"func1/func2", "test");
28+
const auto res = fp_restrictionst::parse_function_pointer_restriction(
29+
"func1/func2", "test");
2830
REQUIRE(res.first == "func1");
2931
REQUIRE(res.second.size() == 1);
3032
REQUIRE(res.second.find("func2") != res.second.end());
3133
}
3234

3335
{
34-
const auto res =
35-
fp_restrictionst::parse_function_pointer_restriction(
36-
"func1/func2,func3", "test");
36+
const auto res = fp_restrictionst::parse_function_pointer_restriction(
37+
"func1/func2,func3", "test");
3738
REQUIRE(res.first == "func1");
3839
REQUIRE(res.second.size() == 2);
3940
REQUIRE(res.second.find("func2") != res.second.end());
@@ -92,6 +93,137 @@ void merge_restrictions_test()
9293
REQUIRE(fp2_restrictions.count("func1") == 1);
9394
}
9495

96+
void get_function_pointer_by_name_restrictions_test()
97+
{
98+
SECTION("Translate parameter restriction to indexed restriction")
99+
{
100+
const std::string code = R"(
101+
typedef void (*fp_t)(void);
102+
void f();
103+
104+
void func(fp_t fp)
105+
{
106+
f(); // ignored
107+
108+
fp();
109+
}
110+
111+
void main() {}
112+
)";
113+
114+
goto_modelt goto_model = get_goto_model_from_c(code);
115+
label_function_pointer_call_sites(goto_model);
116+
117+
const auto restrictions =
118+
fp_restrictionst::get_function_pointer_by_name_restrictions(
119+
{"func::fp/g"}, goto_model);
120+
121+
REQUIRE(restrictions.size() == 1);
122+
123+
const auto set = restrictions.at("func.function_pointer_call.1");
124+
REQUIRE(set.size() == 1);
125+
REQUIRE(set.count("g") == 1);
126+
}
127+
128+
SECTION("Translate local nested variable restriction to indexed restriction")
129+
{
130+
const std::string code = R"(
131+
typedef void (*fp_t)(void);
132+
void f();
133+
134+
void main()
135+
{
136+
f(); // ignored
137+
138+
{
139+
fp_t fp;
140+
fp();
141+
}
142+
}
143+
)";
144+
145+
goto_modelt goto_model = get_goto_model_from_c(code);
146+
label_function_pointer_call_sites(goto_model);
147+
148+
const auto restrictions =
149+
fp_restrictionst::get_function_pointer_by_name_restrictions(
150+
{"main::1::1::fp/g"}, goto_model);
151+
152+
REQUIRE(restrictions.size() == 1);
153+
154+
const auto set = restrictions.at("main.function_pointer_call.1");
155+
REQUIRE(set.size() == 1);
156+
REQUIRE(set.count("g") == 1);
157+
}
158+
159+
SECTION("Translate global variable restriction to indexed restriction")
160+
{
161+
const std::string code = R"(
162+
typedef void (*fp_t)(void);
163+
void f();
164+
165+
fp_t fp;
166+
167+
void main()
168+
{
169+
f(); // ignored
170+
171+
fp();
172+
}
173+
)";
174+
175+
goto_modelt goto_model = get_goto_model_from_c(code);
176+
label_function_pointer_call_sites(goto_model);
177+
178+
const auto restrictions =
179+
fp_restrictionst::get_function_pointer_by_name_restrictions(
180+
{"fp/g"}, goto_model);
181+
182+
REQUIRE(restrictions.size() == 1);
183+
184+
const auto set = restrictions.at("main.function_pointer_call.1");
185+
REQUIRE(set.size() == 1);
186+
REQUIRE(set.count("g") == 1);
187+
}
188+
189+
SECTION(
190+
"Translate a variable restriction to indexed restrictions, "
191+
"for the case when a function pointer is called more than once")
192+
{
193+
const std::string code = R"(
194+
typedef void (*fp_t)(void);
195+
void f();
196+
197+
fp_t fp;
198+
199+
void main()
200+
{
201+
f(); // ignored
202+
203+
fp();
204+
fp(); // second call to same function pointer
205+
}
206+
)";
207+
208+
goto_modelt goto_model = get_goto_model_from_c(code);
209+
label_function_pointer_call_sites(goto_model);
210+
211+
const auto restrictions =
212+
fp_restrictionst::get_function_pointer_by_name_restrictions(
213+
{"fp/g"}, goto_model);
214+
215+
REQUIRE(restrictions.size() == 2);
216+
217+
const auto set1 = restrictions.at("main.function_pointer_call.1");
218+
REQUIRE(set1.size() == 1);
219+
REQUIRE(set1.count("g") == 1);
220+
221+
const auto set2 = restrictions.at("main.function_pointer_call.2");
222+
REQUIRE(set2.size() == 1);
223+
REQUIRE(set2.count("g") == 1);
224+
}
225+
}
226+
95227
TEST_CASE("Restriction parsing", "[core]")
96228
{
97229
restriction_parsing_test();
@@ -152,3 +284,10 @@ TEST_CASE("Json conversion", "[core]")
152284
function_pointer_restrictions1.restrictions ==
153285
function_pointer_restrictions2.restrictions);
154286
}
287+
288+
TEST_CASE(
289+
"Get function pointer by name restrictions",
290+
"[core][goto-programs][restrict-function-pointers]")
291+
{
292+
get_function_pointer_by_name_restrictions_test();
293+
}

0 commit comments

Comments
 (0)