xref: /linux/tools/testing/selftests/net/lib/py/ksft.py (revision 9fc31a9251de4acaab2d0704450d70ddc99f5ea2)
1# SPDX-License-Identifier: GPL-2.0
2
3import builtins
4import inspect
5import sys
6import time
7import traceback
8from .consts import KSFT_MAIN_NAME
9
10KSFT_RESULT = None
11KSFT_RESULT_ALL = True
12
13
14class KsftSkipEx(Exception):
15    pass
16
17
18class KsftXfailEx(Exception):
19    pass
20
21
22def ksft_pr(*objs, **kwargs):
23    print("#", *objs, **kwargs)
24
25
26def _fail(*args):
27    global KSFT_RESULT
28    KSFT_RESULT = False
29
30    frame = inspect.stack()[2]
31    ksft_pr("At " + frame.filename + " line " + str(frame.lineno) + ":")
32    ksft_pr(*args)
33
34
35def ksft_eq(a, b, comment=""):
36    global KSFT_RESULT
37    if a != b:
38        _fail("Check failed", a, "!=", b, comment)
39
40
41def ksft_true(a, comment=""):
42    if not a:
43        _fail("Check failed", a, "does not eval to True", comment)
44
45
46def ksft_in(a, b, comment=""):
47    if a not in b:
48        _fail("Check failed", a, "not in", b, comment)
49
50
51def ksft_ge(a, b, comment=""):
52    if a < b:
53        _fail("Check failed", a, "<", b, comment)
54
55
56def ksft_busy_wait(cond, sleep=0.005, deadline=1, comment=""):
57    end = time.monotonic() + deadline
58    while True:
59        if cond():
60            return
61        if time.monotonic() > end:
62            _fail("Waiting for condition timed out", comment)
63            return
64        time.sleep(sleep)
65
66
67def ktap_result(ok, cnt=1, case="", comment=""):
68    global KSFT_RESULT_ALL
69    KSFT_RESULT_ALL = KSFT_RESULT_ALL and ok
70
71    res = ""
72    if not ok:
73        res += "not "
74    res += "ok "
75    res += str(cnt) + " "
76    res += KSFT_MAIN_NAME
77    if case:
78        res += "." + str(case.__name__)
79    if comment:
80        res += " # " + comment
81    print(res)
82
83
84def ksft_run(cases, args=()):
85    totals = {"pass": 0, "fail": 0, "skip": 0, "xfail": 0}
86
87    print("KTAP version 1")
88    print("1.." + str(len(cases)))
89
90    global KSFT_RESULT
91    cnt = 0
92    for case in cases:
93        KSFT_RESULT = True
94        cnt += 1
95        try:
96            case(*args)
97        except KsftSkipEx as e:
98            ktap_result(True, cnt, case, comment="SKIP " + str(e))
99            totals['skip'] += 1
100            continue
101        except KsftXfailEx as e:
102            ktap_result(True, cnt, case, comment="XFAIL " + str(e))
103            totals['xfail'] += 1
104            continue
105        except Exception as e:
106            tb = traceback.format_exc()
107            for line in tb.strip().split('\n'):
108                ksft_pr("Exception|", line)
109            ktap_result(False, cnt, case)
110            totals['fail'] += 1
111            continue
112
113        ktap_result(KSFT_RESULT, cnt, case)
114        if KSFT_RESULT:
115            totals['pass'] += 1
116        else:
117            totals['fail'] += 1
118
119    print(
120        f"# Totals: pass:{totals['pass']} fail:{totals['fail']} xfail:{totals['xfail']} xpass:0 skip:{totals['skip']} error:0"
121    )
122
123
124def ksft_exit():
125    global KSFT_RESULT_ALL
126    sys.exit(0 if KSFT_RESULT_ALL else 1)
127