Skip to content

Commit 1e43704

Browse files
committed
ported test suite feature from CBMC
1 parent 7d8c648 commit 1e43704

File tree

2 files changed

+224
-1
lines changed

2 files changed

+224
-1
lines changed

src/symex/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
SRC = symex_main.cpp symex_parse_options.cpp path_search.cpp
1+
SRC = symex_main.cpp symex_parse_options.cpp path_search.cpp \
2+
symex_cover.cpp
23

34
OBJ += ../ansi-c/ansi-c$(LIBEXT) \
45
../linking/linking$(LIBEXT) \

src/symex/symex_cover.cpp

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*******************************************************************\
2+
3+
Module: Symex Test Suite Generation
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include <iostream>
10+
11+
#include <util/i2string.h>
12+
#include <util/json_expr.h>
13+
#include <util/xml_expr.h>
14+
15+
#include <goto-programs/xml_goto_trace.h>
16+
#include <goto-programs/json_goto_trace.h>
17+
18+
#include "symex_parse_options.h"
19+
20+
/*******************************************************************\
21+
22+
Function: symex_parse_optionst::get_test
23+
24+
Inputs:
25+
26+
Outputs:
27+
28+
Purpose:
29+
30+
\*******************************************************************/
31+
32+
std::string symex_parse_optionst::get_test(const goto_tracet &goto_trace)
33+
{
34+
bool first=true;
35+
std::string test;
36+
const namespacet ns(goto_model.symbol_table);
37+
38+
for(const auto & step : goto_trace.steps)
39+
{
40+
if(step.is_input())
41+
{
42+
if(first)
43+
first=false;
44+
else
45+
test+=", ";
46+
47+
test+=id2string(step.io_id)+"=";
48+
49+
if(step.io_args.size()==1)
50+
test+=from_expr(ns, "", step.io_args.front());
51+
}
52+
}
53+
return test;
54+
}
55+
56+
/*******************************************************************\
57+
58+
Function: symex_parse_optionst::report_cover
59+
60+
Inputs:
61+
62+
Outputs:
63+
64+
Purpose:
65+
66+
\*******************************************************************/
67+
68+
void symex_parse_optionst::report_cover(
69+
const path_searcht::property_mapt &property_map)
70+
{
71+
// report
72+
unsigned goals_covered=0;
73+
74+
for(const auto & it : property_map)
75+
if(it.second.is_failure())
76+
goals_covered++;
77+
78+
switch(get_ui())
79+
{
80+
case ui_message_handlert::PLAIN:
81+
{
82+
status() << "\n** coverage results:" << eom;
83+
84+
for(const auto & it : property_map)
85+
{
86+
const auto &property=it.second;
87+
88+
status() << "[" << it.first << "]";
89+
90+
if(property.source_location.is_not_nil())
91+
status() << ' ' << property.source_location;
92+
93+
if(!property.description.empty()) status() << ' ' << property.description;
94+
95+
status() << ": " << (property.is_failure()?"SATISFIED":"FAILED")
96+
<< eom;
97+
}
98+
99+
status() << '\n';
100+
101+
break;
102+
}
103+
104+
case ui_message_handlert::XML_UI:
105+
{
106+
for(const auto & it : property_map)
107+
{
108+
const auto &property=it.second;
109+
110+
xmlt xml_result("result");
111+
xml_result.set_attribute("goal", id2string(it.first));
112+
xml_result.set_attribute("description", id2string(property.description));
113+
xml_result.set_attribute("status", property.is_failure()?"SATISFIED":"FAILED");
114+
115+
if(property.source_location.is_not_nil())
116+
xml_result.new_element()=xml(property.source_location);
117+
118+
if(property.is_failure())
119+
{
120+
const namespacet ns(goto_model.symbol_table);
121+
122+
if(cmdline.isset("trace"))
123+
{
124+
convert(ns, property.error_trace, xml_result.new_element());
125+
}
126+
else
127+
{
128+
xmlt &xml_test=xml_result.new_element("test");
129+
130+
for(const auto & step : property.error_trace.steps)
131+
{
132+
if(step.is_input())
133+
{
134+
xmlt &xml_input=xml_test.new_element("input");
135+
xml_input.set_attribute("id", id2string(step.io_id));
136+
if(step.io_args.size()==1)
137+
xml_input.new_element("value")=
138+
xml(step.io_args.front(), ns);
139+
}
140+
}
141+
142+
}
143+
}
144+
145+
std::cout << xml_result << "\n";
146+
}
147+
148+
break;
149+
}
150+
case ui_message_handlert::JSON_UI:
151+
{
152+
json_objectt json_result;
153+
json_arrayt &result_array=json_result["results"].make_array();
154+
for(const auto & it : property_map)
155+
{
156+
const auto &property=it.second;
157+
158+
json_objectt &result=result_array.push_back().make_object();
159+
result["status"]=json_stringt(property.is_failure()?"satisfied":"failed");
160+
result["goal"]=json_stringt(id2string(it.first));
161+
result["description"]=json_stringt(id2string(property.description));
162+
163+
if(property.source_location.is_not_nil())
164+
result["sourceLocation"]=json(property.source_location);
165+
166+
if(property.is_failure())
167+
{
168+
const namespacet ns(goto_model.symbol_table);
169+
170+
if(cmdline.isset("trace"))
171+
{
172+
jsont &json_trace=result["trace"];
173+
convert(ns, property.error_trace, json_trace);
174+
}
175+
else
176+
{
177+
json_arrayt &json_test=result["test"].make_array();
178+
179+
for(const auto & step : property.error_trace.steps)
180+
{
181+
if(step.is_input())
182+
{
183+
json_objectt json_input;
184+
json_input["id"]=json_stringt(id2string(step.io_id));
185+
if(step.io_args.size()==1)
186+
json_input["value"]=json(step.io_args.front(), ns);
187+
json_test.push_back(json_input);
188+
}
189+
}
190+
191+
}
192+
}
193+
}
194+
json_result["totalGoals"]=json_numbert(i2string(property_map.size()));
195+
json_result["goalsCovered"]=json_numbert(i2string(goals_covered));
196+
std::cout << ",\n" << json_result;
197+
break;
198+
}
199+
}
200+
201+
status() << "** " << goals_covered
202+
<< " of " << property_map.size() << " covered ("
203+
<< std::fixed << std::setw(1) << std::setprecision(1)
204+
<< (property_map.empty()?100.0:100.0*goals_covered/property_map.size())
205+
<< "%)"
206+
<< eom;
207+
208+
if(get_ui()==ui_message_handlert::PLAIN)
209+
{
210+
std::set<std::string> tests;
211+
212+
for(const auto & it : property_map)
213+
if(it.second.is_failure())
214+
tests.insert(get_test(it.second.error_trace));
215+
216+
std::cout << "Test suite:" << '\n';
217+
218+
for(const auto & t : tests)
219+
std::cout << t << '\n';
220+
}
221+
}
222+

0 commit comments

Comments
 (0)