xref: /aosp_15_r20/external/OpenCL-CTS/scripts/generate_test_files.py (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
1import json
2import os
3import re
4import shutil
5import subprocess
6from xml.dom import minidom
7from xml.etree import ElementTree
8
9
10SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
11TEST_JSON = 'tests.json'
12TEST_JSON_PATH = os.path.join(SCRIPT_DIR, TEST_JSON)
13
14
15def write_one_cc_test(test_details, f):
16  stringified_sources = map(lambda s: f'"{s}"', test_details['srcs'])
17  stringified_data = map(lambda s: f'"{s}"', test_details.get('data', []))
18  stringified_cflags = map(lambda s: f'"{s}"', test_details.get('cflags', []))
19
20  default = "ocl-test-defaults"
21  if test_details.get('image_type', False):
22    default = "ocl-test-image-defaults"
23
24  rtti = test_details.get('rtti', False)
25
26  cc_test_string = """
27cc_test {{
28    name: "{}",
29    srcs: [ {} ],
30    data: [ {} ],
31    cflags: [ {} ],
32    defaults: [ "{}" ],
33    rtti: {},
34    gtest: false
35}}
36
37""".format(test_details['binary_name'],
38           ", ".join(stringified_sources),
39           ", ".join(stringified_data),
40           ", ".join(stringified_cflags),
41           default,
42           (str(rtti)).lower())
43
44  empty_field_regex = re.compile("^\s*\w+: \[\s*\],?$")
45  cc_test_string = '\n'.join([line for line in cc_test_string.split('\n')
46                                   if not empty_field_regex.match(line)])
47  f.write(cc_test_string)
48
49
50# Return value indicates whether the output should be formatted with bpfmt
51def generate_android_bp() -> bool:
52  android_bp_head_path = os.path.join(SCRIPT_DIR, 'android_bp_head')
53  android_bp_tail_path = os.path.join(SCRIPT_DIR, 'android_bp_tail')
54
55  with open('Android.bp', 'w') as android_bp:
56    with open(android_bp_head_path, 'r') as android_bp_head:
57      android_bp.write(android_bp_head.read())
58
59    with open(TEST_JSON_PATH) as f:
60      tests = json.load(f)
61    for test in tests:
62      write_one_cc_test(test, android_bp)
63
64    with open(android_bp_tail_path, 'r') as android_bp_tail:
65      android_bp.write(android_bp_tail.read())
66
67  if shutil.which('bpfmt') is not None:
68    subprocess.run(['bpfmt', '-w', 'Android.bp'])
69    return True
70
71  return False
72
73
74def create_subelement_with_attribs(element, tag, attribs):
75  subelement = ElementTree.SubElement(element, tag)
76
77  for key, value in attribs.items():
78    subelement.attrib[key] = value
79
80  return subelement
81
82
83def generate_push_file_rules(configuration):
84  create_subelement_with_attribs(configuration, 'target_preparer',
85      { 'class': "com.android.tradefed.targetprep.RootTargetPreparer" })
86  file_pusher = create_subelement_with_attribs(configuration, 'target_preparer',
87      { 'class': "com.android.compatibility.common.tradefed.targetprep.FilePusher" })
88  create_subelement_with_attribs(file_pusher, 'option',
89      { 'name': "cleanup", 'value': "true" })
90  create_subelement_with_attribs(file_pusher, 'option',
91      { 'name': "append-bitness", 'value': "true" })
92
93  with open(TEST_JSON_PATH, "r") as f:
94    tests = json.load(f)
95
96  for test in tests:
97    if test.get('manual_only', False):
98      continue
99
100    create_subelement_with_attribs(file_pusher, 'option',
101        {
102          'name': "push-file",
103          'key': test['binary_name'],
104          'value': "/data/nativetest64/unrestricted/{}".format(test['binary_name'])
105        })
106
107
108def generate_test_rules(configuration):
109  with open(TEST_JSON_PATH, "r") as f:
110    tests = json.load(f)
111
112  for test in tests:
113    if test.get('manual_only', False):
114      continue
115
116    test_rule = create_subelement_with_attribs(configuration, 'test',
117        { 'class': "com.android.tradefed.testtype.python.PythonBinaryHostTest" })
118
119    create_subelement_with_attribs(test_rule, 'option',
120        { 'name': "par-file-name", 'value': "opencl_cts" })
121    create_subelement_with_attribs(test_rule, 'option',
122        { 'name': "inject-android-serial", 'value': "true" })
123    create_subelement_with_attribs(test_rule, 'option',
124        { 'name': "test-timeout", 'value': test.get('timeout', "30m") })
125    create_subelement_with_attribs(test_rule, 'option',
126        { 'name': "python-options", 'value': test["test_name"] })
127    create_subelement_with_attribs(test_rule, 'option',
128        { 'name': "python-options",
129          'value': "/data/nativetest64/unrestricted/{}".format(test['binary_name']) })
130
131    for arg in test.get('arguments', []):
132      create_subelement_with_attribs(test_rule, 'option',
133          { 'name': "python-options", 'value': arg })
134
135
136def generate_test_xml():
137  configuration = ElementTree.Element('configuration')
138  configuration.attrib['description'] = "Config to run OpenCL CTS"
139
140  logcat = ElementTree.SubElement(configuration, 'option')
141  logcat.attrib['name'] = "logcat-on-failure"
142  logcat.attrib['value'] = "false"
143
144  generate_push_file_rules(configuration)
145  generate_test_rules(configuration)
146
147  stringified_configuration = ElementTree.tostring(configuration, 'utf-8')
148  reparsed_configuration = minidom.parseString(stringified_configuration)
149  with open('test_opencl_cts.xml', 'w') as f:
150    f.write(reparsed_configuration.toprettyxml(indent=" "*4))
151
152
153def main():
154  android_bp_formatted = generate_android_bp()
155  generate_test_xml()
156
157  print("Don't forget to move -")
158  print("    Android.bp -> {ANDROID_ROOT}/external/OpenCL-CTS/Android.bp")
159  print("    test_opencl_cts.xml -> {ANDROID_ROOT}/external/OpenCL-CTS/scripts/test_opencl_cts.xml")
160  if not android_bp_formatted:
161    print("then run the blueprint autoformatter:")
162    print("    bpfmt -w {ANDROID_ROOT}/external/OpenCL-CTS/Android.bp")
163
164
165if __name__ == '__main__':
166  main()
167