blob: 363470c6d19ebeac95def16896c574b77e7501eb [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
kjellander@webrtc.orge4158642014-08-06 09:11:18 +000099
100def _CheckGypChanges(input_api, output_api):
101 source_file_filter = lambda x: input_api.FilterSourceFile(
102 x, white_list=(r'.+\.(gyp|gypi)$',))
103
104 gyp_files = []
105 for f in input_api.AffectedSourceFiles(source_file_filter):
106 gyp_files.append(f.LocalPath())
107
108 result = []
109 if gyp_files:
110 result.append(output_api.PresubmitNotifyResult(
111 'As you\'re changing GYP files: please make sure corresponding '
112 'BUILD.gn files are also updated.\nChanged GYP files:',
113 items=gyp_files))
114 return result
115
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000116def _CheckUnwantedDependencies(input_api, output_api):
117 """Runs checkdeps on #include statements added in this
118 change. Breaking - rules is an error, breaking ! rules is a
119 warning.
120 """
121 # Copied from Chromium's src/PRESUBMIT.py.
122
123 # We need to wait until we have an input_api object and use this
124 # roundabout construct to import checkdeps because this file is
125 # eval-ed and thus doesn't have __file__.
126 original_sys_path = sys.path
127 try:
128 sys.path = sys.path + [input_api.os_path.join(
129 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
130 import checkdeps
131 from cpp_checker import CppChecker
132 from rules import Rule
133 finally:
134 # Restore sys.path to what it was before.
135 sys.path = original_sys_path
136
137 added_includes = []
138 for f in input_api.AffectedFiles():
139 if not CppChecker.IsCppFile(f.LocalPath()):
140 continue
141
142 changed_lines = [line for _line_num, line in f.ChangedContents()]
143 added_includes.append([f.LocalPath(), changed_lines])
144
145 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
146
147 error_descriptions = []
148 warning_descriptions = []
149 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
150 added_includes):
151 description_with_path = '%s\n %s' % (path, rule_description)
152 if rule_type == Rule.DISALLOW:
153 error_descriptions.append(description_with_path)
154 else:
155 warning_descriptions.append(description_with_path)
156
157 results = []
158 if error_descriptions:
159 results.append(output_api.PresubmitError(
160 'You added one or more #includes that violate checkdeps rules.',
161 error_descriptions))
162 if warning_descriptions:
163 results.append(output_api.PresubmitPromptOrNotify(
164 'You added one or more #includes of files that are temporarily\n'
165 'allowed but being removed. Can you avoid introducing the\n'
166 '#include? See relevant DEPS file(s) for details and contacts.',
167 warning_descriptions))
168 return results
169
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000170
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000171def _CommonChecks(input_api, output_api):
172 """Checks common to both upload and commit."""
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000173 # TODO(kjellander): Use presubmit_canned_checks.PanProjectChecks too.
niklase@google.comda159d62011-05-30 11:51:34 +0000174 results = []
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000175 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
176 black_list=(r'^.*gviz_api\.py$',
177 r'^.*gaeunit\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000178 # Embedded shell-script fakes out pylint.
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000179 r'^build/.*\.py$',
180 r'^buildtools/.*\.py$',
kjellander@webrtc.org89256622014-08-20 12:10:11 +0000181 r'^chromium/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000182 r'^out.*/.*\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000183 r'^talk/site_scons/site_tools/talk_linux.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000184 r'^testing/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000185 r'^third_party/.*\.py$',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000186 r'^tools/clang/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000187 r'^tools/gn/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000188 r'^tools/gyp/.*\.py$',
189 r'^tools/perf_expectations/.*\.py$',
phoglund@webrtc.org6d07ad92013-05-14 09:42:39 +0000190 r'^tools/protoc_wrapper/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000191 r'^tools/python/.*\.py$',
192 r'^tools/python_charts/data/.*\.py$',
kjellander@webrtc.org33654222013-08-22 07:57:00 +0000193 r'^tools/refactoring/.*\.py$',
kjellander@webrtc.orgf9bdbe32013-12-11 13:37:12 +0000194 r'^tools/swarming_client/.*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000195 # TODO(phoglund): should arguably be checked.
196 r'^tools/valgrind-webrtc/.*\.py$',
197 r'^tools/valgrind/.*\.py$',
198 # TODO(phoglund): should arguably be checked.
199 r'^webrtc/build/.*\.py$',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000200 r'^xcodebuild.*/.*\.py$',),
201
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000202 disabled_warnings=['F0401', # Failed to import x
203 'E0611', # No package y in x
204 'W0232', # Class has no __init__ method
205 ]))
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000206 results.extend(input_api.canned_checks.CheckLongLines(
pbos@webrtc.orgf2e7bc62013-04-08 15:46:07 +0000207 input_api, output_api, maxlen=80))
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000208 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
209 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000210 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
211 input_api, output_api))
212 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
213 input_api, output_api))
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000214 results.extend(_CheckApprovedFilesLintClean(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000215 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
216 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000217 results.extend(_CheckGypChanges(input_api, output_api))
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000218 results.extend(_CheckUnwantedDependencies(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000219 return results
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000220
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000221
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000222def CheckChangeOnUpload(input_api, output_api):
223 results = []
224 results.extend(_CommonChecks(input_api, output_api))
niklase@google.comda159d62011-05-30 11:51:34 +0000225 return results
226
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000227
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000228def CheckChangeOnCommit(input_api, output_api):
niklase@google.com1198db92011-06-09 07:07:24 +0000229 results = []
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000230 results.extend(_CommonChecks(input_api, output_api))
niklase@google.com1198db92011-06-09 07:07:24 +0000231 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000232 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
233 input_api, output_api))
234 results.extend(input_api.canned_checks.CheckChangeHasDescription(
235 input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000236 results.extend(input_api.canned_checks.CheckChangeHasBugField(
237 input_api, output_api))
238 results.extend(input_api.canned_checks.CheckChangeHasTestField(
239 input_api, output_api))
kjellander@webrtc.org12cb88c2014-02-13 11:53:43 +0000240 results.extend(input_api.canned_checks.CheckTreeIsOpen(
241 input_api, output_api,
242 json_url='http://webrtc-status.appspot.com/current?format=json'))
niklase@google.com1198db92011-06-09 07:07:24 +0000243 return results
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000244
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000245
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000246def GetDefaultTryConfigs(bots=None):
247 """Returns a list of ('bot', set(['tests']), optionally filtered by [bots].
248
249 For WebRTC purposes, we always return an empty list of tests, since we want
250 to run all tests by default on all our trybots.
251 """
252 return { 'tryserver.webrtc': dict((bot, []) for bot in bots)}
253
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000254
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000255# pylint: disable=W0613
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000256def GetPreferredTryMasters(project, change):
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000257 files = change.LocalPaths()
258
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000259 android_gn_bots = [
260 'android_gn',
261 'android_gn_rel',
262 ]
kjellander@webrtc.orgcf2b3ac2013-12-20 21:20:42 +0000263 android_bots = [
264 'android',
kjellander@webrtc.org9359eda2014-06-08 17:55:51 +0000265 'android_arm64',
kjellander@webrtc.orgcf2b3ac2013-12-20 21:20:42 +0000266 'android_rel',
267 'android_clang',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000268 ] + android_gn_bots
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000269 ios_bots = [
270 'ios',
271 'ios_rel',
272 ]
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000273 linux_gn_bots = [
274 'linux_gn',
275 'linux_gn_rel',
276 ]
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000277 linux_bots = [
278 'linux',
279 'linux_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000280 'linux_baremetal',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000281 'linux_memcheck',
282 'linux_rel',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000283 'linux_tsan2',
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000284 ] + linux_gn_bots
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000285 mac_bots = [
286 'mac',
287 'mac_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000288 'mac_baremetal',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000289 'mac_rel',
290 'mac_x64_rel',
291 ]
292 win_bots = [
293 'win',
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000294 'win_asan',
kjellander@webrtc.org570bc3d2014-01-22 19:00:01 +0000295 'win_baremetal',
kjellander@webrtc.orga956ec22014-04-14 08:38:27 +0000296 'win_drmemory_light',
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000297 'win_rel',
298 'win_x64_rel',
299 ]
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000300 if not files or all(re.search(r'[\\/]OWNERS$', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000301 return {}
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000302 if all(re.search(r'[\\/]BUILD.gn$', f) for f in files):
303 return GetDefaultTryConfigs(android_gn_bots + linux_gn_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000304 if all(re.search('\.(m|mm)$|(^|[/_])mac[/_.]', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000305 return GetDefaultTryConfigs(mac_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000306 if all(re.search('(^|[/_])win[/_.]', f) for f in files):
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000307 return GetDefaultTryConfigs(win_bots)
308 if all(re.search('(^|[/_])android[/_.]', f) for f in files):
309 return GetDefaultTryConfigs(android_bots)
310 if all(re.search('[/_]ios[/_.]', f) for f in files):
311 return GetDefaultTryConfigs(ios_bots)
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000312
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000313 return GetDefaultTryConfigs(android_bots + ios_bots + linux_bots + mac_bots +
314 win_bots)