blob: abb85825a3e0572b9ba42c1e01b4536bc92afd02 [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
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +000012import sys
Mirko Bonadei4dc4e252017-09-19 13:49:16 +020013from collections import defaultdict
Oleh Prypin2f33a562017-10-04 20:17:54 +020014from contextlib import contextmanager
kjellander@webrtc.org85759802013-10-22 16:47:40 +000015
16
oprypin2aa463f2017-03-23 03:17:02 -070017# Files and directories that are *skipped* by cpplint in the presubmit script.
18CPPLINT_BLACKLIST = [
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019 'api/video_codecs/video_decoder.h',
20 'common_types.cc',
21 'common_types.h',
22 'examples/objc',
Steve Antone78bcb92017-10-31 09:53:08 -070023 'media/base/streamparams.h',
24 'media/base/videocommon.h',
25 'media/engine/fakewebrtcdeviceinfo.h',
26 'media/sctp/sctptransport.cc',
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027 'modules/audio_coding',
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028 'modules/audio_device',
29 'modules/audio_processing',
30 'modules/desktop_capture',
31 'modules/include/module_common_types.h',
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032 'modules/utility',
33 'modules/video_capture',
Steve Anton6c38cc72017-11-29 10:25:58 -080034 'p2p/base/pseudotcp.cc',
35 'p2p/base/pseudotcp.h',
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020036 'rtc_base',
37 'sdk/android/src/jni',
38 'sdk/objc',
39 'system_wrappers',
40 'test',
Henrik Kjellander90fd7d82017-05-09 08:30:10 +020041 'tools_webrtc',
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020042 'voice_engine',
Artem Titova04d1402018-05-11 11:23:00 +020043 'third_party',
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010044]
45
jbauchc4e3ead2016-02-19 00:25:55 -080046# These filters will always be removed, even if the caller specifies a filter
47# set, as they are problematic or broken in some way.
48#
49# Justifications for each filter:
50# - build/c++11 : Rvalue ref checks are unreliable (false positives),
51# include file and feature blacklists are
52# google3-specific.
kjellandere5a87a52016-04-27 02:32:12 -070053# - whitespace/operators: Same as above (doesn't seem sufficient to eliminate
54# all move-related errors).
jbauchc4e3ead2016-02-19 00:25:55 -080055BLACKLIST_LINT_FILTERS = [
56 '-build/c++11',
kjellandere5a87a52016-04-27 02:32:12 -070057 '-whitespace/operators',
jbauchc4e3ead2016-02-19 00:25:55 -080058]
59
kjellanderfd595232015-12-04 02:44:09 -080060# List of directories of "supported" native APIs. That means changes to headers
61# will be done in a compatible way following this scheme:
62# 1. Non-breaking changes are made.
63# 2. The old APIs as marked as deprecated (with comments).
64# 3. Deprecation is announced to discuss-webrtc@googlegroups.com and
65# webrtc-users@google.com (internal list).
66# 4. (later) The deprecated APIs are removed.
kjellander53047c92015-12-02 23:56:14 -080067NATIVE_API_DIRS = (
Karl Wibergef52d8b82017-10-25 13:20:03 +020068 'api', # All subdirectories of api/ are included as well.
Mirko Bonadeia4eeeff2018-01-11 13:16:52 +010069 'media/base',
70 'media/engine',
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020071 'modules/audio_device/include',
72 'pc',
kjellanderdd705472016-06-09 11:17:27 -070073)
Mirko Bonadei4dc4e252017-09-19 13:49:16 +020074
kjellanderdd705472016-06-09 11:17:27 -070075# These directories should not be used but are maintained only to avoid breaking
76# some legacy downstream code.
77LEGACY_API_DIRS = (
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020078 'common_audio/include',
79 'modules/audio_coding/include',
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020080 'modules/audio_processing/include',
81 'modules/bitrate_controller/include',
82 'modules/congestion_controller/include',
83 'modules/include',
84 'modules/remote_bitrate_estimator/include',
85 'modules/rtp_rtcp/include',
86 'modules/rtp_rtcp/source',
87 'modules/utility/include',
88 'modules/video_coding/codecs/h264/include',
89 'modules/video_coding/codecs/i420/include',
90 'modules/video_coding/codecs/vp8/include',
91 'modules/video_coding/codecs/vp9/include',
92 'modules/video_coding/include',
93 'rtc_base',
94 'system_wrappers/include',
kjellander53047c92015-12-02 23:56:14 -080095)
Mirko Bonadei4dc4e252017-09-19 13:49:16 +020096
Karl Wibergd4f01c12017-11-10 10:55:45 +010097# NOTE: The set of directories in API_DIRS should be the same as those
98# listed in the table in native-api.md.
kjellanderdd705472016-06-09 11:17:27 -070099API_DIRS = NATIVE_API_DIRS[:] + LEGACY_API_DIRS[:]
kjellander53047c92015-12-02 23:56:14 -0800100
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200101# TARGET_RE matches a GN target, and extracts the target name and the contents.
102TARGET_RE = re.compile(r'(?P<indent>\s*)\w+\("(?P<target_name>\w+)"\) {'
103 r'(?P<target_contents>.*?)'
104 r'(?P=indent)}',
105 re.MULTILINE | re.DOTALL)
106
107# SOURCES_RE matches a block of sources inside a GN target.
108SOURCES_RE = re.compile(r'sources \+?= \[(?P<sources>.*?)\]',
109 re.MULTILINE | re.DOTALL)
110
111# FILE_PATH_RE matchies a file path.
112FILE_PATH_RE = re.compile(r'"(?P<file_path>(\w|\/)+)(?P<extension>\.\w+)"')
113
kjellander53047c92015-12-02 23:56:14 -0800114
Oleh Prypin2f33a562017-10-04 20:17:54 +0200115@contextmanager
116def _AddToPath(*paths):
117 original_sys_path = sys.path
118 sys.path.extend(paths)
119 try:
120 yield
121 finally:
122 # Restore sys.path to what it was before.
123 sys.path = original_sys_path
ehmaldonado4fb97462017-01-30 05:27:22 -0800124
125
charujain9893e252017-09-14 13:33:22 +0200126def VerifyNativeApiHeadersListIsValid(input_api, output_api):
kjellander53047c92015-12-02 23:56:14 -0800127 """Ensures the list of native API header directories is up to date."""
128 non_existing_paths = []
129 native_api_full_paths = [
130 input_api.os_path.join(input_api.PresubmitLocalPath(),
kjellanderdd705472016-06-09 11:17:27 -0700131 *path.split('/')) for path in API_DIRS]
kjellander53047c92015-12-02 23:56:14 -0800132 for path in native_api_full_paths:
133 if not os.path.isdir(path):
134 non_existing_paths.append(path)
135 if non_existing_paths:
136 return [output_api.PresubmitError(
137 'Directories to native API headers have changed which has made the '
138 'list in PRESUBMIT.py outdated.\nPlease update it to the current '
139 'location of our native APIs.',
140 non_existing_paths)]
141 return []
142
kjellanderc88b5d52017-04-05 06:42:43 -0700143API_CHANGE_MSG = """
kwibergeb133022016-04-07 07:41:48 -0700144You seem to be changing native API header files. Please make sure that you:
oprypin375b9ac2017-02-13 04:13:23 -0800145 1. Make compatible changes that don't break existing clients. Usually
146 this is done by keeping the existing method signatures unchanged.
147 2. Mark the old stuff as deprecated (see RTC_DEPRECATED macro).
kwibergeb133022016-04-07 07:41:48 -0700148 3. Create a timeline and plan for when the deprecated stuff will be
149 removed. (The amount of time we give users to change their code
150 should be informed by how much work it is for them. If they just
151 need to replace one name with another or something equally
152 simple, 1-2 weeks might be good; if they need to do serious work,
153 up to 3 months may be called for.)
154 4. Update/inform existing downstream code owners to stop using the
155 deprecated stuff. (Send announcements to
156 discuss-webrtc@googlegroups.com and webrtc-users@google.com.)
157 5. Remove the deprecated stuff, once the agreed-upon amount of time
158 has passed.
159Related files:
160"""
kjellander53047c92015-12-02 23:56:14 -0800161
charujain9893e252017-09-14 13:33:22 +0200162def CheckNativeApiHeaderChanges(input_api, output_api):
kjellander53047c92015-12-02 23:56:14 -0800163 """Checks to remind proper changing of native APIs."""
164 files = []
Karl Wiberg6bfac032017-10-27 15:14:20 +0200165 source_file_filter = lambda x: input_api.FilterSourceFile(
166 x, white_list=[r'.+\.(gn|gni|h)$'])
167 for f in input_api.AffectedSourceFiles(source_file_filter):
168 for path in API_DIRS:
169 dn = os.path.dirname(f.LocalPath())
170 if path == 'api':
171 # Special case: Subdirectories included.
172 if dn == 'api' or dn.startswith('api/'):
173 files.append(f)
174 else:
175 # Normal case: Subdirectories not included.
176 if dn == path:
177 files.append(f)
kjellander53047c92015-12-02 23:56:14 -0800178
179 if files:
kjellanderc88b5d52017-04-05 06:42:43 -0700180 return [output_api.PresubmitNotifyResult(API_CHANGE_MSG, files)]
kjellander53047c92015-12-02 23:56:14 -0800181 return []
182
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100183
Artem Titova04d1402018-05-11 11:23:00 +0200184def CheckNoIOStreamInHeaders(input_api, output_api,
185 source_file_filter):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000186 """Checks to make sure no .h files include <iostream>."""
187 files = []
188 pattern = input_api.re.compile(r'^#include\s*<iostream>',
189 input_api.re.MULTILINE)
Artem Titova04d1402018-05-11 11:23:00 +0200190 file_filter = lambda x: (input_api.FilterSourceFile(x)
191 and source_file_filter(x))
192 for f in input_api.AffectedSourceFiles(file_filter):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000193 if not f.LocalPath().endswith('.h'):
194 continue
195 contents = input_api.ReadFile(f)
196 if pattern.search(contents):
197 files.append(f)
198
199 if len(files):
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200200 return [output_api.PresubmitError(
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000201 'Do not #include <iostream> in header files, since it inserts static ' +
202 'initialization into every file including the header. Instead, ' +
203 '#include <ostream>. See http://crbug.com/94794',
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200204 files)]
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000205 return []
206
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000207
Artem Titova04d1402018-05-11 11:23:00 +0200208def CheckNoPragmaOnce(input_api, output_api,
209 source_file_filter):
kjellander6aeef742017-02-20 01:13:18 -0800210 """Make sure that banned functions are not used."""
211 files = []
212 pattern = input_api.re.compile(r'^#pragma\s+once',
213 input_api.re.MULTILINE)
Artem Titova04d1402018-05-11 11:23:00 +0200214 file_filter = lambda x: (input_api.FilterSourceFile(x)
215 and source_file_filter(x))
216 for f in input_api.AffectedSourceFiles(file_filter):
kjellander6aeef742017-02-20 01:13:18 -0800217 if not f.LocalPath().endswith('.h'):
218 continue
219 contents = input_api.ReadFile(f)
220 if pattern.search(contents):
221 files.append(f)
222
223 if files:
224 return [output_api.PresubmitError(
225 'Do not use #pragma once in header files.\n'
226 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
227 files)]
228 return []
229
230
Artem Titova04d1402018-05-11 11:23:00 +0200231def CheckNoFRIEND_TEST(input_api, output_api, # pylint: disable=invalid-name
232 source_file_filter):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000233 """Make sure that gtest's FRIEND_TEST() macro is not used, the
234 FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be
235 used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes."""
236 problems = []
237
Artem Titova04d1402018-05-11 11:23:00 +0200238 file_filter = lambda f: (f.LocalPath().endswith(('.cc', '.h'))
239 and source_file_filter(f))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000240 for f in input_api.AffectedFiles(file_filter=file_filter):
241 for line_num, line in f.ChangedContents():
242 if 'FRIEND_TEST(' in line:
243 problems.append(' %s:%d' % (f.LocalPath(), line_num))
244
245 if not problems:
246 return []
247 return [output_api.PresubmitPromptWarning('WebRTC\'s code should not use '
248 'gtest\'s FRIEND_TEST() macro. Include testsupport/gtest_prod_util.h and '
249 'use FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems))]
250
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000251
charujain9893e252017-09-14 13:33:22 +0200252def IsLintBlacklisted(blacklist_paths, file_path):
oprypin2aa463f2017-03-23 03:17:02 -0700253 """ Checks if a file is blacklisted for lint check."""
254 for path in blacklist_paths:
255 if file_path == path or os.path.dirname(file_path).startswith(path):
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100256 return True
257 return False
258
259
charujain9893e252017-09-14 13:33:22 +0200260def CheckApprovedFilesLintClean(input_api, output_api,
Artem Titova04d1402018-05-11 11:23:00 +0200261 source_file_filter=None):
oprypin2aa463f2017-03-23 03:17:02 -0700262 """Checks that all new or non-blacklisted .cc and .h files pass cpplint.py.
charujain9893e252017-09-14 13:33:22 +0200263 This check is based on CheckChangeLintsClean in
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000264 depot_tools/presubmit_canned_checks.py but has less filters and only checks
265 added files."""
266 result = []
267
268 # Initialize cpplint.
269 import cpplint
270 # Access to a protected member _XX of a client class
271 # pylint: disable=W0212
272 cpplint._cpplint_state.ResetErrorCounts()
273
jbauchc4e3ead2016-02-19 00:25:55 -0800274 lint_filters = cpplint._Filters()
275 lint_filters.extend(BLACKLIST_LINT_FILTERS)
276 cpplint._SetFilters(','.join(lint_filters))
277
oprypin2aa463f2017-03-23 03:17:02 -0700278 # Create a platform independent blacklist for cpplint.
279 blacklist_paths = [input_api.os_path.join(*path.split('/'))
280 for path in CPPLINT_BLACKLIST]
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100281
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000282 # Use the strictest verbosity level for cpplint.py (level 1) which is the
oprypin2aa463f2017-03-23 03:17:02 -0700283 # default when running cpplint.py from command line. To make it possible to
284 # work with not-yet-converted code, we're only applying it to new (or
285 # moved/renamed) files and files not listed in CPPLINT_BLACKLIST.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000286 verbosity_level = 1
287 files = []
288 for f in input_api.AffectedSourceFiles(source_file_filter):
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200289 # Note that moved/renamed files also count as added.
charujain9893e252017-09-14 13:33:22 +0200290 if f.Action() == 'A' or not IsLintBlacklisted(blacklist_paths,
oprypin2aa463f2017-03-23 03:17:02 -0700291 f.LocalPath()):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000292 files.append(f.AbsoluteLocalPath())
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000293
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000294 for file_name in files:
295 cpplint.ProcessFile(file_name, verbosity_level)
296
297 if cpplint._cpplint_state.error_count > 0:
298 if input_api.is_committing:
oprypin8e58d652017-03-21 07:52:41 -0700299 res_type = output_api.PresubmitError
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000300 else:
301 res_type = output_api.PresubmitPromptWarning
302 result = [res_type('Changelist failed cpplint.py check.')]
303
304 return result
305
charujain9893e252017-09-14 13:33:22 +0200306def CheckNoSourcesAbove(input_api, gn_files, output_api):
ehmaldonado5b1ba082016-09-02 05:51:08 -0700307 # Disallow referencing source files with paths above the GN file location.
308 source_pattern = input_api.re.compile(r' +sources \+?= \[(.*?)\]',
309 re.MULTILINE | re.DOTALL)
310 file_pattern = input_api.re.compile(r'"((\.\./.*?)|(//.*?))"')
311 violating_gn_files = set()
312 violating_source_entries = []
313 for gn_file in gn_files:
314 contents = input_api.ReadFile(gn_file)
315 for source_block_match in source_pattern.finditer(contents):
316 # Find all source list entries starting with ../ in the source block
317 # (exclude overrides entries).
318 for file_list_match in file_pattern.finditer(source_block_match.group(1)):
319 source_file = file_list_match.group(1)
320 if 'overrides/' not in source_file:
321 violating_source_entries.append(source_file)
322 violating_gn_files.add(gn_file)
323 if violating_gn_files:
324 return [output_api.PresubmitError(
325 'Referencing source files above the directory of the GN file is not '
Henrik Kjellanderb4af3d62016-11-16 20:11:29 +0100326 'allowed. Please introduce new GN targets in the proper location '
327 'instead.\n'
ehmaldonado5b1ba082016-09-02 05:51:08 -0700328 'Invalid source entries:\n'
329 '%s\n'
330 'Violating GN files:' % '\n'.join(violating_source_entries),
331 items=violating_gn_files)]
332 return []
333
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200334def CheckNoMixingSources(input_api, gn_files, output_api):
335 """Disallow mixing C, C++ and Obj-C/Obj-C++ in the same target.
336
337 See bugs.webrtc.org/7743 for more context.
338 """
339 def _MoreThanOneSourceUsed(*sources_lists):
340 sources_used = 0
341 for source_list in sources_lists:
342 if len(source_list):
343 sources_used += 1
344 return sources_used > 1
345
346 errors = defaultdict(lambda: [])
kjellander7439f972016-12-05 22:47:46 -0800347 for gn_file in gn_files:
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200348 gn_file_content = input_api.ReadFile(gn_file)
349 for target_match in TARGET_RE.finditer(gn_file_content):
350 # list_of_sources is a list of tuples of the form
351 # (c_files, cc_files, objc_files) that keeps track of all the sources
352 # defined in a target. A GN target can have more that on definition of
353 # sources (since it supports if/else statements).
354 # E.g.:
355 # rtc_static_library("foo") {
356 # if (is_win) {
357 # sources = [ "foo.cc" ]
358 # } else {
359 # sources = [ "foo.mm" ]
360 # }
361 # }
362 # This is allowed and the presubmit check should support this case.
363 list_of_sources = []
kjellander7439f972016-12-05 22:47:46 -0800364 c_files = []
365 cc_files = []
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200366 objc_files = []
367 target_name = target_match.group('target_name')
368 target_contents = target_match.group('target_contents')
369 for sources_match in SOURCES_RE.finditer(target_contents):
370 if '+=' not in sources_match.group(0):
371 if c_files or cc_files or objc_files:
372 list_of_sources.append((c_files, cc_files, objc_files))
373 c_files = []
374 cc_files = []
375 objc_files = []
376 for file_match in FILE_PATH_RE.finditer(sources_match.group(1)):
377 file_path = file_match.group('file_path')
378 extension = file_match.group('extension')
379 if extension == '.c':
380 c_files.append(file_path + extension)
381 if extension == '.cc':
382 cc_files.append(file_path + extension)
383 if extension in ['.m', '.mm']:
384 objc_files.append(file_path + extension)
385 list_of_sources.append((c_files, cc_files, objc_files))
386 for c_files_list, cc_files_list, objc_files_list in list_of_sources:
387 if _MoreThanOneSourceUsed(c_files_list, cc_files_list, objc_files_list):
388 all_sources = sorted(c_files_list + cc_files_list + objc_files_list)
389 errors[gn_file.LocalPath()].append((target_name, all_sources))
390 if errors:
kjellander7439f972016-12-05 22:47:46 -0800391 return [output_api.PresubmitError(
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200392 'GN targets cannot mix .c, .cc and .m (or .mm) source files.\n'
393 'Please create a separate target for each collection of sources.\n'
kjellander7439f972016-12-05 22:47:46 -0800394 'Mixed sources: \n'
395 '%s\n'
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200396 'Violating GN files:\n%s\n' % (json.dumps(errors, indent=2),
397 '\n'.join(errors.keys())))]
kjellander7439f972016-12-05 22:47:46 -0800398 return []
399
charujain9893e252017-09-14 13:33:22 +0200400def CheckNoPackageBoundaryViolations(input_api, gn_files, output_api):
ehmaldonado4fb97462017-01-30 05:27:22 -0800401 cwd = input_api.PresubmitLocalPath()
Oleh Prypin2f33a562017-10-04 20:17:54 +0200402 with _AddToPath(input_api.os_path.join(
403 cwd, 'tools_webrtc', 'presubmit_checks_lib')):
404 from check_package_boundaries import CheckPackageBoundaries
405 build_files = [os.path.join(cwd, gn_file.LocalPath()) for gn_file in gn_files]
406 errors = CheckPackageBoundaries(cwd, build_files)[:5]
407 if errors:
ehmaldonado4fb97462017-01-30 05:27:22 -0800408 return [output_api.PresubmitError(
Oleh Prypin2f33a562017-10-04 20:17:54 +0200409 'There are package boundary violations in the following GN files:',
410 long_text='\n\n'.join(str(err) for err in errors))]
ehmaldonado4fb97462017-01-30 05:27:22 -0800411 return []
412
Mirko Bonadeia51bbd82018-03-08 16:15:45 +0100413
414def _ReportErrorFileAndLineNumber(filename, line_num):
415 """Default error formatter for _FindNewViolationsOfRule."""
416 return '%s (line %s)' % (filename, line_num)
417
418
419def CheckNoStreamUsageIsAdded(input_api, output_api,
Artem Titova04d1402018-05-11 11:23:00 +0200420 error_formatter=_ReportErrorFileAndLineNumber,
421 source_file_filter):
Mirko Bonadeia51bbd82018-03-08 16:15:45 +0100422 """Make sure that no more dependencies on stringstream are added."""
423 error_msg = ('Usage of <sstream>, <istream> and <ostream> in WebRTC is '
424 'deprecated.\n'
425 'This includes the following types:\n'
426 'std::istringstream, std::ostringstream, std::wistringstream, '
427 'std::wostringstream,\n'
428 'std::wstringstream, std::ostream, std::wostream, std::istream,'
429 'std::wistream,\n'
430 'std::iostream, std::wiostream.\n'
431 'If you are not adding this code (e.g. you are just moving '
432 'existing code),\n'
433 'you can add a comment on the line that causes the problem:\n\n'
434 '#include <sstream> // no-presubmit-check TODO(webrtc:8982)\n'
435 'std::ostream& F() { // no-presubmit-check TODO(webrtc:8982)\n'
436 '\n'
Karl Wibergebd01e82018-03-14 15:08:39 +0100437 'If you are adding new code, consider using '
438 'rtc::SimpleStringBuilder\n'
439 '(in rtc_base/strings/string_builder.h).\n'
Mirko Bonadeia51bbd82018-03-08 16:15:45 +0100440 'Affected files:\n')
441 errors = [] # 2-element tuples with (file, line number)
442 include_re = input_api.re.compile(r'#include <(i|o|s)stream>')
443 usage_re = input_api.re.compile(r'std::(w|i|o|io|wi|wo|wio)(string)*stream')
444 no_presubmit_re = input_api.re.compile(
Jonas Olsson74395342018-04-03 12:22:07 +0200445 r'// no-presubmit-check TODO\(webrtc:8982\)')
Artem Titova04d1402018-05-11 11:23:00 +0200446 file_filter = lambda x: (input_api.FilterSourceFile(x)
447 and source_file_filter(x))
448 for f in input_api.AffectedSourceFiles(file_filter):
Mirko Bonadeid2c83322018-03-19 10:31:47 +0000449 if f.LocalPath() == 'PRESUBMIT.py':
450 continue
451 for line_num, line in f.ChangedContents():
452 if ((include_re.search(line) or usage_re.search(line))
453 and not no_presubmit_re.search(line)):
454 errors.append(error_formatter(f.LocalPath(), line_num))
Mirko Bonadeia51bbd82018-03-08 16:15:45 +0100455 if errors:
456 return [output_api.PresubmitError(error_msg, errors)]
457 return []
458
Mirko Bonadeia05d47e2018-05-09 11:03:38 +0200459def CheckPublicDepsIsNotUsed(gn_files, input_api, output_api):
460 """Checks that public_deps is not used without a good reason."""
Mirko Bonadei5c1ad592017-12-12 11:52:27 +0100461 result = []
Mirko Bonadeia05d47e2018-05-09 11:03:38 +0200462 no_presubmit_check_re = input_api.re.compile(
463 r'# no-presubmit-check TODO\(webrtc:8603\)')
464 error_msg = ('public_deps is not recommended in WebRTC BUILD.gn files '
465 'because it doesn\'t map well to downstream build systems.\n'
466 'Used in: %s (line %d).\n'
467 'If you are not adding this code (e.g. you are just moving '
468 'existing code) or you have a good reason, you can add a '
469 'comment on the line that causes the problem:\n\n'
470 'public_deps = [ # no-presubmit-check TODO(webrtc:8603)\n')
Mirko Bonadei5c1ad592017-12-12 11:52:27 +0100471 for affected_file in gn_files:
472 for (line_number, affected_line) in affected_file.ChangedContents():
Mirko Bonadeia05d47e2018-05-09 11:03:38 +0200473 if ('public_deps' in affected_line
474 and not no_presubmit_check_re.search(affected_line)):
Mirko Bonadei5c1ad592017-12-12 11:52:27 +0100475 result.append(
476 output_api.PresubmitError(error_msg % (affected_file.LocalPath(),
477 line_number)))
478 return result
479
Patrik Höglund6f491062018-01-11 12:04:23 +0100480def CheckCheckIncludesIsNotUsed(gn_files, output_api):
481 result = []
482 error_msg = ('check_includes overrides are not allowed since it can cause '
483 'incorrect dependencies to form. It effectively means that your '
484 'module can include any .h file without depending on its '
485 'corresponding target. There are some exceptional cases when '
486 'this is allowed: if so, get approval from a .gn owner in the'
487 'root OWNERS file.\n'
488 'Used in: %s (line %d).')
489 for affected_file in gn_files:
490 for (line_number, affected_line) in affected_file.ChangedContents():
491 if 'check_includes' in affected_line:
492 result.append(
493 output_api.PresubmitError(error_msg % (affected_file.LocalPath(),
494 line_number)))
495 return result
496
Artem Titova04d1402018-05-11 11:23:00 +0200497def CheckGnChanges(input_api, output_api, source_file_filter):
498 file_filter = lambda x: (input_api.FilterSourceFile(
Oleh Prypinafe01652017-10-04 15:56:08 +0200499 x, white_list=(r'.+\.(gn|gni)$',),
Mirko Bonadei5c1ad592017-12-12 11:52:27 +0100500 black_list=(r'.*/presubmit_checks_lib/testdata/.*',))
Artem Titova04d1402018-05-11 11:23:00 +0200501 and source_file_filter(x))
ehmaldonado5b1ba082016-09-02 05:51:08 -0700502
503 gn_files = []
Artem Titova04d1402018-05-11 11:23:00 +0200504 for f in input_api.AffectedSourceFiles(file_filter):
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200505 gn_files.append(f)
ehmaldonado5b1ba082016-09-02 05:51:08 -0700506
507 result = []
508 if gn_files:
charujain9893e252017-09-14 13:33:22 +0200509 result.extend(CheckNoSourcesAbove(input_api, gn_files, output_api))
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200510 result.extend(CheckNoMixingSources(input_api, gn_files, output_api))
511 result.extend(CheckNoPackageBoundaryViolations(input_api, gn_files,
512 output_api))
Mirko Bonadeia05d47e2018-05-09 11:03:38 +0200513 result.extend(CheckPublicDepsIsNotUsed(gn_files, input_api, output_api))
Patrik Höglund6f491062018-01-11 12:04:23 +0100514 result.extend(CheckCheckIncludesIsNotUsed(gn_files, output_api))
ehmaldonado5b1ba082016-09-02 05:51:08 -0700515 return result
516
Oleh Prypin920b6532017-10-05 11:28:51 +0200517def CheckGnGen(input_api, output_api):
518 """Runs `gn gen --check` with default args to detect mismatches between
519 #includes and dependencies in the BUILD.gn files, as well as general build
520 errors.
521 """
522 with _AddToPath(input_api.os_path.join(
523 input_api.PresubmitLocalPath(), 'tools_webrtc', 'presubmit_checks_lib')):
524 from gn_check import RunGnCheck
525 errors = RunGnCheck(input_api.PresubmitLocalPath())[:5]
526 if errors:
527 return [output_api.PresubmitPromptWarning(
528 'Some #includes do not match the build dependency graph. Please run:\n'
529 ' gn gen --check <out_dir>',
530 long_text='\n\n'.join(errors))]
531 return []
532
Artem Titova04d1402018-05-11 11:23:00 +0200533def CheckUnwantedDependencies(input_api, output_api, source_file_filter):
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000534 """Runs checkdeps on #include statements added in this
535 change. Breaking - rules is an error, breaking ! rules is a
536 warning.
537 """
538 # Copied from Chromium's src/PRESUBMIT.py.
539
540 # We need to wait until we have an input_api object and use this
541 # roundabout construct to import checkdeps because this file is
542 # eval-ed and thus doesn't have __file__.
Oleh Prypin2f33a562017-10-04 20:17:54 +0200543 checkdeps_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
544 'buildtools', 'checkdeps')
545 if not os.path.exists(checkdeps_path):
546 return [output_api.PresubmitError(
547 'Cannot find checkdeps at %s\nHave you run "gclient sync" to '
548 'download all the DEPS entries?' % checkdeps_path)]
549 with _AddToPath(checkdeps_path):
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000550 import checkdeps
551 from cpp_checker import CppChecker
552 from rules import Rule
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000553
554 added_includes = []
Artem Titova04d1402018-05-11 11:23:00 +0200555 for f in input_api.AffectedFiles(file_filter=source_file_filter):
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000556 if not CppChecker.IsCppFile(f.LocalPath()):
557 continue
558
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200559 changed_lines = [line for _, line in f.ChangedContents()]
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000560 added_includes.append([f.LocalPath(), changed_lines])
561
562 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
563
564 error_descriptions = []
565 warning_descriptions = []
566 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
567 added_includes):
568 description_with_path = '%s\n %s' % (path, rule_description)
569 if rule_type == Rule.DISALLOW:
570 error_descriptions.append(description_with_path)
571 else:
572 warning_descriptions.append(description_with_path)
573
574 results = []
575 if error_descriptions:
576 results.append(output_api.PresubmitError(
kjellandera7066a32017-03-23 03:47:05 -0700577 'You added one or more #includes that violate checkdeps rules.\n'
578 'Check that the DEPS files in these locations contain valid rules.\n'
579 'See https://cs.chromium.org/chromium/src/buildtools/checkdeps/ for '
580 'more details about checkdeps.',
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000581 error_descriptions))
582 if warning_descriptions:
583 results.append(output_api.PresubmitPromptOrNotify(
584 'You added one or more #includes of files that are temporarily\n'
585 'allowed but being removed. Can you avoid introducing the\n'
kjellandera7066a32017-03-23 03:47:05 -0700586 '#include? See relevant DEPS file(s) for details and contacts.\n'
587 'See https://cs.chromium.org/chromium/src/buildtools/checkdeps/ for '
588 'more details about checkdeps.',
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000589 warning_descriptions))
590 return results
591
charujain9893e252017-09-14 13:33:22 +0200592def CheckCommitMessageBugEntry(input_api, output_api):
593 """Check that bug entries are well-formed in commit message."""
594 bogus_bug_msg = (
Mirko Bonadei61880182017-10-12 15:12:35 +0200595 'Bogus Bug entry: %s. Please specify the issue tracker prefix and the '
charujain9893e252017-09-14 13:33:22 +0200596 'issue number, separated by a colon, e.g. webrtc:123 or chromium:12345.')
597 results = []
Mirko Bonadei61880182017-10-12 15:12:35 +0200598 for bug in input_api.change.BugsFromDescription():
charujain9893e252017-09-14 13:33:22 +0200599 bug = bug.strip()
600 if bug.lower() == 'none':
601 continue
charujain81a58c72017-09-25 13:25:45 +0200602 if 'b/' not in bug and ':' not in bug:
charujain9893e252017-09-14 13:33:22 +0200603 try:
604 if int(bug) > 100000:
605 # Rough indicator for current chromium bugs.
606 prefix_guess = 'chromium'
607 else:
608 prefix_guess = 'webrtc'
Mirko Bonadei61880182017-10-12 15:12:35 +0200609 results.append('Bug entry requires issue tracker prefix, e.g. %s:%s' %
charujain9893e252017-09-14 13:33:22 +0200610 (prefix_guess, bug))
611 except ValueError:
612 results.append(bogus_bug_msg % bug)
charujain81a58c72017-09-25 13:25:45 +0200613 elif not (re.match(r'\w+:\d+', bug) or re.match(r'b/\d+', bug)):
charujain9893e252017-09-14 13:33:22 +0200614 results.append(bogus_bug_msg % bug)
615 return [output_api.PresubmitError(r) for r in results]
616
617def CheckChangeHasBugField(input_api, output_api):
Mirko Bonadei61880182017-10-12 15:12:35 +0200618 """Requires that the changelist is associated with a bug.
kjellanderd1e26a92016-09-19 08:11:16 -0700619
620 This check is stricter than the one in depot_tools/presubmit_canned_checks.py
Mirko Bonadei61880182017-10-12 15:12:35 +0200621 since it fails the presubmit if the bug field is missing or doesn't contain
kjellanderd1e26a92016-09-19 08:11:16 -0700622 a bug reference.
Mirko Bonadei61880182017-10-12 15:12:35 +0200623
624 This supports both 'BUG=' and 'Bug:' since we are in the process of migrating
625 to Gerrit and it encourages the usage of 'Bug:'.
kjellanderd1e26a92016-09-19 08:11:16 -0700626 """
Mirko Bonadei61880182017-10-12 15:12:35 +0200627 if input_api.change.BugsFromDescription():
kjellanderd1e26a92016-09-19 08:11:16 -0700628 return []
629 else:
630 return [output_api.PresubmitError(
Mirko Bonadei61880182017-10-12 15:12:35 +0200631 'The "Bug: [bug number]" footer is mandatory. Please create a bug and '
kjellanderd1e26a92016-09-19 08:11:16 -0700632 'reference it using either of:\n'
Mirko Bonadei61880182017-10-12 15:12:35 +0200633 ' * https://bugs.webrtc.org - reference it using Bug: webrtc:XXXX\n'
634 ' * https://crbug.com - reference it using Bug: chromium:XXXXXX')]
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000635
Artem Titova04d1402018-05-11 11:23:00 +0200636def CheckJSONParseErrors(input_api, output_api, source_file_filter):
kjellander569cf942016-02-11 05:02:59 -0800637 """Check that JSON files do not contain syntax errors."""
638
639 def FilterFile(affected_file):
Artem Titova04d1402018-05-11 11:23:00 +0200640 return (input_api.os_path.splitext(affected_file.LocalPath())[1] == '.json'
641 and source_file_filter(affected_file))
kjellander569cf942016-02-11 05:02:59 -0800642
643 def GetJSONParseError(input_api, filename):
644 try:
645 contents = input_api.ReadFile(filename)
646 input_api.json.loads(contents)
647 except ValueError as e:
648 return e
649 return None
650
651 results = []
652 for affected_file in input_api.AffectedFiles(
653 file_filter=FilterFile, include_deletes=False):
654 parse_error = GetJSONParseError(input_api,
655 affected_file.AbsoluteLocalPath())
656 if parse_error:
657 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
658 (affected_file.LocalPath(), parse_error)))
659 return results
660
661
charujain9893e252017-09-14 13:33:22 +0200662def RunPythonTests(input_api, output_api):
kjellanderc88b5d52017-04-05 06:42:43 -0700663 def Join(*args):
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200664 return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
665
666 test_directories = [
Edward Lemur6d01f6d2017-09-14 17:02:01 +0200667 input_api.PresubmitLocalPath(),
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200668 Join('rtc_tools', 'py_event_log_analyzer'),
669 Join('rtc_tools'),
670 Join('audio', 'test', 'unittests'),
ehmaldonado4fb97462017-01-30 05:27:22 -0800671 ] + [
Henrik Kjellander90fd7d82017-05-09 08:30:10 +0200672 root for root, _, files in os.walk(Join('tools_webrtc'))
ehmaldonado4fb97462017-01-30 05:27:22 -0800673 if any(f.endswith('_test.py') for f in files)
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200674 ]
675
676 tests = []
677 for directory in test_directories:
678 tests.extend(
679 input_api.canned_checks.GetUnitTestsInDirectory(
680 input_api,
681 output_api,
682 directory,
683 whitelist=[r'.+_test\.py$']))
684 return input_api.RunTests(tests, parallel=True)
685
686
Artem Titova04d1402018-05-11 11:23:00 +0200687def CheckUsageOfGoogleProtobufNamespace(input_api, output_api,
688 source_file_filter):
mbonadei38415b22017-04-07 05:38:01 -0700689 """Checks that the namespace google::protobuf has not been used."""
690 files = []
691 pattern = input_api.re.compile(r'google::protobuf')
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200692 proto_utils_path = os.path.join('rtc_base', 'protobuf_utils.h')
Artem Titova04d1402018-05-11 11:23:00 +0200693 file_filter = lambda x: (input_api.FilterSourceFile(x)
694 and source_file_filter(x))
695 for f in input_api.AffectedSourceFiles(file_filter):
mbonadei38415b22017-04-07 05:38:01 -0700696 if f.LocalPath() in [proto_utils_path, 'PRESUBMIT.py']:
697 continue
698 contents = input_api.ReadFile(f)
699 if pattern.search(contents):
700 files.append(f)
701
702 if files:
703 return [output_api.PresubmitError(
704 'Please avoid to use namespace `google::protobuf` directly.\n'
705 'Add a using directive in `%s` and include that header instead.'
706 % proto_utils_path, files)]
707 return []
708
709
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200710def _LicenseHeader(input_api):
711 """Returns the license header regexp."""
712 # Accept any year number from 2003 to the current year
713 current_year = int(input_api.time.strftime('%Y'))
714 allowed_years = (str(s) for s in reversed(xrange(2003, current_year + 1)))
715 years_re = '(' + '|'.join(allowed_years) + ')'
716 license_header = (
717 r'.*? Copyright( \(c\))? %(year)s The WebRTC [Pp]roject [Aa]uthors\. '
718 r'All [Rr]ights [Rr]eserved\.\n'
719 r'.*?\n'
720 r'.*? Use of this source code is governed by a BSD-style license\n'
721 r'.*? that can be found in the LICENSE file in the root of the source\n'
722 r'.*? tree\. An additional intellectual property rights grant can be '
723 r'found\n'
724 r'.*? in the file PATENTS\. All contributing project authors may\n'
725 r'.*? be found in the AUTHORS file in the root of the source tree\.\n'
726 ) % {
727 'year': years_re,
728 }
729 return license_header
730
731
charujain9893e252017-09-14 13:33:22 +0200732def CommonChecks(input_api, output_api):
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000733 """Checks common to both upload and commit."""
niklase@google.comda159d62011-05-30 11:51:34 +0000734 results = []
tkchin42f580e2015-11-26 23:18:23 -0800735 # Filter out files that are in objc or ios dirs from being cpplint-ed since
736 # they do not follow C++ lint rules.
737 black_list = input_api.DEFAULT_BLACK_LIST + (
738 r".*\bobjc[\\\/].*",
Kári Tristan Helgason3fa35172016-09-09 08:55:05 +0000739 r".*objc\.[hcm]+$",
tkchin42f580e2015-11-26 23:18:23 -0800740 )
741 source_file_filter = lambda x: input_api.FilterSourceFile(x, None, black_list)
charujain9893e252017-09-14 13:33:22 +0200742 results.extend(CheckApprovedFilesLintClean(
tkchin42f580e2015-11-26 23:18:23 -0800743 input_api, output_api, source_file_filter))
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200744 results.extend(input_api.canned_checks.CheckLicense(
745 input_api, output_api, _LicenseHeader(input_api)))
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000746 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
kjellander@webrtc.org177567c2016-12-22 10:40:28 +0100747 black_list=(r'^base[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200748 r'^build[\\\/].*\.py$',
749 r'^buildtools[\\\/].*\.py$',
kjellander38c65c82017-04-12 22:43:38 -0700750 r'^infra[\\\/].*\.py$',
Henrik Kjellander0779e8f2016-12-22 12:01:17 +0100751 r'^ios[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200752 r'^out.*[\\\/].*\.py$',
753 r'^testing[\\\/].*\.py$',
754 r'^third_party[\\\/].*\.py$',
kjellander@webrtc.org177567c2016-12-22 10:40:28 +0100755 r'^tools[\\\/].*\.py$',
kjellanderafd54942016-12-17 12:21:39 -0800756 # TODO(phoglund): should arguably be checked.
Henrik Kjellander90fd7d82017-05-09 08:30:10 +0200757 r'^tools_webrtc[\\\/]mb[\\\/].*\.py$',
758 r'^tools_webrtc[\\\/]valgrind[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200759 r'^xcodebuild.*[\\\/].*\.py$',),
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200760 pylintrc='pylintrc'))
kjellander569cf942016-02-11 05:02:59 -0800761
nisse3d21e232016-09-02 03:07:06 -0700762 # TODO(nisse): talk/ is no more, so make below checks simpler?
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200763 # WebRTC can't use the presubmit_canned_checks.PanProjectChecks function since
764 # we need to have different license checks in talk/ and webrtc/ directories.
765 # Instead, hand-picked checks are included below.
Henrik Kjellander63224672015-09-08 08:03:56 +0200766
tkchin3cd9a302016-06-08 12:40:28 -0700767 # .m and .mm files are ObjC files. For simplicity we will consider .h files in
768 # ObjC subdirectories ObjC headers.
769 objc_filter_list = (r'.+\.m$', r'.+\.mm$', r'.+objc\/.+\.h$')
Henrik Kjellanderb4af3d62016-11-16 20:11:29 +0100770 # Skip long-lines check for DEPS and GN files.
771 build_file_filter_list = (r'.+\.gn$', r'.+\.gni$', 'DEPS')
Artem Titova04d1402018-05-11 11:23:00 +0200772 # Also we will skip most checks for third_party directory.
773 third_party_filter_list = (r'^third_party[\\\/].+',)
tkchin3cd9a302016-06-08 12:40:28 -0700774 eighty_char_sources = lambda x: input_api.FilterSourceFile(x,
Artem Titova04d1402018-05-11 11:23:00 +0200775 black_list=build_file_filter_list + objc_filter_list +
776 third_party_filter_list)
tkchin3cd9a302016-06-08 12:40:28 -0700777 hundred_char_sources = lambda x: input_api.FilterSourceFile(x,
778 white_list=objc_filter_list)
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000779 results.extend(input_api.canned_checks.CheckLongLines(
tkchin3cd9a302016-06-08 12:40:28 -0700780 input_api, output_api, maxlen=80, source_file_filter=eighty_char_sources))
781 results.extend(input_api.canned_checks.CheckLongLines(
782 input_api, output_api, maxlen=100,
783 source_file_filter=hundred_char_sources))
784
Artem Titova04d1402018-05-11 11:23:00 +0200785 non_third_party_sources = lambda x: input_api.FilterSourceFile(x,
786 black_list=third_party_filter_list)
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000787 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
Artem Titova04d1402018-05-11 11:23:00 +0200788 input_api, output_api, source_file_filter=non_third_party_sources))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000789 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
Artem Titova04d1402018-05-11 11:23:00 +0200790 input_api, output_api, source_file_filter=non_third_party_sources))
kjellandere5dc62a2016-12-14 00:16:21 -0800791 results.extend(input_api.canned_checks.CheckAuthorizedAuthor(
792 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000793 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
Artem Titova04d1402018-05-11 11:23:00 +0200794 input_api, output_api, source_file_filter=non_third_party_sources))
charujain9893e252017-09-14 13:33:22 +0200795 results.extend(CheckNativeApiHeaderChanges(input_api, output_api))
Artem Titova04d1402018-05-11 11:23:00 +0200796 results.extend(CheckNoIOStreamInHeaders(
797 input_api, output_api, source_file_filter=non_third_party_sources))
798 results.extend(CheckNoPragmaOnce(
799 input_api, output_api, source_file_filter=non_third_party_sources))
800 results.extend(CheckNoFRIEND_TEST(
801 input_api, output_api, source_file_filter=non_third_party_sources))
802 results.extend(CheckGnChanges(
803 input_api, output_api, source_file_filter=non_third_party_sources))
804 results.extend(CheckUnwantedDependencies(
805 input_api, output_api, source_file_filter=non_third_party_sources))
806 results.extend(CheckJSONParseErrors(
807 input_api, output_api, source_file_filter=non_third_party_sources))
charujain9893e252017-09-14 13:33:22 +0200808 results.extend(RunPythonTests(input_api, output_api))
Artem Titova04d1402018-05-11 11:23:00 +0200809 results.extend(CheckUsageOfGoogleProtobufNamespace(
810 input_api, output_api, source_file_filter=non_third_party_sources))
811 results.extend(CheckOrphanHeaders(
812 input_api, output_api, source_file_filter=non_third_party_sources))
813 results.extend(CheckNewlineAtTheEndOfProtoFiles(
814 input_api, output_api, source_file_filter=non_third_party_sources))
815 results.extend(CheckNoStreamUsageIsAdded(
816 input_api, output_api, source_file_filter=non_third_party_sources))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000817 return results
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000818
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000819
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000820def CheckChangeOnUpload(input_api, output_api):
821 results = []
charujain9893e252017-09-14 13:33:22 +0200822 results.extend(CommonChecks(input_api, output_api))
Oleh Prypin920b6532017-10-05 11:28:51 +0200823 results.extend(CheckGnGen(input_api, output_api))
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200824 results.extend(
825 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
niklase@google.comda159d62011-05-30 11:51:34 +0000826 return results
827
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000828
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000829def CheckChangeOnCommit(input_api, output_api):
niklase@google.com1198db92011-06-09 07:07:24 +0000830 results = []
charujain9893e252017-09-14 13:33:22 +0200831 results.extend(CommonChecks(input_api, output_api))
832 results.extend(VerifyNativeApiHeadersListIsValid(input_api, output_api))
niklase@google.com1198db92011-06-09 07:07:24 +0000833 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000834 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
835 input_api, output_api))
836 results.extend(input_api.canned_checks.CheckChangeHasDescription(
837 input_api, output_api))
charujain9893e252017-09-14 13:33:22 +0200838 results.extend(CheckChangeHasBugField(input_api, output_api))
839 results.extend(CheckCommitMessageBugEntry(input_api, output_api))
kjellander@webrtc.org12cb88c2014-02-13 11:53:43 +0000840 results.extend(input_api.canned_checks.CheckTreeIsOpen(
841 input_api, output_api,
842 json_url='http://webrtc-status.appspot.com/current?format=json'))
niklase@google.com1198db92011-06-09 07:07:24 +0000843 return results
mbonadei74973ed2017-05-09 07:58:05 -0700844
845
Artem Titova04d1402018-05-11 11:23:00 +0200846def CheckOrphanHeaders(input_api, output_api, source_file_filter):
mbonadei74973ed2017-05-09 07:58:05 -0700847 # We need to wait until we have an input_api object and use this
848 # roundabout construct to import prebubmit_checks_lib because this file is
849 # eval-ed and thus doesn't have __file__.
Patrik Höglund2f3f7222017-12-19 11:08:56 +0100850 error_msg = """{} should be listed in {}."""
mbonadei74973ed2017-05-09 07:58:05 -0700851 results = []
Patrik Höglund7e60de22018-01-09 14:22:00 +0100852 orphan_blacklist = [
853 os.path.join('tools_webrtc', 'ios', 'SDK'),
854 ]
Oleh Prypin2f33a562017-10-04 20:17:54 +0200855 with _AddToPath(input_api.os_path.join(
856 input_api.PresubmitLocalPath(), 'tools_webrtc', 'presubmit_checks_lib')):
mbonadei74973ed2017-05-09 07:58:05 -0700857 from check_orphan_headers import GetBuildGnPathFromFilePath
858 from check_orphan_headers import IsHeaderInBuildGn
mbonadei74973ed2017-05-09 07:58:05 -0700859
Artem Titova04d1402018-05-11 11:23:00 +0200860 file_filter = lambda x: input_api.FilterSourceFile(
861 x, black_list=orphan_blacklist) and source_file_filter(x)
862 for f in input_api.AffectedSourceFiles(file_filter):
Patrik Höglund7e60de22018-01-09 14:22:00 +0100863 if f.LocalPath().endswith('.h'):
mbonadei74973ed2017-05-09 07:58:05 -0700864 file_path = os.path.abspath(f.LocalPath())
865 root_dir = os.getcwd()
866 gn_file_path = GetBuildGnPathFromFilePath(file_path, os.path.exists,
867 root_dir)
868 in_build_gn = IsHeaderInBuildGn(file_path, gn_file_path)
869 if not in_build_gn:
870 results.append(output_api.PresubmitError(error_msg.format(
Patrik Höglund2f3f7222017-12-19 11:08:56 +0100871 f.LocalPath(), os.path.relpath(gn_file_path))))
mbonadei74973ed2017-05-09 07:58:05 -0700872 return results
Mirko Bonadei960fd5b2017-06-29 14:59:36 +0200873
874
Artem Titova04d1402018-05-11 11:23:00 +0200875def CheckNewlineAtTheEndOfProtoFiles(input_api, output_api,
876 source_file_filter):
Mirko Bonadei960fd5b2017-06-29 14:59:36 +0200877 """Checks that all .proto files are terminated with a newline."""
878 error_msg = 'File {} must end with exactly one newline.'
879 results = []
Artem Titova04d1402018-05-11 11:23:00 +0200880 file_filter = lambda x: input_api.FilterSourceFile(
881 x, white_list=(r'.+\.proto$',)) and source_file_filter(x)
882 for f in input_api.AffectedSourceFiles(file_filter):
Mirko Bonadei960fd5b2017-06-29 14:59:36 +0200883 file_path = f.LocalPath()
884 with open(file_path) as f:
885 lines = f.readlines()
Mirko Bonadeia730c1c2017-09-18 11:33:13 +0200886 if len(lines) > 0 and not lines[-1].endswith('\n'):
Mirko Bonadei960fd5b2017-06-29 14:59:36 +0200887 results.append(output_api.PresubmitError(error_msg.format(file_path)))
888 return results