PageRenderTime 28ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/neutron/tests/unit/hacking/test_checks.py

https://github.com/openstack/neutron
Python | 287 lines | 266 code | 10 blank | 11 comment | 1 complexity | 7154c271444445e2b9b6a8242d23680c MD5 | raw file
  1. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  2. # not use this file except in compliance with the License. You may obtain
  3. # a copy of the License at
  4. #
  5. # http://www.apache.org/licenses/LICENSE-2.0
  6. #
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. # License for the specific language governing permissions and limitations
  11. # under the License.
  12. import io
  13. import re
  14. import tokenize
  15. from unittest import mock
  16. import testtools
  17. from neutron.hacking import checks
  18. from neutron.tests import base
  19. CREATE_DUMMY_MATCH_OBJECT = re.compile('a')
  20. class HackingTestCase(base.BaseTestCase):
  21. def assertLinePasses(self, func, line, *args, **kwargs):
  22. with testtools.ExpectedException(StopIteration):
  23. next(func(line, *args, **kwargs))
  24. def assertLineFails(self, expected_code, func, line, *args, **kwargs):
  25. value = next(func(line, *args, **kwargs))
  26. self.assertIsInstance(value, tuple)
  27. self.assertIn(expected_code, value[1])
  28. def test_assert_called_once_with(self):
  29. fail_code2 = """
  30. mock = Mock()
  31. mock.method(1, 2, 3, test='wow')
  32. mock.method.assertCalledOnceWith()
  33. """
  34. fail_code3 = """
  35. mock = Mock()
  36. mock.method(1, 2, 3, test='wow')
  37. mock.method.called_once_with()
  38. """
  39. fail_code4 = """
  40. mock = Mock()
  41. mock.method(1, 2, 3, test='wow')
  42. mock.method.assert_has_called()
  43. """
  44. pass_code = """
  45. mock = Mock()
  46. mock.method(1, 2, 3, test='wow')
  47. mock.method.assert_called_once_with()
  48. """
  49. pass_code2 = """
  50. mock = Mock()
  51. mock.method(1, 2, 3, test='wow')
  52. mock.method.assert_has_calls()
  53. """
  54. self.assertEqual(
  55. 1, len(list(checks.check_assert_called_once_with(fail_code2,
  56. "neutron/tests/test_assert.py"))))
  57. self.assertEqual(
  58. 1, len(list(checks.check_assert_called_once_with(fail_code3,
  59. "neutron/tests/test_assert.py"))))
  60. self.assertEqual(
  61. 0, len(list(checks.check_assert_called_once_with(pass_code,
  62. "neutron/tests/test_assert.py"))))
  63. self.assertEqual(
  64. 1, len(list(checks.check_assert_called_once_with(fail_code4,
  65. "neutron/tests/test_assert.py"))))
  66. self.assertEqual(
  67. 0, len(list(checks.check_assert_called_once_with(pass_code2,
  68. "neutron/tests/test_assert.py"))))
  69. def test_asserttruefalse(self):
  70. true_fail_code1 = """
  71. test_bool = True
  72. self.assertEqual(True, test_bool)
  73. """
  74. true_fail_code2 = """
  75. test_bool = True
  76. self.assertEqual(test_bool, True)
  77. """
  78. true_pass_code = """
  79. test_bool = True
  80. self.assertTrue(test_bool)
  81. """
  82. false_fail_code1 = """
  83. test_bool = False
  84. self.assertEqual(False, test_bool)
  85. """
  86. false_fail_code2 = """
  87. test_bool = False
  88. self.assertEqual(test_bool, False)
  89. """
  90. false_pass_code = """
  91. test_bool = False
  92. self.assertFalse(test_bool)
  93. """
  94. self.assertEqual(
  95. 1, len(list(
  96. checks.check_asserttruefalse(true_fail_code1,
  97. "neutron/tests/test_assert.py"))))
  98. self.assertEqual(
  99. 1, len(list(
  100. checks.check_asserttruefalse(true_fail_code2,
  101. "neutron/tests/test_assert.py"))))
  102. self.assertEqual(
  103. 0, len(list(
  104. checks.check_asserttruefalse(true_pass_code,
  105. "neutron/tests/test_assert.py"))))
  106. self.assertEqual(
  107. 1, len(list(
  108. checks.check_asserttruefalse(false_fail_code1,
  109. "neutron/tests/test_assert.py"))))
  110. self.assertEqual(
  111. 1, len(list(
  112. checks.check_asserttruefalse(false_fail_code2,
  113. "neutron/tests/test_assert.py"))))
  114. self.assertFalse(
  115. list(
  116. checks.check_asserttruefalse(false_pass_code,
  117. "neutron/tests/test_assert.py")))
  118. def test_assertempty(self):
  119. fail_code = """
  120. test_empty = %s
  121. self.assertEqual(test_empty, %s)
  122. """
  123. pass_code1 = """
  124. test_empty = %s
  125. self.assertEqual(%s, test_empty)
  126. """
  127. pass_code2 = """
  128. self.assertEqual(123, foo(abc, %s))
  129. """
  130. empty_cases = ['{}', '[]', '""', "''", '()', 'set()']
  131. for ec in empty_cases:
  132. self.assertEqual(
  133. 1, len(list(checks.check_assertempty(fail_code % (ec, ec),
  134. "neutron/tests/test_assert.py"))))
  135. self.assertEqual(
  136. 0, len(list(checks.check_asserttruefalse(pass_code1 % (ec, ec),
  137. "neutron/tests/test_assert.py"))))
  138. self.assertEqual(
  139. 0, len(list(checks.check_asserttruefalse(pass_code2 % ec,
  140. "neutron/tests/test_assert.py"))))
  141. def test_assertisinstance(self):
  142. fail_code = """
  143. self.assertTrue(isinstance(observed, ANY_TYPE))
  144. """
  145. pass_code1 = """
  146. self.assertEqual(ANY_TYPE, type(observed))
  147. """
  148. pass_code2 = """
  149. self.assertIsInstance(observed, ANY_TYPE)
  150. """
  151. self.assertEqual(
  152. 1, len(list(checks.check_assertisinstance(fail_code,
  153. "neutron/tests/test_assert.py"))))
  154. self.assertEqual(
  155. 0, len(list(checks.check_assertisinstance(pass_code1,
  156. "neutron/tests/test_assert.py"))))
  157. self.assertEqual(
  158. 0, len(list(checks.check_assertisinstance(pass_code2,
  159. "neutron/tests/test_assert.py"))))
  160. def test_assertequal_for_httpcode(self):
  161. fail_code = """
  162. self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
  163. """
  164. pass_code = """
  165. self.assertEqual(webob.exc.HTTPBadRequest.code, res.status_int)
  166. """
  167. self.assertEqual(
  168. 1, len(list(checks.check_assertequal_for_httpcode(fail_code,
  169. "neutron/tests/test_assert.py"))))
  170. self.assertEqual(
  171. 0, len(list(checks.check_assertequal_for_httpcode(pass_code,
  172. "neutron/tests/test_assert.py"))))
  173. def test_check_no_imports_from_tests(self):
  174. fail_codes = ('from neutron import tests',
  175. 'from neutron.tests import base',
  176. 'import neutron.tests.base')
  177. for fail_code in fail_codes:
  178. self.assertEqual(
  179. 1, len(list(
  180. checks.check_no_imports_from_tests(
  181. fail_code, "neutron/common/utils.py", None))))
  182. self.assertEqual(
  183. 0, len(list(
  184. checks.check_no_imports_from_tests(
  185. fail_code, "neutron/tests/test_fake.py", None))))
  186. def test_check_python3_no_filter(self):
  187. f = checks.check_python3_no_filter
  188. self.assertLineFails('N344', f, "filter(lambda obj: test(obj), data)")
  189. self.assertLinePasses(f, "[obj for obj in data if test(obj)]")
  190. self.assertLinePasses(f, "filter(function, range(0,10))")
  191. self.assertLinePasses(f, "lambda x, y: x+y")
  192. def test_check_no_import_mock(self):
  193. pass_line = 'from unittest import mock'
  194. fail_lines = ('import mock',
  195. 'import mock as mock_lib',
  196. 'from mock import patch')
  197. self.assertEqual(
  198. 0, len(list(
  199. checks.check_no_import_mock(
  200. pass_line, "neutron/tests/test_fake.py", None))))
  201. for fail_line in fail_lines:
  202. self.assertEqual(
  203. 0, len(list(
  204. checks.check_no_import_mock(
  205. fail_line, "neutron/common/utils.py", None))))
  206. self.assertEqual(
  207. 1, len(list(
  208. checks.check_no_import_mock(
  209. fail_line, "neutron/tests/test_fake.py", None))))
  210. def test_check_no_import_six(self):
  211. pass_line = 'from other_library import six'
  212. fail_lines = ('import six',
  213. 'import six as six_lib',
  214. 'from six import moves')
  215. self.assertEqual(
  216. 0,
  217. len(list(checks.check_no_import_six(pass_line, mock.ANY, None))))
  218. for fail_line in fail_lines:
  219. self.assertEqual(
  220. 1, len(list(checks.check_no_import_six(
  221. fail_line, mock.ANY, None))))
  222. def test_check_oslo_i18n_wrapper(self):
  223. def _pass(line, filename, noqa=False):
  224. self.assertLinePasses(
  225. checks.check_oslo_i18n_wrapper,
  226. line, filename, noqa)
  227. def _fail(line, filename):
  228. self.assertLineFails(
  229. "N340", checks.check_oslo_i18n_wrapper,
  230. line, filename, noqa=False)
  231. _pass("from neutron._i18n import _", "neutron/foo/bar.py")
  232. _pass("from neutron_fwaas._i18n import _", "neutron_fwaas/foo/bar.py")
  233. _fail("from neutron.i18n import _", "neutron/foo/bar.py")
  234. _fail("from neutron_fwaas.i18n import _", "neutron_fwaas/foo/bar.py")
  235. _fail("from neutron.i18n import _", "neutron_fwaas/foo/bar.py")
  236. _fail("from neutron._i18n import _", "neutron_fwaas/foo/bar.py")
  237. _pass("from neutron.i18n import _", "neutron/foo/bar.py", noqa=True)
  238. def test_check_builtins_gettext(self):
  239. # NOTE: check_builtins_gettext() takes two additional arguments,
  240. # "tokens" and "lines". "tokens" is a list of tokens from the target
  241. # logical line, and "lines" is a list of lines of the input file.
  242. # Considering this, test functions (_pass and _fail) take "lines"
  243. # as an argument and calls the hacking check function line by line
  244. # after generating tokens from the target line.
  245. def _get_tokens(line):
  246. return tokenize.tokenize(io.BytesIO(line.encode('utf-8')).readline)
  247. def _pass(lines, filename, noqa=False):
  248. for line in lines:
  249. self.assertLinePasses(
  250. checks.check_builtins_gettext,
  251. line, _get_tokens(line), filename, lines, noqa)
  252. def _fail(lines, filename):
  253. for line in lines:
  254. self.assertLineFails(
  255. "N341", checks.check_builtins_gettext,
  256. line, _get_tokens(line), filename, lines, noqa=False)
  257. _pass(["from neutron._i18n import _", "_('foo')"], "neutron/foo.py")
  258. _fail(["_('foo')"], "neutron/foo.py")
  259. _pass(["_('foo')"], "neutron/_i18n.py")
  260. _pass(["_('foo')"], "neutron/i18n.py")
  261. _pass(["_('foo')"], "neutron/foo.py", noqa=True)