Creating NotificationService. Split test cases. Avoiding DCHECK for g_browser_process.
[chromium-blink-merge.git] / PRESUBMIT.py
blob63c81aa07dc11ffdacaed4980f93315e2240957b
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Top-level presubmit script for Chromium.
7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
8 for more details about the presubmit API built into gcl.
9 """
11 _EXCLUDED_PATHS = (
12 r"^breakpad[\\\/].*",
13 r"^net/tools/spdyshark/[\\\/].*",
14 r"^skia[\\\/].*",
15 r"^v8[\\\/].*",
16 r".*MakeFile$",
20 def _CheckNoInterfacesInBase(input_api, output_api):
21 """Checks to make sure no files in libbase.a have |@interface|."""
22 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE)
23 files = []
24 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
25 if (f.LocalPath().find('base/') != -1 and
26 f.LocalPath().find('base/test/') == -1 and
27 not f.LocalPath().endswith('_unittest.mm')):
28 contents = input_api.ReadFile(f)
29 if pattern.search(contents):
30 files.append(f)
32 if len(files):
33 return [ output_api.PresubmitError(
34 'Objective-C interfaces or categories are forbidden in libbase. ' +
35 'See http://groups.google.com/a/chromium.org/group/chromium-dev/' +
36 'browse_thread/thread/efb28c10435987fd',
37 files) ]
38 return []
41 def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
42 """Attempts to prevent use of functions intended only for testing in
43 non-testing code. For now this is just a best-effort implementation
44 that ignores header files and may have some false positives. A
45 better implementation would probably need a proper C++ parser.
46 """
47 # We only scan .cc files and the like, as the declaration of
48 # for-testing functions in header files are hard to distinguish from
49 # calls to such functions without a proper C++ parser.
50 source_extensions = r'\.(cc|cpp|cxx|mm)$'
51 file_inclusion_pattern = r'.+%s' % source_extensions
52 file_exclusion_pattern = (r'.+(_test_support|_(unit|browser|ui|perf)test)%s' %
53 source_extensions)
54 path_exclusion_pattern = r'.*[/\\](test|tool(s)?)[/\\].*'
56 base_function_pattern = r'ForTest(ing)?|for_test(ing)?'
57 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
58 exclusion_pattern = input_api.re.compile(
59 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
60 base_function_pattern, base_function_pattern))
62 def FilterFile(affected_file):
63 black_list = ((file_exclusion_pattern, path_exclusion_pattern, ) +
64 _EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
65 return input_api.FilterSourceFile(
66 affected_file,
67 white_list=(file_inclusion_pattern, ),
68 black_list=black_list)
70 problems = []
71 for f in input_api.AffectedSourceFiles(FilterFile):
72 local_path = f.LocalPath()
73 lines = input_api.ReadFile(f).splitlines()
74 line_number = 0
75 for line in lines:
76 if (inclusion_pattern.search(line) and
77 not exclusion_pattern.search(line)):
78 problems.append(
79 '%s:%d\n %s' % (local_path, line_number, line.strip()))
80 line_number += 1
82 if problems:
83 return [output_api.PresubmitPromptWarning(
84 'You might be calling functions intended only for testing from\n'
85 'production code. Please verify that the following usages are OK,\n'
86 'and email joi@chromium.org if you are seeing false positives:',
87 problems)]
88 else:
89 return []
92 def _CommonChecks(input_api, output_api):
93 """Checks common to both upload and commit."""
94 results = []
95 results.extend(input_api.canned_checks.PanProjectChecks(
96 input_api, output_api, excluded_paths=_EXCLUDED_PATHS))
97 results.extend(_CheckNoInterfacesInBase(input_api, output_api))
98 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
99 results.extend(
100 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
101 return results
104 def _CheckSubversionConfig(input_api, output_api):
105 """Verifies the subversion config file is correctly setup.
107 Checks that autoprops are enabled, returns an error otherwise.
109 join = input_api.os_path.join
110 if input_api.platform == 'win32':
111 appdata = input_api.environ.get('APPDATA', '')
112 if not appdata:
113 return [output_api.PresubmitError('%APPDATA% is not configured.')]
114 path = join(appdata, 'Subversion', 'config')
115 else:
116 home = input_api.environ.get('HOME', '')
117 if not home:
118 return [output_api.PresubmitError('$HOME is not configured.')]
119 path = join(home, '.subversion', 'config')
121 error_msg = (
122 'Please look at http://dev.chromium.org/developers/coding-style to\n'
123 'configure your subversion configuration file. This enables automatic\n'
124 'properties to simplify the project maintenance.\n'
125 'Pro-tip: just download and install\n'
126 'http://src.chromium.org/viewvc/chrome/trunk/tools/build/slave/config\n')
128 try:
129 lines = open(path, 'r').read().splitlines()
130 # Make sure auto-props is enabled and check for 2 Chromium standard
131 # auto-prop.
132 if (not '*.cc = svn:eol-style=LF' in lines or
133 not '*.pdf = svn:mime-type=application/pdf' in lines or
134 not 'enable-auto-props = yes' in lines):
135 return [
136 output_api.PresubmitNotifyResult(
137 'It looks like you have not configured your subversion config '
138 'file or it is not up-to-date.\n' + error_msg)
140 except (OSError, IOError):
141 return [
142 output_api.PresubmitNotifyResult(
143 'Can\'t find your subversion config file.\n' + error_msg)
145 return []
148 def _CheckAuthorizedAuthor(input_api, output_api):
149 """For non-googler/chromites committers, verify the author's email address is
150 in AUTHORS.
152 # TODO(maruel): Add it to input_api?
153 import fnmatch
155 author = input_api.change.author_email
156 if not author:
157 input_api.logging.info('No author, skipping AUTHOR check')
158 return []
159 authors_path = input_api.os_path.join(
160 input_api.PresubmitLocalPath(), 'AUTHORS')
161 valid_authors = (
162 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
163 for line in open(authors_path))
164 valid_authors = [item.group(1).lower() for item in valid_authors if item]
165 if input_api.verbose:
166 print 'Valid authors are %s' % ', '.join(valid_authors)
167 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors):
168 return [output_api.PresubmitPromptWarning(
169 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
170 '\n'
171 'http://www.chromium.org/developers/contributing-code and read the '
172 '"Legal" section\n'
173 'If you are a chromite, verify the contributor signed the CLA.') %
174 author)]
175 return []
178 def CheckChangeOnUpload(input_api, output_api):
179 results = []
180 results.extend(_CommonChecks(input_api, output_api))
181 return results
184 def CheckChangeOnCommit(input_api, output_api):
185 results = []
186 results.extend(_CommonChecks(input_api, output_api))
187 # TODO(thestig) temporarily disabled, doesn't work in third_party/
188 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories(
189 # input_api, output_api, sources))
190 # Make sure the tree is 'open'.
191 results.extend(input_api.canned_checks.CheckTreeIsOpen(
192 input_api,
193 output_api,
194 json_url='http://chromium-status.appspot.com/current?format=json'))
195 results.extend(input_api.canned_checks.CheckRietveldTryJobExecution(input_api,
196 output_api, 'http://codereview.chromium.org', ('win', 'linux', 'mac'),
197 'tryserver@chromium.org'))
199 results.extend(input_api.canned_checks.CheckChangeHasBugField(
200 input_api, output_api))
201 results.extend(input_api.canned_checks.CheckChangeHasTestField(
202 input_api, output_api))
203 results.extend(_CheckSubversionConfig(input_api, output_api))
204 return results
207 def GetPreferredTrySlaves():
208 return ['win', 'linux', 'mac']