1*6777b538SAndroid Build Coastguard Worker# Copyright 2021 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker"""Utilities for invoking executables. 5*6777b538SAndroid Build Coastguard Worker""" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Workerimport os 8*6777b538SAndroid Build Coastguard Workerimport subprocess 9*6777b538SAndroid Build Coastguard Workerimport re 10*6777b538SAndroid Build Coastguard Workerimport sys 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker# Regex for matching 7-bit and 8-bit C1 ANSI sequences. 13*6777b538SAndroid Build Coastguard Worker# Credit: https://stackoverflow.com/a/14693789/4692014 14*6777b538SAndroid Build Coastguard Worker_ANSI_ESCAPE_8BIT_REGEX = re.compile( 15*6777b538SAndroid Build Coastguard Worker r""" 16*6777b538SAndroid Build Coastguard Worker (?: # either 7-bit C1, two bytes, ESC Fe (omitting CSI) 17*6777b538SAndroid Build Coastguard Worker \x1B 18*6777b538SAndroid Build Coastguard Worker [@-Z\\-_] 19*6777b538SAndroid Build Coastguard Worker | # or a single 8-bit byte Fe (omitting CSI) 20*6777b538SAndroid Build Coastguard Worker [\x80-\x9A\x9C-\x9F] 21*6777b538SAndroid Build Coastguard Worker | # or CSI + control codes 22*6777b538SAndroid Build Coastguard Worker (?: # 7-bit CSI, ESC [ 23*6777b538SAndroid Build Coastguard Worker \x1B\[ 24*6777b538SAndroid Build Coastguard Worker | # 8-bit CSI, 9B 25*6777b538SAndroid Build Coastguard Worker \x9B 26*6777b538SAndroid Build Coastguard Worker ) 27*6777b538SAndroid Build Coastguard Worker [0-?]* # Parameter bytes 28*6777b538SAndroid Build Coastguard Worker [ -/]* # Intermediate bytes 29*6777b538SAndroid Build Coastguard Worker [@-~] # Final byte 30*6777b538SAndroid Build Coastguard Worker ) 31*6777b538SAndroid Build Coastguard Worker""", re.VERBOSE) 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker 34*6777b538SAndroid Build Coastguard Workerdef run_and_tee_output(args): 35*6777b538SAndroid Build Coastguard Worker """Runs the test executable passing-thru its output to stdout (in a 36*6777b538SAndroid Build Coastguard Worker terminal-colors-friendly way). Waits for the executable to exit. 37*6777b538SAndroid Build Coastguard Worker 38*6777b538SAndroid Build Coastguard Worker Returns: 39*6777b538SAndroid Build Coastguard Worker The full executable output as an UTF-8 string. 40*6777b538SAndroid Build Coastguard Worker """ 41*6777b538SAndroid Build Coastguard Worker # Capture stdout (where test results are written), but inherit stderr. This 42*6777b538SAndroid Build Coastguard Worker # way errors related to invalid arguments are printed normally. 43*6777b538SAndroid Build Coastguard Worker proc = subprocess.Popen(args, stdout=subprocess.PIPE) 44*6777b538SAndroid Build Coastguard Worker captured_output = b'' 45*6777b538SAndroid Build Coastguard Worker while proc.poll() is None: 46*6777b538SAndroid Build Coastguard Worker buf = proc.stdout.read() 47*6777b538SAndroid Build Coastguard Worker # Write captured output directly, so escape sequences are preserved. 48*6777b538SAndroid Build Coastguard Worker sys.stdout.buffer.write(buf) 49*6777b538SAndroid Build Coastguard Worker captured_output += buf 50*6777b538SAndroid Build Coastguard Worker 51*6777b538SAndroid Build Coastguard Worker captured_output = _ANSI_ESCAPE_8BIT_REGEX.sub( 52*6777b538SAndroid Build Coastguard Worker '', captured_output.decode('utf-8')) 53*6777b538SAndroid Build Coastguard Worker 54*6777b538SAndroid Build Coastguard Worker return captured_output 55