Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 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 | |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 13 | import ast |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 14 | import importlib |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 15 | import os |
Ghanshyam Mann | 238be50 | 2021-03-09 12:30:47 -0600 | [diff] [blame] | 16 | import shutil |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 17 | import sys |
Martin Kopec | e1eebfa | 2020-07-08 09:39:50 +0000 | [diff] [blame] | 18 | import tempfile |
| 19 | from unittest import mock |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 20 | |
| 21 | from tempest.lib.cmd import check_uuid |
| 22 | from tempest.tests import base |
| 23 | |
| 24 | |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 25 | class TestCLInterface(base.TestCase): |
| 26 | CODE = "import unittest\n" \ |
| 27 | "class TestClass(unittest.TestCase):\n" \ |
| 28 | " def test_tests(self):\n" \ |
| 29 | " pass" |
| 30 | |
Martin Kopec | ea3e38c | 2021-09-14 05:13:02 +0000 | [diff] [blame] | 31 | 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 Kopec | e74445b | 2021-08-17 09:55:10 +0000 | [diff] [blame] | 37 | init_file.close() |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 38 | |
Martin Kopec | ea3e38c | 2021-09-14 05:13:02 +0000 | [diff] [blame] | 39 | self.tests_file = self.directory + "/tests.py" |
| 40 | with open(self.tests_file, "w") as fake_file: |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 41 | fake_file.write(TestCLInterface.CODE) |
Martin Kopec | e74445b | 2021-08-17 09:55:10 +0000 | [diff] [blame] | 42 | fake_file.close() |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 43 | |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 44 | def test_fix_argument_no(self): |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 45 | sys.argv = [sys.argv[0]] + ["--package", |
Martin Kopec | ea3e38c | 2021-09-14 05:13:02 +0000 | [diff] [blame] | 46 | os.path.relpath(self.directory)] |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 47 | |
| 48 | self.assertRaises(SystemExit, check_uuid.run) |
Martin Kopec | ea3e38c | 2021-09-14 05:13:02 +0000 | [diff] [blame] | 49 | with open(self.tests_file, "r") as f: |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 50 | self.assertTrue(TestCLInterface.CODE == f.read()) |
| 51 | |
| 52 | def test_fix_argument_yes(self): |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 53 | |
| 54 | sys.argv = [sys.argv[0]] + ["--fix", "--package", |
Martin Kopec | ea3e38c | 2021-09-14 05:13:02 +0000 | [diff] [blame] | 55 | os.path.relpath(self.directory)] |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 56 | check_uuid.run() |
Martin Kopec | ea3e38c | 2021-09-14 05:13:02 +0000 | [diff] [blame] | 57 | with open(self.tests_file, "r") as f: |
Lukas Piwowarski | a9af3ea | 2020-07-13 18:08:06 +0200 | [diff] [blame] | 58 | self.assertTrue(TestCLInterface.CODE != f.read()) |
| 59 | |
| 60 | |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 61 | class 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 | |
| 94 | class TestTestChecker(base.TestCase): |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 95 | IMPORT_LINE = "from tempest.lib import decorators\n" |
| 96 | |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 97 | 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 | |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 129 | @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 Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 141 | def test_add_import_for_test_uuid_no_tempest(self): |
| 142 | patcher = check_uuid.SourcePatcher() |
| 143 | checker = check_uuid.TestChecker(importlib.import_module('tempest')) |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 144 | 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 Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 148 | |
| 149 | class Fake_src_parsed(): |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 150 | body = [TestTestChecker.get_mocked_ast_object( |
| 151 | 1, 4, 'unittest', 'mock', ast.ImportFrom)] |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 152 | |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 153 | checker._add_import_for_test_uuid(patcher, Fake_src_parsed, |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 154 | fake_file.name) |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 155 | 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 Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 160 | |
| 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) |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 165 | source_code = "from tempest import a_fake_module\n" |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 166 | fake_file.write(source_code) |
| 167 | fake_file.close() |
| 168 | |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 169 | class Fake_src_parsed: |
| 170 | body = [TestTestChecker.get_mocked_ast_object( |
| 171 | 1, 4, 'tempest', 'a_fake_module', ast.ImportFrom)] |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 172 | |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 173 | checker._add_import_for_test_uuid(patcher, Fake_src_parsed, |
Tomas Krchnak | 536d828 | 2020-06-24 12:41:45 +0200 | [diff] [blame] | 174 | fake_file.name) |
lkuchlan | c8b966f | 2020-01-07 12:53:55 +0200 | [diff] [blame] | 175 | 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) |