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