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