checkdeps_test.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2012 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """Tests for checkdeps.
  6. """
  7. import os
  8. import unittest
  9. import builddeps
  10. import checkdeps
  11. import results
  12. class CheckDepsTest(unittest.TestCase):
  13. def setUp(self):
  14. self.deps_checker = checkdeps.DepsChecker(
  15. being_tested=True,
  16. base_directory=os.path.join(os.path.dirname(__file__), '..', '..'))
  17. def ImplTestRegularCheckDepsRun(self, ignore_temp_rules, skip_tests):
  18. self.deps_checker._ignore_temp_rules = ignore_temp_rules
  19. self.deps_checker._skip_tests = skip_tests
  20. self.deps_checker.CheckDirectory(
  21. os.path.join(self.deps_checker.base_directory,
  22. 'buildtools/checkdeps/testdata'))
  23. problems = self.deps_checker.results_formatter.GetResults()
  24. if skip_tests:
  25. self.assertEqual(4, len(problems))
  26. else:
  27. self.assertEqual(5, len(problems))
  28. def VerifySubstringsInProblems(key_path, substrings_in_sequence):
  29. """Finds the problem in |problems| that contains |key_path|,
  30. then verifies that each of |substrings_in_sequence| occurs in
  31. that problem, in the order they appear in
  32. |substrings_in_sequence|.
  33. """
  34. found = False
  35. key_path = os.path.normpath(key_path)
  36. for problem in problems:
  37. index = problem.find(key_path)
  38. if index != -1:
  39. for substring in substrings_in_sequence:
  40. index = problem.find(substring, index + 1)
  41. self.assertTrue(index != -1, '%s in %s' % (substring, problem))
  42. found = True
  43. break
  44. if not found:
  45. self.fail('Found no problem for file %s' % key_path)
  46. if ignore_temp_rules:
  47. VerifySubstringsInProblems('testdata/allowed/test.h',
  48. ['-buildtools/checkdeps/testdata/disallowed',
  49. 'temporarily_allowed.h',
  50. '-third_party/explicitly_disallowed',
  51. 'Because of no rule applying'])
  52. else:
  53. VerifySubstringsInProblems('testdata/allowed/test.h',
  54. ['-buildtools/checkdeps/testdata/disallowed',
  55. '-third_party/explicitly_disallowed',
  56. 'Because of no rule applying'])
  57. VerifySubstringsInProblems('testdata/disallowed/test.h',
  58. ['-third_party/explicitly_disallowed',
  59. 'Because of no rule applying',
  60. 'Because of no rule applying'])
  61. VerifySubstringsInProblems('disallowed/allowed/test.h',
  62. ['-third_party/explicitly_disallowed',
  63. 'Because of no rule applying',
  64. 'Because of no rule applying'])
  65. VerifySubstringsInProblems('testdata/noparent/test.h',
  66. ['allowed/bad.h',
  67. 'Because of no rule applying'])
  68. if not skip_tests:
  69. VerifySubstringsInProblems('allowed/not_a_test.cc',
  70. ['-buildtools/checkdeps/testdata/disallowed'])
  71. def testRegularCheckDepsRun(self):
  72. self.ImplTestRegularCheckDepsRun(False, False)
  73. def testRegularCheckDepsRunIgnoringTempRules(self):
  74. self.ImplTestRegularCheckDepsRun(True, False)
  75. def testRegularCheckDepsRunSkipTests(self):
  76. self.ImplTestRegularCheckDepsRun(False, True)
  77. def testRegularCheckDepsRunIgnoringTempRulesSkipTests(self):
  78. self.ImplTestRegularCheckDepsRun(True, True)
  79. def CountViolations(self, ignore_temp_rules):
  80. self.deps_checker._ignore_temp_rules = ignore_temp_rules
  81. self.deps_checker.results_formatter = results.CountViolationsFormatter()
  82. self.deps_checker.CheckDirectory(
  83. os.path.join(self.deps_checker.base_directory,
  84. 'buildtools/checkdeps/testdata'))
  85. return self.deps_checker.results_formatter.GetResults()
  86. def testCountViolations(self):
  87. self.assertEqual('11', self.CountViolations(False))
  88. def testCountViolationsIgnoringTempRules(self):
  89. self.assertEqual('12', self.CountViolations(True))
  90. def testCountViolationsWithRelativePath(self):
  91. self.deps_checker.results_formatter = results.CountViolationsFormatter()
  92. self.deps_checker.CheckDirectory(
  93. os.path.join('buildtools', 'checkdeps', 'testdata', 'allowed'))
  94. self.assertEqual('4', self.deps_checker.results_formatter.GetResults())
  95. def testTempRulesGenerator(self):
  96. self.deps_checker.results_formatter = results.TemporaryRulesFormatter()
  97. self.deps_checker.CheckDirectory(
  98. os.path.join(self.deps_checker.base_directory,
  99. 'buildtools/checkdeps/testdata/allowed'))
  100. temp_rules = self.deps_checker.results_formatter.GetResults()
  101. expected = [' "!buildtools/checkdeps/testdata/disallowed/bad.h",',
  102. ' "!buildtools/checkdeps/testdata/disallowed/teststuff/bad.h",',
  103. ' "!third_party/explicitly_disallowed/bad.h",',
  104. ' "!third_party/no_rule/bad.h",']
  105. self.assertEqual(expected, temp_rules)
  106. def testBadBaseDirectoryNotCheckoutRoot(self):
  107. # This assumes git. It's not a valid test if buildtools is fetched via svn.
  108. with self.assertRaises(builddeps.DepsBuilderError):
  109. checkdeps.DepsChecker(being_tested=True,
  110. base_directory=os.path.dirname(__file__))
  111. def testCheckAddedIncludesAllGood(self):
  112. problems = self.deps_checker.CheckAddedCppIncludes(
  113. [['buildtools/checkdeps/testdata/allowed/test.cc',
  114. ['#include "buildtools/checkdeps/testdata/allowed/good.h"',
  115. '#include "buildtools/checkdeps/testdata/disallowed/allowed/good.h"']
  116. ]])
  117. self.assertFalse(problems)
  118. def testCheckAddedIncludesManyGarbageLines(self):
  119. garbage_lines = ["My name is Sam%d\n" % num for num in range(50)]
  120. problems = self.deps_checker.CheckAddedCppIncludes(
  121. [['buildtools/checkdeps/testdata/allowed/test.cc', garbage_lines]])
  122. self.assertFalse(problems)
  123. def testCheckAddedIncludesNoRule(self):
  124. problems = self.deps_checker.CheckAddedCppIncludes(
  125. [['buildtools/checkdeps/testdata/allowed/test.cc',
  126. ['#include "no_rule_for_this/nogood.h"']
  127. ]])
  128. self.assertTrue(problems)
  129. def testCheckAddedIncludesSkippedDirectory(self):
  130. problems = self.deps_checker.CheckAddedCppIncludes(
  131. [['buildtools/checkdeps/testdata/disallowed/allowed/skipped/test.cc',
  132. ['#include "whatever/whocares.h"']
  133. ]])
  134. self.assertFalse(problems)
  135. def testCheckAddedIncludesTempAllowed(self):
  136. problems = self.deps_checker.CheckAddedCppIncludes(
  137. [['buildtools/checkdeps/testdata/allowed/test.cc',
  138. ['#include "buildtools/checkdeps/testdata/disallowed/temporarily_allowed.h"']
  139. ]])
  140. self.assertTrue(problems)
  141. def testCopyIsDeep(self):
  142. # Regression test for a bug where we were making shallow copies of
  143. # Rules objects and therefore all Rules objects shared the same
  144. # dictionary for specific rules.
  145. #
  146. # The first pair should bring in a rule from testdata/allowed/DEPS
  147. # into that global dictionary that allows the
  148. # temp_allowed_for_tests.h file to be included in files ending
  149. # with _unittest.cc, and the second pair should completely fail
  150. # once the bug is fixed, but succeed (with a temporary allowance)
  151. # if the bug is in place.
  152. problems = self.deps_checker.CheckAddedCppIncludes(
  153. [['buildtools/checkdeps/testdata/allowed/test.cc',
  154. ['#include "buildtools/checkdeps/testdata/disallowed/temporarily_allowed.h"']
  155. ],
  156. ['buildtools/checkdeps/testdata/disallowed/foo_unittest.cc',
  157. ['#include "buildtools/checkdeps/testdata/bongo/temp_allowed_for_tests.h"']
  158. ]])
  159. # With the bug in place, there would be two problems reported, and
  160. # the second would be for foo_unittest.cc.
  161. self.assertTrue(len(problems) == 1)
  162. self.assertTrue(problems[0][0].endswith('/test.cc'))
  163. def testTraversalIsOrdered(self):
  164. dirs_traversed = []
  165. for rules, filenames in self.deps_checker.GetAllRulesAndFiles(dir_name='buildtools'):
  166. self.assertEqual(type(filenames), list)
  167. self.assertEqual(filenames, sorted(filenames))
  168. if filenames:
  169. dir_names = set(os.path.dirname(file) for file in filenames)
  170. self.assertEqual(1, len(dir_names))
  171. dirs_traversed.append(dir_names.pop())
  172. self.assertEqual(dirs_traversed, sorted(dirs_traversed))
  173. def testCheckPartialImportsAreAllowed(self):
  174. problems = self.deps_checker.CheckAddedProtoImports(
  175. [['buildtools/checkdeps/testdata/test.proto',
  176. ['import "no_rule_for_this/nogood.proto"']
  177. ]])
  178. self.assertFalse(problems)
  179. def testCheckAddedFullPathImportsAllowed(self):
  180. problems = self.deps_checker.CheckAddedProtoImports(
  181. [['buildtools/checkdeps/testdata/test.proto',
  182. ['import "buildtools/checkdeps/testdata/allowed/good.proto"',
  183. 'import "buildtools/checkdeps/testdata/disallowed/sub_folder/good.proto"']
  184. ]])
  185. self.assertFalse(problems)
  186. def testCheckAddedFullPathImportsDisallowed(self):
  187. problems = self.deps_checker.CheckAddedProtoImports(
  188. [['buildtools/checkdeps/testdata/test.proto',
  189. ['import "buildtools/checkdeps/testdata/disallowed/bad.proto"']
  190. ]])
  191. self.assertTrue(problems)
  192. def testCheckAddedFullPathImportsManyGarbageLines(self):
  193. garbage_lines = ["My name is Sam%d\n" % num for num in range(50)]
  194. problems = self.deps_checker.CheckAddedProtoImports(
  195. [['buildtools/checkdeps/testdata/test.proto',
  196. garbage_lines]])
  197. self.assertFalse(problems)
  198. def testCheckAddedIncludesNoRuleFullPath(self):
  199. problems = self.deps_checker.CheckAddedProtoImports(
  200. [['buildtools/checkdeps/testdata/test.proto',
  201. ['import "tools/some.proto"']
  202. ]])
  203. self.assertTrue(problems)
  204. if __name__ == '__main__':
  205. unittest.main()