"""Tests for certbot.error_handler.""" import contextlib import signal import sys import unittest import mock # pylint: disable=unused-import, no-name-in-module from acme.magic_typing import Callable, Dict, Union # pylint: enable=unused-import, no-name-in-module from certbot.compat import os def get_signals(signums): """Get the handlers for an iterable of signums.""" return dict((s, signal.getsignal(s)) for s in signums) def set_signals(sig_handler_dict): """Set the signal (keys) with the handler (values) from the input dict.""" for s, h in sig_handler_dict.items(): signal.signal(s, h) @contextlib.contextmanager def signal_receiver(signums): """Context manager to catch signals""" signals = [] prev_handlers = get_signals(signums) # type: Dict[int, Union[int, None, Callable]] set_signals(dict((s, lambda s, _: signals.append(s)) for s in signums)) yield signals set_signals(prev_handlers) def send_signal(signum): """Send the given signal""" os.kill(os.getpid(), signum) class ErrorHandlerTest(unittest.TestCase): """Tests for certbot.error_handler.ErrorHandler.""" def setUp(self): from certbot import error_handler self.init_func = mock.MagicMock() self.init_args = set((42,)) self.init_kwargs = {'foo': 'bar'} self.handler = error_handler.ErrorHandler(self.init_func, *self.init_args, **self.init_kwargs) # pylint: disable=protected-access self.signals = error_handler._SIGNALS def test_context_manager(self): exception_raised = False try: with self.handler: raise ValueError except ValueError: exception_raised = True self.assertTrue(exception_raised) self.init_func.assert_called_once_with(*self.init_args, **self.init_kwargs) def test_context_manager_with_signal(self): if not self.signals: self.skipTest(reason='Signals cannot be handled on Windows.') init_signals = get_signals(self.signals) with signal_receiver(self.signals) as signals_received: with self.handler: should_be_42 = 42 send_signal(self.signals[0]) should_be_42 *= 10 # check execution stoped when the signal was sent self.assertEqual(42, should_be_42) # assert signals were caught self.assertEqual([self.signals[0]], signals_received) # assert the error handling function was just called once self.init_func.assert_called_once_with(*self.init_args, **self.init_kwargs) for signum in self.signals: self.assertEqual(init_signals[signum], signal.getsignal(signum)) def test_bad_recovery(self): bad_func = mock.MagicMock(side_effect=[ValueError]) self.handler.register(bad_func) try: with self.handler: raise ValueError except ValueError: pass self.init_func.assert_called_once_with(*self.init_args, **self.init_kwargs) bad_func.assert_called_once_with() def test_bad_recovery_with_signal(self): if not self.signals: self.skipTest(reason='Signals cannot be handled on Windows.') sig1 = self.signals[0] sig2 = self.signals[-1] bad_func = mock.MagicMock(side_effect=lambda: send_signal(sig1)) self.handler.register(bad_func) with signal_receiver(self.signals) as signals_received: with self.handler: send_signal(sig2) self.assertEqual([sig2, sig1], signals_received) self.init_func.assert_called_once_with(*self.init_args, **self.init_kwargs) bad_func.assert_called_once_with() def test_sysexit_ignored(self): try: with self.handler: sys.exit(0) except SystemExit: pass self.assertFalse(self.init_func.called) def test_regular_exit(self): func = mock.MagicMock() self.handler.register(func) with self.handler: pass self.init_func.assert_not_called() func.assert_not_called() class ExitHandlerTest(ErrorHandlerTest): """Tests for certbot.error_handler.ExitHandler.""" def setUp(self): from certbot import error_handler super(ExitHandlerTest, self).setUp() self.handler = error_handler.ExitHandler(self.init_func, *self.init_args, **self.init_kwargs) def test_regular_exit(self): func = mock.MagicMock() self.handler.register(func) with self.handler: pass self.init_func.assert_called_once_with(*self.init_args, **self.init_kwargs) func.assert_called_once_with() if __name__ == "__main__": unittest.main() # pragma: no cover
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
__pycache__ | Folder | 0755 |
|
|
compat | Folder | 0755 |
|
|
display | Folder | 0755 |
|
|
testdata | Folder | 0755 |
|
|
__init__.py | File | 20 B | 0644 |
|
account_test.py | File | 13.79 KB | 0644 |
|
acme_util.py | File | 2.85 KB | 0644 |
|
auth_handler_test.py | File | 21.79 KB | 0644 |
|
cert_manager_test.py | File | 28.16 KB | 0644 |
|
cli_test.py | File | 21.26 KB | 0644 |
|
client_test.py | File | 31.74 KB | 0644 |
|
configuration_test.py | File | 6.82 KB | 0644 |
|
crypto_util_test.py | File | 13.43 KB | 0644 |
|
eff_test.py | File | 5.94 KB | 0644 |
|
error_handler_test.py | File | 5.14 KB | 0644 |
|
errors_test.py | File | 1.8 KB | 0644 |
|
hook_test.py | File | 17.44 KB | 0644 |
|
lock_test.py | File | 4.87 KB | 0644 |
|
log_test.py | File | 14.9 KB | 0644 |
|
main_test.py | File | 82.76 KB | 0644 |
|
notify_test.py | File | 2.07 KB | 0644 |
|
ocsp_test.py | File | 16.3 KB | 0644 |
|
renewal_test.py | File | 5.03 KB | 0644 |
|
renewupdater_test.py | File | 5.32 KB | 0644 |
|
reporter_test.py | File | 2.73 KB | 0644 |
|
reverter_test.py | File | 18.1 KB | 0644 |
|
storage_test.py | File | 41.63 KB | 0644 |
|
util.py | File | 13.77 KB | 0644 |
|
util_test.py | File | 21.2 KB | 0644 |
|