blob: 03a77b28681d9df9e72559a4d71c3418159661dc [file] [log] [blame]
andrew@webrtc.org2442de12012-01-23 17:45:41 +00001# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
2#
3# Use of this source code is governed by a BSD-style license
4# that can be found in the LICENSE file in the root of the source
5# tree. An additional intellectual property rights grant can be found
6# in the file PATENTS. All contributing project authors may
7# be found in the AUTHORS file in the root of the source tree.
niklase@google.comda159d62011-05-30 11:51:34 +00008
kjellander7439f972016-12-05 22:47:46 -08009import json
kjellander@webrtc.orgaefe61a2014-12-08 13:00:30 +000010import os
kjellander@webrtc.org85759802013-10-22 16:47:40 +000011import re
ehmaldonado4fb97462017-01-30 05:27:22 -080012import subprocess
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +000013import sys
kjellander@webrtc.org85759802013-10-22 16:47:40 +000014
15
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010016# Directories that will be scanned by cpplint by the presubmit script.
17CPPLINT_DIRS = [
oprypin803dc292017-02-01 01:55:59 -080018 'webrtc/api',
Fredrik Solenbergea073732015-12-01 11:26:34 +010019 'webrtc/audio',
20 'webrtc/call',
oprypin67fdb802017-03-09 06:25:06 -080021 'webrtc/common_audio',
jbauch0f2e9392015-12-10 03:11:42 -080022 'webrtc/common_video',
jbauch70625e52015-12-09 14:18:14 -080023 'webrtc/examples',
aleloidf9e4d92016-08-08 10:26:09 -070024 'webrtc/modules/audio_mixer',
jbauchf91e6d02016-01-24 23:05:21 -080025 'webrtc/modules/bitrate_controller',
Stefan Holmer80e12072016-02-23 13:30:42 +010026 'webrtc/modules/congestion_controller',
jbauchd2a22962016-02-08 23:18:25 -080027 'webrtc/modules/pacing',
terelius8f09f172015-12-15 00:51:54 -080028 'webrtc/modules/remote_bitrate_estimator',
danilchap377b5e62015-12-15 04:33:44 -080029 'webrtc/modules/rtp_rtcp',
philipel5908c712015-12-21 08:23:20 -080030 'webrtc/modules/video_coding',
mflodman88eeac42015-12-08 09:21:28 +010031 'webrtc/modules/video_processing',
jbauch0f2e9392015-12-10 03:11:42 -080032 'webrtc/tools',
mflodmand1590b22015-12-09 07:07:59 -080033 'webrtc/video',
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010034]
35
jbauchc4e3ead2016-02-19 00:25:55 -080036# These filters will always be removed, even if the caller specifies a filter
37# set, as they are problematic or broken in some way.
38#
39# Justifications for each filter:
40# - build/c++11 : Rvalue ref checks are unreliable (false positives),
41# include file and feature blacklists are
42# google3-specific.
kjellandere5a87a52016-04-27 02:32:12 -070043# - whitespace/operators: Same as above (doesn't seem sufficient to eliminate
44# all move-related errors).
jbauchc4e3ead2016-02-19 00:25:55 -080045BLACKLIST_LINT_FILTERS = [
46 '-build/c++11',
kjellandere5a87a52016-04-27 02:32:12 -070047 '-whitespace/operators',
jbauchc4e3ead2016-02-19 00:25:55 -080048]
49
kjellanderfd595232015-12-04 02:44:09 -080050# List of directories of "supported" native APIs. That means changes to headers
51# will be done in a compatible way following this scheme:
52# 1. Non-breaking changes are made.
53# 2. The old APIs as marked as deprecated (with comments).
54# 3. Deprecation is announced to discuss-webrtc@googlegroups.com and
55# webrtc-users@google.com (internal list).
56# 4. (later) The deprecated APIs are removed.
kjellander53047c92015-12-02 23:56:14 -080057NATIVE_API_DIRS = (
kjellander53047c92015-12-02 23:56:14 -080058 'webrtc',
kjellanderdd705472016-06-09 11:17:27 -070059 'webrtc/api',
60 'webrtc/media',
kjellander53047c92015-12-02 23:56:14 -080061 'webrtc/modules/audio_device/include',
kjellanderdd705472016-06-09 11:17:27 -070062 'webrtc/pc',
63)
64# These directories should not be used but are maintained only to avoid breaking
65# some legacy downstream code.
66LEGACY_API_DIRS = (
kjellanderdd705472016-06-09 11:17:27 -070067 'webrtc/base',
68 'webrtc/common_audio/include',
69 'webrtc/modules/audio_coding/include',
70 'webrtc/modules/audio_conference_mixer/include',
kjellander53047c92015-12-02 23:56:14 -080071 'webrtc/modules/audio_processing/include',
72 'webrtc/modules/bitrate_controller/include',
Stefan Holmer80e12072016-02-23 13:30:42 +010073 'webrtc/modules/congestion_controller/include',
kjellander53047c92015-12-02 23:56:14 -080074 'webrtc/modules/include',
75 'webrtc/modules/remote_bitrate_estimator/include',
76 'webrtc/modules/rtp_rtcp/include',
kjellanderdd705472016-06-09 11:17:27 -070077 'webrtc/modules/rtp_rtcp/source',
kjellander53047c92015-12-02 23:56:14 -080078 'webrtc/modules/utility/include',
79 'webrtc/modules/video_coding/codecs/h264/include',
80 'webrtc/modules/video_coding/codecs/i420/include',
81 'webrtc/modules/video_coding/codecs/vp8/include',
82 'webrtc/modules/video_coding/codecs/vp9/include',
83 'webrtc/modules/video_coding/include',
kjellanderdd705472016-06-09 11:17:27 -070084 'webrtc/system_wrappers/include',
kjellander53047c92015-12-02 23:56:14 -080085 'webrtc/voice_engine/include',
86)
kjellanderdd705472016-06-09 11:17:27 -070087API_DIRS = NATIVE_API_DIRS[:] + LEGACY_API_DIRS[:]
kjellander53047c92015-12-02 23:56:14 -080088
89
ehmaldonado4fb97462017-01-30 05:27:22 -080090def _RunCommand(command, cwd):
91 """Runs a command and returns the output from that command."""
92 p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
93 cwd=cwd)
94 stdout = p.stdout.read()
95 stderr = p.stderr.read()
96 p.wait()
97 p.stdout.close()
98 p.stderr.close()
99 return p.returncode, stdout, stderr
100
101
kjellander53047c92015-12-02 23:56:14 -0800102def _VerifyNativeApiHeadersListIsValid(input_api, output_api):
103 """Ensures the list of native API header directories is up to date."""
104 non_existing_paths = []
105 native_api_full_paths = [
106 input_api.os_path.join(input_api.PresubmitLocalPath(),
kjellanderdd705472016-06-09 11:17:27 -0700107 *path.split('/')) for path in API_DIRS]
kjellander53047c92015-12-02 23:56:14 -0800108 for path in native_api_full_paths:
109 if not os.path.isdir(path):
110 non_existing_paths.append(path)
111 if non_existing_paths:
112 return [output_api.PresubmitError(
113 'Directories to native API headers have changed which has made the '
114 'list in PRESUBMIT.py outdated.\nPlease update it to the current '
115 'location of our native APIs.',
116 non_existing_paths)]
117 return []
118
kjellander94f4d9e2017-03-09 06:09:33 -0800119api_change_msg = """
kwibergeb133022016-04-07 07:41:48 -0700120You seem to be changing native API header files. Please make sure that you:
oprypin375b9ac2017-02-13 04:13:23 -0800121 1. Make compatible changes that don't break existing clients. Usually
122 this is done by keeping the existing method signatures unchanged.
123 2. Mark the old stuff as deprecated (see RTC_DEPRECATED macro).
kwibergeb133022016-04-07 07:41:48 -0700124 3. Create a timeline and plan for when the deprecated stuff will be
125 removed. (The amount of time we give users to change their code
126 should be informed by how much work it is for them. If they just
127 need to replace one name with another or something equally
128 simple, 1-2 weeks might be good; if they need to do serious work,
129 up to 3 months may be called for.)
130 4. Update/inform existing downstream code owners to stop using the
131 deprecated stuff. (Send announcements to
132 discuss-webrtc@googlegroups.com and webrtc-users@google.com.)
133 5. Remove the deprecated stuff, once the agreed-upon amount of time
134 has passed.
135Related files:
136"""
kjellander53047c92015-12-02 23:56:14 -0800137
138def _CheckNativeApiHeaderChanges(input_api, output_api):
139 """Checks to remind proper changing of native APIs."""
140 files = []
141 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
142 if f.LocalPath().endswith('.h'):
kjellanderdd705472016-06-09 11:17:27 -0700143 for path in API_DIRS:
kjellander53047c92015-12-02 23:56:14 -0800144 if os.path.dirname(f.LocalPath()) == path:
145 files.append(f)
146
147 if files:
kjellander94f4d9e2017-03-09 06:09:33 -0800148 return [output_api.PresubmitNotifyResult(api_change_msg, files)]
kjellander53047c92015-12-02 23:56:14 -0800149 return []
150
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100151
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000152def _CheckNoIOStreamInHeaders(input_api, output_api):
153 """Checks to make sure no .h files include <iostream>."""
154 files = []
155 pattern = input_api.re.compile(r'^#include\s*<iostream>',
156 input_api.re.MULTILINE)
157 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
158 if not f.LocalPath().endswith('.h'):
159 continue
160 contents = input_api.ReadFile(f)
161 if pattern.search(contents):
162 files.append(f)
163
164 if len(files):
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200165 return [output_api.PresubmitError(
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000166 'Do not #include <iostream> in header files, since it inserts static ' +
167 'initialization into every file including the header. Instead, ' +
168 '#include <ostream>. See http://crbug.com/94794',
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200169 files)]
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000170 return []
171
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000172
kjellander6aeef742017-02-20 01:13:18 -0800173def _CheckNoPragmaOnce(input_api, output_api):
174 """Make sure that banned functions are not used."""
175 files = []
176 pattern = input_api.re.compile(r'^#pragma\s+once',
177 input_api.re.MULTILINE)
178 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
179 if not f.LocalPath().endswith('.h'):
180 continue
181 contents = input_api.ReadFile(f)
182 if pattern.search(contents):
183 files.append(f)
184
185 if files:
186 return [output_api.PresubmitError(
187 'Do not use #pragma once in header files.\n'
188 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
189 files)]
190 return []
191
192
kjellander94f4d9e2017-03-09 06:09:33 -0800193def _CheckNoFRIEND_TEST(input_api, output_api):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000194 """Make sure that gtest's FRIEND_TEST() macro is not used, the
195 FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be
196 used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes."""
197 problems = []
198
199 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.h'))
200 for f in input_api.AffectedFiles(file_filter=file_filter):
201 for line_num, line in f.ChangedContents():
202 if 'FRIEND_TEST(' in line:
203 problems.append(' %s:%d' % (f.LocalPath(), line_num))
204
205 if not problems:
206 return []
207 return [output_api.PresubmitPromptWarning('WebRTC\'s code should not use '
208 'gtest\'s FRIEND_TEST() macro. Include testsupport/gtest_prod_util.h and '
209 'use FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems))]
210
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000211
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100212def _IsLintWhitelisted(whitelist_dirs, file_path):
213 """ Checks if a file is whitelisted for lint check."""
214 for path in whitelist_dirs:
215 if os.path.dirname(file_path).startswith(path):
216 return True
217 return False
218
219
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000220def _CheckApprovedFilesLintClean(input_api, output_api,
221 source_file_filter=None):
222 """Checks that all new or whitelisted .cc and .h files pass cpplint.py.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000223 This check is based on _CheckChangeLintsClean in
224 depot_tools/presubmit_canned_checks.py but has less filters and only checks
225 added files."""
226 result = []
227
228 # Initialize cpplint.
229 import cpplint
230 # Access to a protected member _XX of a client class
231 # pylint: disable=W0212
232 cpplint._cpplint_state.ResetErrorCounts()
233
jbauchc4e3ead2016-02-19 00:25:55 -0800234 lint_filters = cpplint._Filters()
235 lint_filters.extend(BLACKLIST_LINT_FILTERS)
236 cpplint._SetFilters(','.join(lint_filters))
237
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100238 # Create a platform independent whitelist for the CPPLINT_DIRS.
239 whitelist_dirs = [input_api.os_path.join(*path.split('/'))
240 for path in CPPLINT_DIRS]
241
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000242 # Use the strictest verbosity level for cpplint.py (level 1) which is the
243 # default when running cpplint.py from command line.
244 # To make it possible to work with not-yet-converted code, we're only applying
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000245 # it to new (or moved/renamed) files and files listed in LINT_FOLDERS.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000246 verbosity_level = 1
247 files = []
248 for f in input_api.AffectedSourceFiles(source_file_filter):
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200249 # Note that moved/renamed files also count as added.
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100250 if f.Action() == 'A' or _IsLintWhitelisted(whitelist_dirs, f.LocalPath()):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000251 files.append(f.AbsoluteLocalPath())
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000252
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000253 for file_name in files:
254 cpplint.ProcessFile(file_name, verbosity_level)
255
256 if cpplint._cpplint_state.error_count > 0:
257 if input_api.is_committing:
oprypin8e58d652017-03-21 07:52:41 -0700258 res_type = output_api.PresubmitError
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000259 else:
260 res_type = output_api.PresubmitPromptWarning
261 result = [res_type('Changelist failed cpplint.py check.')]
262
263 return result
264
Henrik Kjellanderb4af3d62016-11-16 20:11:29 +0100265def _CheckNoSourcesAbove(input_api, gn_files, output_api):
ehmaldonado5b1ba082016-09-02 05:51:08 -0700266 # Disallow referencing source files with paths above the GN file location.
267 source_pattern = input_api.re.compile(r' +sources \+?= \[(.*?)\]',
268 re.MULTILINE | re.DOTALL)
269 file_pattern = input_api.re.compile(r'"((\.\./.*?)|(//.*?))"')
270 violating_gn_files = set()
271 violating_source_entries = []
272 for gn_file in gn_files:
273 contents = input_api.ReadFile(gn_file)
274 for source_block_match in source_pattern.finditer(contents):
275 # Find all source list entries starting with ../ in the source block
276 # (exclude overrides entries).
277 for file_list_match in file_pattern.finditer(source_block_match.group(1)):
278 source_file = file_list_match.group(1)
279 if 'overrides/' not in source_file:
280 violating_source_entries.append(source_file)
281 violating_gn_files.add(gn_file)
282 if violating_gn_files:
283 return [output_api.PresubmitError(
284 'Referencing source files above the directory of the GN file is not '
Henrik Kjellanderb4af3d62016-11-16 20:11:29 +0100285 'allowed. Please introduce new GN targets in the proper location '
286 'instead.\n'
ehmaldonado5b1ba082016-09-02 05:51:08 -0700287 'Invalid source entries:\n'
288 '%s\n'
289 'Violating GN files:' % '\n'.join(violating_source_entries),
290 items=violating_gn_files)]
291 return []
292
kjellander7439f972016-12-05 22:47:46 -0800293def _CheckNoMixingCAndCCSources(input_api, gn_files, output_api):
294 # Disallow mixing .c and .cc source files in the same target.
295 source_pattern = input_api.re.compile(r' +sources \+?= \[(.*?)\]',
296 re.MULTILINE | re.DOTALL)
297 file_pattern = input_api.re.compile(r'"(.*)"')
298 violating_gn_files = dict()
299 for gn_file in gn_files:
300 contents = input_api.ReadFile(gn_file)
301 for source_block_match in source_pattern.finditer(contents):
302 c_files = []
303 cc_files = []
304 for file_list_match in file_pattern.finditer(source_block_match.group(1)):
305 source_file = file_list_match.group(1)
306 if source_file.endswith('.c'):
307 c_files.append(source_file)
308 if source_file.endswith('.cc'):
309 cc_files.append(source_file)
310 if c_files and cc_files:
311 violating_gn_files[gn_file.LocalPath()] = sorted(c_files + cc_files)
312 if violating_gn_files:
313 return [output_api.PresubmitError(
314 'GN targets cannot mix .cc and .c source files. Please create a '
315 'separate target for each collection of sources.\n'
316 'Mixed sources: \n'
317 '%s\n'
318 'Violating GN files:' % json.dumps(violating_gn_files, indent=2),
319 items=violating_gn_files.keys())]
320 return []
321
ehmaldonado4fb97462017-01-30 05:27:22 -0800322def _CheckNoPackageBoundaryViolations(input_api, gn_files, output_api):
323 cwd = input_api.PresubmitLocalPath()
324 script_path = os.path.join('tools-webrtc', 'check_package_boundaries.py')
325 webrtc_path = os.path.join('webrtc')
326 command = [sys.executable, script_path, webrtc_path]
327 command += [gn_file.LocalPath() for gn_file in gn_files]
328 returncode, _, stderr = _RunCommand(command, cwd)
329 if returncode:
330 return [output_api.PresubmitError(
331 'There are package boundary violations in the following GN files:\n\n'
332 '%s' % stderr)]
333 return []
334
ehmaldonado5b1ba082016-09-02 05:51:08 -0700335def _CheckGnChanges(input_api, output_api):
336 source_file_filter = lambda x: input_api.FilterSourceFile(
337 x, white_list=(r'.+\.(gn|gni)$',))
338
339 gn_files = []
340 for f in input_api.AffectedSourceFiles(source_file_filter):
341 if f.LocalPath().startswith('webrtc'):
342 gn_files.append(f)
343
344 result = []
345 if gn_files:
Henrik Kjellanderb4af3d62016-11-16 20:11:29 +0100346 result.extend(_CheckNoSourcesAbove(input_api, gn_files, output_api))
kjellander7439f972016-12-05 22:47:46 -0800347 result.extend(_CheckNoMixingCAndCCSources(input_api, gn_files, output_api))
ehmaldonado4fb97462017-01-30 05:27:22 -0800348 result.extend(_CheckNoPackageBoundaryViolations(
349 input_api, gn_files, output_api))
ehmaldonado5b1ba082016-09-02 05:51:08 -0700350 return result
351
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000352def _CheckUnwantedDependencies(input_api, output_api):
353 """Runs checkdeps on #include statements added in this
354 change. Breaking - rules is an error, breaking ! rules is a
355 warning.
356 """
357 # Copied from Chromium's src/PRESUBMIT.py.
358
359 # We need to wait until we have an input_api object and use this
360 # roundabout construct to import checkdeps because this file is
361 # eval-ed and thus doesn't have __file__.
362 original_sys_path = sys.path
363 try:
kjellander@webrtc.orgaefe61a2014-12-08 13:00:30 +0000364 checkdeps_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
365 'buildtools', 'checkdeps')
366 if not os.path.exists(checkdeps_path):
367 return [output_api.PresubmitError(
368 'Cannot find checkdeps at %s\nHave you run "gclient sync" to '
369 'download Chromium and setup the symlinks?' % checkdeps_path)]
370 sys.path.append(checkdeps_path)
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000371 import checkdeps
372 from cpp_checker import CppChecker
373 from rules import Rule
374 finally:
375 # Restore sys.path to what it was before.
376 sys.path = original_sys_path
377
378 added_includes = []
379 for f in input_api.AffectedFiles():
380 if not CppChecker.IsCppFile(f.LocalPath()):
381 continue
382
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200383 changed_lines = [line for _, line in f.ChangedContents()]
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000384 added_includes.append([f.LocalPath(), changed_lines])
385
386 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
387
388 error_descriptions = []
389 warning_descriptions = []
390 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
391 added_includes):
392 description_with_path = '%s\n %s' % (path, rule_description)
393 if rule_type == Rule.DISALLOW:
394 error_descriptions.append(description_with_path)
395 else:
396 warning_descriptions.append(description_with_path)
397
398 results = []
399 if error_descriptions:
400 results.append(output_api.PresubmitError(
401 'You added one or more #includes that violate checkdeps rules.',
402 error_descriptions))
403 if warning_descriptions:
404 results.append(output_api.PresubmitPromptOrNotify(
405 'You added one or more #includes of files that are temporarily\n'
406 'allowed but being removed. Can you avoid introducing the\n'
407 '#include? See relevant DEPS file(s) for details and contacts.',
408 warning_descriptions))
409 return results
410
kjellanderd1e26a92016-09-19 08:11:16 -0700411def _CheckChangeHasBugField(input_api, output_api):
412 """Requires that the changelist have a BUG= field.
413
414 This check is stricter than the one in depot_tools/presubmit_canned_checks.py
415 since it fails the presubmit if the BUG= field is missing or doesn't contain
416 a bug reference.
417 """
418 if input_api.change.BUG:
419 return []
420 else:
421 return [output_api.PresubmitError(
422 'The BUG=[bug number] field is mandatory. Please create a bug and '
423 'reference it using either of:\n'
424 ' * https://bugs.webrtc.org - reference it using BUG=webrtc:XXXX\n'
425 ' * https://crbug.com - reference it using BUG=chromium:XXXXXX')]
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000426
kjellander569cf942016-02-11 05:02:59 -0800427def _CheckJSONParseErrors(input_api, output_api):
428 """Check that JSON files do not contain syntax errors."""
429
430 def FilterFile(affected_file):
431 return input_api.os_path.splitext(affected_file.LocalPath())[1] == '.json'
432
433 def GetJSONParseError(input_api, filename):
434 try:
435 contents = input_api.ReadFile(filename)
436 input_api.json.loads(contents)
437 except ValueError as e:
438 return e
439 return None
440
441 results = []
442 for affected_file in input_api.AffectedFiles(
443 file_filter=FilterFile, include_deletes=False):
444 parse_error = GetJSONParseError(input_api,
445 affected_file.AbsoluteLocalPath())
446 if parse_error:
447 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
448 (affected_file.LocalPath(), parse_error)))
449 return results
450
451
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200452def _RunPythonTests(input_api, output_api):
kjellander94f4d9e2017-03-09 06:09:33 -0800453 def join(*args):
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200454 return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
455
456 test_directories = [
kjellander94f4d9e2017-03-09 06:09:33 -0800457 join('webrtc', 'tools', 'py_event_log_analyzer')
ehmaldonado4fb97462017-01-30 05:27:22 -0800458 ] + [
kjellander94f4d9e2017-03-09 06:09:33 -0800459 root for root, _, files in os.walk(join('tools-webrtc'))
ehmaldonado4fb97462017-01-30 05:27:22 -0800460 if any(f.endswith('_test.py') for f in files)
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200461 ]
462
463 tests = []
464 for directory in test_directories:
465 tests.extend(
466 input_api.canned_checks.GetUnitTestsInDirectory(
467 input_api,
468 output_api,
469 directory,
470 whitelist=[r'.+_test\.py$']))
471 return input_api.RunTests(tests, parallel=True)
472
473
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000474def _CommonChecks(input_api, output_api):
475 """Checks common to both upload and commit."""
niklase@google.comda159d62011-05-30 11:51:34 +0000476 results = []
tkchin42f580e2015-11-26 23:18:23 -0800477 # Filter out files that are in objc or ios dirs from being cpplint-ed since
478 # they do not follow C++ lint rules.
479 black_list = input_api.DEFAULT_BLACK_LIST + (
480 r".*\bobjc[\\\/].*",
Kári Tristan Helgason3fa35172016-09-09 08:55:05 +0000481 r".*objc\.[hcm]+$",
hjon65ae2d82016-08-02 23:55:44 -0700482 r"webrtc\/build\/ios\/SDK\/.*",
tkchin42f580e2015-11-26 23:18:23 -0800483 )
484 source_file_filter = lambda x: input_api.FilterSourceFile(x, None, black_list)
485 results.extend(_CheckApprovedFilesLintClean(
486 input_api, output_api, source_file_filter))
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000487 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
kjellander@webrtc.org177567c2016-12-22 10:40:28 +0100488 black_list=(r'^base[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200489 r'^build[\\\/].*\.py$',
490 r'^buildtools[\\\/].*\.py$',
Henrik Kjellander0779e8f2016-12-22 12:01:17 +0100491 r'^ios[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200492 r'^out.*[\\\/].*\.py$',
493 r'^testing[\\\/].*\.py$',
494 r'^third_party[\\\/].*\.py$',
kjellander@webrtc.org177567c2016-12-22 10:40:28 +0100495 r'^tools[\\\/].*\.py$',
kjellanderafd54942016-12-17 12:21:39 -0800496 # TODO(phoglund): should arguably be checked.
Henrik Kjellanderb2d55772016-12-18 22:14:50 +0100497 r'^tools-webrtc[\\\/]mb[\\\/].*\.py$',
kjellanderafd54942016-12-17 12:21:39 -0800498 r'^tools-webrtc[\\\/]valgrind[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200499 r'^xcodebuild.*[\\\/].*\.py$',),
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000500 disabled_warnings=['F0401', # Failed to import x
501 'E0611', # No package y in x
502 'W0232', # Class has no __init__ method
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200503 ],
504 pylintrc='pylintrc'))
kjellander569cf942016-02-11 05:02:59 -0800505
nisse3d21e232016-09-02 03:07:06 -0700506 # TODO(nisse): talk/ is no more, so make below checks simpler?
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200507 # WebRTC can't use the presubmit_canned_checks.PanProjectChecks function since
508 # we need to have different license checks in talk/ and webrtc/ directories.
509 # Instead, hand-picked checks are included below.
Henrik Kjellander63224672015-09-08 08:03:56 +0200510
tkchin3cd9a302016-06-08 12:40:28 -0700511 # .m and .mm files are ObjC files. For simplicity we will consider .h files in
512 # ObjC subdirectories ObjC headers.
513 objc_filter_list = (r'.+\.m$', r'.+\.mm$', r'.+objc\/.+\.h$')
Henrik Kjellanderb4af3d62016-11-16 20:11:29 +0100514 # Skip long-lines check for DEPS and GN files.
515 build_file_filter_list = (r'.+\.gn$', r'.+\.gni$', 'DEPS')
tkchin3cd9a302016-06-08 12:40:28 -0700516 eighty_char_sources = lambda x: input_api.FilterSourceFile(x,
517 black_list=build_file_filter_list + objc_filter_list)
518 hundred_char_sources = lambda x: input_api.FilterSourceFile(x,
519 white_list=objc_filter_list)
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000520 results.extend(input_api.canned_checks.CheckLongLines(
tkchin3cd9a302016-06-08 12:40:28 -0700521 input_api, output_api, maxlen=80, source_file_filter=eighty_char_sources))
522 results.extend(input_api.canned_checks.CheckLongLines(
523 input_api, output_api, maxlen=100,
524 source_file_filter=hundred_char_sources))
525
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000526 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
527 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000528 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
529 input_api, output_api))
kjellandere5dc62a2016-12-14 00:16:21 -0800530 results.extend(input_api.canned_checks.CheckAuthorizedAuthor(
531 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000532 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
533 input_api, output_api))
kjellander53047c92015-12-02 23:56:14 -0800534 results.extend(_CheckNativeApiHeaderChanges(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000535 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
kjellander6aeef742017-02-20 01:13:18 -0800536 results.extend(_CheckNoPragmaOnce(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000537 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
ehmaldonado5b1ba082016-09-02 05:51:08 -0700538 results.extend(_CheckGnChanges(input_api, output_api))
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000539 results.extend(_CheckUnwantedDependencies(input_api, output_api))
kjellander569cf942016-02-11 05:02:59 -0800540 results.extend(_CheckJSONParseErrors(input_api, output_api))
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200541 results.extend(_RunPythonTests(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000542 return results
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000543
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000544
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000545def CheckChangeOnUpload(input_api, output_api):
546 results = []
547 results.extend(_CommonChecks(input_api, output_api))
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200548 results.extend(
549 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
niklase@google.comda159d62011-05-30 11:51:34 +0000550 return results
551
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000552
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000553def CheckChangeOnCommit(input_api, output_api):
niklase@google.com1198db92011-06-09 07:07:24 +0000554 results = []
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000555 results.extend(_CommonChecks(input_api, output_api))
kjellander53047c92015-12-02 23:56:14 -0800556 results.extend(_VerifyNativeApiHeadersListIsValid(input_api, output_api))
niklase@google.com1198db92011-06-09 07:07:24 +0000557 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000558 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
559 input_api, output_api))
560 results.extend(input_api.canned_checks.CheckChangeHasDescription(
561 input_api, output_api))
kjellanderd1e26a92016-09-19 08:11:16 -0700562 results.extend(_CheckChangeHasBugField(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000563 results.extend(input_api.canned_checks.CheckChangeHasTestField(
564 input_api, output_api))
kjellander@webrtc.org12cb88c2014-02-13 11:53:43 +0000565 results.extend(input_api.canned_checks.CheckTreeIsOpen(
566 input_api, output_api,
567 json_url='http://webrtc-status.appspot.com/current?format=json'))
niklase@google.com1198db92011-06-09 07:07:24 +0000568 return results