xref: /aosp_15_r20/external/angle/scripts/update_extension_data.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/python3
2*8975f5c5SAndroid Build Coastguard Worker#
3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2021 The ANGLE Project Authors. All rights reserved.
4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
6*8975f5c5SAndroid Build Coastguard Worker#
7*8975f5c5SAndroid Build Coastguard Worker# update_extension_data.py:
8*8975f5c5SAndroid Build Coastguard Worker#   Downloads and updates auto-generated extension data.
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Workerimport argparse
11*8975f5c5SAndroid Build Coastguard Workerimport logging
12*8975f5c5SAndroid Build Coastguard Workerimport json
13*8975f5c5SAndroid Build Coastguard Workerimport os
14*8975f5c5SAndroid Build Coastguard Workerimport re
15*8975f5c5SAndroid Build Coastguard Workerimport shutil
16*8975f5c5SAndroid Build Coastguard Workerimport subprocess
17*8975f5c5SAndroid Build Coastguard Workerimport sys
18*8975f5c5SAndroid Build Coastguard Workerimport tempfile
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard WorkerEXIT_SUCCESS = 0
21*8975f5c5SAndroid Build Coastguard WorkerEXIT_FAILURE = 1
22*8975f5c5SAndroid Build Coastguard Worker
23*8975f5c5SAndroid Build Coastguard WorkerTEST_SUITE = 'angle_end2end_tests'
24*8975f5c5SAndroid Build Coastguard WorkerBUILDERS = [
25*8975f5c5SAndroid Build Coastguard Worker    'angle/ci/android-arm64-test', 'angle/ci/linux-test', 'angle/ci/win-test',
26*8975f5c5SAndroid Build Coastguard Worker    'angle/ci/win-x86-test'
27*8975f5c5SAndroid Build Coastguard Worker]
28*8975f5c5SAndroid Build Coastguard WorkerSWARMING_SERVER = 'chromium-swarm.appspot.com'
29*8975f5c5SAndroid Build Coastguard Worker
30*8975f5c5SAndroid Build Coastguard Workerd = os.path.dirname
31*8975f5c5SAndroid Build Coastguard WorkerTHIS_DIR = d(os.path.abspath(__file__))
32*8975f5c5SAndroid Build Coastguard WorkerANGLE_ROOT_DIR = d(THIS_DIR)
33*8975f5c5SAndroid Build Coastguard Worker
34*8975f5c5SAndroid Build Coastguard Worker# Host GPUs
35*8975f5c5SAndroid Build Coastguard WorkerINTEL_UHD630 = '8086:9bc5'
36*8975f5c5SAndroid Build Coastguard WorkerNVIDIA_GTX1660 = '10de:2184'
37*8975f5c5SAndroid Build Coastguard WorkerSWIFTSHADER = 'none'
38*8975f5c5SAndroid Build Coastguard WorkerGPUS = [INTEL_UHD630, NVIDIA_GTX1660, SWIFTSHADER]
39*8975f5c5SAndroid Build Coastguard WorkerGPU_NAME_MAP = {
40*8975f5c5SAndroid Build Coastguard Worker    INTEL_UHD630: 'intel_630',
41*8975f5c5SAndroid Build Coastguard Worker    NVIDIA_GTX1660: 'nvidia_1660',
42*8975f5c5SAndroid Build Coastguard Worker    SWIFTSHADER: 'swiftshader'
43*8975f5c5SAndroid Build Coastguard Worker}
44*8975f5c5SAndroid Build Coastguard Worker
45*8975f5c5SAndroid Build Coastguard Worker# OSes
46*8975f5c5SAndroid Build Coastguard WorkerLINUX = 'Linux'
47*8975f5c5SAndroid Build Coastguard WorkerWINDOWS_10 = 'Windows-10'
48*8975f5c5SAndroid Build Coastguard WorkerBOT_OSES = [LINUX, WINDOWS_10]
49*8975f5c5SAndroid Build Coastguard WorkerBOT_OS_NAME_MAP = {LINUX: 'linux', WINDOWS_10: 'win10'}
50*8975f5c5SAndroid Build Coastguard Worker
51*8975f5c5SAndroid Build Coastguard Worker# Devices
52*8975f5c5SAndroid Build Coastguard WorkerPIXEL_4 = 'flame'
53*8975f5c5SAndroid Build Coastguard WorkerPIXEL_6 = 'oriole'
54*8975f5c5SAndroid Build Coastguard WorkerDEVICES_TYPES = [PIXEL_4, PIXEL_6]
55*8975f5c5SAndroid Build Coastguard WorkerDEVICE_NAME_MAP = {PIXEL_4: 'pixel_4', PIXEL_6: 'pixel_6'}
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker# Device OSes
58*8975f5c5SAndroid Build Coastguard WorkerANDROID_11 = 'R'
59*8975f5c5SAndroid Build Coastguard WorkerANDROID_13 = 'T'
60*8975f5c5SAndroid Build Coastguard WorkerDEVICE_OSES = [ANDROID_11, ANDROID_13]
61*8975f5c5SAndroid Build Coastguard WorkerDEVICE_OS_NAME_MAP = {ANDROID_11: 'android_11', ANDROID_13: 'android_13'}
62*8975f5c5SAndroid Build Coastguard Worker
63*8975f5c5SAndroid Build Coastguard Worker# Result names
64*8975f5c5SAndroid Build Coastguard WorkerINFO_FILES = [
65*8975f5c5SAndroid Build Coastguard Worker    'GLinfo_ES3_2_Vulkan.json',
66*8975f5c5SAndroid Build Coastguard Worker    'GLinfo_ES3_1_Vulkan_SwiftShader.json',
67*8975f5c5SAndroid Build Coastguard Worker]
68*8975f5c5SAndroid Build Coastguard Worker
69*8975f5c5SAndroid Build Coastguard WorkerLOG_LEVELS = ['WARNING', 'INFO', 'DEBUG']
70*8975f5c5SAndroid Build Coastguard Worker
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Workerdef run_and_get_json(args):
73*8975f5c5SAndroid Build Coastguard Worker    logging.debug(' '.join(args))
74*8975f5c5SAndroid Build Coastguard Worker    output = subprocess.check_output(args)
75*8975f5c5SAndroid Build Coastguard Worker    return json.loads(output)
76*8975f5c5SAndroid Build Coastguard Worker
77*8975f5c5SAndroid Build Coastguard Worker
78*8975f5c5SAndroid Build Coastguard Workerdef get_bb():
79*8975f5c5SAndroid Build Coastguard Worker    return 'bb.bat' if os.name == 'nt' else 'bb'
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker
82*8975f5c5SAndroid Build Coastguard Workerdef run_bb_and_get_output(*args):
83*8975f5c5SAndroid Build Coastguard Worker    bb_args = [get_bb()] + list(args)
84*8975f5c5SAndroid Build Coastguard Worker    return subprocess.check_output(bb_args, encoding='utf-8')
85*8975f5c5SAndroid Build Coastguard Worker
86*8975f5c5SAndroid Build Coastguard Worker
87*8975f5c5SAndroid Build Coastguard Workerdef run_bb_and_get_json(*args):
88*8975f5c5SAndroid Build Coastguard Worker    bb_args = [get_bb()] + list(args) + ['-json']
89*8975f5c5SAndroid Build Coastguard Worker    return run_and_get_json(bb_args)
90*8975f5c5SAndroid Build Coastguard Worker
91*8975f5c5SAndroid Build Coastguard Worker
92*8975f5c5SAndroid Build Coastguard Workerdef get_swarming():
93*8975f5c5SAndroid Build Coastguard Worker    swarming_bin = 'swarming.exe' if os.name == 'nt' else 'swarming'
94*8975f5c5SAndroid Build Coastguard Worker    return os.path.join(ANGLE_ROOT_DIR, 'tools', 'luci-go', swarming_bin)
95*8975f5c5SAndroid Build Coastguard Worker
96*8975f5c5SAndroid Build Coastguard Worker
97*8975f5c5SAndroid Build Coastguard Workerdef run_swarming(*args):
98*8975f5c5SAndroid Build Coastguard Worker    swarming_args = [get_swarming()] + list(args)
99*8975f5c5SAndroid Build Coastguard Worker    logging.debug(' '.join(swarming_args))
100*8975f5c5SAndroid Build Coastguard Worker    subprocess.check_call(swarming_args)
101*8975f5c5SAndroid Build Coastguard Worker
102*8975f5c5SAndroid Build Coastguard Worker
103*8975f5c5SAndroid Build Coastguard Workerdef run_swarming_and_get_json(*args):
104*8975f5c5SAndroid Build Coastguard Worker    swarming_args = [get_swarming()] + list(args)
105*8975f5c5SAndroid Build Coastguard Worker    return run_and_get_json(swarming_args)
106*8975f5c5SAndroid Build Coastguard Worker
107*8975f5c5SAndroid Build Coastguard Worker
108*8975f5c5SAndroid Build Coastguard Workerdef name_device(gpu, device_type):
109*8975f5c5SAndroid Build Coastguard Worker    if gpu:
110*8975f5c5SAndroid Build Coastguard Worker        return GPU_NAME_MAP[gpu]
111*8975f5c5SAndroid Build Coastguard Worker    else:
112*8975f5c5SAndroid Build Coastguard Worker        assert device_type
113*8975f5c5SAndroid Build Coastguard Worker        return DEVICE_NAME_MAP[device_type]
114*8975f5c5SAndroid Build Coastguard Worker
115*8975f5c5SAndroid Build Coastguard Worker
116*8975f5c5SAndroid Build Coastguard Workerdef name_os(bot_os, device_os):
117*8975f5c5SAndroid Build Coastguard Worker    if bot_os:
118*8975f5c5SAndroid Build Coastguard Worker        return BOT_OS_NAME_MAP[bot_os]
119*8975f5c5SAndroid Build Coastguard Worker    else:
120*8975f5c5SAndroid Build Coastguard Worker        assert device_os
121*8975f5c5SAndroid Build Coastguard Worker        return DEVICE_OS_NAME_MAP[device_os]
122*8975f5c5SAndroid Build Coastguard Worker
123*8975f5c5SAndroid Build Coastguard Worker
124*8975f5c5SAndroid Build Coastguard Workerdef get_props_string(gpu, bot_os, device_os, device_type):
125*8975f5c5SAndroid Build Coastguard Worker    d = {'gpu': gpu, 'os': bot_os, 'device os': device_os, 'device': device_type}
126*8975f5c5SAndroid Build Coastguard Worker    return ', '.join('%s %s' % (k, v) for (k, v) in d.items() if v)
127*8975f5c5SAndroid Build Coastguard Worker
128*8975f5c5SAndroid Build Coastguard Worker
129*8975f5c5SAndroid Build Coastguard Workerdef collect_task_and_update_json(task_id, found_dims):
130*8975f5c5SAndroid Build Coastguard Worker    gpu = found_dims.get('gpu', None)
131*8975f5c5SAndroid Build Coastguard Worker    bot_os = found_dims.get('os', None)
132*8975f5c5SAndroid Build Coastguard Worker    device_os = found_dims.get('device_os', None)
133*8975f5c5SAndroid Build Coastguard Worker    device_type = found_dims.get('device_type', None)
134*8975f5c5SAndroid Build Coastguard Worker    logging.info('Found task with ID: %s, %s' %
135*8975f5c5SAndroid Build Coastguard Worker                 (task_id, get_props_string(gpu, bot_os, device_os, device_type)))
136*8975f5c5SAndroid Build Coastguard Worker    target_file_name = '%s_%s.json' % (name_device(gpu, device_type), name_os(bot_os, device_os))
137*8975f5c5SAndroid Build Coastguard Worker    target_file = os.path.join(THIS_DIR, 'extension_data', target_file_name)
138*8975f5c5SAndroid Build Coastguard Worker    with tempfile.TemporaryDirectory() as tempdirname:
139*8975f5c5SAndroid Build Coastguard Worker        run_swarming('collect', '-S', SWARMING_SERVER, '-output-dir=%s' % tempdirname, task_id)
140*8975f5c5SAndroid Build Coastguard Worker        task_dir = os.path.join(tempdirname, task_id)
141*8975f5c5SAndroid Build Coastguard Worker        found = False
142*8975f5c5SAndroid Build Coastguard Worker        for fname in os.listdir(task_dir):
143*8975f5c5SAndroid Build Coastguard Worker            if fname in INFO_FILES:
144*8975f5c5SAndroid Build Coastguard Worker                if found:
145*8975f5c5SAndroid Build Coastguard Worker                    logging.warning('Multiple candidates found for %s' % target_file_name)
146*8975f5c5SAndroid Build Coastguard Worker                    return
147*8975f5c5SAndroid Build Coastguard Worker                else:
148*8975f5c5SAndroid Build Coastguard Worker                    logging.info('%s -> %s' % (fname, target_file))
149*8975f5c5SAndroid Build Coastguard Worker                    found = True
150*8975f5c5SAndroid Build Coastguard Worker                    source_file = os.path.join(task_dir, fname)
151*8975f5c5SAndroid Build Coastguard Worker                    shutil.copy(source_file, target_file)
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker
154*8975f5c5SAndroid Build Coastguard Workerdef get_intersect_or_none(list_a, list_b):
155*8975f5c5SAndroid Build Coastguard Worker    i = [v for v in list_a if v in list_b]
156*8975f5c5SAndroid Build Coastguard Worker    assert not i or len(i) == 1
157*8975f5c5SAndroid Build Coastguard Worker    return i[0] if i else None
158*8975f5c5SAndroid Build Coastguard Worker
159*8975f5c5SAndroid Build Coastguard Worker
160*8975f5c5SAndroid Build Coastguard Workerdef main():
161*8975f5c5SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser(description='Pulls extension support data from ANGLE CI.')
162*8975f5c5SAndroid Build Coastguard Worker    parser.add_argument(
163*8975f5c5SAndroid Build Coastguard Worker        '-v', '--verbose', help='Print additional debugging into.', action='count', default=0)
164*8975f5c5SAndroid Build Coastguard Worker    args = parser.parse_args()
165*8975f5c5SAndroid Build Coastguard Worker
166*8975f5c5SAndroid Build Coastguard Worker    if args.verbose >= len(LOG_LEVELS):
167*8975f5c5SAndroid Build Coastguard Worker        args.verbose = len(LOG_LEVELS) - 1
168*8975f5c5SAndroid Build Coastguard Worker    logging.basicConfig(level=LOG_LEVELS[args.verbose])
169*8975f5c5SAndroid Build Coastguard Worker
170*8975f5c5SAndroid Build Coastguard Worker    name_expr = re.compile(r'^' + TEST_SUITE + r' on (.*) on (.*)$')
171*8975f5c5SAndroid Build Coastguard Worker
172*8975f5c5SAndroid Build Coastguard Worker    for builder in BUILDERS:
173*8975f5c5SAndroid Build Coastguard Worker
174*8975f5c5SAndroid Build Coastguard Worker        # Step 1: Find the build ID.
175*8975f5c5SAndroid Build Coastguard Worker        # We list two builds using 'bb ls' and take the second, to ensure the build is finished.
176*8975f5c5SAndroid Build Coastguard Worker        ls_output = run_bb_and_get_output('ls', builder, '-n', '2', '-id')
177*8975f5c5SAndroid Build Coastguard Worker        build_id = ls_output.splitlines()[1]
178*8975f5c5SAndroid Build Coastguard Worker        logging.info('%s: build id %s' % (builder, build_id))
179*8975f5c5SAndroid Build Coastguard Worker
180*8975f5c5SAndroid Build Coastguard Worker        # Step 2: Get the test suite swarm hashes.
181*8975f5c5SAndroid Build Coastguard Worker        # 'bb get' returns build properties, including cloud storage identifiers for this test suite.
182*8975f5c5SAndroid Build Coastguard Worker        get_json = run_bb_and_get_json('get', build_id, '-p')
183*8975f5c5SAndroid Build Coastguard Worker        test_suite_hash = get_json['output']['properties']['swarm_hashes'][TEST_SUITE]
184*8975f5c5SAndroid Build Coastguard Worker        logging.info('Found swarm hash: %s' % test_suite_hash)
185*8975f5c5SAndroid Build Coastguard Worker
186*8975f5c5SAndroid Build Coastguard Worker        # Step 3: Find all tasks using the swarm hashes.
187*8975f5c5SAndroid Build Coastguard Worker        # 'swarming tasks' can find instances of the test suite that ran on specific systems.
188*8975f5c5SAndroid Build Coastguard Worker        task_json = run_swarming_and_get_json('tasks', '-tag', 'data:%s' % test_suite_hash, '-S',
189*8975f5c5SAndroid Build Coastguard Worker                                              SWARMING_SERVER)
190*8975f5c5SAndroid Build Coastguard Worker
191*8975f5c5SAndroid Build Coastguard Worker        # Step 4: Download the extension data for each configuration we're monitoring.
192*8975f5c5SAndroid Build Coastguard Worker        # 'swarming collect' downloads test artifacts to a temporary directory.
193*8975f5c5SAndroid Build Coastguard Worker        dim_map = {
194*8975f5c5SAndroid Build Coastguard Worker            'gpu': GPUS,
195*8975f5c5SAndroid Build Coastguard Worker            'os': BOT_OSES,
196*8975f5c5SAndroid Build Coastguard Worker            'device_os': DEVICE_OSES,
197*8975f5c5SAndroid Build Coastguard Worker            'device_type': DEVICES_TYPES,
198*8975f5c5SAndroid Build Coastguard Worker        }
199*8975f5c5SAndroid Build Coastguard Worker
200*8975f5c5SAndroid Build Coastguard Worker        for task in task_json:
201*8975f5c5SAndroid Build Coastguard Worker            found_dims = {}
202*8975f5c5SAndroid Build Coastguard Worker            for bot_dim in task['bot_dimensions']:
203*8975f5c5SAndroid Build Coastguard Worker                key, value = bot_dim['key'], bot_dim['value']
204*8975f5c5SAndroid Build Coastguard Worker                if key in dim_map:
205*8975f5c5SAndroid Build Coastguard Worker                    logging.debug('%s=%s' % (key, value))
206*8975f5c5SAndroid Build Coastguard Worker                    mapped_values = dim_map[key]
207*8975f5c5SAndroid Build Coastguard Worker                    found_dim = get_intersect_or_none(mapped_values, value)
208*8975f5c5SAndroid Build Coastguard Worker                    if found_dim:
209*8975f5c5SAndroid Build Coastguard Worker                        found_dims[key] = found_dim
210*8975f5c5SAndroid Build Coastguard Worker            found_gpu_or_device = ('gpu' in found_dims or 'device_type' in found_dims)
211*8975f5c5SAndroid Build Coastguard Worker            found_os = ('os' in found_dims or 'device_os' in found_dims)
212*8975f5c5SAndroid Build Coastguard Worker            if found_gpu_or_device and found_os:
213*8975f5c5SAndroid Build Coastguard Worker                collect_task_and_update_json(task['task_id'], found_dims)
214*8975f5c5SAndroid Build Coastguard Worker
215*8975f5c5SAndroid Build Coastguard Worker    return EXIT_SUCCESS
216*8975f5c5SAndroid Build Coastguard Worker
217*8975f5c5SAndroid Build Coastguard Worker
218*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
219*8975f5c5SAndroid Build Coastguard Worker    sys.exit(main())
220