summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorAntonio Russo <[email protected]>2023-05-15 17:11:33 -0600
committerGitHub <[email protected]>2023-05-15 16:11:33 -0700
commite0d5007bcf7e4425d43ba2ad56489c7db5c4a4c5 (patch)
tree2660f166b03c4f2f67d283db6aba796b9cddae58 /tests
parentee7b71dbc919439b1db6352bcd95f121127b42dd (diff)
test-runner: pass kmemleak and kmsg to Cmd.run
test-runner.py orchestrates all of the ZTS executions. The `Cmd` object manages these process, and its `run` method specifically invokes these possibly long-running processes, possibly retrying in the event of a timeout. Since its inception, memory leak detection using the kmemleak infrastructure [1], and kernel logging [2] have been added to this run mechanism. However, the callback to cull a process beyond its timeout threshold, `kill_cmd`, has evaded modernization by both of these changes. As a result, this function fails to properly invoke `run`, leading to an untrapped exception and unreported test failure. This patch extends `kill_cmd` to receive these kernel devices through the `options` parameter, and regularizes all the `.run` calls from `Cmd`, and its subclasses, to accept that parameter. [1] Commit a69765ea5b563e0cd4d15fac4b1ac08c6ccf12d1 [2] Commit fc2c0256c55a2859d1988671b0896d22b75c8aba Reviewed-by: John Wren Kennedy <[email protected]> Signed-off-by: Antonio Russo <[email protected]> Closes #14849
Diffstat (limited to 'tests')
-rwxr-xr-xtests/test-runner/bin/test-runner.py.in38
1 files changed, 22 insertions, 16 deletions
diff --git a/tests/test-runner/bin/test-runner.py.in b/tests/test-runner/bin/test-runner.py.in
index c454bf8d7..422ebd7bc 100755
--- a/tests/test-runner/bin/test-runner.py.in
+++ b/tests/test-runner/bin/test-runner.py.in
@@ -181,7 +181,7 @@ Timeout: %d
User: %s
''' % (self.pathname, self.identifier, self.outputdir, self.timeout, self.user)
- def kill_cmd(self, proc, keyboard_interrupt=False):
+ def kill_cmd(self, proc, options, kmemleak, keyboard_interrupt=False):
"""
Kill a running command due to timeout, or ^C from the keyboard. If
sudo is required, this user was verified previously.
@@ -211,7 +211,7 @@ User: %s
if int(self.timeout) > runtime:
self.killed = False
self.reran = False
- self.run(False)
+ self.run(options, dryrun=False, kmemleak=kmemleak)
self.reran = True
def update_cmd_privs(self, cmd, user):
@@ -257,15 +257,19 @@ User: %s
return out.lines, err.lines
- def run(self, dryrun, kmemleak, kmsg):
+ def run(self, options, dryrun=None, kmemleak=None):
"""
This is the main function that runs each individual test.
Determine whether or not the command requires sudo, and modify it
if needed. Run the command, and update the result object.
"""
+ if dryrun is None:
+ dryrun = options.dryrun
if dryrun is True:
print(self)
return
+ if kmemleak is None:
+ kmemleak = options.kmemleak
privcmd = self.update_cmd_privs(self.pathname, self.user)
try:
@@ -280,7 +284,7 @@ User: %s
Log each test we run to /dev/kmsg (on Linux), so if there's a kernel
warning we'll be able to match it up to a particular test.
"""
- if kmsg is True and exists("/dev/kmsg"):
+ if options.kmsg is True and exists("/dev/kmsg"):
try:
kp = Popen([SUDO, "sh", "-c",
f"echo ZTS run {self.pathname} > /dev/kmsg"])
@@ -298,7 +302,9 @@ User: %s
# Allow a special timeout value of 0 to mean infinity
if int(self.timeout) == 0:
self.timeout = sys.maxsize / (10 ** 9)
- t = Timer(int(self.timeout), self.kill_cmd, [proc])
+ t = Timer(
+ int(self.timeout), self.kill_cmd, [proc, options, kmemleak]
+ )
try:
t.start()
@@ -310,7 +316,7 @@ User: %s
cmd = f'{SUDO} cat {KMEMLEAK_FILE}'
self.result.kmemleak = check_output(cmd, shell=True)
except KeyboardInterrupt:
- self.kill_cmd(proc, True)
+ self.kill_cmd(proc, options, kmemleak, True)
fail('\nRun terminated at user request.')
finally:
t.cancel()
@@ -450,7 +456,7 @@ Tags: %s
return True
- def run(self, options):
+ def run(self, options, dryrun=None, kmemleak=None):
"""
Create Cmd instances for the pre/post/failsafe scripts. If the pre
script doesn't pass, skip this Test. Run the post script regardless.
@@ -472,14 +478,14 @@ Tags: %s
cont = True
if len(pretest.pathname):
- pretest.run(options.dryrun, False, options.kmsg)
+ pretest.run(options, kmemleak=False)
cont = pretest.result.result == 'PASS'
pretest.log(options)
if cont:
- test.run(options.dryrun, options.kmemleak, options.kmsg)
+ test.run(options, kmemleak=kmemleak)
if test.result.result == 'KILLED' and len(failsafe.pathname):
- failsafe.run(options.dryrun, False, options.kmsg)
+ failsafe.run(options, kmemleak=False)
failsafe.log(options, suppress_console=True)
else:
test.skip()
@@ -487,7 +493,7 @@ Tags: %s
test.log(options)
if len(posttest.pathname):
- posttest.run(options.dryrun, False, options.kmsg)
+ posttest.run(options, kmemleak=False)
posttest.log(options)
@@ -571,7 +577,7 @@ Tags: %s
return len(self.tests) != 0
- def run(self, options):
+ def run(self, options, dryrun=None, kmemleak=None):
"""
Create Cmd instances for the pre/post/failsafe scripts. If the pre
script doesn't pass, skip all the tests in this TestGroup. Run the
@@ -590,7 +596,7 @@ Tags: %s
cont = True
if len(pretest.pathname):
- pretest.run(options.dryrun, False, options.kmsg)
+ pretest.run(options, dryrun=dryrun, kmemleak=False)
cont = pretest.result.result == 'PASS'
pretest.log(options)
@@ -603,9 +609,9 @@ Tags: %s
failsafe = Cmd(self.failsafe, outputdir=odir, timeout=self.timeout,
user=self.failsafe_user, identifier=self.identifier)
if cont:
- test.run(options.dryrun, options.kmemleak, options.kmsg)
+ test.run(options, dryrun=dryrun, kmemleak=kmemleak)
if test.result.result == 'KILLED' and len(failsafe.pathname):
- failsafe.run(options.dryrun, False, options.kmsg)
+ failsafe.run(options, dryrun=dryrun, kmemleak=False)
failsafe.log(options, suppress_console=True)
else:
test.skip()
@@ -613,7 +619,7 @@ Tags: %s
test.log(options)
if len(posttest.pathname):
- posttest.run(options.dryrun, False, options.kmsg)
+ posttest.run(options, dryrun=dryrun, kmemleak=False)
posttest.log(options)