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