55 goto_functionst::function_mapt::const_iterator gf_it,
83 std::map<goto_programt::const_targett, coverage_conditiont>
conditions;
95 rate(std::size_t covered, std::size_t total,
bool per_cent =
false)
97 std::ostringstream oss;
105 fraction =
static_cast<float>(covered) /
static_cast<float>(total);
108 oss << fraction * 100.0 <<
'%';
112 oss << covered <<
" of " << total;
119 rate_detailed(std::size_t covered, std::size_t total,
bool per_cent =
false)
121 std::ostringstream oss;
122 oss <<
rate(covered, total, per_cent) <<
" (" << covered <<
'/' << total
129 goto_functionst::function_mapt::const_iterator gf_it,
138 --gf_it->second.body.instructions.end();
140 end_function->is_end_function(),
141 "last instruction in a function body is end function");
142 file_name = end_function->source_location.get_file();
164 "signature",
from_type(ns, gf_it->first, gf_it->second.type));
171 for(
const auto &cov_line : coverage_lines_map)
177 if(cov_line.second.conditions.empty())
185 std::size_t number = 0, total_taken = 0;
186 for(
const auto &c : cov_line.second.conditions)
192 unsigned taken = c.second.false_taken + c.second.true_taken;
193 total_taken += taken;
198 "condition-coverage",
rate_detailed(total_taken, number * 2,
true));
211 it->source_location.is_nil() ||
212 it->source_location.get_file() !=
file_name || it->is_dead() ||
213 it->is_end_function())
216 const bool is_branch = it->is_goto() && !it->guard.is_constant();
220 std::pair<coverage_lines_mapt::iterator, bool> entry =
231 if(!entry.first->second.conditions.insert({it, coverage_conditiont()})
236 symex_coveraget::coveraget::const_iterator c_entry = coverage.find(it);
237 if(c_entry != coverage.end())
239 if(!(c_entry->second.size() == 1 || is_branch))
241 std::cerr << it->location_number <<
'\n';
242 for(
const auto &cov : c_entry->second)
243 std::cerr << cov.second.succ->location_number <<
'\n';
246 c_entry->second.size() == 1 || is_branch,
247 "instructions other than branch instructions have exactly 1 successor");
249 for(
const auto &cov : c_entry->second)
252 cov.second.num_executions > 0,
253 "coverage entries can only exist with at least one execution");
255 if(entry.first->second.hits == 0)
258 if(cov.second.num_executions > entry.first->second.hits)
259 entry.first->second.hits = cov.second.num_executions;
263 auto cond_entry = entry.first->second.conditions.find(it);
265 cond_entry != entry.first->second.conditions.end(),
266 "branch should have condition");
268 if(it->get_target() == cov.second.succ)
270 if(!cond_entry->second.false_taken)
272 cond_entry->second.false_taken =
true;
278 if(!cond_entry->second.true_taken)
280 cond_entry->second.true_taken =
true;
294 typedef std::map<irep_idt, coverage_recordt> file_recordst;
295 file_recordst file_records;
300 !gf_it->second.body_available() ||
307 std::pair<file_recordst::iterator, bool> entry = file_records.insert(
321 for(xmlt::elementst::const_iterator it =
323 it != func_cov.
xml.
elements.front().elements.end();
338 for(file_recordst::const_iterator it = file_records.begin();
339 it != file_records.end();
366 xmlt &xml_coverage)
const
371 std::string overall_line_rate_str =
373 std::string overall_branch_rate_str =
376 auto now = std::chrono::system_clock::now();
377 auto current_time = std::chrono::time_point_cast<std::chrono::seconds>(now);
378 std::time_t tt = std::chrono::system_clock::to_time_t(current_time);
384 xml_coverage.
set_attribute(
"line-rate", overall_line_rate_str);
385 xml_coverage.
set_attribute(
"branch-rate", overall_branch_rate_str);
401 xmlt &
package = packages.new_element(overall_cov.xml);
403 package.set_attribute(
"line-rate", overall_line_rate_str);
404 package.set_attribute(
"branch-rate", overall_branch_rate_str);
405 package.set_attribute(
"complexity",
"0.0");
410 std::ostream &os)
const
412 xmlt xml_coverage(
"coverage");
415 os <<
"<?xml version=\"1.0\"?>\n";
416 os <<
"<!DOCTYPE coverage SYSTEM \""
417 <<
"http://cobertura.sourceforge.net/xml/coverage-04.dtd\">\n";
425 const std::string &path)
const
433 std::ofstream out(path.c_str());