blob: 976a1d5cd292b1b5fa074989f148785788b17e82 [file] [log] [blame]
Anders Roxell65be7682022-12-08 12:02:43 +01001#!/usr/bin/env python3
2import sys
3import re
Ryan Roberts6e2cfcd2024-02-10 11:45:59 +00004from tap import parser
Anders Roxell65be7682022-12-08 12:02:43 +01005
6
7def slugify(line):
8 non_ascii_pattern = r"[^A-Za-z0-9_-]+"
9 line = re.sub(r"\[\d{1,5}\]", "", line)
10 return re.sub(
11 r"_-", "_", re.sub(r"(^_|_$)", "", re.sub(non_ascii_pattern, "_", line))
12 )
13
14
Ryan Roberts6e2cfcd2024-02-10 11:45:59 +000015def parse_nested_tap(string):
16 results = []
17
18 def uncomment(line):
19 # All of the input lines should be comments and begin with #, but let's
20 # be cautious; don't do anything if the line doesn't begin with #.
21 if len(line) > 0 and line[0] == "#":
22 return line[1:].strip()
23 return line
24
25 def make_name(name, directive, ok, skip):
26 # Some of this is to maintain compatibility with the old parser.
27 if name.startswith("selftests:"):
28 name = name[10:]
29 if ok and skip and directive.lower().startswith("skip"):
30 directive = directive[4:]
Anders Roxell65be7682022-12-08 12:02:43 +010031 else:
Ryan Roberts6e2cfcd2024-02-10 11:45:59 +000032 directive = ""
33 name = f"{name} {directive}".strip()
34 if name == "":
35 name = "<unknown>"
36 return slugify(name)
37
38 def make_result(ok, skip):
39 return ("skip" if skip else "pass") if ok else "fail"
40
41 output = ""
42 ps = parser.Parser()
43 for l in ps.parse_text(string):
44 if l.category == "test":
45 results.append(
46 {
47 "name": make_name(l.description, l.directive.text, l.ok, l.skip),
48 "result": make_result(l.ok, l.skip),
49 "children": parse_nested_tap(output),
50 }
51 )
52 output = ""
53 elif l.category == "diagnostic":
54 output += f"{uncomment(l.text)}\n"
55
56 return results
57
58
59def flatten_results(prefix, results):
60 ret = []
61 for r in results:
62 test = f"{prefix}{r['name']}"
63 children = flatten_results(f"{test}_", r["children"])
64 ret += children + [{"name": test, "result": r["result"]}]
65 return ret
66
67
68def make_names_unique(results):
69 namecounts = {}
70 for r in results:
71 name = r["name"]
72 namecounts[name] = namecounts.get(name, 0) + 1
73 if namecounts[name] > 1:
74 r["name"] += f"_dup{namecounts[name]}"
75
76
77if __name__ == "__main__":
78 results = parse_nested_tap(sys.stdin.read())
79 results = flatten_results("", results)
80 make_names_unique(results)
81 for r in results:
82 print(f"{r['name']} {r['result']}")