blob: edfb2c801d5e42a16a9df5b2f07e0039e408d080 [file] [log] [blame]
Tomas Krchnak536d8282020-06-24 12:41:45 +02001# 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
lkuchlanc8b966f2020-01-07 12:53:55 +020013import ast
Tomas Krchnak536d8282020-06-24 12:41:45 +020014import importlib
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020015import os
Ghanshyam Mann238be502021-03-09 12:30:47 -060016import shutil
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020017import sys
Martin Kopece1eebfa2020-07-08 09:39:50 +000018import tempfile
19from unittest import mock
Tomas Krchnak536d8282020-06-24 12:41:45 +020020
21from tempest.lib.cmd import check_uuid
22from tempest.tests import base
23
24
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020025class TestCLInterface(base.TestCase):
26 CODE = "import unittest\n" \
27 "class TestClass(unittest.TestCase):\n" \
28 " def test_tests(self):\n" \
29 " pass"
30
Martin Kopecea3e38c2021-09-14 05:13:02 +000031 def setUp(self):
32 super(TestCLInterface, self).setUp()
33 self.directory = tempfile.mkdtemp(prefix='check-uuid', dir=".")
34 self.addCleanup(shutil.rmtree, self.directory, ignore_errors=True)
35
36 init_file = open(self.directory + "/__init__.py", "w")
Martin Kopece74445b2021-08-17 09:55:10 +000037 init_file.close()
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020038
Martin Kopecea3e38c2021-09-14 05:13:02 +000039 self.tests_file = self.directory + "/tests.py"
40 with open(self.tests_file, "w") as fake_file:
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020041 fake_file.write(TestCLInterface.CODE)
Martin Kopece74445b2021-08-17 09:55:10 +000042 fake_file.close()
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020043
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020044 def test_fix_argument_no(self):
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020045 sys.argv = [sys.argv[0]] + ["--package",
Martin Kopecea3e38c2021-09-14 05:13:02 +000046 os.path.relpath(self.directory)]
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020047
48 self.assertRaises(SystemExit, check_uuid.run)
Martin Kopecea3e38c2021-09-14 05:13:02 +000049 with open(self.tests_file, "r") as f:
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020050 self.assertTrue(TestCLInterface.CODE == f.read())
51
52 def test_fix_argument_yes(self):
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020053
54 sys.argv = [sys.argv[0]] + ["--fix", "--package",
Martin Kopecea3e38c2021-09-14 05:13:02 +000055 os.path.relpath(self.directory)]
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020056 check_uuid.run()
Martin Kopecea3e38c2021-09-14 05:13:02 +000057 with open(self.tests_file, "r") as f:
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020058 self.assertTrue(TestCLInterface.CODE != f.read())
59
60
Tomas Krchnak536d8282020-06-24 12:41:45 +020061class TestSourcePatcher(base.TestCase):
62 def test_add_patch(self):
63 patcher = check_uuid.SourcePatcher()
64 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
65 file_contents = 'first_line\nsecond_line'
66 fake_file.write(file_contents)
67 fake_file.close()
68 patcher.add_patch(fake_file.name, 'patch', 2)
69
70 source_file = patcher.source_files[fake_file.name]
71 self.assertEqual(1, len(patcher.patches))
72 (patch_id, patch), = patcher.patches.items()
73 self.assertEqual(patcher._quote('patch\n'), patch)
74 self.assertEqual('first_line\n{%s:s}second_line' % patch_id,
75 patcher._unquote(source_file))
76
77 def test_apply_patches(self):
78 fake_file = tempfile.NamedTemporaryFile("w+t")
79 patcher = check_uuid.SourcePatcher()
80 patcher.patches = {'fake-uuid': patcher._quote('patch\n')}
81 patcher.source_files = {
82 fake_file.name: patcher._quote('first_line\n') +
83 '{fake-uuid:s}second_line'}
84 with mock.patch('sys.stdout'):
85 patcher.apply_patches()
86
87 lines = fake_file.read().split('\n')
88 fake_file.close()
89 self.assertEqual(['first_line', 'patch', 'second_line'], lines)
90 self.assertFalse(patcher.patches)
91 self.assertFalse(patcher.source_files)
92
93
94class TestTestChecker(base.TestCase):
lkuchlanc8b966f2020-01-07 12:53:55 +020095 IMPORT_LINE = "from tempest.lib import decorators\n"
96
Tomas Krchnak536d8282020-06-24 12:41:45 +020097 def _test_add_uuid_to_test(self, source_file):
98 class Fake_test_node():
99 lineno = 1
100 col_offset = 4
101 patcher = check_uuid.SourcePatcher()
102 checker = check_uuid.TestChecker(importlib.import_module('tempest'))
103 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
104 fake_file.write(source_file)
105 fake_file.close()
106 checker._add_uuid_to_test(patcher, Fake_test_node(), fake_file.name)
107
108 self.assertEqual(1, len(patcher.patches))
109 self.assertEqual(1, len(patcher.source_files))
110 (patch_id, patch), = patcher.patches.items()
111 changed_source_file, = patcher.source_files.values()
112 self.assertEqual('{%s:s}%s' % (patch_id, patcher._quote(source_file)),
113 changed_source_file)
114 expected_patch_start = patcher._quote(
115 ' ' + check_uuid.DECORATOR_TEMPLATE.split('(')[0])
116 self.assertTrue(patch.startswith(expected_patch_start))
117
118 def test_add_uuid_to_test_def(self):
119 source_file = (" def test_test():\n"
120 " pass")
121 self._test_add_uuid_to_test(source_file)
122
123 def test_add_uuid_to_test_decorator(self):
124 source_file = (" @decorators.idempotent_id\n"
125 " def test_test():\n"
126 " pass")
127 self._test_add_uuid_to_test(source_file)
128
lkuchlanc8b966f2020-01-07 12:53:55 +0200129 @staticmethod
130 def get_mocked_ast_object(lineno, col_offset, module, name, object_type):
131 ast_object = mock.Mock(spec=object_type)
132 name_obj = mock.Mock()
133 ast_object.lineno = lineno
134 ast_object.col_offset = col_offset
135 name_obj.name = name
136 ast_object.module = module
137 ast_object.names = [name_obj]
138
139 return ast_object
140
Tomas Krchnak536d8282020-06-24 12:41:45 +0200141 def test_add_import_for_test_uuid_no_tempest(self):
142 patcher = check_uuid.SourcePatcher()
143 checker = check_uuid.TestChecker(importlib.import_module('tempest'))
lkuchlanc8b966f2020-01-07 12:53:55 +0200144 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
145 source_code = "from unittest import mock\n"
146 fake_file.write(source_code)
147 fake_file.close()
Tomas Krchnak536d8282020-06-24 12:41:45 +0200148
149 class Fake_src_parsed():
lkuchlanc8b966f2020-01-07 12:53:55 +0200150 body = [TestTestChecker.get_mocked_ast_object(
151 1, 4, 'unittest', 'mock', ast.ImportFrom)]
Tomas Krchnak536d8282020-06-24 12:41:45 +0200152
lkuchlanc8b966f2020-01-07 12:53:55 +0200153 checker._add_import_for_test_uuid(patcher, Fake_src_parsed,
Tomas Krchnak536d8282020-06-24 12:41:45 +0200154 fake_file.name)
lkuchlanc8b966f2020-01-07 12:53:55 +0200155 patcher.apply_patches()
156
157 with open(fake_file.name, "r") as f:
158 expected_result = source_code + '\n' + TestTestChecker.IMPORT_LINE
159 self.assertTrue(expected_result == f.read())
Tomas Krchnak536d8282020-06-24 12:41:45 +0200160
161 def test_add_import_for_test_uuid_tempest(self):
162 patcher = check_uuid.SourcePatcher()
163 checker = check_uuid.TestChecker(importlib.import_module('tempest'))
164 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
lkuchlanc8b966f2020-01-07 12:53:55 +0200165 source_code = "from tempest import a_fake_module\n"
Tomas Krchnak536d8282020-06-24 12:41:45 +0200166 fake_file.write(source_code)
167 fake_file.close()
168
lkuchlanc8b966f2020-01-07 12:53:55 +0200169 class Fake_src_parsed:
170 body = [TestTestChecker.get_mocked_ast_object(
171 1, 4, 'tempest', 'a_fake_module', ast.ImportFrom)]
Tomas Krchnak536d8282020-06-24 12:41:45 +0200172
lkuchlanc8b966f2020-01-07 12:53:55 +0200173 checker._add_import_for_test_uuid(patcher, Fake_src_parsed,
Tomas Krchnak536d8282020-06-24 12:41:45 +0200174 fake_file.name)
lkuchlanc8b966f2020-01-07 12:53:55 +0200175 patcher.apply_patches()
176
177 with open(fake_file.name, "r") as f:
178 expected_result = source_code + TestTestChecker.IMPORT_LINE
179 self.assertTrue(expected_result == f.read())
180
181 def test_add_import_no_import(self):
182 patcher = check_uuid.SourcePatcher()
183 patcher.add_patch = mock.Mock()
184 checker = check_uuid.TestChecker(importlib.import_module('tempest'))
185 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
186 fake_file.close()
187
188 class Fake_src_parsed:
189 body = []
190
191 checker._add_import_for_test_uuid(patcher, Fake_src_parsed,
192 fake_file.name)
193
194 self.assertTrue(not patcher.add_patch.called)