blob: aa0c28f990a042fcbdf9e31897884d09b05d332c [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
kjellander@webrtc.orgaefe61a2014-12-08 13:00:30 +00009import os
kjellander@webrtc.org85759802013-10-22 16:47:40 +000010import re
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +000011import sys
kjellander@webrtc.org85759802013-10-22 16:47:40 +000012
13
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000014def _CheckNoIOStreamInHeaders(input_api, output_api):
15 """Checks to make sure no .h files include <iostream>."""
16 files = []
17 pattern = input_api.re.compile(r'^#include\s*<iostream>',
18 input_api.re.MULTILINE)
19 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
20 if not f.LocalPath().endswith('.h'):
21 continue
22 contents = input_api.ReadFile(f)
23 if pattern.search(contents):
24 files.append(f)
25
26 if len(files):
27 return [ output_api.PresubmitError(
28 'Do not #include <iostream> in header files, since it inserts static ' +
29 'initialization into every file including the header. Instead, ' +
30 '#include <ostream>. See http://crbug.com/94794',
31 files) ]
32 return []
33
kjellander@webrtc.orge4158642014-08-06 09:11:18 +000034
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000035def _CheckNoFRIEND_TEST(input_api, output_api):
36 """Make sure that gtest's FRIEND_TEST() macro is not used, the
37 FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be
38 used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes."""
39 problems = []
40
41 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.h'))
42 for f in input_api.AffectedFiles(file_filter=file_filter):
43 for line_num, line in f.ChangedContents():
44 if 'FRIEND_TEST(' in line:
45 problems.append(' %s:%d' % (f.LocalPath(), line_num))
46
47 if not problems:
48 return []
49 return [output_api.PresubmitPromptWarning('WebRTC\'s code should not use '
50 'gtest\'s FRIEND_TEST() macro. Include testsupport/gtest_prod_util.h and '
51 'use FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems))]
52
kjellander@webrtc.orge4158642014-08-06 09:11:18 +000053
mflodman@webrtc.org2a452092012-07-01 05:55:23 +000054def _CheckApprovedFilesLintClean(input_api, output_api,
55 source_file_filter=None):
56 """Checks that all new or whitelisted .cc and .h files pass cpplint.py.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000057 This check is based on _CheckChangeLintsClean in
58 depot_tools/presubmit_canned_checks.py but has less filters and only checks
59 added files."""
60 result = []
61
62 # Initialize cpplint.
63 import cpplint
64 # Access to a protected member _XX of a client class
65 # pylint: disable=W0212
66 cpplint._cpplint_state.ResetErrorCounts()
67
68 # Justifications for each filter:
69 #
70 # - build/header_guard : WebRTC coding style says they should be prefixed
71 # with WEBRTC_, which is not possible to configure in
72 # cpplint.py.
73 cpplint._SetFilters('-build/header_guard')
74
75 # Use the strictest verbosity level for cpplint.py (level 1) which is the
76 # default when running cpplint.py from command line.
77 # To make it possible to work with not-yet-converted code, we're only applying
mflodman@webrtc.org2a452092012-07-01 05:55:23 +000078 # it to new (or moved/renamed) files and files listed in LINT_FOLDERS.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000079 verbosity_level = 1
80 files = []
81 for f in input_api.AffectedSourceFiles(source_file_filter):
82 # Note that moved/renamed files also count as added for svn.
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +000083 if (f.Action() == 'A'):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000084 files.append(f.AbsoluteLocalPath())
mflodman@webrtc.org2a452092012-07-01 05:55:23 +000085
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000086 for file_name in files:
87 cpplint.ProcessFile(file_name, verbosity_level)
88
89 if cpplint._cpplint_state.error_count > 0:
90 if input_api.is_committing:
91 # TODO(kjellander): Change back to PresubmitError below when we're
92 # confident with the lint settings.
93 res_type = output_api.PresubmitPromptWarning
94 else:
95 res_type = output_api.PresubmitPromptWarning
96 result = [res_type('Changelist failed cpplint.py check.')]
97
98 return result
99
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000100def _CheckNoRtcBaseDeps(input_api, gyp_files, output_api):
101 pattern = input_api.re.compile(r"base.gyp:rtc_base\s*'")
102 violating_files = []
103 for f in gyp_files:
henrike@webrtc.org36b0c1a2014-10-01 14:40:58 +0000104 gyp_exceptions = (
105 'base_tests.gyp',
106 'desktop_capture.gypi',
107 'libjingle.gyp',
henrike@webrtc.org28af6412014-11-04 15:11:46 +0000108 'libjingle_tests.gyp',
henrike@webrtc.org36b0c1a2014-10-01 14:40:58 +0000109 'sound.gyp',
110 'webrtc_test_common.gyp',
111 'webrtc_tests.gypi',
112 )
113 if f.LocalPath().endswith(gyp_exceptions):
114 continue
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000115 contents = input_api.ReadFile(f)
116 if pattern.search(contents):
117 violating_files.append(f)
118 if violating_files:
119 return [output_api.PresubmitError(
120 'Depending on rtc_base is not allowed. Change your dependency to '
121 'rtc_base_approved and possibly sanitize and move the desired source '
122 'file(s) to rtc_base_approved.\nChanged GYP files:',
123 items=violating_files)]
124 return []
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000125
126def _CheckGypChanges(input_api, output_api):
127 source_file_filter = lambda x: input_api.FilterSourceFile(
128 x, white_list=(r'.+\.(gyp|gypi)$',))
129
130 gyp_files = []
131 for f in input_api.AffectedSourceFiles(source_file_filter):
kjellander@webrtc.org3398a4a2014-11-24 10:05:37 +0000132 if f.LocalPath().startswith('webrtc'):
133 gyp_files.append(f)
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000134
135 result = []
136 if gyp_files:
137 result.append(output_api.PresubmitNotifyResult(
138 'As you\'re changing GYP files: please make sure corresponding '
139 'BUILD.gn files are also updated.\nChanged GYP files:',
140 items=gyp_files))
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000141 result.extend(_CheckNoRtcBaseDeps(input_api, gyp_files, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000142 return result
143
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000144def _CheckUnwantedDependencies(input_api, output_api):
145 """Runs checkdeps on #include statements added in this
146 change. Breaking - rules is an error, breaking ! rules is a
147 warning.
148 """
149 # Copied from Chromium's src/PRESUBMIT.py.
150
151 # We need to wait until we have an input_api object and use this
152 # roundabout construct to import checkdeps because this file is
153 # eval-ed and thus doesn't have __file__.
154 original_sys_path = sys.path
155 try:
kjellander@webrtc.orgaefe61a2014-12-08 13:00:30 +0000156 checkdeps_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
157 'buildtools', 'checkdeps')
158 if not os.path.exists(checkdeps_path):
159 return [output_api.PresubmitError(
160 'Cannot find checkdeps at %s\nHave you run "gclient sync" to '
161 'download Chromium and setup the symlinks?' % checkdeps_path)]
162 sys.path.append(checkdeps_path)
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000163 import checkdeps
164 from cpp_checker import CppChecker
165 from rules import Rule
166 finally:
167 # Restore sys.path to what it was before.
168 sys.path = original_sys_path
169
170 added_includes = []
171 for f in input_api.AffectedFiles():
172 if not CppChecker.IsCppFile(f.LocalPath()):
173 continue
174
175 changed_lines = [line for _line_num, line in f.ChangedContents()]
176 added_includes.append([f.LocalPath(), changed_lines])
177
178 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
179
180 error_descriptions = []
181 warning_descriptions = []
182 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
183 added_includes):
184 description_with_path = '%s\n %s' % (path, rule_description)
185 if rule_type == Rule.DISALLOW:
186 error_descriptions.append(description_with_path)
187 else:
188 warning_descriptions.append(description_with_path)
189
190 results = []
191 if error_descriptions:
192 results.append(output_api.PresubmitError(
193 'You added one or more #includes that violate checkdeps rules.',
194 error_descriptions))
195 if warning_descriptions:
196 results.append(output_api.PresubmitPromptOrNotify(
197 'You added one or more #includes of files that are temporarily\n'
198 'allowed but being removed. Can you avoid introducing the\n'
199 '#include? See relevant DEPS file(s) for details and contacts.',
200 warning_descriptions))
201 return results
202
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000203
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000204def _CommonChecks(input_api, output_api):
205 """Checks common to both upload and commit."""
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000206 # TODO(kjellander): Use presubmit_canned_checks.PanProjectChecks too.
niklase@google.comda159d62011-05-30 11:51:34 +0000207 results = []
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000208 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
209 black_list=(r'^.*gviz_api\.py$',
210 r'^.*gaeunit\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000211 # Embedded shell-script fakes out pylint.
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000212 r'^build/.*\.py$',
213 r'^buildtools/.*\.py$',
kjellander@webrtc.org89256622014-08-20 12:10:11 +0000214 r'^chromium/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000215 r'^out.*/.*\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000216 r'^talk/site_scons/site_tools/talk_linux.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000217 r'^testing/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000218 r'^third_party/.*\.py$',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000219 r'^tools/clang/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000220 r'^tools/gn/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000221 r'^tools/gyp/.*\.py$',
222 r'^tools/perf_expectations/.*\.py$',
phoglund@webrtc.org6d07ad92013-05-14 09:42:39 +0000223 r'^tools/protoc_wrapper/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000224 r'^tools/python/.*\.py$',
225 r'^tools/python_charts/data/.*\.py$',
kjellander@webrtc.org33654222013-08-22 07:57:00 +0000226 r'^tools/refactoring/.*\.py$',
kjellander@webrtc.orgf9bdbe32013-12-11 13:37:12 +0000227 r'^tools/swarming_client/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000228 # TODO(phoglund): should arguably be checked.
229 r'^tools/valgrind-webrtc/.*\.py$',
230 r'^tools/valgrind/.*\.py$',
231 # TODO(phoglund): should arguably be checked.
232 r'^webrtc/build/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000233 r'^xcodebuild.*/.*\.py$',),
234
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000235 disabled_warnings=['F0401', # Failed to import x
236 'E0611', # No package y in x
237 'W0232', # Class has no __init__ method
238 ]))
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000239 results.extend(input_api.canned_checks.CheckLongLines(
pbos@webrtc.orgf2e7bc62013-04-08 15:46:07 +0000240 input_api, output_api, maxlen=80))
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000241 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
242 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000243 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
244 input_api, output_api))
245 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
246 input_api, output_api))
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000247 results.extend(_CheckApprovedFilesLintClean(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000248 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
249 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000250 results.extend(_CheckGypChanges(input_api, output_api))
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000251 results.extend(_CheckUnwantedDependencies(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000252 return results
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000253
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000254
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000255def CheckChangeOnUpload(input_api, output_api):
256 results = []
257 results.extend(_CommonChecks(input_api, output_api))
niklase@google.comda159d62011-05-30 11:51:34 +0000258 return results
259
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000260
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000261def CheckChangeOnCommit(input_api, output_api):
niklase@google.com1198db92011-06-09 07:07:24 +0000262 results = []
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000263 results.extend(_CommonChecks(input_api, output_api))
niklase@google.com1198db92011-06-09 07:07:24 +0000264 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000265 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
266 input_api, output_api))
267 results.extend(input_api.canned_checks.CheckChangeHasDescription(
268 input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000269 results.extend(input_api.canned_checks.CheckChangeHasBugField(
270 input_api, output_api))
271 results.extend(input_api.canned_checks.CheckChangeHasTestField(
272 input_api, output_api))
kjellander@webrtc.org12cb88c2014-02-13 11:53:43 +0000273 results.extend(input_api.canned_checks.CheckTreeIsOpen(
274 input_api, output_api,
275 json_url='http://webrtc-status.appspot.com/current?format=json'))
niklase@google.com1198db92011-06-09 07:07:24 +0000276 return results
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000277
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000278
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000279def GetDefaultTryConfigs(bots=None):
280 """Returns a list of ('bot', set(['tests']), optionally filtered by [bots].
281
282 For WebRTC purposes, we always return an empty list of tests, since we want
283 to run all tests by default on all our trybots.
284 """
285 return { 'tryserver.webrtc': dict((bot, []) for bot in bots)}
286
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000287
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000288# pylint: disable=W0613
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000289def GetPreferredTryMasters(project, change):
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000290 files = change.LocalPaths()
291
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000292 android_gn_bots = [
293 'android_gn',
294 'android_gn_rel',
295 ]
kjellander@webrtc.orgcf2b3ac2013-12-20 21:20:42 +0000296 android_bots = [
297 'android',
kjellander@webrtc.org9359eda2014-06-08 17:55:51 +0000298 'android_arm64',
kjellander@webrtc.orgcf2b3ac2013-12-20 21:20:42 +0000299 'android_rel',
300 'android_clang',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000301 ] + android_gn_bots
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000302 ios_bots = [
303 'ios',
kjellander@webrtc.orgd91d3592014-12-08 07:05:38 +0000304 'ios_arm64',
305 'ios_arm64_rel',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000306 'ios_rel',
307 ]
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000308 linux_gn_bots = [
309 'linux_gn',
310 'linux_gn_rel',
311 ]
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000312 linux_bots = [
313 'linux',
314 'linux_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000315 'linux_baremetal',
kjellander@webrtc.org3b839d02014-10-24 21:41:24 +0000316 'linux_msan',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000317 'linux_rel',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000318 'linux_tsan2',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000319 ] + linux_gn_bots
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000320 mac_bots = [
321 'mac',
322 'mac_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000323 'mac_baremetal',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000324 'mac_rel',
325 'mac_x64_rel',
326 ]
327 win_bots = [
328 'win',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000329 'win_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000330 'win_baremetal',
kjellander@webrtc.orga956ec22014-04-14 08:38:27 +0000331 'win_drmemory_light',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000332 'win_rel',
333 'win_x64_rel',
334 ]
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000335 if not files or all(re.search(r'[\\/]OWNERS$', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000336 return {}
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000337 if all(re.search(r'[\\/]BUILD.gn$', f) for f in files):
338 return GetDefaultTryConfigs(android_gn_bots + linux_gn_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000339 if all(re.search('\.(m|mm)$|(^|[/_])mac[/_.]', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000340 return GetDefaultTryConfigs(mac_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000341 if all(re.search('(^|[/_])win[/_.]', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000342 return GetDefaultTryConfigs(win_bots)
343 if all(re.search('(^|[/_])android[/_.]', f) for f in files):
344 return GetDefaultTryConfigs(android_bots)
345 if all(re.search('[/_]ios[/_.]', f) for f in files):
346 return GetDefaultTryConfigs(ios_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000347
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000348 return GetDefaultTryConfigs(android_bots + ios_bots + linux_bots + mac_bots +
349 win_bots)