blob: b949951d21ca7707d90915adb0cfc236d470bd8b [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.org85759802013-10-22 16:47:40 +00009import re
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +000010import sys
kjellander@webrtc.org85759802013-10-22 16:47:40 +000011
12
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000013def _CheckNoIOStreamInHeaders(input_api, output_api):
14 """Checks to make sure no .h files include <iostream>."""
15 files = []
16 pattern = input_api.re.compile(r'^#include\s*<iostream>',
17 input_api.re.MULTILINE)
18 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
19 if not f.LocalPath().endswith('.h'):
20 continue
21 contents = input_api.ReadFile(f)
22 if pattern.search(contents):
23 files.append(f)
24
25 if len(files):
26 return [ output_api.PresubmitError(
27 'Do not #include <iostream> in header files, since it inserts static ' +
28 'initialization into every file including the header. Instead, ' +
29 '#include <ostream>. See http://crbug.com/94794',
30 files) ]
31 return []
32
kjellander@webrtc.orge4158642014-08-06 09:11:18 +000033
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000034def _CheckNoFRIEND_TEST(input_api, output_api):
35 """Make sure that gtest's FRIEND_TEST() macro is not used, the
36 FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be
37 used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes."""
38 problems = []
39
40 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.h'))
41 for f in input_api.AffectedFiles(file_filter=file_filter):
42 for line_num, line in f.ChangedContents():
43 if 'FRIEND_TEST(' in line:
44 problems.append(' %s:%d' % (f.LocalPath(), line_num))
45
46 if not problems:
47 return []
48 return [output_api.PresubmitPromptWarning('WebRTC\'s code should not use '
49 'gtest\'s FRIEND_TEST() macro. Include testsupport/gtest_prod_util.h and '
50 'use FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems))]
51
kjellander@webrtc.orge4158642014-08-06 09:11:18 +000052
mflodman@webrtc.org2a452092012-07-01 05:55:23 +000053def _CheckApprovedFilesLintClean(input_api, output_api,
54 source_file_filter=None):
55 """Checks that all new or whitelisted .cc and .h files pass cpplint.py.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000056 This check is based on _CheckChangeLintsClean in
57 depot_tools/presubmit_canned_checks.py but has less filters and only checks
58 added files."""
59 result = []
60
61 # Initialize cpplint.
62 import cpplint
63 # Access to a protected member _XX of a client class
64 # pylint: disable=W0212
65 cpplint._cpplint_state.ResetErrorCounts()
66
67 # Justifications for each filter:
68 #
69 # - build/header_guard : WebRTC coding style says they should be prefixed
70 # with WEBRTC_, which is not possible to configure in
71 # cpplint.py.
72 cpplint._SetFilters('-build/header_guard')
73
74 # Use the strictest verbosity level for cpplint.py (level 1) which is the
75 # default when running cpplint.py from command line.
76 # To make it possible to work with not-yet-converted code, we're only applying
mflodman@webrtc.org2a452092012-07-01 05:55:23 +000077 # it to new (or moved/renamed) files and files listed in LINT_FOLDERS.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000078 verbosity_level = 1
79 files = []
80 for f in input_api.AffectedSourceFiles(source_file_filter):
81 # Note that moved/renamed files also count as added for svn.
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +000082 if (f.Action() == 'A'):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000083 files.append(f.AbsoluteLocalPath())
mflodman@webrtc.org2a452092012-07-01 05:55:23 +000084
kjellander@webrtc.org51198f12012-02-21 17:53:46 +000085 for file_name in files:
86 cpplint.ProcessFile(file_name, verbosity_level)
87
88 if cpplint._cpplint_state.error_count > 0:
89 if input_api.is_committing:
90 # TODO(kjellander): Change back to PresubmitError below when we're
91 # confident with the lint settings.
92 res_type = output_api.PresubmitPromptWarning
93 else:
94 res_type = output_api.PresubmitPromptWarning
95 result = [res_type('Changelist failed cpplint.py check.')]
96
97 return result
98
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +000099def _CheckNoRtcBaseDeps(input_api, gyp_files, output_api):
100 pattern = input_api.re.compile(r"base.gyp:rtc_base\s*'")
101 violating_files = []
102 for f in gyp_files:
henrike@webrtc.org36b0c1a2014-10-01 14:40:58 +0000103 gyp_exceptions = (
104 'base_tests.gyp',
105 'desktop_capture.gypi',
106 'libjingle.gyp',
107 'libjingle_tests.gyp'
108 'sound.gyp',
109 'webrtc_test_common.gyp',
110 'webrtc_tests.gypi',
111 )
112 if f.LocalPath().endswith(gyp_exceptions):
113 continue
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000114 contents = input_api.ReadFile(f)
115 if pattern.search(contents):
116 violating_files.append(f)
117 if violating_files:
118 return [output_api.PresubmitError(
119 'Depending on rtc_base is not allowed. Change your dependency to '
120 'rtc_base_approved and possibly sanitize and move the desired source '
121 'file(s) to rtc_base_approved.\nChanged GYP files:',
122 items=violating_files)]
123 return []
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000124
125def _CheckGypChanges(input_api, output_api):
126 source_file_filter = lambda x: input_api.FilterSourceFile(
127 x, white_list=(r'.+\.(gyp|gypi)$',))
128
129 gyp_files = []
130 for f in input_api.AffectedSourceFiles(source_file_filter):
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000131 gyp_files.append(f)
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000132
133 result = []
134 if gyp_files:
135 result.append(output_api.PresubmitNotifyResult(
136 'As you\'re changing GYP files: please make sure corresponding '
137 'BUILD.gn files are also updated.\nChanged GYP files:',
138 items=gyp_files))
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000139 result.extend(_CheckNoRtcBaseDeps(input_api, gyp_files, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000140 return result
141
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000142def _CheckUnwantedDependencies(input_api, output_api):
143 """Runs checkdeps on #include statements added in this
144 change. Breaking - rules is an error, breaking ! rules is a
145 warning.
146 """
147 # Copied from Chromium's src/PRESUBMIT.py.
148
149 # We need to wait until we have an input_api object and use this
150 # roundabout construct to import checkdeps because this file is
151 # eval-ed and thus doesn't have __file__.
152 original_sys_path = sys.path
153 try:
154 sys.path = sys.path + [input_api.os_path.join(
155 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
156 import checkdeps
157 from cpp_checker import CppChecker
158 from rules import Rule
159 finally:
160 # Restore sys.path to what it was before.
161 sys.path = original_sys_path
162
163 added_includes = []
164 for f in input_api.AffectedFiles():
165 if not CppChecker.IsCppFile(f.LocalPath()):
166 continue
167
168 changed_lines = [line for _line_num, line in f.ChangedContents()]
169 added_includes.append([f.LocalPath(), changed_lines])
170
171 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
172
173 error_descriptions = []
174 warning_descriptions = []
175 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
176 added_includes):
177 description_with_path = '%s\n %s' % (path, rule_description)
178 if rule_type == Rule.DISALLOW:
179 error_descriptions.append(description_with_path)
180 else:
181 warning_descriptions.append(description_with_path)
182
183 results = []
184 if error_descriptions:
185 results.append(output_api.PresubmitError(
186 'You added one or more #includes that violate checkdeps rules.',
187 error_descriptions))
188 if warning_descriptions:
189 results.append(output_api.PresubmitPromptOrNotify(
190 'You added one or more #includes of files that are temporarily\n'
191 'allowed but being removed. Can you avoid introducing the\n'
192 '#include? See relevant DEPS file(s) for details and contacts.',
193 warning_descriptions))
194 return results
195
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000196
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000197def _CommonChecks(input_api, output_api):
198 """Checks common to both upload and commit."""
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000199 # TODO(kjellander): Use presubmit_canned_checks.PanProjectChecks too.
niklase@google.comda159d62011-05-30 11:51:34 +0000200 results = []
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000201 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
202 black_list=(r'^.*gviz_api\.py$',
203 r'^.*gaeunit\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000204 # Embedded shell-script fakes out pylint.
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000205 r'^build/.*\.py$',
206 r'^buildtools/.*\.py$',
kjellander@webrtc.org89256622014-08-20 12:10:11 +0000207 r'^chromium/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000208 r'^out.*/.*\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000209 r'^talk/site_scons/site_tools/talk_linux.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000210 r'^testing/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000211 r'^third_party/.*\.py$',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000212 r'^tools/clang/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000213 r'^tools/gn/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000214 r'^tools/gyp/.*\.py$',
215 r'^tools/perf_expectations/.*\.py$',
phoglund@webrtc.org6d07ad92013-05-14 09:42:39 +0000216 r'^tools/protoc_wrapper/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000217 r'^tools/python/.*\.py$',
218 r'^tools/python_charts/data/.*\.py$',
kjellander@webrtc.org33654222013-08-22 07:57:00 +0000219 r'^tools/refactoring/.*\.py$',
kjellander@webrtc.orgf9bdbe32013-12-11 13:37:12 +0000220 r'^tools/swarming_client/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000221 # TODO(phoglund): should arguably be checked.
222 r'^tools/valgrind-webrtc/.*\.py$',
223 r'^tools/valgrind/.*\.py$',
224 # TODO(phoglund): should arguably be checked.
225 r'^webrtc/build/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000226 r'^xcodebuild.*/.*\.py$',),
227
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000228 disabled_warnings=['F0401', # Failed to import x
229 'E0611', # No package y in x
230 'W0232', # Class has no __init__ method
231 ]))
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000232 results.extend(input_api.canned_checks.CheckLongLines(
pbos@webrtc.orgf2e7bc62013-04-08 15:46:07 +0000233 input_api, output_api, maxlen=80))
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000234 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
235 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000236 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
237 input_api, output_api))
238 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
239 input_api, output_api))
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000240 results.extend(_CheckApprovedFilesLintClean(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000241 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
242 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000243 results.extend(_CheckGypChanges(input_api, output_api))
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000244 results.extend(_CheckUnwantedDependencies(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000245 return results
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000246
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000247
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000248def CheckChangeOnUpload(input_api, output_api):
249 results = []
250 results.extend(_CommonChecks(input_api, output_api))
niklase@google.comda159d62011-05-30 11:51:34 +0000251 return results
252
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000253
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000254def CheckChangeOnCommit(input_api, output_api):
niklase@google.com1198db92011-06-09 07:07:24 +0000255 results = []
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000256 results.extend(_CommonChecks(input_api, output_api))
niklase@google.com1198db92011-06-09 07:07:24 +0000257 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000258 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
259 input_api, output_api))
260 results.extend(input_api.canned_checks.CheckChangeHasDescription(
261 input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000262 results.extend(input_api.canned_checks.CheckChangeHasBugField(
263 input_api, output_api))
264 results.extend(input_api.canned_checks.CheckChangeHasTestField(
265 input_api, output_api))
kjellander@webrtc.org12cb88c2014-02-13 11:53:43 +0000266 results.extend(input_api.canned_checks.CheckTreeIsOpen(
267 input_api, output_api,
268 json_url='http://webrtc-status.appspot.com/current?format=json'))
niklase@google.com1198db92011-06-09 07:07:24 +0000269 return results
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000270
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000271
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000272def GetDefaultTryConfigs(bots=None):
273 """Returns a list of ('bot', set(['tests']), optionally filtered by [bots].
274
275 For WebRTC purposes, we always return an empty list of tests, since we want
276 to run all tests by default on all our trybots.
277 """
278 return { 'tryserver.webrtc': dict((bot, []) for bot in bots)}
279
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000280
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000281# pylint: disable=W0613
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000282def GetPreferredTryMasters(project, change):
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000283 files = change.LocalPaths()
284
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000285 android_gn_bots = [
286 'android_gn',
287 'android_gn_rel',
288 ]
kjellander@webrtc.orgcf2b3ac2013-12-20 21:20:42 +0000289 android_bots = [
290 'android',
kjellander@webrtc.org9359eda2014-06-08 17:55:51 +0000291 'android_arm64',
kjellander@webrtc.orgcf2b3ac2013-12-20 21:20:42 +0000292 'android_rel',
293 'android_clang',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000294 ] + android_gn_bots
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000295 ios_bots = [
296 'ios',
297 'ios_rel',
298 ]
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000299 linux_gn_bots = [
300 'linux_gn',
301 'linux_gn_rel',
302 ]
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000303 linux_bots = [
304 'linux',
305 'linux_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000306 'linux_baremetal',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000307 'linux_rel',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000308 'linux_tsan2',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000309 ] + linux_gn_bots
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000310 mac_bots = [
311 'mac',
312 'mac_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000313 'mac_baremetal',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000314 'mac_rel',
315 'mac_x64_rel',
316 ]
317 win_bots = [
318 'win',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000319 'win_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000320 'win_baremetal',
kjellander@webrtc.orga956ec22014-04-14 08:38:27 +0000321 'win_drmemory_light',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000322 'win_rel',
323 'win_x64_rel',
324 ]
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000325 if not files or all(re.search(r'[\\/]OWNERS$', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000326 return {}
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000327 if all(re.search(r'[\\/]BUILD.gn$', f) for f in files):
328 return GetDefaultTryConfigs(android_gn_bots + linux_gn_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000329 if all(re.search('\.(m|mm)$|(^|[/_])mac[/_.]', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000330 return GetDefaultTryConfigs(mac_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000331 if all(re.search('(^|[/_])win[/_.]', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000332 return GetDefaultTryConfigs(win_bots)
333 if all(re.search('(^|[/_])android[/_.]', f) for f in files):
334 return GetDefaultTryConfigs(android_bots)
335 if all(re.search('[/_]ios[/_.]', f) for f in files):
336 return GetDefaultTryConfigs(ios_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000337
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000338 return GetDefaultTryConfigs(android_bots + ios_bots + linux_bots + mac_bots +
339 win_bots)