Update generate_buildbot_json to Python 3.
Also updates the unit tests and coverage tests, and manage.py.
Bug: 1208869
Change-Id: I7e5d33aa87f2865e7a98d78dc10c135779dde46e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2892631
Commit-Queue: Jamie Madill <[email protected]>
Reviewed-by: Dirk Pranke <[email protected]>
Reviewed-by: Brian Sheedy <[email protected]>
Cr-Commit-Position: refs/heads/master@{#885155}
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py
index 90072db..377273fd 100755
--- a/testing/buildbot/generate_buildbot_json.py
+++ b/testing/buildbot/generate_buildbot_json.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -12,6 +12,7 @@
import collections
import copy
import difflib
+import functools
import glob
import itertools
import json
@@ -50,13 +51,17 @@
raise NotImplementedError()
+def custom_cmp(a, b):
+ return int(a > b) - int(a < b)
+
+
def cmp_tests(a, b):
# Prefer to compare based on the "test" key.
- val = cmp(a['test'], b['test'])
+ val = custom_cmp(a['test'], b['test'])
if val != 0:
return val
if 'name' in a and 'name' in b:
- return cmp(a['name'], b['name']) # pragma: no cover
+ return custom_cmp(a['name'], b['name']) # pragma: no cover
if 'name' not in a and 'name' not in b:
return 0 # pragma: no cover
# Prefer to put variants of the same test after the first one.
@@ -74,7 +79,7 @@
def generate(self, waterfall, tester_name, tester_config, input_tests):
isolated_scripts = []
- for test_name, test_config in sorted(input_tests.iteritems()):
+ for test_name, test_config in sorted(input_tests.items()):
test = self.bb_gen.generate_gpu_telemetry_test(
waterfall, tester_name, tester_config, test_name, test_config,
self._is_android_webview)
@@ -97,7 +102,7 @@
# key (see gles2_conform_d3d9_test and similar variants). Avoid
# losing the order by avoiding coalescing the dictionaries into one.
gtests = []
- for test_name, test_config in sorted(input_tests.iteritems()):
+ for test_name, test_config in sorted(input_tests.items()):
# Variants allow more than one definition for a given test, and is defined
# in array format from resolve_variants().
if not isinstance(test_config, list):
@@ -112,7 +117,7 @@
return gtests
def sort(self, tests):
- return sorted(tests, cmp=cmp_tests)
+ return sorted(tests, key=functools.cmp_to_key(cmp_tests))
class IsolatedScriptTestGenerator(BaseGenerator):
@@ -121,7 +126,7 @@
def generate(self, waterfall, tester_name, tester_config, input_tests):
isolated_scripts = []
- for test_name, test_config in sorted(input_tests.iteritems()):
+ for test_name, test_config in sorted(input_tests.items()):
# Variants allow more than one definition for a given test, and is defined
# in array format from resolve_variants().
if not isinstance(test_config, list):
@@ -144,7 +149,7 @@
def generate(self, waterfall, tester_name, tester_config, input_tests):
scripts = []
- for test_name, test_config in sorted(input_tests.iteritems()):
+ for test_name, test_config in sorted(input_tests.items()):
test = self.bb_gen.generate_script_test(
waterfall, tester_name, tester_config, test_name, test_config)
if test:
@@ -161,7 +166,7 @@
def generate(self, waterfall, tester_name, tester_config, input_tests):
scripts = []
- for test_name, test_config in sorted(input_tests.iteritems()):
+ for test_name, test_config in sorted(input_tests.items()):
test = self.bb_gen.generate_junit_test(
waterfall, tester_name, tester_config, test_name, test_config)
if test:
@@ -178,7 +183,7 @@
def generate(self, waterfall, tester_name, tester_config, input_tests):
scripts = []
- for test_name, test_config in sorted(input_tests.iteritems()):
+ for test_name, test_config in sorted(input_tests.items()):
for config in test_config:
test = self.bb_gen.generate_skylab_test(waterfall, tester_name,
tester_config, test_name,
@@ -357,7 +362,7 @@
def print_line(self, line):
# Exists so that tests can mock
- print line # pragma: no cover
+ print(line) # pragma: no cover
def read_file(self, relative_path):
with open(self.generate_abs_file_path(relative_path)) as fp:
@@ -365,7 +370,7 @@
def write_file(self, relative_path, contents):
with open(self.generate_abs_file_path(relative_path), 'wb') as fp:
- fp.write(contents)
+ fp.write(contents.encode('utf-8'))
def pyl_file_path(self, filename):
if self.args and self.args.pyl_files_dir:
@@ -545,7 +550,7 @@
# swarming dimension_sets that we have to merge. It will fail
# to merge / override 'args' arrays which are different
# length.
- for idx in xrange(len(b[key])):
+ for idx in range(len(b[key])):
try:
a[key][idx] = self.dictionary_merge(a[key][idx], b[key][idx],
path + [str(key), str(idx)],
@@ -637,7 +642,7 @@
del swarming_dict['hard_timeout'] # pragma: no cover
if not swarming_dict.get('can_use_on_swarming_builders', False):
# Remove all other keys.
- for k in swarming_dict.keys(): # pragma: no cover
+ for k in list(swarming_dict): # pragma: no cover
if k != 'can_use_on_swarming_builders': # pragma: no cover
del swarming_dict[k] # pragma: no cover
@@ -667,12 +672,12 @@
replacements = self.get_test_replacements(
test, test_name, tester_name) or {}
valid_replacement_keys = ['args', 'non_precommit_args', 'precommit_args']
- for key, replacement_dict in replacements.iteritems():
+ for key, replacement_dict in replacements.items():
if key not in valid_replacement_keys:
raise BBGenErr(
'Given replacement key %s for %s on %s is not in the list of valid '
'keys %s' % (key, test_name, tester_name, valid_replacement_keys))
- for replacement_key, replacement_val in replacement_dict.iteritems():
+ for replacement_key, replacement_val in replacement_dict.items():
found_key = False
for i, test_key in enumerate(test.get(key, [])):
# Handle both the key/value being replaced being defined as two
@@ -1006,7 +1011,7 @@
other_suites = self.test_suites.get(other_test_type, {})
basic_suites = self.test_suites.get('basic_suites', {})
- for suite, suite_def in target_suites.iteritems():
+ for suite, suite_def in target_suites.items():
if suite in basic_suites:
raise BBGenErr('%s names may not duplicate basic test suite names '
'(error found while processsing %s)'
@@ -1031,13 +1036,13 @@
new_test_suites = {}
test_types = ['basic_suites', 'compound_suites', 'matrix_compound_suites']
for category in test_types:
- for name, value in self.test_suites.get(category, {}).iteritems():
+ for name, value in self.test_suites.get(category, {}).items():
new_test_suites[name] = value
self.test_suites = new_test_suites
def resolve_test_id_prefixes(self):
- for suite in self.test_suites['basic_suites'].itervalues():
- for key, test in suite.iteritems():
+ for suite in self.test_suites['basic_suites'].values():
+ for key, test in suite.items():
assert isinstance(test, dict)
# This assumes the recipe logic which prefers 'test' to 'isolate_name'
@@ -1074,7 +1079,7 @@
# referenced by compound suites exist.
basic_suites = self.test_suites.get('basic_suites')
- for name, value in compound_suites.iteritems():
+ for name, value in compound_suites.items():
# Resolve this to a dictionary.
full_suite = {}
for entry in value:
@@ -1103,7 +1108,7 @@
# Each test in a basic test suite will have a definition per variant.
test_suite = {}
- for test_name, test_config in basic_test_definition.iteritems():
+ for test_name, test_config in basic_test_definition.items():
definitions = []
for variant in variants:
# Unpack the variant from variants.pyl if it's string based.
@@ -1164,10 +1169,10 @@
# referenced by matrix suites exist.
basic_suites = self.test_suites.get('basic_suites')
- for test_name, matrix_config in matrix_compound_suites.iteritems():
+ for test_name, matrix_config in matrix_compound_suites.items():
full_suite = {}
- for test_suite, mtx_test_suite_config in matrix_config.iteritems():
+ for test_suite, mtx_test_suite_config in matrix_config.items():
basic_test_def = copy.deepcopy(basic_suites[test_suite])
if 'variants' in mtx_test_suite_config:
@@ -1180,8 +1185,8 @@
def link_waterfalls_to_test_suites(self):
for waterfall in self.waterfalls:
- for tester_name, tester in waterfall['machines'].iteritems():
- for suite, value in tester.get('test_suites', {}).iteritems():
+ for tester_name, tester in waterfall['machines'].items():
+ for suite, value in tester.get('test_suites', {}).items():
if not value in self.test_suites:
# Hard / impossible to cover this in the unit test.
raise self.unknown_test_suite(
@@ -1370,9 +1375,8 @@
A dictionary mapping builders to test specs
"""
return {
- name: self.get_tests_for_config(waterfall, name, config)
- for name, config
- in waterfall['machines'].iteritems()
+ name: self.get_tests_for_config(waterfall, name, config)
+ for name, config in waterfall['machines'].items()
}
def get_tests_for_config(self, waterfall, name, config):
@@ -1385,7 +1389,7 @@
if 'additional_compile_targets' in config:
tests['additional_compile_targets'] = config[
'additional_compile_targets']
- for test_type, input_tests in config.get('test_suites', {}).iteritems():
+ for test_type, input_tests in config.get('test_suites', {}).items():
if test_type not in generator_map:
raise self.unknown_test_suite_type(
test_type, name, waterfall['name']) # pragma: no cover
@@ -1581,8 +1585,8 @@
suites_seen = set()
generator_map = self.get_test_generator_map()
for waterfall in self.waterfalls:
- for bot_name, tester in waterfall['machines'].iteritems():
- for suite_type, suite in tester.get('test_suites', {}).iteritems():
+ for bot_name, tester in waterfall['machines'].items():
+ for suite_type, suite in tester.get('test_suites', {}).items():
if suite_type not in generator_map:
raise self.unknown_test_suite_type(suite_type, bot_name,
waterfall['name'])
@@ -1607,17 +1611,17 @@
all_bots = set()
missing_bots = set()
for waterfall in self.waterfalls:
- for bot_name, tester in waterfall['machines'].iteritems():
+ for bot_name, tester in waterfall['machines'].items():
all_bots.add(bot_name)
# In order to disambiguate between bots with the same name on
# different waterfalls, support has been added to various
# exceptions for concatenating the waterfall name after the bot
# name.
all_bots.add(bot_name + ' ' + waterfall['name'])
- for exception in self.exceptions.itervalues():
+ for exception in self.exceptions.values():
removals = (exception.get('remove_from', []) +
exception.get('remove_gtest_from', []) +
- exception.get('modifications', {}).keys())
+ list(exception.get('modifications', {}).keys()))
for removal in removals:
if removal not in all_bots:
missing_bots.add(removal)
@@ -1631,7 +1635,7 @@
seen_mixins = set()
for waterfall in self.waterfalls:
seen_mixins = seen_mixins.union(waterfall.get('mixins', set()))
- for bot_name, tester in waterfall['machines'].iteritems():
+ for bot_name, tester in waterfall['machines'].items():
seen_mixins = seen_mixins.union(tester.get('mixins', set()))
for suite in self.test_suites.values():
if isinstance(suite, list):
@@ -2090,7 +2094,7 @@
configuration, not grouped by their test suite.
"""
tests = {}
- for test_suite in test_suites.itervalues():
+ for test_suite in test_suites.values():
for test in test_suite:
test_info = test_suite[test]
test_name = test