7d6b2e4804
Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
152 lines
4.5 KiB
Python
Executable file
152 lines
4.5 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# tools/gcov.py
|
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
# contributor license agreements. See the NOTICE file distributed with
|
|
# this work for additional information regarding copyright ownership. The
|
|
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance with the
|
|
# License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import argparse
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def copy_file_endswith(endswith, source_dir, target_dir):
|
|
print(f"Collect {endswith} files {source_dir} -> {target_dir}")
|
|
|
|
if not os.path.exists(target_dir):
|
|
os.makedirs(target_dir)
|
|
|
|
for root, _, files in os.walk(source_dir):
|
|
for file in files:
|
|
if file.endswith(endswith):
|
|
source_file = os.path.join(root, file)
|
|
target_file = os.path.join(target_dir, file)
|
|
shutil.copy2(source_file, target_file)
|
|
|
|
|
|
def arg_parser():
|
|
parser = argparse.ArgumentParser(
|
|
description="Code coverage generation tool.", add_help=False
|
|
)
|
|
parser.add_argument("-t", dest="gcov_tool", help="Path to gcov tool")
|
|
parser.add_argument("-s", dest="gcno_dir", help="Directory containing gcno files")
|
|
parser.add_argument("-a", dest="gcda_dir", help="Directory containing gcda files")
|
|
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
|
|
parser.add_argument(
|
|
"-x",
|
|
dest="only_copy",
|
|
action="store_true",
|
|
help="Only copy *.gcno and *.gcda files",
|
|
)
|
|
parser.add_argument(
|
|
"gcov_dir",
|
|
nargs="?",
|
|
default=os.getcwd(),
|
|
help="Directory to store gcov data and report",
|
|
)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def main():
|
|
args = arg_parser()
|
|
|
|
root_dir = os.getcwd()
|
|
gcov_dir = os.path.abspath(args.gcov_dir)
|
|
gcno_dir = os.path.abspath(args.gcno_dir) if args.gcno_dir else root_dir
|
|
gcda_dir = os.path.abspath(args.gcda_dir) if args.gcda_dir else root_dir
|
|
|
|
coverage_file = os.path.join(gcov_dir, "coverage.info")
|
|
result_dir = os.path.join(gcov_dir, "result")
|
|
gcov_data_dir = os.path.join(gcov_dir, "data")
|
|
|
|
if args.debug:
|
|
debug_file = os.path.join(gcov_dir, "debug.log")
|
|
sys.stdout = open(debug_file, "w+")
|
|
|
|
os.makedirs(os.path.join(gcov_dir, "data"), exist_ok=True)
|
|
|
|
# Collect gcno, gcda files
|
|
copy_file_endswith(".gcno", gcno_dir, gcov_data_dir)
|
|
copy_file_endswith(".gcda", gcda_dir, gcov_data_dir)
|
|
|
|
# Only copy files
|
|
if args.only_copy:
|
|
sys.exit(0)
|
|
|
|
# lcov tool is required
|
|
if shutil.which("lcov") is None:
|
|
print(
|
|
"Error: Code coverage generation tool is not detected, please install lcov."
|
|
)
|
|
sys.exit(1)
|
|
|
|
try:
|
|
|
|
# lcov collect coverage data to coverage_file
|
|
subprocess.run(
|
|
[
|
|
"lcov",
|
|
"-c",
|
|
"-d",
|
|
gcov_data_dir,
|
|
"-o",
|
|
coverage_file,
|
|
"--rc",
|
|
"lcov_branch_coverage=1",
|
|
"--gcov-tool",
|
|
args.gcov_tool,
|
|
"--ignore-errors",
|
|
"gcov",
|
|
],
|
|
check=True,
|
|
stdout=sys.stdout,
|
|
stderr=sys.stdout,
|
|
)
|
|
|
|
# genhtml generate coverage report
|
|
subprocess.run(
|
|
[
|
|
"genhtml",
|
|
"--branch-coverage",
|
|
"-o",
|
|
result_dir,
|
|
coverage_file,
|
|
"--ignore-errors",
|
|
"source",
|
|
],
|
|
check=True,
|
|
stdout=sys.stdout,
|
|
stderr=sys.stdout,
|
|
)
|
|
|
|
print(
|
|
"Copy the following link and open it in the browser to view the coverage report:"
|
|
)
|
|
print(f"file://{os.path.join(result_dir, 'index.html')}")
|
|
|
|
except subprocess.CalledProcessError:
|
|
print("Failed to generate coverage file.")
|
|
sys.exit(1)
|
|
|
|
shutil.rmtree(gcov_data_dir)
|
|
os.remove(coverage_file)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|