blob: 2cefb3613a48c92fb2f8250710e8a481f468604e [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:
103 contents = input_api.ReadFile(f)
104 if pattern.search(contents):
105 violating_files.append(f)
106 if violating_files:
107 return [output_api.PresubmitError(
108 'Depending on rtc_base is not allowed. Change your dependency to '
109 'rtc_base_approved and possibly sanitize and move the desired source '
110 'file(s) to rtc_base_approved.\nChanged GYP files:',
111 items=violating_files)]
112 return []
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000113
114def _CheckGypChanges(input_api, output_api):
115 source_file_filter = lambda x: input_api.FilterSourceFile(
116 x, white_list=(r'.+\.(gyp|gypi)$',))
117
118 gyp_files = []
119 for f in input_api.AffectedSourceFiles(source_file_filter):
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000120 gyp_files.append(f)
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000121
122 result = []
123 if gyp_files:
124 result.append(output_api.PresubmitNotifyResult(
125 'As you\'re changing GYP files: please make sure corresponding '
126 'BUILD.gn files are also updated.\nChanged GYP files:',
127 items=gyp_files))
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000128 result.extend(_CheckNoRtcBaseDeps(input_api, gyp_files, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000129 return result
130
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000131def _CheckUnwantedDependencies(input_api, output_api):
132 """Runs checkdeps on #include statements added in this
133 change. Breaking - rules is an error, breaking ! rules is a
134 warning.
135 """
136 # Copied from Chromium's src/PRESUBMIT.py.
137
138 # We need to wait until we have an input_api object and use this
139 # roundabout construct to import checkdeps because this file is
140 # eval-ed and thus doesn't have __file__.
141 original_sys_path = sys.path
142 try:
143 sys.path = sys.path + [input_api.os_path.join(
144 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
145 import checkdeps
146 from cpp_checker import CppChecker
147 from rules import Rule
148 finally:
149 # Restore sys.path to what it was before.
150 sys.path = original_sys_path
151
152 added_includes = []
153 for f in input_api.AffectedFiles():
154 if not CppChecker.IsCppFile(f.LocalPath()):
155 continue
156
157 changed_lines = [line for _line_num, line in f.ChangedContents()]
158 added_includes.append([f.LocalPath(), changed_lines])
159
160 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
161
162 error_descriptions = []
163 warning_descriptions = []
164 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
165 added_includes):
166 description_with_path = '%s\n %s' % (path, rule_description)
167 if rule_type == Rule.DISALLOW:
168 error_descriptions.append(description_with_path)
169 else:
170 warning_descriptions.append(description_with_path)
171
172 results = []
173 if error_descriptions:
174 results.append(output_api.PresubmitError(
175 'You added one or more #includes that violate checkdeps rules.',
176 error_descriptions))
177 if warning_descriptions:
178 results.append(output_api.PresubmitPromptOrNotify(
179 'You added one or more #includes of files that are temporarily\n'
180 'allowed but being removed. Can you avoid introducing the\n'
181 '#include? See relevant DEPS file(s) for details and contacts.',
182 warning_descriptions))
183 return results
184
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000185
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000186def _CommonChecks(input_api, output_api):
187 """Checks common to both upload and commit."""
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000188 # TODO(kjellander): Use presubmit_canned_checks.PanProjectChecks too.
niklase@google.comda159d62011-05-30 11:51:34 +0000189 results = []
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000190 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
191 black_list=(r'^.*gviz_api\.py$',
192 r'^.*gaeunit\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000193 # Embedded shell-script fakes out pylint.
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000194 r'^build/.*\.py$',
195 r'^buildtools/.*\.py$',
kjellander@webrtc.org89256622014-08-20 12:10:11 +0000196 r'^chromium/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000197 r'^out.*/.*\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000198 r'^talk/site_scons/site_tools/talk_linux.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000199 r'^testing/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000200 r'^third_party/.*\.py$',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000201 r'^tools/clang/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000202 r'^tools/gn/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000203 r'^tools/gyp/.*\.py$',
204 r'^tools/perf_expectations/.*\.py$',
phoglund@webrtc.org6d07ad92013-05-14 09:42:39 +0000205 r'^tools/protoc_wrapper/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000206 r'^tools/python/.*\.py$',
207 r'^tools/python_charts/data/.*\.py$',
kjellander@webrtc.org33654222013-08-22 07:57:00 +0000208 r'^tools/refactoring/.*\.py$',
kjellander@webrtc.orgf9bdbe32013-12-11 13:37:12 +0000209 r'^tools/swarming_client/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000210 # TODO(phoglund): should arguably be checked.
211 r'^tools/valgrind-webrtc/.*\.py$',
212 r'^tools/valgrind/.*\.py$',
213 # TODO(phoglund): should arguably be checked.
214 r'^webrtc/build/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000215 r'^xcodebuild.*/.*\.py$',),
216
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000217 disabled_warnings=['F0401', # Failed to import x
218 'E0611', # No package y in x
219 'W0232', # Class has no __init__ method
220 ]))
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000221 results.extend(input_api.canned_checks.CheckLongLines(
pbos@webrtc.orgf2e7bc62013-04-08 15:46:07 +0000222 input_api, output_api, maxlen=80))
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000223 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
224 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000225 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
226 input_api, output_api))
227 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
228 input_api, output_api))
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000229 results.extend(_CheckApprovedFilesLintClean(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000230 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
231 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000232 results.extend(_CheckGypChanges(input_api, output_api))
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000233 results.extend(_CheckUnwantedDependencies(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000234 return results
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000235
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000236
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000237def CheckChangeOnUpload(input_api, output_api):
238 results = []
239 results.extend(_CommonChecks(input_api, output_api))
niklase@google.comda159d62011-05-30 11:51:34 +0000240 return results
241
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000242
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000243def CheckChangeOnCommit(input_api, output_api):
niklase@google.com1198db92011-06-09 07:07:24 +0000244 results = []
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000245 results.extend(_CommonChecks(input_api, output_api))
niklase@google.com1198db92011-06-09 07:07:24 +0000246 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000247 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
248 input_api, output_api))
249 results.extend(input_api.canned_checks.CheckChangeHasDescription(
250 input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000251 results.extend(input_api.canned_checks.CheckChangeHasBugField(
252 input_api, output_api))
253 results.extend(input_api.canned_checks.CheckChangeHasTestField(
254 input_api, output_api))
kjellander@webrtc.org12cb88c2014-02-13 11:53:43 +0000255 results.extend(input_api.canned_checks.CheckTreeIsOpen(
256 input_api, output_api,
257 json_url='http://webrtc-status.appspot.com/current?format=json'))
niklase@google.com1198db92011-06-09 07:07:24 +0000258 return results
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000259
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000260
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000261def GetDefaultTryConfigs(bots=None):
262 """Returns a list of ('bot', set(['tests']), optionally filtered by [bots].
263
264 For WebRTC purposes, we always return an empty list of tests, since we want
265 to run all tests by default on all our trybots.
266 """
267 return { 'tryserver.webrtc': dict((bot, []) for bot in bots)}
268
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000269
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000270# pylint: disable=W0613
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000271def GetPreferredTryMasters(project, change):
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000272 files = change.LocalPaths()
273
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000274 android_gn_bots = [
275 'android_gn',
276 'android_gn_rel',
277 ]
kjellander@webrtc.orgcf2b3ac2013-12-20 21:20:42 +0000278 android_bots = [
279 'android',
kjellander@webrtc.org9359eda2014-06-08 17:55:51 +0000280 'android_arm64',
kjellander@webrtc.orgcf2b3ac2013-12-20 21:20:42 +0000281 'android_rel',
282 'android_clang',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000283 ] + android_gn_bots
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000284 ios_bots = [
285 'ios',
286 'ios_rel',
287 ]
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000288 linux_gn_bots = [
289 'linux_gn',
290 'linux_gn_rel',
291 ]
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000292 linux_bots = [
293 'linux',
294 'linux_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000295 'linux_baremetal',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000296 'linux_rel',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000297 'linux_tsan2',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000298 ] + linux_gn_bots
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000299 mac_bots = [
300 'mac',
301 'mac_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000302 'mac_baremetal',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000303 'mac_rel',
304 'mac_x64_rel',
305 ]
306 win_bots = [
307 'win',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000308 'win_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000309 'win_baremetal',
kjellander@webrtc.orga956ec22014-04-14 08:38:27 +0000310 'win_drmemory_light',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000311 'win_rel',
312 'win_x64_rel',
313 ]
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000314 if not files or all(re.search(r'[\\/]OWNERS$', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000315 return {}
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000316 if all(re.search(r'[\\/]BUILD.gn$', f) for f in files):
317 return GetDefaultTryConfigs(android_gn_bots + linux_gn_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000318 if all(re.search('\.(m|mm)$|(^|[/_])mac[/_.]', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000319 return GetDefaultTryConfigs(mac_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000320 if all(re.search('(^|[/_])win[/_.]', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000321 return GetDefaultTryConfigs(win_bots)
322 if all(re.search('(^|[/_])android[/_.]', f) for f in files):
323 return GetDefaultTryConfigs(android_bots)
324 if all(re.search('[/_]ios[/_.]', f) for f in files):
325 return GetDefaultTryConfigs(ios_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000326
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000327 return GetDefaultTryConfigs(android_bots + ios_bots + linux_bots + mac_bots +
328 win_bots)