blob: 5b8a6de70471b3e43debec9458245b1d18719856 [file] [log] [blame]
William Liua296a002022-08-08 15:22:291#!/usr/bin/env python3
Avi Drissman73a09d12022-09-08 20:33:382# Copyright 2012 The Chromium Authors
Tom Andersone70019692019-02-06 01:38:043# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Tests for checkdeps.
7"""
8
9import os
10import unittest
11
12
13import builddeps
14import checkdeps
15import results
16
17
18class CheckDepsTest(unittest.TestCase):
19
20 def setUp(self):
21 self.deps_checker = checkdeps.DepsChecker(
22 being_tested=True,
John Budorickfd4b2b632019-05-13 19:54:0623 base_directory=os.path.join(os.path.dirname(__file__), '..', '..'))
Tom Andersone70019692019-02-06 01:38:0424
25 def ImplTestRegularCheckDepsRun(self, ignore_temp_rules, skip_tests):
26 self.deps_checker._ignore_temp_rules = ignore_temp_rules
27 self.deps_checker._skip_tests = skip_tests
28 self.deps_checker.CheckDirectory(
29 os.path.join(self.deps_checker.base_directory,
John Budorickfd4b2b632019-05-13 19:54:0630 'buildtools/checkdeps/testdata'))
Tom Andersone70019692019-02-06 01:38:0431
32 problems = self.deps_checker.results_formatter.GetResults()
Tom Andersone70019692019-02-06 01:38:0433
34 def VerifySubstringsInProblems(key_path, substrings_in_sequence):
35 """Finds the problem in |problems| that contains |key_path|,
36 then verifies that each of |substrings_in_sequence| occurs in
37 that problem, in the order they appear in
38 |substrings_in_sequence|.
39 """
40 found = False
41 key_path = os.path.normpath(key_path)
42 for problem in problems:
43 index = problem.find(key_path)
44 if index != -1:
Andrew Grievecabf1202024-11-25 22:22:0545 if substrings_in_sequence is None:
46 self.fail(
47 f'Expected no problems for {key_path}, but found: {problem}')
48
Tom Andersone70019692019-02-06 01:38:0449 for substring in substrings_in_sequence:
50 index = problem.find(substring, index + 1)
Fabrice de Ganse06b1fa2021-06-24 02:10:4951 self.assertTrue(index != -1, '%s in %s' % (substring, problem))
Tom Andersone70019692019-02-06 01:38:0452 found = True
53 break
Andrew Grievecabf1202024-11-25 22:22:0554 if not found and substrings_in_sequence is not None:
Tom Andersone70019692019-02-06 01:38:0455 self.fail('Found no problem for file %s' % key_path)
56
Andrew Grievecabf1202024-11-25 22:22:0557 def VerifyNoProblems(key_path):
58 VerifySubstringsInProblems(key_path, None)
59
Tom Andersone70019692019-02-06 01:38:0460 if ignore_temp_rules:
61 VerifySubstringsInProblems('testdata/allowed/test.h',
John Budorickfd4b2b632019-05-13 19:54:0662 ['-buildtools/checkdeps/testdata/disallowed',
Tom Andersone70019692019-02-06 01:38:0463 'temporarily_allowed.h',
64 '-third_party/explicitly_disallowed',
65 'Because of no rule applying'])
66 else:
67 VerifySubstringsInProblems('testdata/allowed/test.h',
John Budorickfd4b2b632019-05-13 19:54:0668 ['-buildtools/checkdeps/testdata/disallowed',
Tom Andersone70019692019-02-06 01:38:0469 '-third_party/explicitly_disallowed',
70 'Because of no rule applying'])
71
72 VerifySubstringsInProblems('testdata/disallowed/test.h',
73 ['-third_party/explicitly_disallowed',
74 'Because of no rule applying',
75 'Because of no rule applying'])
76 VerifySubstringsInProblems('disallowed/allowed/test.h',
77 ['-third_party/explicitly_disallowed',
78 'Because of no rule applying',
79 'Because of no rule applying'])
80 VerifySubstringsInProblems('testdata/noparent/test.h',
81 ['allowed/bad.h',
82 'Because of no rule applying'])
Andrew Grievecabf1202024-11-25 22:22:0583 VerifySubstringsInProblems('testdata/requires_review_users/usage.cc', [
84 'testdata/requires_review/sub/foo.h"',
85 'requires_review/sub", which is marked'])
86 VerifyNoProblems('requires_review_users/sub/includes_okay/usage.cc')
87 VerifySubstringsInProblems(
88 'requires_review_users/sub/includes_only_sub/usage.cc',
89 [
90 'testdata/requires_review/sub/foo.h"',
91 'requires_review/sub", which is',
92 'testdata/requires_review/sub/inherited/foo.h"',
93 'testdata/requires_review/sub/sub/inherited/bar.h"',
94 'requires_review/sub/sub", which is',
95 ])
Tom Andersone70019692019-02-06 01:38:0496
Andrew Grievecabf1202024-11-25 22:22:0597 if skip_tests:
98 VerifyNoProblems('allowed/not_a_test.cc')
99 else:
Tom Andersone70019692019-02-06 01:38:04100 VerifySubstringsInProblems('allowed/not_a_test.cc',
John Budorickfd4b2b632019-05-13 19:54:06101 ['-buildtools/checkdeps/testdata/disallowed'])
Tom Andersone70019692019-02-06 01:38:04102
103 def testRegularCheckDepsRun(self):
104 self.ImplTestRegularCheckDepsRun(False, False)
105
106 def testRegularCheckDepsRunIgnoringTempRules(self):
107 self.ImplTestRegularCheckDepsRun(True, False)
108
109 def testRegularCheckDepsRunSkipTests(self):
110 self.ImplTestRegularCheckDepsRun(False, True)
111
112 def testRegularCheckDepsRunIgnoringTempRulesSkipTests(self):
113 self.ImplTestRegularCheckDepsRun(True, True)
114
115 def CountViolations(self, ignore_temp_rules):
116 self.deps_checker._ignore_temp_rules = ignore_temp_rules
117 self.deps_checker.results_formatter = results.CountViolationsFormatter()
118 self.deps_checker.CheckDirectory(
119 os.path.join(self.deps_checker.base_directory,
John Budorickfd4b2b632019-05-13 19:54:06120 'buildtools/checkdeps/testdata'))
Tom Andersone70019692019-02-06 01:38:04121 return self.deps_checker.results_formatter.GetResults()
122
123 def testCountViolations(self):
Andrew Grievecabf1202024-11-25 22:22:05124 self.assertEqual('16', self.CountViolations(False))
Tom Andersone70019692019-02-06 01:38:04125
126 def testCountViolationsIgnoringTempRules(self):
Andrew Grievecabf1202024-11-25 22:22:05127 self.assertEqual('17', self.CountViolations(True))
Tom Andersone70019692019-02-06 01:38:04128
129 def testCountViolationsWithRelativePath(self):
130 self.deps_checker.results_formatter = results.CountViolationsFormatter()
131 self.deps_checker.CheckDirectory(
John Budorickfd4b2b632019-05-13 19:54:06132 os.path.join('buildtools', 'checkdeps', 'testdata', 'allowed'))
Andrew Grievecabf1202024-11-25 22:22:05133 self.assertEqual('5', self.deps_checker.results_formatter.GetResults())
Tom Andersone70019692019-02-06 01:38:04134
135 def testTempRulesGenerator(self):
136 self.deps_checker.results_formatter = results.TemporaryRulesFormatter()
137 self.deps_checker.CheckDirectory(
138 os.path.join(self.deps_checker.base_directory,
John Budorickfd4b2b632019-05-13 19:54:06139 'buildtools/checkdeps/testdata/allowed'))
Tom Andersone70019692019-02-06 01:38:04140 temp_rules = self.deps_checker.results_formatter.GetResults()
Andrew Grievecabf1202024-11-25 22:22:05141 expected = [' "!/does_not_exist.h",',
142 ' "!buildtools/checkdeps/testdata/disallowed/bad.h",',
Fabrice de Ganse06b1fa2021-06-24 02:10:49143 ' "!buildtools/checkdeps/testdata/disallowed/teststuff/bad.h",',
144 ' "!third_party/explicitly_disallowed/bad.h",',
145 ' "!third_party/no_rule/bad.h",']
146 self.assertEqual(expected, temp_rules)
Tom Andersone70019692019-02-06 01:38:04147
Rileya95a72ef2024-05-08 15:00:00148 @unittest.skipIf(os.getcwd().startswith('/google/cog/cloud'),
149 "Skip if not git")
Tom Andersone70019692019-02-06 01:38:04150 def testBadBaseDirectoryNotCheckoutRoot(self):
151 # This assumes git. It's not a valid test if buildtools is fetched via svn.
152 with self.assertRaises(builddeps.DepsBuilderError):
153 checkdeps.DepsChecker(being_tested=True,
154 base_directory=os.path.dirname(__file__))
155
156 def testCheckAddedIncludesAllGood(self):
157 problems = self.deps_checker.CheckAddedCppIncludes(
John Budorickfd4b2b632019-05-13 19:54:06158 [['buildtools/checkdeps/testdata/allowed/test.cc',
159 ['#include "buildtools/checkdeps/testdata/allowed/good.h"',
160 '#include "buildtools/checkdeps/testdata/disallowed/allowed/good.h"']
Tom Andersone70019692019-02-06 01:38:04161 ]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49162 self.assertFalse(problems)
Tom Andersone70019692019-02-06 01:38:04163
164 def testCheckAddedIncludesManyGarbageLines(self):
165 garbage_lines = ["My name is Sam%d\n" % num for num in range(50)]
166 problems = self.deps_checker.CheckAddedCppIncludes(
John Budorickfd4b2b632019-05-13 19:54:06167 [['buildtools/checkdeps/testdata/allowed/test.cc', garbage_lines]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49168 self.assertFalse(problems)
Tom Andersone70019692019-02-06 01:38:04169
170 def testCheckAddedIncludesNoRule(self):
171 problems = self.deps_checker.CheckAddedCppIncludes(
John Budorickfd4b2b632019-05-13 19:54:06172 [['buildtools/checkdeps/testdata/allowed/test.cc',
Tom Andersone70019692019-02-06 01:38:04173 ['#include "no_rule_for_this/nogood.h"']
174 ]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49175 self.assertTrue(problems)
Tom Andersone70019692019-02-06 01:38:04176
177 def testCheckAddedIncludesSkippedDirectory(self):
178 problems = self.deps_checker.CheckAddedCppIncludes(
John Budorickfd4b2b632019-05-13 19:54:06179 [['buildtools/checkdeps/testdata/disallowed/allowed/skipped/test.cc',
Tom Andersone70019692019-02-06 01:38:04180 ['#include "whatever/whocares.h"']
181 ]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49182 self.assertFalse(problems)
Tom Andersone70019692019-02-06 01:38:04183
184 def testCheckAddedIncludesTempAllowed(self):
185 problems = self.deps_checker.CheckAddedCppIncludes(
John Budorickfd4b2b632019-05-13 19:54:06186 [['buildtools/checkdeps/testdata/allowed/test.cc',
187 ['#include "buildtools/checkdeps/testdata/disallowed/temporarily_allowed.h"']
Tom Andersone70019692019-02-06 01:38:04188 ]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49189 self.assertTrue(problems)
Tom Andersone70019692019-02-06 01:38:04190
191 def testCopyIsDeep(self):
192 # Regression test for a bug where we were making shallow copies of
193 # Rules objects and therefore all Rules objects shared the same
194 # dictionary for specific rules.
195 #
196 # The first pair should bring in a rule from testdata/allowed/DEPS
197 # into that global dictionary that allows the
198 # temp_allowed_for_tests.h file to be included in files ending
199 # with _unittest.cc, and the second pair should completely fail
200 # once the bug is fixed, but succeed (with a temporary allowance)
201 # if the bug is in place.
202 problems = self.deps_checker.CheckAddedCppIncludes(
John Budorickfd4b2b632019-05-13 19:54:06203 [['buildtools/checkdeps/testdata/allowed/test.cc',
204 ['#include "buildtools/checkdeps/testdata/disallowed/temporarily_allowed.h"']
Tom Andersone70019692019-02-06 01:38:04205 ],
John Budorickfd4b2b632019-05-13 19:54:06206 ['buildtools/checkdeps/testdata/disallowed/foo_unittest.cc',
207 ['#include "buildtools/checkdeps/testdata/bongo/temp_allowed_for_tests.h"']
Tom Andersone70019692019-02-06 01:38:04208 ]])
209 # With the bug in place, there would be two problems reported, and
210 # the second would be for foo_unittest.cc.
Fabrice de Ganse06b1fa2021-06-24 02:10:49211 self.assertTrue(len(problems) == 1)
212 self.assertTrue(problems[0][0].endswith('/test.cc'))
Tom Andersone70019692019-02-06 01:38:04213
214 def testTraversalIsOrdered(self):
215 dirs_traversed = []
John Budorickfd4b2b632019-05-13 19:54:06216 for rules, filenames in self.deps_checker.GetAllRulesAndFiles(dir_name='buildtools'):
Fabrice de Ganse06b1fa2021-06-24 02:10:49217 self.assertEqual(type(filenames), list)
218 self.assertEqual(filenames, sorted(filenames))
Tom Andersone70019692019-02-06 01:38:04219 if filenames:
220 dir_names = set(os.path.dirname(file) for file in filenames)
Fabrice de Ganse06b1fa2021-06-24 02:10:49221 self.assertEqual(1, len(dir_names))
Tom Andersone70019692019-02-06 01:38:04222 dirs_traversed.append(dir_names.pop())
Fabrice de Ganse06b1fa2021-06-24 02:10:49223 self.assertEqual(dirs_traversed, sorted(dirs_traversed))
Tom Andersone70019692019-02-06 01:38:04224
225 def testCheckPartialImportsAreAllowed(self):
226 problems = self.deps_checker.CheckAddedProtoImports(
John Budorickfd4b2b632019-05-13 19:54:06227 [['buildtools/checkdeps/testdata/test.proto',
Tom Andersone70019692019-02-06 01:38:04228 ['import "no_rule_for_this/nogood.proto"']
229 ]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49230 self.assertFalse(problems)
Tom Andersone70019692019-02-06 01:38:04231
232 def testCheckAddedFullPathImportsAllowed(self):
Tom Andersone70019692019-02-06 01:38:04233 problems = self.deps_checker.CheckAddedProtoImports(
John Budorickfd4b2b632019-05-13 19:54:06234 [['buildtools/checkdeps/testdata/test.proto',
235 ['import "buildtools/checkdeps/testdata/allowed/good.proto"',
236 'import "buildtools/checkdeps/testdata/disallowed/sub_folder/good.proto"']
Tom Andersone70019692019-02-06 01:38:04237 ]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49238 self.assertFalse(problems)
Tom Andersone70019692019-02-06 01:38:04239
240 def testCheckAddedFullPathImportsDisallowed(self):
241 problems = self.deps_checker.CheckAddedProtoImports(
John Budorickfd4b2b632019-05-13 19:54:06242 [['buildtools/checkdeps/testdata/test.proto',
243 ['import "buildtools/checkdeps/testdata/disallowed/bad.proto"']
Tom Andersone70019692019-02-06 01:38:04244 ]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49245 self.assertTrue(problems)
Tom Andersone70019692019-02-06 01:38:04246
247 def testCheckAddedFullPathImportsManyGarbageLines(self):
248 garbage_lines = ["My name is Sam%d\n" % num for num in range(50)]
249 problems = self.deps_checker.CheckAddedProtoImports(
John Budorickfd4b2b632019-05-13 19:54:06250 [['buildtools/checkdeps/testdata/test.proto',
Tom Andersone70019692019-02-06 01:38:04251 garbage_lines]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49252 self.assertFalse(problems)
Tom Andersone70019692019-02-06 01:38:04253
254 def testCheckAddedIncludesNoRuleFullPath(self):
255 problems = self.deps_checker.CheckAddedProtoImports(
John Budorickfd4b2b632019-05-13 19:54:06256 [['buildtools/checkdeps/testdata/test.proto',
257 ['import "tools/some.proto"']
Tom Andersone70019692019-02-06 01:38:04258 ]])
Fabrice de Ganse06b1fa2021-06-24 02:10:49259 self.assertTrue(problems)
Tom Andersone70019692019-02-06 01:38:04260
261if __name__ == '__main__':
262 unittest.main()