Home | History | Annotate | Download | only in coverage
      1 #
      2 # Copyright (C) 2016 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 """Generates coverage reports using outputs from GCC.
     17 
     18 The GenerateCoverageReport() function returns HTML to display the coverage
     19 at each line of code in a provided source file. Coverage information is
     20 parsed from .gcno and .gcda file contents and combined with the source file
     21 to reconstruct a coverage report. GenerateLineCoverageVector() is a helper
     22 function that produces a vector of line counts and GenerateCoverageHTML()
     23 uses the vector and source to produce the HTML coverage report.
     24 """
     25 
     26 import cgi
     27 import io
     28 import logging
     29 import os
     30 from vts.utils.python.coverage import gcda_parser
     31 from vts.utils.python.coverage import gcno_parser
     32 
     33 GEN_TAG = "/gen/"
     34 
     35 def GenerateLineCoverageVector(gcno_file_summary, exclude_paths, coverage_dict):
     36     """Process the gcno_file_summary and update the coverage dictionary.
     37 
     38     Create a coverage vector for each source file contained in gcno_file_summary
     39     and update the corresponding item in coverage_dict.
     40 
     41     Args:
     42         gcno_file_summary: FileSummary object after gcno and gcda files have
     43                            been parsed.
     44         exclude_paths: a list of paths should be ignored in the coverage report.
     45         coverage_dict: a dictionary for each source file and its corresponding
     46                        coverage vector.
     47     """
     48     for ident in gcno_file_summary.functions:
     49         func = gcno_file_summary.functions[ident]
     50         file_name = func.src_file_name
     51         if GEN_TAG in file_name:
     52             logging.debug("Skip generated source file %s.", file_name)
     53             continue
     54         skip_file = False
     55         for path in exclude_paths:
     56             if file_name.startswith(path):
     57                 skip_file = True
     58                 break
     59         if skip_file:
     60             logging.debug("Skip excluded source file %s.", file_name)
     61             continue
     62 
     63         src_lines_counts = coverage_dict[file_name] if file_name in coverage_dict else []
     64         for block in func.blocks:
     65             for line in block.lines:
     66                 if line > len(src_lines_counts):
     67                     src_lines_counts.extend([-1] *
     68                                             (line - len(src_lines_counts)))
     69                 if src_lines_counts[line - 1] < 0:
     70                     src_lines_counts[line - 1] = 0
     71                 src_lines_counts[line - 1] += block.count
     72         coverage_dict[file_name] = src_lines_counts
     73 
     74 
     75 def GetCoverageStats(src_lines_counts):
     76     """Returns the coverage stats.
     77 
     78     Args:
     79         src_lines_counts: A list of non-negative integers or -1 representing
     80                           the number of times the i-th line was executed.
     81                           -1 indicates a line that is not executable.
     82 
     83     Returns:
     84         integer, the number of lines instrumented for coverage measurement
     85         integer, the number of executed or covered lines
     86     """
     87     total = 0
     88     covered = 0
     89     if not src_lines_counts or not isinstance(src_lines_counts, list):
     90         logging.error("GetCoverageStats: input invalid.")
     91         return total, covered
     92 
     93     for line in src_lines_counts:
     94         if line < 0:
     95             continue
     96         total += 1
     97         if line > 0:
     98             covered += 1
     99     return total, covered
    100 
    101