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