blob: b6951bf92fd2e28e454356aee6adc3c4e10ba7c5 [file] [log] [blame]
Christoffer Jansson4e8a7732022-02-08 09:01:12 +01001#!/usr/bin/env vpython3
Henrik Kjellandera18a3bf2017-09-15 11:19:10 +02002
3# Copyright 2017 The WebRTC project authors. All Rights Reserved.
4#
5# Use of this source code is governed by a BSD-style license
6# that can be found in the LICENSE file in the root of the source
7# tree. An additional intellectual property rights grant can be found
8# in the file PATENTS. All contributing project authors may
9# be found in the AUTHORS file in the root of the source tree.
10
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010011from __future__ import absolute_import
Mirko Bonadeia730c1c2017-09-18 11:33:13 +020012import os
13import shutil
14import tempfile
15import textwrap
charujain9893e252017-09-14 13:33:22 +020016import unittest
17
18import PRESUBMIT
Mirko Bonadei61880182017-10-12 15:12:35 +020019# pylint: disable=line-too-long
20from presubmit_test_mocks import MockInputApi, MockOutputApi, MockFile, MockChange
charujain9893e252017-09-14 13:33:22 +020021
22
Mirko Bonadei7de1eb72017-09-19 10:16:10 +020023class CheckBugEntryFieldTest(unittest.TestCase):
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010024 def testCommitMessageBugEntryWithNoError(self):
25 mock_input_api = MockInputApi()
26 mock_output_api = MockOutputApi()
27 mock_input_api.change = MockChange([], ['webrtc:1234'])
28 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api,
29 mock_output_api)
30 self.assertEqual(0, len(errors))
charujain9893e252017-09-14 13:33:22 +020031
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010032 def testCommitMessageBugEntryReturnError(self):
33 mock_input_api = MockInputApi()
34 mock_output_api = MockOutputApi()
35 mock_input_api.change = MockChange([], ['webrtc:1234', 'webrtc=4321'])
36 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api,
37 mock_output_api)
38 self.assertEqual(1, len(errors))
39 self.assertEqual(('Bogus Bug entry: webrtc=4321. Please specify'
40 ' the issue tracker prefix and the issue number,'
41 ' separated by a colon, e.g. webrtc:123 or'
42 ' chromium:12345.'), str(errors[0]))
charujain9893e252017-09-14 13:33:22 +020043
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010044 def testCommitMessageBugEntryWithoutPrefix(self):
45 mock_input_api = MockInputApi()
46 mock_output_api = MockOutputApi()
47 mock_input_api.change = MockChange([], ['1234'])
48 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api,
49 mock_output_api)
50 self.assertEqual(1, len(errors))
51 self.assertEqual(('Bug entry requires issue tracker prefix, '
52 'e.g. webrtc:1234'), str(errors[0]))
Mirko Bonadei61880182017-10-12 15:12:35 +020053
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010054 def testCommitMessageBugEntryIsNone(self):
55 mock_input_api = MockInputApi()
56 mock_output_api = MockOutputApi()
57 mock_input_api.change = MockChange([], ['None'])
58 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api,
59 mock_output_api)
60 self.assertEqual(0, len(errors))
charujain9893e252017-09-14 13:33:22 +020061
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010062 def testCommitMessageBugEntrySupportInternalBugReference(self):
63 mock_input_api = MockInputApi()
64 mock_output_api = MockOutputApi()
65 mock_input_api.change.BUG = 'b/12345'
66 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api,
67 mock_output_api)
68 self.assertEqual(0, len(errors))
69 mock_input_api.change.BUG = 'b/12345, webrtc:1234'
70 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api,
71 mock_output_api)
72 self.assertEqual(0, len(errors))
charujain81a58c72017-09-25 13:25:45 +020073
charujain9893e252017-09-14 13:33:22 +020074
Mirko Bonadei7de1eb72017-09-19 10:16:10 +020075class CheckNewlineAtTheEndOfProtoFilesTest(unittest.TestCase):
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010076 def setUp(self):
77 self.tmp_dir = tempfile.mkdtemp()
78 self.proto_file_path = os.path.join(self.tmp_dir, 'foo.proto')
79 self.input_api = MockInputApi()
80 self.output_api = MockOutputApi()
Mirko Bonadeia730c1c2017-09-18 11:33:13 +020081
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010082 def tearDown(self):
83 shutil.rmtree(self.tmp_dir, ignore_errors=True)
Mirko Bonadeia730c1c2017-09-18 11:33:13 +020084
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010085 def testErrorIfProtoFileDoesNotEndWithNewline(self):
86 self._GenerateProtoWithoutNewlineAtTheEnd()
87 self.input_api.files = [MockFile(self.proto_file_path)]
88 errors = PRESUBMIT.CheckNewlineAtTheEndOfProtoFiles(
89 self.input_api, self.output_api, lambda x: True)
90 self.assertEqual(1, len(errors))
91 self.assertEqual(
92 'File %s must end with exactly one newline.' % self.proto_file_path,
93 str(errors[0]))
Mirko Bonadeia730c1c2017-09-18 11:33:13 +020094
Christoffer Jansson4e8a7732022-02-08 09:01:12 +010095 def testNoErrorIfProtoFileEndsWithNewline(self):
96 self._GenerateProtoWithNewlineAtTheEnd()
97 self.input_api.files = [MockFile(self.proto_file_path)]
98 errors = PRESUBMIT.CheckNewlineAtTheEndOfProtoFiles(
99 self.input_api, self.output_api, lambda x: True)
100 self.assertEqual(0, len(errors))
Mirko Bonadeia730c1c2017-09-18 11:33:13 +0200101
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100102 def _GenerateProtoWithNewlineAtTheEnd(self):
103 with open(self.proto_file_path, 'w') as f:
104 f.write(
105 textwrap.dedent("""
Mirko Bonadeia730c1c2017-09-18 11:33:13 +0200106 syntax = "proto2";
107 option optimize_for = LITE_RUNTIME;
108 package webrtc.audioproc;
109 """))
110
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100111 def _GenerateProtoWithoutNewlineAtTheEnd(self):
112 with open(self.proto_file_path, 'w') as f:
113 f.write(
114 textwrap.dedent("""
Mirko Bonadeia730c1c2017-09-18 11:33:13 +0200115 syntax = "proto2";
116 option optimize_for = LITE_RUNTIME;
117 package webrtc.audioproc;"""))
118
119
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200120class CheckNoMixingSourcesTest(unittest.TestCase):
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100121 def setUp(self):
122 self.tmp_dir = tempfile.mkdtemp()
123 self.file_path = os.path.join(self.tmp_dir, 'BUILD.gn')
124 self.input_api = MockInputApi()
125 self.output_api = MockOutputApi()
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200126
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100127 def tearDown(self):
128 shutil.rmtree(self.tmp_dir, ignore_errors=True)
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200129
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100130 def testErrorIfCAndCppAreMixed(self):
131 self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.cc', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200132
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100133 def testErrorIfCAndObjCAreMixed(self):
134 self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.m', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200135
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100136 def testErrorIfCAndObjCppAreMixed(self):
137 self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.mm', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200138
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100139 def testErrorIfCppAndObjCAreMixed(self):
140 self._AssertNumberOfErrorsWithSources(1, ['foo.cc', 'bar.m', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200141
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100142 def testErrorIfCppAndObjCppAreMixed(self):
143 self._AssertNumberOfErrorsWithSources(1, ['foo.cc', 'bar.mm', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200144
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100145 def testNoErrorIfOnlyC(self):
146 self._AssertNumberOfErrorsWithSources(0, ['foo.c', 'bar.c', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200147
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100148 def testNoErrorIfOnlyCpp(self):
149 self._AssertNumberOfErrorsWithSources(0, ['foo.cc', 'bar.cc', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200150
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100151 def testNoErrorIfOnlyObjC(self):
152 self._AssertNumberOfErrorsWithSources(0, ['foo.m', 'bar.m', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200153
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100154 def testNoErrorIfOnlyObjCpp(self):
155 self._AssertNumberOfErrorsWithSources(0, ['foo.mm', 'bar.mm', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200156
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100157 def testNoErrorIfObjCAndObjCppAreMixed(self):
158 self._AssertNumberOfErrorsWithSources(0, ['foo.m', 'bar.mm', 'bar.h'])
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200159
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100160 def testNoErrorIfSourcesAreInExclusiveIfBranches(self):
161 self._GenerateBuildFile(
162 textwrap.dedent("""
Mirko Bonadei86d053c2019-10-17 21:32:04 +0200163 rtc_library("bar_foo") {
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200164 if (is_win) {
165 sources = [
166 "bar.cc",
167 ],
168 }
169 if (is_ios) {
170 sources = [
171 "bar.mm",
172 ],
173 }
174 }
Mirko Bonadei86d053c2019-10-17 21:32:04 +0200175 rtc_library("foo_bar") {
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200176 if (is_win) {
177 sources = [
178 "foo.cc",
179 ],
180 }
181 if (is_ios) {
182 sources = [
183 "foo.mm",
184 ],
185 }
186 }
187 """))
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100188 self.input_api.files = [MockFile(self.file_path)]
189 errors = PRESUBMIT.CheckNoMixingSources(self.input_api,
190 [MockFile(self.file_path)],
191 self.output_api)
192 self.assertEqual(0, len(errors))
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200193
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100194 def testErrorIfSourcesAreNotInExclusiveIfBranches(self):
195 self._GenerateBuildFile(
196 textwrap.dedent("""
Mirko Bonadei86d053c2019-10-17 21:32:04 +0200197 rtc_library("bar_foo") {
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200198 if (is_win) {
199 sources = [
200 "bar.cc",
201 ],
202 }
203 if (foo_bar) {
204 sources += [
205 "bar.mm",
206 ],
207 }
208 }
Mirko Bonadei86d053c2019-10-17 21:32:04 +0200209 rtc_library("foo_bar") {
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200210 if (is_win) {
211 sources = [
212 "foo.cc",
213 ],
214 }
215 if (foo_bar) {
216 sources += [
217 "foo.mm",
218 ],
219 }
220 if (is_ios) {
221 sources = [
222 "bar.m",
223 "bar.c",
224 ],
225 }
226 }
227 """))
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100228 self.input_api.files = [MockFile(self.file_path)]
229 errors = PRESUBMIT.CheckNoMixingSources(self.input_api,
230 [MockFile(self.file_path)],
231 self.output_api)
232 self.assertEqual(1, len(errors))
233 self.assertTrue('bar.cc' in str(errors[0]))
234 self.assertTrue('bar.mm' in str(errors[0]))
235 self.assertTrue('foo.cc' in str(errors[0]))
236 self.assertTrue('foo.mm' in str(errors[0]))
237 self.assertTrue('bar.m' in str(errors[0]))
238 self.assertTrue('bar.c' in str(errors[0]))
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200239
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100240 def _AssertNumberOfErrorsWithSources(self, number_of_errors, sources):
241 assert len(sources) == 3, 'This function accepts a list of 3 source files'
242 self._GenerateBuildFile(
243 textwrap.dedent("""
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200244 rtc_static_library("bar_foo") {
245 sources = [
246 "%s",
247 "%s",
248 "%s",
249 ],
250 }
Mirko Bonadei86d053c2019-10-17 21:32:04 +0200251 rtc_library("foo_bar") {
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200252 sources = [
253 "%s",
254 "%s",
255 "%s",
256 ],
257 }
258 """ % (tuple(sources) * 2)))
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100259 self.input_api.files = [MockFile(self.file_path)]
260 errors = PRESUBMIT.CheckNoMixingSources(self.input_api,
261 [MockFile(self.file_path)],
262 self.output_api)
263 self.assertEqual(number_of_errors, len(errors))
264 if number_of_errors == 1:
265 for source in sources:
266 if not source.endswith('.h'):
267 self.assertTrue(source in str(errors[0]))
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200268
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100269 def _GenerateBuildFile(self, content):
270 with open(self.file_path, 'w') as f:
271 f.write(content)
Mirko Bonadei4dc4e252017-09-19 13:49:16 +0200272
273
Mirko Bonadeia6395132021-07-22 17:35:59 +0200274class CheckAssertUsageTest(unittest.TestCase):
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100275 def setUp(self):
276 self.input_api = MockInputApi()
277 self.output_api = MockOutputApi()
278 self._content_with_assert = ['void Foo() {', ' assert(true);', '}']
279 self._content_without_assert = ['void Foo() {', ' RTC_CHECK(true);', '}']
Mirko Bonadeia6395132021-07-22 17:35:59 +0200280
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100281 def testDetectsAssertInCcFile(self):
282 self.input_api.files = [
283 MockFile('with_assert.cc', self._content_with_assert),
284 MockFile('without_assert.cc', self._content_without_assert),
285 ]
286 errors = PRESUBMIT.CheckAssertUsage(self.input_api,
287 self.output_api, lambda x: True)
288 self.assertEqual(1, len(errors))
289 self.assertEqual('with_assert.cc', errors[0].items[0])
Mirko Bonadeia6395132021-07-22 17:35:59 +0200290
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100291 def testDetectsAssertInHeaderFile(self):
292 self.input_api.files = [
293 MockFile('with_assert.h', self._content_with_assert),
294 MockFile('without_assert.h', self._content_without_assert),
295 ]
296 errors = PRESUBMIT.CheckAssertUsage(self.input_api,
297 self.output_api, lambda x: True)
298 self.assertEqual(1, len(errors))
299 self.assertEqual('with_assert.h', errors[0].items[0])
Mirko Bonadeia6395132021-07-22 17:35:59 +0200300
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100301 def testDetectsAssertInObjCFile(self):
302 self.input_api.files = [
303 MockFile('with_assert.m', self._content_with_assert),
304 MockFile('without_assert.m', self._content_without_assert),
305 ]
306 errors = PRESUBMIT.CheckAssertUsage(self.input_api,
307 self.output_api, lambda x: True)
308 self.assertEqual(1, len(errors))
309 self.assertEqual('with_assert.m', errors[0].items[0])
Mirko Bonadeia6395132021-07-22 17:35:59 +0200310
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100311 def testDetectsAssertInObjCppFile(self):
312 self.input_api.files = [
313 MockFile('with_assert.mm', self._content_with_assert),
314 MockFile('without_assert.mm', self._content_without_assert),
315 ]
316 errors = PRESUBMIT.CheckAssertUsage(self.input_api,
317 self.output_api, lambda x: True)
318 self.assertEqual(1, len(errors))
319 self.assertEqual('with_assert.mm', errors[0].items[0])
Mirko Bonadeia6395132021-07-22 17:35:59 +0200320
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100321 def testDoesntDetectAssertInOtherFiles(self):
322 self.input_api.files = [
323 MockFile('with_assert.cpp', self._content_with_assert),
324 ]
325 errors = PRESUBMIT.CheckAssertUsage(self.input_api,
326 self.output_api, lambda x: True)
327 self.assertEqual(0, len(errors))
Mirko Bonadeia6395132021-07-22 17:35:59 +0200328
329
charujain9893e252017-09-14 13:33:22 +0200330if __name__ == '__main__':
Christoffer Jansson4e8a7732022-02-08 09:01:12 +0100331 unittest.main()