1 # Copyright 2014 The Chromium Authors
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Presubmit script for Chromium browser code."""
10 # Checks whether an autofill-related browsertest fixture class inherits from
11 # either InProcessBrowserTest or AndroidBrowserTest without having a member of
12 # type `autofill::test::AutofillBrowserTestEnvironment`. In that case, the
13 # functions registers a presubmit warning.
14 def _CheckNoAutofillBrowserTestsWithoutAutofillBrowserTestEnvironment(
15 input_api, output_api):
16 autofill_files_pattern = re.compile(
17 r'(autofill|password_manager).*\.(mm|cc|h)')
18 concerned_files = [(f, input_api.ReadFile(f))
19 for f in input_api.AffectedFiles(include_deletes=False)
20 if autofill_files_pattern.search(f.LocalPath())]
23 class_name = r'^( *)(class|struct)\s+\w+\s*:\s*'
24 target_base = r'[^\{]*\bpublic\s+(InProcess|Android)BrowserTest[^\{]*\{'
25 class_declaration_pattern = re.compile(
26 class_name + target_base, re.MULTILINE)
27 for autofill_file, file_content in concerned_files:
28 for class_match in re.finditer(class_declaration_pattern, file_content):
29 indentation = class_match.group(1)
30 class_end_pattern = re.compile(
31 r'^' + indentation + r'\};$', re.MULTILINE)
32 class_end = class_end_pattern.search(file_content[class_match.start():])
34 corresponding_subclass = (
35 '' if class_end is None else
38 class_match.start() + class_end.end()])
40 required_member_pattern = re.compile(
42 r' (::)?(autofill::)?test::AutofillBrowserTestEnvironment\s+\w+_;',
44 if not required_member_pattern.search(corresponding_subclass):
45 warning_files.append(autofill_file)
47 return [output_api.PresubmitPromptWarning(
48 'Consider adding a member autofill::test::AutofillBrowserTestEnvironment '
49 'to the test fixtures that derive from InProcessBrowserTest or '
50 'AndroidBrowserTest in order to disable kAutofillServerCommunication in '
52 warning_files)] if len(warning_files) else []
54 def _RunHistogramChecks(input_api, output_api, histogram_name):
56 # Setup sys.path so that we can call histograms code.
58 original_sys_path = sys.path
59 sys.path = sys.path + [input_api.os_path.join(
60 input_api.change.RepositoryRoot(),
61 'tools', 'metrics', 'histograms')]
65 import presubmit_bad_message_reasons
66 results.extend(presubmit_bad_message_reasons.PrecheckBadMessage(input_api,
67 output_api, histogram_name))
71 return [output_api.PresubmitError('Could not verify histogram!')]
73 sys.path = original_sys_path
76 def _CheckUnwantedDependencies(input_api, output_api):
78 for f in input_api.AffectedFiles():
79 if not f.LocalPath().endswith('DEPS'):
82 for line_num, line in f.ChangedContents():
83 if not line.strip().startswith('#'):
84 m = re.search(r".*\/blink\/public\/web.*", line)
86 problems.append(m.group(0))
90 return [output_api.PresubmitPromptWarning(
91 'chrome/browser cannot depend on blink/public/web interfaces. ' +
92 'Use blink/public/common instead.',
96 def _CheckNoInteractiveUiTestLibInNonInteractiveUiTest(input_api, output_api):
97 """Makes sure that ui_controls related API are used only in
101 # There are interactive tests whose name ends with `_browsertest.cc`
102 # or `_browser_test.cc`.
103 files_to_skip = ((r'.*interactive_.*test\.cc',) +
104 input_api.DEFAULT_FILES_TO_SKIP)
105 def FileFilter(affected_file):
106 """Check non interactive_uitests only."""
107 return input_api.FilterSourceFile(
110 r'.*browsertest\.cc',
112 files_to_skip=files_to_skip)
114 ui_controls_includes =(
115 input_api.re.compile(
116 r'#include.*/(ui_controls.*h|interactive_test_utils.h)"'))
118 for f in input_api.AffectedFiles(include_deletes=False,
119 file_filter=FileFilter):
120 for line_num, line in f.ChangedContents():
121 m = re.search(ui_controls_includes, line)
123 problems.append(' %s:%d:%s' % (f.LocalPath(), line_num, m.group(0)))
129 ui_controls API can be used only in interactive_ui_tests.
130 If the test is in the interactive_ui_tests, please consider renaming
131 to xxx_interactive_uitest.cc"""
132 return [output_api.PresubmitPromptWarning(WARNING_MSG, items=problems)]
135 def _CheckForUselessExterns(input_api, output_api):
136 """Makes sure developers don't copy "extern const char kFoo[]" from
140 BAD_PATTERN = input_api.re.compile(r'^extern const')
142 def FileFilter(affected_file):
143 """Check only a particular list of files"""
144 return input_api.FilterSourceFile(
146 files_to_check=[r'chrome[/\\]browser[/\\]flag_descriptions\.cc']);
148 for f in input_api.AffectedFiles(include_deletes=False,
149 file_filter=FileFilter):
150 for _, line in f.ChangedContents():
151 if BAD_PATTERN.search(line):
157 WARNING_MSG ="""Do not write "extern const char" in these .cc files:"""
158 return [output_api.PresubmitPromptWarning(WARNING_MSG, items=problems)]
161 def _CommonChecks(input_api, output_api):
162 """Checks common to both upload and commit."""
165 _CheckNoAutofillBrowserTestsWithoutAutofillBrowserTestEnvironment(
166 input_api, output_api))
167 results.extend(_CheckUnwantedDependencies(input_api, output_api))
168 results.extend(_RunHistogramChecks(input_api, output_api,
169 "BadMessageReasonChrome"))
170 results.extend(_CheckNoInteractiveUiTestLibInNonInteractiveUiTest(
171 input_api, output_api))
172 results.extend(_CheckForUselessExterns(input_api, output_api))
175 def CheckChangeOnUpload(input_api, output_api):
176 return _CommonChecks(input_api, output_api)
178 def CheckChangeOnCommit(input_api, output_api):
179 return _CommonChecks(input_api, output_api)