1*8975f5c5SAndroid Build Coastguard Worker#! /usr/bin/env vpython3 2*8975f5c5SAndroid Build Coastguard Worker# 3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2020 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""" 8*8975f5c5SAndroid Build Coastguard WorkerScript testing capture_replay with angle_end2end_tests 9*8975f5c5SAndroid Build Coastguard Worker""" 10*8975f5c5SAndroid Build Coastguard Worker 11*8975f5c5SAndroid Build Coastguard Worker# Automation script will: 12*8975f5c5SAndroid Build Coastguard Worker# 1. Build all tests in angle_end2end with frame capture enabled 13*8975f5c5SAndroid Build Coastguard Worker# 2. Run each test with frame capture 14*8975f5c5SAndroid Build Coastguard Worker# 3. Build CaptureReplayTest with cpp trace files 15*8975f5c5SAndroid Build Coastguard Worker# 4. Run CaptureReplayTest 16*8975f5c5SAndroid Build Coastguard Worker# 5. Output the number of test successes and failures. A test succeeds if no error occurs during 17*8975f5c5SAndroid Build Coastguard Worker# its capture and replay, and the GL states at the end of two runs match. Any unexpected failure 18*8975f5c5SAndroid Build Coastguard Worker# will return non-zero exit code 19*8975f5c5SAndroid Build Coastguard Worker 20*8975f5c5SAndroid Build Coastguard Worker# Run this script with Python to test capture replay on angle_end2end tests 21*8975f5c5SAndroid Build Coastguard Worker# python path/to/capture_replay_tests.py 22*8975f5c5SAndroid Build Coastguard Worker# Command line arguments: run with --help for a full list. 23*8975f5c5SAndroid Build Coastguard Worker 24*8975f5c5SAndroid Build Coastguard Workerimport argparse 25*8975f5c5SAndroid Build Coastguard Workerimport concurrent.futures 26*8975f5c5SAndroid Build Coastguard Workerimport contextlib 27*8975f5c5SAndroid Build Coastguard Workerimport difflib 28*8975f5c5SAndroid Build Coastguard Workerimport distutils.util 29*8975f5c5SAndroid Build Coastguard Workerimport getpass 30*8975f5c5SAndroid Build Coastguard Workerimport glob 31*8975f5c5SAndroid Build Coastguard Workerimport json 32*8975f5c5SAndroid Build Coastguard Workerimport logging 33*8975f5c5SAndroid Build Coastguard Workerimport os 34*8975f5c5SAndroid Build Coastguard Workerimport pathlib 35*8975f5c5SAndroid Build Coastguard Workerimport queue 36*8975f5c5SAndroid Build Coastguard Workerimport random 37*8975f5c5SAndroid Build Coastguard Workerimport re 38*8975f5c5SAndroid Build Coastguard Workerimport shutil 39*8975f5c5SAndroid Build Coastguard Workerimport subprocess 40*8975f5c5SAndroid Build Coastguard Workerimport sys 41*8975f5c5SAndroid Build Coastguard Workerimport tempfile 42*8975f5c5SAndroid Build Coastguard Workerimport threading 43*8975f5c5SAndroid Build Coastguard Workerimport time 44*8975f5c5SAndroid Build Coastguard Workerimport traceback 45*8975f5c5SAndroid Build Coastguard Worker 46*8975f5c5SAndroid Build Coastguard WorkerSCRIPT_DIR = str(pathlib.Path(__file__).resolve().parent) 47*8975f5c5SAndroid Build Coastguard WorkerPY_UTILS = str(pathlib.Path(SCRIPT_DIR) / 'py_utils') 48*8975f5c5SAndroid Build Coastguard Workerif PY_UTILS not in sys.path: 49*8975f5c5SAndroid Build Coastguard Worker os.stat(PY_UTILS) and sys.path.insert(0, PY_UTILS) 50*8975f5c5SAndroid Build Coastguard Workerimport angle_test_util 51*8975f5c5SAndroid Build Coastguard Worker 52*8975f5c5SAndroid Build Coastguard WorkerPIPE_STDOUT = True 53*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_OUT_DIR = "out/CaptureReplayTest" # relative to angle folder 54*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_FILTER = "*/ES2_Vulkan_SwiftShader" 55*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_TEST_SUITE = "angle_end2end_tests" 56*8975f5c5SAndroid Build Coastguard WorkerREPLAY_SAMPLE_FOLDER = "src/tests/capture_replay_tests" # relative to angle folder 57*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_BATCH_COUNT = 1 # number of tests batched together for capture 58*8975f5c5SAndroid Build Coastguard WorkerCAPTURE_FRAME_END = 100 59*8975f5c5SAndroid Build Coastguard WorkerTRACE_FILE_SUFFIX = "_context" # because we only deal with 1 context right now 60*8975f5c5SAndroid Build Coastguard WorkerRESULT_TAG = "*RESULT" 61*8975f5c5SAndroid Build Coastguard WorkerSTATUS_MESSAGE_PERIOD = 20 # in seconds 62*8975f5c5SAndroid Build Coastguard WorkerCAPTURE_SUBPROCESS_TIMEOUT = 600 # in seconds 63*8975f5c5SAndroid Build Coastguard WorkerREPLAY_SUBPROCESS_TIMEOUT = 60 # in seconds 64*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_RESULT_FILE = "results.txt" 65*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_LOG_LEVEL = "info" 66*8975f5c5SAndroid Build Coastguard WorkerDEFAULT_MAX_JOBS = 8 67*8975f5c5SAndroid Build Coastguard WorkerREPLAY_BINARY = "capture_replay_tests" 68*8975f5c5SAndroid Build Coastguard Workerif sys.platform == "win32": 69*8975f5c5SAndroid Build Coastguard Worker REPLAY_BINARY += ".exe" 70*8975f5c5SAndroid Build Coastguard WorkerTRACE_FOLDER = "traces" 71*8975f5c5SAndroid Build Coastguard Worker 72*8975f5c5SAndroid Build Coastguard WorkerEXIT_SUCCESS = 0 73*8975f5c5SAndroid Build Coastguard WorkerEXIT_FAILURE = 1 74*8975f5c5SAndroid Build Coastguard WorkerREPLAY_INITIALIZATION_FAILURE = -1 75*8975f5c5SAndroid Build Coastguard WorkerREPLAY_SERIALIZATION_FAILURE = -2 76*8975f5c5SAndroid Build Coastguard Worker 77*8975f5c5SAndroid Build Coastguard Workerswitch_case_without_return_template = """\ 78*8975f5c5SAndroid Build Coastguard Worker case {case}: 79*8975f5c5SAndroid Build Coastguard Worker {namespace}::{call}({params}); 80*8975f5c5SAndroid Build Coastguard Worker break; 81*8975f5c5SAndroid Build Coastguard Worker""" 82*8975f5c5SAndroid Build Coastguard Worker 83*8975f5c5SAndroid Build Coastguard Workerswitch_case_with_return_template = """\ 84*8975f5c5SAndroid Build Coastguard Worker case {case}: 85*8975f5c5SAndroid Build Coastguard Worker return {namespace}::{call}({params}); 86*8975f5c5SAndroid Build Coastguard Worker""" 87*8975f5c5SAndroid Build Coastguard Worker 88*8975f5c5SAndroid Build Coastguard Workerdefault_case_without_return_template = """\ 89*8975f5c5SAndroid Build Coastguard Worker default: 90*8975f5c5SAndroid Build Coastguard Worker break;""" 91*8975f5c5SAndroid Build Coastguard Workerdefault_case_with_return_template = """\ 92*8975f5c5SAndroid Build Coastguard Worker default: 93*8975f5c5SAndroid Build Coastguard Worker return {default_val};""" 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker 96*8975f5c5SAndroid Build Coastguard Workerdef winext(name, ext): 97*8975f5c5SAndroid Build Coastguard Worker return ("%s.%s" % (name, ext)) if sys.platform == "win32" else name 98*8975f5c5SAndroid Build Coastguard Worker 99*8975f5c5SAndroid Build Coastguard Worker 100*8975f5c5SAndroid Build Coastguard WorkerGN_PATH = os.path.join('third_party', 'depot_tools', winext('gn', 'bat')) 101*8975f5c5SAndroid Build Coastguard WorkerAUTONINJA_PATH = os.path.join('third_party', 'depot_tools', 'autoninja.py') 102*8975f5c5SAndroid Build Coastguard Worker 103*8975f5c5SAndroid Build Coastguard Worker 104*8975f5c5SAndroid Build Coastguard Workerdef GetGnArgsStr(args, extra_gn_args=[]): 105*8975f5c5SAndroid Build Coastguard Worker gn_args = [('angle_with_capture_by_default', 'true'), 106*8975f5c5SAndroid Build Coastguard Worker ('angle_enable_vulkan_api_dump_layer', 'false'), 107*8975f5c5SAndroid Build Coastguard Worker ('angle_enable_wgpu', 'false')] + extra_gn_args 108*8975f5c5SAndroid Build Coastguard Worker if args.use_reclient: 109*8975f5c5SAndroid Build Coastguard Worker gn_args.append(('use_remoteexec', 'true')) 110*8975f5c5SAndroid Build Coastguard Worker if not args.debug: 111*8975f5c5SAndroid Build Coastguard Worker gn_args.append(('is_debug', 'false')) 112*8975f5c5SAndroid Build Coastguard Worker gn_args.append(('symbol_level', '1')) 113*8975f5c5SAndroid Build Coastguard Worker gn_args.append(('angle_assert_always_on', 'true')) 114*8975f5c5SAndroid Build Coastguard Worker if args.asan: 115*8975f5c5SAndroid Build Coastguard Worker gn_args.append(('is_asan', 'true')) 116*8975f5c5SAndroid Build Coastguard Worker return ' '.join(['%s=%s' % (k, v) for (k, v) in gn_args]) 117*8975f5c5SAndroid Build Coastguard Worker 118*8975f5c5SAndroid Build Coastguard Worker 119*8975f5c5SAndroid Build Coastguard Workerclass XvfbPool(object): 120*8975f5c5SAndroid Build Coastguard Worker 121*8975f5c5SAndroid Build Coastguard Worker def __init__(self, worker_count): 122*8975f5c5SAndroid Build Coastguard Worker self.queue = queue.Queue() 123*8975f5c5SAndroid Build Coastguard Worker 124*8975f5c5SAndroid Build Coastguard Worker self.processes = [] 125*8975f5c5SAndroid Build Coastguard Worker displays = set() 126*8975f5c5SAndroid Build Coastguard Worker tmp = tempfile.TemporaryDirectory() 127*8975f5c5SAndroid Build Coastguard Worker 128*8975f5c5SAndroid Build Coastguard Worker logging.info('Starting xvfb and openbox...') 129*8975f5c5SAndroid Build Coastguard Worker # Based on the simplest case from testing/xvfb.py, with tweaks to minimize races. 130*8975f5c5SAndroid Build Coastguard Worker try: 131*8975f5c5SAndroid Build Coastguard Worker for worker in range(worker_count): 132*8975f5c5SAndroid Build Coastguard Worker while True: 133*8975f5c5SAndroid Build Coastguard Worker # Pick a set of random displays from a custom range to hopefully avoid 134*8975f5c5SAndroid Build Coastguard Worker # collisions with anything else that might be using xvfb. 135*8975f5c5SAndroid Build Coastguard Worker # Another option would be -displayfd but that has its quirks too. 136*8975f5c5SAndroid Build Coastguard Worker display = random.randint(7700000, 7800000) 137*8975f5c5SAndroid Build Coastguard Worker if display in displays: 138*8975f5c5SAndroid Build Coastguard Worker continue 139*8975f5c5SAndroid Build Coastguard Worker 140*8975f5c5SAndroid Build Coastguard Worker x11_display_file = '/tmp/.X11-unix/X%d' % display 141*8975f5c5SAndroid Build Coastguard Worker 142*8975f5c5SAndroid Build Coastguard Worker if not os.path.exists(x11_display_file): 143*8975f5c5SAndroid Build Coastguard Worker break 144*8975f5c5SAndroid Build Coastguard Worker 145*8975f5c5SAndroid Build Coastguard Worker displays.add(display) 146*8975f5c5SAndroid Build Coastguard Worker 147*8975f5c5SAndroid Build Coastguard Worker x11_proc = subprocess.Popen([ 148*8975f5c5SAndroid Build Coastguard Worker 'Xvfb', 149*8975f5c5SAndroid Build Coastguard Worker ':%d' % display, '-screen', '0', '1280x1024x24', '-ac', '-nolisten', 'tcp', 150*8975f5c5SAndroid Build Coastguard Worker '-dpi', '96', '+extension', 'RANDR', '-maxclients', '512' 151*8975f5c5SAndroid Build Coastguard Worker ], 152*8975f5c5SAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 153*8975f5c5SAndroid Build Coastguard Worker self.processes.append(x11_proc) 154*8975f5c5SAndroid Build Coastguard Worker 155*8975f5c5SAndroid Build Coastguard Worker start_time = time.time() 156*8975f5c5SAndroid Build Coastguard Worker while not os.path.exists(x11_display_file): 157*8975f5c5SAndroid Build Coastguard Worker if time.time() - start_time >= 30: 158*8975f5c5SAndroid Build Coastguard Worker raise Exception('X11 failed to start') 159*8975f5c5SAndroid Build Coastguard Worker time.sleep(0.1) 160*8975f5c5SAndroid Build Coastguard Worker 161*8975f5c5SAndroid Build Coastguard Worker env = os.environ.copy() 162*8975f5c5SAndroid Build Coastguard Worker env['DISPLAY'] = ':%d' % display 163*8975f5c5SAndroid Build Coastguard Worker 164*8975f5c5SAndroid Build Coastguard Worker # testing/xvfb.py uses signals instead, which is tricky with multiple displays. 165*8975f5c5SAndroid Build Coastguard Worker openbox_ready_file = os.path.join(tmp.name, str(display)) 166*8975f5c5SAndroid Build Coastguard Worker openbox_proc = subprocess.Popen( 167*8975f5c5SAndroid Build Coastguard Worker ['openbox', '--sm-disable', '--startup', 168*8975f5c5SAndroid Build Coastguard Worker 'touch %s' % openbox_ready_file], 169*8975f5c5SAndroid Build Coastguard Worker stderr=subprocess.STDOUT, 170*8975f5c5SAndroid Build Coastguard Worker env=env) 171*8975f5c5SAndroid Build Coastguard Worker self.processes.append(openbox_proc) 172*8975f5c5SAndroid Build Coastguard Worker 173*8975f5c5SAndroid Build Coastguard Worker start_time = time.time() 174*8975f5c5SAndroid Build Coastguard Worker while not os.path.exists(openbox_ready_file): 175*8975f5c5SAndroid Build Coastguard Worker if time.time() - start_time >= 30: 176*8975f5c5SAndroid Build Coastguard Worker raise Exception('Openbox failed to start') 177*8975f5c5SAndroid Build Coastguard Worker time.sleep(0.1) 178*8975f5c5SAndroid Build Coastguard Worker 179*8975f5c5SAndroid Build Coastguard Worker self.queue.put(display) 180*8975f5c5SAndroid Build Coastguard Worker 181*8975f5c5SAndroid Build Coastguard Worker logging.info('Started a pool of %d xvfb displays: %s', worker_count, 182*8975f5c5SAndroid Build Coastguard Worker ' '.join(str(d) for d in sorted(displays))) 183*8975f5c5SAndroid Build Coastguard Worker except Exception: 184*8975f5c5SAndroid Build Coastguard Worker self.Teardown() 185*8975f5c5SAndroid Build Coastguard Worker raise 186*8975f5c5SAndroid Build Coastguard Worker finally: 187*8975f5c5SAndroid Build Coastguard Worker tmp.cleanup() 188*8975f5c5SAndroid Build Coastguard Worker 189*8975f5c5SAndroid Build Coastguard Worker def GrabDisplay(self): 190*8975f5c5SAndroid Build Coastguard Worker return self.queue.get() 191*8975f5c5SAndroid Build Coastguard Worker 192*8975f5c5SAndroid Build Coastguard Worker def ReleaseDisplay(self, display): 193*8975f5c5SAndroid Build Coastguard Worker self.queue.put(display) 194*8975f5c5SAndroid Build Coastguard Worker 195*8975f5c5SAndroid Build Coastguard Worker def Teardown(self): 196*8975f5c5SAndroid Build Coastguard Worker logging.info('Stopping xvfb pool') 197*8975f5c5SAndroid Build Coastguard Worker for p in reversed(self.processes): 198*8975f5c5SAndroid Build Coastguard Worker p.kill() 199*8975f5c5SAndroid Build Coastguard Worker p.wait() 200*8975f5c5SAndroid Build Coastguard Worker self.processes = [] 201*8975f5c5SAndroid Build Coastguard Worker 202*8975f5c5SAndroid Build Coastguard Worker 203*8975f5c5SAndroid Build Coastguard Worker@contextlib.contextmanager 204*8975f5c5SAndroid Build Coastguard Workerdef MaybeXvfbPool(xvfb, worker_count): 205*8975f5c5SAndroid Build Coastguard Worker if xvfb: 206*8975f5c5SAndroid Build Coastguard Worker try: 207*8975f5c5SAndroid Build Coastguard Worker xvfb_pool = XvfbPool(worker_count) 208*8975f5c5SAndroid Build Coastguard Worker yield xvfb_pool 209*8975f5c5SAndroid Build Coastguard Worker finally: 210*8975f5c5SAndroid Build Coastguard Worker xvfb_pool.Teardown() 211*8975f5c5SAndroid Build Coastguard Worker else: 212*8975f5c5SAndroid Build Coastguard Worker yield None 213*8975f5c5SAndroid Build Coastguard Worker 214*8975f5c5SAndroid Build Coastguard Worker 215*8975f5c5SAndroid Build Coastguard Worker@contextlib.contextmanager 216*8975f5c5SAndroid Build Coastguard Workerdef GetDisplayEnv(env, xvfb_pool): 217*8975f5c5SAndroid Build Coastguard Worker if not xvfb_pool: 218*8975f5c5SAndroid Build Coastguard Worker yield env 219*8975f5c5SAndroid Build Coastguard Worker return 220*8975f5c5SAndroid Build Coastguard Worker 221*8975f5c5SAndroid Build Coastguard Worker display = xvfb_pool.GrabDisplay() 222*8975f5c5SAndroid Build Coastguard Worker display_var = ':%d' % display 223*8975f5c5SAndroid Build Coastguard Worker try: 224*8975f5c5SAndroid Build Coastguard Worker yield {**env, 'DISPLAY': display_var, 'XVFB_DISPLAY': display_var} 225*8975f5c5SAndroid Build Coastguard Worker finally: 226*8975f5c5SAndroid Build Coastguard Worker xvfb_pool.ReleaseDisplay(display) 227*8975f5c5SAndroid Build Coastguard Worker 228*8975f5c5SAndroid Build Coastguard Worker 229*8975f5c5SAndroid Build Coastguard Workerdef TestLabel(test_name): 230*8975f5c5SAndroid Build Coastguard Worker return test_name.replace(".", "_").replace("/", "_") 231*8975f5c5SAndroid Build Coastguard Worker 232*8975f5c5SAndroid Build Coastguard Worker 233*8975f5c5SAndroid Build Coastguard Workerdef ParseTestNamesFromTestList(output, test_expectation, also_run_skipped_for_capture_tests): 234*8975f5c5SAndroid Build Coastguard Worker output_lines = output.splitlines() 235*8975f5c5SAndroid Build Coastguard Worker tests = [] 236*8975f5c5SAndroid Build Coastguard Worker seen_start_of_tests = False 237*8975f5c5SAndroid Build Coastguard Worker disabled = 0 238*8975f5c5SAndroid Build Coastguard Worker for line in output_lines: 239*8975f5c5SAndroid Build Coastguard Worker l = line.strip() 240*8975f5c5SAndroid Build Coastguard Worker if l == 'Tests list:': 241*8975f5c5SAndroid Build Coastguard Worker seen_start_of_tests = True 242*8975f5c5SAndroid Build Coastguard Worker elif l == 'End tests list.': 243*8975f5c5SAndroid Build Coastguard Worker break 244*8975f5c5SAndroid Build Coastguard Worker elif not seen_start_of_tests: 245*8975f5c5SAndroid Build Coastguard Worker pass 246*8975f5c5SAndroid Build Coastguard Worker elif not test_expectation.TestIsSkippedForCapture(l) or also_run_skipped_for_capture_tests: 247*8975f5c5SAndroid Build Coastguard Worker tests.append(l) 248*8975f5c5SAndroid Build Coastguard Worker else: 249*8975f5c5SAndroid Build Coastguard Worker disabled += 1 250*8975f5c5SAndroid Build Coastguard Worker 251*8975f5c5SAndroid Build Coastguard Worker logging.info('Found %s tests and %d disabled tests.' % (len(tests), disabled)) 252*8975f5c5SAndroid Build Coastguard Worker return tests 253*8975f5c5SAndroid Build Coastguard Worker 254*8975f5c5SAndroid Build Coastguard Worker 255*8975f5c5SAndroid Build Coastguard Workerclass GroupedResult(): 256*8975f5c5SAndroid Build Coastguard Worker Passed = "Pass" 257*8975f5c5SAndroid Build Coastguard Worker Failed = "Fail" 258*8975f5c5SAndroid Build Coastguard Worker TimedOut = "Timeout" 259*8975f5c5SAndroid Build Coastguard Worker CompileFailed = "CompileFailed" 260*8975f5c5SAndroid Build Coastguard Worker CaptureFailed = "CaptureFailed" 261*8975f5c5SAndroid Build Coastguard Worker ReplayFailed = "ReplayFailed" 262*8975f5c5SAndroid Build Coastguard Worker Skipped = "Skipped" 263*8975f5c5SAndroid Build Coastguard Worker FailedToTrace = "FailedToTrace" 264*8975f5c5SAndroid Build Coastguard Worker 265*8975f5c5SAndroid Build Coastguard Worker ResultTypes = [ 266*8975f5c5SAndroid Build Coastguard Worker Passed, Failed, TimedOut, CompileFailed, CaptureFailed, ReplayFailed, Skipped, 267*8975f5c5SAndroid Build Coastguard Worker FailedToTrace 268*8975f5c5SAndroid Build Coastguard Worker ] 269*8975f5c5SAndroid Build Coastguard Worker 270*8975f5c5SAndroid Build Coastguard Worker def __init__(self, resultcode, message, output, tests): 271*8975f5c5SAndroid Build Coastguard Worker self.resultcode = resultcode 272*8975f5c5SAndroid Build Coastguard Worker self.message = message 273*8975f5c5SAndroid Build Coastguard Worker self.output = output 274*8975f5c5SAndroid Build Coastguard Worker self.tests = [] 275*8975f5c5SAndroid Build Coastguard Worker for test in tests: 276*8975f5c5SAndroid Build Coastguard Worker self.tests.append(test) 277*8975f5c5SAndroid Build Coastguard Worker 278*8975f5c5SAndroid Build Coastguard Worker 279*8975f5c5SAndroid Build Coastguard Workerdef CaptureProducedRequiredFiles(all_trace_files, test_name): 280*8975f5c5SAndroid Build Coastguard Worker label = TestLabel(test_name) 281*8975f5c5SAndroid Build Coastguard Worker 282*8975f5c5SAndroid Build Coastguard Worker test_files = [f for f in all_trace_files if f.startswith(label)] 283*8975f5c5SAndroid Build Coastguard Worker 284*8975f5c5SAndroid Build Coastguard Worker frame_files_count = 0 285*8975f5c5SAndroid Build Coastguard Worker context_header_count = 0 286*8975f5c5SAndroid Build Coastguard Worker context_source_count = 0 287*8975f5c5SAndroid Build Coastguard Worker source_json_count = 0 288*8975f5c5SAndroid Build Coastguard Worker context_id = 0 289*8975f5c5SAndroid Build Coastguard Worker for f in test_files: 290*8975f5c5SAndroid Build Coastguard Worker # TODO: Consolidate. http://anglebug.com/42266223 291*8975f5c5SAndroid Build Coastguard Worker if "_001.cpp" in f or "_001.c" in f: 292*8975f5c5SAndroid Build Coastguard Worker frame_files_count += 1 293*8975f5c5SAndroid Build Coastguard Worker elif f.endswith(".json"): 294*8975f5c5SAndroid Build Coastguard Worker source_json_count += 1 295*8975f5c5SAndroid Build Coastguard Worker elif f.endswith(".h"): 296*8975f5c5SAndroid Build Coastguard Worker context_header_count += 1 297*8975f5c5SAndroid Build Coastguard Worker if TRACE_FILE_SUFFIX in f: 298*8975f5c5SAndroid Build Coastguard Worker context = f.split(TRACE_FILE_SUFFIX)[1][:-2] 299*8975f5c5SAndroid Build Coastguard Worker context_id = int(context) 300*8975f5c5SAndroid Build Coastguard Worker # TODO: Consolidate. http://anglebug.com/42266223 301*8975f5c5SAndroid Build Coastguard Worker elif f.endswith(".cpp") or f.endswith(".c"): 302*8975f5c5SAndroid Build Coastguard Worker context_source_count += 1 303*8975f5c5SAndroid Build Coastguard Worker got_all_files = ( 304*8975f5c5SAndroid Build Coastguard Worker frame_files_count >= 1 and context_header_count >= 1 and context_source_count >= 1 and 305*8975f5c5SAndroid Build Coastguard Worker source_json_count == 1) 306*8975f5c5SAndroid Build Coastguard Worker return got_all_files 307*8975f5c5SAndroid Build Coastguard Worker 308*8975f5c5SAndroid Build Coastguard Worker 309*8975f5c5SAndroid Build Coastguard Workerdef GetCaptureEnv(args, trace_folder_path): 310*8975f5c5SAndroid Build Coastguard Worker env = { 311*8975f5c5SAndroid Build Coastguard Worker 'ANGLE_CAPTURE_SERIALIZE_STATE': '1', 312*8975f5c5SAndroid Build Coastguard Worker 'ANGLE_FEATURE_OVERRIDES_ENABLED': 'forceRobustResourceInit:forceInitShaderVariables', 313*8975f5c5SAndroid Build Coastguard Worker 'ANGLE_FEATURE_OVERRIDES_DISABLED': 'supportsHostImageCopy', 314*8975f5c5SAndroid Build Coastguard Worker 'ANGLE_CAPTURE_ENABLED': '1', 315*8975f5c5SAndroid Build Coastguard Worker 'ANGLE_CAPTURE_OUT_DIR': trace_folder_path, 316*8975f5c5SAndroid Build Coastguard Worker } 317*8975f5c5SAndroid Build Coastguard Worker 318*8975f5c5SAndroid Build Coastguard Worker if args.mec > 0: 319*8975f5c5SAndroid Build Coastguard Worker env['ANGLE_CAPTURE_FRAME_START'] = '{}'.format(args.mec) 320*8975f5c5SAndroid Build Coastguard Worker env['ANGLE_CAPTURE_FRAME_END'] = '{}'.format(args.mec + 1) 321*8975f5c5SAndroid Build Coastguard Worker else: 322*8975f5c5SAndroid Build Coastguard Worker env['ANGLE_CAPTURE_FRAME_END'] = '{}'.format(CAPTURE_FRAME_END) 323*8975f5c5SAndroid Build Coastguard Worker 324*8975f5c5SAndroid Build Coastguard Worker if args.expose_nonconformant_features: 325*8975f5c5SAndroid Build Coastguard Worker env['ANGLE_FEATURE_OVERRIDES_ENABLED'] += ':exposeNonConformantExtensionsAndVersions' 326*8975f5c5SAndroid Build Coastguard Worker 327*8975f5c5SAndroid Build Coastguard Worker return env 328*8975f5c5SAndroid Build Coastguard Worker 329*8975f5c5SAndroid Build Coastguard Worker 330*8975f5c5SAndroid Build Coastguard Workerdef PrintContextDiff(replay_build_dir, test_name): 331*8975f5c5SAndroid Build Coastguard Worker frame = 1 332*8975f5c5SAndroid Build Coastguard Worker found = False 333*8975f5c5SAndroid Build Coastguard Worker while True: 334*8975f5c5SAndroid Build Coastguard Worker capture_file = "{}/{}_ContextCaptured{}.json".format(replay_build_dir, test_name, frame) 335*8975f5c5SAndroid Build Coastguard Worker replay_file = "{}/{}_ContextReplayed{}.json".format(replay_build_dir, test_name, frame) 336*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(capture_file) and os.path.exists(replay_file): 337*8975f5c5SAndroid Build Coastguard Worker found = True 338*8975f5c5SAndroid Build Coastguard Worker captured_context = open(capture_file, "r").readlines() 339*8975f5c5SAndroid Build Coastguard Worker replayed_context = open(replay_file, "r").readlines() 340*8975f5c5SAndroid Build Coastguard Worker for line in difflib.unified_diff( 341*8975f5c5SAndroid Build Coastguard Worker captured_context, replayed_context, fromfile=capture_file, tofile=replay_file): 342*8975f5c5SAndroid Build Coastguard Worker print(line, end="") 343*8975f5c5SAndroid Build Coastguard Worker else: 344*8975f5c5SAndroid Build Coastguard Worker if frame > CAPTURE_FRAME_END: 345*8975f5c5SAndroid Build Coastguard Worker break 346*8975f5c5SAndroid Build Coastguard Worker frame = frame + 1 347*8975f5c5SAndroid Build Coastguard Worker if not found: 348*8975f5c5SAndroid Build Coastguard Worker logging.error('Could not find serialization diff files for %s' % test_name) 349*8975f5c5SAndroid Build Coastguard Worker 350*8975f5c5SAndroid Build Coastguard Worker 351*8975f5c5SAndroid Build Coastguard Workerdef UnlinkContextStateJsonFilesIfPresent(replay_build_dir): 352*8975f5c5SAndroid Build Coastguard Worker for f in glob.glob(os.path.join(replay_build_dir, '*_ContextCaptured*.json')): 353*8975f5c5SAndroid Build Coastguard Worker os.unlink(f) 354*8975f5c5SAndroid Build Coastguard Worker for f in glob.glob(os.path.join(replay_build_dir, '*_ContextReplayed*.json')): 355*8975f5c5SAndroid Build Coastguard Worker os.unlink(f) 356*8975f5c5SAndroid Build Coastguard Worker 357*8975f5c5SAndroid Build Coastguard Worker 358*8975f5c5SAndroid Build Coastguard Workerclass TestExpectation(): 359*8975f5c5SAndroid Build Coastguard Worker # tests that must not be run as list 360*8975f5c5SAndroid Build Coastguard Worker skipped_for_capture_tests = {} 361*8975f5c5SAndroid Build Coastguard Worker skipped_for_capture_tests_re = {} 362*8975f5c5SAndroid Build Coastguard Worker 363*8975f5c5SAndroid Build Coastguard Worker # test expectations for tests that do not pass 364*8975f5c5SAndroid Build Coastguard Worker non_pass_results = {} 365*8975f5c5SAndroid Build Coastguard Worker 366*8975f5c5SAndroid Build Coastguard Worker # COMPILE_FAIL 367*8975f5c5SAndroid Build Coastguard Worker compile_fail_tests = {} 368*8975f5c5SAndroid Build Coastguard Worker compile_fail_tests_re = {} 369*8975f5c5SAndroid Build Coastguard Worker 370*8975f5c5SAndroid Build Coastguard Worker flaky_tests = [] 371*8975f5c5SAndroid Build Coastguard Worker 372*8975f5c5SAndroid Build Coastguard Worker non_pass_re = {} 373*8975f5c5SAndroid Build Coastguard Worker 374*8975f5c5SAndroid Build Coastguard Worker result_map = { 375*8975f5c5SAndroid Build Coastguard Worker "FAIL": GroupedResult.Failed, 376*8975f5c5SAndroid Build Coastguard Worker "TIMEOUT": GroupedResult.TimedOut, 377*8975f5c5SAndroid Build Coastguard Worker "COMPILE_FAIL": GroupedResult.CompileFailed, 378*8975f5c5SAndroid Build Coastguard Worker "NOT_RUN": GroupedResult.Skipped, 379*8975f5c5SAndroid Build Coastguard Worker "SKIP_FOR_CAPTURE": GroupedResult.Skipped, 380*8975f5c5SAndroid Build Coastguard Worker "PASS": GroupedResult.Passed, 381*8975f5c5SAndroid Build Coastguard Worker } 382*8975f5c5SAndroid Build Coastguard Worker 383*8975f5c5SAndroid Build Coastguard Worker def __init__(self, args): 384*8975f5c5SAndroid Build Coastguard Worker expected_results_filename = "capture_replay_expectations.txt" 385*8975f5c5SAndroid Build Coastguard Worker expected_results_path = os.path.join(REPLAY_SAMPLE_FOLDER, expected_results_filename) 386*8975f5c5SAndroid Build Coastguard Worker self._asan = args.asan 387*8975f5c5SAndroid Build Coastguard Worker with open(expected_results_path, "rt") as f: 388*8975f5c5SAndroid Build Coastguard Worker for line in f: 389*8975f5c5SAndroid Build Coastguard Worker l = line.strip() 390*8975f5c5SAndroid Build Coastguard Worker if l != "" and not l.startswith("#"): 391*8975f5c5SAndroid Build Coastguard Worker self.ReadOneExpectation(l, args.debug) 392*8975f5c5SAndroid Build Coastguard Worker 393*8975f5c5SAndroid Build Coastguard Worker def _CheckTagsWithConfig(self, tags, config_tags): 394*8975f5c5SAndroid Build Coastguard Worker for tag in tags: 395*8975f5c5SAndroid Build Coastguard Worker if tag not in config_tags: 396*8975f5c5SAndroid Build Coastguard Worker return False 397*8975f5c5SAndroid Build Coastguard Worker return True 398*8975f5c5SAndroid Build Coastguard Worker 399*8975f5c5SAndroid Build Coastguard Worker def ReadOneExpectation(self, line, is_debug): 400*8975f5c5SAndroid Build Coastguard Worker (testpattern, result) = line.split('=') 401*8975f5c5SAndroid Build Coastguard Worker (test_info_string, test_name_string) = testpattern.split(':') 402*8975f5c5SAndroid Build Coastguard Worker test_name = test_name_string.strip() 403*8975f5c5SAndroid Build Coastguard Worker test_info = test_info_string.strip().split() 404*8975f5c5SAndroid Build Coastguard Worker result_stripped = result.strip() 405*8975f5c5SAndroid Build Coastguard Worker 406*8975f5c5SAndroid Build Coastguard Worker tags = [] 407*8975f5c5SAndroid Build Coastguard Worker if len(test_info) > 1: 408*8975f5c5SAndroid Build Coastguard Worker tags = test_info[1:] 409*8975f5c5SAndroid Build Coastguard Worker 410*8975f5c5SAndroid Build Coastguard Worker config_tags = [GetPlatformForSkip()] 411*8975f5c5SAndroid Build Coastguard Worker if self._asan: 412*8975f5c5SAndroid Build Coastguard Worker config_tags += ['ASAN'] 413*8975f5c5SAndroid Build Coastguard Worker if is_debug: 414*8975f5c5SAndroid Build Coastguard Worker config_tags += ['DEBUG'] 415*8975f5c5SAndroid Build Coastguard Worker 416*8975f5c5SAndroid Build Coastguard Worker if self._CheckTagsWithConfig(tags, config_tags): 417*8975f5c5SAndroid Build Coastguard Worker test_name_regex = re.compile('^' + test_name.replace('*', '.*') + '$') 418*8975f5c5SAndroid Build Coastguard Worker if result_stripped == 'COMPILE_FAIL': 419*8975f5c5SAndroid Build Coastguard Worker self.compile_fail_tests[test_name] = self.result_map[result_stripped] 420*8975f5c5SAndroid Build Coastguard Worker self.compile_fail_tests_re[test_name] = test_name_regex 421*8975f5c5SAndroid Build Coastguard Worker if result_stripped == 'SKIP_FOR_CAPTURE' or result_stripped == 'TIMEOUT': 422*8975f5c5SAndroid Build Coastguard Worker self.skipped_for_capture_tests[test_name] = self.result_map[result_stripped] 423*8975f5c5SAndroid Build Coastguard Worker self.skipped_for_capture_tests_re[test_name] = test_name_regex 424*8975f5c5SAndroid Build Coastguard Worker elif result_stripped == 'FLAKY': 425*8975f5c5SAndroid Build Coastguard Worker self.flaky_tests.append(test_name_regex) 426*8975f5c5SAndroid Build Coastguard Worker else: 427*8975f5c5SAndroid Build Coastguard Worker self.non_pass_results[test_name] = self.result_map[result_stripped] 428*8975f5c5SAndroid Build Coastguard Worker self.non_pass_re[test_name] = test_name_regex 429*8975f5c5SAndroid Build Coastguard Worker 430*8975f5c5SAndroid Build Coastguard Worker def TestIsSkippedForCapture(self, test_name): 431*8975f5c5SAndroid Build Coastguard Worker return any(p.match(test_name) for p in self.skipped_for_capture_tests_re.values()) 432*8975f5c5SAndroid Build Coastguard Worker 433*8975f5c5SAndroid Build Coastguard Worker def TestIsCompileFail(self, test_name): 434*8975f5c5SAndroid Build Coastguard Worker return any(p.match(test_name) for p in self.compile_fail_tests_re.values()) 435*8975f5c5SAndroid Build Coastguard Worker 436*8975f5c5SAndroid Build Coastguard Worker def Filter(self, test_list, run_all_tests): 437*8975f5c5SAndroid Build Coastguard Worker result = {} 438*8975f5c5SAndroid Build Coastguard Worker for t in test_list: 439*8975f5c5SAndroid Build Coastguard Worker for key in self.non_pass_results.keys(): 440*8975f5c5SAndroid Build Coastguard Worker if self.non_pass_re[key].match(t) is not None: 441*8975f5c5SAndroid Build Coastguard Worker result[t] = self.non_pass_results[key] 442*8975f5c5SAndroid Build Coastguard Worker for key in self.compile_fail_tests.keys(): 443*8975f5c5SAndroid Build Coastguard Worker if self.compile_fail_tests_re[key].match(t) is not None: 444*8975f5c5SAndroid Build Coastguard Worker result[t] = self.compile_fail_tests[key] 445*8975f5c5SAndroid Build Coastguard Worker if run_all_tests: 446*8975f5c5SAndroid Build Coastguard Worker for [key, r] in self.skipped_for_capture_tests.items(): 447*8975f5c5SAndroid Build Coastguard Worker if self.skipped_for_capture_tests_re[key].match(t) is not None: 448*8975f5c5SAndroid Build Coastguard Worker result[t] = r 449*8975f5c5SAndroid Build Coastguard Worker return result 450*8975f5c5SAndroid Build Coastguard Worker 451*8975f5c5SAndroid Build Coastguard Worker def IsFlaky(self, test_name): 452*8975f5c5SAndroid Build Coastguard Worker for flaky in self.flaky_tests: 453*8975f5c5SAndroid Build Coastguard Worker if flaky.match(test_name) is not None: 454*8975f5c5SAndroid Build Coastguard Worker return True 455*8975f5c5SAndroid Build Coastguard Worker return False 456*8975f5c5SAndroid Build Coastguard Worker 457*8975f5c5SAndroid Build Coastguard Worker 458*8975f5c5SAndroid Build Coastguard Workerdef GetPlatformForSkip(): 459*8975f5c5SAndroid Build Coastguard Worker # yapf: disable 460*8975f5c5SAndroid Build Coastguard Worker # we want each pair on one line 461*8975f5c5SAndroid Build Coastguard Worker platform_map = { 'win32' : 'WIN', 462*8975f5c5SAndroid Build Coastguard Worker 'linux' : 'LINUX' } 463*8975f5c5SAndroid Build Coastguard Worker # yapf: enable 464*8975f5c5SAndroid Build Coastguard Worker return platform_map.get(sys.platform, 'UNKNOWN') 465*8975f5c5SAndroid Build Coastguard Worker 466*8975f5c5SAndroid Build Coastguard Worker 467*8975f5c5SAndroid Build Coastguard Workerdef RunInParallel(f, lst, max_workers, stop_event): 468*8975f5c5SAndroid Build Coastguard Worker with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: 469*8975f5c5SAndroid Build Coastguard Worker future_to_arg = {executor.submit(f, arg): arg for arg in lst} 470*8975f5c5SAndroid Build Coastguard Worker try: 471*8975f5c5SAndroid Build Coastguard Worker for future in concurrent.futures.as_completed(future_to_arg): 472*8975f5c5SAndroid Build Coastguard Worker yield future, future_to_arg[future] 473*8975f5c5SAndroid Build Coastguard Worker except KeyboardInterrupt: 474*8975f5c5SAndroid Build Coastguard Worker stop_event.set() 475*8975f5c5SAndroid Build Coastguard Worker raise 476*8975f5c5SAndroid Build Coastguard Worker 477*8975f5c5SAndroid Build Coastguard Worker 478*8975f5c5SAndroid Build Coastguard Workerdef RunProcess(cmd, env, xvfb_pool, stop_event, timeout): 479*8975f5c5SAndroid Build Coastguard Worker stdout = [None] 480*8975f5c5SAndroid Build Coastguard Worker 481*8975f5c5SAndroid Build Coastguard Worker def _Reader(process): 482*8975f5c5SAndroid Build Coastguard Worker stdout[0] = process.stdout.read().decode() 483*8975f5c5SAndroid Build Coastguard Worker 484*8975f5c5SAndroid Build Coastguard Worker with GetDisplayEnv(env, xvfb_pool) as run_env: 485*8975f5c5SAndroid Build Coastguard Worker process = subprocess.Popen( 486*8975f5c5SAndroid Build Coastguard Worker cmd, env=run_env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 487*8975f5c5SAndroid Build Coastguard Worker t = threading.Thread(target=_Reader, args=(process,)) 488*8975f5c5SAndroid Build Coastguard Worker t.start() 489*8975f5c5SAndroid Build Coastguard Worker time_start = time.time() 490*8975f5c5SAndroid Build Coastguard Worker 491*8975f5c5SAndroid Build Coastguard Worker while True: 492*8975f5c5SAndroid Build Coastguard Worker time.sleep(0.1) 493*8975f5c5SAndroid Build Coastguard Worker if process.poll() is not None: 494*8975f5c5SAndroid Build Coastguard Worker t.join() 495*8975f5c5SAndroid Build Coastguard Worker return process.returncode, stdout[0] 496*8975f5c5SAndroid Build Coastguard Worker if timeout is not None and time.time() - time_start > timeout: 497*8975f5c5SAndroid Build Coastguard Worker process.kill() 498*8975f5c5SAndroid Build Coastguard Worker t.join() 499*8975f5c5SAndroid Build Coastguard Worker return subprocess.TimeoutExpired, stdout[0] 500*8975f5c5SAndroid Build Coastguard Worker if stop_event.is_set(): 501*8975f5c5SAndroid Build Coastguard Worker process.kill() 502*8975f5c5SAndroid Build Coastguard Worker t.join() 503*8975f5c5SAndroid Build Coastguard Worker return None, stdout[0] 504*8975f5c5SAndroid Build Coastguard Worker 505*8975f5c5SAndroid Build Coastguard Worker 506*8975f5c5SAndroid Build Coastguard Workerdef ReturnCodeWithNote(rc): 507*8975f5c5SAndroid Build Coastguard Worker s = 'rc=%s' % rc 508*8975f5c5SAndroid Build Coastguard Worker if sys.platform.startswith('linux'): 509*8975f5c5SAndroid Build Coastguard Worker if rc == -9: 510*8975f5c5SAndroid Build Coastguard Worker # OOM killer sends SIGKILL to the process, return code is -signal 511*8975f5c5SAndroid Build Coastguard Worker s += ' SIGKILL possibly due to OOM' 512*8975f5c5SAndroid Build Coastguard Worker return s 513*8975f5c5SAndroid Build Coastguard Worker 514*8975f5c5SAndroid Build Coastguard Worker 515*8975f5c5SAndroid Build Coastguard Workerdef RunCaptureInParallel(args, trace_folder_path, test_names, worker_count, xvfb_pool): 516*8975f5c5SAndroid Build Coastguard Worker n = args.batch_count 517*8975f5c5SAndroid Build Coastguard Worker test_batches = [test_names[i:i + n] for i in range(0, len(test_names), n)] 518*8975f5c5SAndroid Build Coastguard Worker 519*8975f5c5SAndroid Build Coastguard Worker extra_env = GetCaptureEnv(args, trace_folder_path) 520*8975f5c5SAndroid Build Coastguard Worker env = {**os.environ.copy(), **extra_env} 521*8975f5c5SAndroid Build Coastguard Worker test_exe_path = os.path.join(args.out_dir, 'Capture', args.test_suite) 522*8975f5c5SAndroid Build Coastguard Worker 523*8975f5c5SAndroid Build Coastguard Worker stop_event = threading.Event() 524*8975f5c5SAndroid Build Coastguard Worker 525*8975f5c5SAndroid Build Coastguard Worker def _RunCapture(tests): 526*8975f5c5SAndroid Build Coastguard Worker filt = ':'.join(tests) 527*8975f5c5SAndroid Build Coastguard Worker 528*8975f5c5SAndroid Build Coastguard Worker results_file = tempfile.mktemp() 529*8975f5c5SAndroid Build Coastguard Worker cmd = [ 530*8975f5c5SAndroid Build Coastguard Worker test_exe_path, 531*8975f5c5SAndroid Build Coastguard Worker '--gtest_filter=%s' % filt, 532*8975f5c5SAndroid Build Coastguard Worker '--angle-per-test-capture-label', 533*8975f5c5SAndroid Build Coastguard Worker '--results-file=' + results_file, 534*8975f5c5SAndroid Build Coastguard Worker ] 535*8975f5c5SAndroid Build Coastguard Worker 536*8975f5c5SAndroid Build Coastguard Worker # Add --use-config to avoid registering all test configurations 537*8975f5c5SAndroid Build Coastguard Worker configs = set([t.split('/')[-1] for t in filt.split(':')]) 538*8975f5c5SAndroid Build Coastguard Worker if len(configs) == 1: 539*8975f5c5SAndroid Build Coastguard Worker config, = configs 540*8975f5c5SAndroid Build Coastguard Worker if '*' not in config: 541*8975f5c5SAndroid Build Coastguard Worker cmd.append('--use-config=%s' % config) 542*8975f5c5SAndroid Build Coastguard Worker 543*8975f5c5SAndroid Build Coastguard Worker test_results = None 544*8975f5c5SAndroid Build Coastguard Worker try: 545*8975f5c5SAndroid Build Coastguard Worker rc, stdout = RunProcess(cmd, env, xvfb_pool, stop_event, CAPTURE_SUBPROCESS_TIMEOUT) 546*8975f5c5SAndroid Build Coastguard Worker if rc == 0: 547*8975f5c5SAndroid Build Coastguard Worker with open(results_file) as f: 548*8975f5c5SAndroid Build Coastguard Worker test_results = json.load(f) 549*8975f5c5SAndroid Build Coastguard Worker finally: 550*8975f5c5SAndroid Build Coastguard Worker try: 551*8975f5c5SAndroid Build Coastguard Worker os.unlink(results_file) 552*8975f5c5SAndroid Build Coastguard Worker except Exception: 553*8975f5c5SAndroid Build Coastguard Worker pass 554*8975f5c5SAndroid Build Coastguard Worker 555*8975f5c5SAndroid Build Coastguard Worker return rc, test_results, stdout 556*8975f5c5SAndroid Build Coastguard Worker 557*8975f5c5SAndroid Build Coastguard Worker skipped_by_suite = set() 558*8975f5c5SAndroid Build Coastguard Worker capture_failed = False 559*8975f5c5SAndroid Build Coastguard Worker for (future, tests) in RunInParallel(_RunCapture, test_batches, worker_count, stop_event): 560*8975f5c5SAndroid Build Coastguard Worker rc, test_results, stdout = future.result() 561*8975f5c5SAndroid Build Coastguard Worker 562*8975f5c5SAndroid Build Coastguard Worker if rc == subprocess.TimeoutExpired: 563*8975f5c5SAndroid Build Coastguard Worker logging.error('Capture failed - timed out after %ss\nTests: %s\nPartial stdout:\n%s', 564*8975f5c5SAndroid Build Coastguard Worker CAPTURE_SUBPROCESS_TIMEOUT, ':'.join(tests), stdout) 565*8975f5c5SAndroid Build Coastguard Worker capture_failed = True 566*8975f5c5SAndroid Build Coastguard Worker continue 567*8975f5c5SAndroid Build Coastguard Worker 568*8975f5c5SAndroid Build Coastguard Worker if rc != 0: 569*8975f5c5SAndroid Build Coastguard Worker logging.error('Capture failed (%s)\nTests: %s\nStdout:\n%s\n', rc, 570*8975f5c5SAndroid Build Coastguard Worker ReturnCodeWithNote(rc), ':'.join(tests), stdout) 571*8975f5c5SAndroid Build Coastguard Worker capture_failed = True 572*8975f5c5SAndroid Build Coastguard Worker continue 573*8975f5c5SAndroid Build Coastguard Worker 574*8975f5c5SAndroid Build Coastguard Worker if args.show_capture_stdout: 575*8975f5c5SAndroid Build Coastguard Worker logging.info('Capture test stdout:\n%s\n', stdout) 576*8975f5c5SAndroid Build Coastguard Worker 577*8975f5c5SAndroid Build Coastguard Worker for test_name, res in test_results['tests'].items(): 578*8975f5c5SAndroid Build Coastguard Worker if res['actual'] == 'SKIP': 579*8975f5c5SAndroid Build Coastguard Worker skipped_by_suite.add(test_name) 580*8975f5c5SAndroid Build Coastguard Worker 581*8975f5c5SAndroid Build Coastguard Worker return not capture_failed, skipped_by_suite 582*8975f5c5SAndroid Build Coastguard Worker 583*8975f5c5SAndroid Build Coastguard Worker 584*8975f5c5SAndroid Build Coastguard Workerdef RunReplayTestsInParallel(args, replay_build_dir, replay_tests, expected_results, 585*8975f5c5SAndroid Build Coastguard Worker labels_to_tests, worker_count, xvfb_pool): 586*8975f5c5SAndroid Build Coastguard Worker extra_env = {} 587*8975f5c5SAndroid Build Coastguard Worker if args.expose_nonconformant_features: 588*8975f5c5SAndroid Build Coastguard Worker extra_env['ANGLE_FEATURE_OVERRIDES_ENABLED'] = 'exposeNonConformantExtensionsAndVersions' 589*8975f5c5SAndroid Build Coastguard Worker env = {**os.environ.copy(), **extra_env} 590*8975f5c5SAndroid Build Coastguard Worker 591*8975f5c5SAndroid Build Coastguard Worker stop_event = threading.Event() 592*8975f5c5SAndroid Build Coastguard Worker 593*8975f5c5SAndroid Build Coastguard Worker def _RunReplay(test): 594*8975f5c5SAndroid Build Coastguard Worker replay_exe_path = os.path.join(replay_build_dir, REPLAY_BINARY) 595*8975f5c5SAndroid Build Coastguard Worker cmd = [replay_exe_path, TestLabel(test)] 596*8975f5c5SAndroid Build Coastguard Worker return RunProcess(cmd, env, xvfb_pool, stop_event, REPLAY_SUBPROCESS_TIMEOUT) 597*8975f5c5SAndroid Build Coastguard Worker 598*8975f5c5SAndroid Build Coastguard Worker replay_failed = False 599*8975f5c5SAndroid Build Coastguard Worker for (future, test) in RunInParallel(_RunReplay, replay_tests, worker_count, stop_event): 600*8975f5c5SAndroid Build Coastguard Worker expected_to_pass = expected_results[test] == GroupedResult.Passed 601*8975f5c5SAndroid Build Coastguard Worker rc, stdout = future.result() 602*8975f5c5SAndroid Build Coastguard Worker if rc == subprocess.TimeoutExpired: 603*8975f5c5SAndroid Build Coastguard Worker if expected_to_pass: 604*8975f5c5SAndroid Build Coastguard Worker logging.error('Replay failed - timed out after %ss\nTest: %s\nPartial stdout:\n%s', 605*8975f5c5SAndroid Build Coastguard Worker REPLAY_SUBPROCESS_TIMEOUT, test, stdout) 606*8975f5c5SAndroid Build Coastguard Worker replay_failed = True 607*8975f5c5SAndroid Build Coastguard Worker else: 608*8975f5c5SAndroid Build Coastguard Worker logging.info('Ignoring replay timeout due to expectation: %s [expected %s]', test, 609*8975f5c5SAndroid Build Coastguard Worker expected_results[test]) 610*8975f5c5SAndroid Build Coastguard Worker continue 611*8975f5c5SAndroid Build Coastguard Worker 612*8975f5c5SAndroid Build Coastguard Worker if rc != 0: 613*8975f5c5SAndroid Build Coastguard Worker if expected_to_pass: 614*8975f5c5SAndroid Build Coastguard Worker logging.error('Replay failed (%s)\nTest: %s\nStdout:\n%s\n', 615*8975f5c5SAndroid Build Coastguard Worker ReturnCodeWithNote(rc), test, stdout) 616*8975f5c5SAndroid Build Coastguard Worker replay_failed = True 617*8975f5c5SAndroid Build Coastguard Worker else: 618*8975f5c5SAndroid Build Coastguard Worker logging.info('Ignoring replay failure due to expectation: %s [expected %s]', test, 619*8975f5c5SAndroid Build Coastguard Worker expected_results[test]) 620*8975f5c5SAndroid Build Coastguard Worker continue 621*8975f5c5SAndroid Build Coastguard Worker 622*8975f5c5SAndroid Build Coastguard Worker if args.show_replay_stdout: 623*8975f5c5SAndroid Build Coastguard Worker logging.info('Replay test stdout:\n%s\n', stdout) 624*8975f5c5SAndroid Build Coastguard Worker 625*8975f5c5SAndroid Build Coastguard Worker output_lines = stdout.splitlines() 626*8975f5c5SAndroid Build Coastguard Worker for output_line in output_lines: 627*8975f5c5SAndroid Build Coastguard Worker words = output_line.split(" ") 628*8975f5c5SAndroid Build Coastguard Worker if len(words) == 3 and words[0] == RESULT_TAG: 629*8975f5c5SAndroid Build Coastguard Worker test_name = labels_to_tests[words[1]] 630*8975f5c5SAndroid Build Coastguard Worker result = int(words[2]) 631*8975f5c5SAndroid Build Coastguard Worker 632*8975f5c5SAndroid Build Coastguard Worker if result == 0: 633*8975f5c5SAndroid Build Coastguard Worker pass 634*8975f5c5SAndroid Build Coastguard Worker elif result == REPLAY_INITIALIZATION_FAILURE: 635*8975f5c5SAndroid Build Coastguard Worker if expected_to_pass: 636*8975f5c5SAndroid Build Coastguard Worker replay_failed = True 637*8975f5c5SAndroid Build Coastguard Worker logging.error('Replay failed. Initialization failure: %s' % test_name) 638*8975f5c5SAndroid Build Coastguard Worker else: 639*8975f5c5SAndroid Build Coastguard Worker logging.info( 640*8975f5c5SAndroid Build Coastguard Worker 'Ignoring replay failure due to expectation: %s [expected %s]', test, 641*8975f5c5SAndroid Build Coastguard Worker expected_results[test]) 642*8975f5c5SAndroid Build Coastguard Worker elif result == REPLAY_SERIALIZATION_FAILURE: 643*8975f5c5SAndroid Build Coastguard Worker if expected_to_pass: 644*8975f5c5SAndroid Build Coastguard Worker replay_failed = True 645*8975f5c5SAndroid Build Coastguard Worker logging.error('Replay failed. Context comparison failed: %s' % test_name) 646*8975f5c5SAndroid Build Coastguard Worker PrintContextDiff(replay_build_dir, words[1]) 647*8975f5c5SAndroid Build Coastguard Worker else: 648*8975f5c5SAndroid Build Coastguard Worker logging.info( 649*8975f5c5SAndroid Build Coastguard Worker 'Ignoring replay context diff due to expectation: %s [expected %s]', 650*8975f5c5SAndroid Build Coastguard Worker test, expected_results[test]) 651*8975f5c5SAndroid Build Coastguard Worker else: 652*8975f5c5SAndroid Build Coastguard Worker replay_failed = True 653*8975f5c5SAndroid Build Coastguard Worker logging.error('Replay failed. Unknown result code: %s -> %d' % 654*8975f5c5SAndroid Build Coastguard Worker (test_name, result)) 655*8975f5c5SAndroid Build Coastguard Worker 656*8975f5c5SAndroid Build Coastguard Worker return not replay_failed 657*8975f5c5SAndroid Build Coastguard Worker 658*8975f5c5SAndroid Build Coastguard Worker 659*8975f5c5SAndroid Build Coastguard Workerdef CleanupAfterReplay(replay_build_dir, test_labels): 660*8975f5c5SAndroid Build Coastguard Worker # Remove files that have test labels in the file name, .e.g: 661*8975f5c5SAndroid Build Coastguard Worker # ClearTest_ClearIsClamped_ES2_Vulkan_SwiftShader.dll.pdb 662*8975f5c5SAndroid Build Coastguard Worker for build_file in os.listdir(replay_build_dir): 663*8975f5c5SAndroid Build Coastguard Worker if any(label in build_file for label in test_labels): 664*8975f5c5SAndroid Build Coastguard Worker os.unlink(os.path.join(replay_build_dir, build_file)) 665*8975f5c5SAndroid Build Coastguard Worker 666*8975f5c5SAndroid Build Coastguard Worker 667*8975f5c5SAndroid Build Coastguard Workerdef main(args): 668*8975f5c5SAndroid Build Coastguard Worker angle_test_util.SetupLogging(args.log.upper()) 669*8975f5c5SAndroid Build Coastguard Worker 670*8975f5c5SAndroid Build Coastguard Worker # Set cwd to ANGLE root 671*8975f5c5SAndroid Build Coastguard Worker os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) 672*8975f5c5SAndroid Build Coastguard Worker 673*8975f5c5SAndroid Build Coastguard Worker if getpass.getuser() == 'chrome-bot': 674*8975f5c5SAndroid Build Coastguard Worker # bots need different re-client auth settings than developers b/319246651 675*8975f5c5SAndroid Build Coastguard Worker os.environ["RBE_use_gce_credentials"] = "true" 676*8975f5c5SAndroid Build Coastguard Worker os.environ["RBE_use_application_default_credentials"] = "false" 677*8975f5c5SAndroid Build Coastguard Worker os.environ["RBE_automatic_auth"] = "false" 678*8975f5c5SAndroid Build Coastguard Worker os.environ["RBE_experimental_credentials_helper"] = "" 679*8975f5c5SAndroid Build Coastguard Worker os.environ["RBE_experimental_credentials_helper_args"] = "" 680*8975f5c5SAndroid Build Coastguard Worker 681*8975f5c5SAndroid Build Coastguard Worker trace_dir = "%s%d" % (TRACE_FOLDER, 0) 682*8975f5c5SAndroid Build Coastguard Worker trace_folder_path = os.path.join(REPLAY_SAMPLE_FOLDER, trace_dir) 683*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(trace_folder_path): 684*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(trace_folder_path) 685*8975f5c5SAndroid Build Coastguard Worker os.makedirs(trace_folder_path) 686*8975f5c5SAndroid Build Coastguard Worker 687*8975f5c5SAndroid Build Coastguard Worker capture_build_dir = os.path.join(args.out_dir, 'Capture') 688*8975f5c5SAndroid Build Coastguard Worker replay_build_dir = os.path.join(args.out_dir, 'Replay%d' % 0) 689*8975f5c5SAndroid Build Coastguard Worker 690*8975f5c5SAndroid Build Coastguard Worker logging.info('Building capture tests') 691*8975f5c5SAndroid Build Coastguard Worker 692*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call([GN_PATH, 'gen', '--args=%s' % GetGnArgsStr(args), capture_build_dir]) 693*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call( 694*8975f5c5SAndroid Build Coastguard Worker [sys.executable, AUTONINJA_PATH, '-C', capture_build_dir, args.test_suite]) 695*8975f5c5SAndroid Build Coastguard Worker 696*8975f5c5SAndroid Build Coastguard Worker with MaybeXvfbPool(args.xvfb, 1) as xvfb_pool: 697*8975f5c5SAndroid Build Coastguard Worker logging.info('Getting test list') 698*8975f5c5SAndroid Build Coastguard Worker test_path = os.path.join(capture_build_dir, args.test_suite) 699*8975f5c5SAndroid Build Coastguard Worker with GetDisplayEnv(os.environ, xvfb_pool) as env: 700*8975f5c5SAndroid Build Coastguard Worker test_list = subprocess.check_output( 701*8975f5c5SAndroid Build Coastguard Worker [test_path, "--list-tests", 702*8975f5c5SAndroid Build Coastguard Worker "--gtest_filter=%s" % args.filter], env=env, text=True) 703*8975f5c5SAndroid Build Coastguard Worker 704*8975f5c5SAndroid Build Coastguard Worker test_expectation = TestExpectation(args) 705*8975f5c5SAndroid Build Coastguard Worker test_names = ParseTestNamesFromTestList(test_list, test_expectation, 706*8975f5c5SAndroid Build Coastguard Worker args.also_run_skipped_for_capture_tests) 707*8975f5c5SAndroid Build Coastguard Worker test_expectation_for_list = test_expectation.Filter(test_names, 708*8975f5c5SAndroid Build Coastguard Worker args.also_run_skipped_for_capture_tests) 709*8975f5c5SAndroid Build Coastguard Worker 710*8975f5c5SAndroid Build Coastguard Worker test_names = [ 711*8975f5c5SAndroid Build Coastguard Worker t for t in test_names if (not test_expectation.TestIsCompileFail(t) and 712*8975f5c5SAndroid Build Coastguard Worker not test_expectation.TestIsSkippedForCapture(t)) 713*8975f5c5SAndroid Build Coastguard Worker ] 714*8975f5c5SAndroid Build Coastguard Worker 715*8975f5c5SAndroid Build Coastguard Worker if not test_names: 716*8975f5c5SAndroid Build Coastguard Worker logging.error('No capture tests to run. Is everything skipped?') 717*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 718*8975f5c5SAndroid Build Coastguard Worker 719*8975f5c5SAndroid Build Coastguard Worker worker_count = min(args.max_jobs, os.cpu_count(), 1 + len(test_names) // 10) 720*8975f5c5SAndroid Build Coastguard Worker 721*8975f5c5SAndroid Build Coastguard Worker logging.info('Running %d capture tests, worker_count=%d batch_count=%d', len(test_names), 722*8975f5c5SAndroid Build Coastguard Worker worker_count, args.batch_count) 723*8975f5c5SAndroid Build Coastguard Worker 724*8975f5c5SAndroid Build Coastguard Worker with MaybeXvfbPool(args.xvfb, worker_count) as xvfb_pool: 725*8975f5c5SAndroid Build Coastguard Worker success, skipped_by_suite = RunCaptureInParallel(args, trace_folder_path, test_names, 726*8975f5c5SAndroid Build Coastguard Worker worker_count, xvfb_pool) 727*8975f5c5SAndroid Build Coastguard Worker if not success: 728*8975f5c5SAndroid Build Coastguard Worker logging.error('Capture tests failed, see "Capture failed" errors above') 729*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 730*8975f5c5SAndroid Build Coastguard Worker 731*8975f5c5SAndroid Build Coastguard Worker logging.info('RunCaptureInParallel finished') 732*8975f5c5SAndroid Build Coastguard Worker 733*8975f5c5SAndroid Build Coastguard Worker labels_to_tests = {TestLabel(t): t for t in test_names} 734*8975f5c5SAndroid Build Coastguard Worker 735*8975f5c5SAndroid Build Coastguard Worker all_trace_files = [f.name for f in os.scandir(trace_folder_path) if f.is_file()] 736*8975f5c5SAndroid Build Coastguard Worker 737*8975f5c5SAndroid Build Coastguard Worker replay_tests = [] 738*8975f5c5SAndroid Build Coastguard Worker failed = False 739*8975f5c5SAndroid Build Coastguard Worker for test_name in test_names: 740*8975f5c5SAndroid Build Coastguard Worker if test_name not in skipped_by_suite: 741*8975f5c5SAndroid Build Coastguard Worker if CaptureProducedRequiredFiles(all_trace_files, test_name): 742*8975f5c5SAndroid Build Coastguard Worker replay_tests.append(test_name) 743*8975f5c5SAndroid Build Coastguard Worker else: 744*8975f5c5SAndroid Build Coastguard Worker logging.error('Capture failed: test missing replay files: %s', test_name) 745*8975f5c5SAndroid Build Coastguard Worker failed = True 746*8975f5c5SAndroid Build Coastguard Worker 747*8975f5c5SAndroid Build Coastguard Worker if failed: 748*8975f5c5SAndroid Build Coastguard Worker logging.error('Capture tests failed, see "Capture failed" errors above') 749*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 750*8975f5c5SAndroid Build Coastguard Worker 751*8975f5c5SAndroid Build Coastguard Worker logging.info('CaptureProducedRequiredFiles finished') 752*8975f5c5SAndroid Build Coastguard Worker 753*8975f5c5SAndroid Build Coastguard Worker composite_file_id = 1 754*8975f5c5SAndroid Build Coastguard Worker names_path = os.path.join(trace_folder_path, 'test_names_%d.json' % composite_file_id) 755*8975f5c5SAndroid Build Coastguard Worker with open(names_path, 'w') as f: 756*8975f5c5SAndroid Build Coastguard Worker f.write(json.dumps({'traces': [TestLabel(t) for t in replay_tests]})) 757*8975f5c5SAndroid Build Coastguard Worker 758*8975f5c5SAndroid Build Coastguard Worker replay_build_dir = os.path.join(args.out_dir, 'Replay%d' % 0) 759*8975f5c5SAndroid Build Coastguard Worker UnlinkContextStateJsonFilesIfPresent(replay_build_dir) 760*8975f5c5SAndroid Build Coastguard Worker 761*8975f5c5SAndroid Build Coastguard Worker logging.info('Building replay tests') 762*8975f5c5SAndroid Build Coastguard Worker 763*8975f5c5SAndroid Build Coastguard Worker extra_gn_args = [('angle_build_capture_replay_tests', 'true'), 764*8975f5c5SAndroid Build Coastguard Worker ('angle_capture_replay_test_trace_dir', '"%s"' % trace_dir), 765*8975f5c5SAndroid Build Coastguard Worker ('angle_capture_replay_composite_file_id', str(composite_file_id))] 766*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call( 767*8975f5c5SAndroid Build Coastguard Worker [GN_PATH, 'gen', 768*8975f5c5SAndroid Build Coastguard Worker '--args=%s' % GetGnArgsStr(args, extra_gn_args), replay_build_dir]) 769*8975f5c5SAndroid Build Coastguard Worker subprocess.check_call( 770*8975f5c5SAndroid Build Coastguard Worker [sys.executable, AUTONINJA_PATH, '-C', replay_build_dir, REPLAY_BINARY]) 771*8975f5c5SAndroid Build Coastguard Worker 772*8975f5c5SAndroid Build Coastguard Worker if not replay_tests: 773*8975f5c5SAndroid Build Coastguard Worker logging.error('No replay tests to run. Is everything skipped?') 774*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 775*8975f5c5SAndroid Build Coastguard Worker logging.info('Running %d replay tests', len(replay_tests)) 776*8975f5c5SAndroid Build Coastguard Worker 777*8975f5c5SAndroid Build Coastguard Worker expected_results = {} 778*8975f5c5SAndroid Build Coastguard Worker for test in replay_tests: 779*8975f5c5SAndroid Build Coastguard Worker expected_result = test_expectation_for_list.get(test, GroupedResult.Passed) 780*8975f5c5SAndroid Build Coastguard Worker if test_expectation.IsFlaky(test): 781*8975f5c5SAndroid Build Coastguard Worker expected_result = 'Flaky' 782*8975f5c5SAndroid Build Coastguard Worker expected_results[test] = expected_result 783*8975f5c5SAndroid Build Coastguard Worker 784*8975f5c5SAndroid Build Coastguard Worker if not RunReplayTestsInParallel(args, replay_build_dir, replay_tests, expected_results, 785*8975f5c5SAndroid Build Coastguard Worker labels_to_tests, worker_count, xvfb_pool): 786*8975f5c5SAndroid Build Coastguard Worker logging.error('Replay tests failed, see "Replay failed" errors above') 787*8975f5c5SAndroid Build Coastguard Worker return EXIT_FAILURE 788*8975f5c5SAndroid Build Coastguard Worker 789*8975f5c5SAndroid Build Coastguard Worker logging.info('Replay tests finished successfully') 790*8975f5c5SAndroid Build Coastguard Worker 791*8975f5c5SAndroid Build Coastguard Worker if not args.keep_temp_files: 792*8975f5c5SAndroid Build Coastguard Worker CleanupAfterReplay(replay_build_dir, list(labels_to_tests.keys())) 793*8975f5c5SAndroid Build Coastguard Worker shutil.rmtree(trace_folder_path) 794*8975f5c5SAndroid Build Coastguard Worker 795*8975f5c5SAndroid Build Coastguard Worker return EXIT_SUCCESS 796*8975f5c5SAndroid Build Coastguard Worker 797*8975f5c5SAndroid Build Coastguard Worker 798*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 799*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 800*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 801*8975f5c5SAndroid Build Coastguard Worker '--out-dir', 802*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_OUT_DIR, 803*8975f5c5SAndroid Build Coastguard Worker help='Where to build ANGLE for capture and replay. Relative to the ANGLE folder. Default is "%s".' 804*8975f5c5SAndroid Build Coastguard Worker % DEFAULT_OUT_DIR) 805*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 806*8975f5c5SAndroid Build Coastguard Worker '-f', 807*8975f5c5SAndroid Build Coastguard Worker '--filter', 808*8975f5c5SAndroid Build Coastguard Worker '--gtest_filter', 809*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_FILTER, 810*8975f5c5SAndroid Build Coastguard Worker help='Same as GoogleTest\'s filter argument. Default is "%s".' % DEFAULT_FILTER) 811*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 812*8975f5c5SAndroid Build Coastguard Worker '--test-suite', 813*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_TEST_SUITE, 814*8975f5c5SAndroid Build Coastguard Worker help='Test suite binary to execute. Default is "%s".' % DEFAULT_TEST_SUITE) 815*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 816*8975f5c5SAndroid Build Coastguard Worker '--batch-count', 817*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_BATCH_COUNT, 818*8975f5c5SAndroid Build Coastguard Worker type=int, 819*8975f5c5SAndroid Build Coastguard Worker help='Number of tests in a (capture) batch. Default is %d.' % DEFAULT_BATCH_COUNT) 820*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 821*8975f5c5SAndroid Build Coastguard Worker '--keep-temp-files', 822*8975f5c5SAndroid Build Coastguard Worker action='store_true', 823*8975f5c5SAndroid Build Coastguard Worker help='Whether to keep the temp files and folders. Off by default') 824*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 825*8975f5c5SAndroid Build Coastguard Worker '--use-reclient', 826*8975f5c5SAndroid Build Coastguard Worker default=False, 827*8975f5c5SAndroid Build Coastguard Worker action='store_true', 828*8975f5c5SAndroid Build Coastguard Worker help='Set use_remoteexec=true in args.gn.') 829*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 830*8975f5c5SAndroid Build Coastguard Worker '--result-file', 831*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_RESULT_FILE, 832*8975f5c5SAndroid Build Coastguard Worker help='Name of the result file in the capture_replay_tests folder. Default is "%s".' % 833*8975f5c5SAndroid Build Coastguard Worker DEFAULT_RESULT_FILE) 834*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('-v', '--verbose', action='store_true', help='Shows full test output.') 835*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 836*8975f5c5SAndroid Build Coastguard Worker '-l', 837*8975f5c5SAndroid Build Coastguard Worker '--log', 838*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_LOG_LEVEL, 839*8975f5c5SAndroid Build Coastguard Worker help='Controls the logging level. Default is "%s".' % DEFAULT_LOG_LEVEL) 840*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 841*8975f5c5SAndroid Build Coastguard Worker '-j', 842*8975f5c5SAndroid Build Coastguard Worker '--max-jobs', 843*8975f5c5SAndroid Build Coastguard Worker default=DEFAULT_MAX_JOBS, 844*8975f5c5SAndroid Build Coastguard Worker type=int, 845*8975f5c5SAndroid Build Coastguard Worker help='Maximum number of test processes. Default is %d.' % DEFAULT_MAX_JOBS) 846*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 847*8975f5c5SAndroid Build Coastguard Worker '-M', 848*8975f5c5SAndroid Build Coastguard Worker '--mec', 849*8975f5c5SAndroid Build Coastguard Worker default=0, 850*8975f5c5SAndroid Build Coastguard Worker type=int, 851*8975f5c5SAndroid Build Coastguard Worker help='Enable mid execution capture starting at specified frame, (default: 0 = normal capture)' 852*8975f5c5SAndroid Build Coastguard Worker ) 853*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 854*8975f5c5SAndroid Build Coastguard Worker '-a', 855*8975f5c5SAndroid Build Coastguard Worker '--also-run-skipped-for-capture-tests', 856*8975f5c5SAndroid Build Coastguard Worker action='store_true', 857*8975f5c5SAndroid Build Coastguard Worker help='Also run tests that are disabled in the expectations by SKIP_FOR_CAPTURE') 858*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--xvfb', action='store_true', help='Run with xvfb.') 859*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--asan', action='store_true', help='Build with ASAN.') 860*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 861*8975f5c5SAndroid Build Coastguard Worker '-E', 862*8975f5c5SAndroid Build Coastguard Worker '--expose-nonconformant-features', 863*8975f5c5SAndroid Build Coastguard Worker action='store_true', 864*8975f5c5SAndroid Build Coastguard Worker help='Expose non-conformant features to advertise GLES 3.2') 865*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 866*8975f5c5SAndroid Build Coastguard Worker '--show-capture-stdout', action='store_true', help='Print test stdout during capture.') 867*8975f5c5SAndroid Build Coastguard Worker parser.add_argument( 868*8975f5c5SAndroid Build Coastguard Worker '--show-replay-stdout', action='store_true', help='Print test stdout during replay.') 869*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--debug', action='store_true', help='Debug builds (default is Release).') 870*8975f5c5SAndroid Build Coastguard Worker args = parser.parse_args() 871*8975f5c5SAndroid Build Coastguard Worker if args.debug and (args.out_dir == DEFAULT_OUT_DIR): 872*8975f5c5SAndroid Build Coastguard Worker args.out_dir = args.out_dir + "Debug" 873*8975f5c5SAndroid Build Coastguard Worker 874*8975f5c5SAndroid Build Coastguard Worker if sys.platform == "win32": 875*8975f5c5SAndroid Build Coastguard Worker args.test_suite += ".exe" 876*8975f5c5SAndroid Build Coastguard Worker 877*8975f5c5SAndroid Build Coastguard Worker sys.exit(main(args)) 878