From 165bb2e839b3dc0b30a75e66c46e19cdea69e2bc Mon Sep 17 00:00:00 2001 From: Matt Reichhoff <mreichhoff@chromium.org> Date: Tue, 16 Nov 2021 19:10:34 +0000 Subject: [PATCH] Update ios/build/bots/scripts to python3 Bug: 1262335 Change-Id: Ie3b32c64ef7369ecd915ae751197e230af0ee275 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3273475 Reviewed-by: Dirk Pranke <dpranke@google.com> Reviewed-by: Zhaoyang Li <zhaoyangli@chromium.org> Commit-Queue: Matt Reichhoff <mreichhoff@chromium.org> Cr-Commit-Position: refs/heads/main@{#942247} --- ios/build/bots/scripts/PRESUBMIT.py | 8 ++++- ios/build/bots/scripts/gtest_utils.py | 4 +-- ios/build/bots/scripts/iossim_util.py | 19 +++++++----- ios/build/bots/scripts/iossim_util_test.py | 4 +-- ios/build/bots/scripts/result_sink_util.py | 10 +++++- .../bots/scripts/result_sink_util_test.py | 7 +++-- ios/build/bots/scripts/run_test.py | 1 + ios/build/bots/scripts/shard_util.py | 19 ++++++++---- ios/build/bots/scripts/shard_util_test.py | 31 ++++++++++--------- ios/build/bots/scripts/test_apps.py | 4 +-- ios/build/bots/scripts/test_result_util.py | 4 +-- .../bots/scripts/test_result_util_test.py | 5 ++- ios/build/bots/scripts/test_runner.py | 29 ++++++++++------- ios/build/bots/scripts/test_runner_test.py | 6 ++-- ios/build/bots/scripts/wpr_runner.py | 3 +- ios/build/bots/scripts/wpr_runner_test.py | 20 ++++++------ ios/build/bots/scripts/xcode_log_parser.py | 6 ++-- .../bots/scripts/xcode_log_parser_test.py | 6 ++-- ios/build/bots/scripts/xcode_util.py | 16 ++++++---- ios/build/bots/scripts/xcode_util_test.py | 8 ++--- .../bots/scripts/xcodebuild_runner_test.py | 4 +-- 21 files changed, 128 insertions(+), 86 deletions(-) diff --git a/ios/build/bots/scripts/PRESUBMIT.py b/ios/build/bots/scripts/PRESUBMIT.py index a03ba1eb0b94a..488b9c8da804e 100644 --- a/ios/build/bots/scripts/PRESUBMIT.py +++ b/ios/build/bots/scripts/PRESUBMIT.py @@ -15,7 +15,13 @@ def _RunTestRunnerUnitTests(input_api, output_api): files = ['.*_test.py$'] return input_api.canned_checks.RunUnitTestsInDirectory( - input_api, output_api, '.', files_to_check=files) + input_api, + output_api, + '.', + files_to_check=files, + run_on_python2=not USE_PYTHON3, + run_on_python3=USE_PYTHON3, + skip_shebang_check=True) def CheckChange(input_api, output_api): diff --git a/ios/build/bots/scripts/gtest_utils.py b/ios/build/bots/scripts/gtest_utils.py index 65ced8daf6bed..c96ac7ee8d9cf 100644 --- a/ios/build/bots/scripts/gtest_utils.py +++ b/ios/build/bots/scripts/gtest_utils.py @@ -123,7 +123,7 @@ class GTestResult(object): self._crashed = True # At most one test can crash the entire app in a given parsing. - for test, log_lines in self._failed_tests.iteritems(): + for test, log_lines in self._failed_tests.items(): # A test with no output would have crashed. No output is replaced # by the GTestLogParser by a sentence indicating non-completion. if 'Did not complete.' in log_lines: @@ -131,7 +131,7 @@ class GTestResult(object): self._crashed_test = test # A test marked as flaky may also have crashed the app. - for test, log_lines in self._flaked_tests.iteritems(): + for test, log_lines in self._flaked_tests.items(): if 'Did not complete.' in log_lines: self._crashed = True self._crashed_test = test diff --git a/ios/build/bots/scripts/iossim_util.py b/ios/build/bots/scripts/iossim_util.py index e049e0a7a8895..c0b895e1ee8ab 100644 --- a/ios/build/bots/scripts/iossim_util.py +++ b/ios/build/bots/scripts/iossim_util.py @@ -18,7 +18,9 @@ def _compose_simulator_name(platform, version): def get_simulator_list(): """Gets list of available simulator as a dictionary.""" - return json.loads(subprocess.check_output(['xcrun', 'simctl', 'list', '-j'])) + return json.loads( + subprocess.check_output(['xcrun', 'simctl', 'list', + '-j']).decode('utf-8')) def get_simulator(platform, version): @@ -127,7 +129,8 @@ def create_device_by_platform_and_version(platform, version): runtime = get_simulator_runtime_by_version(simulators, version) try: udid = subprocess.check_output( - ['xcrun', 'simctl', 'create', name, device_type, runtime]).rstrip() + ['xcrun', 'simctl', 'create', name, device_type, + runtime]).decode('utf-8').rstrip() LOGGER.info('Created simulator in first attempt with UDID: %s', udid) # Sometimes above command fails to create a simulator. Verify it and retry # once if first attempt failed. @@ -135,7 +138,8 @@ def create_device_by_platform_and_version(platform, version): # Try to delete once to avoid duplicate in case of race condition. delete_simulator_by_udid(udid) udid = subprocess.check_output( - ['xcrun', 'simctl', 'create', name, device_type, runtime]).rstrip() + ['xcrun', 'simctl', 'create', name, device_type, + runtime]).decode('utf-8').rstrip() LOGGER.info('Created simulator in second attempt with UDID: %s', udid) return udid except subprocess.CalledProcessError as e: @@ -152,7 +156,7 @@ def delete_simulator_by_udid(udid): LOGGER.info('Deleting simulator %s', udid) try: subprocess.check_output(['xcrun', 'simctl', 'delete', udid], - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT).decode('utf-8') except subprocess.CalledProcessError as e: # Logging error instead of throwing so we don't cause failures in case # this was indeed failing to clean up. @@ -188,7 +192,7 @@ def get_home_directory(platform, version): """ return subprocess.check_output( ['xcrun', 'simctl', 'getenv', - get_simulator(platform, version), 'HOME']).rstrip() + get_simulator(platform, version), 'HOME']).decode('utf-8').rstrip() def boot_simulator_if_not_booted(sim_udid): @@ -207,7 +211,8 @@ def boot_simulator_if_not_booted(sim_udid): continue if device['state'] == 'Booted': return - subprocess.check_output(['xcrun', 'simctl', 'boot', sim_udid]) + subprocess.check_output(['xcrun', 'simctl', 'boot', + sim_udid]).decode('utf-8') return raise test_runner.SimulatorNotFoundError( 'Not found simulator with "%s" UDID in devices %s' % @@ -223,7 +228,7 @@ def get_app_data_directory(app_bundle_id, sim_udid): """ return subprocess.check_output( ['xcrun', 'simctl', 'get_app_container', sim_udid, app_bundle_id, - 'data']).rstrip() + 'data']).decode('utf-8').rstrip() def is_device_with_udid_simulator(device_udid): diff --git a/ios/build/bots/scripts/iossim_util_test.py b/ios/build/bots/scripts/iossim_util_test.py index b64d3072bdc94..e358020a24bfc 100755 --- a/ios/build/bots/scripts/iossim_util_test.py +++ b/ios/build/bots/scripts/iossim_util_test.py @@ -166,7 +166,7 @@ class GetiOSSimUtil(test_runner_test.TestCase): @mock.patch('subprocess.check_output', autospec=True) def test_create_device_by_platform_and_version(self, subprocess_mock, _): """Ensures that command is correct.""" - subprocess_mock.return_value = 'NEW_UDID' + subprocess_mock.return_value = b'NEW_UDID' self.assertEqual( 'NEW_UDID', iossim_util.create_device_by_platform_and_version( @@ -195,7 +195,7 @@ class GetiOSSimUtil(test_runner_test.TestCase): @mock.patch('subprocess.check_output', autospec=True) def test_get_home_directory(self, subprocess_mock, _): """Ensures that command is correct.""" - subprocess_mock.return_value = 'HOME_DIRECTORY' + subprocess_mock.return_value = b'HOME_DIRECTORY' self.assertEqual('HOME_DIRECTORY', iossim_util.get_home_directory('iPhone 11', '13.2.2')) self.assertEqual([ diff --git a/ios/build/bots/scripts/result_sink_util.py b/ios/build/bots/scripts/result_sink_util.py index 3a8a85e19d265..f7c30c5105662 100644 --- a/ios/build/bots/scripts/result_sink_util.py +++ b/ios/build/bots/scripts/result_sink_util.py @@ -9,6 +9,7 @@ import json import logging import os import requests +import sys LOGGER = logging.getLogger(__name__) # VALID_STATUSES is a list of valid status values for test_result['status']. @@ -71,10 +72,17 @@ def _compose_test_result(test_id, } for name in file_artifacts } if test_log: + message = '' + if sys.version_info.major < 3: + message = base64.b64encode(test_log) + else: + # Python3 b64encode takes and returns bytes. The result must be + # serializable in order for the eventual json.dumps to succeed + message = base64.b64encode(test_log.encode('utf-8')).decode('utf-8') test_result['summaryHtml'] = '<text-artifact artifact-id="Test Log" />' test_result['artifacts'].update({ 'Test Log': { - 'contents': base64.b64encode(test_log) + 'contents': message }, }) if not test_result['artifacts']: diff --git a/ios/build/bots/scripts/result_sink_util_test.py b/ios/build/bots/scripts/result_sink_util_test.py index 3155899fcbea3..cb4ba7c13f154 100755 --- a/ios/build/bots/scripts/result_sink_util_test.py +++ b/ios/build/bots/scripts/result_sink_util_test.py @@ -62,7 +62,8 @@ class UnitTest(unittest.TestCase): 'summaryHtml': '<text-artifact artifact-id="Test Log" />', 'artifacts': { 'Test Log': { - 'contents': base64.b64encode(short_log) + 'contents': + base64.b64encode(short_log.encode('utf-8')).decode('utf-8') }, 'name': { 'filePath': '/path/to/name' @@ -89,7 +90,9 @@ class UnitTest(unittest.TestCase): 'summaryHtml': '<text-artifact artifact-id="Test Log" />', 'artifacts': { 'Test Log': { - 'contents': base64.b64encode(len_4128_str) + 'contents': + base64.b64encode(len_4128_str.encode('utf-8') + ).decode('utf-8') }, }, 'tags': [], diff --git a/ios/build/bots/scripts/run_test.py b/ios/build/bots/scripts/run_test.py index 2f7a831417889..9e0eed204281e 100755 --- a/ios/build/bots/scripts/run_test.py +++ b/ios/build/bots/scripts/run_test.py @@ -283,6 +283,7 @@ class RunnerInstallXcodeTest(test_runner_test.TestCase): self.runner.args.xcode_build_version = 'testXcodeVersion' self.runner.args.runtime_cache_prefix = 'test/runtime-ios-' self.runner.args.version = '14.4' + self.runner.args.out_dir = 'out/dir' @mock.patch('test_runner.defaults_delete') @mock.patch('json.dump') diff --git a/ios/build/bots/scripts/shard_util.py b/ios/build/bots/scripts/shard_util.py index 659d4f1f2d330..9ccc3bc489f90 100644 --- a/ios/build/bots/scripts/shard_util.py +++ b/ios/build/bots/scripts/shard_util.py @@ -7,6 +7,7 @@ import logging import os import re import subprocess +import sys import test_runner_errors @@ -119,7 +120,7 @@ def fetch_test_names_for_release(stdout): //build/scripts/slave/recipe_modules/ios/api.py Args: - stdout: (string) response of 'otool -ov' + stdout: (bytes) response of 'otool -ov' Returns: (list) a list of (TestCase, testMethod), containing disabled tests. @@ -130,6 +131,10 @@ def fetch_test_names_for_release(stdout): # 1. Parse test class names. # 2. If they are not in ignored list, parse test method names. # 3. Calculate test count per test class. + # |stdout| will be bytes on python3, and therefore must be decoded prior + # to running a regex. + if sys.version_info.major == 3: + stdout = stdout.decode('utf-8') res = re.split(TEST_CLASS_RELEASE_APP_PATTERN, stdout) # Ignore 1st element in split since it does not have any test class data test_classes_output = res[1:] @@ -163,16 +168,18 @@ def fetch_test_names_for_debug(stdout): format of (TestCase, testMethod) including disabled tests, in debug app. Args: - stdout: (string) response of 'otool -ov' + stdout: (bytes) response of 'otool -ov' Returns: (list) a list of (TestCase, testMethod), containing disabled tests. """ - test_names = TEST_NAMES_DEBUG_APP_PATTERN.findall(stdout.decode('utf-8')) + # |stdout| will be bytes on python3, and therefore must be decoded prior + # to running a regex. + if sys.version_info.major == 3: + stdout = stdout.decode('utf-8') + test_names = TEST_NAMES_DEBUG_APP_PATTERN.findall(stdout) test_names = list( - map( - lambda test_name: (test_name[0].encode('utf-8'), test_name[1].encode( - 'utf-8')), test_names)) + map(lambda test_name: (test_name[0], test_name[1]), test_names)) return list( filter(lambda test_name: test_name[0] not in IGNORED_CLASSES, test_names)) diff --git a/ios/build/bots/scripts/shard_util_test.py b/ios/build/bots/scripts/shard_util_test.py index c4757f3946c3f..24bd53464246d 100755 --- a/ios/build/bots/scripts/shard_util_test.py +++ b/ios/build/bots/scripts/shard_util_test.py @@ -27,7 +27,7 @@ DEBUG_APP_OTOOL_OUTPUT = '\n'.join([ 'imp 0x1075e6887 -[ToolBarTestCase testH]', 'imp 0x1075e6887 -[ToolBarTestCase DISABLED_testI]', 'imp 0x1075e6887 -[ToolBarTestCase FLAKY_testJ]', 'version 0' -]) +]).encode('utf-8') # Debug app otool output format in Xcode 11.4 toolchain. DEBUG_APP_OTOOL_OUTPUT_114 = '\n'.join([ @@ -49,7 +49,7 @@ DEBUG_APP_OTOOL_OUTPUT_114 = '\n'.join([ ' imp 0x1075e6887 -[ToolBarTestCase testH]', ' imp 0x1075e6887 -[ToolBarTestCase DISABLED_testI]', ' imp 0x1075e6887 -[ToolBarTestCase FLAKY_testJ]', 'version 0' -]) +]).encode('utf-8') RELEASE_APP_OTOOL_OUTPUT = '\n'.join([ 'Meta Class', 'name 0x1064b8438 CacheTestCase', @@ -73,7 +73,7 @@ RELEASE_APP_OTOOL_OUTPUT = '\n'.join([ 'name 0x1075e6887 testG', 'name 0x1075e6887 testH', 'name 0x1075e6887 DISABLED_testI', 'name 0x1075e6887 FLAKY_testJ', 'name 0x1064b8438 ToolBarTestCase', 'baseProtocols 0x0', 'version 0' -]) +]).encode('utf-8') RELEASE_APP_OTOOL_OUTPUT_CLASS_NOT_IN_PAIRS = '\n'.join([ 'Meta Class', 'name 0x1064b8438 CacheTestCase', @@ -96,7 +96,7 @@ RELEASE_APP_OTOOL_OUTPUT_CLASS_NOT_IN_PAIRS = '\n'.join([ 'name 0x1075e6887 testG', 'name 0x1075e6887 testH', 'name 0x1075e6887 DISABLED_testI', 'name 0x1075e6887 FLAKY_testJ', 'name 0x1064b8438 ToolBarTestCase', 'baseProtocols 0x0', 'version 0' -]) +]).encode('utf-8') # Release app otool output format in Xcode 11.4 toolchain. RELEASE_APP_OTOOL_OUTPUT_114 = '\n'.join([ @@ -123,7 +123,7 @@ RELEASE_APP_OTOOL_OUTPUT_114 = '\n'.join([ ' name 0x1075e6887 DISABLED_testI', ' name 0x1075e6887 FLAKY_testJ', ' name 0x1064b8438 ToolBarTestCase', 'baseProtocols 0x0', 'version 0' -]) +]).encode('utf-8') class TestShardUtil(unittest.TestCase): @@ -179,13 +179,14 @@ class TestShardUtil(unittest.TestCase): for test_name in expected_test_names: self.assertTrue(test_name in resp) - test_cases = map(lambda (test_case, test_method): test_case, resp) - + test_cases = [test_case for (test_case, _) in resp] # ({'CacheTestCase': 3, 'TabUITestCase': 2, 'PasswordsTestCase': 1, # 'KeyboardTestCase': 1, 'ToolBarTestCase': 3}) counts = collections.Counter(test_cases).most_common() name, _ = counts[0] - self.assertEqual(name, 'ToolBarTestCase') + # CacheTestCase and ToolBarTestCase each have 3 entries. + # In case of ties, most_common() returns the first encountered at index 0. + self.assertEqual(name, 'CacheTestCase') def test_fetch_test_counts_release(self): """Ensures that the release output is formatted correctly""" @@ -207,7 +208,7 @@ class TestShardUtil(unittest.TestCase): for test_name in expected_test_names: self.assertTrue(test_name in resp) - test_cases = map(lambda (test_case, test_method): test_case, resp) + test_cases = [test_case for (test_case, _) in resp] # ({'KeyboardTest': 3, 'CacheTestCase': 3, # 'ToolBarTestCase': 4}) counts = collections.Counter(test_cases).most_common() @@ -243,13 +244,15 @@ class TestShardUtil(unittest.TestCase): for test_name in expected_test_names: self.assertTrue(test_name in resp) - test_cases = map(lambda (test_case, test_method): test_case, resp) + test_cases = [test_case for (test_case, _) in resp] # ({'CacheTestCase': 3, 'TabUITestCase': 2, 'PasswordsTestCase': 1, # 'KeyboardTestCase': 1, 'ToolBarTestCase': 3}) counts = collections.Counter(test_cases).most_common() name, _ = counts[0] - self.assertEqual(name, 'ToolBarTestCase') + # CacheTestCase and ToolBarTestCase each have 3 entries. + # In case of ties, most_common() returns the first encountered at index 0. + self.assertEqual(name, 'CacheTestCase') def test_fetch_test_counts_release_114(self): """Test the release output from otool in Xcode 11.4""" @@ -271,7 +274,7 @@ class TestShardUtil(unittest.TestCase): for test_name in expected_test_names: self.assertTrue(test_name in resp) - test_cases = map(lambda (test_case, test_method): test_case, resp) + test_cases = [test_case for (test_case, _) in resp] # ({'KeyboardTest': 3, 'CacheTestCase': 3, # 'ToolBarTestCase': 4}) counts = collections.Counter(test_cases).most_common() @@ -281,7 +284,7 @@ class TestShardUtil(unittest.TestCase): def test_balance_into_sublists_debug(self): """Ensure the balancing algorithm works""" resp = shard_util.fetch_test_names_for_debug(DEBUG_APP_OTOOL_OUTPUT) - test_cases = map(lambda (test_case, test_method): test_case, resp) + test_cases = [test_case for (test_case, _) in resp] test_counts = collections.Counter(test_cases) sublists_1 = shard_util.balance_into_sublists(test_counts, 1) @@ -304,7 +307,7 @@ class TestShardUtil(unittest.TestCase): def test_balance_into_sublists_release(self): """Ensure the balancing algorithm works""" resp = shard_util.fetch_test_names_for_release(RELEASE_APP_OTOOL_OUTPUT) - test_cases = map(lambda (test_case, test_method): test_case, resp) + test_cases = [test_case for (test_case, _) in resp] test_counts = collections.Counter(test_cases) sublists_3 = shard_util.balance_into_sublists(test_counts, 3) diff --git a/ios/build/bots/scripts/test_apps.py b/ios/build/bots/scripts/test_apps.py index ee82f29addeef..08c95b6015dc2 100644 --- a/ios/build/bots/scripts/test_apps.py +++ b/ios/build/bots/scripts/test_apps.py @@ -49,7 +49,7 @@ def get_bundle_id(app_path): '-c', 'Print:CFBundleIdentifier', os.path.join(app_path, 'Info.plist'), - ]).rstrip().decode("utf-8") + ]).decode("utf-8").rstrip() def is_running_rosetta(): @@ -61,7 +61,7 @@ def is_running_rosetta(): running on an Intel machine. """ translated = subprocess.check_output( - ['sysctl', '-i', '-b', 'sysctl.proc_translated']) + ['sysctl', '-i', '-b', 'sysctl.proc_translated']).decode('utf-8') # "sysctl -b" is expected to return a 4-byte integer response. 1 means the # current process is running under Rosetta, 0 means it is not. On x86_64 # machines, this variable does not exist at all, so "-i" is used to return a diff --git a/ios/build/bots/scripts/test_result_util.py b/ios/build/bots/scripts/test_result_util.py index 7f61ee31658f6..a16cfc813eab8 100644 --- a/ios/build/bots/scripts/test_result_util.py +++ b/ios/build/bots/scripts/test_result_util.py @@ -400,9 +400,9 @@ class ResultCollection(object): logs['flaked tests'] = flaked if failed: logs['failed tests'] = failed - for test, log_lines in failed.iteritems(): + for test, log_lines in failed.items(): logs[test] = log_lines - for test, log_lines in flaked.iteritems(): + for test, log_lines in flaked.items(): logs[test] = log_lines return logs diff --git a/ios/build/bots/scripts/test_result_util_test.py b/ios/build/bots/scripts/test_result_util_test.py index ff23d9e6a45ae..a3f057077ec68 100755 --- a/ios/build/bots/scripts/test_result_util_test.py +++ b/ios/build/bots/scripts/test_result_util_test.py @@ -39,13 +39,12 @@ class UtilTest(test_runner_test.TestCase): """Tests _validate_kwargs.""" with self.assertRaises(AssertionError) as context: TestResult('name', TestStatus.PASS, unknown='foo') - expected_message = ( - 'Invalid keyword argument(s) in set([\'unknown\']) passed in!') + expected_message = ("Invalid keyword argument(s) in {'unknown'} passed in!") self.assertTrue(expected_message in str(context.exception)) with self.assertRaises(AssertionError) as context: ResultCollection(test_log='foo') expected_message = ( - 'Invalid keyword argument(s) in set([\'test_log\']) passed in!') + "Invalid keyword argument(s) in {'test_log'} passed in!") self.assertTrue(expected_message in str(context.exception)) def test_validate_test_status(self): diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py index 183c71b0c9a7c..9efb5038b4f5b 100644 --- a/ios/build/bots/scripts/test_runner.py +++ b/ios/build/bots/scripts/test_runner.py @@ -148,9 +148,9 @@ def get_device_ios_version(udid): Returns: Device UDID. """ - return subprocess.check_output(['ideviceinfo', - '--udid', udid, - '-k', 'ProductVersion']).strip() + return subprocess.check_output( + ['ideviceinfo', '--udid', udid, '-k', + 'ProductVersion']).decode('utf-8').strip() def defaults_write(d, key, value): @@ -254,6 +254,10 @@ def print_process_output(proc, timer.cancel() if not line: break + # |line| will be bytes on python3, and therefore must be decoded prior + # to rstrip. + if sys.version_info.major == 3: + line = line.decode('utf-8') line = line.rstrip() out.append(line) if parser: @@ -263,9 +267,6 @@ def print_process_output(proc, if parser: parser.Finalize() - if sys.version_info.major == 3: - for index in range(len(out)): - out[index] = out[index].decode('utf-8') LOGGER.debug('Finished print_process_output.') return out @@ -282,7 +283,8 @@ def get_current_xcode_info(): try: out = subprocess.check_output(['xcodebuild', '-version']).splitlines() version, build_version = out[0].split(' ')[-1], out[1].split(' ')[-1] - path = subprocess.check_output(['xcode-select', '--print-path']).rstrip() + path = subprocess.check_output(['xcode-select', + '--print-path']).decode('utf-8').rstrip() except subprocess.CalledProcessError: version = build_version = path = None @@ -368,7 +370,8 @@ class TestRunner(object): """removes any proxy settings which may remain from a previous run.""" LOGGER.info('Removing any proxy settings.') network_services = subprocess.check_output( - ['networksetup', '-listallnetworkservices']).strip().split('\n') + ['networksetup', + '-listallnetworkservices']).decode('utf-8').strip().split('\n') if len(network_services) > 1: # We ignore the first line as it is a description of the command's output. network_services = network_services[1:] @@ -610,7 +613,7 @@ class TestRunner(object): if self.retries and never_expected_tests: LOGGER.warning('%s tests failed and will be retried.\n', len(never_expected_tests)) - for i in xrange(self.retries): + for i in range(self.retries): tests_to_retry = list(overall_result.never_expected_tests()) for test in tests_to_retry: LOGGER.info('Retry #%s for %s.\n', i + 1, test) @@ -761,9 +764,10 @@ class SimulatorTestRunner(TestRunner): if os.path.exists(docs_dir) and os.path.exists(metadata_plist): cfbundleid = subprocess.check_output([ '/usr/libexec/PlistBuddy', - '-c', 'Print:MCMMetadataIdentifier', + '-c', + 'Print:MCMMetadataIdentifier', metadata_plist, - ]).rstrip() + ]).decode('utf-8').rstrip() if cfbundleid == self.cfbundleid: shutil.copytree(docs_dir, os.path.join(self.out_dir, 'Documents')) return @@ -917,7 +921,8 @@ class DeviceTestRunner(TestRunner): """ super(DeviceTestRunner, self).__init__(app_path, out_dir, **kwargs) - self.udid = subprocess.check_output(['idevice_id', '--list']).rstrip() + self.udid = subprocess.check_output(['idevice_id', + '--list']).decode('utf-8').rstrip() if len(self.udid.splitlines()) != 1: raise DeviceDetectionError(self.udid) diff --git a/ios/build/bots/scripts/test_runner_test.py b/ios/build/bots/scripts/test_runner_test.py index aa96e55fa22d0..3fde2c5fe899f 100755 --- a/ios/build/bots/scripts/test_runner_test.py +++ b/ios/build/bots/scripts/test_runner_test.py @@ -47,7 +47,7 @@ class TestCase(unittest.TestCase): super(TestCase, self).tearDown(*args, **kwargs) for obj in self._mocks: - for member, original_value in self._mocks[obj].iteritems(): + for member, original_value in self._mocks[obj].items(): setattr(obj, member, original_value) @@ -281,8 +281,8 @@ class DeviceTestRunnerTest(TestCase): self.mock(test_runner, 'get_current_xcode_info', lambda: { 'version': 'test version', 'build': 'test build', 'path': 'test/path'}) self.mock(test_runner, 'install_xcode', install_xcode) - self.mock(test_runner.subprocess, 'check_output', - lambda _: 'fake-bundle-id') + self.mock(test_runner.subprocess, + 'check_output', lambda _: b'fake-bundle-id') self.mock(os.path, 'abspath', lambda path: '/abs/path/to/%s' % path) self.mock(os.path, 'exists', lambda _: True) self.mock(os, 'listdir', lambda _: []) diff --git a/ios/build/bots/scripts/wpr_runner.py b/ios/build/bots/scripts/wpr_runner.py index 06bb30aaf1383..ad6a20c569102 100644 --- a/ios/build/bots/scripts/wpr_runner.py +++ b/ios/build/bots/scripts/wpr_runner.py @@ -380,7 +380,8 @@ class WprProxySimulatorTestRunner(test_runner.SimulatorTestRunner): # We route all network adapters through the proxy, since it is easier than # determining which network adapter is being used currently. network_services = subprocess.check_output( - ['networksetup', '-listallnetworkservices']).strip().split('\n') + ['networksetup', + '-listallnetworkservices']).decode('utf-8').strip().split('\n') if len(network_services) > 1: # We ignore the first line as it is a description of the command's output. network_services = network_services[1:] diff --git a/ios/build/bots/scripts/wpr_runner_test.py b/ios/build/bots/scripts/wpr_runner_test.py index f38758ec7192b..b66e74eae33f7 100755 --- a/ios/build/bots/scripts/wpr_runner_test.py +++ b/ios/build/bots/scripts/wpr_runner_test.py @@ -24,8 +24,8 @@ class WprProxySimulatorTestRunnerTest(test_runner_test.TestCase): self.mock(test_runner, 'get_current_xcode_info', lambda: { 'version': 'test version', 'build': 'test build', 'path': 'test/path'}) - self.mock(test_runner.subprocess, 'check_output', - lambda _: 'fake-bundle-id') + self.mock(test_runner.subprocess, + 'check_output', lambda _: b'fake-bundle-id') self.mock(os.path, 'abspath', lambda path: '/abs/path/to/%s' % path) self.mock(os.path, 'exists', lambda _: True) self.mock(test_runner.TestRunner, 'set_sigterm_handler', @@ -113,14 +113,14 @@ class WprProxySimulatorTestRunnerTest(test_runner_test.TestCase): def __init__(self): self.line_index = 0 self.lines = [ - 'Test Case \'-[a 1]\' started.', - 'Test Case \'-[a 1]\' has uninteresting logs.', - 'Test Case \'-[a 1]\' passed (0.1 seconds)', - 'Test Case \'-[b 2]\' started.', - 'Test Case \'-[b 2]\' passed (0.1 seconds)', - 'Test Case \'-[c 3]\' started.', - 'Test Case \'-[c 3]\' has interesting failure info.', - 'Test Case \'-[c 3]\' failed (0.1 seconds)', + b'Test Case \'-[a 1]\' started.', + b'Test Case \'-[a 1]\' has uninteresting logs.', + b'Test Case \'-[a 1]\' passed (0.1 seconds)', + b'Test Case \'-[b 2]\' started.', + b'Test Case \'-[b 2]\' passed (0.1 seconds)', + b'Test Case \'-[c 3]\' started.', + b'Test Case \'-[c 3]\' has interesting failure info.', + b'Test Case \'-[c 3]\' failed (0.1 seconds)', ] def readline(self): diff --git a/ios/build/bots/scripts/xcode_log_parser.py b/ios/build/bots/scripts/xcode_log_parser.py index 66fe7774c008c..d757891e0b462 100644 --- a/ios/build/bots/scripts/xcode_log_parser.py +++ b/ios/build/bots/scripts/xcode_log_parser.py @@ -169,7 +169,7 @@ class Xcode11LogParser(object): id_params = ['--id', ref_id] if ref_id else [] xcresult_command = ['xcresulttool', 'get', '--format', 'json', '--path', xcresult_path] + id_params - return subprocess.check_output(xcresult_command).strip() + return subprocess.check_output(xcresult_command).decode('utf-8').strip() @staticmethod def _list_of_failed_tests(actions_invocation_record, excluded=None): @@ -388,7 +388,7 @@ class Xcode11LogParser(object): test['identifier'] ['_value']] = test['summaryRef']['id']['_value'] - for test, summary_ref_id in test_summary_refs.iteritems(): + for test, summary_ref_id in test_summary_refs.items(): # See SINGLE_TEST_SUMMARY_REF in xcode_log_parser_test.py for an example # of |test_summary|. test_summary = json.loads( @@ -457,7 +457,7 @@ class Xcode11LogParser(object): 'xcresulttool', 'export', '--type', output_type, '--id', ref_id, '--path', xcresult, '--output-path', output_path ] - subprocess.check_output(export_command).strip() + subprocess.check_output(export_command).decode('utf-8').strip() @staticmethod def _extract_attachments(test, diff --git a/ios/build/bots/scripts/xcode_log_parser_test.py b/ios/build/bots/scripts/xcode_log_parser_test.py index 7f7eb407f6d0f..fd298cb48ef52 100755 --- a/ios/build/bots/scripts/xcode_log_parser_test.py +++ b/ios/build/bots/scripts/xcode_log_parser_test.py @@ -85,7 +85,7 @@ XCRESULT_ROOT = """ } }""" -REF_ID = """ +REF_ID = b""" { "actions": { "_values": [{ @@ -435,7 +435,7 @@ class XCode11LogParserTest(test_runner_test.TestCase): @mock.patch('subprocess.check_output', autospec=True) def testXcresulttoolGetRoot(self, mock_process): - mock_process.return_value = '%JSON%' + mock_process.return_value = b'%JSON%' xcode_log_parser.Xcode11LogParser()._xcresulttool_get('xcresult_path') self.assertTrue( os.path.join(XCODE11_DICT['path'], 'usr', 'bin') in os.environ['PATH']) @@ -445,7 +445,7 @@ class XCode11LogParserTest(test_runner_test.TestCase): @mock.patch('subprocess.check_output', autospec=True) def testXcresulttoolGetRef(self, mock_process): - mock_process.side_effect = [REF_ID, 'JSON'] + mock_process.side_effect = [REF_ID, b'JSON'] xcode_log_parser.Xcode11LogParser()._xcresulttool_get('xcresult_path', 'testsRef') self.assertEqual( diff --git a/ios/build/bots/scripts/xcode_util.py b/ios/build/bots/scripts/xcode_util.py index 008df06391199..41e60300f17b0 100644 --- a/ios/build/bots/scripts/xcode_util.py +++ b/ios/build/bots/scripts/xcode_util.py @@ -32,7 +32,8 @@ def _using_new_mac_toolchain(mac_toolchain): mac_toolchain, 'help', ] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + output = subprocess.check_output( + cmd, stderr=subprocess.STDOUT).decode('utf-8') # "install-runtime" presents as a command line switch in help output in the # new mac_toolchain. @@ -181,12 +182,14 @@ def select(xcode_app_path): xcode_app_path, ] LOGGER.debug('Selecting XCode with command %s and "xcrun simctl list".' % cmd) - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + output = subprocess.check_output( + cmd, stderr=subprocess.STDOUT).decode('utf-8') # This is to avoid issues caused by mixed usage of different Xcode versions on # one machine. xcrun_simctl_cmd = ['xcrun', 'simctl', 'list'] - output += subprocess.check_output(xcrun_simctl_cmd, stderr=subprocess.STDOUT) + output += subprocess.check_output( + xcrun_simctl_cmd, stderr=subprocess.STDOUT).decode('utf-8') return output @@ -316,15 +319,16 @@ def version(): ] LOGGER.debug('Checking XCode version with command: %s' % cmd) - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + output = subprocess.check_output( + cmd, stderr=subprocess.STDOUT).decode('utf-8') output = output.splitlines() # output sample: # Xcode 12.0 # Build version 12A6159 LOGGER.info(output) - version = output[0].decode('UTF-8').split(' ')[1] - build_version = output[1].decode('UTF-8').split(' ')[2].lower() + version = output[0].split(' ')[1] + build_version = output[1].split(' ')[2].lower() return version, build_version diff --git a/ios/build/bots/scripts/xcode_util_test.py b/ios/build/bots/scripts/xcode_util_test.py index a11541900ae8c..043c29ccbe555 100755 --- a/ios/build/bots/scripts/xcode_util_test.py +++ b/ios/build/bots/scripts/xcode_util_test.py @@ -14,10 +14,10 @@ import test_runner_test import xcode_util -_XCODEBUILD_VERSION_OUTPUT_12 = """Xcode 12.4 +_XCODEBUILD_VERSION_OUTPUT_12 = b"""Xcode 12.4 Build version 12D4e """ -_XCODEBUILD_VERSION_OUTPUT_13 = """Xcode 13.0 +_XCODEBUILD_VERSION_OUTPUT_13 = b"""Xcode 13.0 Build version 13A5155e """ @@ -189,7 +189,7 @@ class HelperFunctionTests(XcodeUtilTest): @mock.patch('subprocess.check_output', autospec=True) def test_using_new_mac_toolchain(self, mock_check_output): - mock_check_output.return_value = """ + mock_check_output.return_value = b""" Mac OS / iOS toolchain management Usage: mac_toolchain [command] [arguments] @@ -207,7 +207,7 @@ Use "mac_toolchain help [command]" for more information about a command.""" @mock.patch('subprocess.check_output', autospec=True) def test_using_new_legacy_toolchain(self, mock_check_output): - mock_check_output.return_value = """ + mock_check_output.return_value = b""" Mac OS / iOS toolchain management Usage: mac_toolchain [command] [arguments] diff --git a/ios/build/bots/scripts/xcodebuild_runner_test.py b/ios/build/bots/scripts/xcodebuild_runner_test.py index 67b5b61d623bf..38779460dfdc0 100755 --- a/ios/build/bots/scripts/xcodebuild_runner_test.py +++ b/ios/build/bots/scripts/xcodebuild_runner_test.py @@ -141,8 +141,8 @@ class DeviceXcodeTestRunnerTest(test_runner_test.TestCase): self.mock(result_sink_util.ResultSinkClient, 'post', lambda *args, **kwargs: None) - self.mock(test_runner.subprocess, 'check_output', lambda _: 'fake-output') - self.mock(test_runner.subprocess, 'check_call', lambda _: 'fake-out') + self.mock(test_runner.subprocess, 'check_output', lambda _: b'fake-output') + self.mock(test_runner.subprocess, 'check_call', lambda _: b'fake-out') self.mock(test_runner.subprocess, 'Popen', lambda cmd, env, stdout, stderr: 'fake-out') self.mock(test_runner.TestRunner, 'set_sigterm_handler',