Skip to content

Commit 0124043

Browse files
matttbekuba-moo
authored andcommitted
contest: vm: capture code coverage
Code coverage is a valuable info to get to know how much we can trust a test suite, and easily find out what needs to be improved. It is quite easy to get such info with the kernel: - The kernel needs to be compiled with GCOV_KERNEL=y, and have either GCOV_PROFILE_ALL=y, or GCOV_PROFILE := y set in the Makefiles. The recommended way is to add 'GCOV_PROFILE' in net/Makefile and drivers/net/Makefile. - Before stopping the VM, the LCOV file can be captured using the 'lcov' tool, version >= 2.0 is recommended. - 'genhtml' from the LCOV project can be used later to generate an HTML version using all the .lcov files. It could be done per LCOV file, but that will then only show the coverage per VM, not the global one. This GCOV support is disabled by default. It can be enabled via 'vm.gcov=on'. I suggest to keep it off by default, and switch it to on later when everything is in place. Signed-off-by: Matthieu Baerts (NGI0) <[email protected]>
1 parent 3855a91 commit 0124043

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

contest/remote/lib/vm.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import os
1010
import psutil
1111
import re
12+
import shutil
1213
import signal
1314
from .crash import has_crash, extract_crash
1415

@@ -38,6 +39,7 @@
3839
default_timeout=15
3940
boot_timeout=45
4041
slowdown=2.5 # mark the machine as slow and multiply the ksft timeout by 2.5
42+
gcov=off / on
4143
"""
4244

4345

@@ -66,6 +68,7 @@ def __init__(self, config, vm_name=""):
6668

6769
self.filter_data = None
6870
self.has_kmemleak = None
71+
self.has_gcov = self.config.getboolean('vm', 'gcov', fallback=False)
6972
self.log_out = ""
7073
self.log_err = ""
7174

@@ -101,11 +104,13 @@ def build(self, extra_configs, override_configs=None):
101104
if extra_configs:
102105
configs += extra_configs
103106

107+
gcov = " --configitem GCOV_KERNEL=y" if self.has_gcov else ""
108+
104109
print(f"INFO{self.print_pfx} building kernel")
105110
# Make sure we rebuild, config and module deps can be stale otherwise
106111
self.tree_cmd("make mrproper")
107112

108-
rc = self.tree_cmd("vng -v -b" + " -f ".join([""] + configs))
113+
rc = self.tree_cmd("vng -v -b" + " -f ".join([""] + configs) + gcov)
109114
if rc != 0:
110115
print(f"INFO{self.print_pfx} kernel build failed")
111116
return False
@@ -203,6 +208,7 @@ def start(self, cwd=None):
203208
self.cmd("ls /sys/kernel/debug/")
204209
self.drain_to_prompt()
205210
self.has_kmemleak = "kmemleak" in self.log_out[off:]
211+
self.has_gcov = self.has_gcov and "gcov" in self.log_out[off:]
206212

207213
self._set_env()
208214

@@ -387,6 +393,18 @@ def check_health(self):
387393
self.cmd("echo scan > /sys/kernel/debug/kmemleak && cat /sys/kernel/debug/kmemleak")
388394
self.drain_to_prompt()
389395

396+
def capture_gcov(self, dest):
397+
if not self.has_gcov:
398+
return
399+
400+
lcov = "kernel.lcov"
401+
self.cmd(f"lcov --capture --keep-going --rc geninfo_unexecuted_blocks=1 --function-coverage --branch-coverage -j $(nproc) -o {lcov}")
402+
self.drain_to_prompt()
403+
404+
lcov = os.path.join(self.tree_path, lcov)
405+
if os.path.isfile(lcov):
406+
shutil.copy(lcov, dest)
407+
390408
def bash_prev_retcode(self):
391409
self.cmd("echo $?")
392410
stdout, stderr = self.drain_to_prompt()

contest/remote/vmksft-p.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ def _vm_thread(config, results_path, thr_id, hard_stop, in_queue, out_queue):
218218
vm = None
219219

220220
if vm is not None:
221+
vm.capture_gcov(results_path + f'/kernel-thr{thr_id}-{vm_id}.lcov')
221222
vm.stop()
222223
vm.dump_log(results_path + f'/vm-stop-thr{thr_id}-{vm_id}')
223224
return

0 commit comments

Comments
 (0)