blob: 9c870720728967719d7a9aa2ac3e3128ee6ee83d [file] [log] [blame]
Hector Dearman534765e2017-11-01 11:17:38 +00001# Copyright (C) 2017 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
Hector Dearman2cc71f62021-07-14 10:28:58 +010015from __future__ import print_function
Florian Mayer640b7ae2018-05-09 15:28:32 +010016import itertools
Sami Kyostilab27619f2017-12-13 19:22:16 +000017import subprocess
Hector Dearman2cc71f62021-07-14 10:28:58 +010018import time
19
20
21def RunAndReportIfLong(func, *args, **kargs):
22 start = time.time()
23 results = func(*args, **kargs)
24 end = time.time()
25 limit = 0.5 # seconds
26 name = func.__name__
27 runtime = end - start
28 if runtime > limit:
29 print("{} took >{:.2}s ({:.2}s)".format(name, limit, runtime))
30 return results
Sami Kyostilab27619f2017-12-13 19:22:16 +000031
Primiano Tuccibf3b19c2019-06-01 08:40:26 +010032
Hector Dearman534765e2017-11-01 11:17:38 +000033def CheckChange(input, output):
Primiano Tuccibf3b19c2019-06-01 08:40:26 +010034 # There apparently is no way to wrap strings in blueprints, so ignore long
35 # lines in them.
Primiano Tucci834fdc72019-10-04 11:33:44 +010036 def long_line_sources(x):
37 return input.FilterSourceFile(
38 x,
Ryan Savitski135038e2020-11-12 20:57:57 +000039 files_to_check='.*',
40 files_to_skip=[
Lalit Maganti3dc0ffe2021-06-09 13:27:52 +010041 'Android[.]bp',
42 '.*[.]json$',
43 '.*[.]sql$',
44 '.*[.]out$',
45 'test/trace_processor/.*/index$',
46 '(.*/)?BUILD$',
47 'WORKSPACE',
48 '.*/Makefile$',
49 '/perfetto_build_flags.h$',
50 "infra/luci/.*",
Primiano Tucci834fdc72019-10-04 11:33:44 +010051 ])
52
Primiano Tuccibf3b19c2019-06-01 08:40:26 +010053 results = []
Hector Dearman2cc71f62021-07-14 10:28:58 +010054 results += RunAndReportIfLong(input.canned_checks.CheckDoNotSubmit, input,
55 output)
56 results += RunAndReportIfLong(input.canned_checks.CheckChangeHasNoTabs, input,
57 output)
58 results += RunAndReportIfLong(
59 input.canned_checks.CheckLongLines,
60 input,
61 output,
62 80,
63 source_file_filter=long_line_sources)
64 results += RunAndReportIfLong(
65 input.canned_checks.CheckPatchFormatted, input, output, check_js=True)
66 results += RunAndReportIfLong(input.canned_checks.CheckGNFormatted, input,
67 output)
68 results += RunAndReportIfLong(CheckIncludeGuards, input, output)
69 results += RunAndReportIfLong(CheckIncludeViolations, input, output)
70 results += RunAndReportIfLong(CheckProtoComments, input, output)
71 results += RunAndReportIfLong(CheckBuild, input, output)
72 results += RunAndReportIfLong(CheckAndroidBlueprint, input, output)
73 results += RunAndReportIfLong(CheckBinaryDescriptors, input, output)
74 results += RunAndReportIfLong(CheckMergedTraceConfigProto, input, output)
75 results += RunAndReportIfLong(CheckProtoEventList, input, output)
76 results += RunAndReportIfLong(CheckBannedCpp, input, output)
77 results += RunAndReportIfLong(CheckSqlMetrics, input, output)
Primiano Tucci3d4217d2021-11-05 11:11:51 +000078 results += RunAndReportIfLong(CheckTestData, input, output)
Primiano Tuccibf3b19c2019-06-01 08:40:26 +010079 return results
Hector Dearman534765e2017-11-01 11:17:38 +000080
Sami Kyostilab27619f2017-12-13 19:22:16 +000081
Hector Dearman534765e2017-11-01 11:17:38 +000082def CheckChangeOnUpload(input_api, output_api):
Primiano Tuccibf3b19c2019-06-01 08:40:26 +010083 return CheckChange(input_api, output_api)
Hector Dearman534765e2017-11-01 11:17:38 +000084
Sami Kyostilab27619f2017-12-13 19:22:16 +000085
Hector Dearman534765e2017-11-01 11:17:38 +000086def CheckChangeOnCommit(input_api, output_api):
Primiano Tuccibf3b19c2019-06-01 08:40:26 +010087 return CheckChange(input_api, output_api)
Hector Dearman534765e2017-11-01 11:17:38 +000088
Sami Kyostilab27619f2017-12-13 19:22:16 +000089
Lalit Maganti279ecde2019-04-01 16:57:12 +010090def CheckBuild(input_api, output_api):
Primiano Tucci9c411652019-08-27 07:13:59 +020091 tool = 'tools/gen_bazel'
Primiano Tucci834fdc72019-10-04 11:33:44 +010092
Primiano Tuccibf3b19c2019-06-01 08:40:26 +010093 # If no GN files were modified, bail out.
Primiano Tucci834fdc72019-10-04 11:33:44 +010094 def build_file_filter(x):
95 return input_api.FilterSourceFile(
Ryan Savitski135038e2020-11-12 20:57:57 +000096 x, files_to_check=('.*BUILD[.]gn$', '.*[.]gni$', 'BUILD\.extras', tool))
Primiano Tucci834fdc72019-10-04 11:33:44 +010097
Primiano Tuccibf3b19c2019-06-01 08:40:26 +010098 if not input_api.AffectedSourceFiles(build_file_filter):
Lalit Maganti279ecde2019-04-01 16:57:12 +010099 return []
Primiano Tucci9c411652019-08-27 07:13:59 +0200100 if subprocess.call([tool, '--check-only']):
Primiano Tucci834fdc72019-10-04 11:33:44 +0100101 return [
102 output_api.PresubmitError('Bazel BUILD(s) are out of date. Run ' +
103 tool + ' to update them.')
104 ]
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100105 return []
106
Lalit Maganti279ecde2019-04-01 16:57:12 +0100107
Sami Kyostilab27619f2017-12-13 19:22:16 +0000108def CheckAndroidBlueprint(input_api, output_api):
Primiano Tucci9c411652019-08-27 07:13:59 +0200109 tool = 'tools/gen_android_bp'
Primiano Tucci834fdc72019-10-04 11:33:44 +0100110
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100111 # If no GN files were modified, bail out.
Primiano Tucci834fdc72019-10-04 11:33:44 +0100112 def build_file_filter(x):
113 return input_api.FilterSourceFile(
Ryan Savitski135038e2020-11-12 20:57:57 +0000114 x, files_to_check=('.*BUILD[.]gn$', '.*[.]gni$', tool))
Primiano Tucci834fdc72019-10-04 11:33:44 +0100115
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100116 if not input_api.AffectedSourceFiles(build_file_filter):
Sami Kyostilab27619f2017-12-13 19:22:16 +0000117 return []
Primiano Tucci9c411652019-08-27 07:13:59 +0200118 if subprocess.call([tool, '--check-only']):
Primiano Tucci834fdc72019-10-04 11:33:44 +0100119 return [
120 output_api.PresubmitError('Android build files are out of date. ' +
121 'Run ' + tool + ' to update them.')
122 ]
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100123 return []
124
Primiano Tuccic5010802018-01-19 17:13:21 +0000125
Primiano Tucci40e98722018-02-16 11:50:17 +0000126def CheckIncludeGuards(input_api, output_api):
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100127 tool = 'tools/fix_include_guards'
128
Primiano Tucci834fdc72019-10-04 11:33:44 +0100129 def file_filter(x):
130 return input_api.FilterSourceFile(
Ryan Savitski135038e2020-11-12 20:57:57 +0000131 x, files_to_check=['.*[.]cc$', '.*[.]h$', tool])
Primiano Tucci834fdc72019-10-04 11:33:44 +0100132
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100133 if not input_api.AffectedSourceFiles(file_filter):
Primiano Tucci40e98722018-02-16 11:50:17 +0000134 return []
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100135 if subprocess.call([tool, '--check-only']):
136 return [
Primiano Tucci834fdc72019-10-04 11:33:44 +0100137 output_api.PresubmitError('Please run ' + tool +
138 ' to fix include guards.')
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100139 ]
140 return []
141
142
Ryan704bc822020-03-31 02:31:13 +0100143def CheckBannedCpp(input_api, output_api):
Hector Dearman53d91b92019-12-13 17:07:52 +0000144 bad_cpp = [
Hector Dearman53d91b92019-12-13 17:07:52 +0000145 (r'\bstd::stoi\b',
146 'std::stoi throws exceptions prefer base::StringToInt32()'),
147 (r'\bstd::stol\b',
148 'std::stoull throws exceptions prefer base::StringToInt32()'),
149 (r'\bstd::stoul\b',
150 'std::stoull throws exceptions prefer base::StringToUint32()'),
151 (r'\bstd::stoll\b',
152 'std::stoull throws exceptions prefer base::StringToInt64()'),
153 (r'\bstd::stoull\b',
154 'std::stoull throws exceptions prefer base::StringToUint64()'),
155 (r'\bstd::stof\b',
156 'std::stof throws exceptions prefer base::StringToDouble()'),
157 (r'\bstd::stod\b',
158 'std::stod throws exceptions prefer base::StringToDouble()'),
159 (r'\bstd::stold\b',
160 'std::stold throws exceptions prefer base::StringToDouble()'),
Primiano Tucci78cd82b2021-10-13 13:50:27 +0100161 (r'\bstrncpy\b',
162 'strncpy does not null-terminate if src > dst. Use base::StringCopy'),
163 (r'[(=]\s*snprintf\(',
164 'snprintf can return > dst_size. Use base::SprintfTrunc'),
Primiano Tucci997ab092021-10-18 20:53:35 +0100165 (r'//.*\bDNS\b',
166 '// DNS (Do Not Ship) found. Did you mean to remove some testing code?'),
Ryan704bc822020-03-31 02:31:13 +0100167 (r'\bPERFETTO_EINTR\(close\(',
168 'close(2) must not be retried on EINTR on Linux and other OSes '
169 'that we run on, as the fd will be closed.'),
Primiano Tucci58d2dc62021-06-24 16:03:24 +0100170 (r'^#include <inttypes.h>', 'Use <cinttypes> rather than <inttypes.h>. ' +
171 'See https://github.com/google/perfetto/issues/146'),
Hector Dearman53d91b92019-12-13 17:07:52 +0000172 ]
173
174 def file_filter(x):
Ryan Savitski135038e2020-11-12 20:57:57 +0000175 return input_api.FilterSourceFile(x, files_to_check=[r'.*\.h$', r'.*\.cc$'])
Hector Dearman53d91b92019-12-13 17:07:52 +0000176
177 errors = []
178 for f in input_api.AffectedSourceFiles(file_filter):
179 for line_number, line in f.ChangedContents():
Primiano Tucci78cd82b2021-10-13 13:50:27 +0100180 if input_api.re.search(r'^\s*//', line):
181 continue # Skip comments
Hector Dearman53d91b92019-12-13 17:07:52 +0000182 for regex, message in bad_cpp:
183 if input_api.re.search(regex, line):
184 errors.append(
Ryan704bc822020-03-31 02:31:13 +0100185 output_api.PresubmitError('Banned pattern:\n {}:{} {}'.format(
Hector Dearman53d91b92019-12-13 17:07:52 +0000186 f.LocalPath(), line_number, message)))
187 return errors
188
189
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100190def CheckIncludeViolations(input_api, output_api):
191 tool = 'tools/check_include_violations'
192
Primiano Tucci834fdc72019-10-04 11:33:44 +0100193 def file_filter(x):
Ryan Savitski135038e2020-11-12 20:57:57 +0000194 return input_api.FilterSourceFile(
195 x, files_to_check=['include/.*[.]h$', tool])
Primiano Tucci834fdc72019-10-04 11:33:44 +0100196
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100197 if not input_api.AffectedSourceFiles(file_filter):
198 return []
199 if subprocess.call([tool]):
200 return [output_api.PresubmitError(tool + ' failed.')]
201 return []
Primiano Tucci40e98722018-02-16 11:50:17 +0000202
203
Hector Dearmanb7fa5442018-11-08 18:39:32 +0000204def CheckBinaryDescriptors(input_api, output_api):
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100205 tool = 'tools/gen_binary_descriptors'
206
Primiano Tucci834fdc72019-10-04 11:33:44 +0100207 def file_filter(x):
208 return input_api.FilterSourceFile(
Ryan Savitski135038e2020-11-12 20:57:57 +0000209 x, files_to_check=['protos/perfetto/.*[.]proto$', '.*[.]h', tool])
Primiano Tucci834fdc72019-10-04 11:33:44 +0100210
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100211 if not input_api.AffectedSourceFiles(file_filter):
Hector Dearmanb7fa5442018-11-08 18:39:32 +0000212 return []
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100213 if subprocess.call([tool, '--check-only']):
214 return [
Primiano Tucci834fdc72019-10-04 11:33:44 +0100215 output_api.PresubmitError('Please run ' + tool +
216 ' to update binary descriptors.')
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100217 ]
218 return []
Hector Dearmanb7fa5442018-11-08 18:39:32 +0000219
220
Primiano Tuccic5010802018-01-19 17:13:21 +0000221def CheckMergedTraceConfigProto(input_api, output_api):
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100222 tool = 'tools/gen_merged_protos'
223
Primiano Tucci834fdc72019-10-04 11:33:44 +0100224 def build_file_filter(x):
225 return input_api.FilterSourceFile(
Ryan Savitski135038e2020-11-12 20:57:57 +0000226 x, files_to_check=['protos/perfetto/.*[.]proto$', tool])
Primiano Tucci834fdc72019-10-04 11:33:44 +0100227
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100228 if not input_api.AffectedSourceFiles(build_file_filter):
Primiano Tuccic5010802018-01-19 17:13:21 +0000229 return []
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100230 if subprocess.call([tool, '--check-only']):
231 return [
232 output_api.PresubmitError(
233 'perfetto_config.proto or perfetto_trace.proto is out of ' +
234 'date. Please run ' + tool + ' to update it.')
235 ]
236 return []
Florian Mayer640b7ae2018-05-09 15:28:32 +0100237
238
Primiano Tuccia3645202020-08-03 16:28:18 +0200239# Prevent removing or changing lines in event_list.
240def CheckProtoEventList(input_api, output_api):
Florian Mayer640b7ae2018-05-09 15:28:32 +0100241 for f in input_api.AffectedFiles():
Primiano Tuccia3645202020-08-03 16:28:18 +0200242 if f.LocalPath() != 'tools/ftrace_proto_gen/event_list':
Florian Mayer640b7ae2018-05-09 15:28:32 +0100243 continue
Primiano Tucci834fdc72019-10-04 11:33:44 +0100244 if any((not new_line.startswith('removed')) and new_line != old_line
245 for old_line, new_line in itertools.izip(f.OldContents(),
246 f.NewContents())):
Florian Mayer640b7ae2018-05-09 15:28:32 +0100247 return [
Primiano Tuccibf3b19c2019-06-01 08:40:26 +0100248 output_api.PresubmitError(
Primiano Tuccia3645202020-08-03 16:28:18 +0200249 'event_list only has two supported changes: '
Primiano Tucci834fdc72019-10-04 11:33:44 +0100250 'appending a new line, and replacing a line with removed.')
Florian Mayer640b7ae2018-05-09 15:28:32 +0100251 ]
252 return []
Anindita Ghosh2aa4e422020-06-26 15:48:32 +0100253
254
255def CheckProtoComments(input_api, output_api):
256 tool = 'tools/check_proto_comments'
257
258 def file_filter(x):
259 return input_api.FilterSourceFile(
Ryan Savitski135038e2020-11-12 20:57:57 +0000260 x, files_to_check=['protos/perfetto/.*[.]proto$', tool])
Anindita Ghosh2aa4e422020-06-26 15:48:32 +0100261
262 if not input_api.AffectedSourceFiles(file_filter):
263 return []
264 if subprocess.call([tool]):
265 return [output_api.PresubmitError(tool + ' failed')]
266 return []
Lalit Magantie0e8bdb2021-01-11 19:43:55 +0000267
268
269def CheckSqlMetrics(input_api, output_api):
270 tool = 'tools/check_sql_metrics.py'
271
272 def file_filter(x):
273 return input_api.FilterSourceFile(
274 x, files_to_check=['src/trace_processor/metrics/.*[.]sql$', tool])
275
276 if not input_api.AffectedSourceFiles(file_filter):
277 return []
278 if subprocess.call([tool]):
279 return [output_api.PresubmitError(tool + ' failed')]
280 return []
Primiano Tucci3d4217d2021-11-05 11:11:51 +0000281
282
283def CheckTestData(input_api, output_api):
284 tool = 'tools/test_data'
285 if subprocess.call([tool, 'status', '--quiet']):
286 return [
287 output_api.PresubmitError(
288 '//test/data is out of sync. Run ' + tool + ' status for more. \n' +
289 'If you rebaselined UI tests or added a new test trace, run: \n' +
290 'tools/test_data upload')
291 ]
292 return []