summaryrefslogtreecommitdiff
path: root/scripts/code_cov_gather_on_test
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/code_cov_gather_on_test')
-rwxr-xr-xscripts/code_cov_gather_on_test91
1 files changed, 91 insertions, 0 deletions
diff --git a/scripts/code_cov_gather_on_test b/scripts/code_cov_gather_on_test
new file mode 100755
index 00000000..b4356aa1
--- /dev/null
+++ b/scripts/code_cov_gather_on_test
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0 OR MIT
+#
+# Copyright (C) 2022 Intel Corporation
+#
+# gather_on_test.py
+#
+# by Tomi Sarvela <tomi.p.sarvela@intel.com>
+#
+# Faster implementation for linux kernel GCOV data collection
+# Command line compatible with original gather_on_test.sh
+#
+# Refs:
+# https://www.kernel.org/doc/html/latest/dev-tools/gcov.html
+#
+import argparse
+import errno
+import io
+import os
+import sys
+import tarfile
+
+def parse_args() -> argparse.Namespace:
+ '''Command line arguments'''
+ ap = argparse.ArgumentParser(description="Gather Linux kernel GCOV data")
+ ap.add_argument('output',
+ help="Output file name (.tar.gz will be added)")
+ ap.add_argument('--gcov', default='/sys/kernel/debug/gcov',
+ help="GCOV directory, default: /sys/kernel/debug/gcov")
+ return ap.parse_args()
+
+def tar_add_link(tar:tarfile.TarFile, filename:str):
+ '''Add filename as symlink to tarfile'''
+ info = tarfile.TarInfo(filename)
+ if info.name[0] == '/': info.name = info.name[1:]
+ info.type = tarfile.SYMTYPE
+ info.linkname = os.readlink(filename)
+ tar.addfile(info)
+
+def tar_add_file(tar:tarfile.TarFile, filename:str):
+ '''Add filename to tarfile, file size expected to be invalid'''
+ try:
+ with open(filename, "rb") as fp:
+ data = fp.read() # big gulp
+ except OSError as e:
+ print(f"ERROR: {filename}: {e}", file=sys.stderr)
+ return
+ info = tarfile.TarInfo(filename)
+ if info.name[0] == '/': info.name = info.name[1:]
+ info.size = len(data)
+ tar.addfile(info, io.BytesIO(data))
+
+def tar_add_tree(tar:tarfile.TarFile, tree:str):
+ '''Add gcov files in directory tree to tar'''
+ # FIXME: should dirs be added to tar for compatibility?
+ for root, _, files in os.walk(tree, followlinks=False):
+ for file in files:
+ filepath = os.path.join(root, file)
+ if file.endswith('.gcda'): tar_add_file(tar, filepath)
+ if file.endswith('.gcno'): tar_add_link(tar, filepath)
+
+def main() -> int:
+ '''MAIN'''
+ if not os.path.isdir(args.gcov):
+ print(f"ERROR: [Errno {errno.ENOTDIR}] {os.strerror(errno.ENOTDIR)}: '{args.gcov}'",
+ file=sys.stderr)
+ return errno.ENOTDIR
+ if args.output == '-':
+ # reopen stdout as bytes for tarfile
+ fp = os.fdopen(sys.stdout.fileno(), "wb", closefd=False)
+ else:
+ if not args.output.endswith('.tgz') and \
+ not args.output.endswith('.tar.gz'):
+ args.output+='.tar.gz'
+ try:
+ fp = open(args.output, 'wb')
+ except OSError as e:
+ print(f"ERROR: {e}", file=sys.stderr)
+ return e.errno
+ with tarfile.open(fileobj=fp, mode='w:gz') as tar:
+ tar_add_tree(tar, args.gcov)
+ fp.close()
+ return 0
+
+if __name__ == '__main__':
+ try:
+ args = parse_args()
+ sys.exit(main())
+ except KeyboardInterrupt:
+ print("Interrupted", file=sys.stderr)
+ sys.exit(errno.EINTR)