xref: /aosp_15_r20/external/igt-gpu-tools/docs/reference/igt-gpu-tools/generate_description_xml.py (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1#!/usr/bin/env python3
2
3import re
4import sys
5import os.path
6import subprocess
7import xml.etree.cElementTree as ET
8
9from collections import namedtuple
10
11Subtest = namedtuple("Subtest", "name description")
12KEYWORDS=re.compile(r'\b(invalid|hang|swap|thrash|crc|tiled|tiling|rte|ctx|render|blt|bsd|vebox|exec|rpm)\b')
13
14
15def get_testlist(path):
16    "read binaries' names from test-list.txt"
17    with open(path, 'r') as f:
18        assert(f.readline() == "TESTLIST\n")
19        tests = f.readline().strip().split(" ")
20        assert(f.readline() == "END TESTLIST\n")
21
22    return tests
23
24
25def keywordize(root, text, keywords):
26    "set text for root element and wrap KEYWORDS in a <acronym>"
27    matches = list(keywords.finditer(text))
28
29    if not matches:
30        root.text = text
31        return
32
33    pos = 0
34    last_element = None
35    root.text = ""
36
37    for match in matches:
38        if match.start() > pos:
39            to_append = text[pos:match.start()]
40
41            if last_element == None:
42                root.text += to_append
43            else:
44                last_element.tail += to_append
45
46        last_element = ET.SubElement(root, "acronym")
47        last_element.tail = ""
48        last_element.text=match.group()
49        pos = match.end()
50
51    last_element.tail = text[pos:]
52
53
54def get_subtests(testdir, test):
55    "execute test and get subtests with their descriptions via --describe"
56    output = []
57    full_test_path = os.path.join(testdir, test)
58    proc = subprocess.run([full_test_path, "--describe"], stdout=subprocess.PIPE)
59    description = ""
60    current_subtest = None
61
62    for line in proc.stdout.decode().splitlines():
63        if line.startswith("SUB "):
64            output += [Subtest(current_subtest, description)]
65            description = ""
66            current_subtest = line.split(' ')[1]
67        else:
68            description += line
69
70    output += [Subtest(current_subtest, description)]
71
72    return output
73
74def main():
75    output_file   = sys.argv[1]
76    test_filter   = re.compile(sys.argv[2])
77    testlist_file = sys.argv[3]
78    testdir       = os.path.abspath(os.path.dirname(testlist_file))
79
80    root = ET.Element("refsect1")
81    ET.SubElement(root, "title").text = "Description"
82
83    tests = get_testlist(testlist_file)
84
85    for test in tests:
86        if not test_filter.match(test):
87            continue
88
89        test_section = ET.SubElement(root, "refsect2", id=test)
90        test_title = ET.SubElement(test_section, "title")
91        keywordize(test_title, test, KEYWORDS)
92
93        subtests = get_subtests(testdir, test)
94
95        # we have description with no subtest name, add it at the top level
96        if subtests and not subtests[0].name:
97            ET.SubElement(test_section, "para").text = subtests[0].description
98
99        if len(subtests) > 100:
100            ET.SubElement(test_section, "para").text = "More than 100 subtests, skipping listing"
101            continue
102
103        for name, description in subtests:
104            if not name:
105                continue
106
107            subtest_section = ET.SubElement(test_section, "refsect3", id="{}@{}".format(test, name))
108            subtest_title = ET.SubElement(subtest_section, "title")
109            keywordize(subtest_title, name, KEYWORDS)
110            ET.SubElement(subtest_section, "para").text = description
111
112    ET.ElementTree(root).write(output_file)
113
114main()
115