Avi Drissman | dfd88085 | 2022-09-15 20:11:09 | [diff] [blame] | 1 | # Copyright 2012 The Chromium Authors |
[email protected] | a2387a0 | 2012-09-19 22:31:36 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
[email protected] | 09e151b | 2014-03-30 16:52:17 | [diff] [blame] | 4 | |
| 5 | """Presubmit script for changes affecting tools/perf/. |
| 6 | |
| 7 | See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
tfarina | 78bb92f4 | 2015-01-31 00:20:48 | [diff] [blame] | 8 | for more details about the presubmit API built into depot_tools. |
[email protected] | 09e151b | 2014-03-30 16:52:17 | [diff] [blame] | 9 | """ |
| 10 | |
[email protected] | a2387a0 | 2012-09-19 22:31:36 | [diff] [blame] | 11 | import os |
[email protected] | a2387a0 | 2012-09-19 22:31:36 | [diff] [blame] | 12 | |
Bruce Dawson | 1359067 | 2022-11-28 23:05:20 | [diff] [blame] | 13 | PRESUBMIT_VERSION = '2.0.0' |
| 14 | |
[email protected] | 7c97bc2 | 2013-08-03 01:39:38 | [diff] [blame] | 15 | |
Ashley Enstad | 5c8ad416 | 2018-02-16 16:45:23 | [diff] [blame] | 16 | def _CommonChecks(input_api, output_api, block_on_failure=False): |
Bruce Dawson | 35f8e8c2 | 2022-11-29 06:00:47 | [diff] [blame] | 17 | """Performs common checks that vary between commit and upload. |
Ashley Enstad | 5c8ad416 | 2018-02-16 16:45:23 | [diff] [blame] | 18 | |
| 19 | block_on_failure: For some failures, we would like to warn the |
| 20 | user but still allow them to upload the change. However, we |
| 21 | don't want them to commit code with those failures, so we |
| 22 | need to block the change on commit. |
| 23 | """ |
[email protected] | 67374a9 | 2012-10-05 05:48:11 | [diff] [blame] | 24 | results = [] |
nednguyen | 087ed2c | 2015-11-04 20:11:21 | [diff] [blame] | 25 | |
Ned Nguyen | aba7760 | 2018-06-29 20:46:39 | [diff] [blame] | 26 | results.extend( |
| 27 | _CheckPerfDataCurrentness(input_api, output_api, block_on_failure)) |
| 28 | results.extend( |
| 29 | _CheckPerfJsonConfigs(input_api, output_api, block_on_failure)) |
Caleb Rouleau | 0d3593c7 | 2019-05-17 00:47:24 | [diff] [blame] | 30 | results.extend(_CheckShardMaps(input_api, output_api, block_on_failure)) |
[email protected] | 67374a9 | 2012-10-05 05:48:11 | [diff] [blame] | 31 | return results |
[email protected] | a2387a0 | 2012-09-19 22:31:36 | [diff] [blame] | 32 | |
[email protected] | 7c97bc2 | 2013-08-03 01:39:38 | [diff] [blame] | 33 | |
Bruce Dawson | 1359067 | 2022-11-28 23:05:20 | [diff] [blame] | 34 | def CheckPyLint(input_api, output_api): |
| 35 | return input_api.RunTests( |
| 36 | input_api.canned_checks.GetPylint( |
| 37 | input_api, |
| 38 | output_api, |
| 39 | extra_paths_list=_GetPathsToPrepend(input_api), |
| 40 | pylintrc='pylintrc', |
| 41 | version='2.7')) |
| 42 | |
| 43 | |
nednguyen | 5919f7c | 2015-08-20 19:53:48 | [diff] [blame] | 44 | def _GetPathsToPrepend(input_api): |
| 45 | perf_dir = input_api.PresubmitLocalPath() |
| 46 | chromium_src_dir = input_api.os_path.join(perf_dir, '..', '..') |
aiolos | 285b8fdf | 2016-01-27 22:14:57 | [diff] [blame] | 47 | telemetry_dir = input_api.os_path.join( |
| 48 | chromium_src_dir, 'third_party', 'catapult', 'telemetry') |
Rakib M. Hasan | 6480326 | 2019-08-08 23:56:24 | [diff] [blame] | 49 | typ_dir = input_api.os_path.join( |
| 50 | chromium_src_dir, 'third_party', 'catapult', 'third_party', 'typ') |
wierichs | 05d6ac7 | 2016-03-04 06:43:55 | [diff] [blame] | 51 | experimental_dir = input_api.os_path.join( |
| 52 | chromium_src_dir, 'third_party', 'catapult', 'experimental') |
rnephew | aa1f961 | 2017-03-10 00:34:11 | [diff] [blame] | 53 | tracing_dir = input_api.os_path.join( |
| 54 | chromium_src_dir, 'third_party', 'catapult', 'tracing') |
nednguyen | 3e9cc4ae | 2017-08-01 16:19:10 | [diff] [blame] | 55 | py_utils_dir = input_api.os_path.join( |
| 56 | chromium_src_dir, 'third_party', 'catapult', 'common', 'py_utils') |
bsheedy | e95bb96 | 2017-08-17 16:48:54 | [diff] [blame] | 57 | android_pylib_dir = input_api.os_path.join( |
| 58 | chromium_src_dir, 'build', 'android') |
Xiyuan Xia | f9c2d70 | 2019-10-30 15:55:23 | [diff] [blame] | 59 | testing_dir = input_api.os_path.join(chromium_src_dir, 'testing') |
nednguyen | 5919f7c | 2015-08-20 19:53:48 | [diff] [blame] | 60 | return [ |
| 61 | telemetry_dir, |
Rakib M. Hasan | 6480326 | 2019-08-08 23:56:24 | [diff] [blame] | 62 | typ_dir, |
wierichs | 05d6ac7 | 2016-03-04 06:43:55 | [diff] [blame] | 63 | experimental_dir, |
rnephew | aa1f961 | 2017-03-10 00:34:11 | [diff] [blame] | 64 | tracing_dir, |
bsheedy | e95bb96 | 2017-08-17 16:48:54 | [diff] [blame] | 65 | py_utils_dir, |
| 66 | android_pylib_dir, |
Xiyuan Xia | f9c2d70 | 2019-10-30 15:55:23 | [diff] [blame] | 67 | testing_dir, |
nednguyen | 5919f7c | 2015-08-20 19:53:48 | [diff] [blame] | 68 | ] |
| 69 | |
| 70 | |
nednguyen | 292aea8 | 2017-02-23 19:06:00 | [diff] [blame] | 71 | def _RunArgs(args, input_api): |
| 72 | p = input_api.subprocess.Popen(args, stdout=input_api.subprocess.PIPE, |
| 73 | stderr=input_api.subprocess.STDOUT) |
| 74 | out, _ = p.communicate() |
| 75 | return (out, p.returncode) |
| 76 | |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 77 | def _RunValidationScript( |
| 78 | input_api, |
| 79 | output_api, |
| 80 | script_path, |
| 81 | extra_args = None, |
| 82 | block_on_failure = None): |
| 83 | results = [] |
Brian Sheedy | 91853fc | 2021-11-05 23:06:10 | [diff] [blame] | 84 | vpython = 'vpython3.bat' if input_api.is_windows else 'vpython3' |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 85 | perf_dir = input_api.PresubmitLocalPath() |
| 86 | script_abs_path = input_api.os_path.join(perf_dir, script_path) |
| 87 | extra_args = extra_args if extra_args else [] |
Bruce Dawson | 8b5adcd | 2022-04-03 00:51:04 | [diff] [blame] | 88 | # When running git cl presubmit --all this presubmit may be asked to check |
| 89 | # ~500 files, leading to a command line that is over 43,000 characters. |
| 90 | # This goes past the Windows 8191 character cmd.exe limit and causes cryptic |
| 91 | # failures. To avoid these we break the command up into smaller pieces. The |
| 92 | # non-Windows limit is chosen so that the code that splits up commands will |
| 93 | # get some exercise on other platforms. |
| 94 | # Depending on how long the command is on Windows the error may be: |
| 95 | # The command line is too long. |
| 96 | # Or it may be: |
| 97 | # OSError: Execution failed with error: [WinError 206] The filename or |
| 98 | # extension is too long. |
| 99 | # I suspect that the latter error comes from CreateProcess hitting its 32768 |
| 100 | # character limit. |
| 101 | files_per_command = 50 if input_api.is_windows else 1000 |
| 102 | # Handle the case where extra_args is empty. |
| 103 | for i in range(0, len(extra_args) if extra_args else 1, files_per_command): |
| 104 | args = [vpython, script_abs_path] + extra_args[i:i + files_per_command] |
| 105 | out, return_code = _RunArgs(args, input_api) |
| 106 | if return_code: |
| 107 | error_msg = 'Script ' + script_path + ' failed.' |
| 108 | if block_on_failure is None or block_on_failure: |
| 109 | results.append(output_api.PresubmitError(error_msg, long_text=out)) |
| 110 | else: |
| 111 | results.append( |
| 112 | output_api.PresubmitPromptWarning(error_msg, long_text=out)) |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 113 | return results |
nednguyen | 292aea8 | 2017-02-23 19:06:00 | [diff] [blame] | 114 | |
Bruce Dawson | 1359067 | 2022-11-28 23:05:20 | [diff] [blame] | 115 | |
| 116 | def CheckExpectations(input_api, output_api): |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 117 | return _RunValidationScript( |
| 118 | input_api, |
| 119 | output_api, |
| 120 | 'validate_story_expectation_data', |
| 121 | ) |
Ashley Enstad | f6f833b | 2017-11-03 19:18:48 | [diff] [blame] | 122 | |
Ned Nguyen | aba7760 | 2018-06-29 20:46:39 | [diff] [blame] | 123 | def _CheckPerfDataCurrentness(input_api, output_api, block_on_failure): |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 124 | return _RunValidationScript( |
| 125 | input_api, |
| 126 | output_api, |
| 127 | 'generate_perf_data', |
| 128 | ['--validate-only'], |
| 129 | block_on_failure |
| 130 | ) |
Ned Nguyen | aba7760 | 2018-06-29 20:46:39 | [diff] [blame] | 131 | |
| 132 | def _CheckPerfJsonConfigs(input_api, output_api, block_on_failure): |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 133 | return _RunValidationScript( |
| 134 | input_api, |
| 135 | output_api, |
| 136 | 'validate_perf_json_config', |
| 137 | ['--validate-only'], |
| 138 | block_on_failure |
| 139 | ) |
nednguyen | 292aea8 | 2017-02-23 19:06:00 | [diff] [blame] | 140 | |
Bruce Dawson | 1359067 | 2022-11-28 23:05:20 | [diff] [blame] | 141 | |
| 142 | def CheckWprShaFiles(input_api, output_api): |
nednguyen | 417ee8e | 2015-02-25 02:34:21 | [diff] [blame] | 143 | """Check whether the wpr sha files have matching URLs.""" |
nednguyen | 3e9cc4ae | 2017-08-01 16:19:10 | [diff] [blame] | 144 | wpr_archive_shas = [] |
nednguyen | 417ee8e | 2015-02-25 02:34:21 | [diff] [blame] | 145 | for affected_file in input_api.AffectedFiles(include_deletes=False): |
| 146 | filename = affected_file.AbsoluteLocalPath() |
nednguyen | 3e9cc4ae | 2017-08-01 16:19:10 | [diff] [blame] | 147 | if not filename.endswith('.sha1'): |
nednguyen | 417ee8e | 2015-02-25 02:34:21 | [diff] [blame] | 148 | continue |
nednguyen | 3e9cc4ae | 2017-08-01 16:19:10 | [diff] [blame] | 149 | wpr_archive_shas.append(filename) |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 150 | return _RunValidationScript( |
| 151 | input_api, |
| 152 | output_api, |
| 153 | 'validate_wpr_archives', |
| 154 | wpr_archive_shas |
| 155 | ) |
nednguyen | 417ee8e | 2015-02-25 02:34:21 | [diff] [blame] | 156 | |
Caleb Rouleau | 0d3593c7 | 2019-05-17 00:47:24 | [diff] [blame] | 157 | def _CheckShardMaps(input_api, output_api, block_on_failure): |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 158 | return _RunValidationScript( |
| 159 | input_api, |
| 160 | output_api, |
Caleb Rouleau | 9799662 | 2019-12-10 01:22:52 | [diff] [blame] | 161 | 'generate_perf_sharding.py', |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 162 | ['validate'], |
| 163 | block_on_failure |
| 164 | ) |
Caleb Rouleau | 0d3593c7 | 2019-05-17 00:47:24 | [diff] [blame] | 165 | |
Bruce Dawson | 1359067 | 2022-11-28 23:05:20 | [diff] [blame] | 166 | |
| 167 | def CheckJson(input_api, output_api): |
[email protected] | 09e151b | 2014-03-30 16:52:17 | [diff] [blame] | 168 | """Checks whether JSON files in this change can be parsed.""" |
[email protected] | faccd7e | 2014-04-01 23:05:19 | [diff] [blame] | 169 | for affected_file in input_api.AffectedFiles(include_deletes=False): |
| 170 | filename = affected_file.AbsoluteLocalPath() |
| 171 | if os.path.splitext(filename)[1] != '.json': |
| 172 | continue |
John Chen | 288dee0 | 2022-04-28 17:37:06 | [diff] [blame] | 173 | if (os.path.basename(filename) == 'perf_results.json' and |
| 174 | os.path.basename(os.path.dirname(filename)) == 'speedometer2-future'): |
| 175 | # Intentionally invalid JSON file. |
| 176 | continue |
[email protected] | 09e151b | 2014-03-30 16:52:17 | [diff] [blame] | 177 | try: |
Bruce Dawson | c4d1f41 | 2023-02-27 19:45:40 | [diff] [blame] | 178 | input_api.json.load(open(filename, encoding='utf-8')) |
[email protected] | 09e151b | 2014-03-30 16:52:17 | [diff] [blame] | 179 | except ValueError: |
| 180 | return [output_api.PresubmitError('Error parsing JSON in %s!' % filename)] |
| 181 | return [] |
| 182 | |
Bruce Dawson | 1359067 | 2022-11-28 23:05:20 | [diff] [blame] | 183 | |
| 184 | def CheckVersionsInSmokeTests(input_api, output_api): |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 185 | return _RunValidationScript( |
| 186 | input_api, |
| 187 | output_api, |
Wenbin Zhang | a903f879 | 2019-10-11 04:45:54 | [diff] [blame] | 188 | input_api.os_path.join( |
Wenbin Zhang | 80cd5a54 | 2019-10-15 22:29:54 | [diff] [blame] | 189 | 'benchmarks', 'system_health_load_tests_smoke_test.py'), |
| 190 | ) |
[email protected] | 09e151b | 2014-03-30 16:52:17 | [diff] [blame] | 191 | |
[email protected] | 67374a9 | 2012-10-05 05:48:11 | [diff] [blame] | 192 | def CheckChangeOnUpload(input_api, output_api): |
| 193 | report = [] |
| 194 | report.extend(_CommonChecks(input_api, output_api)) |
| 195 | return report |
| 196 | |
[email protected] | 7c97bc2 | 2013-08-03 01:39:38 | [diff] [blame] | 197 | |
[email protected] | 67374a9 | 2012-10-05 05:48:11 | [diff] [blame] | 198 | def CheckChangeOnCommit(input_api, output_api): |
| 199 | report = [] |
Ashley Enstad | 5c8ad416 | 2018-02-16 16:45:23 | [diff] [blame] | 200 | report.extend(_CommonChecks(input_api, output_api, block_on_failure=True)) |
[email protected] | a2387a0 | 2012-09-19 22:31:36 | [diff] [blame] | 201 | return report |