blob: 5d63dec8ac6c1b88261c98056b562c6c86d59775 [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
Ghanshyam Mannc76e1862021-03-10 10:09:14 -060022from tempest.lib import decorators
Tomas Krchnak536d8282020-06-24 12:41:45 +020023from tempest.tests import base
24
25
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020026class TestCLInterface(base.TestCase):
27 CODE = "import unittest\n" \
28 "class TestClass(unittest.TestCase):\n" \
29 " def test_tests(self):\n" \
30 " pass"
31
32 def create_tests_file(self, directory):
33 with open(directory + "/__init__.py", "w"):
34 pass
35
36 tests_file = directory + "/tests.py"
37 with open(tests_file, "w") as fake_file:
38 fake_file.write(TestCLInterface.CODE)
39
40 return tests_file
41
42 def test_fix_argument_no(self):
Ghanshyam Mann238be502021-03-09 12:30:47 -060043 temp_dir = tempfile.mkdtemp(prefix='check-uuid-no', dir=".")
44 self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True)
45 tests_file = self.create_tests_file(temp_dir)
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020046 sys.argv = [sys.argv[0]] + ["--package",
Ghanshyam Mann238be502021-03-09 12:30:47 -060047 os.path.relpath(temp_dir)]
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020048
49 self.assertRaises(SystemExit, check_uuid.run)
50 with open(tests_file, "r") as f:
51 self.assertTrue(TestCLInterface.CODE == f.read())
52
Ghanshyam Mannc76e1862021-03-10 10:09:14 -060053 @decorators.skip_because(bug='1918316')
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020054 def test_fix_argument_yes(self):
Ghanshyam Mann238be502021-03-09 12:30:47 -060055 temp_dir = tempfile.mkdtemp(prefix='check-uuid-yes', dir=".")
56 self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True)
57 tests_file = self.create_tests_file(temp_dir)
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020058
59 sys.argv = [sys.argv[0]] + ["--fix", "--package",
Ghanshyam Mann238be502021-03-09 12:30:47 -060060 os.path.relpath(temp_dir)]
Lukas Piwowarskia9af3ea2020-07-13 18:08:06 +020061 check_uuid.run()
62 with open(tests_file, "r") as f:
63 self.assertTrue(TestCLInterface.CODE != f.read())
64
65
Tomas Krchnak536d8282020-06-24 12:41:45 +020066class TestSourcePatcher(base.TestCase):
67 def test_add_patch(self):
68 patcher = check_uuid.SourcePatcher()
69 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
70 file_contents = 'first_line\nsecond_line'
71 fake_file.write(file_contents)
72 fake_file.close()
73 patcher.add_patch(fake_file.name, 'patch', 2)
74
75 source_file = patcher.source_files[fake_file.name]
76 self.assertEqual(1, len(patcher.patches))
77 (patch_id, patch), = patcher.patches.items()
78 self.assertEqual(patcher._quote('patch\n'), patch)
79 self.assertEqual('first_line\n{%s:s}second_line' % patch_id,
80 patcher._unquote(source_file))
81
82 def test_apply_patches(self):
83 fake_file = tempfile.NamedTemporaryFile("w+t")
84 patcher = check_uuid.SourcePatcher()
85 patcher.patches = {'fake-uuid': patcher._quote('patch\n')}
86 patcher.source_files = {
87 fake_file.name: patcher._quote('first_line\n') +
88 '{fake-uuid:s}second_line'}
89 with mock.patch('sys.stdout'):
90 patcher.apply_patches()
91
92 lines = fake_file.read().split('\n')
93 fake_file.close()
94 self.assertEqual(['first_line', 'patch', 'second_line'], lines)
95 self.assertFalse(patcher.patches)
96 self.assertFalse(patcher.source_files)
97
98
99class TestTestChecker(base.TestCase):
lkuchlanc8b966f2020-01-07 12:53:55 +0200100 IMPORT_LINE = "from tempest.lib import decorators\n"
101
Tomas Krchnak536d8282020-06-24 12:41:45 +0200102 def _test_add_uuid_to_test(self, source_file):
103 class Fake_test_node():
104 lineno = 1
105 col_offset = 4
106 patcher = check_uuid.SourcePatcher()
107 checker = check_uuid.TestChecker(importlib.import_module('tempest'))
108 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
109 fake_file.write(source_file)
110 fake_file.close()
111 checker._add_uuid_to_test(patcher, Fake_test_node(), fake_file.name)
112
113 self.assertEqual(1, len(patcher.patches))
114 self.assertEqual(1, len(patcher.source_files))
115 (patch_id, patch), = patcher.patches.items()
116 changed_source_file, = patcher.source_files.values()
117 self.assertEqual('{%s:s}%s' % (patch_id, patcher._quote(source_file)),
118 changed_source_file)
119 expected_patch_start = patcher._quote(
120 ' ' + check_uuid.DECORATOR_TEMPLATE.split('(')[0])
121 self.assertTrue(patch.startswith(expected_patch_start))
122
123 def test_add_uuid_to_test_def(self):
124 source_file = (" def test_test():\n"
125 " pass")
126 self._test_add_uuid_to_test(source_file)
127
128 def test_add_uuid_to_test_decorator(self):
129 source_file = (" @decorators.idempotent_id\n"
130 " def test_test():\n"
131 " pass")
132 self._test_add_uuid_to_test(source_file)
133
lkuchlanc8b966f2020-01-07 12:53:55 +0200134 @staticmethod
135 def get_mocked_ast_object(lineno, col_offset, module, name, object_type):
136 ast_object = mock.Mock(spec=object_type)
137 name_obj = mock.Mock()
138 ast_object.lineno = lineno
139 ast_object.col_offset = col_offset
140 name_obj.name = name
141 ast_object.module = module
142 ast_object.names = [name_obj]
143
144 return ast_object
145
Tomas Krchnak536d8282020-06-24 12:41:45 +0200146 def test_add_import_for_test_uuid_no_tempest(self):
147 patcher = check_uuid.SourcePatcher()
148 checker = check_uuid.TestChecker(importlib.import_module('tempest'))
lkuchlanc8b966f2020-01-07 12:53:55 +0200149 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
150 source_code = "from unittest import mock\n"
151 fake_file.write(source_code)
152 fake_file.close()
Tomas Krchnak536d8282020-06-24 12:41:45 +0200153
154 class Fake_src_parsed():
lkuchlanc8b966f2020-01-07 12:53:55 +0200155 body = [TestTestChecker.get_mocked_ast_object(
156 1, 4, 'unittest', 'mock', ast.ImportFrom)]
Tomas Krchnak536d8282020-06-24 12:41:45 +0200157
lkuchlanc8b966f2020-01-07 12:53:55 +0200158 checker._add_import_for_test_uuid(patcher, Fake_src_parsed,
Tomas Krchnak536d8282020-06-24 12:41:45 +0200159 fake_file.name)
lkuchlanc8b966f2020-01-07 12:53:55 +0200160 patcher.apply_patches()
161
162 with open(fake_file.name, "r") as f:
163 expected_result = source_code + '\n' + TestTestChecker.IMPORT_LINE
164 self.assertTrue(expected_result == f.read())
Tomas Krchnak536d8282020-06-24 12:41:45 +0200165
166 def test_add_import_for_test_uuid_tempest(self):
167 patcher = check_uuid.SourcePatcher()
168 checker = check_uuid.TestChecker(importlib.import_module('tempest'))
169 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
lkuchlanc8b966f2020-01-07 12:53:55 +0200170 source_code = "from tempest import a_fake_module\n"
Tomas Krchnak536d8282020-06-24 12:41:45 +0200171 fake_file.write(source_code)
172 fake_file.close()
173
lkuchlanc8b966f2020-01-07 12:53:55 +0200174 class Fake_src_parsed:
175 body = [TestTestChecker.get_mocked_ast_object(
176 1, 4, 'tempest', 'a_fake_module', ast.ImportFrom)]
Tomas Krchnak536d8282020-06-24 12:41:45 +0200177
lkuchlanc8b966f2020-01-07 12:53:55 +0200178 checker._add_import_for_test_uuid(patcher, Fake_src_parsed,
Tomas Krchnak536d8282020-06-24 12:41:45 +0200179 fake_file.name)
lkuchlanc8b966f2020-01-07 12:53:55 +0200180 patcher.apply_patches()
181
182 with open(fake_file.name, "r") as f:
183 expected_result = source_code + TestTestChecker.IMPORT_LINE
184 self.assertTrue(expected_result == f.read())
185
186 def test_add_import_no_import(self):
187 patcher = check_uuid.SourcePatcher()
188 patcher.add_patch = mock.Mock()
189 checker = check_uuid.TestChecker(importlib.import_module('tempest'))
190 fake_file = tempfile.NamedTemporaryFile("w+t", delete=False)
191 fake_file.close()
192
193 class Fake_src_parsed:
194 body = []
195
196 checker._add_import_for_test_uuid(patcher, Fake_src_parsed,
197 fake_file.name)
198
199 self.assertTrue(not patcher.add_patch.called)