1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "VtsCoverageProcessor.h" 17 18 #include <dirent.h> 19 #include <fcntl.h> 20 #include <fstream> 21 #include <iostream> 22 #include <map> 23 #include <string> 24 #include <vector> 25 26 #include <google/protobuf/text_format.h> 27 #include <test/vts/proto/VtsReportMessage.pb.h> 28 29 using namespace std; 30 using google::protobuf::TextFormat; 31 32 namespace android { 33 namespace vts { 34 35 void VtsCoverageProcessor::ParseCoverageData(const string& coverage_file, 36 TestReportMessage* report_msg) { 37 ifstream in(coverage_file, std::ios::in); 38 string msg_str((istreambuf_iterator<char>(in)), istreambuf_iterator<char>()); 39 if (!TextFormat::MergeFromString(msg_str, report_msg)) { 40 cerr << "Can't parse a given coverage report: " << msg_str << endl; 41 exit(-1); 42 } 43 } 44 45 void VtsCoverageProcessor::UpdateCoverageData( 46 const CoverageReportMessage& ref_msg, 47 CoverageReportMessage* msg_to_be_updated) { 48 if (ref_msg.file_path() == msg_to_be_updated->file_path()) { 49 for (int line = 0; line < ref_msg.line_coverage_vector_size(); line++) { 50 if (line < msg_to_be_updated->line_coverage_vector_size()) { 51 if (ref_msg.line_coverage_vector(line) > 0 && 52 msg_to_be_updated->line_coverage_vector(line) > 0) { 53 msg_to_be_updated->set_line_coverage_vector(line, 0); 54 msg_to_be_updated->set_covered_line_count( 55 msg_to_be_updated->covered_line_count() - 1); 56 } 57 } else { 58 cout << "Reached the end of line_coverage_vector." << endl; 59 break; 60 } 61 } 62 // sanity check. 63 if (msg_to_be_updated->covered_line_count() < 0) { 64 cerr << __func__ << ": covered_line_count should not be negative." 65 << endl; 66 exit(-1); 67 } 68 } 69 } 70 71 void VtsCoverageProcessor::MergeCoverage(const string& coverage_file_dir, 72 const string& merged_coverage_file) { 73 DIR* coverage_dir = opendir(coverage_file_dir.c_str()); 74 if (coverage_dir == 0) { 75 cerr << __func__ << ": " << coverage_file_dir << " does not exist." << endl; 76 return; 77 } 78 TestReportMessage merged_coverage_report; 79 80 struct dirent* file; 81 while ((file = readdir(coverage_dir)) != NULL) { 82 if (file->d_type == DT_REG) { 83 string coverage_file = coverage_file_dir; 84 if (coverage_file_dir.substr(coverage_file_dir.size() - 1) != "/") { 85 coverage_file += "/"; 86 } 87 string coverage_file_base_name = file->d_name; 88 coverage_file += coverage_file_base_name; 89 TestReportMessage coverage_report; 90 ParseCoverageData(coverage_file, &coverage_report); 91 92 for (const auto cov : coverage_report.coverage()) { 93 bool seen_cov = false; 94 for (int i = 0; i < merged_coverage_report.coverage_size(); i++) { 95 if (merged_coverage_report.coverage(i).file_path() == 96 cov.file_path()) { 97 MergeCoverageMsg(cov, merged_coverage_report.mutable_coverage(i)); 98 seen_cov = true; 99 break; 100 } 101 } 102 if (!seen_cov) { 103 *merged_coverage_report.add_coverage() = cov; 104 } 105 } 106 } 107 } 108 109 PrintCoverageSummary(merged_coverage_report); 110 ofstream fout; 111 fout.open(merged_coverage_file); 112 fout << merged_coverage_report.DebugString(); 113 fout.close(); 114 } 115 116 void VtsCoverageProcessor::MergeCoverageMsg( 117 const CoverageReportMessage& ref_coverage_msg, 118 CoverageReportMessage* merged_coverage_msg) { 119 // sanity check. 120 if (ref_coverage_msg.file_path() != merged_coverage_msg->file_path()) { 121 cerr << "Trying to merge coverage data for different files." << endl; 122 exit(-1); 123 } 124 if (ref_coverage_msg.line_coverage_vector_size() != 125 merged_coverage_msg->line_coverage_vector_size()) { 126 cerr << "Trying to merge coverage data with different lines." 127 << "ref_coverage_msg: " << ref_coverage_msg.DebugString() 128 << "merged_coverage_msg: " << merged_coverage_msg->DebugString() 129 << endl; 130 exit(-1); 131 } 132 for (int i = 0; i < ref_coverage_msg.line_coverage_vector_size(); i++) { 133 if (i > merged_coverage_msg->line_coverage_vector_size() - 1) { 134 cerr << "Reach the end of coverage vector" << endl; 135 break; 136 } 137 int ref_line_count = ref_coverage_msg.line_coverage_vector(i); 138 int merged_line_count = merged_coverage_msg->line_coverage_vector(i); 139 if (ref_line_count > 0) { 140 if (merged_line_count == 0) { 141 merged_coverage_msg->set_covered_line_count( 142 merged_coverage_msg->covered_line_count() + 1); 143 } 144 merged_coverage_msg->set_line_coverage_vector( 145 i, merged_line_count + ref_line_count); 146 } 147 } 148 } 149 150 void VtsCoverageProcessor::CompareCoverage(const string& ref_msg_file, 151 const string& new_msg_file) { 152 TestReportMessage ref_coverage_report; 153 TestReportMessage new_coverage_report; 154 ParseCoverageData(ref_msg_file, &ref_coverage_report); 155 ParseCoverageData(new_msg_file, &new_coverage_report); 156 map<string, vector<int>> new_coverage_map; 157 158 for (const auto& new_coverage : new_coverage_report.coverage()) { 159 bool seen_file = false; 160 for (const auto& ref_coverage : ref_coverage_report.coverage()) { 161 if (new_coverage.file_path() == ref_coverage.file_path()) { 162 int line = 0; 163 for (; line < new_coverage.line_coverage_vector_size(); line++) { 164 if (new_coverage.line_coverage_vector(line) > 0 && 165 ref_coverage.line_coverage_vector(line) == 0) { 166 if (new_coverage_map.find(new_coverage.file_path()) != 167 new_coverage_map.end()) { 168 new_coverage_map[new_coverage.file_path()].push_back(line); 169 } else { 170 new_coverage_map.insert(std::pair<string, vector<int>>( 171 new_coverage.file_path(), vector<int>{line})); 172 } 173 } 174 } 175 seen_file = true; 176 break; 177 } 178 } 179 if (!seen_file) { 180 vector<int> new_line; 181 for (int line = 0; line < new_coverage.line_coverage_vector_size(); 182 line++) { 183 if (new_coverage.line_coverage_vector(line) > 0) { 184 new_line.push_back(line); 185 } 186 } 187 new_coverage_map.insert( 188 std::pair<string, vector<int>>(new_coverage.file_path(), new_line)); 189 } 190 } 191 for (auto it = new_coverage_map.begin(); it != new_coverage_map.end(); it++) { 192 cout << it->first << ": " << endl; 193 for (int covered_line : it->second) { 194 cout << covered_line << endl; 195 } 196 } 197 } 198 199 void VtsCoverageProcessor::GetSubsetCoverage(const string& ref_msg_file, 200 const string& full_msg_file, 201 const string& result_msg_file) { 202 TestReportMessage ref_coverage_report; 203 TestReportMessage full_coverage_report; 204 TestReportMessage result_coverage_report; 205 ParseCoverageData(ref_msg_file, &ref_coverage_report); 206 ParseCoverageData(full_msg_file, &full_coverage_report); 207 208 for (const auto& ref_coverage : ref_coverage_report.coverage()) { 209 bool seen_file = false; 210 for (const auto& coverage : full_coverage_report.coverage()) { 211 if (coverage.file_path() == ref_coverage.file_path()) { 212 *result_coverage_report.add_coverage() = coverage; 213 seen_file = true; 214 break; 215 } 216 } 217 if (!seen_file) { 218 cout << ": missing coverage for file " << ref_coverage.file_path() 219 << endl; 220 CoverageReportMessage* empty_coverage = 221 result_coverage_report.add_coverage(); 222 *empty_coverage = ref_coverage; 223 for (int line = 0; line < empty_coverage->line_coverage_vector_size(); 224 line++) { 225 if (empty_coverage->line_coverage_vector(line) > 0) { 226 empty_coverage->set_line_coverage_vector(line, 0); 227 } 228 } 229 empty_coverage->set_covered_line_count(0); 230 } 231 } 232 PrintCoverageSummary(result_coverage_report); 233 ofstream fout; 234 fout.open(result_msg_file); 235 fout << result_coverage_report.DebugString(); 236 fout.close(); 237 } 238 239 void VtsCoverageProcessor::GetCoverageSummary(const string& coverage_msg_file) { 240 TestReportMessage coverage_report; 241 ParseCoverageData(coverage_msg_file, &coverage_report); 242 PrintCoverageSummary(coverage_report); 243 } 244 245 void VtsCoverageProcessor::PrintCoverageSummary( 246 const TestReportMessage& coverage_report) { 247 long total_lines_covered = GetTotalCoverageLine(coverage_report); 248 long total_code_lines = GetTotalCodeLine(coverage_report); 249 double coverage_rate = (double)total_lines_covered / total_code_lines; 250 cout << "total lines covered: " << total_lines_covered << endl; 251 cout << "total lines: " << total_code_lines << endl; 252 cout << "coverage rate: " << coverage_rate << endl; 253 } 254 255 long VtsCoverageProcessor::GetTotalCoverageLine( 256 const TestReportMessage& msg) const { 257 long total_coverage_line = 0; 258 for (const auto coverage : msg.coverage()) { 259 total_coverage_line += coverage.covered_line_count(); 260 } 261 return total_coverage_line; 262 } 263 264 long VtsCoverageProcessor::GetTotalCodeLine( 265 const TestReportMessage& msg) const { 266 long total_line = 0; 267 for (const auto coverage : msg.coverage()) { 268 total_line += coverage.total_line_count(); 269 } 270 return total_line; 271 } 272 273 } // namespace vts 274 } // namespace android 275