diff --git a/ci/lint.sh b/ci/lint.sh index c1c4ce8e07816..05c6d94e87b79 100755 --- a/ci/lint.sh +++ b/ci/lint.sh @@ -75,6 +75,6 @@ pylint-2.7 --rcfile=.pylintrc \ "ci/" \ "impeller/" \ "tools/gn" \ - "testing/run_tests.py" + "testing/" echo "$(date +%T) Linting complete" diff --git a/testing/android_systrace_test.py b/testing/android_systrace_test.py index e6c039db5ac59..1de674b5d299c 100755 --- a/testing/android_systrace_test.py +++ b/testing/android_systrace_test.py @@ -15,7 +15,7 @@ PERFETTO_SESSION_KEY = 'session1' PERFETTO_TRACE_FILE = '/data/misc/perfetto-traces/trace' -PERFETTO_CONFIG = ''' +PERFETTO_CONFIG = """ write_into_file: true file_write_period_ms: 1000000000 flush_period_ms: 1000 @@ -32,10 +32,10 @@ } } } -''' +""" -def InstallApk(apk_path, package_name, adb_path='adb'): +def install_apk(apk_path, package_name, adb_path='adb'): print('Installing APK') subprocess.check_output([adb_path, 'shell', 'am', 'force-stop', package_name]) # Allowed to fail if APK was never installed. @@ -44,7 +44,7 @@ def InstallApk(apk_path, package_name, adb_path='adb'): subprocess.check_output([adb_path, 'install', apk_path]) -def StartPerfetto(package_name, adb_path='adb'): +def start_perfetto(package_name, adb_path='adb'): print('Starting trace') cmd = [ adb_path, 'shell', 'echo', "'" + PERFETTO_CONFIG % package_name + "'", @@ -55,7 +55,7 @@ def StartPerfetto(package_name, adb_path='adb'): subprocess.check_output(cmd, stderr=subprocess.STDOUT) -def LaunchPackage(package_name, activity_name, adb_path='adb'): +def launch_package(package_name, activity_name, adb_path='adb'): print('Scanning logcat') subprocess.check_output([adb_path, 'logcat', '-c'], stderr=subprocess.STDOUT) logcat = subprocess.Popen([adb_path, 'logcat'], @@ -77,7 +77,7 @@ def LaunchPackage(package_name, activity_name, adb_path='adb'): break -def CollectAndValidateTrace(adb_path='adb'): +def collect_and_validate_trace(adb_path='adb'): print('Fetching trace') subprocess.check_output([ adb_path, 'shell', 'perfetto', '--attach', PERFETTO_SESSION_KEY, '--stop' @@ -140,10 +140,10 @@ def main(): args = parser.parse_args() - InstallApk(args.apk_path, args.package_name, args.adb_path) - StartPerfetto(args.package_name, args.adb_path) - LaunchPackage(args.package_name, args.activity_name, args.adb_path) - return CollectAndValidateTrace(args.adb_path) + install_apk(args.apk_path, args.package_name, args.adb_path) + start_perfetto(args.package_name, args.adb_path) + launch_package(args.package_name, args.activity_name, args.adb_path) + return collect_and_validate_trace(args.adb_path) if __name__ == '__main__': diff --git a/testing/benchmark/displaylist_benchmark_parser.py b/testing/benchmark/displaylist_benchmark_parser.py index a8b49c6b95579..dac0f4485b4f8 100755 --- a/testing/benchmark/displaylist_benchmark_parser.py +++ b/testing/benchmark/displaylist_benchmark_parser.py @@ -8,52 +8,52 @@ import csv import json import sys -import matplotlib.pyplot as plt -from matplotlib.backends.backend_pdf import PdfPages as pdfp +import matplotlib.pyplot as plt # pylint: disable=import-error +from matplotlib.backends.backend_pdf import PdfPages as pdfp # pylint: disable=import-error -class BenchmarkResult: +class BenchmarkResult: # pylint: disable=too-many-instance-attributes - def __init__(self, name, backend, timeUnit, drawCallCount): + def __init__(self, name, backend, time_unit, draw_call_count): self.name = name self.series = {} - self.seriesLabels = {} + self.series_labels = {} self.backend = backend - self.largeYValues = False - self.yLimit = 200 - self.timeUnit = timeUnit - self.drawCallCount = drawCallCount - self.optionalValues = {} + self.large_y_values = False + self.y_limit = 200 + self.time_unit = time_unit + self.draw_call_count = draw_call_count + self.optional_values = {} def __repr__(self): return 'Name: % s\nBackend: % s\nSeries: % s\nSeriesLabels: % s\n' % ( - self.name, self.backend, self.series, self.seriesLabels + self.name, self.backend, self.series, self.series_labels ) - def addDataPoint(self, family, x, y): + def add_data_point(self, family, xval, yval): if family not in self.series: self.series[family] = {'x': [], 'y': []} - self.series[family]['x'].append(x) - self.series[family]['y'].append(y) + self.series[family]['x'].append(xval) + self.series[family]['y'].append(yval) - if y > self.yLimit: - self.largeYValues = True + if yval > self.y_limit: + self.large_y_values = True - def addOptionalValue(self, name, x, y): - if name not in self.optionalValues: - self.optionalValues[name] = {} + def add_optional_value(self, name, xval, yval): + if name not in self.optional_values: + self.optional_values[name] = {} - self.optionalValues[name][x] = y + self.optional_values[name][xval] = yval - def setFamilyLabel(self, family, label): + def set_family_label(self, family, label): # I'm not keying the main series dict off the family label # just in case we get data where the two aren't a 1:1 mapping - if family in self.seriesLabels: - assert self.seriesLabels[family] == label + if family in self.series_labels: + assert self.series_labels[family] == label return - self.seriesLabels[family] = label + self.series_labels[family] = label def plot(self): figures = [] @@ -63,22 +63,22 @@ def plot(self): plt.plot( self.series[family]['x'], self.series[family]['y'], - label=self.seriesLabels[family] + label=self.series_labels[family] ) plt.xlabel('Benchmark Seed') - plt.ylabel('Time (' + self.timeUnit + ')') + plt.ylabel('Time (' + self.time_unit + ')') title = '' # Crop the Y axis so that we can see what's going on at the lower end - if self.largeYValues: - plt.ylim((0, self.yLimit)) + if self.large_y_values: + plt.ylim((0, self.y_limit)) title = self.name + ' ' + self.backend + ' (Cropped)' else: title = self.name + ' ' + self.backend - if self.drawCallCount != -1: - title += '\nDraw Call Count: ' + str(int(self.drawCallCount)) + if self.draw_call_count != -1: + title += '\nDraw Call Count: ' + str(int(self.draw_call_count)) plt.title(title) @@ -87,22 +87,22 @@ def plot(self): plt.legend(fontsize='xx-small') plt.plot() - if self.largeYValues: + if self.large_y_values: # Plot again but with the full Y axis visible figures.append(plt.figure(dpi=1200, frameon=False, figsize=(11, 8.5))) for family in self.series: plt.plot( self.series[family]['x'], self.series[family]['y'], - label=self.seriesLabels[family] + label=self.series_labels[family] ) plt.xlabel('Benchmark Seed') - plt.ylabel('Time (' + self.timeUnit + ')') + plt.ylabel('Time (' + self.time_unit + ')') title = self.name + ' ' + self.backend + ' (Complete)' - if self.drawCallCount != -1: - title += '\nDraw Call Count: ' + str(int(self.drawCallCount)) + if self.draw_call_count != -1: + title += '\nDraw Call Count: ' + str(int(self.draw_call_count)) plt.title(title) @@ -113,25 +113,25 @@ def plot(self): return figures - def writeCSV(self, writer): + def write_csv(self, writer): # For now assume that all our series have the same x values # this is true for now, but may differ in the future with benchmark changes x_values = [] y_values = [] for family in self.series: x_values = ['x'] + self.series[family]['x'] - y_values.append([self.seriesLabels[family]] + self.series[family]['y']) + y_values.append([self.series_labels[family]] + self.series[family]['y']) - for name in self.optionalValues: + for name in self.optional_values: column = [name] - for key in self.optionalValues[name]: - column.append(self.optionalValues[name][key]) + for key in self.optional_values[name]: + column.append(self.optional_values[name][key]) y_values.append(column) - writer.writerow([self.name, self.drawCallCount]) - for line in range(len(x_values)): + writer.writerow([self.name, self.draw_call_count]) + for line, _ in enumerate(x_values): row = [x_values[line]] - for series in range(len(y_values)): + for series, _ in enumerate(y_values): row.append(y_values[series][line]) writer.writerow(row) @@ -147,7 +147,7 @@ def main(): parser.add_argument( '-o', '--output-pdf', - dest='outputPDF', + dest='output_pdf', action='store', default='output.pdf', help='Filename to output the PDF of graphs to.' @@ -155,23 +155,23 @@ def main(): parser.add_argument( '-c', '--output-csv', - dest='outputCSV', + dest='output_csv', action='store', default='output.csv', help='Filename to output the CSV data to.' ) args = parser.parse_args() - jsonData = parseJSON(args.filename) - return processBenchmarkData(jsonData, args.outputPDF, args.outputCSV) + json_data = parse_json(args.filename) + return process_benchmark_data(json_data, args.output_pdf, args.output_csv) def error(message): print(message) - exit(1) + sys.exit(1) -def extractAttributesLabel(benchmarkResult): +def extrac_attributes_label(benchmark_result): # Possible attribute keys are: # AntiAliasing # HairlineStroke @@ -182,7 +182,7 @@ def extractAttributesLabel(benchmarkResult): for attr in attributes: try: - if benchmarkResult[attr] != 0: + if benchmark_result[attr] != 0: label += attr + ', ' except KeyError: pass @@ -190,96 +190,97 @@ def extractAttributesLabel(benchmarkResult): return label[:-2] -def processBenchmarkData(benchmarkJSON, outputPDF, outputCSV): - benchmarkResultsData = {} +def process_benchmark_data(benchmark_json, output_pdf, output_csv): + benchmark_results_data = {} - for benchmarkResult in benchmarkJSON: + for benchmark_result in benchmark_json: # Skip aggregate results - if 'aggregate_name' in benchmarkResult: + if 'aggregate_name' in benchmark_result: continue - benchmarkVariant = benchmarkResult['name'].split('/') + benchmark_variant = benchmark_result['name'].split('/') # The final split is always `real_time` and can be discarded - benchmarkVariant.remove('real_time') + benchmark_variant.remove('real_time') - splits = len(benchmarkVariant) + splits = len(benchmark_variant) # First split is always the benchmark function name - benchmarkName = benchmarkVariant[0] + benchmark_name = benchmark_variant[0] # The last split is always the seeded value into the benchmark - benchmarkSeededValue = benchmarkVariant[splits - 1] + benchmark_seeded_value = benchmark_variant[splits - 1] # The second last split is always the backend - benchmarkBackend = benchmarkVariant[splits - 2] + benchmark_backend = benchmark_variant[splits - 2] # Time taken (wall clock time) for benchmark to run - benchmarkRealTime = benchmarkResult['real_time'] - benchmarkUnit = benchmarkResult['time_unit'] + benchmark_real_time = benchmark_result['real_time'] + benchmark_unit = benchmark_result['time_unit'] - benchmarkFamilyIndex = benchmarkResult['family_index'] + benchmark_family_index = benchmark_result['family_index'] - benchmarkFamilyLabel = '' + benchmark_family_label = '' if splits > 3: for i in range(1, splits - 2): - benchmarkFamilyLabel += benchmarkVariant[i] + ', ' + benchmark_family_label += benchmark_variant[i] + ', ' - benchmarkFamilyAttributes = extractAttributesLabel(benchmarkResult) + benchmark_family_attributes = extrac_attributes_label(benchmark_result) - if benchmarkFamilyAttributes == '': - benchmarkFamilyLabel = benchmarkFamilyLabel[:-2] + if benchmark_family_attributes == '': + benchmark_family_label = benchmark_family_label[:-2] else: - benchmarkFamilyLabel = benchmarkFamilyLabel + benchmarkFamilyAttributes + benchmark_family_label = benchmark_family_label + benchmark_family_attributes - if 'DrawCallCount' in benchmarkResult: - benchmarkDrawCallCount = benchmarkResult['DrawCallCount'] + if 'DrawCallCount' in benchmark_result: + benchmark_draw_call_count = benchmark_result['DrawCallCount'] else: - benchmarkDrawCallCount = -1 + benchmark_draw_call_count = -1 optional_keys = [ 'DrawCallCount_Varies', 'VerbCount', 'PointCount', 'VertexCount', 'GlyphCount' ] - if benchmarkName not in benchmarkResultsData: - benchmarkResultsData[benchmarkName] = BenchmarkResult( - benchmarkName, benchmarkBackend, benchmarkUnit, benchmarkDrawCallCount + if benchmark_name not in benchmark_results_data: + benchmark_results_data[benchmark_name] = BenchmarkResult( + benchmark_name, benchmark_backend, benchmark_unit, + benchmark_draw_call_count ) for key in optional_keys: - if key in benchmarkResult: - benchmarkResultsData[benchmarkName].addOptionalValue( - key, benchmarkSeededValue, benchmarkResult[key] + if key in benchmark_result: + benchmark_results_data[benchmark_name].add_optional_value( + key, benchmark_seeded_value, benchmark_result[key] ) - benchmarkResultsData[benchmarkName].addDataPoint( - benchmarkFamilyIndex, benchmarkSeededValue, benchmarkRealTime + benchmark_results_data[benchmark_name].add_data_point( + benchmark_family_index, benchmark_seeded_value, benchmark_real_time ) - benchmarkResultsData[benchmarkName].setFamilyLabel( - benchmarkFamilyIndex, benchmarkFamilyLabel + benchmark_results_data[benchmark_name].set_family_label( + benchmark_family_index, benchmark_family_label ) - pp = pdfp(outputPDF) + pdf = pdfp(output_pdf) - csv_file = open(outputCSV, 'w') + csv_file = open(output_csv, 'w') csv_writer = csv.writer(csv_file) - for benchmark in benchmarkResultsData: - figures = benchmarkResultsData[benchmark].plot() + for benchmark in benchmark_results_data: + figures = benchmark_results_data[benchmark].plot() for fig in figures: - pp.savefig(fig) - benchmarkResultsData[benchmark].writeCSV(csv_writer) - pp.close() + pdf.savefig(fig) + benchmark_results_data[benchmark].write_csv(csv_writer) + pdf.close() -def parseJSON(filename): +def parse_json(filename): try: - jsonFile = open(filename, 'r') - except: + json_file = open(filename, 'r') + except: # pylint: disable=bare-except error('Unable to load file.') try: - jsonData = json.load(jsonFile) - except JSONDecodeError: + json_data = json.load(json_file) + except JSONDecodeError: # pylint: disable=undefined-variable error('Invalid JSON. Unable to parse.') - return jsonData['benchmarks'] + return json_data['benchmarks'] if __name__ == '__main__': diff --git a/testing/run_tests.py b/testing/run_tests.py index b3213c8867cb1..9d4603df027cd 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -1089,7 +1089,7 @@ def main(): if 'impeller-vulkan' in types: build_name = args.variant try: - xvfb.StartVirtualX(build_name, build_dir) + xvfb.start_virtual_x(build_name, build_dir) vulkan_gtest_filter = parse_impeller_vulkan_filter() gtest_flags = shuffle_flags gtest_flags.append(vulkan_gtest_filter) @@ -1101,7 +1101,7 @@ def main(): coverage=args.coverage ) finally: - xvfb.StopVirtualX(build_name) + xvfb.stop_virtual_x(build_name) if 'dart' in types: dart_filter = args.dart_filter.split(',') if args.dart_filter else None diff --git a/testing/xvfb.py b/testing/xvfb.py index fe09429b552f8..079ddea878b4f 100644 --- a/testing/xvfb.py +++ b/testing/xvfb.py @@ -6,27 +6,26 @@ """ import os -import platform import signal import subprocess import tempfile import time -def _XvfbDisplayIndex(_child_build_name): +def xvfb_display_index(_child_build_name): return '9' -def _XvfbPidFilename(child_build_name): +def xvfb_pid_filename(child_build_name): """Returns the filename to the Xvfb pid file. This name is unique for each builder. This is used by the linux builders.""" return os.path.join( tempfile.gettempdir(), - 'xvfb-' + _XvfbDisplayIndex(child_build_name) + '.pid' + 'xvfb-' + xvfb_display_index(child_build_name) + '.pid' ) -def StartVirtualX(child_build_name, build_dir): +def start_virtual_x(child_build_name, build_dir): """Start a virtual X server and set the DISPLAY environment variable so sub processes will use the virtual X server. Also start openbox. This only works on Linux and assumes that xvfb and openbox are installed. @@ -40,13 +39,13 @@ def StartVirtualX(child_build_name, build_dir): """ # We use a pid file to make sure we don't have any xvfb processes running # from a previous test run. - StopVirtualX(child_build_name) + stop_virtual_x(child_build_name) xdisplaycheck_path = None if build_dir: xdisplaycheck_path = os.path.join(build_dir, 'xdisplaycheck') - display = ':%s' % _XvfbDisplayIndex(child_build_name) + display = ':%s' % xvfb_display_index(child_build_name) # Note we don't add the optional screen here (+ '.0') os.environ['DISPLAY'] = display @@ -73,13 +72,13 @@ def StartVirtualX(child_build_name, build_dir): print('xdisplaycheck says there is a display still running, exiting...') raise Exception('Display already present.') - xvfb_lock_filename = '/tmp/.X%s-lock' % _XvfbDisplayIndex(child_build_name) + xvfb_lock_filename = '/tmp/.X%s-lock' % xvfb_display_index(child_build_name) if os.path.exists(xvfb_lock_filename): print('Removing stale xvfb lock file %r' % xvfb_lock_filename) try: os.unlink(xvfb_lock_filename) - except OSError as e: - print('Removing xvfb lock file failed: %s' % e) + except OSError as err: + print('Removing xvfb lock file failed: %s' % err) # Figure out which X server to try. cmd = 'Xvfb' @@ -93,8 +92,8 @@ def StartVirtualX(child_build_name, build_dir): stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) - xvfb_pid_filename = _XvfbPidFilename(child_build_name) - open(xvfb_pid_filename, 'w').write(str(proc.pid)) + pid_filename = xvfb_pid_filename(child_build_name) + open(pid_filename, 'w').write(str(proc.pid)) # Wait for Xvfb to start up. time.sleep(10) @@ -112,24 +111,24 @@ def StartVirtualX(child_build_name, build_dir): if xdisplayproc.returncode != 0: print('xdisplaycheck failed after %d seconds.' % checktime) print('xdisplaycheck output:') - for l in logs.splitlines(): - print('> %s' % l) - rc = proc.poll() - if rc is None: + for line in logs.splitlines(): + print('> %s' % line) + return_code = proc.poll() + if return_code is None: print('Xvfb still running, stopping.') proc.terminate() else: - print('Xvfb exited, code %d' % rc) + print('Xvfb exited, code %d' % return_code) print('Xvfb output:') - for l in proc.communicate()[0].splitlines(): - print('> %s' % l) + for line in proc.communicate()[0].splitlines(): + print('> %s' % line) raise Exception(logs) - else: - print('xdisplaycheck succeeded after %d seconds.' % checktime) - print('xdisplaycheck output:') - for l in logs.splitlines(): - print('> %s' % l) + + print('xdisplaycheck succeeded after %d seconds.' % checktime) + print('xdisplaycheck output:') + for line in logs.splitlines(): + print('> %s' % line) print('...OK') # Some ChromeOS tests need a window manager. @@ -137,18 +136,18 @@ def StartVirtualX(child_build_name, build_dir): print('Window manager (openbox) started.') -def StopVirtualX(child_build_name): +def stop_virtual_x(child_build_name): """Try and stop the virtual X server if one was started with StartVirtualX. When the X server dies, it takes down the window manager with it. If a virtual x server is not running, this method does nothing.""" - xvfb_pid_filename = _XvfbPidFilename(child_build_name) - if os.path.exists(xvfb_pid_filename): - xvfb_pid = int(open(xvfb_pid_filename).read()) + pid_filename = xvfb_pid_filename(child_build_name) + if os.path.exists(pid_filename): + xvfb_pid = int(open(pid_filename).read()) print('Stopping Xvfb with pid %d ...' % xvfb_pid) # If the process doesn't exist, we raise an exception that we can ignore. try: os.kill(xvfb_pid, signal.SIGKILL) except OSError: print('... killing failed, presuming unnecessary.') - os.remove(xvfb_pid_filename) + os.remove(pid_filename) print('Xvfb pid file removed')