summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/net/lib/py/ksft.py
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2024-06-27 20:55:01 +0200
committerJakub Kicinski <kuba@kernel.org>2024-06-29 03:39:39 +0200
commit8510801a9dbd9f0d64079d7061d3452efc752550 (patch)
treea17ac2873b55ec5b1668bffe830950cd811c55fb /tools/testing/selftests/net/lib/py/ksft.py
parentselftests: net: ksft: avoid continue when handling results (diff)
downloadlinux-8510801a9dbd9f0d64079d7061d3452efc752550.tar.xz
linux-8510801a9dbd9f0d64079d7061d3452efc752550.zip
selftests: drv-net: add ability to schedule cleanup with defer()
This implements what I was describing in [1]. When writing a test author can schedule cleanup / undo actions right after the creation completes, eg: cmd("touch /tmp/file") defer(cmd, "rm /tmp/file") defer() takes the function name as first argument, and the rest are arguments for that function. defer()red functions are called in inverse order after test exits. It's also possible to capture them and execute earlier (in which case they get automatically de-queued). undo = defer(cmd, "rm /tmp/file") # ... some unsafe code ... undo.exec() As a nice safety all exceptions from defer()ed calls are captured, printed, and ignored (they do make the test fail, however). This addresses the common problem of exceptions in cleanup paths often being unhandled, leading to potential leaks. There is a global action queue, flushed by ksft_run(). We could support function level defers too, I guess, but there's no immediate need.. Link: https://lore.kernel.org/all/877cedb2ki.fsf@nvidia.com/ # [1] Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Reviewed-by: Petr Machata <petrm@nvidia.com> Link: https://patch.msgid.link/20240627185502.3069139-3-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'tools/testing/selftests/net/lib/py/ksft.py')
-rw-r--r--tools/testing/selftests/net/lib/py/ksft.py21
1 files changed, 21 insertions, 0 deletions
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index 789433262dc7..3aaa2748a58e 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -6,6 +6,7 @@ import sys
import time
import traceback
from .consts import KSFT_MAIN_NAME
+from .utils import global_defer_queue
KSFT_RESULT = None
KSFT_RESULT_ALL = True
@@ -108,6 +109,24 @@ def ktap_result(ok, cnt=1, case="", comment=""):
print(res)
+def ksft_flush_defer():
+ global KSFT_RESULT
+
+ i = 0
+ qlen_start = len(global_defer_queue)
+ while global_defer_queue:
+ i += 1
+ entry = global_defer_queue.pop()
+ try:
+ entry.exec_only()
+ except:
+ ksft_pr(f"Exception while handling defer / cleanup (callback {i} of {qlen_start})!")
+ tb = traceback.format_exc()
+ for line in tb.strip().split('\n'):
+ ksft_pr("Defer Exception|", line)
+ KSFT_RESULT = False
+
+
def ksft_run(cases=None, globs=None, case_pfx=None, args=()):
cases = cases or []
@@ -148,6 +167,8 @@ def ksft_run(cases=None, globs=None, case_pfx=None, args=()):
KSFT_RESULT = False
cnt_key = 'fail'
+ ksft_flush_defer()
+
if not cnt_key:
cnt_key = 'pass' if KSFT_RESULT else 'fail'