blob: 6b3aa0d03cdd8ddd06e3ccb9fd3f8b33675858e2 [file] [log] [blame]
Matthew Treinishaaa35952014-05-02 18:50:16 -04001# Copyright 2014 Matthew Treinish
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from tempest.hacking import checks
Jordan Pittier41129042016-03-29 21:21:16 +020016from tempest.tests.lib import base
Matthew Treinishaaa35952014-05-02 18:50:16 -040017
18
19class HackingTestCase(base.TestCase):
Ken'ichi Ohmichic864f592015-11-19 08:45:06 +000020 """Test class for hacking rule
21
Matthew Treinishe2eee322014-05-02 19:58:54 -040022 This class tests the hacking checks in tempest.hacking.checks by passing
23 strings to the check methods like the pep8/flake8 parser would. The parser
24 loops over each line in the file and then passes the parameters to the
25 check method. The parameter names in the check method dictate what type of
26 object is passed to the check method. The parameter types are::
27
28 logical_line: A processed line with the following modifications:
29 - Multi-line statements converted to a single line.
30 - Stripped left and right.
31 - Contents of strings replaced with "xxx" of same length.
32 - Comments removed.
33 physical_line: Raw line of text from the input file.
34 lines: a list of the raw lines from the input file
35 tokens: the tokens that contribute to this logical line
36 line_number: line number in the input file
37 total_lines: number of lines in the input file
38 blank_lines: blank lines before this one
39 indent_char: indentation character in this file (" " or "\t")
40 indent_level: indentation (with tabs expanded to multiples of 8)
41 previous_indent_level: indentation on previous line
42 previous_logical: previous logical line
43 filename: Path of the file being run through pep8
44
45 When running a test on a check method the return will be False/None if
46 there is no violation in the sample input. If there is an error a tuple is
47 returned with a position in the line, and a message. So to check the result
48 just assertTrue if the check is expected to fail and assertFalse if it
49 should pass.
50 """
Andrea Frittoli41fa16d2014-09-15 13:41:37 +010051 def test_no_setup_teardown_class_for_tests(self):
52 self.assertTrue(checks.no_setup_teardown_class_for_tests(
Matthew Treinishaaa35952014-05-02 18:50:16 -040053 " def setUpClass(cls):", './tempest/tests/fake_test.py'))
Andrea Frittoli41fa16d2014-09-15 13:41:37 +010054 self.assertIsNone(checks.no_setup_teardown_class_for_tests(
Matthew Treinishaaa35952014-05-02 18:50:16 -040055 " def setUpClass(cls): # noqa", './tempest/tests/fake_test.py'))
Andrea Frittoli41fa16d2014-09-15 13:41:37 +010056 self.assertTrue(checks.no_setup_teardown_class_for_tests(
Matthew Treinishaaa35952014-05-02 18:50:16 -040057 " def setUpClass(cls):", './tempest/api/fake_test.py'))
Andrea Frittoli41fa16d2014-09-15 13:41:37 +010058 self.assertTrue(checks.no_setup_teardown_class_for_tests(
59 " def setUpClass(cls):", './tempest/scenario/fake_test.py'))
60 self.assertFalse(checks.no_setup_teardown_class_for_tests(
61 " def setUpClass(cls):", './tempest/test.py'))
62 self.assertTrue(checks.no_setup_teardown_class_for_tests(
63 " def tearDownClass(cls):", './tempest/tests/fake_test.py'))
64 self.assertIsNone(checks.no_setup_teardown_class_for_tests(
65 " def tearDownClass(cls): # noqa", './tempest/tests/fake_test.py'))
66 self.assertTrue(checks.no_setup_teardown_class_for_tests(
67 " def tearDownClass(cls):", './tempest/api/fake_test.py'))
68 self.assertTrue(checks.no_setup_teardown_class_for_tests(
69 " def tearDownClass(cls):", './tempest/scenario/fake_test.py'))
70 self.assertFalse(checks.no_setup_teardown_class_for_tests(
71 " def tearDownClass(cls):", './tempest/test.py'))
Matthew Treinishe2eee322014-05-02 19:58:54 -040072
ghanshyam50f19472014-11-26 17:04:37 +090073 def test_import_no_clients_in_api_and_scenario_tests(self):
Matthew Treinishe2eee322014-05-02 19:58:54 -040074 for client in checks.PYTHON_CLIENTS:
75 string = "import " + client + "client"
ghanshyam50f19472014-11-26 17:04:37 +090076 self.assertTrue(
77 checks.import_no_clients_in_api_and_scenario_tests(
78 string, './tempest/api/fake_test.py'))
79 self.assertTrue(
80 checks.import_no_clients_in_api_and_scenario_tests(
81 string, './tempest/scenario/fake_test.py'))
82 self.assertFalse(
83 checks.import_no_clients_in_api_and_scenario_tests(
84 string, './tempest/test.py'))
Matthew Treinishe2eee322014-05-02 19:58:54 -040085
86 def test_scenario_tests_need_service_tags(self):
87 self.assertFalse(checks.scenario_tests_need_service_tags(
88 'def test_fake:', './tempest/scenario/test_fake.py',
89 "@test.services('compute')"))
90 self.assertFalse(checks.scenario_tests_need_service_tags(
91 'def test_fake_test:', './tempest/api/compute/test_fake.py',
92 "@test.services('image')"))
Matthew Treinishb12ad762014-06-19 10:18:05 -040093 self.assertFalse(checks.scenario_tests_need_service_tags(
94 'def test_fake:', './tempest/scenario/orchestration/test_fake.py',
95 "@test.services('compute')"))
Matthew Treinishe2eee322014-05-02 19:58:54 -040096 self.assertTrue(checks.scenario_tests_need_service_tags(
97 'def test_fake_test:', './tempest/scenario/test_fake.py',
98 '\n'))
Matthew Treinishb12ad762014-06-19 10:18:05 -040099 self.assertTrue(checks.scenario_tests_need_service_tags(
100 'def test_fake:', './tempest/scenario/orchestration/test_fake.py',
101 "\n"))
Matthew Treinishe2eee322014-05-02 19:58:54 -0400102
103 def test_no_vi_headers(self):
104 # NOTE(mtreinish) The lines parameter is used only for finding the
105 # line location in the file. So these tests just pass a list of an
106 # arbitrary length to use for verifying the check function.
107 self.assertTrue(checks.no_vi_headers(
108 '# vim: tabstop=4 shiftwidth=4 softtabstop=4', 1, range(250)))
109 self.assertTrue(checks.no_vi_headers(
110 '# vim: tabstop=4 shiftwidth=4 softtabstop=4', 249, range(250)))
111 self.assertFalse(checks.no_vi_headers(
112 '# vim: tabstop=4 shiftwidth=4 softtabstop=4', 149, range(250)))
113
114 def test_service_tags_not_in_module_path(self):
115 self.assertTrue(checks.service_tags_not_in_module_path(
116 "@test.services('compute')", './tempest/api/compute/fake_test.py'))
117 self.assertFalse(checks.service_tags_not_in_module_path(
118 "@test.services('compute')",
119 './tempest/scenario/compute/fake_test.py'))
120 self.assertFalse(checks.service_tags_not_in_module_path(
121 "@test.services('compute')", './tempest/api/image/fake_test.py'))
Matthew Treinish7acaba42014-05-28 09:19:03 -0400122
Ken'ichi Ohmichi80369a92015-04-06 23:41:14 +0000123 def test_no_hyphen_at_end_of_rand_name(self):
124 self.assertIsNone(checks.no_hyphen_at_end_of_rand_name(
125 'data_utils.rand_name("fake-resource")', './tempest/test_foo.py'))
126 self.assertEqual(2, len(list(checks.no_hyphen_at_end_of_rand_name(
127 'data_utils.rand_name("fake-resource-")', './tempest/test_foo.py')
128 )))
129
Ghanshyam2a180b82014-06-16 13:54:22 +0900130 def test_no_mutable_default_args(self):
131 self.assertEqual(1, len(list(checks.no_mutable_default_args(
132 " def function1(para={}):"))))
133
134 self.assertEqual(1, len(list(checks.no_mutable_default_args(
135 "def function2(para1, para2, para3=[])"))))
136
137 self.assertEqual(0, len(list(checks.no_mutable_default_args(
138 "defined = []"))))
139
140 self.assertEqual(0, len(list(checks.no_mutable_default_args(
141 "defined, undefined = [], {}"))))
John Warren3059a092015-08-31 15:34:49 -0400142
143 def test_no_testtools_skip_decorator(self):
144 self.assertEqual(1, len(list(checks.no_testtools_skip_decorator(
145 " @testtools.skip('Bug xxx')"))))
146 self.assertEqual(0, len(list(checks.no_testtools_skip_decorator(
147 " @testtools.skipUnless(CONF.something, 'msg')"))))
148 self.assertEqual(0, len(list(checks.no_testtools_skip_decorator(
149 " @testtools.skipIf(CONF.something, 'msg')"))))
Ken'ichi Ohmichi0dc97472016-03-25 15:10:08 -0700150
151 def test_dont_import_local_tempest_code_into_lib(self):
152 self.assertEqual(0, len(list(checks.dont_import_local_tempest_into_lib(
153 "from tempest.common import waiters",
154 './tempest/common/compute.py'))))
155 self.assertEqual(0, len(list(checks.dont_import_local_tempest_into_lib(
156 "from tempest import config",
157 './tempest/common/compute.py'))))
158 self.assertEqual(0, len(list(checks.dont_import_local_tempest_into_lib(
159 "import tempest.exception",
160 './tempest/common/compute.py'))))
161 self.assertEqual(1, len(list(checks.dont_import_local_tempest_into_lib(
162 "from tempest.common import waiters",
163 './tempest/lib/common/compute.py'))))
164 self.assertEqual(1, len(list(checks.dont_import_local_tempest_into_lib(
165 "from tempest import config",
166 './tempest/lib/common/compute.py'))))
167 self.assertEqual(1, len(list(checks.dont_import_local_tempest_into_lib(
168 "import tempest.exception",
169 './tempest/lib/common/compute.py'))))