• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
18The GenerateCoverageReport() function returns HTML to display the coverage
19at each line of code in a provided source file. Coverage information is
20parsed from .gcno and .gcda file contents and combined with the source file
21to reconstruct a coverage report. GenerateLineCoverageVector() is a helper
22function that produces a vector of line counts and GenerateCoverageHTML()
23uses the vector and source to produce the HTML coverage report.
24"""
25
26import cgi
27import io
28import logging
29import os
30from vts.utils.python.coverage import gcda_parser
31from vts.utils.python.coverage import gcno_parser
32
33
34def GenerateLineCoverageVector(src_file_name, gcno_file_summary):
35    """Returns a list of invocation counts for each line in the file.
36
37    Parses the GCNO and GCDA file specified to calculate the number of times
38    each line in the source file specified by src_file_name was executed.
39
40    Args:
41        src_file_name: string, the source file name.
42        gcno_file_summary: FileSummary object after gcno and gcda files have
43                           been parsed.
44
45    Returns:
46        A list of non-negative integers or -1 representing the number of times
47        the i-th line was executed. -1 indicates a line that is not executable.
48    """
49    src_lines_counts = []
50    covered_line_count = 0
51    for ident in gcno_file_summary.functions:
52        func = gcno_file_summary.functions[ident]
53        if not src_file_name == func.src_file_name:
54            logging.warn("GenerateLineCoverageVector: \"%s\" file is skipped \"%s\"",
55                         func.src_file_name, src_file_name)
56            continue
57        for block in func.blocks:
58            for line in block.lines:
59                if line > len(src_lines_counts):
60                    src_lines_counts.extend([-1] *
61                                            (line - len(src_lines_counts)))
62                if src_lines_counts[line - 1] < 0:
63                    src_lines_counts[line - 1] = 0
64                src_lines_counts[line - 1] += block.count
65                if block.count > 0:
66                    covered_line_count += 1
67    logging.info("GenerateLineCoverageVector: file %s: %s lines covered",
68                 src_file_name, str(covered_line_count))
69    return src_lines_counts
70
71
72def GetCoverageStats(src_lines_counts):
73    """Returns the coverage stats.
74
75    Args:
76        src_lines_counts: A list of non-negative integers or -1 representing
77                          the number of times the i-th line was executed.
78                          -1 indicates a line that is not executable.
79
80    Returns:
81        integer, the number of lines instrumented for coverage measurement
82        integer, the number of executed or covered lines
83    """
84    total = 0
85    covered = 0
86    if not src_lines_counts or not isinstance(src_lines_counts, list):
87        logging.error("GetCoverageStats: input invalid.")
88        return total, covered
89
90    for line in src_lines_counts:
91        if line < 0:
92            continue
93        total += 1
94        if line > 0:
95            covered += 1
96    return total, covered
97
98