Home | History | Annotate | Download | only in trace_processor
      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