[Coverage] Add debug info for diagnostics.
This CL adds an argument option to print out debug info for diagnostics.
Bug: 801231
Change-Id: I53b23c6569c9938ef4c5b5a786ceaeee751ffc5d
Reviewed-on: https://chromium-review.googlesource.com/871506
Reviewed-by: Abhishek Arya <[email protected]>
Commit-Queue: Yuke Liao <[email protected]>
Cr-Commit-Position: refs/heads/master@{#532530}
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py
index 3eecc775..2c36146 100755
--- a/tools/code_coverage/coverage.py
+++ b/tools/code_coverage/coverage.py
@@ -54,6 +54,7 @@
import argparse
import json
+import logging
import os
import subprocess
import urllib2
@@ -331,7 +332,7 @@
try:
clang_update.DownloadAndUnpack(coverage_tools_url,
clang_update.LLVM_BUILD_DIR)
- print('Coverage tools %s unpacked' % package_version)
+ logging.info('Coverage tools %s unpacked', package_version)
with open(coverage_revision_stamp_file, 'w') as file_handle:
file_handle.write('%s,%s' % (package_version, platform))
file_handle.write('\n')
@@ -357,6 +358,8 @@
# [[-object BIN]] [SOURCES]
# NOTE: For object files, the first one is specified as a positional argument,
# and the rest are specified as keyword argument.
+ logging.debug('Generating per file line by line coverage reports using '
+ '"llvm-cov show" command')
subprocess_cmd = [
LLVM_COV_PATH, 'show', '-format=html',
'-output-dir={}'.format(OUTPUT_DIR),
@@ -365,16 +368,16 @@
subprocess_cmd.extend(
['-object=' + binary_path for binary_path in binary_paths[1:]])
subprocess_cmd.extend(filters)
-
subprocess.check_call(subprocess_cmd)
+ logging.debug('Finished running "llvm-cov show" command')
def _GeneratePerDirectoryCoverageInHtml(binary_paths, profdata_file_path,
filters):
"""Generates coverage breakdown per directory."""
+ logging.debug('Calculating and writing per-directory coverage reports')
per_file_coverage_summary = _GeneratePerFileCoverageSummary(
binary_paths, profdata_file_path, filters)
-
per_directory_coverage_summary = defaultdict(
lambda: _CoverageSummary(0, 0, 0, 0, 0, 0))
@@ -393,6 +396,9 @@
_GenerateCoverageInHtmlForDirectory(
dir_path, per_directory_coverage_summary, per_file_coverage_summary)
+ logging.debug(
+ 'Finished calculating and writing per-directory coverage reports')
+
def _GenerateCoverageInHtmlForDirectory(
dir_path, per_directory_coverage_summary, per_file_coverage_summary):
@@ -496,8 +502,7 @@
build_args = _ParseArgsGnFile()
return 'use_goma' in build_args and build_args['use_goma'] == 'true'
- print('Building %s' % str(targets))
-
+ logging.info('Building %s', str(targets))
if jobs_count is None and _IsGomaConfigured():
jobs_count = DEFAULT_GOMA_JOBS
@@ -507,6 +512,7 @@
subprocess_cmd.extend(targets)
subprocess.check_call(subprocess_cmd)
+ logging.debug('Finished building %s', str(targets))
def _GetProfileRawDataPathsByExecutingCommands(targets, commands):
@@ -519,6 +525,8 @@
Returns:
A list of relative paths to the generated profraw data files.
"""
+ logging.debug('Executing the test commands')
+
# Remove existing profraw data files.
for file_or_dir in os.listdir(OUTPUT_DIR):
if file_or_dir.endswith(PROFRAW_FILE_EXTENSION):
@@ -528,6 +536,8 @@
for target, command in zip(targets, commands):
_ExecuteCommand(target, command)
+ logging.debug('Finished executing the test commands')
+
profraw_file_paths = []
for file_or_dir in os.listdir(OUTPUT_DIR):
if file_or_dir.endswith(PROFRAW_FILE_EXTENSION):
@@ -570,8 +580,8 @@
output_file_name = os.extsep.join([target + '_output', 'txt'])
output_file_path = os.path.join(OUTPUT_DIR, output_file_name)
- print('Running command: "%s", the output is redirected to "%s"' %
- (command, output_file_path))
+ logging.info('Running command: "%s", the output is redirected to "%s"',
+ command, output_file_path)
output = subprocess.check_output(
command.split(), env={
'LLVM_PROFILE_FILE': expected_profraw_file_path
@@ -593,10 +603,9 @@
Raises:
CalledProcessError: An error occurred merging profraw data files.
"""
- print('Creating the profile data file')
-
+ logging.info('Creating the coverage profile data file')
+ logging.debug('Merging profraw files to create profdata file')
profdata_file_path = os.path.join(OUTPUT_DIR, PROFDATA_FILE_NAME)
-
try:
subprocess_cmd = [
LLVM_PROFDATA_PATH, 'merge', '-o', profdata_file_path, '-sparse=true'
@@ -607,6 +616,9 @@
print('Failed to merge profraw files to create profdata file')
raise error
+ logging.debug('Finished merging profraw files')
+ logging.info('Code coverage profile data is created as: %s',
+ profdata_file_path)
return profdata_file_path
@@ -616,6 +628,8 @@
# [[-object BIN]] [SOURCES].
# NOTE: For object files, the first one is specified as a positional argument,
# and the rest are specified as keyword argument.
+ logging.debug('Generating per-file code coverage summary using "llvm-cov '
+ 'export -summary-only" command')
subprocess_cmd = [
LLVM_COV_PATH, 'export', '-summary-only',
'-instr-profile=' + profdata_file_path, binary_paths[0]
@@ -652,6 +666,7 @@
lines_total=summary['lines']['count'],
lines_covered=summary['lines']['covered'])
+ logging.debug('Finished generating per-file code coverage summary')
return per_file_coverage_summary
@@ -782,6 +797,15 @@
'\'ninja -h\' for more details.')
arg_parser.add_argument(
+ '-v',
+ '--verbose',
+ action='store_true',
+ help='Prints additional output for diagnostics.')
+
+ arg_parser.add_argument(
+ '-l', '--log_file', type=str, help='Redirects logs to a file.')
+
+ arg_parser.add_argument(
'targets', nargs='+', help='The names of the test targets to run.')
args = arg_parser.parse_args()
@@ -803,6 +827,11 @@
global OUTPUT_DIR
OUTPUT_DIR = args.output_dir
+ log_level = logging.DEBUG if args.verbose else logging.INFO
+ log_format = '[%(asctime)s] %(message)s'
+ log_file = args.log_file if args.log_file else None
+ logging.basicConfig(filename=log_file, level=log_level, format=log_format)
+
assert len(args.targets) == len(args.command), ('Number of targets must be '
'equal to the number of test '
'commands.')
@@ -823,8 +852,8 @@
args.targets, args.command, args.jobs)
binary_paths = [_GetBinaryPath(command) for command in args.command]
- print('Generating code coverage report in html (this can take a while '
- 'depending on size of target!)')
+ logging.info('Generating code coverage report in html (this can take a while '
+ 'depending on size of target!)')
_GenerateLineByLineFileCoverageInHtml(binary_paths, profdata_file_path,
absolute_filter_paths)
_GeneratePerDirectoryCoverageInHtml(binary_paths, profdata_file_path,
@@ -836,8 +865,8 @@
html_index_file_path = 'file://' + os.path.abspath(
os.path.join(OUTPUT_DIR, 'index.html'))
- print('\nCode coverage profile data is created as: %s' % profdata_file_path)
- print('Index file for html report is generated as: %s' % html_index_file_path)
+ logging.info('Index file for html report is generated as: %s',
+ html_index_file_path)
if __name__ == '__main__':