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