Exemple #1
0
    def test_main_some_args(self):
        reloader = MockReloader('example_service.standalone', ['pysoa'])

        mock_func = mock.MagicMock()

        # noinspection PyUnresolvedReferences
        with mock.patch.object(
                target=reloader,
                attribute='watch_and_reload') as mock_watch_and_reload:
            reloader.main(mock_func, ('a', 'b'), {'c': 'd'})

            mock_watch_and_reload.assert_called_once_with(
                mock_func, ('a', 'b'), {'c': 'd'})

        self.assertFalse(mock_func.called)
Exemple #2
0
    def test_only_file_watcher_argument_no_values(self, mock_get_reloader):
        server_getter = mock.MagicMock()

        sys.argv = [
            '/path/to/example_service/standalone.py', '--use-file-watcher'
        ]

        standalone.simple_main(server_getter)

        server_getter.assert_called_once_with()
        self.assertFalse(server_getter.return_value.main.called)

        mock_get_reloader.assert_called_once_with('', None, signal_forks=False)
        self.assertEqual(1, mock_get_reloader.return_value.main.call_count)
        self.assertEqual(
            server_getter.return_value,
            mock_get_reloader.return_value.main.call_args_list[0][0][1][1],
        )
Exemple #3
0
def _start_patches(test_target):
    if 'mock_patches' in test_target:
        for mock_target, config in six.iteritems(test_target['mock_patches']):
            config['patcher'] = unittest_mock.patch(mock_target, new=unittest_mock.MagicMock())
            config['magic_mock'] = config['patcher'].start()

            if config['configure']:
                # The code in this came, and is slightly modified, from unittest.mock.Mock
                # "We sort on the number of dots so that attributes are set before we set attributes on attributes"
                for path, value in sorted(config['configure'].items(), key=lambda e: e[0].count('.')):
                    paths = path.split('.')
                    final = paths.pop()
                    obj = config['magic_mock']
                    for entry in paths:
                        obj = getattr(obj, entry)
                    if value is _DELETE_ATTRIBUTE:
                        delattr(obj, final)
                    else:
                        setattr(obj, final, value)
    def test_watch_and_reload_for_restart(self, mock_sys, mock_os):
        reloader = MockReloader('example_service.standalone', ['pysoa'])

        mock_func = mock.MagicMock()

        # noinspection PyUnresolvedReferences
        with mock.patch.object(target=reloader, attribute='restart_with_reloader') as mock_restart_with_reloader,\
                mock.patch.object(target=reloader, attribute='watch_files') as mock_watch_files,\
                mock.patch.object(target=reloader, attribute='stop_watching') as mock_stop_watching:

            mock_os.environ.get.return_value = None
            mock_restart_with_reloader.return_value = 15

            reloader.watch_and_reload(mock_func, (), {})

            mock_restart_with_reloader.assert_called_once_with()
            mock_sys.exit.assert_called_once_with(15)
            mock_os.environ.get.assert_called_once_with(
                'PYSOA_RELOADER_RUN_MAIN')
            self.assertFalse(mock_watch_files.called)
            self.assertFalse(mock_stop_watching.called)
            self.assertFalse(mock_os.getpid.called)
            self.assertFalse(mock_os.kill.called)

            mock_restart_with_reloader.reset_mock()
            mock_sys.reset_mock()
            mock_os.reset_mock()

            mock_restart_with_reloader.return_value = -21
            mock_os.getpid.return_value = 92738

            reloader.watch_and_reload(mock_func, (), {})

            mock_restart_with_reloader.assert_called_once_with()
            mock_os.getpid.assert_called_once_with()
            mock_os.kill.assert_called_once_with(92738, 21)
            mock_os.environ.get.assert_called_once_with(
                'PYSOA_RELOADER_RUN_MAIN')
            self.assertFalse(mock_watch_files.called)
            self.assertFalse(mock_stop_watching.called)
            self.assertFalse(mock_sys.exit.called)
Exemple #5
0
    def test_assert_warns_regex(self):
        with self.assertWarnsRegex(DeprecationWarning, '[a-z]+') as context:
            warnings.warn('hello', DeprecationWarning)
        assert issubclass(context.list[0].category, DeprecationWarning)

        with self.assertWarnsRegex(FutureWarning, '[a-z]+') as context:
            warnings.warn('goodbye', FutureWarning)
        assert issubclass(context.list[0].category, FutureWarning)

        with pytest.raises(pytest.raises.Exception):
            with self.assertWarnsRegex(DeprecationWarning, '[a-z]+'):
                warnings.warn('1234', DeprecationWarning)

        flags = mock.MagicMock()
        del flags.raise_value
        del flags.raise_type

        def raise_value(*args, **kwargs):
            flags.raise_value = args, kwargs
            if not args or args[0] is not False:
                warnings.warn('hello', DeprecationWarning)
            else:
                warnings.warn('1234', DeprecationWarning)

        def raise_type(*args, **kwargs):
            flags.raise_type = args, kwargs
            warnings.warn('goodbye', FutureWarning)

        assert self.assertWarnsRegex(
            DeprecationWarning, '[a-z]+', raise_value, 'foo',
            bar='baz') is None
        assert flags.raise_value == (('foo', ), {'bar': 'baz'})

        assert self.assertWarnsRegex(
            FutureWarning, '[a-z]+', raise_type, 'qux', baz='foo') is None
        assert flags.raise_type == (('qux', ), {'baz': 'foo'})

        with pytest.raises(pytest.raises.Exception):
            self.assertWarnsRegex(DeprecationWarning, '[a-z]+', raise_value,
                                  False)
        assert flags.raise_value == ((False, ), {})
Exemple #6
0
    def test_cleanups(self):
        flags = mock.MagicMock()
        del flags.clean1
        del flags.clean2

        def clean1(*args, **kwargs):
            flags.clean1 = args, kwargs

        def clean2(*args, **kwargs):
            flags.clean2 = args, kwargs

        class PyTestServerTestCase1(PyTestServerTestCase):
            server_class = CompleteServer
            server_settings = {}

            # noinspection PyDeprecation
            def setup_method(self):  # type: () -> None
                super(PyTestServerTestCase1, self).setup_method()

                self.addCleanup(clean1, 'foo', bar='baz')
                self.addCleanup(clean2, 'qux', baz='foo')

        case = PyTestServerTestCase1()
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter('always', DeprecationWarning)

            case.setup_method()

        assert w is not None
        assert len(w) == 2
        assert issubclass(w[0].category, DeprecationWarning)
        assert issubclass(w[1].category, DeprecationWarning)

        assert not hasattr(flags, 'clean1')
        assert not hasattr(flags, 'clean2')

        case.teardown_method()

        assert flags.clean1 == (('foo', ), {'bar': 'baz'})
        assert flags.clean2 == (('qux', ), {'baz': 'foo'})
Exemple #7
0
    def test_assert_raises_regex(self):
        with self.assertRaisesRegex(ValueError, '[a-z]+') as context:
            raise ValueError('hello')
        assert context.value.args == ('hello', )
        assert context.exception.args == ('hello', )

        with self.assertRaisesRegex(TypeError, '[a-z]+') as context:
            raise TypeError('goodbye')
        assert context.value.args == ('goodbye', )
        assert context.exception.args == ('goodbye', )

        with pytest.raises(AssertionError):
            with self.assertRaisesRegex(ValueError, '[a-z]+'):
                raise ValueError('1234')

        flags = mock.MagicMock()
        del flags.raise_value
        del flags.raise_type

        def raise_value(*args, **kwargs):
            flags.raise_value = args, kwargs
            if not args or args[0] is not False:
                raise ValueError('hello')
            raise ValueError('1234')

        def raise_type(*args, **kwargs):
            flags.raise_type = args, kwargs
            raise TypeError('goodbye')

        assert self.assertRaisesRegex(
            ValueError, '[a-z]+', raise_value, 'foo', bar='baz') is None
        assert flags.raise_value == (('foo', ), {'bar': 'baz'})

        assert self.assertRaisesRegex(
            TypeError, '[a-z]+', raise_type, 'qux', baz='foo') is None
        assert flags.raise_type == (('qux', ), {'baz': 'foo'})

        with pytest.raises(AssertionError):
            self.assertRaisesRegex(ValueError, '[a-z]+', raise_value, False)
        assert flags.raise_value == ((False, ), {})
Exemple #8
0
    def test_assert_raises(self):
        with self.assertRaises(ValueError) as context:
            raise ValueError()
        assert context.value.args == ()
        assert context.exception.args == ()

        with self.assertRaises(TypeError) as context:
            raise TypeError()
        assert context.value.args == ()
        assert context.exception.args == ()

        with pytest.raises(pytest.raises.Exception):
            with self.assertRaises(ValueError):
                assert 1 == 1

        flags = mock.MagicMock()
        del flags.raise_value
        del flags.raise_type

        def raise_value(*args, **kwargs):
            flags.raise_value = args, kwargs
            if not args or args[0] is not False:
                raise ValueError()

        def raise_type(*args, **kwargs):
            flags.raise_type = args, kwargs
            raise TypeError()

        assert self.assertRaises(ValueError, raise_value, 'foo',
                                 bar='baz') is None
        assert flags.raise_value == (('foo', ), {'bar': 'baz'})

        assert self.assertRaises(TypeError, raise_type, 'qux',
                                 baz='foo') is None
        assert flags.raise_type == (('qux', ), {'baz': 'foo'})

        with pytest.raises(pytest.raises.Exception):
            self.assertRaises(ValueError, raise_value, False)
        assert flags.raise_value == ((False, ), {})
    def test_only_file_watcher_argument_no_values(self, mock_get_reloader):
        server_getter = mock.MagicMock()

        sys.argv = [
            '/path/to/example_service/standalone.py', '--use-file-watcher'
        ]

        standalone.simple_main(server_getter)  # type: ignore

        server_getter.assert_called_once_with()
        self.assertFalse(server_getter.return_value.main.called)

        assert mock_get_reloader.call_count == 1
        assert mock_get_reloader.call_args_list[0][0][0] in ('', 'pytest',
                                                             'coverage')
        assert mock_get_reloader.call_args_list[0][0][1] is None
        assert mock_get_reloader.call_args_list[0][1]['signal_forks'] is False

        self.assertEqual(1, mock_get_reloader.return_value.main.call_count)
        self.assertEqual(
            server_getter.return_value,
            mock_get_reloader.return_value.main.call_args_list[0][0][1][1],
        )
Exemple #10
0
    def test_only_file_watcher_argument_some_values(self, mock_get_reloader):
        server_getter = mock.MagicMock()

        sys.argv = [
            '/path/to/example_service/standalone.py', '--use-file-watcher',
            'example,pysoa,conformity'
        ]

        standalone.simple_main(server_getter)

        server_getter.assert_called_once_with()
        self.assertFalse(server_getter.return_value.main.called)

        mock_get_reloader.assert_called_once_with(
            '', ['example', 'pysoa', 'conformity'], signal_forks=False)
        self.assertEqual(1, mock_get_reloader.return_value.main.call_count)
        self.assertEqual(
            0, mock_get_reloader.return_value.main.call_args_list[0][0][1]
            [0].fork_processes)
        self.assertEqual(
            server_getter.return_value,
            mock_get_reloader.return_value.main.call_args_list[0][0][1][1],
        )
Exemple #11
0
 def __init__(self):
     super(MockSentinelRedis, self).__init__(strict=True,
                                             load_lua_dependencies=False)
     self.connection_pool = mock.MagicMock()
     self.connection_pool.get_master_address.return_value = (
         '192.0.2.13', '6379')  # used official "example" address
Exemple #12
0
    def test_filter(self):
        record = mock.MagicMock()

        log_filter = PySOALogContextFilter()

        self.assertTrue(log_filter.filter(record))
        self.assertEqual('--', record.correlation_id)
        self.assertEqual('--', record.request_id)
        self.assertEqual('unknown', record.service_name)

        PySOALogContextFilter.set_service_name('foo_qux')
        PySOALogContextFilter.set_logging_request_context(
            filter='mine', **{'logger': 'yours'})
        self.assertEqual({
            'filter': 'mine',
            'logger': 'yours'
        }, PySOALogContextFilter.get_logging_request_context())

        record.reset_mock()

        self.assertTrue(log_filter.filter(record))
        self.assertEqual('--', record.correlation_id)
        self.assertEqual('--', record.request_id)
        self.assertEqual('foo_qux', record.service_name)

        PySOALogContextFilter.set_logging_request_context(
            request_id=4321, **{'correlation_id': 'abc1234'})
        self.assertEqual({
            'request_id': 4321,
            'correlation_id': 'abc1234'
        }, PySOALogContextFilter.get_logging_request_context())

        record.reset_mock()

        self.assertTrue(log_filter.filter(record))
        self.assertEqual('abc1234', record.correlation_id)
        self.assertEqual(4321, record.request_id)
        self.assertEqual('foo_qux', record.service_name)

        PySOALogContextFilter.clear_logging_request_context()
        self.assertEqual({
            'filter': 'mine',
            'logger': 'yours'
        }, PySOALogContextFilter.get_logging_request_context())

        record.reset_mock()

        self.assertTrue(log_filter.filter(record))
        self.assertEqual('--', record.correlation_id)
        self.assertEqual('--', record.request_id)
        self.assertEqual('foo_qux', record.service_name)

        PySOALogContextFilter.clear_logging_request_context()
        self.assertIsNone(PySOALogContextFilter.get_logging_request_context())

        record.reset_mock()

        self.assertTrue(log_filter.filter(record))
        self.assertEqual('--', record.correlation_id)
        self.assertEqual('--', record.request_id)
        self.assertEqual('foo_qux', record.service_name)
Exemple #13
0
    def reset(cls, include_setup=True):
        if include_setup:
            if hasattr(cls, '_test_fixture_setup_called'):
                del cls._test_fixture_setup_called
            if hasattr(cls, '_test_fixture_setup_succeeded'):
                del cls._test_fixture_setup_succeeded

        cls.addError = mock.MagicMock()
        cls.addFailure = mock.MagicMock()
        cls.set_up_test_fixture = mock.MagicMock()
        cls.tear_down_test_fixture = mock.MagicMock()
        cls.setUp = mock.MagicMock()
        cls.tearDown = mock.MagicMock()
        cls.set_up_test_case = mock.MagicMock()
        cls.tear_down_test_case = mock.MagicMock()
        cls.set_up_test_case_action = mock.MagicMock()
        cls.tear_down_test_case_action = mock.MagicMock()
        cls._run_test_case = mock.MagicMock()

        cls._all_directives = (mock.MagicMock(), )
        # Mock doesn't automatically mock methods that start with `assert`, so we have to do this
        cls._all_directives[
            0].return_value.assert_test_fixture_results = mock.MagicMock()
    def test_other_error_on_assert_test_fixture_results_some_other_errors(
            self):
        test_case = {'my': 'case'}
        test_fixture = [{'foo': 'bar'}]
        test_fixture_results = [{
            'baz': None
        }]  # type: List[Dict[six.text_type, Optional[ActionResponse]]]

        test = MockedTestCase()

        case_data = mock.MagicMock()
        case_data.fixture_name = 'bbb'
        case_data.test_fixture = test_fixture

        test_function = test._create_test_function('aaa', 'bbb', test_case,
                                                   test_fixture,
                                                   test_fixture_results)
        test_function._last_fixture_test = True  # type: ignore
        test._pytest_first_fixture_case = case_data  # type: ignore
        test._pytest_last_fixture_case = case_data  # type: ignore

        mock_dir = cast(mock.MagicMock, test._all_directives[0])

        mock_dir.return_value.assert_test_fixture_results.side_effect = Error3(
        )
        mock_dir.return_value.tear_down_test_fixture.side_effect = Error4()

        test.setup_method()
        with pytest.raises(Error3):
            test_function(test)
        with pytest.raises(Error4):
            test.teardown_method()

        test.set_up_test_fixture.assert_called_once_with(test_fixture)
        test.tear_down_test_fixture.assert_not_called()
        test.set_up_test_case.assert_called_once_with(test_case, test_fixture)
        test.tear_down_test_case.assert_called_once_with(
            test_case, test_fixture)
        test.set_up_test_case_action.assert_not_called()
        test.tear_down_test_case_action.assert_not_called()
        test._run_test_case.assert_called_once_with(test_case, test_fixture,
                                                    test_fixture_results)

        mock_dir.return_value.set_up_test_fixture.assert_called_once_with(
            test_fixture)
        mock_dir.return_value.assert_test_fixture_results.assert_called_once_with(
            test_fixture_results,
            test_fixture,
        )
        mock_dir.return_value.tear_down_test_fixture.assert_called_once_with(
            test_fixture)
        mock_dir.return_value.set_up_test_case.assert_called_once_with(
            test_case, test_fixture)
        mock_dir.return_value.tear_down_test_case.assert_called_once_with(
            test_case, test_fixture)
        mock_dir.return_value.set_up_test_case_action.assert_not_called()
        mock_dir.return_value.tear_down_test_case_action.assert_not_called()

        assert test.add_error.call_count == 0

        assert test.setUpClass.call_count == 0
        assert test.tearDownClass.call_count == 0
class MockedTestCase(ServicePlanTestCase):
    server_class = _TestServiceServer
    server_settings = {}  # type: SettingsData

    add_error = mock.MagicMock()
    set_up_test_fixture = mock.MagicMock()
    tear_down_test_fixture = mock.MagicMock()
    set_up_test_case = mock.MagicMock()
    tear_down_test_case = mock.MagicMock()
    set_up_test_case_action = mock.MagicMock()
    tear_down_test_case_action = mock.MagicMock()
    _run_test_case = mock.MagicMock()

    setUpClass = mock.MagicMock()
    setUpClass.__func__ = ServicePlanTestCase.setUpClass.__func__  # type: ignore
    tearDownClass = mock.MagicMock()
    tearDownClass.__func__ = ServicePlanTestCase.tearDownClass.__func__  # type: ignore

    _all_directives = [
        cast(Type[Directive], mock.MagicMock()),
    ]

    @classmethod
    def reset(cls):
        cls._test_fixture_setup_called = {}  # type: ignore
        cls._test_fixture_setup_succeeded = {}  # type: ignore

        cls.add_error = mock.MagicMock()
        cls.set_up_test_fixture = mock.MagicMock()
        cls.tear_down_test_fixture = mock.MagicMock()
        cls.set_up_test_case = mock.MagicMock()
        cls.tear_down_test_case = mock.MagicMock()
        cls.set_up_test_case_action = mock.MagicMock()
        cls.tear_down_test_case_action = mock.MagicMock()
        cls._run_test_case = mock.MagicMock()

        cls._all_directives = [
            cast(Type[Directive], mock.MagicMock()),
        ]
        # Mock doesn't automatically mock methods that start with `assert`, so we have to do this
        cls._all_directives[
            0].return_value.assert_test_fixture_results = mock.MagicMock(
            )  # type: ignore
    def test_normal_fixture_tear_down(self):
        test_case = {'my': 'case'}
        test_fixture = [{'foo': 'bar'}]
        test_fixture_results = [{
            'baz': None
        }]  # type: List[Dict[six.text_type, Optional[ActionResponse]]]

        test = MockedTestCase()

        case_data = mock.MagicMock()
        case_data.fixture_name = 'my_fixture'
        case_data.test_fixture = test_fixture

        test_function = test._create_test_function(
            'My test description',
            'my_fixture',
            test_case,
            test_fixture,
            test_fixture_results,
        )
        test_function._last_fixture_test = True  # type: ignore
        test._pytest_first_fixture_case = case_data  # type: ignore
        test._pytest_last_fixture_case = case_data  # type: ignore

        assert test_function.__doc__ == 'My test description'

        test.setup_method()
        test_function(test)
        test.teardown_method()

        test.set_up_test_fixture.assert_called_once_with(test_fixture)
        test.tear_down_test_fixture.assert_called_once_with(test_fixture)
        test.set_up_test_case.assert_called_once_with(test_case, test_fixture)
        test.tear_down_test_case.assert_called_once_with(
            test_case, test_fixture)
        test.set_up_test_case_action.assert_not_called()
        test.tear_down_test_case_action.assert_not_called()
        test._run_test_case.assert_called_once_with(test_case, test_fixture,
                                                    test_fixture_results)

        mock_dir = cast(mock.MagicMock, test._all_directives[0])
        mock_dir.return_value.set_up_test_fixture.assert_called_once_with(
            test_fixture)
        mock_dir.return_value.assert_test_fixture_results.assert_called_once_with(
            test_fixture_results,
            test_fixture,
        )
        mock_dir.return_value.tear_down_test_fixture.assert_called_once_with(
            test_fixture)
        mock_dir.return_value.set_up_test_case.assert_called_once_with(
            test_case, test_fixture)
        mock_dir.return_value.tear_down_test_case.assert_called_once_with(
            test_case, test_fixture)
        mock_dir.return_value.set_up_test_case_action.assert_not_called()
        mock_dir.return_value.tear_down_test_case_action.assert_not_called()

        test.teardown_class()

        test.tear_down_test_fixture.assert_called_once_with(test_fixture)
        mock_dir.return_value.tear_down_test_fixture.assert_called_once_with(
            test_fixture)

        test.add_error.assert_not_called()

        assert test.setUpClass.call_count == 0
        assert test.tearDownClass.call_count == 0
Exemple #17
0
class MockedTestCase(ServicePlanTestCase):
    addError = mock.MagicMock()
    addFailure = mock.MagicMock()
    set_up_test_fixture = mock.MagicMock()
    tear_down_test_fixture = mock.MagicMock()
    setUp = mock.MagicMock()
    tearDown = mock.MagicMock()
    set_up_test_case = mock.MagicMock()
    tear_down_test_case = mock.MagicMock()
    set_up_test_case_action = mock.MagicMock()
    tear_down_test_case_action = mock.MagicMock()
    _run_test_case = mock.MagicMock()

    _all_directives = (mock.MagicMock(), )

    def __init__(self):
        super(MockedTestCase, self).__init__('fake_test')

    def fake_test(self):
        """
        This is so that we can instantiate the class.
        """

    @classmethod
    def reset(cls, include_setup=True):
        if include_setup:
            if hasattr(cls, '_test_fixture_setup_called'):
                del cls._test_fixture_setup_called
            if hasattr(cls, '_test_fixture_setup_succeeded'):
                del cls._test_fixture_setup_succeeded

        cls.addError = mock.MagicMock()
        cls.addFailure = mock.MagicMock()
        cls.set_up_test_fixture = mock.MagicMock()
        cls.tear_down_test_fixture = mock.MagicMock()
        cls.setUp = mock.MagicMock()
        cls.tearDown = mock.MagicMock()
        cls.set_up_test_case = mock.MagicMock()
        cls.tear_down_test_case = mock.MagicMock()
        cls.set_up_test_case_action = mock.MagicMock()
        cls.tear_down_test_case_action = mock.MagicMock()
        cls._run_test_case = mock.MagicMock()

        cls._all_directives = (mock.MagicMock(), )
        # Mock doesn't automatically mock methods that start with `assert`, so we have to do this
        cls._all_directives[
            0].return_value.assert_test_fixture_results = mock.MagicMock()
    def test_forking_with_default_respawn(self, mock_cpu_count, mock_process):
        server_getter = mock.MagicMock()

        mock_cpu_count.return_value = 2

        sys.argv = ['/path/to/example_service/standalone.py', '-f', '3']

        prev_sigint = prev_sigterm = prev_sighup = None
        try:
            prev_sigint = signal.signal(signal.SIGINT, signal.SIG_IGN)
            prev_sigterm = signal.signal(signal.SIGTERM, signal.SIG_IGN)
            prev_sighup = signal.signal(signal.SIGHUP, signal.SIG_IGN)

            living_processes = []
            quick_dying_processes = []
            slow_dying_processes = []
            bad_processes = []

            def patched_freeze_time():
                # TODO Until https://github.com/spulec/freezegun/issues/307 is fixed
                f = freezegun.freeze_time()
                f.ignore = tuple(set(f.ignore) - {'threading'})
                return f

            with patched_freeze_time() as frozen_time:

                def tick_six_se():
                    frozen_time.tick(datetime.timedelta(seconds=6))

                def tick_twenty_se():
                    frozen_time.tick(datetime.timedelta(seconds=20))

                def signal_se():
                    os.kill(os.getpid(), signal.SIGTERM)
                    time.sleep(0.3)

                def se(target, name, args):
                    process = mock.MagicMock()
                    process.culprit = (target, name, args)
                    if args[0] == 1:
                        # If it's the first process, we want to actually live. This tests normal operation.
                        living_processes.append(process)
                        if len(living_processes) == 6:
                            raise ValueError('Too many, too many!')
                        elif len(living_processes) == 5:
                            process.join.side_effect = signal_se
                        else:
                            process.join.side_effect = tick_twenty_se
                        if len(living_processes) == 1:
                            time.sleep(
                                3
                            )  # sleep 3 seconds so that all of these happen after quick- and slow-dying
                    elif args[0] == 2:
                        # If it's the second process, we want to die quickly. This tests the 15-second respawn limit.
                        quick_dying_processes.append(process)
                        # no sleep so that all of these happen before any ticks, before slow-dying and living
                    elif args[0] == 3:
                        # If it's the third process, we want to die slowly. This tests the 60-second respawn limit.
                        slow_dying_processes.append(process)
                        process.join.side_effect = tick_six_se
                        if len(slow_dying_processes) == 1:
                            time.sleep(
                                1
                            )  # sleep 1 second so that all of these happen after quick-dying
                    else:
                        bad_processes.append((target, name, args))
                        raise ValueError('Nope nope nope')
                    return process

                mock_process.side_effect = se

                standalone.simple_main(server_getter)  # type: ignore

            server_getter.assert_called_once_with()
            assert server_getter.return_value.main.called is False

            assert len(bad_processes) == 0
            assert len(quick_dying_processes) == 4
            assert len(slow_dying_processes) == 9
            assert len(living_processes) == 5

            for i, p in enumerate(living_processes):
                assert p.culprit[0] is server_getter.return_value.main
                assert p.culprit[1] == 'pysoa-worker-1'
                assert p.culprit[2] == (1, )
                if i < 5:
                    p.start.assert_called_once_with()
                    p.join.assert_called_once_with()
            for p in living_processes[:-1]:
                assert p.terminate.called is False
            living_processes[-1].terminate.assert_called_once_with()

            for p in quick_dying_processes:
                assert p.culprit[0] is server_getter.return_value.main
                assert p.culprit[1] == 'pysoa-worker-2'
                assert p.culprit[2] == (2, )
                p.start.assert_called_once_with()
                p.join.assert_called_once_with()
                assert p.terminate.called is False

            for p in slow_dying_processes:
                assert p.culprit[0] is server_getter.return_value.main
                assert p.culprit[1] == 'pysoa-worker-3'
                assert p.culprit[2] == (3, )
                p.start.assert_called_once_with()
                p.join.assert_called_once_with()
                assert p.terminate.called is False
        finally:
            if prev_sigint is not None:
                signal.signal(signal.SIGINT, prev_sigint or signal.SIG_IGN)
            if prev_sigterm is not None:
                signal.signal(signal.SIGTERM, prev_sigterm or signal.SIG_IGN)
            if prev_sighup is not None:
                signal.signal(signal.SIGHUP, prev_sighup or signal.SIG_IGN)