Alex | 0989ecf | 2022-03-29 13:43:21 -0500 | [diff] [blame] | 1 | # Author: Alex Savatieiev (osavatieiev@mirantis.com; a.savex@gmail.com) |
| 2 | # Copyright 2019-2022 Mirantis, Inc. |
Alex | 265f45e | 2019-04-23 18:51:23 -0500 | [diff] [blame] | 3 | import contextlib |
| 4 | import io |
Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 5 | import os |
Alex | 265f45e | 2019-04-23 18:51:23 -0500 | [diff] [blame] | 6 | import sys |
| 7 | import unittest |
Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 8 | import logging |
| 9 | |
| 10 | from copy import deepcopy |
| 11 | |
| 12 | tests_dir = os.path.dirname(__file__) |
| 13 | tests_dir = os.path.normpath(tests_dir) |
| 14 | tests_dir = os.path.abspath(tests_dir) |
Alex | 265f45e | 2019-04-23 18:51:23 -0500 | [diff] [blame] | 15 | |
| 16 | |
| 17 | class CfgCheckerTestBase(unittest.TestCase): |
| 18 | dummy_base_var = 0 |
Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 19 | last_stderr = "" |
| 20 | last_stdout = "" |
Alex | 265f45e | 2019-04-23 18:51:23 -0500 | [diff] [blame] | 21 | |
Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 22 | def _safe_import(self, _str): |
| 23 | if "." not in _str: |
| 24 | return self._safe_import_module(_str) |
| 25 | else: |
| 26 | return self._safe_import_class(_str) |
| 27 | |
| 28 | def _safe_import_class(self, _str): |
| 29 | _import_msg = "" |
| 30 | attrs = _str.split('.') |
| 31 | _import_msg, _module = self._safe_import_module(attrs[0]) |
| 32 | if _import_msg: |
| 33 | return _import_msg, _module |
| 34 | else: |
| 35 | for attr_name in attrs[1:]: |
| 36 | _module = getattr(_module, attr_name) |
| 37 | return "", _module |
| 38 | |
| 39 | @staticmethod |
| 40 | def _safe_import_module(_str, *args, **kwargs): |
Alex | 265f45e | 2019-04-23 18:51:23 -0500 | [diff] [blame] | 41 | _import_msg = "" |
| 42 | _module = None |
| 43 | |
| 44 | try: |
Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 45 | _module = __import__(_str, *args, **kwargs) |
Alex | 265f45e | 2019-04-23 18:51:23 -0500 | [diff] [blame] | 46 | except ImportError as e: |
| 47 | _import_msg = e.message |
| 48 | |
| 49 | return _import_msg, _module |
| 50 | |
Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 51 | @staticmethod |
| 52 | def _safe_run(_obj, *args, **kwargs): |
| 53 | _m = "" |
| 54 | try: |
| 55 | _r = _obj(*args, **kwargs) |
| 56 | except Exception as ex: |
| 57 | if hasattr(ex, 'message'): |
| 58 | _m = "{}: {}".format(str(_obj), ex.message) |
| 59 | elif hasattr(ex, 'msg'): |
| 60 | _m = "{}: {}".format(str(_obj), ex.msg) |
| 61 | else: |
| 62 | _m = "{}: {}".format(str(_obj), "<no message>") |
| 63 | return _r, _m |
| 64 | |
| 65 | def run_main(self, args_list): |
| 66 | _module_name = 'cfg_checker.cfg_check' |
| 67 | _m = self._try_import(_module_name) |
| 68 | with self.save_arguments(): |
| 69 | with self.redirect_output(): |
| 70 | with self.assertRaises(SystemExit) as ep: |
| 71 | sys.argv = ["fake.py"] + args_list |
| 72 | _m.cfg_check.config_check_entrypoint() |
| 73 | return ep.exception.code |
| 74 | |
| 75 | def run_cli(self, command, args_list): |
| 76 | _module_name = 'cfg_checker.cli.command' |
| 77 | _m = self._try_import(_module_name) |
| 78 | with self.save_arguments(): |
| 79 | with self.redirect_output(): |
| 80 | with self.assertRaises(SystemExit) as ep: |
| 81 | import sys |
| 82 | sys.argv = ["fake.py"] + args_list |
| 83 | _m.cli.command.cli_command( |
| 84 | "Fake run for '{} {}'".format( |
| 85 | command, |
| 86 | " ".join(args_list) |
| 87 | ), |
| 88 | command |
| 89 | ) |
| 90 | return ep.exception.code |
| 91 | |
Alex | 265f45e | 2019-04-23 18:51:23 -0500 | [diff] [blame] | 92 | @contextlib.contextmanager |
| 93 | def redirect_output(self): |
| 94 | save_stdout = sys.stdout |
| 95 | save_stderr = sys.stderr |
Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 96 | sys.stdout = io.StringIO() |
| 97 | sys.stderr = io.StringIO() |
| 98 | logging.disable(logging.CRITICAL) |
Alex | 265f45e | 2019-04-23 18:51:23 -0500 | [diff] [blame] | 99 | yield |
| 100 | sys.stdout = save_stdout |
| 101 | sys.stderr = save_stderr |
Alex | 3bc95f6 | 2020-03-05 17:00:04 -0600 | [diff] [blame] | 102 | |
| 103 | @contextlib.contextmanager |
| 104 | def save_arguments(self): |
| 105 | _argv = deepcopy(sys.argv) |
| 106 | yield |
| 107 | sys.argv = _argv |
| 108 | |
| 109 | def _try_import(self, module_name): |
| 110 | with self.redirect_output(): |
| 111 | _msg, _m = self._safe_import_module(module_name) |
| 112 | |
| 113 | self.assertEqual( |
| 114 | len(_msg), |
| 115 | 0, |
| 116 | "Error importing '{}': {}".format( |
| 117 | module_name, |
| 118 | _msg |
| 119 | ) |
| 120 | ) |
| 121 | |
| 122 | return _m |