Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /PRESUBMIT_test.py
blob: 073f473cc1cfa07aa1260a593e1442830bc18edc [file] [log] [blame]
Andrew Grieve3f9b9662022-02-02 19:07:55[diff] [blame]1#!/usr/bin/env python3
Avi Drissman24976592022-09-12 15:24:31[diff] [blame]2# Copyright 2012 The Chromium Authors
marja@chromium.org2299dcf2012-11-15 19:56:24[diff] [blame]3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Andrew Grieve4deedb12022-02-03 21:34:50[diff] [blame]6import io
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]7import os.path
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]8import subprocess
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]9import textwrap
marja@chromium.org2299dcf2012-11-15 19:56:24[diff] [blame]10import unittest
11
12import PRESUBMIT
Saagar Sanghavifceeaae2020-08-12 16:40:36[diff] [blame]13
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]14from PRESUBMIT_test_mocksimportMockFile,MockAffectedFile
gayane3dff8c22014-12-04 17:09:51[diff] [blame]15from PRESUBMIT_test_mocksimportMockInputApi,MockOutputApi
marja@chromium.org2299dcf2012-11-15 19:56:24[diff] [blame]16
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]17
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]18_TEST_DATA_DIR='base/test/data/presubmit'
19
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]20
dbeam@chromium.orgb00342e7f2013-03-26 16:21:54[diff] [blame]21classVersionControlConflictsTest(unittest.TestCase):
dbeam@chromium.org70ca77752012-11-20 03:45:03[diff] [blame]22
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]23def testTypicalConflict(self):
24 lines=[
25'<<<<<<< HEAD',' base::ScopedTempDir temp_dir_;','=======',
26' ScopedTempDir temp_dir_;','>>>>>>> master'
27]
28 errors= PRESUBMIT._CheckForVersionControlConflictsInFile(
29MockInputApi(),MockFile('some/path/foo_platform.cc', lines))
30 self.assertEqual(3, len(errors))
31 self.assertTrue('1'in errors[0])
32 self.assertTrue('3'in errors[1])
33 self.assertTrue('5'in errors[2])
34
35def testIgnoresReadmes(self):
36 lines=[
37'A First Level Header','====================','',
38'A Second Level Header','---------------------'
39]
40 errors= PRESUBMIT._CheckForVersionControlConflictsInFile(
41MockInputApi(),MockFile('some/polymer/README.md', lines))
42 self.assertEqual(0, len(errors))
dbeam95c35a2f2015-06-02 01:40:23[diff] [blame]43
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]44
enne@chromium.orgb8079ae4a2012-12-05 19:56:49[diff] [blame]45classBadExtensionsTest(unittest.TestCase):
enne@chromium.orgb8079ae4a2012-12-05 19:56:49[diff] [blame]46
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]47def testBadRejFile(self):
48 mock_input_api=MockInputApi()
49 mock_input_api.files=[
50MockFile('some/path/foo.cc',''),
51MockFile('some/path/foo.cc.rej',''),
52MockFile('some/path2/bar.h.rej',''),
53]
enne@chromium.orgb8079ae4a2012-12-05 19:56:49[diff] [blame]54
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]55 results= PRESUBMIT.CheckPatchFiles(mock_input_api,MockOutputApi())
56 self.assertEqual(1, len(results))
57 self.assertEqual(2, len(results[0].items))
58 self.assertTrue('foo.cc.rej'in results[0].items[0])
59 self.assertTrue('bar.h.rej'in results[0].items[1])
enne@chromium.orgb8079ae4a2012-12-05 19:56:49[diff] [blame]60
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]61def testBadOrigFile(self):
62 mock_input_api=MockInputApi()
63 mock_input_api.files=[
64MockFile('other/path/qux.h.orig',''),
65MockFile('other/path/qux.h',''),
66MockFile('other/path/qux.cc',''),
67]
enne@chromium.orgb8079ae4a2012-12-05 19:56:49[diff] [blame]68
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]69 results= PRESUBMIT.CheckPatchFiles(mock_input_api,MockOutputApi())
70 self.assertEqual(1, len(results))
71 self.assertEqual(1, len(results[0].items))
72 self.assertTrue('qux.h.orig'in results[0].items[0])
73
74def testGoodFiles(self):
75 mock_input_api=MockInputApi()
76 mock_input_api.files=[
77MockFile('other/path/qux.h',''),
78MockFile('other/path/qux.cc',''),
79]
80 results= PRESUBMIT.CheckPatchFiles(mock_input_api,MockOutputApi())
81 self.assertEqual(0, len(results))
enne@chromium.orgb8079ae4a2012-12-05 19:56:49[diff] [blame]82
83
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]84classCheckForSuperfluousStlIncludesInHeadersTest(unittest.TestCase):
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]85
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]86def testGoodFiles(self):
87 mock_input_api=MockInputApi()
88 mock_input_api.files=[
89# The check is not smart enough to figure out which definitions correspond
90# to which header.
91MockFile('other/path/foo.h',['#include <string>','std::vector']),
92# The check is not smart enough to do IWYU.
93MockFile('other/path/bar.h',
94['#include "base/check.h"','std::vector']),
95MockFile('other/path/qux.h',
96['#include "base/stl_util.h"','foobar']),
97MockFile('other/path/baz.h',
98['#include "set/vector.h"','bazzab']),
99# The check is only for header files.
100MockFile('other/path/not_checked.cc',
101['#include <vector>','bazbaz']),
102]
103 results= PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
104 mock_input_api,MockOutputApi())
105 self.assertEqual(0, len(results))
106
107def testBadFiles(self):
108 mock_input_api=MockInputApi()
109 mock_input_api.files=[
110MockFile('other/path/foo.h',['#include <vector>','vector']),
111MockFile(
112'other/path/bar.h',
113['#include <limits>','#include <set>','no_std_namespace']),
114]
115 results= PRESUBMIT.CheckForSuperfluousStlIncludesInHeaders(
116 mock_input_api,MockOutputApi())
117 self.assertEqual(1, len(results))
118 self.assertTrue('foo.h: Includes STL'in results[0].message)
119 self.assertTrue('bar.h: Includes STL'in results[0].message)
Lei Zhang1c12a22f2021-05-12 11:28:45[diff] [blame]120
121
glidere61efad2015-02-18 17:39:43[diff] [blame]122classCheckSingletonInHeadersTest(unittest.TestCase):
glidere61efad2015-02-18 17:39:43[diff] [blame]123
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]124def testSingletonInArbitraryHeader(self):
125 diff_singleton_h=[
126'base::subtle::AtomicWord '
127'base::Singleton<Type, Traits, DifferentiatingType>::'
128]
129 diff_foo_h=[
130'// base::Singleton<Foo> in comment.',
131'friend class base::Singleton<Foo>'
132]
133 diff_foo2_h=[' //Foo* bar = base::Singleton<Foo>::get();']
134 diff_bad_h=['Foo* foo = base::Singleton<Foo>::get();']
135 mock_input_api=MockInputApi()
136 mock_input_api.files=[
137MockAffectedFile('base/memory/singleton.h', diff_singleton_h),
138MockAffectedFile('foo.h', diff_foo_h),
139MockAffectedFile('foo2.h', diff_foo2_h),
140MockAffectedFile('bad.h', diff_bad_h)
141]
142 warnings= PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
143MockOutputApi())
144 self.assertEqual(1, len(warnings))
145 self.assertEqual(1, len(warnings[0].items))
146 self.assertEqual('error', warnings[0].type)
147 self.assertTrue('Found base::Singleton<T>'in warnings[0].message)
148
149def testSingletonInCC(self):
150 diff_cc=['Foo* foo = base::Singleton<Foo>::get();']
151 mock_input_api=MockInputApi()
152 mock_input_api.files=[MockAffectedFile('some/path/foo.cc', diff_cc)]
153 warnings= PRESUBMIT.CheckSingletonInHeaders(mock_input_api,
154MockOutputApi())
155 self.assertEqual(0, len(warnings))
glidere61efad2015-02-18 17:39:43[diff] [blame]156
157
Xiaohan Wang42d96c22022-01-20 17:23:11[diff] [blame]158classDeprecatedOSMacroNamesTest(unittest.TestCase):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]159
160def testDeprecatedOSMacroNames(self):
161 lines=[
162'#if defined(OS_WIN)',' #elif defined(OS_WINDOW)',
163' # if defined(OS_MAC) || defined(OS_CHROME)'
164]
165 errors= PRESUBMIT._CheckForDeprecatedOSMacrosInFile(
166MockInputApi(),MockFile('some/path/foo_platform.cc', lines))
167 self.assertEqual(len(lines)+1, len(errors))
168 self.assertTrue(
169':1: defined(OS_WIN) -> BUILDFLAG(IS_WIN)'in errors[0])
dbeam@chromium.orgb00342e7f2013-03-26 16:21:54[diff] [blame]170
171
lliabraa35bab3932014-10-01 12:16:44[diff] [blame]172classInvalidIfDefinedMacroNamesTest(unittest.TestCase):
lliabraa35bab3932014-10-01 12:16:44[diff] [blame]173
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]174def testInvalidIfDefinedMacroNames(self):
175 lines=[
176'#if defined(TARGET_IPHONE_SIMULATOR)',
177'#if !defined(TARGET_IPHONE_SIMULATOR)',
178'#elif defined(TARGET_IPHONE_SIMULATOR)',
179'#ifdef TARGET_IPHONE_SIMULATOR',
180' # ifdef TARGET_IPHONE_SIMULATOR',
181'# if defined(VALID) || defined(TARGET_IPHONE_SIMULATOR)',
182'# else // defined(TARGET_IPHONE_SIMULATOR)',
183'#endif // defined(TARGET_IPHONE_SIMULATOR)'
184]
185 errors= PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
186MockInputApi(),MockFile('some/path/source.mm', lines))
187 self.assertEqual(len(lines), len(errors))
188
189def testValidIfDefinedMacroNames(self):
190 lines=[
191'#if defined(FOO)','#ifdef BAR','#if TARGET_IPHONE_SIMULATOR'
192]
193 errors= PRESUBMIT._CheckForInvalidIfDefinedMacrosInFile(
194MockInputApi(),MockFile('some/path/source.cc', lines))
195 self.assertEqual(0, len(errors))
lliabraa35bab3932014-10-01 12:16:44[diff] [blame]196
197
Andrew Williamsc9f69b482023-07-10 16:07:36[diff] [blame]198classCheckNoUNIT_TESTInSourceFilesTest(unittest.TestCase):
Andrew Williamsc9f69b482023-07-10 16:07:36[diff] [blame]199
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]200def testUnitTestMacros(self):
201 lines=[
202'#if defined(UNIT_TEST)','#if defined UNIT_TEST',
203'#if !defined(UNIT_TEST)','#elif defined(UNIT_TEST)',
204'#ifdef UNIT_TEST',' # ifdef UNIT_TEST','#ifndef UNIT_TEST',
205'# if defined(VALID) || defined(UNIT_TEST)',
206'# if defined(UNIT_TEST) && defined(VALID)',
207'# else // defined(UNIT_TEST)','#endif // defined(UNIT_TEST)'
208]
209 errors= PRESUBMIT._CheckNoUNIT_TESTInSourceFiles(
210MockInputApi(),MockFile('some/path/source.cc', lines))
211 self.assertEqual(len(lines), len(errors))
212
213def testNotUnitTestMacros(self):
214 lines=[
215'// Comment about "#if defined(UNIT_TEST)"',
216'/* Comment about #if defined(UNIT_TEST)" */',
217'#ifndef UNIT_TEST_H','#define UNIT_TEST_H',
218'#ifndef TEST_UNIT_TEST','#define TEST_UNIT_TEST',
219'#if defined(_UNIT_TEST)','#if defined(UNIT_TEST_)',
220'#ifdef _UNIT_TEST','#ifdef UNIT_TEST_','#ifndef _UNIT_TEST',
221'#ifndef UNIT_TEST_'
222]
223 errors= PRESUBMIT._CheckNoUNIT_TESTInSourceFiles(
224MockInputApi(),MockFile('some/path/source.cc', lines))
225 self.assertEqual(0, len(errors))
Andrew Williamsc9f69b482023-07-10 16:07:36[diff] [blame]226
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]227
228classCheckEachPerfettoTestDataFileHasDepsEntry(unittest.TestCase):
229
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]230def testNewSha256FileNoDEPS(self):
231 input_api=MockInputApi()
232 input_api.files=[
233MockFile('base/tracing/test/data_sha256/new.pftrace.sha256',[]),
234]
235 results= PRESUBMIT.CheckEachPerfettoTestDataFileHasDepsEntry(
236 input_api,MockOutputApi())
237 self.assertEqual(
238('You must update the DEPS file when you update a .sha256 file '
239'in base/tracing/test/data_sha256'), results[0].message)
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]240
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]241def testNewSha256FileSuccess(self):
242 input_api=MockInputApi()
243 new_deps="""deps = {
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]244 'src/base/tracing/test/data': {
245 'bucket': 'perfetto',
246 'objects': [
247 {
248 'object_name': 'test_data/new.pftrace-a1b2c3f4',
249 'sha256sum': 'a1b2c3f4',
250 'size_bytes': 1,
251 'generation': 1,
252 'output_file': 'new.pftrace'
253 },
254 ],
255 'dep_type': 'gcs'
256 },
257 }""".splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]258 input_api.files=[
259MockFile('base/tracing/test/data_sha256/new.pftrace.sha256',
260['a1b2c3f4']),
261MockFile('DEPS', new_deps,
262["deps={'src/base/tracing/test/data':{}}"]),
263]
264 results= PRESUBMIT.CheckEachPerfettoTestDataFileHasDepsEntry(
265 input_api,MockOutputApi())
266 self.assertEqual(0, len(results))
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]267
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]268def testNewSha256FileWrongSha256(self):
269 input_api=MockInputApi()
270 new_deps="""deps = {
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]271 'src/base/tracing/test/data': {
272 'bucket': 'perfetto',
273 'objects': [
274 {
275 'object_name': 'test_data/new.pftrace-a1b2c3f4',
276 'sha256sum': 'wrong_hash',
277 'size_bytes': 1,
278 'generation': 1,
279 'output_file': 'new.pftrace'
280 },
281 ],
282 'dep_type': 'gcs'
283 },
284 }""".splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]285 f=MockFile('base/tracing/test/data_sha256/new.pftrace.sha256',
286['a1b2c3f4'])
287 input_api.files=[
288 f,
289MockFile('DEPS', new_deps,
290["deps={'src/base/tracing/test/data':{}}"]),
291]
292 results= PRESUBMIT.CheckEachPerfettoTestDataFileHasDepsEntry(
293 input_api,MockOutputApi())
294 self.assertEqual(
295('No corresponding DEPS entry found for %s. '
296'Run `base/tracing/test/test_data.py get_deps --filepath %s` '
297'to generate the DEPS entry.'%(f.LocalPath(), f.LocalPath())),
298 results[0].message)
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]299
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]300def testDeleteSha256File(self):
301 input_api=MockInputApi()
302 old_deps="""deps = {
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]303 'src/base/tracing/test/data': {
304 'bucket': 'perfetto',
305 'objects': [
306 {
307 'object_name': 'test_data/new.pftrace-a1b2c3f4',
308 'sha256sum': 'a1b2c3f4',
309 'size_bytes': 1,
310 'generation': 1,
311 'output_file': 'new.pftrace'
312 },
313 ],
314 'dep_type': 'gcs'
315 },
316 }""".splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]317 f=MockFile('base/tracing/test/data_sha256/new.pftrace.sha256',[],
318['a1b2c3f4'],
319 action='D')
320 input_api.files=[
321 f,
322MockFile('DEPS', old_deps, old_deps),
323]
324 results= PRESUBMIT.CheckEachPerfettoTestDataFileHasDepsEntry(
325 input_api,MockOutputApi())
326 self.assertEqual((
327'You deleted %s so you must also remove the corresponding DEPS entry.'
328% f.LocalPath()), results[0].message)
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]329
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]330def testDeleteSha256Success(self):
331 input_api=MockInputApi()
332 new_deps="""deps = {
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]333 'src/base/tracing/test/data': {
334 'bucket': 'perfetto',
335 'objects': [],
336 'dep_type': 'gcs'
337 },
338 }""".splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]339 old_deps="""deps = {
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]340 'src/base/tracing/test/data': {
341 'bucket': 'perfetto',
342 'objects': [
343 {
344 'object_name': 'test_data/new.pftrace-a1b2c3f4',
345 'sha256sum': 'a1b2c3f4',
346 'size_bytes': 1,
347 'generation': 1,
348 'output_file': 'new.pftrace'
349 },
350 ],
351 'dep_type': 'gcs'
352 },
353 }""".splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]354 f=MockFile('base/tracing/test/data_sha256/new.pftrace.sha256',[],
355['a1b2c3f4'],
356 action='D')
357 input_api.files=[
358 f,
359MockFile('DEPS', new_deps, old_deps),
360]
361 results= PRESUBMIT.CheckEachPerfettoTestDataFileHasDepsEntry(
362 input_api,MockOutputApi())
363 self.assertEqual(0, len(results))
Rasika Navarangec2d33d22024-05-23 15:19:02[diff] [blame]364
365
Samuel Huang0db2ea22019-12-09 16:42:47[diff] [blame]366classCheckAddedDepsHaveTestApprovalsTest(unittest.TestCase):
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]367
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]368def setUp(self):
369 self.input_api= input_api=MockInputApi()
370 input_api.environ={}
371 input_api.owners_client= self.FakeOwnersClient()
372 input_api.gerrit= self.fakeGerrit()
373 input_api.change.issue=123
374 self.mockOwnersAndReviewers("owner", set(["reviewer"]))
375 self.mockListSubmodules([])
376
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]377def calculate(self, old_include_rules, old_specific_include_rules,
378 new_include_rules, new_specific_include_rules):
379return PRESUBMIT._CalculateAddedDeps(
380 os.path,'include_rules = %r\nspecific_include_rules = %r'%
381(old_include_rules, old_specific_include_rules),
382'include_rules = %r\nspecific_include_rules = %r'%
383(new_include_rules, new_specific_include_rules))
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]384
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]385def testCalculateAddedDeps(self):
386 old_include_rules=[
387'+base',
388'-chrome',
389'+content',
390'-grit',
391'-grit/",',
392'+jni/fooblat.h',
393'!sandbox',
394]
395 old_specific_include_rules={
Justin Lulejiana2fc7882025-04-01 18:34:47[diff] [blame]396 r'compositor\.*':{
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]397'+cc',
398},
399}
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]400
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]401 new_include_rules=[
402'-ash',
403'+base',
404'+chrome',
405'+components',
406'+content',
407'+grit',
408'+grit/generated_resources.h",',
409'+grit/",',
410'+jni/fooblat.h',
411'+policy',
412'+'+ os.path.join('third_party','WebKit'),
413]
414 new_specific_include_rules={
Justin Lulejiana2fc7882025-04-01 18:34:47[diff] [blame]415 r'compositor\.*':{
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]416'+cc',
417},
Justin Lulejiana2fc7882025-04-01 18:34:47[diff] [blame]418 r'widget\.*':{
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]419'+gpu',
420},
421}
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]422
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]423 expected= set([
424 os.path.join('chrome','DEPS'),
425 os.path.join('gpu','DEPS'),
426 os.path.join('components','DEPS'),
427 os.path.join('policy','DEPS'),
428 os.path.join('third_party','WebKit','DEPS'),
429])
430 self.assertEqual(
431 expected,
432 self.calculate(old_include_rules, old_specific_include_rules,
433 new_include_rules, new_specific_include_rules))
Daniel Cheng4dcdb6b2017-04-13 08:30:17[diff] [blame]434
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]435def testCalculateAddedDepsIgnoresPermutations(self):
436 old_include_rules=[
437'+base',
438'+chrome',
439]
440 new_include_rules=[
441'+chrome',
442'+base',
443]
444 self.assertEqual(
445 set(), self.calculate(old_include_rules,{}, new_include_rules,
446{}))
tony@chromium.orgf32e2d1e2013-07-26 21:39:08[diff] [blame]447
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]448def testFindAddedDepsThatRequireReview(self):
449 caring=['new_usages_require_review = True']
450 self.input_api.InitFiles([
451MockAffectedFile('cares/DEPS', caring),
452MockAffectedFile('cares/inherits/DEPS',[]),
453MockAffectedFile('willynilly/DEPS',[]),
454MockAffectedFile('willynilly/butactually/DEPS', caring),
455])
456
457 expected={
458'cares':True,
459'cares/sub/sub':True,
460'cares/inherits':True,
461'cares/inherits/sub':True,
462'willynilly':False,
463'willynilly/butactually':True,
464'willynilly/butactually/sub':True,
465}
466 results= PRESUBMIT._FindAddedDepsThatRequireReview(
467 self.input_api, set(expected))
468 actual={k: kin resultsfor kin expected}
469 self.assertEqual(expected, actual)
470
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]471classFakeOwnersClient(object):
472 APPROVED="APPROVED"
473 PENDING="PENDING"
474 returns={}
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]475
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]476defListOwners(self,*args,**kwargs):
477return self.returns.get(self.ListOwners.__name__,"")
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]478
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]479def mockListOwners(self, owners):
480 self.returns[self.ListOwners.__name__]= owners
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]481
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]482defGetFilesApprovalStatus(self,*args,**kwargs):
483return self.returns.get(self.GetFilesApprovalStatus.__name__,{})
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]484
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]485def mockGetFilesApprovalStatus(self, status):
486 self.returns[self.GetFilesApprovalStatus.__name__]= status
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]487
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]488defSuggestOwners(self,*args,**kwargs):
489return["eng1","eng2","eng3"]
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]490
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]491class fakeGerrit(object):
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]492
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]493defIsOwnersOverrideApproved(self, issue):
494returnFalse
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]495
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]496def mockOwnersAndReviewers(self, owner, reviewers):
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]497
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]498def mock(*args,**kwargs):
499return[owner, reviewers]
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]500
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]501 self.input_api.canned_checks.GetCodereviewOwnerAndReviewers= mock
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]502
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]503def mockListSubmodules(self, paths):
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]504
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]505def mock(*args,**kwargs):
506return paths
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]507
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]508 self.input_api.ListSubmodules= mock
509
510def testApprovedAdditionalDep(self):
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]511 self.input_api.InitFiles([
Joanna Wang130e7bdd2024-12-10 17:39:03[diff] [blame]512MockAffectedFile('pdf/DEPS',
513['include_rules=["+v8/123", "+foo/bar"]']),
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]514MockAffectedFile('v8/DEPS',['new_usages_require_review=True']),
Joanna Wang130e7bdd2024-12-10 17:39:03[diff] [blame]515# Check that we ignore "DEPS" directories. Note there are real cases
516# of directories named "deps/" and, especially for case-insensitive file
517# systems we should prevent these from being considered.
518MockAffectedFile('foo/bar/DEPS/boofar',['boofar file contents']),
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]519])
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]520
521# mark the additional dep as approved.
522 os_path= self.input_api.os_path
523 self.input_api.owners_client.mockGetFilesApprovalStatus(
524{os_path.join('v8/123','DEPS'): self.FakeOwnersClient.APPROVED})
525 results= PRESUBMIT.CheckAddedDepsHaveTargetApprovals(
526 self.input_api,MockOutputApi())
527# Then, the check should pass.
528 self.assertEqual([], results)
529
530def testUnapprovedAdditionalDep(self):
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]531 self.input_api.InitFiles([
532MockAffectedFile('pdf/DEPS',['include_rules=["+v8/123"]']),
Andrew Grieveb77ac762024-11-29 15:01:48[diff] [blame]533MockAffectedFile('v8/DEPS',['new_usages_require_review=True']),
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]534])
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]535
536# pending.
537 os_path= self.input_api.os_path
538 self.input_api.owners_client.mockGetFilesApprovalStatus(
539{os_path.join('v8/123','DEPS'): self.FakeOwnersClient.PENDING})
540 results= PRESUBMIT.CheckAddedDepsHaveTargetApprovals(
541 self.input_api,MockOutputApi())
542# the check should fail
543 self.assertIn('You need LGTM', results[0].message)
544 self.assertIn('+v8/123', results[0].message)
545
546# unless the added dep is from a submodule.
547 self.mockListSubmodules(['v8'])
548 results= PRESUBMIT.CheckAddedDepsHaveTargetApprovals(
549 self.input_api,MockOutputApi())
550 self.assertEqual([], results)
Scott Leebf6a0942024-06-26 22:59:39[diff] [blame]551
tony@chromium.orgf32e2d1e2013-07-26 21:39:08[diff] [blame]552
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]553classJSONParsingTest(unittest.TestCase):
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]554
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]555def testSuccess(self):
556 input_api=MockInputApi()
557 filename='valid_json.json'
558 contents=[
559'// This is a comment.','{',' "key1": ["value1", "value2"],',
560' "key2": 3 // This is an inline comment.','}'
561]
562 input_api.files=[MockFile(filename, contents)]
563 self.assertEqual(None,
564 PRESUBMIT._GetJSONParseError(input_api, filename))
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]565
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]566def testFailure(self):
567 input_api=MockInputApi()
568 test_data=[
569('invalid_json_1.json',['{ x }'],'Expecting property name'),
570('invalid_json_2.json',['// Hello world!','{ "hello": "world }'],
571'Unterminated string starting at:'),
572('invalid_json_3.json',['{ "a": "b", "c": "d", }'],
573'Expecting property name'),
574('invalid_json_4.json',['{ "a": "b" "c": "d" }'],
575"Expecting ',' delimiter:"),
576]
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]577
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]578 input_api.files=[
579MockFile(filename, contents)
580for(filename, contents, _)in test_data
581]
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]582
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]583for(filename, _, expected_error)in test_data:
584 actual_error= PRESUBMIT._GetJSONParseError(input_api, filename)
585 self.assertTrue(
586 expected_errorin str(actual_error),
587"'%s' not found in '%s'"%(expected_error, actual_error))
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]588
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]589def testNoEatComments(self):
590 input_api=MockInputApi()
591 file_with_comments='file_with_comments.json'
592 contents_with_comments=[
593'// This is a comment.','{',' "key1": ["value1", "value2"],',
594' "key2": 3 // This is an inline comment.','}'
595]
596 file_without_comments='file_without_comments.json'
597 contents_without_comments=[
598'{',' "key1": ["value1", "value2"],',' "key2": 3','}'
599]
600 input_api.files=[
601MockFile(file_with_comments, contents_with_comments),
602MockFile(file_without_comments, contents_without_comments)
603]
604
605 self.assertNotEqual(
606None,
607 str(
608 PRESUBMIT._GetJSONParseError(input_api,
609 file_with_comments,
610 eat_comments=False)))
611 self.assertEqual(
612None,
613 PRESUBMIT._GetJSONParseError(input_api,
614 file_without_comments,
615 eat_comments=False))
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]616
617
618classIDLParsingTest(unittest.TestCase):
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]619
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]620def testSuccess(self):
621 input_api=MockInputApi()
622 filename='valid_idl_basics.idl'
623 contents=[
624'// Tests a valid IDL file.','namespace idl_basics {',
625' enum EnumType {',' name1,',' name2',' };','',
626' dictionary MyType1 {',' DOMString a;',' };','',
627' callback Callback1 = void();',
628' callback Callback2 = void(long x);',
629' callback Callback3 = void(MyType1 arg);',
630' callback Callback4 = void(EnumType type);','',
631' interface Functions {',' static void function1();',
632' static void function2(long x);',
633' static void function3(MyType1 arg);',
634' static void function4(Callback1 cb);',
635' static void function5(Callback2 cb);',
636' static void function6(Callback3 cb);',
637' static void function7(Callback4 cb);',' };','',
638' interface Events {',' static void onFoo1();',
639' static void onFoo2(long x);',
640' static void onFoo2(MyType1 arg);',
641' static void onFoo3(EnumType type);',' };','};'
642]
643 input_api.files=[MockFile(filename, contents)]
644 self.assertEqual(None,
645 PRESUBMIT._GetIDLParseError(input_api, filename))
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]646
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]647def testFailure(self):
648 input_api=MockInputApi()
649 test_data=[
650('invalid_idl_1.idl',[
651'//','namespace test {',' dictionary {',' DOMString s;',
652' };','};'
653],'Unexpected "{" after keyword "dictionary".\n'),
654# TODO(yoz): Disabled because it causes the IDL parser to hang.
655# See crbug.com/363830.
656# ('invalid_idl_2.idl',
657# (['namespace test {',
658# ' dictionary MissingSemicolon {',
659# ' DOMString a',
660# ' DOMString b;',
661# ' };',
662# '};'],
663# 'Unexpected symbol DOMString after symbol a.'),
664('invalid_idl_3.idl',[
665'//','namespace test {',' enum MissingComma {',' name1',
666' name2',' };','};'
667],'Unexpected symbol name2 after symbol name1.'),
668('invalid_idl_4.idl',[
669'//','namespace test {',' enum TrailingComma {',
670' name1,',' name2,',' };','};'
671],'Trailing comma in block.'),
672('invalid_idl_5.idl',
673['//','namespace test {',' callback Callback1 = void(;',
674'};'],'Unexpected ";" after "(".'),
675('invalid_idl_6.idl',[
676'//','namespace test {',
677' callback Callback1 = void(long );','};'
678],'Unexpected ")" after symbol long.'),
679('invalid_idl_7.idl',[
680'//','namespace test {',' interace Events {',
681' static void onFoo1();',' };','};'
682],'Unexpected symbol Events after symbol interace.'),
683('invalid_idl_8.idl',[
684'//','namespace test {',' interface NotEvent {',
685' static void onFoo1();',' };','};'
686],'Did not process Interface Interface(NotEvent)'),
687('invalid_idl_9.idl',[
688'//','namespace test {',' interface {',
689' static void function1();',' };','};'
690],'Interface missing name.'),
691]
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]692
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]693 input_api.files=[
694MockFile(filename, contents)
695for(filename, contents, _)in test_data
696]
697
698for(filename, _, expected_error)in test_data:
699 actual_error= PRESUBMIT._GetIDLParseError(input_api, filename)
700 self.assertTrue(
701 expected_errorin str(actual_error),
702"'%s' not found in '%s'"%(expected_error, actual_error))
yoz@chromium.org99171a92014-06-03 08:44:47[diff] [blame]703
704
davileene0426252015-03-02 21:10:41[diff] [blame]705classUserMetricsActionTest(unittest.TestCase):
davileene0426252015-03-02 21:10:41[diff] [blame]706
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]707def testUserMetricsActionInActions(self):
708 input_api=MockInputApi()
709 file_with_user_action='file_with_user_action.cc'
710 contents_with_user_action=['base::UserMetricsAction("AboutChrome")']
davileene0426252015-03-02 21:10:41[diff] [blame]711
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]712 input_api.files=[
713MockFile(file_with_user_action, contents_with_user_action)
714]
davileene0426252015-03-02 21:10:41[diff] [blame]715
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]716 self.assertEqual([],
717 PRESUBMIT.CheckUserActionUpdate(
718 input_api,MockOutputApi()))
davileene0426252015-03-02 21:10:41[diff] [blame]719
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]720def testUserMetricsActionNotAddedToActions(self):
721 input_api=MockInputApi()
722 file_with_user_action='file_with_user_action.cc'
723 contents_with_user_action=[
724'base::UserMetricsAction("NotInActionsXml")'
725]
davileene0426252015-03-02 21:10:41[diff] [blame]726
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]727 input_api.files=[
728MockFile(file_with_user_action, contents_with_user_action)
729]
davileene0426252015-03-02 21:10:41[diff] [blame]730
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]731 output= PRESUBMIT.CheckUserActionUpdate(input_api,MockOutputApi())
732 self.assertEqual(
733('File %s line %d: %s is missing in '
734'tools/metrics/actions/actions.xml. Please run '
735'tools/metrics/actions/extract_actions.py to update.'%
736(file_with_user_action,1,'NotInActionsXml')), output[0].message)
Alexei Svitkine64505a92021-03-11 22:00:54[diff] [blame]737
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]738def testUserMetricsActionInTestFile(self):
739 input_api=MockInputApi()
740 file_with_user_action='file_with_user_action_unittest.cc'
741 contents_with_user_action=[
742'base::UserMetricsAction("NotInActionsXml")'
743]
Alexei Svitkine64505a92021-03-11 22:00:54[diff] [blame]744
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]745 input_api.files=[
746MockFile(file_with_user_action, contents_with_user_action)
747]
748
749 self.assertEqual([],
750 PRESUBMIT.CheckUserActionUpdate(
751 input_api,MockOutputApi()))
Alexei Svitkine64505a92021-03-11 22:00:54[diff] [blame]752
davileene0426252015-03-02 21:10:41[diff] [blame]753
agrievef32bcc72016-04-04 14:57:40[diff] [blame]754classPydepsNeedsUpdatingTest(unittest.TestCase):
755
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]756classMockPopen:
Andrew Grieve4deedb12022-02-03 21:34:50[diff] [blame]757
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]758def __init__(self, stdout):
759 self.stdout= io.StringIO(stdout)
Andrew Grieve4deedb12022-02-03 21:34:50[diff] [blame]760
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]761def wait(self):
762return0
Andrew Grieve4deedb12022-02-03 21:34:50[diff] [blame]763
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]764classMockSubprocess:
765CalledProcessError= subprocess.CalledProcessError
766 PIPE=0
Andrew Grieve4deedb12022-02-03 21:34:50[diff] [blame]767
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]768def __init__(self):
769 self._popen_func=None
agrievef32bcc72016-04-04 14:57:40[diff] [blame]770
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]771defSetPopenCallback(self, func):
772 self._popen_func= func
Mohamed Heikal7cd4d8312020-06-16 16:49:40[diff] [blame]773
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]774defPopen(self, cmd,*args,**kwargs):
775returnPydepsNeedsUpdatingTest.MockPopen(self._popen_func(cmd))
agrievef32bcc72016-04-04 14:57:40[diff] [blame]776
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]777def_MockParseGclientArgs(self, is_android=True):
778returnlambda:{'checkout_android':'true'if is_androidelse'false'}
agrievef32bcc72016-04-04 14:57:40[diff] [blame]779
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]780def setUp(self):
781 mock_all_pydeps=['A.pydeps','B.pydeps','D.pydeps']
782 self.old_ALL_PYDEPS_FILES= PRESUBMIT._ALL_PYDEPS_FILES
783 PRESUBMIT._ALL_PYDEPS_FILES= mock_all_pydeps
784 mock_android_pydeps=['D.pydeps']
785 self.old_ANDROID_SPECIFIC_PYDEPS_FILES=(
786 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES)
787 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES= mock_android_pydeps
788 self.old_ParseGclientArgs= PRESUBMIT._ParseGclientArgs
789 PRESUBMIT._ParseGclientArgs= self._MockParseGclientArgs()
790 self.mock_input_api=MockInputApi()
791 self.mock_output_api=MockOutputApi()
792 self.mock_input_api.subprocess=PydepsNeedsUpdatingTest.MockSubprocess(
793)
794 self.checker= PRESUBMIT.PydepsChecker(self.mock_input_api,
795 mock_all_pydeps)
796 self.checker._file_cache={
797'A.pydeps':
798'# Generated by:\n# CMD --output A.pydeps A\nA.py\nC.py\n',
799'B.pydeps':
800'# Generated by:\n# CMD --output B.pydeps B\nB.py\nC.py\n',
801'D.pydeps':'# Generated by:\n# CMD --output D.pydeps D\nD.py\n',
802}
agrievef32bcc72016-04-04 14:57:40[diff] [blame]803
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]804def tearDown(self):
805 PRESUBMIT._ALL_PYDEPS_FILES= self.old_ALL_PYDEPS_FILES
806 PRESUBMIT._ANDROID_SPECIFIC_PYDEPS_FILES=(
807 self.old_ANDROID_SPECIFIC_PYDEPS_FILES)
808 PRESUBMIT._ParseGclientArgs= self.old_ParseGclientArgs
pastarmovj89f7ee12016-09-20 14:58:13[diff] [blame]809
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]810def_RunCheck(self):
811return PRESUBMIT.CheckPydepsNeedsUpdating(
812 self.mock_input_api,
813 self.mock_output_api,
814 checker_for_tests=self.checker)
agrievef32bcc72016-04-04 14:57:40[diff] [blame]815
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]816def testAddedPydep(self):
817# PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
818ifnot self.mock_input_api.platform.startswith('linux'):
819return[]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]820
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]821 self.mock_input_api.InitFiles([
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]822MockAffectedFile('new.pydeps',[], action='A'),
Sophey Dong58cf9bbd2024-10-09 00:08:10[diff] [blame]823])
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]824
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]825 results= self._RunCheck()
826 self.assertEqual(1, len(results))
827 self.assertIn('PYDEPS_FILES', str(results[0]))
pastarmovj89f7ee12016-09-20 14:58:13[diff] [blame]828
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]829def testPydepNotInSrc(self):
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]830 self.mock_input_api.InitFiles([
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]831MockAffectedFile('new.pydeps',[], action='A'),
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]832])
833 self.mock_input_api.os_path.exists=lambda x:False
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]834 results= self._RunCheck()
835 self.assertEqual(0, len(results))
agrievef32bcc72016-04-04 14:57:40[diff] [blame]836
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]837def testRemovedPydep(self):
838# PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
839ifnot self.mock_input_api.platform.startswith('linux'):
840return[]
pastarmovj89f7ee12016-09-20 14:58:13[diff] [blame]841
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]842 self.mock_input_api.InitFiles([
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]843MockAffectedFile(PRESUBMIT._ALL_PYDEPS_FILES[0],[], action='D'),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]844])
845 results= self._RunCheck()
846 self.assertEqual(1, len(results))
847 self.assertIn('PYDEPS_FILES', str(results[0]))
agrievef32bcc72016-04-04 14:57:40[diff] [blame]848
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]849def testRandomPyIgnored(self):
850# PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
851ifnot self.mock_input_api.platform.startswith('linux'):
852return[]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]853
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]854 self.mock_input_api.files=[
855MockAffectedFile('random.py',[]),
856]
pastarmovj89f7ee12016-09-20 14:58:13[diff] [blame]857
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]858 results= self._RunCheck()
859 self.assertEqual(0, len(results),'Unexpected results: %r'% results)
agrievef32bcc72016-04-04 14:57:40[diff] [blame]860
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]861def testRelevantPyNoChange(self):
862# PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
863ifnot self.mock_input_api.platform.startswith('linux'):
864return[]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]865
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]866 self.mock_input_api.files=[
867MockAffectedFile('A.py',[]),
868]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]869
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]870def popen_callback(cmd):
871 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
872return self.checker._file_cache['A.pydeps']
agrievef32bcc72016-04-04 14:57:40[diff] [blame]873
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]874 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
pastarmovj89f7ee12016-09-20 14:58:13[diff] [blame]875
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]876 results= self._RunCheck()
877 self.assertEqual(0, len(results),'Unexpected results: %r'% results)
agrievef32bcc72016-04-04 14:57:40[diff] [blame]878
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]879def testRelevantPyOneChange(self):
880# PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
881ifnot self.mock_input_api.platform.startswith('linux'):
882return[]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]883
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]884 self.mock_input_api.files=[
885MockAffectedFile('A.py',[]),
886]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]887
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]888def popen_callback(cmd):
889 self.assertEqual('CMD --output A.pydeps A --output ""', cmd)
890return'changed data'
agrievef32bcc72016-04-04 14:57:40[diff] [blame]891
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]892 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
pastarmovj89f7ee12016-09-20 14:58:13[diff] [blame]893
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]894 results= self._RunCheck()
895 self.assertEqual(1, len(results))
896# Check that --output "" is not included.
897 self.assertNotIn('""', str(results[0]))
898 self.assertIn('File is stale', str(results[0]))
agrievef32bcc72016-04-04 14:57:40[diff] [blame]899
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]900def testRelevantPyTwoChanges(self):
901# PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
902ifnot self.mock_input_api.platform.startswith('linux'):
903return[]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]904
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]905 self.mock_input_api.files=[
906MockAffectedFile('C.py',[]),
907]
agrievef32bcc72016-04-04 14:57:40[diff] [blame]908
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]909def popen_callback(cmd):
910return'changed data'
agrievef32bcc72016-04-04 14:57:40[diff] [blame]911
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]912 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
Mohamed Heikal7cd4d8312020-06-16 16:49:40[diff] [blame]913
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]914 results= self._RunCheck()
915 self.assertEqual(2, len(results))
916 self.assertIn('File is stale', str(results[0]))
917 self.assertIn('File is stale', str(results[1]))
Mohamed Heikal7cd4d8312020-06-16 16:49:40[diff] [blame]918
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]919def testRelevantAndroidPyInNonAndroidCheckout(self):
920# PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
921ifnot self.mock_input_api.platform.startswith('linux'):
922return[]
Mohamed Heikal7cd4d8312020-06-16 16:49:40[diff] [blame]923
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]924 self.mock_input_api.files=[
925MockAffectedFile('D.py',[]),
926]
Mohamed Heikal7cd4d8312020-06-16 16:49:40[diff] [blame]927
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]928def popen_callback(cmd):
929 self.assertEqual('CMD --output D.pydeps D --output ""', cmd)
930return'changed data'
Andrew Grieve5bb4cf702020-10-22 20:21:39[diff] [blame]931
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]932 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
933 PRESUBMIT._ParseGclientArgs= self._MockParseGclientArgs(
934 is_android=False)
Andrew Grieve5bb4cf702020-10-22 20:21:39[diff] [blame]935
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]936 results= self._RunCheck()
937 self.assertEqual(1, len(results))
938 self.assertIn('Android', str(results[0]))
939 self.assertIn('D.pydeps', str(results[0]))
Andrew Grieve5bb4cf702020-10-22 20:21:39[diff] [blame]940
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]941def testGnPathsAndMissingOutputFlag(self):
942# PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux.
943ifnot self.mock_input_api.platform.startswith('linux'):
944return[]
Andrew Grieve5bb4cf702020-10-22 20:21:39[diff] [blame]945
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]946 self.checker._file_cache={
947'A.pydeps':
948'# Generated by:\n# CMD --gn-paths A\n//A.py\n//C.py\n',
949'B.pydeps':
950'# Generated by:\n# CMD --gn-paths B\n//B.py\n//C.py\n',
951'D.pydeps':'# Generated by:\n# CMD --gn-paths D\n//D.py\n',
952}
Andrew Grieve5bb4cf702020-10-22 20:21:39[diff] [blame]953
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]954 self.mock_input_api.files=[
955MockAffectedFile('A.py',[]),
956]
Andrew Grieve5bb4cf702020-10-22 20:21:39[diff] [blame]957
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]958def popen_callback(cmd):
959 self.assertEqual('CMD --gn-paths A --output A.pydeps --output ""',
960 cmd)
961return'changed data'
962
963 self.mock_input_api.subprocess.SetPopenCallback(popen_callback)
964
965 results= self._RunCheck()
966 self.assertEqual(1, len(results))
967 self.assertIn('File is stale', str(results[0]))
Mohamed Heikal7cd4d8312020-06-16 16:49:40[diff] [blame]968
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]969
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]970classIncludeGuardTest(unittest.TestCase):
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]971
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]972def testIncludeGuardChecks(self):
973 mock_input_api=MockInputApi()
974 mock_output_api=MockOutputApi()
975 mock_input_api.files=[
976MockAffectedFile('content/browser/thing/foo.h',[
977'// Comment',
978'#ifndef CONTENT_BROWSER_THING_FOO_H_',
979'#define CONTENT_BROWSER_THING_FOO_H_',
980'struct McBoatFace;',
981'#endif // CONTENT_BROWSER_THING_FOO_H_',
982]),
983MockAffectedFile('content/browser/thing/bar.h',[
984'#ifndef CONTENT_BROWSER_THING_BAR_H_',
985'#define CONTENT_BROWSER_THING_BAR_H_',
986'namespace content {',
987'#endif // CONTENT_BROWSER_THING_BAR_H_',
988'} // namespace content',
989]),
990MockAffectedFile('content/browser/test1.h',[
991'namespace content {',
992'} // namespace content',
993]),
994MockAffectedFile('content\\browser\\win.h',[
995'#ifndef CONTENT_BROWSER_WIN_H_',
996'#define CONTENT_BROWSER_WIN_H_',
997'struct McBoatFace;',
998'#endif // CONTENT_BROWSER_WIN_H_',
999]),
1000MockAffectedFile('content/browser/test2.h',[
1001'// Comment',
1002'#ifndef CONTENT_BROWSER_TEST2_H_',
1003'struct McBoatFace;',
1004'#endif // CONTENT_BROWSER_TEST2_H_',
1005]),
1006MockAffectedFile('content/browser/internal.h',[
1007'// Comment',
1008'#ifndef CONTENT_BROWSER_INTERNAL_H_',
1009'#define CONTENT_BROWSER_INTERNAL_H_',
1010'// Comment',
1011'#ifndef INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
1012'#define INTERNAL_CONTENT_BROWSER_INTERNAL_H_',
1013'namespace internal {',
1014'} // namespace internal',
1015'#endif // INTERNAL_CONTENT_BROWSER_THING_BAR_H_',
1016'namespace content {',
1017'} // namespace content',
1018'#endif // CONTENT_BROWSER_THING_BAR_H_',
1019]),
1020MockAffectedFile('content/browser/thing/foo.cc',[
1021'// This is a non-header.',
1022]),
1023MockAffectedFile('content/browser/disabled.h',[
1024'// no-include-guard-because-multiply-included',
1025'struct McBoatFace;',
1026]),
1027# New files don't allow misspelled include guards.
1028MockAffectedFile('content/browser/spleling.h',[
1029'#ifndef CONTENT_BROWSER_SPLLEING_H_',
1030'#define CONTENT_BROWSER_SPLLEING_H_',
1031'struct McBoatFace;',
1032'#endif // CONTENT_BROWSER_SPLLEING_H_',
1033]),
1034# New files don't allow + in include guards.
1035MockAffectedFile('content/browser/foo+bar.h',[
1036'#ifndef CONTENT_BROWSER_FOO+BAR_H_',
1037'#define CONTENT_BROWSER_FOO+BAR_H_',
1038'struct McBoatFace;',
1039'#endif // CONTENT_BROWSER_FOO+BAR_H_',
1040]),
1041# Old files allow misspelled include guards (for now).
1042MockAffectedFile('chrome/old.h',[
1043'// New contents',
1044'#ifndef CHROME_ODL_H_',
1045'#define CHROME_ODL_H_',
1046'#endif // CHROME_ODL_H_',
1047],[
1048'// Old contents',
1049'#ifndef CHROME_ODL_H_',
1050'#define CHROME_ODL_H_',
1051'#endif // CHROME_ODL_H_',
1052],
1053 action='M'),
1054# Using a Blink style include guard outside Blink is wrong.
1055MockAffectedFile('content/NotInBlink.h',[
1056'#ifndef NotInBlink_h',
1057'#define NotInBlink_h',
1058'struct McBoatFace;',
1059'#endif // NotInBlink_h',
1060]),
1061# Using a Blink style include guard in Blink is no longer ok.
1062MockAffectedFile('third_party/blink/InBlink.h',[
1063'#ifndef InBlink_h',
1064'#define InBlink_h',
1065'struct McBoatFace;',
1066'#endif // InBlink_h',
1067]),
1068# Using a bad include guard in Blink is not ok.
1069MockAffectedFile('third_party/blink/AlsoInBlink.h',[
1070'#ifndef WrongInBlink_h',
1071'#define WrongInBlink_h',
1072'struct McBoatFace;',
1073'#endif // WrongInBlink_h',
1074]),
1075# Using a bad include guard in Blink is not supposed to be accepted even
1076# if it's an old file. However the current presubmit has accepted this
1077# for a while.
1078MockAffectedFile('third_party/blink/StillInBlink.h',[
1079'// New contents',
1080'#ifndef AcceptedInBlink_h',
1081'#define AcceptedInBlink_h',
1082'struct McBoatFace;',
1083'#endif // AcceptedInBlink_h',
1084],[
1085'// Old contents',
1086'#ifndef AcceptedInBlink_h',
1087'#define AcceptedInBlink_h',
1088'struct McBoatFace;',
1089'#endif // AcceptedInBlink_h',
1090],
1091 action='M'),
1092# Using a non-Chromium include guard in third_party
1093# (outside blink) is accepted.
1094MockAffectedFile('third_party/foo/some_file.h',[
1095'#ifndef REQUIRED_RPCNDR_H_',
1096'#define REQUIRED_RPCNDR_H_',
1097'struct SomeFileFoo;',
1098'#endif // REQUIRED_RPCNDR_H_',
1099]),
1100# Not having proper include guard in *_message_generator.h
1101# for old IPC messages is allowed.
1102MockAffectedFile('content/common/content_message_generator.h',[
1103'#undef CONTENT_COMMON_FOO_MESSAGES_H_',
1104'#include "content/common/foo_messages.h"',
1105'#ifndef CONTENT_COMMON_FOO_MESSAGES_H_',
1106'#error "Failed to include content/common/foo_messages.h"',
1107'#endif',
1108]),
1109MockAffectedFile('chrome/renderer/thing/qux.h',[
1110'// Comment',
1111'#ifndef CHROME_RENDERER_THING_QUX_H_',
1112'#define CHROME_RENDERER_THING_QUX_H_',
1113'struct Boaty;',
1114'#endif',
1115]),
1116]
1117 msgs= PRESUBMIT.CheckForIncludeGuards(mock_input_api, mock_output_api)
1118 expected_fail_count=10
1119 self.assertEqual(
1120 expected_fail_count, len(msgs),'Expected %d items, found %d: %s'%
1121(expected_fail_count, len(msgs), msgs))
1122 self.assertEqual(msgs[0].items,['content/browser/thing/bar.h'])
1123 self.assertEqual(
1124 msgs[0].message,'Include guard CONTENT_BROWSER_THING_BAR_H_ '
1125'not covering the whole file')
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]1126
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1127 self.assertIn('content/browser/test1.h', msgs[1].message)
1128 self.assertIn('Recommended name: CONTENT_BROWSER_TEST1_H_',
1129 msgs[1].message)
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]1130
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1131 self.assertEqual(msgs[2].items,['content/browser/test2.h:3'])
1132 self.assertEqual(
1133 msgs[2].message,'Missing "#define CONTENT_BROWSER_TEST2_H_" for '
1134'include guard')
Lei Zhangd84f9512024-05-28 19:43:30[diff] [blame]1135
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1136 self.assertIn('content/browser/internal.h', msgs[3].message)
1137 self.assertIn(
1138'Recommended #endif comment: // CONTENT_BROWSER_INTERNAL_H_',
1139 msgs[3].message)
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]1140
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1141 self.assertEqual(msgs[4].items,['content/browser/spleling.h:1'])
1142 self.assertEqual(
1143 msgs[4].message,'Header using the wrong include guard name '
1144'CONTENT_BROWSER_SPLLEING_H_')
Olivier Robinbba137492018-07-30 11:31:34[diff] [blame]1145
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1146 self.assertIn('content/browser/foo+bar.h', msgs[5].message)
1147 self.assertIn('Recommended name: CONTENT_BROWSER_FOO_BAR_H_',
1148 msgs[5].message)
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]1149
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1150 self.assertEqual(msgs[6].items,['content/NotInBlink.h:1'])
1151 self.assertEqual(
1152 msgs[6].message,'Header using the wrong include guard name '
1153'NotInBlink_h')
Daniel Bratell39b5b062018-05-16 18:09:57[diff] [blame]1154
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1155 self.assertEqual(msgs[7].items,['third_party/blink/InBlink.h:1'])
1156 self.assertEqual(
1157 msgs[7].message,'Header using the wrong include guard name '
1158'InBlink_h')
Daniel Bratell8ba52722018-03-02 16:06:14[diff] [blame]1159
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1160 self.assertEqual(msgs[8].items,['third_party/blink/AlsoInBlink.h:1'])
1161 self.assertEqual(
1162 msgs[8].message,'Header using the wrong include guard name '
1163'WrongInBlink_h')
1164
1165 self.assertIn('chrome/renderer/thing/qux.h', msgs[9].message)
1166 self.assertIn(
1167'Recommended #endif comment: // CHROME_RENDERER_THING_QUX_H_',
1168 msgs[9].message)
Lei Zhangd84f9512024-05-28 19:43:30[diff] [blame]1169
1170
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1171classAccessibilityRelnotesFieldTest(unittest.TestCase):
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1172
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1173def testRelnotesPresent(self):
1174 mock_input_api=MockInputApi()
1175 mock_output_api=MockOutputApi()
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1176
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1177 mock_input_api.files=[
1178MockAffectedFile('ui/accessibility/foo.bar',[''])
1179]
1180 mock_input_api.change.DescriptionText=lambda:'Commit description'
1181 mock_input_api.change.footers['AX-Relnotes']=[
1182'Important user facing change'
1183]
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1184
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1185 msgs= PRESUBMIT.CheckAccessibilityRelnotesField(
1186 mock_input_api, mock_output_api)
1187 self.assertEqual(
11880, len(msgs),
1189'Expected %d messages, found %d: %s'%(0, len(msgs), msgs))
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1190
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1191def testRelnotesMissingFromAccessibilityChange(self):
1192 mock_input_api=MockInputApi()
1193 mock_output_api=MockOutputApi()
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1194
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1195 mock_input_api.files=[
1196MockAffectedFile('some/file',['']),
1197MockAffectedFile('ui/accessibility/foo.bar',['']),
1198MockAffectedFile('some/other/file',[''])
1199]
1200 mock_input_api.change.DescriptionText=lambda:'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1201
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1202 msgs= PRESUBMIT.CheckAccessibilityRelnotesField(
1203 mock_input_api, mock_output_api)
1204 self.assertEqual(
12051, len(msgs),
1206'Expected %d messages, found %d: %s'%(1, len(msgs), msgs))
1207 self.assertTrue(
1208"Missing 'AX-Relnotes:' field"in msgs[0].message,
1209'Missing AX-Relnotes field message not found in errors')
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1210
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1211# The relnotes footer is not required for changes which do not touch any
1212# accessibility directories.
1213def testIgnoresNonAccessibilityCode(self):
1214 mock_input_api=MockInputApi()
1215 mock_output_api=MockOutputApi()
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1216
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1217 mock_input_api.files=[
1218MockAffectedFile('some/file',['']),
1219MockAffectedFile('some/other/file',[''])
1220]
1221 mock_input_api.change.DescriptionText=lambda:'Commit description'
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1222
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1223 msgs= PRESUBMIT.CheckAccessibilityRelnotesField(
1224 mock_input_api, mock_output_api)
1225 self.assertEqual(
12260, len(msgs),
1227'Expected %d messages, found %d: %s'%(0, len(msgs), msgs))
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1228
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1229# Test that our presubmit correctly raises an error for a set of known paths.
1230def testExpectedPaths(self):
1231 filesToTest=[
1232"chrome/browser/accessibility/foo.py",
1233"chrome/browser/ash/arc/accessibility/foo.cc",
1234"chrome/browser/ui/views/accessibility/foo.h",
1235"chrome/browser/extensions/api/automation/foo.h",
1236"chrome/browser/extensions/api/automation_internal/foo.cc",
1237"chrome/renderer/extensions/accessibility_foo.h",
1238"chrome/tests/data/accessibility/foo.html",
1239"content/browser/accessibility/foo.cc",
1240"content/renderer/accessibility/foo.h",
1241"content/tests/data/accessibility/foo.cc",
1242"extensions/renderer/api/automation/foo.h",
1243"ui/accessibility/foo/bar/baz.cc",
1244"ui/views/accessibility/foo/bar/baz.h",
1245]
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1246
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1247for testFilein filesToTest:
1248 mock_input_api=MockInputApi()
1249 mock_output_api=MockOutputApi()
Chris Hall59f8d0c72020-05-01 07:31:19[diff] [blame]1250
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1251 mock_input_api.files=[MockAffectedFile(testFile,[''])]
1252 mock_input_api.change.DescriptionText=lambda:'Commit description'
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]1253
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1254 msgs= PRESUBMIT.CheckAccessibilityRelnotesField(
1255 mock_input_api, mock_output_api)
1256 self.assertEqual(
12571, len(msgs),
1258'Expected %d messages, found %d: %s, for file %s'%
1259(1, len(msgs), msgs, testFile))
1260 self.assertTrue(
1261"Missing 'AX-Relnotes:' field"in msgs[0].message,
1262('Missing AX-Relnotes field message not found in errors '
1263' for file %s'%(testFile)))
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1264
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1265# Test that AX-Relnotes field can appear in the commit description (as long
1266# as it appears at the beginning of a line).
1267def testRelnotesInCommitDescription(self):
1268 mock_input_api=MockInputApi()
1269 mock_output_api=MockOutputApi()
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1270
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1271 mock_input_api.files=[
1272MockAffectedFile('ui/accessibility/foo.bar',['']),
1273]
1274 mock_input_api.change.DescriptionText=lambda:(
1275'Description:\n'+
1276'AX-Relnotes: solves all accessibility issues forever')
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1277
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1278 msgs= PRESUBMIT.CheckAccessibilityRelnotesField(
1279 mock_input_api, mock_output_api)
1280 self.assertEqual(
12810, len(msgs),
1282'Expected %d messages, found %d: %s'%(0, len(msgs), msgs))
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1283
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1284# Test that we don't match AX-Relnotes if it appears in the middle of a line.
1285def testRelnotesMustAppearAtBeginningOfLine(self):
1286 mock_input_api=MockInputApi()
1287 mock_output_api=MockOutputApi()
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1288
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1289 mock_input_api.files=[
1290MockAffectedFile('ui/accessibility/foo.bar',['']),
1291]
1292 mock_input_api.change.DescriptionText=lambda:(
1293'Description:\n'+
1294'This change has no AX-Relnotes: we should print a warning')
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1295
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1296 msgs= PRESUBMIT.CheckAccessibilityRelnotesField(
1297 mock_input_api, mock_output_api)
1298 self.assertTrue(
1299"Missing 'AX-Relnotes:' field"in msgs[0].message,
1300'Missing AX-Relnotes field message not found in errors')
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1301
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1302# Tests that the AX-Relnotes field can be lowercase and use a '=' in place
1303# of a ':'.
1304def testRelnotesLowercaseWithEqualSign(self):
1305 mock_input_api=MockInputApi()
1306 mock_output_api=MockOutputApi()
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1307
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1308 mock_input_api.files=[
1309MockAffectedFile('ui/accessibility/foo.bar',['']),
1310]
1311 mock_input_api.change.DescriptionText=lambda:(
1312'Description:\n'+
1313'ax-relnotes= this is a valid format for accessibility relnotes')
1314
1315 msgs= PRESUBMIT.CheckAccessibilityRelnotesField(
1316 mock_input_api, mock_output_api)
1317 self.assertEqual(
13180, len(msgs),
1319'Expected %d messages, found %d: %s'%(0, len(msgs), msgs))
1320
Akihiro Ota08108e542020-05-20 15:30:53[diff] [blame]1321
Mark Schillaci44c90b42024-11-22 20:44:38[diff] [blame]1322classAccessibilityAriaElementAttributeGettersTest(unittest.TestCase):
1323
1324# Test warning is surfaced for various possible uses of bad methods.
1325def testMatchingLines(self):
1326 mock_input_api=MockInputApi()
1327 mock_input_api.files=[
1328MockFile(
1329"third_party/blink/renderer/core/accessibility/ax_object.h",
1330[
1331"->getAttribute(html_names::kAriaCheckedAttr)",
1332"node->hasAttribute(html_names::kRoleAttr)",
1333"->FastHasAttribute(html_names::kAriaLabelAttr)",
1334" .FastGetAttribute(html_names::kAriaCurrentAttr);",
1335
1336],
1337 action='M'
1338),
1339MockFile(
1340"third_party/blink/renderer/core/accessibility/ax_table.cc",
1341[
1342"bool result = node->hasAttribute(html_names::kFooAttr);",
1343"foo->getAttribute(html_names::kAriaInvalidValueAttr)",
1344"foo->GetAriaCurrentState(html_names::kAriaCurrentStateAttr)",
1345],
1346 action='M'
1347),
1348]
1349
1350 results= PRESUBMIT.CheckAccessibilityAriaElementAttributeGetters(mock_input_api,MockOutputApi())
1351 self.assertEqual(1, len(results))
1352 self.assertEqual(5, len(results[0].items))
1353 self.assertIn("ax_object.h:1", results[0].items[0])
1354 self.assertIn("ax_object.h:2", results[0].items[1])
1355 self.assertIn("ax_object.h:3", results[0].items[2])
1356 self.assertIn("ax_object.h:4", results[0].items[3])
1357 self.assertIn("ax_table.cc:2", results[0].items[4])
1358 self.assertIn("Please use ARIA-specific attribute access", results[0].message)
1359
1360# Test no warnings for files that are not accessibility related.
1361def testNonMatchingFiles(self):
1362 mock_input_api=MockInputApi()
1363 mock_input_api.files=[
1364MockFile(
1365"content/browser/foobar/foo.cc",
1366["->getAttribute(html_names::kAriaCheckedAttr)"],
1367 action='M'),
1368MockFile(
1369"third_party/blink/renderer/core/foo.cc",
1370["node->hasAttribute(html_names::kRoleAttr)"],
1371 action='M'),
1372]
1373 results= PRESUBMIT.CheckAccessibilityAriaElementAttributeGetters(mock_input_api,MockOutputApi())
1374 self.assertEqual(0, len(results))
1375
1376# Test no warning when methods are used with different attribute params.
1377def testNoBadParam(self):
1378 mock_input_api=MockInputApi()
1379 mock_input_api.files=[
1380MockFile(
1381"third_party/blink/renderer/core/accessibility/ax_object.h",
1382[
1383"->getAttribute(html_names::kCheckedAttr)",
1384"->hasAttribute(html_names::kIdAttr)",
1385],
1386 action='M'
1387)
1388]
1389
1390 results= PRESUBMIT.CheckAccessibilityAriaElementAttributeGetters(mock_input_api,MockOutputApi())
1391 self.assertEqual(0, len(results))
1392
1393# Test no warning when attribute params are used for different methods.
1394def testNoMethod(self):
1395 mock_input_api=MockInputApi()
1396 mock_input_api.files=[
1397MockFile(
1398"third_party/blink/renderer/core/accessibility/ax_object.cc",
1399[
1400"foo(html_names::kAriaCheckedAttr)",
1401"bar(html_names::kRoleAttr)"
1402],
1403 action='M'
1404)
1405]
1406
1407 results= PRESUBMIT.CheckAccessibilityAriaElementAttributeGetters(mock_input_api,MockOutputApi())
1408 self.assertEqual(0, len(results))
1409
1410
yolandyan45001472016-12-21 21:12:42[diff] [blame]1411classAndroidDeprecatedTestAnnotationTest(unittest.TestCase):
yolandyan45001472016-12-21 21:12:42[diff] [blame]1412
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1413def testCheckAndroidTestAnnotationUsage(self):
1414 mock_input_api=MockInputApi()
1415 mock_output_api=MockOutputApi()
1416
1417 mock_input_api.files=[
1418MockAffectedFile('LalaLand.java',['random stuff']),
1419MockAffectedFile('CorrectUsage.java',[
1420'import androidx.test.filters.LargeTest;',
1421'import androidx.test.filters.MediumTest;',
1422'import androidx.test.filters.SmallTest;',
1423]),
1424MockAffectedFile('UsedDeprecatedLargeTestAnnotation.java',[
1425'import android.test.suitebuilder.annotation.LargeTest;',
1426]),
1427MockAffectedFile('UsedDeprecatedMediumTestAnnotation.java',[
1428'import android.test.suitebuilder.annotation.MediumTest;',
1429]),
1430MockAffectedFile('UsedDeprecatedSmallTestAnnotation.java',[
1431'import android.test.suitebuilder.annotation.SmallTest;',
1432]),
1433MockAffectedFile('UsedDeprecatedSmokeAnnotation.java',[
1434'import android.test.suitebuilder.annotation.Smoke;',
1435])
1436]
1437 msgs= PRESUBMIT._CheckAndroidTestAnnotationUsage(
1438 mock_input_api, mock_output_api)
1439 self.assertEqual(
14401, len(msgs),
1441'Expected %d items, found %d: %s'%(1, len(msgs), msgs))
1442 self.assertEqual(
14434, len(msgs[0].items),'Expected %d items, found %d: %s'%
1444(4, len(msgs[0].items), msgs[0].items))
1445 self.assertTrue(
1446'UsedDeprecatedLargeTestAnnotation.java:1'in msgs[0].items,
1447'UsedDeprecatedLargeTestAnnotation not found in errors')
1448 self.assertTrue(
1449'UsedDeprecatedMediumTestAnnotation.java:1'in msgs[0].items,
1450'UsedDeprecatedMediumTestAnnotation not found in errors')
1451 self.assertTrue(
1452'UsedDeprecatedSmallTestAnnotation.java:1'in msgs[0].items,
1453'UsedDeprecatedSmallTestAnnotation not found in errors')
1454 self.assertTrue(
1455'UsedDeprecatedSmokeAnnotation.java:1'in msgs[0].items,
1456'UsedDeprecatedSmokeAnnotation not found in errors')
1457
yolandyan45001472016-12-21 21:12:42[diff] [blame]1458
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]1459classAndroidBannedImportTest(unittest.TestCase):
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]1460
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1461def testCheckAndroidNoBannedImports(self):
1462 mock_input_api=MockInputApi()
1463 mock_output_api=MockOutputApi()
1464
1465 test_files=[
1466MockAffectedFile('RandomStufff.java',['random stuff']),
1467MockAffectedFile('NoBannedImports.java',[
1468'import androidx.test.filters.LargeTest;',
1469'import androidx.test.filters.MediumTest;',
1470'import androidx.test.filters.SmallTest;',
1471]),
1472MockAffectedFile('BannedUri.java',[
1473'import java.net.URI;',
1474]),
1475MockAffectedFile('BannedTargetApi.java',[
1476'import android.annotation.TargetApi;',
1477]),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1478MockAffectedFile('BannedActivityTestRule.java',[
1479'import androidx.test.rule.ActivityTestRule;',
1480]),
1481MockAffectedFile('BannedVectorDrawableCompat.java',[
1482'import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;',
1483])
1484]
1485 msgs=[]
1486for filein test_files:
1487 mock_input_api.files=[file]
1488 msgs.append(
1489 PRESUBMIT._CheckAndroidNoBannedImports(mock_input_api,
1490 mock_output_api))
1491 self.assertEqual(0, len(msgs[0]))
1492 self.assertEqual(0, len(msgs[1]))
1493 self.assertTrue(msgs[2][0].message.startswith(
1494 textwrap.dedent("""\
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]1495 Banned imports were used.
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1496 BannedUri.java:1:""")))
1497 self.assertTrue(msgs[3][0].message.startswith(
1498 textwrap.dedent("""\
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]1499 Banned imports were used.
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1500 BannedTargetApi.java:1:""")))
1501 self.assertTrue(msgs[4][0].message.startswith(
1502 textwrap.dedent("""\
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]1503 Banned imports were used.
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1504 BannedActivityTestRule.java:1:""")))
Theo Cristea1d9a90a2024-11-14 13:31:30[diff] [blame]1505 self.assertTrue(msgs[5][0].message.startswith(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1506 textwrap.dedent("""\
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]1507 Banned imports were used.
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1508 BannedVectorDrawableCompat.java:1:""")))
1509
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]1510
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1511classCheckNoDownstreamDepsTest(unittest.TestCase):
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1512
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1513def testInvalidDepFromUpstream(self):
1514 mock_input_api=MockInputApi()
1515 mock_output_api=MockOutputApi()
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1516
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1517 mock_input_api.files=[
1518MockAffectedFile('BUILD.gn',
1519['deps = [',' "//clank/target:test",',']']),
1520MockAffectedFile('chrome/android/BUILD.gn',
1521['deps = [ "//clank/target:test" ]']),
1522MockAffectedFile(
1523'chrome/chrome_java_deps.gni',
1524['java_deps = [',' "//clank/target:test",',']']),
1525]
1526 mock_input_api.change.RepositoryRoot=lambda:'chromium/src'
1527 msgs= PRESUBMIT.CheckNoUpstreamDepsOnClank(mock_input_api,
1528 mock_output_api)
1529 self.assertEqual(
15301, len(msgs),
1531'Expected %d items, found %d: %s'%(1, len(msgs), msgs))
1532 self.assertEqual(
15333, len(msgs[0].items),'Expected %d items, found %d: %s'%
1534(3, len(msgs[0].items), msgs[0].items))
1535 self.assertTrue(any('BUILD.gn:2'in itemfor itemin msgs[0].items),
1536'BUILD.gn not found in errors')
1537 self.assertTrue(
1538 any('chrome/android/BUILD.gn:1'in itemfor itemin msgs[0].items),
1539'chrome/android/BUILD.gn:1 not found in errors')
1540 self.assertTrue(
1541 any('chrome/chrome_java_deps.gni:2'in item
1542for itemin msgs[0].items),
1543'chrome/chrome_java_deps.gni:2 not found in errors')
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1544
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1545def testAllowsComments(self):
1546 mock_input_api=MockInputApi()
1547 mock_output_api=MockOutputApi()
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1548
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1549 mock_input_api.files=[
1550MockAffectedFile('BUILD.gn',[
1551'# real implementation in //clank/target:test',
1552]),
1553]
1554 mock_input_api.change.RepositoryRoot=lambda:'chromium/src'
1555 msgs= PRESUBMIT.CheckNoUpstreamDepsOnClank(mock_input_api,
1556 mock_output_api)
1557 self.assertEqual(
15580, len(msgs),
1559'Expected %d items, found %d: %s'%(0, len(msgs), msgs))
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1560
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1561def testOnlyChecksBuildFiles(self):
1562 mock_input_api=MockInputApi()
1563 mock_output_api=MockOutputApi()
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1564
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1565 mock_input_api.files=[
1566MockAffectedFile('README.md',
1567['DEPS = [ "//clank/target:test" ]']),
1568MockAffectedFile('chrome/android/java/file.java',
1569['//clank/ only function']),
1570]
1571 mock_input_api.change.RepositoryRoot=lambda:'chromium/src'
1572 msgs= PRESUBMIT.CheckNoUpstreamDepsOnClank(mock_input_api,
1573 mock_output_api)
1574 self.assertEqual(
15750, len(msgs),
1576'Expected %d items, found %d: %s'%(0, len(msgs), msgs))
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1577
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1578def testValidDepFromDownstream(self):
1579 mock_input_api=MockInputApi()
1580 mock_output_api=MockOutputApi()
1581
1582 mock_input_api.files=[
1583MockAffectedFile('BUILD.gn',
1584['DEPS = [',' "//clank/target:test",',']']),
1585MockAffectedFile('java/BUILD.gn',
1586['DEPS = [ "//clank/target:test" ]']),
1587]
1588 mock_input_api.change.RepositoryRoot=lambda:'chromium/src/clank'
1589 msgs= PRESUBMIT.CheckNoUpstreamDepsOnClank(mock_input_api,
1590 mock_output_api)
1591 self.assertEqual(
15920, len(msgs),
1593'Expected %d items, found %d: %s'%(0, len(msgs), msgs))
Mohamed Heikal5e5b7922020-10-29 18:57:59[diff] [blame]1594
yolandyan45001472016-12-21 21:12:42[diff] [blame]1595
Jinsong Fan91ebbbd2019-04-16 14:57:17[diff] [blame]1596classAndroidDebuggableBuildTest(unittest.TestCase):
1597
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1598def testCheckAndroidDebuggableBuild(self):
1599 mock_input_api=MockInputApi()
1600 mock_output_api=MockOutputApi()
Jinsong Fan91ebbbd2019-04-16 14:57:17[diff] [blame]1601
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1602 mock_input_api.files=[
1603MockAffectedFile('RandomStuff.java',['random stuff']),
1604MockAffectedFile('CorrectUsage.java',[
1605'import org.chromium.base.BuildInfo;',
1606'some random stuff',
1607'boolean isOsDebuggable = BuildInfo.isDebugAndroid();',
1608]),
1609MockAffectedFile('JustCheckUserdebugBuild.java',[
1610'import android.os.Build;',
1611'some random stuff',
1612'boolean isOsDebuggable = Build.TYPE.equals("userdebug")',
1613]),
1614MockAffectedFile('JustCheckEngineeringBuild.java',[
1615'import android.os.Build;',
1616'some random stuff',
1617'boolean isOsDebuggable = "eng".equals(Build.TYPE)',
1618]),
1619MockAffectedFile('UsedBuildType.java',[
1620'import android.os.Build;',
1621'some random stuff',
1622'boolean isOsDebuggable = Build.TYPE.equals("userdebug")'
1623'|| "eng".equals(Build.TYPE)',
1624]),
1625MockAffectedFile('UsedExplicitBuildType.java',[
1626'some random stuff',
1627'boolean isOsDebuggable = android.os.Build.TYPE.equals("userdebug")'
1628'|| "eng".equals(android.os.Build.TYPE)',
1629]),
1630]
Jinsong Fan91ebbbd2019-04-16 14:57:17[diff] [blame]1631
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1632 msgs= PRESUBMIT._CheckAndroidDebuggableBuild(mock_input_api,
1633 mock_output_api)
1634 self.assertEqual(
16351, len(msgs),
1636'Expected %d items, found %d: %s'%(1, len(msgs), msgs))
1637 self.assertEqual(
16384, len(msgs[0].items),'Expected %d items, found %d: %s'%
1639(4, len(msgs[0].items), msgs[0].items))
1640 self.assertTrue('JustCheckUserdebugBuild.java:3'in msgs[0].items)
1641 self.assertTrue('JustCheckEngineeringBuild.java:3'in msgs[0].items)
1642 self.assertTrue('UsedBuildType.java:3'in msgs[0].items)
1643 self.assertTrue('UsedExplicitBuildType.java:2'in msgs[0].items)
Jinsong Fan91ebbbd2019-04-16 14:57:17[diff] [blame]1644
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]1645
dgn4401aa52015-04-29 16:26:17[diff] [blame]1646classLogUsageTest(unittest.TestCase):
1647
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1648def testCheckAndroidCrLogUsage(self):
1649 mock_input_api=MockInputApi()
1650 mock_output_api=MockOutputApi()
dgnaa68d5e2015-06-10 10:08:22[diff] [blame]1651
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1652 mock_input_api.files=[
1653MockAffectedFile('RandomStuff.java',['random stuff']),
1654MockAffectedFile('HasAndroidLog.java',[
1655'import android.util.Log;',
1656'some random stuff',
1657'Log.d("TAG", "foo");',
1658]),
1659MockAffectedFile('HasExplicitUtilLog.java',[
1660'some random stuff',
1661'android.util.Log.d("TAG", "foo");',
1662]),
1663MockAffectedFile('IsInBasePackage.java',[
1664'package org.chromium.base;',
1665'private static final String TAG = "cr_Foo";',
1666'Log.d(TAG, "foo");',
1667]),
1668MockAffectedFile('IsInBasePackageButImportsLog.java',[
1669'package org.chromium.base;',
1670'import android.util.Log;',
1671'private static final String TAG = "cr_Foo";',
1672'Log.d(TAG, "foo");',
1673]),
1674MockAffectedFile('HasBothLog.java',[
1675'import org.chromium.base.Log;',
1676'some random stuff',
1677'private static final String TAG = "cr_Foo";',
1678'Log.d(TAG, "foo");',
1679'android.util.Log.d("TAG", "foo");',
1680]),
1681MockAffectedFile('HasCorrectTag.java',[
1682'import org.chromium.base.Log;',
1683'some random stuff',
1684'private static final String TAG = "cr_Foo";',
1685'Log.d(TAG, "foo");',
1686]),
1687MockAffectedFile('HasOldTag.java',[
1688'import org.chromium.base.Log;',
1689'some random stuff',
1690'private static final String TAG = "cr.Foo";',
1691'Log.d(TAG, "foo");',
1692]),
1693MockAffectedFile('HasDottedTag.java',[
1694'import org.chromium.base.Log;',
1695'some random stuff',
1696'private static final String TAG = "cr_foo.bar";',
1697'Log.d(TAG, "foo");',
1698]),
1699MockAffectedFile('HasDottedTagPublic.java',[
1700'import org.chromium.base.Log;',
1701'some random stuff',
1702'public static final String TAG = "cr_foo.bar";',
1703'Log.d(TAG, "foo");',
1704]),
1705MockAffectedFile('HasNoTagDecl.java',[
1706'import org.chromium.base.Log;',
1707'some random stuff',
1708'Log.d(TAG, "foo");',
1709]),
1710MockAffectedFile('HasIncorrectTagDecl.java',[
1711'import org.chromium.base.Log;',
1712'private static final String TAHG = "cr_Foo";',
1713'some random stuff',
1714'Log.d(TAG, "foo");',
1715]),
1716MockAffectedFile('HasInlineTag.java',[
1717'import org.chromium.base.Log;',
1718'some random stuff',
1719'private static final String TAG = "cr_Foo";',
1720'Log.d("TAG", "foo");',
1721]),
1722MockAffectedFile('HasInlineTagWithSpace.java',[
1723'import org.chromium.base.Log;',
1724'some random stuff',
1725'private static final String TAG = "cr_Foo";',
1726'Log.d("log message", "foo");',
1727]),
1728MockAffectedFile('HasUnprefixedTag.java',[
1729'import org.chromium.base.Log;',
1730'some random stuff',
1731'private static final String TAG = "rubbish";',
1732'Log.d(TAG, "foo");',
1733]),
1734MockAffectedFile('HasTooLongTag.java',[
1735'import org.chromium.base.Log;',
1736'some random stuff',
1737'private static final String TAG = "21_characters_long___";',
1738'Log.d(TAG, "foo");',
1739]),
1740MockAffectedFile('HasTooLongTagWithNoLogCallsInDiff.java',[
1741'import org.chromium.base.Log;',
1742'some random stuff',
1743'private static final String TAG = "21_characters_long___";',
1744]),
1745]
dgnaa68d5e2015-06-10 10:08:22[diff] [blame]1746
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1747 msgs= PRESUBMIT._CheckAndroidCrLogUsage(mock_input_api,
1748 mock_output_api)
dgnaa68d5e2015-06-10 10:08:22[diff] [blame]1749
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1750 self.assertEqual(
17515, len(msgs),
1752'Expected %d items, found %d: %s'%(5, len(msgs), msgs))
dgnaa68d5e2015-06-10 10:08:22[diff] [blame]1753
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1754# Declaration format
1755 nb= len(msgs[0].items)
1756 self.assertEqual(
17572, nb,'Expected %d items, found %d: %s'%(2, nb, msgs[0].items))
1758 self.assertTrue('HasNoTagDecl.java'in msgs[0].items)
1759 self.assertTrue('HasIncorrectTagDecl.java'in msgs[0].items)
dgnaa68d5e2015-06-10 10:08:22[diff] [blame]1760
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1761# Tag length
1762 nb= len(msgs[1].items)
1763 self.assertEqual(
17642, nb,'Expected %d items, found %d: %s'%(2, nb, msgs[1].items))
1765 self.assertTrue('HasTooLongTag.java'in msgs[1].items)
1766 self.assertTrue(
1767'HasTooLongTagWithNoLogCallsInDiff.java'in msgs[1].items)
Geoff Huang77e3d6f2023-12-25 06:27:38[diff] [blame]1768
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1769# Tag must be a variable named TAG
1770 nb= len(msgs[2].items)
1771 self.assertEqual(
17723, nb,'Expected %d items, found %d: %s'%(3, nb, msgs[2].items))
1773 self.assertTrue('HasBothLog.java:5'in msgs[2].items)
1774 self.assertTrue('HasInlineTag.java:4'in msgs[2].items)
1775 self.assertTrue('HasInlineTagWithSpace.java:4'in msgs[2].items)
dgnaa68d5e2015-06-10 10:08:22[diff] [blame]1776
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1777# Util Log usage
1778 nb= len(msgs[3].items)
1779 self.assertEqual(
17803, nb,'Expected %d items, found %d: %s'%(3, nb, msgs[3].items))
1781 self.assertTrue('HasAndroidLog.java:3'in msgs[3].items)
1782 self.assertTrue('HasExplicitUtilLog.java:2'in msgs[3].items)
1783 self.assertTrue('IsInBasePackageButImportsLog.java:4'in msgs[3].items)
Andrew Grieved3a35d82024-01-02 21:24:38[diff] [blame]1784
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1785# Tag must not contain
1786 nb= len(msgs[4].items)
1787 self.assertEqual(
17883, nb,'Expected %d items, found %d: %s'%(2, nb, msgs[4].items))
1789 self.assertTrue('HasDottedTag.java'in msgs[4].items)
1790 self.assertTrue('HasDottedTagPublic.java'in msgs[4].items)
1791 self.assertTrue('HasOldTag.java'in msgs[4].items)
dgn38736db2015-09-18 19:20:51[diff] [blame]1792
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]1793
estadee17314a02017-01-12 16:22:16[diff] [blame]1794classGoogleAnswerUrlFormatTest(unittest.TestCase):
1795
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1796def testCatchAnswerUrlId(self):
1797 input_api=MockInputApi()
1798 input_api.files=[
1799MockFile('somewhere/file.cc',[
1800'char* host = '
1801' "https://support.google.com/chrome/answer/123456";'
1802]),
1803MockFile('somewhere_else/file.cc',[
1804'char* host = '
1805' "https://support.google.com/chrome/a/answer/123456";'
1806]),
1807]
estadee17314a02017-01-12 16:22:16[diff] [blame]1808
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1809 warnings= PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
1810 input_api,MockOutputApi())
1811 self.assertEqual(1, len(warnings))
1812 self.assertEqual(2, len(warnings[0].items))
estadee17314a02017-01-12 16:22:16[diff] [blame]1813
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1814def testAllowAnswerUrlParam(self):
1815 input_api=MockInputApi()
1816 input_api.files=[
1817MockFile('somewhere/file.cc',[
1818'char* host = '
1819' "https://support.google.com/chrome/?p=cpn_crash_reports";'
1820]),
1821]
estadee17314a02017-01-12 16:22:16[diff] [blame]1822
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1823 warnings= PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload(
1824 input_api,MockOutputApi())
1825 self.assertEqual(0, len(warnings))
estadee17314a02017-01-12 16:22:16[diff] [blame]1826
Wei-Yin Chen (陳威尹)54086c212018-07-27 21:41:39[diff] [blame]1827
reillyi38965732015-11-16 18:27:33[diff] [blame]1828classHardcodedGoogleHostsTest(unittest.TestCase):
1829
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1830def testWarnOnAssignedLiterals(self):
1831 input_api=MockInputApi()
1832 input_api.files=[
1833MockFile('content/file.cc',
1834['char* host = "https://www.google.com";']),
1835MockFile('content/file.cc',
1836['char* host = "https://www.googleapis.com";']),
1837MockFile('content/file.cc',
1838['char* host = "https://clients1.google.com";']),
1839]
reillyi38965732015-11-16 18:27:33[diff] [blame]1840
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1841 warnings= PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
1842 input_api,MockOutputApi())
1843 self.assertEqual(1, len(warnings))
1844 self.assertEqual(3, len(warnings[0].items))
reillyi38965732015-11-16 18:27:33[diff] [blame]1845
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1846def testAllowInComment(self):
1847 input_api=MockInputApi()
1848 input_api.files=[
1849MockFile('content/file.cc',
1850['char* host = "https://www.aol.com"; // google.com'])
1851]
reillyi38965732015-11-16 18:27:33[diff] [blame]1852
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1853 warnings= PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers(
1854 input_api,MockOutputApi())
1855 self.assertEqual(0, len(warnings))
reillyi38965732015-11-16 18:27:33[diff] [blame]1856
dgn4401aa52015-04-29 16:26:17[diff] [blame]1857
James Cook6b6597c2019-11-06 22:05:29[diff] [blame]1858classChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
1859
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1860def testWarnsOnChromeOsDirectories(self):
1861 files=[
1862MockFile('ash/file.cc',['PrefRegistrySyncable::SYNCABLE_PREF']),
1863MockFile('chrome/browser/chromeos/file.cc',
1864['PrefRegistrySyncable::SYNCABLE_PREF']),
1865MockFile('chromeos/file.cc',
1866['PrefRegistrySyncable::SYNCABLE_PREF']),
1867MockFile('components/arc/file.cc',
1868['PrefRegistrySyncable::SYNCABLE_PREF']),
1869MockFile('components/exo/file.cc',
1870['PrefRegistrySyncable::SYNCABLE_PREF']),
1871]
1872 input_api=MockInputApi()
1873for filein files:
1874 input_api.files=[file]
1875 warnings= PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
1876 input_api,MockOutputApi())
1877 self.assertEqual(1, len(warnings))
James Cook6b6597c2019-11-06 22:05:29[diff] [blame]1878
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1879def testDoesNotWarnOnSyncOsPref(self):
1880 input_api=MockInputApi()
1881 input_api.files=[
1882MockFile('chromeos/file.cc',
1883['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
1884]
1885 warnings= PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
1886 input_api,MockOutputApi())
1887 self.assertEqual(0, len(warnings))
James Cook6b6597c2019-11-06 22:05:29[diff] [blame]1888
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1889def testDoesNotWarnOnOtherDirectories(self):
1890 input_api=MockInputApi()
1891 input_api.files=[
1892MockFile('chrome/browser/ui/file.cc',
1893['PrefRegistrySyncable::SYNCABLE_PREF']),
1894MockFile('components/sync/file.cc',
1895['PrefRegistrySyncable::SYNCABLE_PREF']),
1896MockFile('content/browser/file.cc',
1897['PrefRegistrySyncable::SYNCABLE_PREF']),
1898MockFile('a/notchromeos/file.cc',
1899['PrefRegistrySyncable::SYNCABLE_PREF']),
1900]
1901 warnings= PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
1902 input_api,MockOutputApi())
1903 self.assertEqual(0, len(warnings))
James Cook6b6597c2019-11-06 22:05:29[diff] [blame]1904
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1905def testSeparateWarningForPriorityPrefs(self):
1906 input_api=MockInputApi()
1907 input_api.files=[
1908MockFile('chromeos/file.cc',[
1909'PrefRegistrySyncable::SYNCABLE_PREF',
1910'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF'
1911]),
1912]
1913 warnings= PRESUBMIT.CheckChromeOsSyncedPrefRegistration(
1914 input_api,MockOutputApi())
1915 self.assertEqual(2, len(warnings))
James Cook6b6597c2019-11-06 22:05:29[diff] [blame]1916
1917
jbriance9e12f162016-11-25 07:57:50[diff] [blame]1918classForwardDeclarationTest(unittest.TestCase):
jbriance9e12f162016-11-25 07:57:50[diff] [blame]1919
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1920def testCheckHeadersOnlyOutsideThirdParty(self):
1921 mock_input_api=MockInputApi()
1922 mock_input_api.files=[
1923MockAffectedFile('somewhere/file.cc',['class DummyClass;']),
1924MockAffectedFile('third_party/header.h',['class DummyClass;'])
1925]
1926 warnings= PRESUBMIT.CheckUselessForwardDeclarations(
1927 mock_input_api,MockOutputApi())
1928 self.assertEqual(0, len(warnings))
jbriance9e12f162016-11-25 07:57:50[diff] [blame]1929
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1930def testNoNestedDeclaration(self):
1931 mock_input_api=MockInputApi()
1932 mock_input_api.files=[
1933MockAffectedFile('somewhere/header.h',[
1934'class SomeClass {',' protected:',' class NotAMatch;','};'
1935])
1936]
1937 warnings= PRESUBMIT.CheckUselessForwardDeclarations(
1938 mock_input_api,MockOutputApi())
1939 self.assertEqual(0, len(warnings))
jbriance9e12f162016-11-25 07:57:50[diff] [blame]1940
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1941def testSubStrings(self):
1942 mock_input_api=MockInputApi()
1943 mock_input_api.files=[
1944MockAffectedFile('somewhere/header.h',[
1945'class NotUsefulClass;','struct SomeStruct;',
1946'UsefulClass *p1;','SomeStructPtr *p2;'
1947])
1948]
1949 warnings= PRESUBMIT.CheckUselessForwardDeclarations(
1950 mock_input_api,MockOutputApi())
1951 self.assertEqual(2, len(warnings))
jbriance9e12f162016-11-25 07:57:50[diff] [blame]1952
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1953def testUselessForwardDeclaration(self):
1954 mock_input_api=MockInputApi()
1955 mock_input_api.files=[
1956MockAffectedFile('somewhere/header.h',[
1957'class DummyClass;','struct DummyStruct;',
1958'class UsefulClass;','std::unique_ptr<UsefulClass> p;'
1959])
1960]
1961 warnings= PRESUBMIT.CheckUselessForwardDeclarations(
1962 mock_input_api,MockOutputApi())
1963 self.assertEqual(2, len(warnings))
1964
1965def testBlinkHeaders(self):
1966 mock_input_api=MockInputApi()
1967 mock_input_api.files=[
1968MockAffectedFile('third_party/blink/header.h',[
1969'class DummyClass;',
1970'struct DummyStruct;',
1971]),
1972MockAffectedFile('third_party\\blink\\header.h',[
1973'class DummyClass;',
1974'struct DummyStruct;',
1975])
1976]
1977 warnings= PRESUBMIT.CheckUselessForwardDeclarations(
1978 mock_input_api,MockOutputApi())
1979 self.assertEqual(4, len(warnings))
jbriance2c51e821a2016-12-12 08:24:31[diff] [blame]1980
jbriance9e12f162016-11-25 07:57:50[diff] [blame]1981
rlanday6802cf632017-05-30 17:48:36[diff] [blame]1982classRelativeIncludesTest(unittest.TestCase):
rlanday6802cf632017-05-30 17:48:36[diff] [blame]1983
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1984def testThirdPartyNotWebKitIgnored(self):
1985 mock_input_api=MockInputApi()
1986 mock_input_api.files=[
1987MockAffectedFile('third_party/test.cpp','#include "../header.h"'),
1988MockAffectedFile('third_party/test/test.cpp',
1989'#include "../header.h"'),
1990]
rlanday6802cf632017-05-30 17:48:36[diff] [blame]1991
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1992 mock_output_api=MockOutputApi()
rlanday6802cf632017-05-30 17:48:36[diff] [blame]1993
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1994 errors= PRESUBMIT.CheckForRelativeIncludes(mock_input_api,
1995 mock_output_api)
1996 self.assertEqual(0, len(errors))
rlanday6802cf632017-05-30 17:48:36[diff] [blame]1997
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]1998def testNonCppFileIgnored(self):
1999 mock_input_api=MockInputApi()
2000 mock_input_api.files=[
2001MockAffectedFile('test.py','#include "../header.h"'),
2002]
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2003
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2004 mock_output_api=MockOutputApi()
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2005
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2006 errors= PRESUBMIT.CheckForRelativeIncludes(mock_input_api,
2007 mock_output_api)
2008 self.assertEqual(0, len(errors))
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2009
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2010def testInnocuousChangesAllowed(self):
2011 mock_input_api=MockInputApi()
2012 mock_input_api.files=[
2013MockAffectedFile('test.cpp','#include "header.h"'),
2014MockAffectedFile('test2.cpp','../'),
2015]
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2016
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2017 mock_output_api=MockOutputApi()
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2018
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2019 errors= PRESUBMIT.CheckForRelativeIncludes(mock_input_api,
2020 mock_output_api)
2021 self.assertEqual(0, len(errors))
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2022
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2023def testRelativeIncludeNonWebKitProducesError(self):
2024 mock_input_api=MockInputApi()
2025 mock_input_api.files=[
2026MockAffectedFile('test.cpp',['#include "../header.h"']),
2027]
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2028
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2029 mock_output_api=MockOutputApi()
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2030
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2031 errors= PRESUBMIT.CheckForRelativeIncludes(mock_input_api,
2032 mock_output_api)
2033 self.assertEqual(1, len(errors))
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2034
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2035def testRelativeIncludeWebKitProducesError(self):
2036 mock_input_api=MockInputApi()
2037 mock_input_api.files=[
2038MockAffectedFile('third_party/blink/test.cpp',
2039['#include "../header.h']),
2040]
rlanday6802cf632017-05-30 17:48:36[diff] [blame]2041
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2042 mock_output_api=MockOutputApi()
2043
2044 errors= PRESUBMIT.CheckForRelativeIncludes(mock_input_api,
2045 mock_output_api)
2046 self.assertEqual(1, len(errors))
dbeam1ec68ac2016-12-15 05:22:24[diff] [blame]2047
Daniel Cheng13ca61a882017-08-25 15:11:25[diff] [blame]2048
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2049classCCIncludeTest(unittest.TestCase):
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2050
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2051def testThirdPartyNotBlinkIgnored(self):
2052 mock_input_api=MockInputApi()
2053 mock_input_api.files=[
2054MockAffectedFile('third_party/test.cpp','#include "file.cc"'),
2055]
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2056
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2057 mock_output_api=MockOutputApi()
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2058
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2059 errors= PRESUBMIT.CheckForCcIncludes(mock_input_api, mock_output_api)
2060 self.assertEqual(0, len(errors))
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2061
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2062def testPythonFileIgnored(self):
2063 mock_input_api=MockInputApi()
2064 mock_input_api.files=[
2065MockAffectedFile('test.py','#include "file.cc"'),
2066]
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2067
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2068 mock_output_api=MockOutputApi()
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2069
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2070 errors= PRESUBMIT.CheckForCcIncludes(mock_input_api, mock_output_api)
2071 self.assertEqual(0, len(errors))
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2072
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2073def testIncFilesAccepted(self):
2074 mock_input_api=MockInputApi()
2075 mock_input_api.files=[
2076MockAffectedFile('test.py','#include "file.inc"'),
2077]
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2078
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2079 mock_output_api=MockOutputApi()
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2080
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2081 errors= PRESUBMIT.CheckForCcIncludes(mock_input_api, mock_output_api)
2082 self.assertEqual(0, len(errors))
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2083
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2084def testInnocuousChangesAllowed(self):
2085 mock_input_api=MockInputApi()
2086 mock_input_api.files=[
2087MockAffectedFile('test.cpp','#include "header.h"'),
2088MockAffectedFile('test2.cpp','Something "file.cc"'),
2089]
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2090
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2091 mock_output_api=MockOutputApi()
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2092
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2093 errors= PRESUBMIT.CheckForCcIncludes(mock_input_api, mock_output_api)
2094 self.assertEqual(0, len(errors))
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2095
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2096def testCcIncludeNonBlinkProducesError(self):
2097 mock_input_api=MockInputApi()
2098 mock_input_api.files=[
2099MockAffectedFile('test.cpp',['#include "file.cc"']),
2100]
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2101
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2102 mock_output_api=MockOutputApi()
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2103
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2104 errors= PRESUBMIT.CheckForCcIncludes(mock_input_api, mock_output_api)
2105 self.assertEqual(1, len(errors))
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2106
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2107def testCppIncludeBlinkProducesError(self):
2108 mock_input_api=MockInputApi()
2109 mock_input_api.files=[
2110MockAffectedFile('third_party/blink/test.cpp',
2111['#include "foo/file.cpp"']),
2112]
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2113
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2114 mock_output_api=MockOutputApi()
2115
2116 errors= PRESUBMIT.CheckForCcIncludes(mock_input_api, mock_output_api)
2117 self.assertEqual(1, len(errors))
Daniel Bratell65b033262019-04-23 08:17:06[diff] [blame]2118
2119
Andrew Grieve1b290e4a22020-11-24 20:07:01[diff] [blame]2120classGnGlobForwardTest(unittest.TestCase):
Andrew Grieve1b290e4a22020-11-24 20:07:01[diff] [blame]2121
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2122def testAddBareGlobs(self):
2123 mock_input_api=MockInputApi()
2124 mock_input_api.files=[
2125MockAffectedFile('base/stuff.gni',
2126['forward_variables_from(invoker, "*")']),
2127MockAffectedFile('base/BUILD.gn',
2128['forward_variables_from(invoker, "*")']),
2129]
2130 warnings= PRESUBMIT.CheckGnGlobForward(mock_input_api,
2131MockOutputApi())
2132 self.assertEqual(1, len(warnings))
2133 msg='\n'.join(warnings[0].items)
2134 self.assertIn('base/stuff.gni', msg)
2135# Should not check .gn files. Local templates don't need to care about
2136# visibility / testonly.
2137 self.assertNotIn('base/BUILD.gn', msg)
2138
2139def testValidUses(self):
2140 mock_input_api=MockInputApi()
2141 mock_input_api.files=[
2142MockAffectedFile('base/stuff.gni',
2143['forward_variables_from(invoker, "*", [])']),
2144MockAffectedFile('base/stuff2.gni',[
2145'forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)'
2146]),
2147MockAffectedFile(
2148'base/stuff3.gni',
2149['forward_variables_from(invoker, [ "testonly" ])']),
2150]
2151 warnings= PRESUBMIT.CheckGnGlobForward(mock_input_api,
2152MockOutputApi())
2153 self.assertEqual([], warnings)
Andrew Grieve1b290e4a22020-11-24 20:07:01[diff] [blame]2154
2155
Sean Kaucb7c9b32022-10-25 21:25:52[diff] [blame]2156classGnRebasePathTest(unittest.TestCase):
Sean Kaucb7c9b32022-10-25 21:25:52[diff] [blame]2157
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2158def testAddAbsolutePath(self):
2159 mock_input_api=MockInputApi()
2160 mock_input_api.files=[
2161MockAffectedFile('base/BUILD.gn',
2162['rebase_path("$target_gen_dir", "//")']),
2163MockAffectedFile('base/root/BUILD.gn',
2164['rebase_path("$target_gen_dir", "/")']),
2165MockAffectedFile('base/variable/BUILD.gn',
2166['rebase_path(target_gen_dir, "/")']),
2167]
2168 warnings= PRESUBMIT.CheckGnRebasePath(mock_input_api,MockOutputApi())
2169 self.assertEqual(1, len(warnings))
2170 msg='\n'.join(warnings[0].items)
2171 self.assertIn('base/BUILD.gn', msg)
2172 self.assertIn('base/root/BUILD.gn', msg)
2173 self.assertIn('base/variable/BUILD.gn', msg)
2174 self.assertEqual(3, len(warnings[0].items))
2175
2176def testValidUses(self):
2177 mock_input_api=MockInputApi()
2178 mock_input_api.files=[
2179MockAffectedFile(
2180'base/foo/BUILD.gn',
2181['rebase_path("$target_gen_dir", root_build_dir)']),
2182MockAffectedFile(
2183'base/bar/BUILD.gn',
2184['rebase_path("$target_gen_dir", root_build_dir, "/")']),
2185MockAffectedFile('base/baz/BUILD.gn',
2186['rebase_path(target_gen_dir, root_build_dir)']),
2187MockAffectedFile(
2188'base/baz/BUILD.gn',
2189['rebase_path(target_gen_dir, "//some/arbitrary/path")']),
2190MockAffectedFile('base/okay_slash/BUILD.gn',
2191['rebase_path(".", "//")']),
2192]
2193 warnings= PRESUBMIT.CheckGnRebasePath(mock_input_api,MockOutputApi())
2194 self.assertEqual([], warnings)
Sean Kaucb7c9b32022-10-25 21:25:52[diff] [blame]2195
2196
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2197classNewHeaderWithoutGnChangeTest(unittest.TestCase):
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2198
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2199def testAddHeaderWithoutGn(self):
2200 mock_input_api=MockInputApi()
2201 mock_input_api.files=[
2202MockAffectedFile('base/stuff.h',''),
2203]
2204 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2205 mock_input_api,MockOutputApi())
2206 self.assertEqual(1, len(warnings))
2207 self.assertTrue('base/stuff.h'in warnings[0].items)
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2208
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2209def testModifyHeader(self):
2210 mock_input_api=MockInputApi()
2211 mock_input_api.files=[
2212MockAffectedFile('base/stuff.h','', action='M'),
2213]
2214 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2215 mock_input_api,MockOutputApi())
2216 self.assertEqual(0, len(warnings))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2217
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2218def testDeleteHeader(self):
2219 mock_input_api=MockInputApi()
2220 mock_input_api.files=[
2221MockAffectedFile('base/stuff.h','', action='D'),
2222]
2223 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2224 mock_input_api,MockOutputApi())
2225 self.assertEqual(0, len(warnings))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2226
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2227def testAddHeaderWithGn(self):
2228 mock_input_api=MockInputApi()
2229 mock_input_api.files=[
2230MockAffectedFile('base/stuff.h',''),
2231MockAffectedFile('base/BUILD.gn','stuff.h'),
2232]
2233 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2234 mock_input_api,MockOutputApi())
2235 self.assertEqual(0, len(warnings))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2236
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2237def testAddHeaderWithGni(self):
2238 mock_input_api=MockInputApi()
2239 mock_input_api.files=[
2240MockAffectedFile('base/stuff.h',''),
2241MockAffectedFile('base/files.gni','stuff.h'),
2242]
2243 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2244 mock_input_api,MockOutputApi())
2245 self.assertEqual(0, len(warnings))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2246
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2247def testAddHeaderWithOther(self):
2248 mock_input_api=MockInputApi()
2249 mock_input_api.files=[
2250MockAffectedFile('base/stuff.h',''),
2251MockAffectedFile('base/stuff.cc','stuff.h'),
2252]
2253 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2254 mock_input_api,MockOutputApi())
2255 self.assertEqual(1, len(warnings))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2256
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2257def testAddHeaderWithWrongGn(self):
2258 mock_input_api=MockInputApi()
2259 mock_input_api.files=[
2260MockAffectedFile('base/stuff.h',''),
2261MockAffectedFile('base/BUILD.gn','stuff_h'),
2262]
2263 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2264 mock_input_api,MockOutputApi())
2265 self.assertEqual(1, len(warnings))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2266
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2267def testAddHeadersWithGn(self):
2268 mock_input_api=MockInputApi()
2269 mock_input_api.files=[
2270MockAffectedFile('base/stuff.h',''),
2271MockAffectedFile('base/another.h',''),
2272MockAffectedFile('base/BUILD.gn','another.h\nstuff.h'),
2273]
2274 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2275 mock_input_api,MockOutputApi())
2276 self.assertEqual(0, len(warnings))
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2277
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2278def testAddHeadersWithWrongGn(self):
2279 mock_input_api=MockInputApi()
2280 mock_input_api.files=[
2281MockAffectedFile('base/stuff.h',''),
2282MockAffectedFile('base/another.h',''),
2283MockAffectedFile('base/BUILD.gn','another_h\nstuff.h'),
2284]
2285 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2286 mock_input_api,MockOutputApi())
2287 self.assertEqual(1, len(warnings))
2288 self.assertFalse('base/stuff.h'in warnings[0].items)
2289 self.assertTrue('base/another.h'in warnings[0].items)
2290
2291def testAddHeadersWithWrongGn2(self):
2292 mock_input_api=MockInputApi()
2293 mock_input_api.files=[
2294MockAffectedFile('base/stuff.h',''),
2295MockAffectedFile('base/another.h',''),
2296MockAffectedFile('base/BUILD.gn','another_h\nstuff_h'),
2297]
2298 warnings= PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload(
2299 mock_input_api,MockOutputApi())
2300 self.assertEqual(1, len(warnings))
2301 self.assertTrue('base/stuff.h'in warnings[0].items)
2302 self.assertTrue('base/another.h'in warnings[0].items)
Wei-Yin Chen (陳威尹)c0624d002018-07-30 18:22:19[diff] [blame]2303
2304
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]2305classCorrectProductNameInMessagesTest(unittest.TestCase):
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]2306
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2307def testProductNameInDesc(self):
2308 mock_input_api=MockInputApi()
2309 mock_input_api.files=[
2310MockAffectedFile('chrome/app/google_chrome_strings.grd',[
2311'<message name="Foo" desc="Welcome to Chrome">',
2312' Welcome to Chrome!',
2313'</message>',
2314]),
2315MockAffectedFile('chrome/app/chromium_strings.grd',[
2316'<message name="Bar" desc="Welcome to Chrome">',
2317' Welcome to Chromium!',
2318'</message>',
2319]),
2320]
2321 warnings= PRESUBMIT.CheckCorrectProductNameInMessages(
2322 mock_input_api,MockOutputApi())
2323 self.assertEqual(0, len(warnings))
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]2324
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2325def testChromeInChromium(self):
2326 mock_input_api=MockInputApi()
2327 mock_input_api.files=[
2328MockAffectedFile('chrome/app/google_chrome_strings.grd',[
2329'<message name="Foo" desc="Welcome to Chrome">',
2330' Welcome to Chrome!',
2331'</message>',
2332]),
2333MockAffectedFile('chrome/app/chromium_strings.grd',[
2334'<message name="Bar" desc="Welcome to Chrome">',
2335' Welcome to Chrome!',
2336'</message>',
2337]),
2338]
2339 warnings= PRESUBMIT.CheckCorrectProductNameInMessages(
2340 mock_input_api,MockOutputApi())
2341 self.assertEqual(1, len(warnings))
2342 self.assertTrue(
2343'chrome/app/chromium_strings.grd'in warnings[0].items[0])
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]2344
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2345def testChromiumInChrome(self):
2346 mock_input_api=MockInputApi()
2347 mock_input_api.files=[
2348MockAffectedFile('chrome/app/google_chrome_strings.grd',[
2349'<message name="Foo" desc="Welcome to Chrome">',
2350' Welcome to Chromium!',
2351'</message>',
2352]),
2353MockAffectedFile('chrome/app/chromium_strings.grd',[
2354'<message name="Bar" desc="Welcome to Chrome">',
2355' Welcome to Chromium!',
2356'</message>',
2357]),
2358]
2359 warnings= PRESUBMIT.CheckCorrectProductNameInMessages(
2360 mock_input_api,MockOutputApi())
2361 self.assertEqual(1, len(warnings))
2362 self.assertTrue(
2363'chrome/app/google_chrome_strings.grd:2'in warnings[0].items[0])
Thiago Perrotta099034f2023-06-05 18:10:20[diff] [blame]2364
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2365def testChromeForTestingInChromium(self):
2366 mock_input_api=MockInputApi()
2367 mock_input_api.files=[
2368MockAffectedFile('chrome/app/chromium_strings.grd',[
2369'<message name="Bar" desc="Welcome to Chrome">',
2370' Welcome to Chrome for Testing!',
2371'</message>',
2372]),
2373]
2374 warnings= PRESUBMIT.CheckCorrectProductNameInMessages(
2375 mock_input_api,MockOutputApi())
2376 self.assertEqual(0, len(warnings))
Thiago Perrotta099034f2023-06-05 18:10:20[diff] [blame]2377
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2378def testChromeForTestingInChrome(self):
2379 mock_input_api=MockInputApi()
2380 mock_input_api.files=[
2381MockAffectedFile('chrome/app/google_chrome_strings.grd',[
2382'<message name="Bar" desc="Welcome to Chrome">',
2383' Welcome to Chrome for Testing!',
2384'</message>',
2385]),
2386]
2387 warnings= PRESUBMIT.CheckCorrectProductNameInMessages(
2388 mock_input_api,MockOutputApi())
2389 self.assertEqual(1, len(warnings))
2390 self.assertTrue(
2391'chrome/app/google_chrome_strings.grd:2'in warnings[0].items[0])
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]2392
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2393def testMultipleInstances(self):
2394 mock_input_api=MockInputApi()
2395 mock_input_api.files=[
2396MockAffectedFile('chrome/app/chromium_strings.grd',[
2397'<message name="Bar" desc="Welcome to Chrome">',
2398' Welcome to Chrome!',
2399'</message>',
2400'<message name="Baz" desc="A correct message">',
2401' Chromium is the software you are using.',
2402'</message>',
2403'<message name="Bat" desc="An incorrect message">',
2404' Google Chrome is the software you are using.',
2405'</message>',
2406]),
2407]
2408 warnings= PRESUBMIT.CheckCorrectProductNameInMessages(
2409 mock_input_api,MockOutputApi())
2410 self.assertEqual(1, len(warnings))
2411 self.assertTrue(
2412'chrome/app/chromium_strings.grd:2'in warnings[0].items[0])
2413 self.assertTrue(
2414'chrome/app/chromium_strings.grd:8'in warnings[0].items[1])
2415
2416def testMultipleWarnings(self):
2417 mock_input_api=MockInputApi()
2418 mock_input_api.files=[
2419MockAffectedFile('chrome/app/chromium_strings.grd',[
2420'<message name="Bar" desc="Welcome to Chrome">',
2421' Welcome to Chrome!',
2422'</message>',
2423'<message name="Baz" desc="A correct message">',
2424' Chromium is the software you are using.',
2425'</message>',
2426'<message name="Bat" desc="An incorrect message">',
2427' Google Chrome is the software you are using.',
2428'</message>',
2429]),
2430MockAffectedFile(
2431'components/components_google_chrome_strings.grd',[
2432'<message name="Bar" desc="Welcome to Chrome">',
2433' Welcome to Chrome!',
2434'</message>',
2435'<message name="Baz" desc="A correct message">',
2436' Chromium is the software you are using.',
2437'</message>',
2438'<message name="Bat" desc="An incorrect message">',
2439' Google Chrome is the software you are using.',
2440'</message>',
2441]),
2442]
2443 warnings= PRESUBMIT.CheckCorrectProductNameInMessages(
2444 mock_input_api,MockOutputApi())
2445 self.assertEqual(2, len(warnings))
2446 self.assertTrue('components/components_google_chrome_strings.grd:5'in
2447 warnings[0].items[0])
2448 self.assertTrue(
2449'chrome/app/chromium_strings.grd:2'in warnings[1].items[0])
2450 self.assertTrue(
2451'chrome/app/chromium_strings.grd:8'in warnings[1].items[1])
Michael Giuffridad3bc8672018-10-25 22:48:02[diff] [blame]2452
2453
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]2454class_SecurityOwnersTestCase(unittest.TestCase):
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]2455
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2456def _createMockInputApi(self):
2457 mock_input_api=MockInputApi()
Daniel Chengd88244472022-05-16 09:08:47[diff] [blame]2458
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2459defFakeRepositoryRoot():
2460return mock_input_api.os_path.join('chromium','src')
Daniel Chengd88244472022-05-16 09:08:47[diff] [blame]2461
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2462 mock_input_api.change.RepositoryRoot=FakeRepositoryRoot
2463 self._injectFakeOwnersClient(
2464 mock_input_api,['apple@chromium.org','orange@chromium.org'])
2465return mock_input_api
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]2466
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2467def _setupFakeChange(self, input_api):
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]2468
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2469classFakeGerrit(object):
2470
2471defIsOwnersOverrideApproved(self, issue):
2472returnFalse
2473
2474 input_api.change.issue=123
2475 input_api.gerrit=FakeGerrit()
2476
2477def _injectFakeOwnersClient(self, input_api, owners):
2478
2479classFakeOwnersClient(object):
2480
2481defListOwners(self, f):
2482return owners
2483
2484 input_api.owners_client=FakeOwnersClient()
2485
2486def _injectFakeChangeOwnerAndReviewers(self, input_api, owner, reviewers):
2487
2488defMockOwnerAndReviewers(input_api,
2489 email_regexp,
2490 approval_needed=False):
2491return[owner, reviewers]
2492
2493 input_api.canned_checks.GetCodereviewOwnerAndReviewers= \
2494MockOwnerAndReviewers
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]2495
2496
2497classIpcSecurityOwnerTest(_SecurityOwnersTestCase):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2498 _test_cases=[
2499('*_messages.cc','scary_messages.cc'),
2500('*_messages*.h','scary_messages.h'),
2501('*_messages*.h','scary_messages_android.h'),
2502('*_param_traits*.*','scary_param_traits.h'),
2503('*_param_traits*.*','scary_param_traits_win.h'),
2504('*.mojom','scary.mojom'),
2505('*_mojom_traits*.*','scary_mojom_traits.h'),
2506('*_mojom_traits*.*','scary_mojom_traits_mac.h'),
2507('*_type_converter*.*','scary_type_converter.h'),
2508('*_type_converter*.*','scary_type_converter_nacl.h'),
2509('*.aidl','scary.aidl'),
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]2510]
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]2511
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2512def testHasCorrectPerFileRulesAndSecurityReviewer(self):
2513 mock_input_api= self._createMockInputApi()
2514 new_owners_file_path= mock_input_api.os_path.join(
2515'services','goat','public','OWNERS')
2516 new_owners_file=[
2517'per-file *.mojom=set noparent',
2518'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2519]
Daniel Cheng3008dc12022-05-13 04:02:11[diff] [blame]2520
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2521defFakeReadFile(filename):
2522 self.assertEqual(
2523 mock_input_api.os_path.join('chromium','src',
2524 new_owners_file_path), filename)
2525return'\n'.join(new_owners_file)
Daniel Cheng3008dc12022-05-13 04:02:11[diff] [blame]2526
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2527 mock_input_api.ReadFile=FakeReadFile
2528 mock_input_api.files=[
2529MockAffectedFile(new_owners_file_path, new_owners_file),
Daniel Cheng171dad8d2022-05-21 00:40:25[diff] [blame]2530MockAffectedFile(
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2531 mock_input_api.os_path.join('services','goat','public',
2532'goat.mojom'),
2533['// Scary contents.'])
2534]
2535 self._setupFakeChange(mock_input_api)
2536 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2537'owner@chromium.org',
2538['orange@chromium.org'])
2539 mock_input_api.is_committing=True
2540 mock_input_api.dry_run=False
2541 mock_output_api=MockOutputApi()
2542 results= PRESUBMIT.CheckSecurityOwners(mock_input_api,
2543 mock_output_api)
2544 self.assertEqual(0, len(results))
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]2545
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2546def testMissingSecurityReviewerAtUpload(self):
2547 mock_input_api= self._createMockInputApi()
2548 new_owners_file_path= mock_input_api.os_path.join(
2549'services','goat','public','OWNERS')
2550 new_owners_file=[
2551'per-file *.mojom=set noparent',
2552'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2553]
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]2554
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2555defFakeReadFile(filename):
2556 self.assertEqual(
2557 mock_input_api.os_path.join('chromium','src',
2558 new_owners_file_path), filename)
2559return'\n'.join(new_owners_file)
Ken Rockot9f668262018-12-21 18:56:36[diff] [blame]2560
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2561 mock_input_api.ReadFile=FakeReadFile
2562 mock_input_api.files=[
2563MockAffectedFile(new_owners_file_path, new_owners_file),
2564MockAffectedFile(
2565 mock_input_api.os_path.join('services','goat','public',
2566'goat.mojom'),
2567['// Scary contents.'])
2568]
2569 self._setupFakeChange(mock_input_api)
2570 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2571'owner@chromium.org',
2572['banana@chromium.org'])
2573 mock_input_api.is_committing=False
2574 mock_input_api.dry_run=False
2575 mock_output_api=MockOutputApi()
2576 results= PRESUBMIT.CheckSecurityOwners(mock_input_api,
2577 mock_output_api)
2578 self.assertEqual(1, len(results))
2579 self.assertEqual('notify', results[0].type)
2580 self.assertEqual(
2581'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2582'following newly-added files:', results[0].message)
2583
2584def testMissingSecurityReviewerAtDryRunCommit(self):
2585 mock_input_api= self._createMockInputApi()
2586 new_owners_file_path= mock_input_api.os_path.join(
2587'services','goat','public','OWNERS')
2588 new_owners_file=[
2589'per-file *.mojom=set noparent',
2590'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2591]
2592
2593defFakeReadFile(filename):
2594 self.assertEqual(
2595 mock_input_api.os_path.join('chromium','src',
2596 new_owners_file_path), filename)
2597return'\n'.join(new_owners_file)
2598
2599 mock_input_api.ReadFile=FakeReadFile
2600 mock_input_api.files=[
2601MockAffectedFile(new_owners_file_path, new_owners_file),
2602MockAffectedFile(
2603 mock_input_api.os_path.join('services','goat','public',
2604'goat.mojom'),
2605['// Scary contents.'])
2606]
2607 self._setupFakeChange(mock_input_api)
2608 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2609'owner@chromium.org',
2610['banana@chromium.org'])
2611 mock_input_api.is_committing=True
2612 mock_input_api.dry_run=True
2613 mock_output_api=MockOutputApi()
2614 results= PRESUBMIT.CheckSecurityOwners(mock_input_api,
2615 mock_output_api)
2616 self.assertEqual(1, len(results))
2617 self.assertEqual('error', results[0].type)
2618 self.assertEqual(
2619'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2620'following newly-added files:', results[0].message)
2621
2622def testMissingSecurityApprovalAtRealCommit(self):
2623 mock_input_api= self._createMockInputApi()
2624 new_owners_file_path= mock_input_api.os_path.join(
2625'services','goat','public','OWNERS')
2626 new_owners_file=[
2627'per-file *.mojom=set noparent',
2628'per-file *.mojom=file://ipc/SECURITY_OWNERS'
2629]
2630
2631defFakeReadFile(filename):
2632 self.assertEqual(
2633 mock_input_api.os_path.join('chromium','src',
2634 new_owners_file_path), filename)
2635return'\n'.join(new_owners_file)
2636
2637 mock_input_api.ReadFile=FakeReadFile
2638 mock_input_api.files=[
2639MockAffectedFile(new_owners_file_path, new_owners_file),
2640MockAffectedFile(
2641 mock_input_api.os_path.join('services','goat','public',
2642'goat.mojom'),
2643['// Scary contents.'])
2644]
2645 self._setupFakeChange(mock_input_api)
2646 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2647'owner@chromium.org',
2648['banana@chromium.org'])
2649 mock_input_api.is_committing=True
2650 mock_input_api.dry_run=False
2651 mock_output_api=MockOutputApi()
2652 results= PRESUBMIT.CheckSecurityOwners(mock_input_api,
2653 mock_output_api)
2654 self.assertEqual('error', results[0].type)
2655 self.assertEqual(
2656'Review from an owner in ipc/SECURITY_OWNERS is required for the '
2657'following newly-added files:', results[0].message)
2658
2659def testIpcChangeNeedsSecurityOwner(self):
2660for is_committingin[True,False]:
2661for pattern, filenamein self._test_cases:
2662with self.subTest(
2663 line=
2664 f'is_committing={is_committing}, filename={filename}'):
2665 mock_input_api= self._createMockInputApi()
2666 mock_input_api.files=[
2667MockAffectedFile(
2668 mock_input_api.os_path.join(
2669'services','goat','public', filename),
2670['// Scary contents.'])
2671]
2672 self._setupFakeChange(mock_input_api)
2673 self._injectFakeChangeOwnerAndReviewers(
2674 mock_input_api,'owner@chromium.org',
2675['banana@chromium.org'])
2676 mock_input_api.is_committing= is_committing
2677 mock_input_api.dry_run=False
2678 mock_output_api=MockOutputApi()
2679 results= PRESUBMIT.CheckSecurityOwners(
2680 mock_input_api, mock_output_api)
2681 self.assertEqual(1, len(results))
2682 self.assertEqual('error', results[0].type)
2683 self.assertTrue(results[0].message.replace(
2684'\\','/'
2685).startswith(
2686'Found missing OWNERS lines for security-sensitive files. '
2687'Please add the following lines to services/goat/public/OWNERS:'
2688))
2689 self.assertEqual(['ipc-security-reviews@chromium.org'],
2690 mock_output_api.more_cc)
2691
2692def testServiceManifestChangeNeedsSecurityOwner(self):
2693 mock_input_api= self._createMockInputApi()
2694 mock_input_api.files=[
2695MockAffectedFile(
2696 mock_input_api.os_path.join('services','goat','public',
2697'cpp','manifest.cc'),
2698[
2699'#include "services/goat/public/cpp/manifest.h"',
2700'const service_manager::Manifest& GetManifest() {}',
2701])
2702]
2703 self._setupFakeChange(mock_input_api)
2704 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2705'owner@chromium.org',
2706['banana@chromium.org'])
2707 mock_output_api=MockOutputApi()
2708 errors= PRESUBMIT.CheckSecurityOwners(mock_input_api, mock_output_api)
2709 self.assertEqual(1, len(errors))
2710 self.assertTrue(errors[0].message.replace('\\','/').startswith(
2711'Found missing OWNERS lines for security-sensitive files. '
2712'Please add the following lines to services/goat/public/cpp/OWNERS:'
2713))
2714 self.assertEqual(['ipc-security-reviews@chromium.org'],
2715 mock_output_api.more_cc)
2716
2717def testNonServiceManifestSourceChangesDoNotRequireSecurityOwner(self):
2718 mock_input_api= self._createMockInputApi()
2719 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2720'owner@chromium.org',
2721['banana@chromium.org'])
2722 mock_input_api.files=[
2723MockAffectedFile('some/non/service/thing/foo_manifest.cc',[
2724'const char kNoEnforcement[] = "not a manifest!";',
2725])
2726]
2727 mock_output_api=MockOutputApi()
2728 errors= PRESUBMIT.CheckSecurityOwners(mock_input_api, mock_output_api)
2729 self.assertEqual([], errors)
2730 self.assertEqual([], mock_output_api.more_cc)
Wez17c66962020-04-29 15:26:03[diff] [blame]2731
2732
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]2733classFuchsiaSecurityOwnerTest(_SecurityOwnersTestCase):
Wez17c66962020-04-29 15:26:03[diff] [blame]2734
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2735def testFidlChangeNeedsSecurityOwner(self):
2736 mock_input_api= self._createMockInputApi()
2737 mock_input_api.files=[
2738MockAffectedFile('potentially/scary/ipc.fidl',
2739['library test.fidl'])
2740]
2741 self._setupFakeChange(mock_input_api)
2742 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2743'owner@chromium.org',
2744['banana@chromium.org'])
2745 mock_output_api=MockOutputApi()
2746 errors= PRESUBMIT.CheckSecurityOwners(mock_input_api, mock_output_api)
2747 self.assertEqual(1, len(errors))
2748 self.assertTrue(errors[0].message.replace('\\','/').startswith(
2749'Found missing OWNERS lines for security-sensitive files. '
2750'Please add the following lines to potentially/scary/OWNERS:'))
Wez17c66962020-04-29 15:26:03[diff] [blame]2751
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2752def testComponentManifestV1ChangeNeedsSecurityOwner(self):
2753 mock_input_api= self._createMockInputApi()
2754 mock_input_api.files=[
2755MockAffectedFile('potentially/scary/v2_manifest.cmx',
2756['{ "that is no": "manifest!" }'])
2757]
2758 self._setupFakeChange(mock_input_api)
2759 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2760'owner@chromium.org',
2761['banana@chromium.org'])
2762 mock_output_api=MockOutputApi()
2763 errors= PRESUBMIT.CheckSecurityOwners(mock_input_api, mock_output_api)
2764 self.assertEqual(1, len(errors))
2765 self.assertTrue(errors[0].message.replace('\\','/').startswith(
2766'Found missing OWNERS lines for security-sensitive files. '
2767'Please add the following lines to potentially/scary/OWNERS:'))
Wez17c66962020-04-29 15:26:03[diff] [blame]2768
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2769def testComponentManifestV2NeedsSecurityOwner(self):
2770 mock_input_api= self._createMockInputApi()
2771 mock_input_api.files=[
2772MockAffectedFile('potentially/scary/v2_manifest.cml',
2773['{ "that is no": "manifest!" }'])
2774]
2775 self._setupFakeChange(mock_input_api)
2776 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2777'owner@chromium.org',
2778['banana@chromium.org'])
2779 mock_output_api=MockOutputApi()
2780 errors= PRESUBMIT.CheckSecurityOwners(mock_input_api, mock_output_api)
2781 self.assertEqual(1, len(errors))
2782 self.assertTrue(errors[0].message.replace('\\','/').startswith(
2783'Found missing OWNERS lines for security-sensitive files. '
2784'Please add the following lines to potentially/scary/OWNERS:'))
Joshua Peraza1ca6d392020-12-08 00:14:09[diff] [blame]2785
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2786def testThirdPartyTestsDoNotRequireSecurityOwner(self):
2787 mock_input_api=MockInputApi()
2788 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2789'owner@chromium.org',
2790['banana@chromium.org'])
2791 mock_input_api.files=[
2792MockAffectedFile('third_party/crashpad/test/tests.cmx',[
2793'const char kNoEnforcement[] = "Security?!? Pah!";',
2794])
2795]
2796 mock_output_api=MockOutputApi()
2797 errors= PRESUBMIT.CheckSecurityOwners(mock_input_api, mock_output_api)
2798 self.assertEqual([], errors)
2799
2800def testOtherFuchsiaChangesDoNotRequireSecurityOwner(self):
2801 mock_input_api=MockInputApi()
2802 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2803'owner@chromium.org',
2804['banana@chromium.org'])
2805 mock_input_api.files=[
2806MockAffectedFile(
2807'some/non/service/thing/fuchsia_fidl_cml_cmx_magic.cc',[
2808'const char kNoEnforcement[] = "Security?!? Pah!";',
2809])
2810]
2811 mock_output_api=MockOutputApi()
2812 errors= PRESUBMIT.CheckSecurityOwners(mock_input_api, mock_output_api)
2813 self.assertEqual([], errors)
Ken Rockot9f668262018-12-21 18:56:36[diff] [blame]2814
Daniel Cheng13ca61a882017-08-25 15:11:25[diff] [blame]2815
Daniel Chenga37c03db2022-05-12 17:20:34[diff] [blame]2816classSecurityChangeTest(_SecurityOwnersTestCase):
Robert Sesek2c905332020-05-06 23:17:13[diff] [blame]2817
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2818def testDiffGetServiceSandboxType(self):
2819 mock_input_api=MockInputApi()
2820 mock_input_api.files=[
2821MockAffectedFile('services/goat/teleporter_host.cc',[
2822'template <>','inline content::SandboxType',
2823'content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {',
2824'#if defined(OS_WIN)',' return SandboxType::kGoaty;',
2825'#else',' return SandboxType::kNoSandbox;',
2826'#endif // !defined(OS_WIN)','}'
2827]),
2828]
2829 files_to_functions= PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2830 mock_input_api)
2831 self.assertEqual(
2832{
2833'services/goat/teleporter_host.cc':
2834 set(['content::GetServiceSandboxType<>()'])
2835}, files_to_functions)
2836
2837def testDiffRemovingLine(self):
2838 mock_input_api=MockInputApi()
2839 mock_file=MockAffectedFile('services/goat/teleporter_host.cc','')
2840 mock_file._scm_diff="""--- old 2020-05-04 14:08:25.000000000 -0400
Robert Sesek2c905332020-05-06 23:17:13[diff] [blame]2841+++ new 2020-05-04 14:08:32.000000000 -0400
2842@@ -1,5 +1,4 @@
Alex Goughbc964dd2020-06-15 17:52:37[diff] [blame]2843 template <>
2844 inline content::SandboxType
2845-content::GetServiceSandboxType<chrome::mojom::GoatTeleporter>() {
2846 #if defined(OS_WIN)
2847 return SandboxType::kGoaty;
Robert Sesek2c905332020-05-06 23:17:13[diff] [blame]2848"""
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2849 mock_input_api.files=[mock_file]
2850 files_to_functions= PRESUBMIT._GetFilesUsingSecurityCriticalFunctions(
2851 mock_input_api)
2852 self.assertEqual(
2853{
2854'services/goat/teleporter_host.cc':
2855 set(['content::GetServiceSandboxType<>()'])
2856}, files_to_functions)
Robert Sesek2c905332020-05-06 23:17:13[diff] [blame]2857
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2858def testChangeOwnersMissing(self):
2859 mock_input_api= self._createMockInputApi()
2860 self._setupFakeChange(mock_input_api)
2861 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2862'owner@chromium.org',
2863['banana@chromium.org'])
2864 mock_input_api.is_committing=False
2865 mock_input_api.files=[
2866MockAffectedFile('file.cc',
2867['GetServiceSandboxType<Goat>(Sandbox)'])
2868]
2869 mock_output_api=MockOutputApi()
2870 result= PRESUBMIT.CheckSecurityChanges(mock_input_api,
2871 mock_output_api)
2872 self.assertEqual(1, len(result))
2873 self.assertEqual(result[0].type,'notify')
2874 self.assertEqual(result[0].message,
2875'The following files change calls to security-sensitive functions\n' \
2876'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2877' file.cc\n'
2878' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:13[diff] [blame]2879
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2880def testChangeOwnersMissingAtCommit(self):
2881 mock_input_api= self._createMockInputApi()
2882 self._setupFakeChange(mock_input_api)
2883 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2884'owner@chromium.org',
2885['banana@chromium.org'])
2886 mock_input_api.is_committing=True
2887 mock_input_api.dry_run=False
2888 mock_input_api.files=[
2889MockAffectedFile('file.cc',
2890['GetServiceSandboxType<mojom::Goat>()'])
2891]
2892 mock_output_api=MockOutputApi()
2893 result= PRESUBMIT.CheckSecurityChanges(mock_input_api,
2894 mock_output_api)
2895 self.assertEqual(1, len(result))
2896 self.assertEqual(result[0].type,'error')
2897 self.assertEqual(result[0].message,
2898'The following files change calls to security-sensitive functions\n' \
2899'that need to be reviewed by ipc/SECURITY_OWNERS.\n'
2900' file.cc\n'
2901' content::GetServiceSandboxType<>()\n\n')
Robert Sesek2c905332020-05-06 23:17:13[diff] [blame]2902
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2903def testChangeOwnersPresent(self):
2904 mock_input_api= self._createMockInputApi()
2905 self._injectFakeChangeOwnerAndReviewers(
2906 mock_input_api,'owner@chromium.org',
2907['apple@chromium.org','banana@chromium.org'])
2908 mock_input_api.files=[
2909MockAffectedFile('file.cc',['WithSandboxType(Sandbox)'])
2910]
2911 mock_output_api=MockOutputApi()
2912 result= PRESUBMIT.CheckSecurityChanges(mock_input_api,
2913 mock_output_api)
2914 self.assertEqual(0, len(result))
Robert Sesek2c905332020-05-06 23:17:13[diff] [blame]2915
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2916def testChangeOwnerIsSecurityOwner(self):
2917 mock_input_api= self._createMockInputApi()
2918 self._setupFakeChange(mock_input_api)
2919 self._injectFakeChangeOwnerAndReviewers(mock_input_api,
2920'orange@chromium.org',
2921['pear@chromium.org'])
2922 mock_input_api.files=[
2923MockAffectedFile('file.cc',['GetServiceSandboxType<T>(Sandbox)'])
2924]
2925 mock_output_api=MockOutputApi()
2926 result= PRESUBMIT.CheckSecurityChanges(mock_input_api,
2927 mock_output_api)
2928 self.assertEqual(1, len(result))
Robert Sesek2c905332020-05-06 23:17:13[diff] [blame]2929
2930
Mario Sanchez Prada2472cab2019-09-18 10:58:31[diff] [blame]2931classBannedTypeCheckTest(unittest.TestCase):
Clement Yan9b330cb2022-11-17 05:25:29[diff] [blame]2932
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2933def testBannedJsFunctions(self):
2934 input_api=MockInputApi()
2935 input_api.files=[
2936MockFile('ash/webui/file.js',['chrome.send(something);']),
2937MockFile('some/js/ok/file.js',['chrome.send(something);']),
2938]
Clement Yan9b330cb2022-11-17 05:25:29[diff] [blame]2939
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2940 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]2941
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2942 self.assertEqual(1, len(results))
2943 self.assertTrue('ash/webui/file.js'in results[0].message)
2944 self.assertFalse('some/js/ok/file.js'in results[0].message)
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]2945
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2946def testBannedJavaFunctions(self):
2947 input_api=MockInputApi()
2948 input_api.files=[
2949MockFile('some/java/problematic/diskread.java',
2950['StrictMode.allowThreadDiskReads();']),
2951MockFile('some/java/problematic/diskwrite.java',
2952['StrictMode.allowThreadDiskWrites();']),
2953MockFile('some/java/ok/diskwrite.java',
2954['StrictModeContext.allowDiskWrites();']),
2955MockFile('some/java/problematic/waitidleforsync.java',
2956['instrumentation.waitForIdleSync();']),
2957MockFile('some/java/problematic/registerreceiver.java',
2958['context.registerReceiver();']),
2959MockFile('some/java/problematic/property.java',
2960['new Property<abc, Integer>;']),
2961MockFile('some/java/problematic/requestlayout.java',
2962['requestLayout();']),
2963MockFile('some/java/problematic/lastprofile.java',
2964['ProfileManager.getLastUsedRegularProfile();']),
2965MockFile('some/java/problematic/getdrawable1.java',
2966['ResourcesCompat.getDrawable();']),
2967MockFile('some/java/problematic/getdrawable2.java',
2968['getResources().getDrawable();']),
Jenna Himawan859865d2025-02-25 22:22:31[diff] [blame]2969MockFile('some/java/problematic/announceForAccessibility.java',
2970['view.announceForAccessibility(accessibilityText);']),
2971MockFile(
2972'some/java/problematic/accessibilityTypeAnnouncement.java',[
2973'accessibilityEvent.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);'
2974]),
Sirisha Kavuluru042e4772025-07-03 02:41:09[diff] [blame]2975MockFile(
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]2976'content/java/problematic/desktopandroid.java',[
Sirisha Kavuluru042e4772025-07-03 02:41:09[diff] [blame]2977'if (DeviceInfo.isDesktop()) {}'
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]2978]),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2979]
Min Qinbc44383c2023-02-22 17:25:26[diff] [blame]2980
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2981 errors= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2982 self.assertEqual(12, len(errors))
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2983 self.assertTrue(
2984'some/java/problematic/diskread.java'in errors[0].message)
2985 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2986'some/java/problematic/diskwrite.java'in errors[1].message)
2987 self.assertTrue(all('some/java/ok/diskwrite.java'notin e.messagefor ein errors))
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2988 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2989'some/java/problematic/waitidleforsync.java'in errors[2].message)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2990 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2991'some/java/problematic/registerreceiver.java'in errors[3].message)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2992 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2993'some/java/problematic/property.java'in errors[4].message)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2994 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2995'some/java/problematic/requestlayout.java'in errors[5].message)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2996 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2997'some/java/problematic/lastprofile.java'in errors[6].message)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]2998 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]2999'some/java/problematic/getdrawable1.java'in errors[7].message)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3000 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3001'some/java/problematic/getdrawable2.java'in errors[8].message)
Jenna Himawan859865d2025-02-25 22:22:31[diff] [blame]3002 self.assertTrue('some/java/problematic/announceForAccessibility.java'
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3003in errors[9].message)
Jenna Himawan859865d2025-02-25 22:22:31[diff] [blame]3004 self.assertTrue(
3005'some/java/problematic/accessibilityTypeAnnouncement.java'in
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3006 errors[10].message)
Nate Fischerd541ff82025-03-11 21:34:19[diff] [blame]3007 self.assertTrue(
3008'content/java/problematic/desktopandroid.java'in
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3009 errors[11].message)
Jenna Himawan859865d2025-02-25 22:22:31[diff] [blame]3010
Peter Kasting94a56c42019-10-25 21:54:04[diff] [blame]3011
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3012def testBannedCppFunctions(self):
3013 input_api=MockInputApi()
3014 input_api.files=[
3015MockFile('some/cpp/problematic/file.cc',['using namespace std;']),
3016MockFile('third_party/blink/problematic/file.cc',
3017['GetInterfaceProvider()']),
3018MockFile('some/cpp/ok/file.cc',['using std::string;']),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3019MockFile('some/cpp/nocheck/file.cc',
3020['using namespace std; // nocheck']),
3021MockFile('some/cpp/comment/file.cc',
3022[' // A comment about `using namespace std;`']),
Peter Kasting13607932025-04-10 22:52:38[diff] [blame]3023MockFile('some/cpp/problematic/file2.cc',[
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3024'params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET'
3025]),
Peter Kasting13607932025-04-10 22:52:38[diff] [blame]3026MockFile('some/cpp/problematic/file3.cc',[
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3027'params.ownership = Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET'
3028]),
Peter Kasting13607932025-04-10 22:52:38[diff] [blame]3029MockFile('some/cpp/problematic/file4.cc',[
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3030'Browser* browser = chrome::FindBrowserWithTab(web_contents)'
3031]),
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]3032MockFile(
3033'allowed_ranges_usage.cc',
3034[
3035'std::ranges::begin(vec);',
Michael Tang626d8982025-05-08 23:24:29[diff] [blame]3036'std::ranges::subrange(first, last);',
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]3037# std::ranges::view is a concept and allowed, but the views
3038# library itself is not (see below)
3039'static_assert(std::ranges::view<SomeType>);'
3040]),
3041MockFile(
3042'banned_ranges_usage.cc',
3043[
Michael Tang626d8982025-05-08 23:24:29[diff] [blame]3044'std::ranges::borrowed_subrange_t(subrange);',
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]3045# Edge case: make sure std::ranges::views is disallowed,
3046# even though std::ranges::view is allowed.
3047'std::ranges::views::take(first, count);'
3048]),
Daniel Cheng89719222024-07-04 04:59:29[diff] [blame]3049MockFile('views_usage.cc',['std::views::all(vec)']),
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]3050MockFile('content/desktop_android.cc',[
3051'// some first line',
3052'#if BUILDFLAG(IS_DESKTOP_ANDROID)',
3053'// some third line',
3054]),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3055]
Oksana Zhuravlovac8222d22019-12-19 19:21:16[diff] [blame]3056
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3057 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Peter Kasting94a56c42019-10-25 21:54:04[diff] [blame]3058
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3059# Each entry in results corresponds to a BanRule with a violation, in
3060# the order they were encountered.
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]3061 self.assertEqual(9, len(results))
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3062 self.assertTrue('some/cpp/problematic/file.cc'in results[0].message)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3063 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3064'third_party/blink/problematic/file.cc'in results[1].message)
3065 self.assertTrue(all('some/cpp/ok/file.cc'notin r.messagefor rin results))
3066 self.assertTrue('some/cpp/problematic/file2.cc'in results[2].message)
3067 self.assertTrue('some/cpp/problematic/file3.cc'in results[3].message)
3068 self.assertTrue('some/cpp/problematic/file4.cc'in results[4].message)
3069 self.assertTrue(all('some/cpp/nocheck/file.cc'notin r.messagefor rin results))
3070 self.assertTrue(all('some/cpp/comment/file.cc'notin r.messagefor rin results))
3071 self.assertTrue(all('allowed_ranges_usage.cc'notin r.messagefor rin results))
3072 self.assertTrue('banned_ranges_usage.cc'in results[5].message)
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]3073 self.assertTrue('banned_ranges_usage.cc'in results[6].message)
3074 self.assertTrue('views_usage.cc'in results[7].message)
3075 self.assertTrue('content/desktop_android.cc'in results[8].message)
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3076
3077# Check ResultLocation data. Line nums start at 1.
Daniel Cheng70a35272025-05-06 16:41:34[diff] [blame]3078 self.assertEqual(results[8].locations[0].file_path,
3079'content/desktop_android.cc')
3080 self.assertEqual(results[8].locations[0].start_line,2)
3081 self.assertEqual(results[8].locations[0].end_line,2)
Daniel Cheng192683f2022-11-01 20:52:44[diff] [blame]3082
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3083def testBannedCppRandomFunctions(self):
3084 banned_rngs=[
3085'absl::BitGen',
3086'absl::InsecureBitGen',
3087'std::linear_congruential_engine',
3088'std::mersenne_twister_engine',
3089'std::subtract_with_carry_engine',
3090'std::discard_block_engine',
3091'std::independent_bits_engine',
3092'std::shuffle_order_engine',
3093'std::minstd_rand0',
3094'std::minstd_rand',
3095'std::mt19937',
3096'std::mt19937_64',
3097'std::ranlux24_base',
3098'std::ranlux48_base',
3099'std::ranlux24',
3100'std::ranlux48',
3101'std::knuth_b',
3102'std::default_random_engine',
3103'std::random_device',
3104]
3105for banned_rngin banned_rngs:
3106 input_api=MockInputApi()
3107 input_api.files=[
3108MockFile('some/cpp/problematic/file.cc',
3109[f'{banned_rng} engine;']),
3110MockFile('third_party/blink/problematic/file.cc',
3111[f'{banned_rng} engine;']),
3112MockFile('third_party/ok/file.cc',[f'{banned_rng} engine;']),
3113]
3114 results= PRESUBMIT.CheckNoBannedFunctions(input_api,
3115MockOutputApi())
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3116 self.assertEqual(2, len(results), banned_rng)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3117 self.assertTrue(
3118'some/cpp/problematic/file.cc'in results[0].message,
3119 banned_rng)
3120 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3121'third_party/blink/problematic/file.cc'in results[1].message,
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3122 banned_rng)
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3123 self.assertTrue(all('third_party/ok/file.cc'notin r.messagefor rin results))
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]3124
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3125def testBannedIosObjcFunctions(self):
3126 input_api=MockInputApi()
3127 input_api.files=[
3128MockFile('some/ios/file.mm',
3129['TEST(SomeClassTest, SomeInteraction) {','}']),
3130MockFile('some/mac/file.mm',
3131['TEST(SomeClassTest, SomeInteraction) {','}']),
3132MockFile('another/ios_file.mm',
3133['class SomeTest : public testing::Test {};']),
3134MockFile(
3135'some/ios/file_egtest.mm',
3136['- (void)testSomething { EXPECT_OCMOCK_VERIFY(aMock); }']),
3137MockFile('some/ios/file_unittest.mm',[
3138'TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }'
3139]),
3140]
Sylvain Defresnea8b73d252018-02-28 15:45:54[diff] [blame]3141
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3142 errors= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3143 self.assertEqual(3, len(errors))
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3144 self.assertTrue('some/ios/file.mm'in errors[0].message)
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3145 self.assertTrue('another/ios_file.mm'in errors[1].message)
3146 self.assertTrue(all('some/mac/file.mm'notin e.messagefor ein errors))
3147 self.assertTrue('some/ios/file_egtest.mm'in errors[2].message)
3148 self.assertTrue(all('some/ios/file_unittest.mm'notin e.messagefor ein errors))
Carlos Knippschildab192b8c2019-04-08 20:02:38[diff] [blame]3149
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3150def testBannedMojoFunctions(self):
3151 input_api=MockInputApi()
3152 input_api.files=[
3153MockFile('some/cpp/problematic/file2.cc',['mojo::ConvertTo<>']),
3154MockFile('third_party/blink/ok/file3.cc',['mojo::ConvertTo<>']),
3155MockFile('content/renderer/ok/file3.cc',['mojo::ConvertTo<>']),
3156]
Oksana Zhuravlova1d3b59de2019-05-17 00:08:22[diff] [blame]3157
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3158 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Carlos Knippschildab192b8c2019-04-08 20:02:38[diff] [blame]3159
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3160# Each entry in results corresponds to a BanRule with a violation, in
3161# the order they were encountered.
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3162 self.assertEqual(1, len(results))
3163 self.assertTrue('some/cpp/problematic/file2.cc'in results[0].message)
3164 self.assertTrue(
3165'third_party/blink/ok/file3.cc'notin results[0].message)
3166 self.assertTrue(
3167'content/renderer/ok/file3.cc'notin results[0].message)
3168
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]3169def testBannedMojomPatterns_SharedBuffer(self):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3170 input_api=MockInputApi()
3171 input_api.files=[
3172MockFile(
3173'bad.mojom',
3174['struct Bad {',' handle<shared_buffer> buffer;','};']),
3175MockFile('good.mojom',[
3176'struct Good {',
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]3177' mojo_base.mojom.ReadOnlySharedMemoryRegion region1;',
3178' mojo_base.mojom.WritableSharedMemoryRegion region2;',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3179' mojo_base.mojom.UnsafeSharedMemoryRegion region3;','};'
3180]),
3181]
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]3182
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3183 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]3184
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3185# Each entry in results corresponds to a BanRule with a violation, in
3186# the order they were encountered.
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3187 self.assertEqual(1, len(results))
3188 self.assertTrue('bad.mojom'in results[0].message)
3189 self.assertTrue('good.mojom'notin results[0].message)
Daniel Cheng92c15e32022-03-16 17:48:22[diff] [blame]3190
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]3191def testBannedMojomPatterns_ExtensionId(self):
3192 input_api=MockInputApi()
3193 input_api.files=[
3194# Pattern tests.
3195MockFile('extensions/bad.mojom',['string extension_id']),
3196MockFile('extensions/bad_struct.mojom',
3197['struct Bad {',' string extension_id;','};']),
3198MockFile('extensions/good.mojom',['ExtensionId extension_id']),
3199MockFile('extensions/good_struct.mojom',
3200['struct Bad {',' ExtensionId extension_id;','};']),
3201
3202# Path exclusion tests.
3203MockFile('some/included/extensions/path/bad_extension_id.mojom',
3204['string extension_id']),
3205MockFile('some/excluded/path/bad_extension_id.mojom',
3206['string extension_id']),
3207]
3208
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3209# Each entry in results corresponds to a BanRule with a violation, in
3210# the order they were encountered.
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]3211 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
3212
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3213 self.assertEqual(3, len(results))
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]3214
3215# Pattern test assertions.
3216 self.assertTrue('bad.mojom'in results[0].message)
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3217 self.assertTrue('bad_struct.mojom'in results[1].message)
3218 self.assertTrue(all('good.mojom'notin r.messagefor rin results))
3219 self.assertTrue(all('good_struct.mojom'notin r.messagefor rin results))
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]3220
3221# Path exclusion assertions.
3222 self.assertTrue('some/included/extensions/path/bad_extension_id.mojom'
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]3223in results[2].message)
3224 self.assertTrue(all('some/excluded/path/bad_extension_id.mojom'notin r.messagefor rin results))
3225
Justin Lulejian09fd06872025-04-01 22:03:28[diff] [blame]3226
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:27[diff] [blame]3227classNoProductionCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozekf01ed502018-03-16 19:38:24[diff] [blame]3228
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3229def testTruePositives(self):
3230 mock_input_api=MockInputApi()
3231 mock_input_api.files=[
3232MockFile('some/path/foo.cc',['foo_for_testing();']),
3233MockFile('some/path/foo.mm',['FooForTesting();']),
3234MockFile('some/path/foo.cxx',['FooForTests();']),
3235MockFile('some/path/foo.cpp',['foo_for_test();']),
3236]
Vaclav Brozekf01ed502018-03-16 19:38:24[diff] [blame]3237
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3238 results= PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
3239 mock_input_api,MockOutputApi())
3240 self.assertEqual(1, len(results))
3241 self.assertEqual(4, len(results[0].items))
3242 self.assertTrue('foo.cc'in results[0].items[0])
3243 self.assertTrue('foo.mm'in results[0].items[1])
3244 self.assertTrue('foo.cxx'in results[0].items[2])
3245 self.assertTrue('foo.cpp'in results[0].items[3])
Vaclav Brozekf01ed502018-03-16 19:38:24[diff] [blame]3246
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3247def testFalsePositives(self):
3248 mock_input_api=MockInputApi()
3249 mock_input_api.files=[
3250MockFile('some/path/foo.h',['foo_for_testing();']),
3251MockFile('some/path/foo.mm',['FooForTesting() {']),
3252MockFile('some/path/foo.cc',['::FooForTests();']),
3253MockFile('some/path/foo.cpp',['// foo_for_test();']),
3254MockFile('some/path/foo.cxx',['foo_for_test(); // IN-TEST']),
3255]
Vaclav Brozekf01ed502018-03-16 19:38:24[diff] [blame]3256
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3257 results= PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
3258 mock_input_api,MockOutputApi())
3259 self.assertEqual(0, len(results))
James Cook1b4dc132021-03-09 22:45:13[diff] [blame]3260
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3261def testAllowedFiles(self):
3262 mock_input_api=MockInputApi()
3263 mock_input_api.files=[
3264MockFile('path/foo_unittest.cc',['foo_for_testing();']),
3265MockFile('path/bar_unittest_mac.cc',['foo_for_testing();']),
3266MockFile('path/baz_unittests.cc',['foo_for_testing();']),
3267]
3268
3269 results= PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions(
3270 mock_input_api,MockOutputApi())
3271 self.assertEqual(0, len(results))
James Cook1b4dc132021-03-09 22:45:13[diff] [blame]3272
Vaclav Brozekf01ed502018-03-16 19:38:24[diff] [blame]3273
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:27[diff] [blame]3274classNoProductionJavaCodeUsingTestOnlyFunctionsTest(unittest.TestCase):
Vaclav Brozek7dbc28c2018-03-27 08:35:23[diff] [blame]3275
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3276def testTruePositives(self):
3277 mock_input_api=MockInputApi()
3278 mock_input_api.files=[
3279MockFile('dir/java/src/foo.java',['FooForTesting();']),
3280MockFile('dir/java/src/bar.java',['FooForTests(x);']),
3281MockFile('dir/java/src/baz.java',['FooForTest(','y',');']),
3282MockFile('dir/java/src/mult.java',[
3283'int x = SomethingLongHere()',
3284' * SomethingLongHereForTesting();'
3285])
3286]
Vaclav Brozek7dbc28c2018-03-27 08:35:23[diff] [blame]3287
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3288 results= PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
3289 mock_input_api,MockOutputApi())
3290 self.assertEqual(1, len(results))
3291 self.assertEqual(4, len(results[0].items))
3292 self.assertTrue('foo.java'in results[0].items[0])
3293 self.assertTrue('bar.java'in results[0].items[1])
3294 self.assertTrue('baz.java'in results[0].items[2])
3295 self.assertTrue('mult.java'in results[0].items[3])
Vaclav Brozek7dbc28c2018-03-27 08:35:23[diff] [blame]3296
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3297def testFalsePositives(self):
3298 mock_input_api=MockInputApi()
3299 mock_input_api.files=[
3300MockFile('dir/java/src/foo.xml',['FooForTesting();']),
3301MockFile('dir/java/src/foo.java',['FooForTests() {']),
3302MockFile('dir/java/src/bar.java',['// FooForTest();']),
3303MockFile('dir/java/src/bar2.java',['x = 1; // FooForTest();']),
3304MockFile('dir/java/src/bar3.java',['@VisibleForTesting']),
3305MockFile('dir/java/src/bar4.java',['@VisibleForTesting()']),
3306MockFile('dir/java/src/bar5.java',[
3307'@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)'
3308]),
3309MockFile('dir/javatests/src/baz.java',['FooForTest(','y',');']),
3310MockFile('dir/junit/src/baz.java',['FooForTest(','y',');']),
3311MockFile('dir/junit/src/javadoc.java',
3312['/** Use FooForTest(); to obtain foo in tests.'
3313' */']),
3314MockFile(
3315'dir/junit/src/javadoc2.java',
3316['/** ',' * Use FooForTest(); to obtain foo in tests.'
3317' */']),
3318MockFile('dir/java/src/bar6.java',
3319['FooForTesting(); // IN-TEST']),
3320]
3321
3322 results= PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava(
3323 mock_input_api,MockOutputApi())
3324 self.assertEqual(0, len(results))
Vaclav Brozek7dbc28c2018-03-27 08:35:23[diff] [blame]3325
3326
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]3327classNewImagesWarningTest(unittest.TestCase):
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]3328
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3329def testTruePositives(self):
3330 mock_input_api=MockInputApi()
3331 mock_input_api.files=[
3332MockFile('dir/android/res/drawable/foo.png',[]),
3333MockFile('dir/android/res/drawable-v21/bar.svg',[]),
3334MockFile('dir/android/res/mipmap-v21-en/baz.webp',[]),
3335MockFile('dir/android/res_gshoe/drawable-mdpi/foobar.png',[]),
3336]
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]3337
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3338 results= PRESUBMIT._CheckNewImagesWarning(mock_input_api,
3339MockOutputApi())
3340 self.assertEqual(1, len(results))
3341 self.assertEqual(4, len(results[0].items))
3342 self.assertTrue('foo.png'in results[0].items[0].LocalPath())
3343 self.assertTrue('bar.svg'in results[0].items[1].LocalPath())
3344 self.assertTrue('baz.webp'in results[0].items[2].LocalPath())
3345 self.assertTrue('foobar.png'in results[0].items[3].LocalPath())
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]3346
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3347def testFalsePositives(self):
3348 mock_input_api=MockInputApi()
3349 mock_input_api.files=[
3350MockFile('dir/pngs/README.md',[]),
3351MockFile('java/test/res/drawable/foo.png',[]),
3352MockFile('third_party/blink/foo.png',[]),
3353MockFile('dir/third_party/libpng/src/foo.cc',['foobar']),
3354MockFile('dir/resources.webp/.gitignore',['foo.png']),
3355]
3356
3357 results= PRESUBMIT._CheckNewImagesWarning(mock_input_api,
3358MockOutputApi())
3359 self.assertEqual(0, len(results))
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]3360
Evan Stade7cd4a2c2022-08-04 23:37:25[diff] [blame]3361classProductIconsTest(unittest.TestCase):
Evan Stade7cd4a2c2022-08-04 23:37:25[diff] [blame]3362
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3363def test(self):
3364 mock_input_api=MockInputApi()
3365 mock_input_api.files=[
3366MockFile('components/vector_icons/google_jetpack.icon',[]),
3367MockFile('components/vector_icons/generic_jetpack.icon',[]),
3368]
3369
3370 results= PRESUBMIT.CheckNoProductIconsAddedToPublicRepo(
3371 mock_input_api,MockOutputApi())
3372 self.assertEqual(1, len(results))
3373 self.assertEqual(1, len(results[0].items))
3374 self.assertTrue('google_jetpack.icon'in results[0].items[0])
Mohamed Heikald048240a2019-11-12 16:57:37[diff] [blame]3375
Wei-Yin Chen (陳威尹)032f1ac2018-07-27 21:21:27[diff] [blame]3376classCheckUniquePtrTest(unittest.TestCase):
Vaclav Brozek851d9602018-04-04 16:13:05[diff] [blame]3377
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3378def testTruePositivesNullptr(self):
3379 mock_input_api=MockInputApi()
3380 mock_input_api.files=[
3381MockFile('dir/baz.cc',['std::unique_ptr<T>()']),
3382MockFile('dir/baz-p.cc',['std::unique_ptr<T<P>>()']),
3383]
Vaclav Brozek851d9602018-04-04 16:13:05[diff] [blame]3384
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3385 results= PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api,
3386MockOutputApi())
3387 self.assertEqual(1, len(results))
3388 self.assertTrue('nullptr'in results[0].message)
3389 self.assertEqual(2, len(results[0].items))
3390 self.assertTrue('baz.cc'in results[0].items[0])
3391 self.assertTrue('baz-p.cc'in results[0].items[1])
Vaclav Brozek52e18bf2018-04-03 07:05:24[diff] [blame]3392
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3393def testTruePositivesConstructor(self):
3394 mock_input_api=MockInputApi()
3395 mock_input_api.files=[
3396MockFile('dir/foo.cc',['return std::unique_ptr<T>(foo);']),
3397MockFile('dir/bar.mm',['bar = std::unique_ptr<T>(foo)']),
3398MockFile('dir/mult.cc',[
3399'return',
3400' std::unique_ptr<T>(barVeryVeryLongFooSoThatItWouldNotFitAbove);'
3401]),
3402MockFile('dir/mult2.cc',[
3403'barVeryVeryLongLongBaaaaaarSoThatTheLineLimitIsAlmostReached =',
3404' std::unique_ptr<T>(foo);'
3405]),
3406MockFile('dir/mult3.cc',[
3407'bar = std::unique_ptr<T>(',
3408' fooVeryVeryVeryLongStillGoingWellThisWillTakeAWhileFinallyThere);'
3409]),
3410MockFile('dir/multi_arg.cc',[
3411'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));'
3412]),
3413]
Vaclav Brozek52e18bf2018-04-03 07:05:24[diff] [blame]3414
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3415 results= PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api,
3416MockOutputApi())
3417 self.assertEqual(1, len(results))
3418 self.assertTrue('std::make_unique'in results[0].message)
3419 self.assertEqual(6, len(results[0].items))
3420 self.assertTrue('foo.cc'in results[0].items[0])
3421 self.assertTrue('bar.mm'in results[0].items[1])
3422 self.assertTrue('mult.cc'in results[0].items[2])
3423 self.assertTrue('mult2.cc'in results[0].items[3])
3424 self.assertTrue('mult3.cc'in results[0].items[4])
3425 self.assertTrue('multi_arg.cc'in results[0].items[5])
Vaclav Brozekb7fadb692018-08-30 06:39:53[diff] [blame]3426
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3427def testFalsePositives(self):
3428 mock_input_api=MockInputApi()
3429 mock_input_api.files=[
3430MockFile('dir/foo.cc',['return std::unique_ptr<T[]>(foo);']),
3431MockFile('dir/bar.mm',['bar = std::unique_ptr<T[]>(foo)']),
3432MockFile('dir/file.cc',['std::unique_ptr<T> p = Foo();']),
3433MockFile('dir/baz.cc',
3434['std::unique_ptr<T> result = std::make_unique<T>();']),
3435MockFile('dir/baz2.cc',
3436['std::unique_ptr<T> result = std::make_unique<T>(']),
3437MockFile('dir/nested.cc',['set<std::unique_ptr<T>>();']),
3438MockFile('dir/nested2.cc',['map<U, std::unique_ptr<T>>();']),
3439# Changed line is inside a multiline template block.
3440MockFile('dir/template.cc',[' std::unique_ptr<T>>(']),
3441MockFile('dir/template2.cc',[' std::unique_ptr<T>>()']),
Vaclav Brozek52e18bf2018-04-03 07:05:24[diff] [blame]3442
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3443# Two-argument invocation of std::unique_ptr is exempt because there is
3444# no equivalent using std::make_unique.
3445MockFile('dir/multi_arg.cc',
3446['auto p = std::unique_ptr<T, D>(new T(), D());']),
3447]
3448
3449 results= PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api,
3450MockOutputApi())
3451 self.assertEqual([], results)
Vaclav Brozek52e18bf2018-04-03 07:05:24[diff] [blame]3452
Danil Chapovalov3518f362018-08-11 16:13:43[diff] [blame]3453classCheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase):
Danil Chapovalov3518f362018-08-11 16:13:43[diff] [blame]3454
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3455def testBlocksDirectIncludes(self):
3456 mock_input_api=MockInputApi()
3457 mock_input_api.files=[
3458MockFile('dir/foo_win.cc',['#include "shlwapi.h"']),
3459MockFile('dir/bar.h',['#include <propvarutil.h>']),
3460MockFile('dir/baz.h',['#include <atlbase.h>']),
3461MockFile('dir/jumbo.h',['#include "sphelper.h"']),
3462]
3463 results= PRESUBMIT.CheckNoStrCatRedefines(mock_input_api,
3464MockOutputApi())
3465 self.assertEqual(1, len(results))
3466 self.assertEqual(4, len(results[0].items))
3467 self.assertTrue('StrCat'in results[0].message)
3468 self.assertTrue('foo_win.cc'in results[0].items[0])
3469 self.assertTrue('bar.h'in results[0].items[1])
3470 self.assertTrue('baz.h'in results[0].items[2])
3471 self.assertTrue('jumbo.h'in results[0].items[3])
Danil Chapovalov3518f362018-08-11 16:13:43[diff] [blame]3472
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3473def testAllowsToIncludeWrapper(self):
3474 mock_input_api=MockInputApi()
3475 mock_input_api.files=[
3476MockFile('dir/baz_win.cc',['#include "base/win/shlwapi.h"']),
3477MockFile('dir/baz-win.h',['#include "base/win/atl.h"']),
3478]
3479 results= PRESUBMIT.CheckNoStrCatRedefines(mock_input_api,
3480MockOutputApi())
3481 self.assertEqual(0, len(results))
Aleksey Khoroshilov9b28c032022-06-03 16:35:32[diff] [blame]3482
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3483def testAllowsToCreateWrapper(self):
3484 mock_input_api=MockInputApi()
3485 mock_input_api.files=[
3486MockFile('base/win/shlwapi.h',[
3487'#include <shlwapi.h>',
3488'#include "base/win/windows_defines.inc"'
3489]),
3490]
3491 results= PRESUBMIT.CheckNoStrCatRedefines(mock_input_api,
3492MockOutputApi())
3493 self.assertEqual(0, len(results))
3494
3495def testIgnoresNonImplAndHeaders(self):
3496 mock_input_api=MockInputApi()
3497 mock_input_api.files=[
3498MockFile('dir/foo_win.txt',['#include "shlwapi.h"']),
3499MockFile('dir/bar.asm',['#include <propvarutil.h>']),
3500]
3501 results= PRESUBMIT.CheckNoStrCatRedefines(mock_input_api,
3502MockOutputApi())
3503 self.assertEqual(0, len(results))
Vaclav Brozek52e18bf2018-04-03 07:05:24[diff] [blame]3504
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]3505
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]3506classStringTest(unittest.TestCase):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3507"""Tests ICU syntax check and translation screenshots check."""
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]3508
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3509# An empty grd file.
3510 OLD_GRD_CONTENTS="""<?xml version="1.0" encoding="UTF-8"?>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]3511 <grit latest_public_release="1" current_release="1">
3512 <release seq="1">
3513 <messages></messages>
3514 </release>
3515 </grit>
3516 """.splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3517# A grd file with a single message.
3518 NEW_GRD_CONTENTS1="""<?xml version="1.0" encoding="UTF-8"?>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]3519 <grit latest_public_release="1" current_release="1">
3520 <release seq="1">
3521 <messages>
3522 <message name="IDS_TEST1">
3523 Test string 1
3524 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:48[diff] [blame]3525 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE1"
3526 translateable="false">
3527 Non translateable message 1, should be ignored
3528 </message>
Mustafa Emre Acered1a48962020-06-30 19:15:39[diff] [blame]3529 <message name="IDS_TEST_STRING_ACCESSIBILITY"
Mustafa Emre Acerd3ca8be2020-07-07 22:35:34[diff] [blame]3530 is_accessibility_with_no_ui="true">
Mustafa Emre Acered1a48962020-06-30 19:15:39[diff] [blame]3531 Accessibility label 1, should be ignored
3532 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]3533 </messages>
3534 </release>
3535 </grit>
3536 """.splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3537# A grd file with two messages.
3538 NEW_GRD_CONTENTS2="""<?xml version="1.0" encoding="UTF-8"?>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]3539 <grit latest_public_release="1" current_release="1">
3540 <release seq="1">
3541 <messages>
3542 <message name="IDS_TEST1">
3543 Test string 1
3544 </message>
3545 <message name="IDS_TEST2">
3546 Test string 2
3547 </message>
Mustafa Emre Acere4b349c2020-06-03 23:42:48[diff] [blame]3548 <message name="IDS_TEST_STRING_NON_TRANSLATEABLE2"
3549 translateable="false">
3550 Non translateable message 2, should be ignored
3551 </message>
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]3552 </messages>
3553 </release>
3554 </grit>
3555 """.splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3556# A grd file with one ICU syntax message without syntax errors.
3557 NEW_GRD_CONTENTS_ICU_SYNTAX_OK1="""<?xml version="1.0" encoding="UTF-8"?>
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]3558 <grit latest_public_release="1" current_release="1">
3559 <release seq="1">
3560 <messages>
3561 <message name="IDS_TEST1">
3562 {NUM, plural,
3563 =1 {Test text for numeric one}
3564 other {Test text for plural with {NUM} as number}}
3565 </message>
3566 </messages>
3567 </release>
3568 </grit>
3569 """.splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3570# A grd file with one ICU syntax message without syntax errors.
3571 NEW_GRD_CONTENTS_ICU_SYNTAX_OK2="""<?xml version="1.0" encoding="UTF-8"?>
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]3572 <grit latest_public_release="1" current_release="1">
3573 <release seq="1">
3574 <messages>
3575 <message name="IDS_TEST1">
3576 {NUM, plural,
3577 =1 {Different test text for numeric one}
3578 other {Different test text for plural with {NUM} as number}}
3579 </message>
3580 </messages>
3581 </release>
3582 </grit>
3583 """.splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3584# A grd file with multiple ICU syntax messages without syntax errors.
3585 NEW_GRD_CONTENTS_ICU_SYNTAX_OK3="""<?xml version="1.0" encoding="UTF-8"?>
Rainhard Findling3cde3ef02024-02-05 18:40:32[diff] [blame]3586 <grit latest_public_release="1" current_release="1">
3587 <release seq="1">
3588 <messages>
3589 <message name="IDS_TEST1">
3590 {NUM, plural,
3591 =0 {New test text for numeric zero}
3592 =1 {Different test text for numeric one}
3593 =2 {New test text for numeric two}
3594 =3 {New test text for numeric three}
3595 other {Different test text for plural with {NUM} as number}}
3596 </message>
3597 </messages>
3598 </release>
3599 </grit>
3600 """.splitlines()
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3601# A grd file with one ICU syntax message with syntax errors (misses a comma).
3602 NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR="""<?xml version="1.0" encoding="UTF-8"?>
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]3603 <grit latest_public_release="1" current_release="1">
3604 <release seq="1">
3605 <messages>
3606 <message name="IDS_TEST1">
3607 {NUM, plural
3608 =1 {Test text for numeric one}
3609 other {Test text for plural with {NUM} as number}}
3610 </message>
3611 </messages>
3612 </release>
3613 </grit>
3614 """.splitlines()
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]3615
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3616 OLD_GRDP_CONTENTS=('<?xml version="1.0" encoding="utf-8"?>',
3617'<grit-part>','</grit-part>')
meacerff8a9b62019-12-10 19:43:58[diff] [blame]3618
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3619 NEW_GRDP_CONTENTS1=('<?xml version="1.0" encoding="utf-8"?>',
3620'<grit-part>','<message name="IDS_PART_TEST1">',
3621'Part string 1','</message>','</grit-part>')
meacerff8a9b62019-12-10 19:43:58[diff] [blame]3622
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3623 NEW_GRDP_CONTENTS2=('<?xml version="1.0" encoding="utf-8"?>',
3624'<grit-part>','<message name="IDS_PART_TEST1">',
3625'Part string 1','</message>',
3626'<message name="IDS_PART_TEST2">','Part string 2',
3627'</message>','</grit-part>')
meacerff8a9b62019-12-10 19:43:58[diff] [blame]3628
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3629 NEW_GRDP_CONTENTS3=(
3630'<?xml version="1.0" encoding="utf-8"?>','<grit-part>',
Rainhard Findlingd8d04372020-08-13 13:30:09[diff] [blame]3631'<message name="IDS_PART_TEST1" desc="Description with typo.">',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3632'Part string 1','</message>','</grit-part>')
Rainhard Findlingd8d04372020-08-13 13:30:09[diff] [blame]3633
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3634 NEW_GRDP_CONTENTS4=(
3635'<?xml version="1.0" encoding="utf-8"?>','<grit-part>',
Rainhard Findlingd8d04372020-08-13 13:30:09[diff] [blame]3636'<message name="IDS_PART_TEST1" desc="Description with typo fixed.">',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3637'Part string 1','</message>','</grit-part>')
Rainhard Findlingd8d04372020-08-13 13:30:09[diff] [blame]3638
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3639 NEW_GRDP_CONTENTS5=(
3640'<?xml version="1.0" encoding="utf-8"?>','<grit-part>',
Rainhard Findling1a3e71e2020-09-21 07:33:35[diff] [blame]3641'<message name="IDS_PART_TEST1" meaning="Meaning with typo.">',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3642'Part string 1','</message>','</grit-part>')
Rainhard Findling1a3e71e2020-09-21 07:33:35[diff] [blame]3643
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3644 NEW_GRDP_CONTENTS6=(
3645'<?xml version="1.0" encoding="utf-8"?>','<grit-part>',
Rainhard Findling1a3e71e2020-09-21 07:33:35[diff] [blame]3646'<message name="IDS_PART_TEST1" meaning="Meaning with typo fixed.">',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3647'Part string 1','</message>','</grit-part>')
Rainhard Findling1a3e71e2020-09-21 07:33:35[diff] [blame]3648
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3649# A grdp file with one ICU syntax message without syntax errors.
3650 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1=(
3651'<?xml version="1.0" encoding="utf-8"?>','<grit-part>',
3652'<message name="IDS_PART_TEST1">','{NUM, plural,',
3653'=1 {Test text for numeric one}',
3654'other {Test text for plural with {NUM} as number}}','</message>',
3655'</grit-part>')
3656# A grdp file with one ICU syntax message without syntax errors.
3657 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2=(
3658'<?xml version="1.0" encoding="utf-8"?>','<grit-part>',
3659'<message name="IDS_PART_TEST1">','{NUM, plural,',
3660'=1 {Different test text for numeric one}',
3661'other {Different test text for plural with {NUM} as number}}',
3662'</message>','</grit-part>')
3663# A grdp file with multiple ICU syntax messages without syntax errors.
3664 NEW_GRDP_CONTENTS_ICU_SYNTAX_OK3=(
3665'<?xml version="1.0" encoding="utf-8"?>','<grit-part>',
3666'<message name="IDS_PART_TEST1">','{NUM, plural,',
3667'=0 {New test text for numeric zero}',
3668'=1 {Different test text for numeric one}',
3669'=2 {New test text for numeric two}',
3670'=3 {New test text for numeric three}',
3671'other {Different test text for plural with {NUM} as number}}',
3672'</message>','</grit-part>')
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]3673
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3674# A grdp file with one ICU syntax message with syntax errors (superfluous
3675# space).
3676 NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR=(
3677'<?xml version="1.0" encoding="utf-8"?>','<grit-part>',
3678'<message name="IDS_PART_TEST1">','{NUM, plural,',
3679'= 1 {Test text for numeric one}',
3680'other {Test text for plural with {NUM} as number}}','</message>',
3681'</grit-part>')
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]3682
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3683 VALID_SHA1=('0000000000000000000000000000000000000000',)
3684 DO_NOT_UPLOAD_PNG_MESSAGE=('Do not include actual screenshots in the '
3685'changelist. Run '
3686'tools/translate/upload_screenshots.py to '
3687'upload them instead:')
3688 ADD_SIGNATURES_MESSAGE=('You are adding UI strings.\n'
3689'To ensure the best translations, take '
3690'screenshots of the relevant UI '
3691'(https://g.co/chrome/translation) and add '
3692'these files to your changelist:')
3693 REMOVE_SIGNATURES_MESSAGE=('You removed strings associated with these '
3694'files. Remove:')
3695 ICU_SYNTAX_ERROR_MESSAGE=(
3696'ICU syntax errors were found in the following '
3697'strings (problems or feedback? Contact '
3698'rainhard@chromium.org):')
3699 SHA1_FORMAT_MESSAGE=(
3700'The following files do not seem to contain valid sha1 '
3701'hashes. Make sure they contain hashes created by '
3702'tools/translate/upload_screenshots.py:')
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]3703
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3704def makeInputApi(self, files):
3705 input_api=MockInputApi()
Andrew Grieve713b89b2024-10-15 20:20:08[diff] [blame]3706 input_api.InitFiles(files)
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3707return input_api
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]3708
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3709""" CL modified and added messages, but didn't add any screenshots."""
meacerff8a9b62019-12-10 19:43:58[diff] [blame]3710
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3711def testNoScreenshots(self):
3712# No new strings (file contents same). Should not warn.
3713 input_api= self.makeInputApi([
3714MockAffectedFile('test.grd',
3715 self.NEW_GRD_CONTENTS1,
3716 self.NEW_GRD_CONTENTS1,
3717 action='M'),
3718MockAffectedFile('part.grdp',
3719 self.NEW_GRDP_CONTENTS1,
3720 self.NEW_GRDP_CONTENTS1,
3721 action='M')
3722])
3723 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3724 self.assertEqual(0, len(warnings))
Mustafa Emre Acer36eaad52019-11-12 23:03:34[diff] [blame]3725
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3726# Add two new strings. Should have two warnings.
3727 input_api= self.makeInputApi([
3728MockAffectedFile('test.grd',
3729 self.NEW_GRD_CONTENTS2,
3730 self.NEW_GRD_CONTENTS1,
3731 action='M'),
3732MockAffectedFile('part.grdp',
3733 self.NEW_GRDP_CONTENTS2,
3734 self.NEW_GRDP_CONTENTS1,
3735 action='M')
3736])
3737 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3738 self.assertEqual(1, len(warnings))
3739 self.assertEqual(self.ADD_SIGNATURES_MESSAGE, warnings[0].message)
3740 self.assertEqual('error', warnings[0].type)
3741 self.assertEqual([
3742 os.path.join('part_grdp','IDS_PART_TEST2.png.sha1'),
3743 os.path.join('test_grd','IDS_TEST2.png.sha1')
3744], warnings[0].items)
Mustafa Emre Acerad8fb082019-11-19 04:24:21[diff] [blame]3745
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3746# Add four new strings. Should have four warnings.
3747 input_api= self.makeInputApi([
3748MockAffectedFile('test.grd',
3749 self.NEW_GRD_CONTENTS2,
3750 self.OLD_GRD_CONTENTS,
3751 action='M'),
3752MockAffectedFile('part.grdp',
3753 self.NEW_GRDP_CONTENTS2,
3754 self.OLD_GRDP_CONTENTS,
3755 action='M')
3756])
3757 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3758 self.assertEqual(1, len(warnings))
3759 self.assertEqual('error', warnings[0].type)
3760 self.assertEqual(self.ADD_SIGNATURES_MESSAGE, warnings[0].message)
3761 self.assertEqual([
meacerff8a9b62019-12-10 19:43:58[diff] [blame]3762 os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
meacerff8a9b62019-12-10 19:43:58[diff] [blame]3763 os.path.join('part_grdp','IDS_PART_TEST2.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]3764 os.path.join('test_grd','IDS_TEST1.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]3765 os.path.join('test_grd','IDS_TEST2.png.sha1'),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3766], warnings[0].items)
3767
3768def testModifiedMessageDescription(self):
3769# CL modified a message description for a message that does not yet have a
3770# screenshot. Should not warn.
3771 input_api= self.makeInputApi([
3772MockAffectedFile('part.grdp',
3773 self.NEW_GRDP_CONTENTS3,
3774 self.NEW_GRDP_CONTENTS4,
3775 action='M')
3776])
3777 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3778 self.assertEqual(0, len(warnings))
3779
3780# CL modified a message description for a message that already has a
3781# screenshot. Should not warn.
3782 input_api= self.makeInputApi([
3783MockAffectedFile('part.grdp',
3784 self.NEW_GRDP_CONTENTS3,
3785 self.NEW_GRDP_CONTENTS4,
3786 action='M'),
3787MockFile(os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
3788 self.VALID_SHA1,
3789 action='A')
3790])
3791 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3792 self.assertEqual(0, len(warnings))
3793
3794def testModifiedMessageMeaning(self):
3795# CL modified a message meaning for a message that does not yet have a
3796# screenshot. Should warn.
3797 input_api= self.makeInputApi([
3798MockAffectedFile('part.grdp',
3799 self.NEW_GRDP_CONTENTS5,
3800 self.NEW_GRDP_CONTENTS6,
3801 action='M')
3802])
3803 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3804 self.assertEqual(1, len(warnings))
3805
3806# CL modified a message meaning for a message that already has a
3807# screenshot. Should not warn.
3808 input_api= self.makeInputApi([
3809MockAffectedFile('part.grdp',
3810 self.NEW_GRDP_CONTENTS5,
3811 self.NEW_GRDP_CONTENTS6,
3812 action='M'),
3813MockFile(os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
3814 self.VALID_SHA1,
3815 action='A')
3816])
3817 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3818 self.assertEqual(0, len(warnings))
3819
3820def testModifiedIntroducedInvalidSha1(self):
3821# CL modified a message and the sha1 file changed to invalid
3822 input_api= self.makeInputApi([
3823MockAffectedFile('part.grdp',
3824 self.NEW_GRDP_CONTENTS5,
3825 self.NEW_GRDP_CONTENTS6,
3826 action='M'),
3827MockAffectedFile(os.path.join('part_grdp',
3828'IDS_PART_TEST1.png.sha1'),
3829('some invalid sha1',),
3830 self.VALID_SHA1,
3831 action='M')
3832])
3833 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3834 self.assertEqual(1, len(warnings))
3835
3836def testPngAddedSha1NotAdded(self):
3837# CL added one new message in a grd file and added the png file associated
3838# with it, but did not add the corresponding sha1 file. This should warn
3839# twice:
3840# - Once for the added png file (because we don't want developers to upload
3841# actual images)
3842# - Once for the missing .sha1 file
3843 input_api= self.makeInputApi([
3844MockAffectedFile('test.grd',
3845 self.NEW_GRD_CONTENTS1,
3846 self.OLD_GRD_CONTENTS,
3847 action='M'),
3848MockAffectedFile(os.path.join('test_grd','IDS_TEST1.png'),
3849'binary',
3850 action='A')
3851])
3852 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3853 self.assertEqual(2, len(warnings))
3854 self.assertEqual('error', warnings[0].type)
3855 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
3856 self.assertEqual([os.path.join('test_grd','IDS_TEST1.png')],
3857 warnings[0].items)
3858 self.assertEqual('error', warnings[1].type)
3859 self.assertEqual(self.ADD_SIGNATURES_MESSAGE, warnings[1].message)
3860 self.assertEqual([os.path.join('test_grd','IDS_TEST1.png.sha1')],
3861 warnings[1].items)
3862
3863# CL added two messages (one in grd, one in grdp) and added the png files
3864# associated with the messages, but did not add the corresponding sha1
3865# files. This should warn twice:
3866# - Once for the added png files (because we don't want developers to upload
3867# actual images)
3868# - Once for the missing .sha1 files
3869 input_api= self.makeInputApi([
3870# Modified files:
3871MockAffectedFile('test.grd',
3872 self.NEW_GRD_CONTENTS1,
3873 self.OLD_GRD_CONTENTS,
3874 action='M'),
3875MockAffectedFile('part.grdp',
3876 self.NEW_GRDP_CONTENTS1,
3877 self.OLD_GRDP_CONTENTS,
3878 action='M'),
3879# Added files:
3880MockAffectedFile(os.path.join('test_grd','IDS_TEST1.png'),
3881'binary',
3882 action='A'),
3883MockAffectedFile(os.path.join('part_grdp','IDS_PART_TEST1.png'),
3884'binary',
3885 action='A')
3886])
3887 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3888 self.assertEqual(2, len(warnings))
3889 self.assertEqual('error', warnings[0].type)
3890 self.assertEqual(self.DO_NOT_UPLOAD_PNG_MESSAGE, warnings[0].message)
3891 self.assertEqual([
3892 os.path.join('part_grdp','IDS_PART_TEST1.png'),
3893 os.path.join('test_grd','IDS_TEST1.png')
3894], warnings[0].items)
3895 self.assertEqual('error', warnings[0].type)
3896 self.assertEqual(self.ADD_SIGNATURES_MESSAGE, warnings[1].message)
3897 self.assertEqual([
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]3898 os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3899 os.path.join('test_grd','IDS_TEST1.png.sha1')
3900], warnings[1].items)
3901
3902def testScreenshotsWithSha1(self):
3903# CL added four messages (two each in a grd and grdp) and their
3904# corresponding .sha1 files. No warnings.
3905 input_api= self.makeInputApi([
3906# Modified files:
3907MockAffectedFile('test.grd',
3908 self.NEW_GRD_CONTENTS2,
3909 self.OLD_GRD_CONTENTS,
3910 action='M'),
3911MockAffectedFile('part.grdp',
3912 self.NEW_GRDP_CONTENTS2,
3913 self.OLD_GRDP_CONTENTS,
3914 action='M'),
3915# Added files:
3916MockFile(os.path.join('test_grd','IDS_TEST1.png.sha1'),
3917 self.VALID_SHA1,
3918 action='A'),
3919MockFile(os.path.join('test_grd','IDS_TEST2.png.sha1'),
3920('0000000000000000000000000000000000000000',''),
3921 action='A'),
3922MockFile(os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
3923 self.VALID_SHA1,
3924 action='A'),
3925MockFile(os.path.join('part_grdp','IDS_PART_TEST2.png.sha1'),
3926 self.VALID_SHA1,
3927 action='A'),
3928])
3929 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3930 self.assertEqual([], warnings)
3931
3932def testScreenshotsWithInvalidSha1(self):
3933 input_api= self.makeInputApi([
3934# Modified files:
3935MockAffectedFile('test.grd',
3936 self.NEW_GRD_CONTENTS2,
3937 self.OLD_GRD_CONTENTS,
3938 action='M'),
3939MockAffectedFile('part.grdp',
3940 self.NEW_GRDP_CONTENTS2,
3941 self.OLD_GRDP_CONTENTS,
3942 action='M'),
3943# Added files:
3944MockFile(os.path.join('test_grd','IDS_TEST1.png.sha1'),
3945 self.VALID_SHA1,
3946 action='A'),
3947MockFile(os.path.join('test_grd','IDS_TEST2.png.sha1'),
3948('‰PNG','test'),
3949 action='A'),
3950MockFile(os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
3951 self.VALID_SHA1,
3952 action='A'),
3953MockFile(os.path.join('part_grdp','IDS_PART_TEST2.png.sha1'),
3954 self.VALID_SHA1,
3955 action='A'),
3956])
3957 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3958 self.assertEqual(1, len(warnings))
3959 self.assertEqual('error', warnings[0].type)
3960 self.assertEqual(self.SHA1_FORMAT_MESSAGE, warnings[0].message)
3961 self.assertEqual([os.path.join('test_grd','IDS_TEST2.png.sha1')],
3962 warnings[0].items)
3963
3964def testScreenshotsRemovedWithSha1(self):
3965# Replace new contents with old contents in grd and grp files, removing
3966# IDS_TEST1, IDS_TEST2, IDS_PART_TEST1 and IDS_PART_TEST2.
3967# Should warn to remove the sha1 files associated with these strings.
3968 input_api= self.makeInputApi([
3969# Modified files:
3970MockAffectedFile(
3971'test.grd',
3972 self.OLD_GRD_CONTENTS,# new_contents
3973 self.NEW_GRD_CONTENTS2,# old_contents
3974 action='M'),
3975MockAffectedFile(
3976'part.grdp',
3977 self.OLD_GRDP_CONTENTS,# new_contents
3978 self.NEW_GRDP_CONTENTS2,# old_contents
3979 action='M'),
3980# Unmodified files:
3981MockFile(os.path.join('test_grd','IDS_TEST1.png.sha1'),
3982 self.VALID_SHA1,''),
3983MockFile(os.path.join('test_grd','IDS_TEST2.png.sha1'),
3984 self.VALID_SHA1,''),
3985MockFile(os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
3986 self.VALID_SHA1,''),
3987MockFile(os.path.join('part_grdp','IDS_PART_TEST2.png.sha1'),
3988 self.VALID_SHA1,'')
3989])
3990 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
3991 self.assertEqual(1, len(warnings))
3992 self.assertEqual('error', warnings[0].type)
3993 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
3994 self.assertEqual([
3995 os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
Jens Mueller054652c2023-05-10 15:12:30[diff] [blame]3996 os.path.join('part_grdp','IDS_PART_TEST2.png.sha1'),
Mustafa Emre Acerea3e57a2018-12-17 23:51:01[diff] [blame]3997 os.path.join('test_grd','IDS_TEST1.png.sha1'),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]3998 os.path.join('test_grd','IDS_TEST2.png.sha1')
3999], warnings[0].items)
4000
4001# Same as above, but this time one of the .sha1 files is also removed.
4002 input_api= self.makeInputApi([
4003# Modified files:
4004MockAffectedFile(
4005'test.grd',
4006 self.OLD_GRD_CONTENTS,# new_contents
4007 self.NEW_GRD_CONTENTS2,# old_contents
4008 action='M'),
4009MockAffectedFile(
4010'part.grdp',
4011 self.OLD_GRDP_CONTENTS,# new_contents
4012 self.NEW_GRDP_CONTENTS2,# old_contents
4013 action='M'),
4014# Unmodified files:
4015MockFile(os.path.join('test_grd','IDS_TEST1.png.sha1'),
4016 self.VALID_SHA1,''),
4017MockFile(os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
4018 self.VALID_SHA1,''),
4019# Deleted files:
4020MockAffectedFile(os.path.join('test_grd','IDS_TEST2.png.sha1'),
4021'',
4022'old_contents',
4023 action='D'),
4024MockAffectedFile(os.path.join('part_grdp',
4025'IDS_PART_TEST2.png.sha1'),
4026'',
4027'old_contents',
4028 action='D')
4029])
4030 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
4031 self.assertEqual(1, len(warnings))
4032 self.assertEqual('error', warnings[0].type)
4033 self.assertEqual(self.REMOVE_SIGNATURES_MESSAGE, warnings[0].message)
4034 self.assertEqual([
meacerff8a9b62019-12-10 19:43:58[diff] [blame]4035 os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4036 os.path.join('test_grd','IDS_TEST1.png.sha1')
4037], warnings[0].items)
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]4038
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4039# Remove all sha1 files. There should be no warnings.
4040 input_api= self.makeInputApi([
4041# Modified files:
4042MockAffectedFile('test.grd',
4043 self.OLD_GRD_CONTENTS,
4044 self.NEW_GRD_CONTENTS2,
4045 action='M'),
4046MockAffectedFile('part.grdp',
4047 self.OLD_GRDP_CONTENTS,
4048 self.NEW_GRDP_CONTENTS2,
4049 action='M'),
4050# Deleted files:
4051MockFile(os.path.join('test_grd','IDS_TEST1.png.sha1'),
4052 self.VALID_SHA1,
4053 action='D'),
4054MockFile(os.path.join('test_grd','IDS_TEST2.png.sha1'),
4055 self.VALID_SHA1,
4056 action='D'),
4057MockFile(os.path.join('part_grdp','IDS_PART_TEST1.png.sha1'),
4058 self.VALID_SHA1,
4059 action='D'),
4060MockFile(os.path.join('part_grdp','IDS_PART_TEST2.png.sha1'),
4061 self.VALID_SHA1,
4062 action='D')
4063])
4064 warnings= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
4065 self.assertEqual([], warnings)
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]4066
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4067def testIcuSyntax(self):
4068# Add valid ICU syntax string. Should not raise an error.
4069 input_api= self.makeInputApi([
4070MockAffectedFile('test.grd',
4071 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
4072 self.NEW_GRD_CONTENTS1,
4073 action='M'),
4074MockAffectedFile('part.grdp',
4075 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
4076 self.NEW_GRDP_CONTENTS1,
4077 action='M')
4078])
4079 results= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
4080# We expect no ICU syntax errors.
4081 icu_errors=[
4082 efor ein resultsif e.message== self.ICU_SYNTAX_ERROR_MESSAGE
4083]
4084 self.assertEqual(0, len(icu_errors))
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]4085
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4086# Valid changes in ICU syntax. Should not raise an error.
4087 input_api= self.makeInputApi([
4088MockAffectedFile('test.grd',
4089 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK2,
4090 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1,
4091 action='M'),
4092MockAffectedFile('part.grdp',
4093 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2,
4094 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1,
4095 action='M')
4096])
4097 results= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
4098# We expect no ICU syntax errors.
4099 icu_errors=[
4100 efor ein resultsif e.message== self.ICU_SYNTAX_ERROR_MESSAGE
4101]
4102 self.assertEqual(0, len(icu_errors))
Rainhard Findling3cde3ef02024-02-05 18:40:32[diff] [blame]4103
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4104# Valid changes in ICU syntax. Should not raise an error.
4105 input_api= self.makeInputApi([
4106MockAffectedFile('test.grd',
4107 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK3,
4108 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1,
4109 action='M'),
4110MockAffectedFile('part.grdp',
4111 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK3,
4112 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1,
4113 action='M')
4114])
4115 results= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
4116# We expect no ICU syntax errors.
4117 icu_errors=[
4118 efor ein resultsif e.message== self.ICU_SYNTAX_ERROR_MESSAGE
4119]
4120 self.assertEqual(0, len(icu_errors))
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]4121
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4122# Add invalid ICU syntax strings. Should raise two errors.
4123 input_api= self.makeInputApi([
4124MockAffectedFile('test.grd',
4125 self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
4126 self.NEW_GRD_CONTENTS1,
4127 action='M'),
4128MockAffectedFile('part.grdp',
4129 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
4130 self.NEW_GRD_CONTENTS1,
4131 action='M')
4132])
4133 results= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
4134# We expect 2 ICU syntax errors.
4135 icu_errors=[
4136 efor ein resultsif e.message== self.ICU_SYNTAX_ERROR_MESSAGE
4137]
4138 self.assertEqual(1, len(icu_errors))
4139 self.assertEqual([
4140'IDS_TEST1: This message looks like an ICU plural, but does not follow '
4141'ICU syntax.',
4142'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
4143], icu_errors[0].items)
4144
4145# Change two strings to have ICU syntax errors. Should raise two errors.
4146 input_api= self.makeInputApi([
4147MockAffectedFile('test.grd',
4148 self.NEW_GRD_CONTENTS_ICU_SYNTAX_ERROR,
4149 self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1,
4150 action='M'),
4151MockAffectedFile('part.grdp',
4152 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR,
4153 self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1,
4154 action='M')
4155])
4156 results= PRESUBMIT.CheckStrings(input_api,MockOutputApi())
4157# We expect 2 ICU syntax errors.
4158 icu_errors=[
4159 efor ein resultsif e.message== self.ICU_SYNTAX_ERROR_MESSAGE
4160]
4161 self.assertEqual(1, len(icu_errors))
4162 self.assertEqual([
4163'IDS_TEST1: This message looks like an ICU plural, but does not follow '
4164'ICU syntax.',
4165'IDS_PART_TEST1: Variant "= 1" is not valid for plural message'
4166], icu_errors[0].items)
Rainhard Findlingfc31844c52020-05-15 09:58:26[diff] [blame]4167
Mustafa Emre Acer29bf6ac92018-07-30 21:42:14[diff] [blame]4168
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]4169classTranslationExpectationsTest(unittest.TestCase):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4170 ERROR_MESSAGE_FORMAT=(
4171"Failed to get a list of translatable grd files. "
4172"This happens when:\n"
4173" - One of the modified grd or grdp files cannot be parsed or\n"
4174" - %s is not updated.\n"
4175"Stack:\n")
4176 REPO_ROOT= os.path.join('tools','translation','testdata')
4177# This lists all .grd files under REPO_ROOT.
4178 EXPECTATIONS= os.path.join(REPO_ROOT,"translation_expectations.pyl")
4179# This lists all .grd files under REPO_ROOT except unlisted.grd.
4180 EXPECTATIONS_WITHOUT_UNLISTED_FILE= os.path.join(
4181 REPO_ROOT,"translation_expectations_without_unlisted_file.pyl")
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]4182
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4183# Tests that the presubmit doesn't return when no grd or grdp files are
4184# modified.
4185def testExpectationsNoModifiedGrd(self):
4186 input_api=MockInputApi()
4187 input_api.files=[
4188MockAffectedFile('not_used.txt',
4189'not used',
4190'not used',
4191 action='M')
4192]
4193# Fake list of all grd files in the repo. This list is missing all grd/grdps
4194# under tools/translation/testdata. This is OK because the presubmit won't
4195# run in the first place since there are no modified grd/grps in input_api.
4196 grd_files=['doesnt_exist_doesnt_matter.grd']
4197 warnings= PRESUBMIT.CheckTranslationExpectations(
4198 input_api,MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
4199 grd_files)
4200 self.assertEqual(0, len(warnings))
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]4201
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4202# Tests that the list of files passed to the presubmit matches the list of
4203# files in the expectations.
4204def testExpectationsSuccess(self):
4205# Mock input file list needs a grd or grdp file in order to run the
4206# presubmit. The file itself doesn't matter.
4207 input_api=MockInputApi()
4208 input_api.files=[
4209MockAffectedFile('dummy.grd','not used','not used', action='M')
4210]
4211# List of all grd files in the repo.
4212 grd_files=[
4213'test.grd','unlisted.grd','not_translated.grd','internal.grd'
4214]
4215 warnings= PRESUBMIT.CheckTranslationExpectations(
4216 input_api,MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
4217 grd_files)
4218 self.assertEqual(0, len(warnings))
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]4219
Ben Mason5d4c3242025-04-15 20:28:37[diff] [blame]4220# Tests that the list of files passed to the presubmit does not
4221# contain duplicate basenames.
4222def testExpectationsSuccess(self):
4223# Mock input file list needs a grd or grdp file in order to run the
4224# presubmit. The file itself doesn't matter.
4225 input_api=MockInputApi()
4226 input_api.files=[
4227MockAffectedFile('dummy.grd','not used','not used', action='M')
4228]
4229# List of all grd files in the repo.
4230 grd_files=[
4231'dir1/test.grd','unlisted.grd','not_translated.grd',
4232'internal.grd','dir2/test.grd'
4233]
4234 warnings= PRESUBMIT.CheckTranslationExpectations(
4235 input_api,MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
4236 grd_files)
4237 self.assertEqual(1, len(warnings))
4238 self.assertTrue(
4239("Multiple string files have the same basename. "
4240"This will result in missing translations. "
4241"Files: dir1/test.grd, dir2/test.grd")in warnings[0].message)
4242
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4243# Tests that the presubmit warns when a file is listed in expectations, but
4244# does not actually exist.
4245def testExpectationsMissingFile(self):
4246# Mock input file list needs a grd or grdp file in order to run the
4247# presubmit.
4248 input_api=MockInputApi()
4249 input_api.files=[
4250MockAffectedFile('dummy.grd','not used','not used', action='M')
4251]
4252# unlisted.grd is listed under tools/translation/testdata but is not
4253# included in translation expectations.
4254 grd_files=['unlisted.grd','not_translated.grd','internal.grd']
4255 warnings= PRESUBMIT.CheckTranslationExpectations(
4256 input_api,MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS,
4257 grd_files)
4258 self.assertEqual(1, len(warnings))
4259 self.assertTrue(warnings[0].message.startswith(
4260 self.ERROR_MESSAGE_FORMAT% self.EXPECTATIONS))
4261 self.assertTrue(
4262("test.grd is listed in the translation expectations, "
4263"but this grd file does not exist")in warnings[0].message)
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]4264
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4265# Tests that the presubmit warns when a file is not listed in expectations but
4266# does actually exist.
4267def testExpectationsUnlistedFile(self):
4268# Mock input file list needs a grd or grdp file in order to run the
4269# presubmit.
4270 input_api=MockInputApi()
4271 input_api.files=[
4272MockAffectedFile('dummy.grd','not used','not used', action='M')
4273]
4274# unlisted.grd is listed under tools/translation/testdata but is not
4275# included in translation expectations.
4276 grd_files=[
4277'test.grd','unlisted.grd','not_translated.grd','internal.grd'
4278]
4279 warnings= PRESUBMIT.CheckTranslationExpectations(
4280 input_api,MockOutputApi(), self.REPO_ROOT,
4281 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
4282 self.assertEqual(1, len(warnings))
4283 self.assertTrue(warnings[0].message.startswith(
4284 self.ERROR_MESSAGE_FORMAT%
4285 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
4286 self.assertTrue(("unlisted.grd appears to be translatable "
4287"(because it contains <file> or <message> elements), "
4288"but is not listed in the translation expectations."
4289)in warnings[0].message)
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]4290
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4291# Tests that the presubmit warns twice:
4292# - for a non-existing file listed in expectations
4293# - for an existing file not listed in expectations
4294def testMultipleWarnings(self):
4295# Mock input file list needs a grd or grdp file in order to run the
4296# presubmit.
4297 input_api=MockInputApi()
4298 input_api.files=[
4299MockAffectedFile('dummy.grd','not used','not used', action='M')
4300]
4301# unlisted.grd is listed under tools/translation/testdata but is not
4302# included in translation expectations.
4303# test.grd is not listed under tools/translation/testdata but is included
4304# in translation expectations.
4305 grd_files=['unlisted.grd','not_translated.grd','internal.grd']
4306 warnings= PRESUBMIT.CheckTranslationExpectations(
4307 input_api,MockOutputApi(), self.REPO_ROOT,
4308 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files)
4309 self.assertEqual(1, len(warnings))
4310 self.assertTrue(warnings[0].message.startswith(
4311 self.ERROR_MESSAGE_FORMAT%
4312 self.EXPECTATIONS_WITHOUT_UNLISTED_FILE))
4313 self.assertTrue(("unlisted.grd appears to be translatable "
4314"(because it contains <file> or <message> elements), "
4315"but is not listed in the translation expectations."
4316)in warnings[0].message)
4317 self.assertTrue(
4318("test.grd is listed in the translation expectations, "
4319"but this grd file does not exist")in warnings[0].message)
Mustafa Emre Acer51f2f742020-03-09 19:41:12[diff] [blame]4320
4321
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]4322classDISABLETypoInTest(unittest.TestCase):
4323
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4324def testPositive(self):
4325# Verify the typo "DISABLE_" instead of "DISABLED_" in various contexts
4326# where the desire is to disable a test.
4327 tests=[
4328# Disabled on one platform:
4329'#if defined(OS_WIN)\n'
4330'#define MAYBE_FoobarTest DISABLE_FoobarTest\n'
4331'#else\n'
4332'#define MAYBE_FoobarTest FoobarTest\n'
4333'#endif\n',
4334# Disabled on one platform spread cross lines:
4335'#if defined(OS_WIN)\n'
4336'#define MAYBE_FoobarTest \\\n'
4337' DISABLE_FoobarTest\n'
4338'#else\n'
4339'#define MAYBE_FoobarTest FoobarTest\n'
4340'#endif\n',
4341# Disabled on all platforms:
4342' TEST_F(FoobarTest, DISABLE_Foo)\n{\n}',
4343# Disabled on all platforms but multiple lines
4344' TEST_F(FoobarTest,\n DISABLE_foo){\n}\n',
4345]
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]4346
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4347for testin tests:
4348 mock_input_api=MockInputApi()
4349 mock_input_api.files=[
4350MockFile('some/path/foo_unittest.cc', test.splitlines()),
4351]
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]4352
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4353 results= PRESUBMIT.CheckNoDISABLETypoInTests(
4354 mock_input_api,MockOutputApi())
4355 self.assertEqual(
43561,
4357 len(results),
4358 msg=('expected len(results) == 1 but got %d in test: %s'%
4359(len(results), test)))
4360 self.assertTrue(
4361'foo_unittest.cc'in results[0].message,
4362 msg=(
4363'expected foo_unittest.cc in message but got %s in test %s'
4364%(results[0].message, test)))
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]4365
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4366def testIgnoreNotTestFiles(self):
4367 mock_input_api=MockInputApi()
4368 mock_input_api.files=[
4369MockFile('some/path/foo.cc','TEST_F(FoobarTest, DISABLE_Foo)'),
4370]
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]4371
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4372 results= PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
4373MockOutputApi())
4374 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]4375
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4376def testIgnoreDeletedFiles(self):
4377 mock_input_api=MockInputApi()
4378 mock_input_api.files=[
4379MockFile('some/path/foo.cc','TEST_F(FoobarTest, Foo)',
4380 action='D'),
4381]
Katie Df13948e2018-09-25 07:33:44[diff] [blame]4382
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4383 results= PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api,
4384MockOutputApi())
4385 self.assertEqual(0, len(results))
Dominic Battre033531052018-09-24 15:45:34[diff] [blame]4386
Nina Satragnof7660532021-09-20 18:03:35[diff] [blame]4387classForgettingMAYBEInTests(unittest.TestCase):
Nina Satragnof7660532021-09-20 18:03:35[diff] [blame]4388
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4389def testPositive(self):
4390 test=('#if defined(HAS_ENERGY)\n'
4391'#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
4392'#else\n'
4393'#define MAYBE_CastExplosion CastExplosion\n'
4394'#endif\n'
4395'TEST_F(ArchWizard, CastExplosion) {\n'
4396'#if defined(ARCH_PRIEST_IN_PARTY)\n'
4397'#define MAYBE_ArchPriest ArchPriest\n'
4398'#else\n'
4399'#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
4400'#endif\n'
4401'TEST_F(ArchPriest, CastNaturesBounty) {\n'
4402'#if !defined(CRUSADER_IN_PARTY)\n'
4403'#define MAYBE_Crusader \\\n'
4404' DISABLED_Crusader \n'
4405'#else\n'
4406'#define MAYBE_Crusader \\\n'
4407' Crusader\n'
4408'#endif\n'
4409' TEST_F(\n'
4410' Crusader,\n'
4411' CastTaunt) { }\n'
4412'#if defined(LEARNED_BASIC_SKILLS)\n'
4413'#define MAYBE_CastSteal \\\n'
4414' DISABLED_CastSteal \n'
4415'#else\n'
4416'#define MAYBE_CastSteal \\\n'
4417' CastSteal\n'
4418'#endif\n'
4419' TEST_F(\n'
4420' ThiefClass,\n'
4421' CastSteal) { }\n')
4422 mock_input_api=MockInputApi()
4423 mock_input_api.files=[
4424MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
4425]
4426 results= PRESUBMIT.CheckForgettingMAYBEInTests(
4427 mock_input_api,MockOutputApi())
4428 self.assertEqual(4, len(results))
4429 self.assertTrue('CastExplosion'in results[0].message)
4430 self.assertTrue(
4431'fantasyworld/classes_unittest.cc:2'in results[0].message)
4432 self.assertTrue('ArchPriest'in results[1].message)
4433 self.assertTrue(
4434'fantasyworld/classes_unittest.cc:8'in results[1].message)
4435 self.assertTrue('Crusader'in results[2].message)
4436 self.assertTrue(
4437'fantasyworld/classes_unittest.cc:14'in results[2].message)
4438 self.assertTrue('CastSteal'in results[3].message)
4439 self.assertTrue(
4440'fantasyworld/classes_unittest.cc:24'in results[3].message)
Nina Satragnof7660532021-09-20 18:03:35[diff] [blame]4441
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4442def testNegative(self):
4443 test=('#if defined(HAS_ENERGY)\n'
4444'#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
4445'#else\n'
4446'#define MAYBE_CastExplosion CastExplosion\n'
4447'#endif\n'
4448'TEST_F(ArchWizard, MAYBE_CastExplosion) {\n'
4449'#if defined(ARCH_PRIEST_IN_PARTY)\n'
4450'#define MAYBE_ArchPriest ArchPriest\n'
4451'#else\n'
4452'#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
4453'#endif\n'
4454'TEST_F(MAYBE_ArchPriest, CastNaturesBounty) {\n'
4455'#if !defined(CRUSADER_IN_PARTY)\n'
4456'#define MAYBE_Crusader \\\n'
4457' DISABLED_Crusader \n'
4458'#else\n'
4459'#define MAYBE_Crusader \\\n'
4460' Crusader\n'
4461'#endif\n'
4462' TEST_F(\n'
4463' MAYBE_Crusader,\n'
4464' CastTaunt) { }\n'
4465'#if defined(LEARNED_BASIC_SKILLS)\n'
4466'#define MAYBE_CastSteal \\\n'
4467' DISABLED_CastSteal \n'
4468'#else\n'
4469'#define MAYBE_CastSteal \\\n'
4470' CastSteal\n'
4471'#endif\n'
4472' TEST_F(\n'
4473' ThiefClass,\n'
4474' MAYBE_CastSteal) { }\n')
4475
4476 mock_input_api=MockInputApi()
4477 mock_input_api.files=[
4478MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
4479]
4480 results= PRESUBMIT.CheckForgettingMAYBEInTests(
4481 mock_input_api,MockOutputApi())
4482 self.assertEqual(0, len(results))
Dirk Pranke3c18a382019-03-15 01:07:51[diff] [blame]4483
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]4484classCheckFuzzTargetsTest(unittest.TestCase):
4485
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4486def _check(self, files):
4487 mock_input_api=MockInputApi()
4488 mock_input_api.files=[]
4489for fname, contentsin files.items():
4490 mock_input_api.files.append(MockFile(fname, contents.splitlines()))
4491return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api,
4492MockOutputApi())
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]4493
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4494def testLibFuzzerSourcesIgnored(self):
4495 results= self._check({
4496"third_party/lib/Fuzzer/FuzzerDriver.cpp":
4497"LLVMFuzzerInitialize",
4498})
4499 self.assertEqual(results,[])
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]4500
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4501def testNonCodeFilesIgnored(self):
4502 results= self._check({
4503"README.md":"LLVMFuzzerInitialize",
4504})
4505 self.assertEqual(results,[])
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]4506
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4507def testNoErrorHeaderPresent(self):
4508 results= self._check({
4509"fuzzer.cc":
4510("#include \"testing/libfuzzer/libfuzzer_exports.h\"\n"+
4511"LLVMFuzzerInitialize")
4512})
4513 self.assertEqual(results,[])
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]4514
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4515def testErrorMissingHeader(self):
4516 results= self._check({"fuzzer.cc":"LLVMFuzzerInitialize"})
4517 self.assertEqual(len(results),1)
4518 self.assertEqual(results[0].items,['fuzzer.cc'])
Max Morozb47503b2019-08-08 21:03:27[diff] [blame]4519
4520
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:26[diff] [blame]4521classSetNoParentTest(unittest.TestCase):
John Abd-El-Malekdfd1edc2021-02-24 22:22:40[diff] [blame]4522
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4523def testSetNoParentTopLevelAllowed(self):
4524 mock_input_api=MockInputApi()
4525 mock_input_api.files=[
4526MockAffectedFile('goat/OWNERS',[
4527'set noparent',
4528'jochen@chromium.org',
4529])
4530]
4531 mock_output_api=MockOutputApi()
4532 errors= PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
4533 self.assertEqual([], errors)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:26[diff] [blame]4534
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4535def testSetNoParentMissing(self):
4536 mock_input_api=MockInputApi()
4537 mock_input_api.files=[
4538MockAffectedFile('services/goat/OWNERS',[
4539'set noparent',
4540'jochen@chromium.org',
4541'per-file *.json=set noparent',
4542'per-file *.json=jochen@chromium.org',
4543])
4544]
4545 mock_output_api=MockOutputApi()
4546 errors= PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
4547 self.assertEqual(1, len(errors))
4548 self.assertTrue('goat/OWNERS:1'in errors[0].long_text)
4549 self.assertTrue('goat/OWNERS:3'in errors[0].long_text)
4550
4551def testSetNoParentWithCorrectRule(self):
4552 mock_input_api=MockInputApi()
4553 mock_input_api.files=[
4554MockAffectedFile('services/goat/OWNERS',[
4555'set noparent',
4556'file://ipc/SECURITY_OWNERS',
4557'per-file *.json=set noparent',
4558'per-file *.json=file://ipc/SECURITY_OWNERS',
4559])
4560]
4561 mock_output_api=MockOutputApi()
4562 errors= PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api)
4563 self.assertEqual([], errors)
Jochen Eisingerf9fbe7b6c32019-11-18 09:37:26[diff] [blame]4564
4565
Ken Rockotc31f4832020-05-29 18:58:51[diff] [blame]4566classMojomStabilityCheckTest(unittest.TestCase):
Ken Rockotc31f4832020-05-29 18:58:51[diff] [blame]4567
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4568def runTestWithAffectedFiles(self, affected_files):
4569 mock_input_api=MockInputApi()
4570 mock_input_api.files= affected_files
4571 mock_output_api=MockOutputApi()
4572return PRESUBMIT.CheckStableMojomChanges(mock_input_api,
4573 mock_output_api)
Ken Rockotc31f4832020-05-29 18:58:51[diff] [blame]4574
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4575def testSafeChangePasses(self):
4576 errors= self.runTestWithAffectedFiles([
4577MockAffectedFile(
4578'foo/foo.mojom',
4579['[Stable] struct S { [MinVersion=1] int32 x; };'],
4580 old_contents=['[Stable] struct S {};'])
4581])
4582 self.assertEqual([], errors)
Ken Rockotc31f4832020-05-29 18:58:51[diff] [blame]4583
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4584def testBadChangeFails(self):
4585 errors= self.runTestWithAffectedFiles([
4586MockAffectedFile('foo/foo.mojom',
4587['[Stable] struct S { int32 x; };'],
4588 old_contents=['[Stable] struct S {};'])
4589])
4590 self.assertEqual(1, len(errors))
4591 self.assertTrue('not backward-compatible'in errors[0].message)
4592
4593def testDeletedFile(self):
4594"""Regression test for https://crbug.com/1091407."""
4595 errors= self.runTestWithAffectedFiles([
4596MockAffectedFile('a.mojom',[],
4597 old_contents=['struct S {};'],
4598 action='D'),
4599MockAffectedFile(
4600'b.mojom',['struct S {}; struct T { S s; };'],
4601 old_contents=['import "a.mojom"; struct T { S s; };'])
4602])
4603 self.assertEqual([], errors)
4604
Ken Rockotad7901f942020-06-04 20:17:09[diff] [blame]4605
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]4606classCheckForUseOfChromeAppsDeprecationsTest(unittest.TestCase):
4607
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4608 ERROR_MSG_PIECE='technologies which will soon be deprecated'
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]4609
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4610# Each positive test is also a naive negative test for the other cases.
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]4611
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4612def testWarningNMF(self):
4613 mock_input_api=MockInputApi()
4614 mock_input_api.files=[
4615MockAffectedFile(
4616'foo.NMF',['"program"','"Z":"content"','B'],
4617['"program"','B'],
4618 scm_diff='\n'.join([
4619'--- foo.NMF.old 2020-12-02 20:40:54.430676385 +0100',
4620'+++ foo.NMF.new 2020-12-02 20:41:02.086700197 +0100',
4621'@@ -1,2 +1,3 @@',' "program"','+"Z":"content"',' B'
4622]),
4623 action='M')
4624]
4625 mock_output_api=MockOutputApi()
4626 errors= PRESUBMIT.CheckForUseOfChromeAppsDeprecations(
4627 mock_input_api, mock_output_api)
4628 self.assertEqual(1, len(errors))
4629 self.assertTrue(self.ERROR_MSG_PIECEin errors[0].message)
4630 self.assertTrue('foo.NMF'in errors[0].message)
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]4631
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4632def testWarningManifest(self):
4633 mock_input_api=MockInputApi()
4634 mock_input_api.files=[
4635MockAffectedFile(
4636'manifest.json',['"app":','"Z":"content"','B'],
4637['"app":"','B'],
4638 scm_diff='\n'.join([
4639'--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
4640'+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
4641'@@ -1,2 +1,3 @@',' "app"','+"Z":"content"',' B'
4642]),
4643 action='M')
4644]
4645 mock_output_api=MockOutputApi()
4646 errors= PRESUBMIT.CheckForUseOfChromeAppsDeprecations(
4647 mock_input_api, mock_output_api)
4648 self.assertEqual(1, len(errors))
4649 self.assertTrue(self.ERROR_MSG_PIECEin errors[0].message)
4650 self.assertTrue('manifest.json'in errors[0].message)
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]4651
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4652def testOKWarningManifestWithoutApp(self):
4653 mock_input_api=MockInputApi()
4654 mock_input_api.files=[
4655MockAffectedFile(
4656'manifest.json',['"name":','"Z":"content"','B'],
4657['"name":"','B'],
4658 scm_diff='\n'.join([
4659'--- manifest.json.old 2020-12-02 20:40:54.430676385 +0100',
4660'+++ manifest.json.new 2020-12-02 20:41:02.086700197 +0100',
4661'@@ -1,2 +1,3 @@',' "app"','+"Z":"content"',' B'
4662]),
4663 action='M')
4664]
4665 mock_output_api=MockOutputApi()
4666 errors= PRESUBMIT.CheckForUseOfChromeAppsDeprecations(
4667 mock_input_api, mock_output_api)
4668 self.assertEqual(0, len(errors))
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]4669
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4670def testWarningPPAPI(self):
4671 mock_input_api=MockInputApi()
4672 mock_input_api.files=[
4673MockAffectedFile(
4674'foo.hpp',['A','#include <ppapi.h>','B'],['A','B'],
4675 scm_diff='\n'.join([
4676'--- foo.hpp.old 2020-12-02 20:40:54.430676385 +0100',
4677'+++ foo.hpp.new 2020-12-02 20:41:02.086700197 +0100',
4678'@@ -1,2 +1,3 @@',' A','+#include <ppapi.h>',' B'
4679]),
4680 action='M')
4681]
4682 mock_output_api=MockOutputApi()
4683 errors= PRESUBMIT.CheckForUseOfChromeAppsDeprecations(
4684 mock_input_api, mock_output_api)
4685 self.assertEqual(1, len(errors))
4686 self.assertTrue(self.ERROR_MSG_PIECEin errors[0].message)
4687 self.assertTrue('foo.hpp'in errors[0].message)
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]4688
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4689def testNoWarningPPAPI(self):
4690 mock_input_api=MockInputApi()
4691 mock_input_api.files=[
4692MockAffectedFile(
4693'foo.txt',['A','Peppapig','B'],['A','B'],
4694 scm_diff='\n'.join([
4695'--- foo.txt.old 2020-12-02 20:40:54.430676385 +0100',
4696'+++ foo.txt.new 2020-12-02 20:41:02.086700197 +0100',
4697'@@ -1,2 +1,3 @@',' A','+Peppapig',' B'
4698]),
4699 action='M')
4700]
4701 mock_output_api=MockOutputApi()
4702 errors= PRESUBMIT.CheckForUseOfChromeAppsDeprecations(
4703 mock_input_api, mock_output_api)
4704 self.assertEqual(0, len(errors))
4705
Jose Magana2b456f22021-03-09 23:26:40[diff] [blame]4706
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]4707classCheckDeprecationOfPreferencesTest(unittest.TestCase):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4708# Test that a warning is generated if a preference registration is removed
4709# from a random file.
4710def testWarning(self):
4711 mock_input_api=MockInputApi()
4712 mock_input_api.files=[
4713MockAffectedFile(
4714'foo.cc',['A','B'],
4715['A','prefs->RegisterStringPref("foo", "default");','B'],
4716 scm_diff='\n'.join([
4717'--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4718'+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4719'@@ -1,3 +1,2 @@',' A',
4720'-prefs->RegisterStringPref("foo", "default");',' B'
4721]),
4722 action='M')
4723]
4724 mock_output_api=MockOutputApi()
4725 errors= PRESUBMIT.CheckDeprecationOfPreferences(
4726 mock_input_api, mock_output_api)
4727 self.assertEqual(1, len(errors))
4728 self.assertTrue(
4729'Discovered possible removal of preference registrations'in
4730 errors[0].message)
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]4731
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4732# Test that a warning is inhibited if the preference registration was moved
4733# to the deprecation functions in browser prefs.
4734def testNoWarningForMigration(self):
4735 mock_input_api=MockInputApi()
4736 mock_input_api.files=[
4737# RegisterStringPref was removed from foo.cc.
4738MockAffectedFile(
4739'foo.cc',['A','B'],
4740['A','prefs->RegisterStringPref("foo", "default");','B'],
4741 scm_diff='\n'.join([
4742'--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4743'+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4744'@@ -1,3 +1,2 @@',' A',
4745'-prefs->RegisterStringPref("foo", "default");',' B'
4746]),
4747 action='M'),
4748# But the preference was properly migrated.
4749MockAffectedFile(
4750'chrome/browser/prefs/browser_prefs.cc',[
4751'// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4752'// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4753'// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4754'prefs->RegisterStringPref("foo", "default");',
4755'// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4756],[
4757'// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4758'// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4759'// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4760'// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4761],
4762 scm_diff='\n'.join([
4763'--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
4764'+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
4765'@@ -2,3 +2,4 @@',
4766' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4767' // BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4768'+prefs->RegisterStringPref("foo", "default");',
4769' // END_MIGRATE_OBSOLETE_PROFILE_PREFS'
4770]),
4771 action='M'),
4772]
4773 mock_output_api=MockOutputApi()
4774 errors= PRESUBMIT.CheckDeprecationOfPreferences(
4775 mock_input_api, mock_output_api)
4776 self.assertEqual(0, len(errors))
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]4777
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4778# Test that a warning is NOT inhibited if the preference registration was
4779# moved to a place outside of the migration functions in browser_prefs.cc
4780def testWarningForImproperMigration(self):
4781 mock_input_api=MockInputApi()
4782 mock_input_api.files=[
4783# RegisterStringPref was removed from foo.cc.
4784MockAffectedFile(
4785'foo.cc',['A','B'],
4786['A','prefs->RegisterStringPref("foo", "default");','B'],
4787 scm_diff='\n'.join([
4788'--- foo.cc.old 2020-12-02 20:40:54.430676385 +0100',
4789'+++ foo.cc.new 2020-12-02 20:41:02.086700197 +0100',
4790'@@ -1,3 +1,2 @@',' A',
4791'-prefs->RegisterStringPref("foo", "default");',' B'
4792]),
4793 action='M'),
4794# The registration call was moved to a place in browser_prefs.cc that
4795# is outside the migration functions.
4796MockAffectedFile(
4797'chrome/browser/prefs/browser_prefs.cc',[
4798'prefs->RegisterStringPref("foo", "default");',
4799'// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4800'// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4801'// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4802'// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4803],[
4804'// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4805'// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4806'// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4807'// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4808],
4809 scm_diff='\n'.join([
4810'--- browser_prefs.cc.old 2020-12-02 20:51:40.812686731 +0100',
4811'+++ browser_prefs.cc.new 2020-12-02 20:52:02.936755539 +0100',
4812'@@ -1,2 +1,3 @@',
4813'+prefs->RegisterStringPref("foo", "default");',
4814' // BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4815' // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS'
4816]),
4817 action='M'),
4818]
4819 mock_output_api=MockOutputApi()
4820 errors= PRESUBMIT.CheckDeprecationOfPreferences(
4821 mock_input_api, mock_output_api)
4822 self.assertEqual(1, len(errors))
4823 self.assertTrue(
4824'Discovered possible removal of preference registrations'in
4825 errors[0].message)
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]4826
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4827# Check that the presubmit fails if a marker line in browser_prefs.cc is
4828# deleted.
4829def testDeletedMarkerRaisesError(self):
4830 mock_input_api=MockInputApi()
4831 mock_input_api.files=[
4832MockAffectedFile(
4833'chrome/browser/prefs/browser_prefs.cc',
4834[
4835'// BEGIN_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4836'// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS',
4837'// BEGIN_MIGRATE_OBSOLETE_PROFILE_PREFS',
4838# The following line is deleted for this test
4839# '// END_MIGRATE_OBSOLETE_PROFILE_PREFS',
4840])
4841]
4842 mock_output_api=MockOutputApi()
4843 errors= PRESUBMIT.CheckDeprecationOfPreferences(
4844 mock_input_api, mock_output_api)
4845 self.assertEqual(1, len(errors))
4846 self.assertEqual(
4847'Broken .*MIGRATE_OBSOLETE_.*_PREFS markers in browser_prefs.cc.',
4848 errors[0].message)
Dominic Battre645d42342020-12-04 16:14:10[diff] [blame]4849
Sven Zheng76a79ea2022-12-21 21:25:24[diff] [blame]4850classCheckCrosApiNeedBrowserTestTest(unittest.TestCase):
4851def testWarning(self):
4852 mock_input_api=MockInputApi()
4853 mock_output_api=MockOutputApi()
4854 mock_input_api.files=[
4855MockAffectedFile('chromeos/crosapi/mojom/example.mojom',[], action='A'),
4856]
4857 result= PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4858 self.assertEqual(1, len(result))
4859 self.assertEqual(result[0].type,'warning')
4860
4861def testNoWarningWithBrowserTest(self):
4862 mock_input_api=MockInputApi()
4863 mock_output_api=MockOutputApi()
4864 mock_input_api.files=[
4865MockAffectedFile('chromeos/crosapi/mojom/example.mojom',[], action='A'),
4866MockAffectedFile('chrome/example_browsertest.cc',[], action='A'),
4867]
4868 result= PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4869 self.assertEqual(0, len(result))
4870
4871def testNoWarningModifyCrosapi(self):
4872 mock_input_api=MockInputApi()
4873 mock_output_api=MockOutputApi()
4874 mock_input_api.files=[
4875MockAffectedFile('chromeos/crosapi/mojom/example.mojom',[], action='M'),
4876]
4877 result= PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4878 self.assertEqual(0, len(result))
4879
4880def testNoWarningAddNonMojomFile(self):
4881 mock_input_api=MockInputApi()
4882 mock_output_api=MockOutputApi()
4883 mock_input_api.files=[
4884MockAffectedFile('chromeos/crosapi/mojom/example.cc',[], action='A'),
4885]
4886 result= PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4887 self.assertEqual(0, len(result))
4888
4889def testNoWarningNoneRelatedMojom(self):
4890 mock_input_api=MockInputApi()
4891 mock_output_api=MockOutputApi()
4892 mock_input_api.files=[
4893MockAffectedFile('random/folder/example.mojom',[], action='A'),
4894]
4895 result= PRESUBMIT.CheckCrosApiNeedBrowserTest(mock_input_api, mock_output_api)
4896 self.assertEqual(0, len(result))
4897
4898
Henrique Ferreiro2a4b55942021-11-29 23:45:36[diff] [blame]4899classAssertAshOnlyCodeTest(unittest.TestCase):
4900def testErrorsOnlyOnAshDirectories(self):
4901 files_in_ash=[
4902MockFile('ash/BUILD.gn',[]),
4903MockFile('chrome/browser/ash/BUILD.gn',[]),
4904]
4905 other_files=[
4906MockFile('chrome/browser/BUILD.gn',[]),
Georg Neis94f87f02024-10-22 08:20:13[diff] [blame]4907MockFile('chrome/browser/foo/BUILD.gn',['assert(is_chromeos_ash)']),
Henrique Ferreiro2a4b55942021-11-29 23:45:36[diff] [blame]4908]
4909 input_api=MockInputApi()
4910 input_api.files= files_in_ash
4911 errors= PRESUBMIT.CheckAssertAshOnlyCode(input_api,MockOutputApi())
4912 self.assertEqual(2, len(errors))
4913
4914 input_api.files= other_files
4915 errors= PRESUBMIT.CheckAssertAshOnlyCode(input_api,MockOutputApi())
4916 self.assertEqual(0, len(errors))
4917
4918def testDoesNotErrorOnNonGNFiles(self):
4919 input_api=MockInputApi()
4920 input_api.files=[
4921MockFile('ash/test.h',['assert(is_chromeos_ash)']),
4922MockFile('chrome/browser/ash/test.cc',
4923['assert(is_chromeos_ash)']),
4924]
4925 errors= PRESUBMIT.CheckAssertAshOnlyCode(input_api,MockOutputApi())
4926 self.assertEqual(0, len(errors))
4927
Giovanni Ortuño Urquidiab84da62021-12-10 00:53:21[diff] [blame]4928def testDeletedFile(self):
4929 input_api=MockInputApi()
4930 input_api.files=[
4931MockFile('ash/BUILD.gn',[]),
4932MockFile('ash/foo/BUILD.gn',[], action='D'),
4933]
4934 errors= PRESUBMIT.CheckAssertAshOnlyCode(input_api,MockOutputApi())
4935 self.assertEqual(1, len(errors))
4936
Henrique Ferreiro2a4b55942021-11-29 23:45:36[diff] [blame]4937def testDoesNotErrorWithAssertion(self):
4938 input_api=MockInputApi()
4939 input_api.files=[
4940MockFile('ash/BUILD.gn',['assert(is_chromeos_ash)']),
4941MockFile('chrome/browser/ash/BUILD.gn',
4942['assert(is_chromeos_ash)']),
Georg Neis94f87f02024-10-22 08:20:13[diff] [blame]4943MockFile('chrome/browser/ash/1/BUILD.gn',
4944['assert(is_chromeos)']),
4945MockFile('chrome/browser/ash/2/BUILD.gn',
4946['assert(is_chromeos_ash)']),
4947MockFile('chrome/browser/ash/3/BUILD.gn',
4948['assert(is_chromeos, "test")']),
4949MockFile('chrome/browser/ash/4/BUILD.gn',
Henrique Ferreiro2a4b55942021-11-29 23:45:36[diff] [blame]4950['assert(is_chromeos_ash, "test")']),
4951]
4952 errors= PRESUBMIT.CheckAssertAshOnlyCode(input_api,MockOutputApi())
4953 self.assertEqual(0, len(errors))
4954
4955
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]4956classCheckRawPtrUsageTest(unittest.TestCase):
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]4957
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4958def testAllowedCases(self):
4959 mock_input_api=MockInputApi()
4960 mock_input_api.files=[
4961# Browser-side files are allowed.
4962MockAffectedFile('test10/browser/foo.h',['raw_ptr<int>']),
4963MockAffectedFile('test11/browser/foo.cc',['raw_ptr<int>']),
4964MockAffectedFile('test12/blink/common/foo.cc',['raw_ptr<int>']),
4965MockAffectedFile('test13/blink/public/common/foo.cc',
4966['raw_ptr<int>']),
4967MockAffectedFile('test14/blink/public/platform/foo.cc',
4968['raw_ptr<int>']),
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]4969
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4970# Non-C++ files are allowed.
4971MockAffectedFile('test20/renderer/foo.md',['raw_ptr<int>']),
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]4972
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]4973# Renderer code is generally allowed (except specifically
4974# disallowed directories).
4975MockAffectedFile('test30/renderer/foo.cc',['raw_ptr<int>']),
4976]
4977 mock_output_api=MockOutputApi()
4978 errors= PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
4979 self.assertFalse(errors)
4980
4981def testDisallowedCases(self):
4982 mock_input_api=MockInputApi()
4983 mock_input_api.files=[
4984MockAffectedFile('test1/third_party/blink/renderer/core/foo.h',
4985['raw_ptr<int>']),
4986MockAffectedFile(
4987'test2/third_party/blink/renderer/platform/heap/foo.cc',
4988['raw_ptr<int>']),
4989MockAffectedFile(
4990'test3/third_party/blink/renderer/platform/wtf/foo.cc',
4991['raw_ptr<int>']),
4992MockAffectedFile(
4993'test4/third_party/blink/renderer/platform/fonts/foo.h',
4994['raw_ptr<int>']),
4995MockAffectedFile(
4996'test5/third_party/blink/renderer/core/paint/foo.cc',
4997['raw_ptr<int>']),
4998MockAffectedFile(
4999'test6/third_party/blink/renderer/platform/graphics/compositing/foo.h',
5000['raw_ptr<int>']),
5001MockAffectedFile(
5002'test7/third_party/blink/renderer/platform/graphics/paint/foo.cc',
5003['raw_ptr<int>']),
5004]
5005 mock_output_api=MockOutputApi()
5006 errors= PRESUBMIT.CheckRawPtrUsage(mock_input_api, mock_output_api)
5007 self.assertEqual(len(mock_input_api.files), len(errors))
5008for errorin errors:
5009 self.assertTrue(
5010'raw_ptr<T> should not be used in this renderer code'in
5011 error.message)
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]5012
mikt9337567c2023-09-08 18:38:17[diff] [blame]5013classCheckAdvancedMemorySafetyChecksUsageTest(unittest.TestCase):
mikt9337567c2023-09-08 18:38:17[diff] [blame]5014
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5015def testAllowedCases(self):
5016 mock_input_api=MockInputApi()
5017 mock_input_api.files=[
5018# Non-C++ files are allowed.
5019MockAffectedFile('test20/renderer/foo.md',
5020['ADVANCED_MEMORY_SAFETY_CHECKS()']),
mikt9337567c2023-09-08 18:38:17[diff] [blame]5021
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5022# Mentions in a comment are allowed.
5023MockAffectedFile('test30/renderer/foo.cc',
5024['//ADVANCED_MEMORY_SAFETY_CHECKS()']),
5025]
5026 mock_output_api=MockOutputApi()
5027 errors= PRESUBMIT.CheckAdvancedMemorySafetyChecksUsage(
5028 mock_input_api, mock_output_api)
5029 self.assertFalse(errors)
5030
5031def testDisallowedCases(self):
5032 mock_input_api=MockInputApi()
5033 mock_input_api.files=[
5034MockAffectedFile('test1/foo.h',
5035['ADVANCED_MEMORY_SAFETY_CHECKS()']),
5036MockAffectedFile('test2/foo.cc',
5037['ADVANCED_MEMORY_SAFETY_CHECKS()']),
5038]
5039 mock_output_api=MockOutputApi()
5040 errors= PRESUBMIT.CheckAdvancedMemorySafetyChecksUsage(
5041 mock_input_api, mock_output_api)
5042 self.assertEqual(1, len(errors))
5043 self.assertTrue('ADVANCED_MEMORY_SAFETY_CHECKS() macro is managed by'
5044in errors[0].message)
Lukasz Anforowicz7016d05e2021-11-30 03:56:27[diff] [blame]5045
Henrique Ferreirof9819f2e32021-11-30 13:31:56[diff] [blame]5046classAssertPythonShebangTest(unittest.TestCase):
5047def testError(self):
5048 input_api=MockInputApi()
5049 input_api.files=[
5050MockFile('ash/test.py',['#!/usr/bin/python']),
5051MockFile('chrome/test.py',['#!/usr/bin/python2']),
5052MockFile('third_party/blink/test.py',['#!/usr/bin/python3']),
Takuto Ikuta36976512021-11-30 23:15:27[diff] [blame]5053MockFile('empty.py',[]),
Henrique Ferreirof9819f2e32021-11-30 13:31:56[diff] [blame]5054]
5055 errors= PRESUBMIT.CheckPythonShebang(input_api,MockOutputApi())
5056 self.assertEqual(3, len(errors))
5057
5058def testNonError(self):
5059 input_api=MockInputApi()
5060 input_api.files=[
5061MockFile('chrome/browser/BUILD.gn',['#!/usr/bin/python']),
5062MockFile('third_party/blink/web_tests/external/test.py',
5063['#!/usr/bin/python2']),
5064MockFile('third_party/test/test.py',['#!/usr/bin/python3']),
5065]
5066 errors= PRESUBMIT.CheckPythonShebang(input_api,MockOutputApi())
5067 self.assertEqual(0, len(errors))
5068
Kalvin Lee4a3b79de2022-05-26 16:00:16[diff] [blame]5069classVerifyDcheckParentheses(unittest.TestCase):
Kalvin Lee4a3b79de2022-05-26 16:00:16[diff] [blame]5070
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5071def testPermissibleUsage(self):
5072 input_api=MockInputApi()
5073 input_api.files=[
5074MockFile('okay1.cc',['DCHECK_IS_ON()']),
5075MockFile('okay2.cc',['#if DCHECK_IS_ON()']),
Kalvin Lee4a3b79de2022-05-26 16:00:16[diff] [blame]5076
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5077# Other constructs that aren't exactly `DCHECK_IS_ON()` do their
5078# own thing at their own risk.
5079MockFile('okay3.cc',['PA_DCHECK_IS_ON']),
5080MockFile('okay4.cc',['#if PA_DCHECK_IS_ON']),
5081MockFile('okay6.cc',['PA_BUILDFLAG(PA_DCHECK_IS_ON)']),
5082]
5083 errors= PRESUBMIT.CheckDCHECK_IS_ONHasBraces(input_api,
5084MockOutputApi())
5085 self.assertEqual(0, len(errors))
5086
5087def testMissingParentheses(self):
5088 input_api=MockInputApi()
5089 input_api.files=[
5090MockFile('bad1.cc',['DCHECK_IS_ON']),
5091MockFile('bad2.cc',['#if DCHECK_IS_ON']),
5092MockFile('bad3.cc',['DCHECK_IS_ON && foo']),
5093]
5094 errors= PRESUBMIT.CheckDCHECK_IS_ONHasBraces(input_api,
5095MockOutputApi())
5096 self.assertEqual(3, len(errors))
5097for errorin errors:
5098 self.assertRegex(error.message, r'DCHECK_IS_ON().+parentheses')
Henrique Ferreirof9819f2e32021-11-30 13:31:56[diff] [blame]5099
Sam Maier4cef9242022-10-03 14:21:24[diff] [blame]5100
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5101classCheckAndroidTestAnnotations(unittest.TestCase):
5102"""Test the CheckAndroidTestAnnotations presubmit check."""
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]5103
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5104def testBatchTruePositives(self):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5105"""Examples of when there is no @Batch or @DoNotBatch is correctly flagged.
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]5106"""
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5107 mock_input=MockInputApi()
5108 mock_input.files=[
5109MockFile('path/OneTest.java',['public class OneTest']),
5110MockFile('path/TwoTest.java',['public class TwoTest']),
5111MockFile('path/ThreeTest.java',[
5112'@Batch(Batch.PER_CLASS)',
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5113'@RunWith(BaseRobolectricTestRunner.class)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5114'public class Three {'
5115]),
5116MockFile('path/FourTest.java',[
5117'@DoNotBatch(reason = "placeholder reason 1")',
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5118'@RunWith(BaseRobolectricTestRunner.class)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5119'public class Four {'
5120]),
5121]
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5122 errors= PRESUBMIT.CheckAndroidTestAnnotations(mock_input,MockOutputApi())
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5123 self.assertEqual(2, len(errors))
5124 self.assertEqual(2, len(errors[0].items))
5125 self.assertIn('OneTest.java', errors[0].items[0])
5126 self.assertIn('TwoTest.java', errors[0].items[1])
5127 self.assertEqual(2, len(errors[1].items))
5128 self.assertIn('ThreeTest.java', errors[1].items[0])
5129 self.assertIn('FourTest.java', errors[1].items[1])
ckitagawae8fd23b2022-06-17 15:29:38[diff] [blame]5130
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5131def testBatchAnnotationsPresent(self):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5132"""Examples of when there is @Batch or @DoNotBatch is correctly flagged."""
5133 mock_input=MockInputApi()
5134 mock_input.files=[
5135MockFile('path/OneTest.java',
5136['@Batch(Batch.PER_CLASS)','public class One {']),
5137MockFile('path/TwoTest.java',[
5138'@DoNotBatch(reason = "placeholder reasons.")',
5139'public class Two {'
5140]),
5141MockFile('path/ThreeTest.java',[
5142'@Batch(Batch.PER_CLASS)',
5143'public class Three extends BaseTestA {'
5144],[
5145'@Batch(Batch.PER_CLASS)',
5146'public class Three extends BaseTestB {'
5147]),
5148MockFile('path/FourTest.java',[
5149'@DoNotBatch(reason = "placeholder reason 1")',
5150'public class Four extends BaseTestA {'
5151],[
5152'@DoNotBatch(reason = "placeholder reason 2")',
5153'public class Four extends BaseTestB {'
5154]),
5155MockFile('path/FiveTest.java',[
5156'import androidx.test.uiautomator.UiDevice;',
5157'public class Five extends BaseTestA {'
5158],[
5159'import androidx.test.uiautomator.UiDevice;',
5160'public class Five extends BaseTestB {'
5161]),
5162MockFile('path/SixTest.java',[
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5163'@RunWith(BaseRobolectricTestRunner.class)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5164'public class Six extends BaseTestA {'
5165],[
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5166'@RunWith(BaseRobolectricTestRunner.class)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5167'public class Six extends BaseTestB {'
5168]),
5169MockFile('path/SevenTest.java',[
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5170'@RunWith(BaseRobolectricTestRunner.class)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5171'public class Seven extends BaseTestA {'
5172],[
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5173'@RunWith(BaseRobolectricTestRunner.class)',
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5174'public class Seven extends BaseTestB {'
5175]),
5176MockFile(
5177'path/OtherClass.java',
5178['public class OtherClass {'],
5179),
5180MockFile('path/PRESUBMIT.py',[
5181'@Batch(Batch.PER_CLASS)',
5182'@DoNotBatch(reason = "placeholder reason)'
5183]),
5184MockFile(
5185'path/AnnotationTest.java',
5186['public @interface SomeAnnotation {'],
5187),
5188]
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5189 errors= PRESUBMIT.CheckAndroidTestAnnotations(mock_input,MockOutputApi())
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5190 self.assertEqual(0, len(errors))
James Shen81cc0e22022-06-15 21:10:45[diff] [blame]5191
Andrew Grieve5a66ae72024-12-13 15:21:53[diff] [blame]5192def testWrongRobolectricTestRunner(self):
5193 mock_input=MockInputApi()
5194 mock_input.files=[
5195MockFile('path/OneTest.java',[
5196'@RunWith(RobolectricTestRunner.class)',
5197'public class ThreeTest {'
5198]),
5199MockFile('path/TwoTest.java',[
5200'import org.chromium.base.test.BaseRobolectricTestRule;',
5201'@RunWith(RobolectricTestRunner.class)',
5202'public class TwoTest {'
5203]),
5204MockFile('path/ThreeTest.java',[
5205'@RunWith(FooRobolectricTestRunner.class)',
5206'public class ThreeTest {'
5207]),
5208MockFile('webapks/FourTest.java',[
5209'@RunWith(RobolectricTestRunner.class)',
5210'public class ThreeTest {'
5211]),
5212]
5213 errors= PRESUBMIT.CheckAndroidTestAnnotations(mock_input,MockOutputApi())
5214 self.assertEqual(1, len(errors))
5215 self.assertEqual(1, len(errors[0].items))
5216 self.assertIn('OneTest.java', errors[0].items[0])
5217
Sam Maier4cef9242022-10-03 14:21:24[diff] [blame]5218
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]5219classCheckAndroidNullAwayAnnotatedClasses(unittest.TestCase):
5220"""Test the _CheckAndroidNullAwayAnnotatedClasses presubmit check."""
5221
5222def testDetectsInClasses(self):
5223"""Tests that missing @NullMarked or @NullUnmarked are correctly flagged in classes."""
5224 mock_input=MockInputApi()
5225 mock_input.files=[
5226MockFile('path/OneMissing.java',['public class OneMissing']),
5227MockFile('path/TwoMarked.java',[
5228'@NullMarked',
5229'public class TwoMarked {',
5230]),
5231MockFile('path/ThreeMarked.java',[
5232'@NullUnmarked',
5233'public class ThreeMarked {',
5234]),
5235MockFile('path/FourMissing.java',['class FourMissing']),
5236]
5237 results= PRESUBMIT._CheckAndroidNullAwayAnnotatedClasses(mock_input,MockOutputApi())
5238 self.assertEqual(1, len(results))
Henrique Nakashima8bafbc52025-04-22 19:38:42[diff] [blame]5239 self.assertEqual('error', results[0].type)
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]5240 self.assertEqual(2, len(results[0].items))
5241 self.assertIn('OneMissing.java', results[0].items[0])
5242 self.assertIn('FourMissing.java', results[0].items[1])
5243
5244def testDetectsInAnnotations(self):
5245"""Tests that missing @NullMarked or @NullUnmarked are correctly flagged in annotations."""
5246 mock_input=MockInputApi()
5247 mock_input.files=[
5248MockFile('path/OneMissing.java',['@interface OneMissing']),
5249MockFile('path/TwoMarked.java',[
5250'@NullMarked',
5251'@interface TwoMarked {',
5252]),
5253]
5254 results= PRESUBMIT._CheckAndroidNullAwayAnnotatedClasses(mock_input,MockOutputApi())
5255 self.assertEqual(1, len(results))
Henrique Nakashima8bafbc52025-04-22 19:38:42[diff] [blame]5256 self.assertEqual('error', results[0].type)
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]5257 self.assertEqual(1, len(results[0].items))
5258 self.assertIn('OneMissing.java', results[0].items[0])
5259
5260def testDetectsInInterfaces(self):
5261"""Tests that missing @NullMarked or @NullUnmarked are correctly flagged in interfaces."""
5262 mock_input=MockInputApi()
5263 mock_input.files=[
5264MockFile('path/OneMissing.java',['interface OneMissing']),
5265MockFile('path/TwoMarked.java',[
5266'@NullMarked',
5267'interface TwoMarked {',
5268]),
5269]
5270 results= PRESUBMIT._CheckAndroidNullAwayAnnotatedClasses(mock_input,MockOutputApi())
5271 self.assertEqual(1, len(results))
Henrique Nakashima8bafbc52025-04-22 19:38:42[diff] [blame]5272 self.assertEqual('error', results[0].type)
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]5273 self.assertEqual(1, len(results[0].items))
5274 self.assertIn('OneMissing.java', results[0].items[0])
5275
Henrique Nakashimac6605432025-04-24 18:11:59[diff] [blame]5276def testOnlyChecksAddedFiles(self):
5277"""Tests that missing @NullMarked or @NullUnmarked is only flagged in newly added files."""
5278 mock_input=MockInputApi()
5279 mock_input.files=[
5280MockFile('path/OneMissing.java',['public class OneMissing'], action='M'),
5281]
5282 results= PRESUBMIT._CheckAndroidNullAwayAnnotatedClasses(mock_input,MockOutputApi())
5283 self.assertEqual(0, len(results))
5284
Henrique Nakashima224ee2482025-03-21 18:35:02[diff] [blame]5285def testExcludesTests(self):
5286"""Tests that missing @NullMarked or @NullUnmarked are not flagged in tests."""
5287 mock_input=MockInputApi()
5288 mock_input.files=[
5289MockFile('path/OneTest.java',['public class OneTest']),
5290]
5291 results= PRESUBMIT._CheckAndroidNullAwayAnnotatedClasses(mock_input,MockOutputApi())
5292 self.assertEqual(0, len(results))
5293
5294def testExcludesTestSupport(self):
5295"""Tests that missing @NullMarked or @NullUnmarked are not flagged in test support classes."""
5296 mock_input=MockInputApi()
5297 mock_input.files=[
5298MockFile('path/test/Two.java',[
5299'public class Two'
5300]),
5301]
5302 results= PRESUBMIT._CheckAndroidNullAwayAnnotatedClasses(mock_input,MockOutputApi())
5303 self.assertEqual(0, len(results))
5304
5305
Mike Dougherty1b8be712022-10-20 00:15:13[diff] [blame]5306classAssertNoJsInIosTest(unittest.TestCase):
5307def testErrorJs(self):
5308 input_api=MockInputApi()
5309 input_api.files=[
5310MockFile('components/feature/ios/resources/script.js',[]),
5311MockFile('ios/chrome/feature/resources/script.js',[]),
5312]
5313 results= PRESUBMIT.CheckNoJsInIos(input_api,MockOutputApi())
5314 self.assertEqual(1, len(results))
5315 self.assertEqual('error', results[0].type)
5316 self.assertEqual(2, len(results[0].items))
5317
5318def testNonError(self):
5319 input_api=MockInputApi()
5320 input_api.files=[
5321MockFile('chrome/resources/script.js',[]),
5322MockFile('components/feature/ios/resources/script.ts',[]),
5323MockFile('ios/chrome/feature/resources/script.ts',[]),
5324MockFile('ios/web/feature/resources/script.ts',[]),
5325MockFile('ios/third_party/script.js',[]),
5326MockFile('third_party/ios/script.js',[]),
5327]
5328 results= PRESUBMIT.CheckNoJsInIos(input_api,MockOutputApi())
5329 self.assertEqual(0, len(results))
5330
5331def testExistingFilesWarningOnly(self):
5332 input_api=MockInputApi()
5333 input_api.files=[
5334MockFile('ios/chrome/feature/resources/script.js',[], action='M'),
5335MockFile('ios/chrome/feature/resources/script2.js',[], action='D'),
5336]
5337 results= PRESUBMIT.CheckNoJsInIos(input_api,MockOutputApi())
5338 self.assertEqual(1, len(results))
5339 self.assertEqual('warning', results[0].type)
5340 self.assertEqual(1, len(results[0].items))
5341
Mike Dougherty4d1050b2023-03-14 15:59:53[diff] [blame]5342def testMovedScriptWarningOnly(self):
5343 input_api=MockInputApi()
5344 input_api.files=[
5345MockFile('ios/chrome/feature/resources/script.js',[], action='D'),
5346MockFile('ios/chrome/renamed_feature/resources/script.js',[], action='A'),
5347]
5348 results= PRESUBMIT.CheckNoJsInIos(input_api,MockOutputApi())
5349 self.assertEqual(1, len(results))
5350 self.assertEqual('warning', results[0].type)
5351 self.assertEqual(1, len(results[0].items))
5352
Yuanqing Zhu9eef02832022-12-04 14:42:17[diff] [blame]5353classCheckNoAbbreviationInPngFileNameTest(unittest.TestCase):
Yuanqing Zhu9eef02832022-12-04 14:42:17[diff] [blame]5354
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5355def testHasAbbreviation(self):
5356"""test png file names with abbreviation that fails the check"""
5357 input_api=MockInputApi()
5358 input_api.files=[
5359MockFile('image_a.png',[], action='A'),
5360MockFile('image_a_.png',[], action='A'),
5361MockFile('image_a_name.png',[], action='A'),
5362MockFile('chrome/ui/feature_name/resources/image_a.png',[],
5363 action='A'),
5364MockFile('chrome/ui/feature_name/resources/image_a_.png',[],
5365 action='A'),
5366MockFile('chrome/ui/feature_name/resources/image_a_name.png',[],
5367 action='A'),
5368]
5369 results= PRESUBMIT.CheckNoAbbreviationInPngFileName(
5370 input_api,MockOutputApi())
5371 self.assertEqual(1, len(results))
5372 self.assertEqual('error', results[0].type)
5373 self.assertEqual(len(input_api.files), len(results[0].items))
5374
5375def testNoAbbreviation(self):
5376"""test png file names without abbreviation that passes the check"""
5377 input_api=MockInputApi()
5378 input_api.files=[
5379MockFile('a.png',[], action='A'),
5380MockFile('_a.png',[], action='A'),
5381MockFile('image.png',[], action='A'),
5382MockFile('image_ab_.png',[], action='A'),
5383MockFile('image_ab_name.png',[], action='A'),
5384# These paths used to fail because `feature_a_name` matched the regex by mistake.
5385# They should pass now because the path components ahead of the file name are ignored in the check.
5386MockFile('chrome/ui/feature_a_name/resources/a.png',[],
5387 action='A'),
5388MockFile('chrome/ui/feature_a_name/resources/_a.png',[],
5389 action='A'),
5390MockFile('chrome/ui/feature_a_name/resources/image.png',[],
5391 action='A'),
5392MockFile('chrome/ui/feature_a_name/resources/image_ab_.png',[],
5393 action='A'),
5394MockFile('chrome/ui/feature_a_name/resources/image_ab_name.png',
5395[],
5396 action='A'),
5397]
5398 results= PRESUBMIT.CheckNoAbbreviationInPngFileName(
5399 input_api,MockOutputApi())
5400 self.assertEqual(0, len(results))
Yuanqing Zhu9eef02832022-12-04 14:42:17[diff] [blame]5401
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5402classCheckDanglingUntriagedTest(unittest.TestCase):
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5403
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5404def testError(self):
5405"""Test patch adding dangling pointers are reported"""
5406 mock_input_api=MockInputApi()
5407 mock_output_api=MockOutputApi()
5408
5409 mock_input_api.change.DescriptionText=lambda:"description"
5410 mock_input_api.files=[
5411MockAffectedFile(
5412 local_path="foo/foo.cc",
5413 old_contents=["raw_ptr<T>"],
5414 new_contents=["raw_ptr<T, DanglingUntriaged>"],
5415)
5416]
5417 msgs= PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5418 mock_output_api)
5419 self.assertEqual(len(msgs),1)
5420 self.assertEqual(len(msgs[0].message),10)
5421 self.assertEqual(
5422 msgs[0].message[0],
5423"Unexpected new occurrences of `DanglingUntriaged` detected. Please",
5424)
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5425
5426classCheckDanglingUntriagedTest(unittest.TestCase):
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5427
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5428def testError(self):
5429"""Test patch adding dangling pointers are reported"""
5430 mock_input_api=MockInputApi()
5431 mock_output_api=MockOutputApi()
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5432
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5433 mock_input_api.change.DescriptionText=lambda:"description"
5434 mock_input_api.files=[
5435MockAffectedFile(
5436 local_path="foo/foo.cc",
5437 old_contents=["raw_ptr<T>"],
5438 new_contents=["raw_ptr<T, DanglingUntriaged>"],
5439)
5440]
5441 msgs= PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5442 mock_output_api)
5443 self.assertEqual(len(msgs),1)
5444 self.assertTrue(
5445("Unexpected new occurrences of `DanglingUntriaged` detected"
5446in msgs[0].message))
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5447
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5448def testNonCppFile(self):
5449"""Test patch adding dangling pointers are not reported in non C++ files"""
5450 mock_input_api=MockInputApi()
5451 mock_output_api=MockOutputApi()
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5452
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5453 mock_input_api.change.DescriptionText=lambda:"description"
5454 mock_input_api.files=[
5455MockAffectedFile(
5456 local_path="foo/README.md",
5457 old_contents=[""],
5458 new_contents=["The DanglingUntriaged annotation means"],
5459)
5460]
5461 msgs= PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5462 mock_output_api)
5463 self.assertEqual(len(msgs),0)
5464
5465def testDeveloperAcknowledgeInCommitDescription(self):
5466"""Test patch adding dangling pointers, but acknowledged by the developers
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5467 aren't reported"""
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5468 mock_input_api=MockInputApi()
5469 mock_output_api=MockOutputApi()
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5470
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5471 mock_input_api.files=[
5472MockAffectedFile(
5473 local_path="foo/foo.cc",
5474 old_contents=["raw_ptr<T>"],
5475 new_contents=["raw_ptr<T, DanglingUntriaged>"],
5476)
5477]
5478 mock_input_api.change.DescriptionText=lambda:(
5479"DanglingUntriaged-notes: Sorry about this!")
5480 msgs= PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5481 mock_output_api)
5482 self.assertEqual(len(msgs),0)
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5483
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5484def testDeveloperAcknowledgeInCommitFooter(self):
5485"""Test patch adding dangling pointers, but acknowledged by the developers
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5486 aren't reported"""
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5487 mock_input_api=MockInputApi()
5488 mock_output_api=MockOutputApi()
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5489
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5490 mock_input_api.files=[
5491MockAffectedFile(
5492 local_path="foo/foo.cc",
5493 old_contents=["raw_ptr<T>"],
5494 new_contents=["raw_ptr<T, DanglingUntriaged>"],
5495)
5496]
5497 mock_input_api.change.DescriptionText=lambda:"description"
5498 mock_input_api.change.footers["DanglingUntriaged-notes"]=["Sorry!"]
5499 msgs= PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5500 mock_output_api)
5501 self.assertEqual(len(msgs),0)
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5502
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5503def testCongrats(self):
5504"""Test the presubmit congrats users removing dangling pointers"""
5505 mock_input_api=MockInputApi()
5506 mock_output_api=MockOutputApi()
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5507
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5508 mock_input_api.files=[
5509MockAffectedFile(
5510 local_path="foo/foo.cc",
5511 old_contents=["raw_ptr<T, DanglingUntriaged>"],
5512 new_contents=["raw_ptr<T>"],
5513)
5514]
5515 mock_input_api.change.DescriptionText=lambda:(
5516"This patch fixes some DanglingUntriaged pointers!")
5517 msgs= PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5518 mock_output_api)
5519 self.assertEqual(len(msgs),1)
5520 self.assertTrue(
5521"DanglingUntriaged pointers removed: 1"in msgs[0].message)
5522 self.assertTrue("Thank you!"in msgs[0].message)
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5523
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5524def testRenameFile(self):
5525"""Patch that we do not warn about DanglingUntriaged when moving files"""
5526 mock_input_api=MockInputApi()
5527 mock_output_api=MockOutputApi()
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5528
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5529 mock_input_api.files=[
5530MockAffectedFile(
5531 local_path="foo/foo.cc",
5532 old_contents=["raw_ptr<T, DanglingUntriaged>"],
5533 new_contents=[""],
5534 action="D",
5535),
5536MockAffectedFile(
5537 local_path="foo/foo.cc",
5538 old_contents=[""],
5539 new_contents=["raw_ptr<T, DanglingUntriaged>"],
5540 action="A",
5541),
5542]
5543 mock_input_api.change.DescriptionText=lambda:(
5544"This patch moves files")
5545 msgs= PRESUBMIT.CheckDanglingUntriaged(mock_input_api,
5546 mock_output_api)
5547 self.assertEqual(len(msgs),0)
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5548
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5549classCheckInlineConstexprDefinitionsInHeadersTest(unittest.TestCase):
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5550
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5551def testNoInlineConstexprInHeaderFile(self):
5552"""Tests that non-inlined constexpr variables in headers fail the test."""
5553 input_api=MockInputApi()
5554 input_api.files=[
5555MockAffectedFile('src/constants.h',
5556['constexpr int kVersion = 5;'])
5557]
5558 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5559 input_api,MockOutputApi())
5560 self.assertEqual(1, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5561
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5562def testNoInlineConstexprInHeaderFileInitializedFromFunction(self):
5563"""Tests that non-inlined constexpr header variables that are initialized from a function fail."""
5564 input_api=MockInputApi()
5565 input_api.files=[
5566MockAffectedFile('src/constants.h',
5567['constexpr int kVersion = GetVersion();'])
5568]
5569 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5570 input_api,MockOutputApi())
5571 self.assertEqual(1, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5572
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5573def testNoInlineConstexprInHeaderFileInitializedWithExpression(self):
5574"""Tests that non-inlined constexpr header variables initialized with an expression fail."""
5575 input_api=MockInputApi()
5576 input_api.files=[
5577MockAffectedFile('src/constants.h',
5578['constexpr int kVersion = (4 + 5)*3;'])
5579]
5580 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5581 input_api,MockOutputApi())
5582 self.assertEqual(1, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5583
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5584def testNoInlineConstexprInHeaderFileBraceInitialized(self):
5585"""Tests that non-inlined constexpr header variables that are brace-initialized fail."""
5586 input_api=MockInputApi()
5587 input_api.files=[
5588MockAffectedFile('src/constants.h',['constexpr int kVersion{5};'])
5589]
5590 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5591 input_api,MockOutputApi())
5592 self.assertEqual(1, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5593
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5594def testNoInlineConstexprInHeaderWithAttribute(self):
5595"""Tests that non-inlined constexpr header variables that have compiler attributes fail."""
5596 input_api=MockInputApi()
5597 input_api.files=[
5598MockAffectedFile('src/constants.h',
5599['constexpr [[maybe_unused]] int kVersion{5};'])
5600]
5601 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5602 input_api,MockOutputApi())
5603 self.assertEqual(1, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5604
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5605def testInlineConstexprInHeaderWithAttribute(self):
5606"""Tests that inlined constexpr header variables that have compiler attributes pass."""
5607 input_api=MockInputApi()
5608 input_api.files=[
5609MockAffectedFile(
5610'src/constants.h',
5611['inline constexpr [[maybe_unused]] int kVersion{5};']),
5612MockAffectedFile(
5613'src/constants.h',
5614['constexpr inline [[maybe_unused]] int kVersion{5};']),
5615MockAffectedFile(
5616'src/constants.h',
5617['inline constexpr [[maybe_unused]] inline int kVersion{5};'])
5618]
5619 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5620 input_api,MockOutputApi())
5621 self.assertEqual(0, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5622
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5623def testNoInlineConstexprInHeaderFileMultipleLines(self):
5624"""Tests that non-inlined constexpr header variable definitions spanning multiple lines fail."""
5625 input_api=MockInputApi()
5626 lines=[
5627'constexpr char kLongName =',
5628' "This is a very long name of something.";'
5629]
5630 input_api.files=[MockAffectedFile('src/constants.h', lines)]
5631 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5632 input_api,MockOutputApi())
5633 self.assertEqual(1, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5634
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5635def testNoInlineConstexprInCCFile(self):
5636"""Tests that non-inlined constexpr variables in .cc files pass the test."""
5637 input_api=MockInputApi()
5638 input_api.files=[
5639MockAffectedFile('src/implementation.cc',
5640['constexpr int kVersion = 5;'])
5641]
5642 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5643 input_api,MockOutputApi())
5644 self.assertEqual(0, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5645
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5646def testInlineConstexprInHeaderFile(self):
5647"""Tests that inlined constexpr variables in header files pass the test."""
5648 input_api=MockInputApi()
5649 input_api.files=[
5650MockAffectedFile('src/constants.h',
5651['constexpr inline int kX = 5;']),
5652MockAffectedFile('src/version.h',
5653['inline constexpr float kY = 5.0f;'])
5654]
5655 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5656 input_api,MockOutputApi())
5657 self.assertEqual(0, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5658
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5659def testConstexprStandaloneFunctionInHeaderFile(self):
5660"""Tests that non-inlined constexpr functions in headers pass the test."""
5661 input_api=MockInputApi()
5662 input_api.files=[
5663MockAffectedFile('src/helpers.h',['constexpr int GetVersion();'])
5664]
5665 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5666 input_api,MockOutputApi())
5667 self.assertEqual(0, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5668
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5669def testConstexprWithAbseilAttributeInHeader(self):
5670"""Tests that non-inlined constexpr variables with Abseil-type prefixes in headers fail."""
5671 input_api=MockInputApi()
5672 input_api.files=[
5673MockAffectedFile('src/helpers.h',
5674['ABSL_FOOFOO constexpr int i = 5;'])
5675]
5676 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5677 input_api,MockOutputApi())
5678 self.assertEqual(1, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5679
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5680def testInlineConstexprWithAbseilAttributeInHeader(self):
5681"""Tests that inlined constexpr variables with Abseil-type prefixes in headers pass."""
5682 input_api=MockInputApi()
5683 input_api.files=[
5684MockAffectedFile('src/helpers.h',
5685['constexpr ABSL_FOO inline int i = 5;'])
5686]
5687 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5688 input_api,MockOutputApi())
5689 self.assertEqual(0, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5690
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5691def testConstexprWithClangAttributeInHeader(self):
5692"""Tests that non-inlined constexpr variables with attributes with colons in headers fail."""
5693 input_api=MockInputApi()
5694 input_api.files=[
5695MockAffectedFile('src/helpers.h',
5696['[[clang::someattribute]] constexpr int i = 5;'])
5697]
5698 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5699 input_api,MockOutputApi())
5700 self.assertEqual(1, len(warnings))
Jan Keitel77be7522023-10-12 20:40:49[diff] [blame]5701
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5702def testInlineConstexprWithClangAttributeInHeader(self):
5703"""Tests that inlined constexpr variables with attributes with colons in headers pass."""
5704 input_api=MockInputApi()
5705 input_api.files=[
5706MockAffectedFile(
5707'src/helpers.h',
5708['constexpr [[clang::someattribute]] inline int i = 5;'])
5709]
5710 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5711 input_api,MockOutputApi())
5712 self.assertEqual(0, len(warnings))
Arthur Sonzogni7109bd32023-10-03 10:34:42[diff] [blame]5713
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5714def testNoExplicitInlineConstexprInsideClassInHeaderFile(self):
5715"""Tests that non-inlined constexpr class members pass the test."""
5716 input_api=MockInputApi()
5717 lines=[
5718'class SomeClass {',' public:',
5719' static constexpr kVersion = 5;','};'
5720]
5721 input_api.files=[MockAffectedFile('src/class.h', lines)]
5722 warnings= PRESUBMIT.CheckInlineConstexprDefinitionsInHeaders(
5723 input_api,MockOutputApi())
5724 self.assertEqual(0, len(warnings))
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]5725
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5726def testTodoBugReferencesWithOldBugId(self):
5727"""Tests that an old monorail bug ID in a TODO fails."""
5728 input_api=MockInputApi()
5729 input_api.files=[
5730MockAffectedFile('src/helpers.h',['// TODO(crbug.com/12345)'])
5731]
5732 warnings= PRESUBMIT.CheckTodoBugReferences(input_api,MockOutputApi())
5733 self.assertEqual(1, len(warnings))
5734
5735def testTodoBugReferencesWithUpdatedBugId(self):
5736"""Tests that a new issue tracker bug ID in a TODO passes."""
5737 input_api=MockInputApi()
5738 input_api.files=[
5739MockAffectedFile('src/helpers.h',['// TODO(crbug.com/40781525)'])
5740]
5741 warnings= PRESUBMIT.CheckTodoBugReferences(input_api,MockOutputApi())
5742 self.assertEqual(0, len(warnings))
Alison Galed6b25fe2024-04-17 13:59:04[diff] [blame]5743
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5744classCheckDeprecatedSyncConsentFunctionsTest(unittest.TestCase):
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5745"""Test the presubmit for deprecated ConsentLevel::kSync functions."""
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5746
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5747def testCppMobilePlatformPath(self):
5748 input_api=MockInputApi()
5749 input_api.files=[
5750MockFile('chrome/browser/android/file.cc',['OtherFunction']),
5751MockFile('chrome/android/file.cc',['HasSyncConsent']),
5752MockFile('ios/file.mm',['CanSyncFeatureStart']),
5753MockFile('components/foo/ios/file.cc',['IsSyncFeatureEnabled']),
5754MockFile('components/foo/delegate_android.cc',
5755['IsSyncFeatureActive']),
5756MockFile('components/foo/delegate_ios.cc',
5757['IsSyncFeatureActive']),
5758MockFile('components/foo/android_delegate.cc',
5759['IsSyncFeatureActive']),
5760MockFile('components/foo/ios_delegate.cc',
5761['IsSyncFeatureActive']),
5762]
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5763
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5764 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5765
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]5766 self.assertEqual(7, len(results))
5767 self.assertTrue(all('chrome/browser/android/file.cc'notin r.messagefor rin results))
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5768 self.assertTrue('chrome/android/file.cc'in results[0].message),
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]5769 self.assertTrue('ios/file.mm'in results[1].message),
5770 self.assertTrue('components/foo/ios/file.cc'in results[2].message),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5771 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]5772'components/foo/delegate_android.cc'in results[3].message),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5773 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]5774'components/foo/delegate_ios.cc'in results[4].message),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5775 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]5776'components/foo/android_delegate.cc'in results[5].message),
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5777 self.assertTrue(
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]5778'components/foo/ios_delegate.cc'in results[6].message),
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5779
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5780def testCppNonMobilePlatformPath(self):
5781 input_api=MockInputApi()
5782 input_api.files=[
5783MockFile('chrome/browser/file.cc',['HasSyncConsent']),
5784MockFile('bios/file.cc',['HasSyncConsent']),
5785MockFile('components/kiosk/file.cc',['HasSyncConsent']),
5786]
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5787
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5788 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5789
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5790 self.assertEqual(0, len(results))
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5791
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5792def testJavaPath(self):
5793 input_api=MockInputApi()
5794 input_api.files=[
5795MockFile('components/foo/file1.java',['otherFunction']),
5796MockFile('components/foo/file2.java',['hasSyncConsent']),
5797MockFile('chrome/foo/file3.java',['canSyncFeatureStart']),
5798MockFile('chrome/foo/file4.java',['isSyncFeatureEnabled']),
5799MockFile('chrome/foo/file5.java',['isSyncFeatureActive']),
5800]
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5801
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5802 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5803
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]5804 self.assertEqual(4, len(results))
5805 self.assertTrue(all('components/foo/file1.java'notin r.messagefor rin results))
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5806 self.assertTrue('components/foo/file2.java'in results[0].message),
Ben Pastenee79d66112025-04-23 19:46:15[diff] [blame]5807 self.assertTrue('chrome/foo/file3.java'in results[1].message),
5808 self.assertTrue('chrome/foo/file4.java'in results[2].message),
5809 self.assertTrue('chrome/foo/file5.java'in results[3].message),
Victor Hugo Vianna Silvadbe81542024-05-21 11:09:15[diff] [blame]5810
5811
Erik Chen1396bbe2025-01-27 23:39:36[diff] [blame]5812classCheckAnonymousNamespaceTest(unittest.TestCase):
5813"""Test the presubmit for anonymous namespaces."""
5814
5815def testAnonymousNamespace(self):
5816 input_api=MockInputApi()
5817 input_api.files=[
5818MockFile('chrome/test.h',['namespace {']),
5819MockFile('chrome/test.cc',['namespace {']),
5820MockFile('chrome/test.java',['namespace {']),
5821MockFile('chrome/test.cpp',['namespace {']),
5822MockFile('chrome/test.txt',['namespace {']),
5823]
5824
5825 results= PRESUBMIT.CheckNoBannedFunctions(input_api,MockOutputApi())
5826
5827 self.assertEqual(1, len(results))
5828 self.assertTrue(
5829'chrome/test.h'in results[0].message),
5830 self.assertFalse(
5831'chrome/test.cc'in results[0].message),
5832 self.assertFalse(
5833'chrome/test.java'in results[0].message),
5834 self.assertFalse(
5835'chrome/test.cpp'in results[0].message),
5836 self.assertFalse(
5837'chrome/test.txt'in results[0].message),
5838
5839
marja@chromium.org2299dcf2012-11-15 19:56:24[diff] [blame]5840if __name__=='__main__':
Daniel Cheng566634ff2024-06-29 14:56:53[diff] [blame]5841 unittest.main()

[8]ページ先頭

©2009-2025 Movatter.jp