def test_stop_subcommand_doesnt_kill_pid_if_pid_file_doesnt_exist(self):
        self.os_path_exists_patch.return_value = False

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.assertFalse(self.os_kill_patch.called)
    def setUp(self):
        super().setUp()
        self._mock_os_path_exists = self.patch('os.path.exists')
        self._mock_psutil_pid_exists = self.patch('psutil.pid_exists')
        self._mock_psutil_process = self.patch('psutil.Process')

        self._fake_slave_pid_file_sys_path = join(os.getcwd(),
                                                  'slave_pid_file')
        self._fake_master_pid_file_sys_path = join(os.getcwd(),
                                                   'master_pid_file')
        Configuration['slave_pid_file'] = self._fake_slave_pid_file_sys_path
        Configuration['master_pid_file'] = self._fake_master_pid_file_sys_path

        self._fake_slave_pid = 1111
        self._fake_master_pid = 2222
        self._mock_open = mock_open()
        self._mock_open.side_effect = [
            StringIO(str(self._fake_slave_pid)
                     ),  # pretend to be fhe slave pid file object
            StringIO(str(self._fake_master_pid)
                     ),  # pretend to be the master pid file object
        ]

        self.patch('app.subcommands.stop_subcommand.open',
                   new=self._mock_open,
                   create=True)
        self._mock_os_remove = self.patch('os.remove')

        self._stop_subcommand = StopSubcommand()

        # setup the return value of time.time() and SIGTERM grace period so the test won't actually sleep
        self._stop_subcommand.SIGTERM_SIGKILL_GRACE_PERIOD_SEC = -1
        mock_time = self.patch('time.time')
        mock_time.return_value = 0
Ejemplo n.º 3
0
    def test_stop_subcommand_doesnt_kill_pid_if_pid_file_doesnt_exist(self):
        self.os_path_exists_patch.return_value = False

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.assertFalse(self.os_kill_patch.called)
    def test_stop_subcommand_doesnt_kill_pid_if_pid_file_exists_but_pid_doesnt_exist(self):
        self.os_path_exists_patch.return_value = True
        self.psutil_pid_exists_patch.side_effect = [False]
        self._mock_open(read_data='9999')

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.assertFalse(self.os_kill_patch.called)
Ejemplo n.º 5
0
    def test_stop_subcommand_doesnt_kill_pid_if_pid_file_exists_but_pid_doesnt_exist(self):
        self.os_path_exists_patch.return_value = True
        self.psutil_pid_exists_patch.side_effect = [False]
        self._mock_open(read_data='9999')

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.assertFalse(self.os_kill_patch.called)
Ejemplo n.º 6
0
    def test_stop_subcommand_kills_pid_with_sigterm_if_pid_file_and_pid_exist_and_command_is_whitelisted(self):
        self.os_path_exists_patch.return_value = True
        self._mock_open(read_data='9999')
        self.psutil_pid_exists_patch.side_effect = [True, False, False]
        mock_psutil_process = self.patch('psutil.Process').return_value
        mock_psutil_process.cmdline.return_value = ['python', './main.py', 'master']

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.os_kill_patch.assert_called_with(9999, signal.SIGTERM)
    def test_stop_subcommand_kills_pid_with_sigterm_if_pid_file_and_pid_exist_and_command_is_whitelisted(self):
        self.os_path_exists_patch.return_value = True
        self._mock_open(read_data='9999')
        self.psutil_pid_exists_patch.side_effect = [True, False, False]
        mock_psutil_process = self.patch('psutil.Process').return_value
        mock_psutil_process.cmdline.return_value = ['python', './main.py', 'master']

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.os_kill_patch.assert_called_with(9999, signal.SIGTERM)
Ejemplo n.º 8
0
    def test_stop_subcommand_doesnt_kill_pid_if_pid_file_and_pid_exist_but_command_isnt_whitelisted(self):
        self.os_path_exists_patch.return_value = True
        self.psutil_pid_exists_patch.side_effect = [True]
        self._mock_open(read_data='9999')
        mock_psutil_process = self.patch('psutil.Process').return_value
        mock_psutil_process.cmdline.return_value = ['python', './SOME_OTHER_main.py', 'other_master']

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.assertFalse(self.os_kill_patch.called)
    def test_stop_subcommand_doesnt_kill_pid_if_pid_file_and_pid_exist_but_command_isnt_whitelisted(self):
        self.os_path_exists_patch.return_value = True
        self.psutil_pid_exists_patch.side_effect = [True]
        self._mock_open(read_data='9999')
        mock_psutil_process = self.patch('psutil.Process').return_value
        mock_psutil_process.cmdline.return_value = ['python', './SOME_OTHER_main.py', 'other_master']

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.assertFalse(self.os_kill_patch.called)
Ejemplo n.º 10
0
    def test_stop_subcommand_kills_pid_with_sigterm_if_pid_file_and_pid_exist_and_command_is_whitelisted(self):
        main_proc_pid = 9999
        threshold = NUM_OF_IS_RUNNING_CHECKS_TILL_SIGKILL - 1
        child_pid = main_proc_pid + 1

        self.setup_environment_for_os_kill(main_proc_pid)
        self.setup_main_and_child_proc(main_proc_pid, threshold, child_pid, threshold)

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.os_kill_patch.assert_called_with(main_proc_pid, signal.SIGTERM)
        self.assertEquals(2, self.os_kill_patch.call_count)
Ejemplo n.º 11
0
    def test_stop_subcommand_kills_child_proc_with_sigkill_if_still_running_after_sigterm(self):
        main_proc_pid = 9999
        main_threshold = NUM_OF_IS_RUNNING_CHECKS_TILL_SIGKILL - 1
        child_threshold = NUM_OF_IS_RUNNING_CHECKS_TILL_SIGKILL
        child_pid = main_proc_pid + 1

        self.setup_environment_for_os_kill(main_proc_pid)
        self.setup_main_and_child_proc(main_proc_pid, main_threshold, child_pid, child_threshold)

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.os_kill_patch.assert_called_with(child_pid, signal.SIGKILL)
        self.assertEquals(3, self.os_kill_patch.call_count)
Ejemplo n.º 12
0
    def test_stop_subcommand_kills_proc_with_sigkill(self):
        main_proc_pid = 9999

        self.setup_environment_for_os_kill(main_proc_pid)
        self.patch('psutil.Process').return_value = self.create_process_mock(
            pid=main_proc_pid,
            is_running_threshold=NUM_OF_IS_RUNNING_CHECKS_TILL_SIGKILL,
            cmdline=['python', './main.py', 'master'],
            children=[])

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.os_kill_patch.assert_called_with(main_proc_pid, signal.SIGKILL)
        self.assertEquals(2, self.os_kill_patch.call_count)
Ejemplo n.º 13
0
    def test_stop_subcommand_kills_pid_with_sigterm_if_pid_file_and_pid_exist_and_command_is_whitelisted(
            self):
        main_proc_pid = 9999
        threshold = NUM_OF_IS_RUNNING_CHECKS_TILL_SIGKILL - 1
        child_pid = main_proc_pid + 1

        self.setup_environment_for_os_kill(main_proc_pid)
        self.setup_main_and_child_proc(main_proc_pid, threshold, child_pid,
                                       threshold)

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.os_kill_patch.assert_called_with(main_proc_pid, signal.SIGTERM)
        self.assertEquals(2, self.os_kill_patch.call_count)
Ejemplo n.º 14
0
    def test_stop_subcommand_kills_child_proc_with_sigkill_if_still_running_after_sigterm(
            self):
        main_proc_pid = 9999
        main_threshold = NUM_OF_IS_RUNNING_CHECKS_TILL_SIGKILL - 1
        child_threshold = NUM_OF_IS_RUNNING_CHECKS_TILL_SIGKILL
        child_pid = main_proc_pid + 1

        self.setup_environment_for_os_kill(main_proc_pid)
        self.setup_main_and_child_proc(main_proc_pid, main_threshold,
                                       child_pid, child_threshold)

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.os_kill_patch.assert_called_with(child_pid, signal.SIGKILL)
        self.assertEquals(3, self.os_kill_patch.call_count)
Ejemplo n.º 15
0
    def test_stop_subcommand_kills_proc_with_sigkill(self):
        main_proc_pid = 9999

        self.setup_environment_for_os_kill(main_proc_pid)
        self.patch('psutil.Process').return_value = self.create_process_mock(
            pid=main_proc_pid,
            is_running_threshold=NUM_OF_IS_RUNNING_CHECKS_TILL_SIGKILL,
            cmdline=['python', './main.py', 'master'],
            children=[]
        )

        stop_subcommand = StopSubcommand()
        stop_subcommand._kill_pid_in_file_if_exists('/tmp/pid_file_path.pid')

        self.os_kill_patch.assert_called_with(main_proc_pid, signal.SIGKILL)
        self.assertEquals(2, self.os_kill_patch.call_count)
Ejemplo n.º 16
0
    def setUp(self):
        super().setUp()
        self._mock_os_path_exists = self.patch('os.path.exists')
        self._mock_psutil_pid_exists = self.patch('psutil.pid_exists')
        self._mock_psutil_process = self.patch('psutil.Process')

        self._fake_slave_pid_file_sys_path = join(os.getcwd(), 'slave_pid_file')
        self._fake_master_pid_file_sys_path = join(os.getcwd(), 'master_pid_file')
        Configuration['slave_pid_file'] = self._fake_slave_pid_file_sys_path
        Configuration['master_pid_file'] = self._fake_master_pid_file_sys_path

        self._fake_slave_pid = 1111
        self._fake_master_pid = 2222
        self._mock_open = mock_open()
        self._mock_open.side_effect = [
            StringIO(str(self._fake_slave_pid)),     # pretend to be fhe slave pid file object
            StringIO(str(self._fake_master_pid)),    # pretend to be the master pid file object
        ]

        self.patch('app.subcommands.stop_subcommand.open', new=self._mock_open, create=True)
        self._mock_os_remove = self.patch('os.remove')

        self._stop_subcommand = StopSubcommand()

        # setup the return value of time.time() and SIGTERM grace period so the test won't actually sleep
        self._stop_subcommand.SIGTERM_SIGKILL_GRACE_PERIOD_SEC = -1
        mock_time = self.patch('time.time')
        mock_time.return_value = 0
class TestStopSubcommand(BaseUnitTestCase):
    def setUp(self):
        super().setUp()
        self._mock_os_path_exists = self.patch('os.path.exists')
        self._mock_psutil_pid_exists = self.patch('psutil.pid_exists')
        self._mock_psutil_process = self.patch('psutil.Process')

        self._fake_slave_pid_file_sys_path = join(os.getcwd(),
                                                  'slave_pid_file')
        self._fake_master_pid_file_sys_path = join(os.getcwd(),
                                                   'master_pid_file')
        Configuration['slave_pid_file'] = self._fake_slave_pid_file_sys_path
        Configuration['master_pid_file'] = self._fake_master_pid_file_sys_path

        self._fake_slave_pid = 1111
        self._fake_master_pid = 2222
        self._mock_open = mock_open()
        self._mock_open.side_effect = [
            StringIO(str(self._fake_slave_pid)
                     ),  # pretend to be fhe slave pid file object
            StringIO(str(self._fake_master_pid)
                     ),  # pretend to be the master pid file object
        ]

        self.patch('app.subcommands.stop_subcommand.open',
                   new=self._mock_open,
                   create=True)
        self._mock_os_remove = self.patch('os.remove')

        self._stop_subcommand = StopSubcommand()

        # setup the return value of time.time() and SIGTERM grace period so the test won't actually sleep
        self._stop_subcommand.SIGTERM_SIGKILL_GRACE_PERIOD_SEC = -1
        mock_time = self.patch('time.time')
        mock_time.return_value = 0

    def _setup_pid_file_does_not_exist(self):
        self._mock_os_path_exists.return_value = False

    def _setup_pid_file_exists_but_pid_does_not_exist(self):
        self._mock_os_path_exists.return_value = True
        self._mock_psutil_pid_exists.return_value = False

    def _setup_both_pid_file_and_pids_exist(self):
        self._mock_os_path_exists.return_value = True
        self._mock_psutil_pid_exists.return_value = True

    def test_stop_subcommand_does_not_call_terminate_if_pid_file_does_not_exist(
            self):
        # Arrange
        self._setup_pid_file_does_not_exist()

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self.assertFalse(self._mock_psutil_process.terminate.called)
        self.assertEqual(
            [
                call(self._fake_slave_pid_file_sys_path),
                call(self._fake_master_pid_file_sys_path),
            ],
            self._mock_os_path_exists.call_args_list,
        )

    def test_stop_subcommand_does_not_call_terminate_if_pid_does_not_exist(
            self):
        # Arrange
        self._setup_pid_file_exists_but_pid_does_not_exist()

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self.assertFalse(self._mock_psutil_process.terminate.called)
        self.assertEqual(
            [
                call(self._fake_slave_pid_file_sys_path),
                call(self._fake_master_pid_file_sys_path),
            ],
            self._mock_os_remove.call_args_list,
        )

    def test_stop_subcommand_does_not_call_terminate_if_pid_file_and_pid_exist_but_command_isnt_whitelisted(
            self):
        # Arrange
        self._setup_both_pid_file_and_pids_exist()
        self._setup_processes(
            master_cmdline=['python', './foo.py'],
            slave_cmdline=['python', './bar.py'],
        )

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self.assertFalse(self._mock_psutil_process.terminate.called)

    def _create_mock_process(self, pid, child_processes=None, cmdline=None):
        proc = Mock(psutil.Process)
        proc.pid = pid
        proc.is_running.return_value = True
        if cmdline:
            proc.cmdline.return_value = cmdline
        proc.children.return_value = child_processes if child_processes else []
        return proc

    def _setup_processes(self, master_cmdline=None, slave_cmdline=None):
        master_process = self._create_mock_process(
            self._fake_master_pid,
            cmdline=master_cmdline
            if master_cmdline else ['python', '-m', 'app', 'master'],
        )

        slave_child_process = self._create_mock_process(3333)
        slave_process = self._create_mock_process(
            self._fake_slave_pid,
            child_processes=[slave_child_process],
            cmdline=slave_cmdline
            if slave_cmdline else ['python', '-m', 'app', 'slave'],
        )

        self._mock_psutil_process.side_effect = [
            slave_process,
            master_process,
        ]

        return master_process, slave_process, slave_child_process

    def _assert_called_terminate(self, process_list):
        for proc in process_list:
            self.assertTrue(proc.terminate.called)

    @staticmethod
    def _successful_terminate_or_kill(proc):
        proc.is_running.return_value = False

    def test_stop_subcommand_kills_pid_with_sigterm_if_pid_file_and_pid_exist_and_command_is_whitelisted(
            self):
        # Arrange
        self._setup_both_pid_file_and_pids_exist()
        master_process, slave_process, slave_child_process = self._setup_processes(
        )

        master_process.terminate.side_effect = partial(
            self._successful_terminate_or_kill, master_process)
        slave_process.terminate.side_effect = partial(
            self._successful_terminate_or_kill, slave_process)
        slave_child_process.terminate.side_effect = partial(
            self._successful_terminate_or_kill, slave_child_process)

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self._assert_called_terminate(
            [master_process, slave_process, slave_child_process])
        self.assertFalse(master_process.kill.called)
        self.assertFalse(slave_process.kill.called)
        self.assertFalse(slave_child_process.kill.called)

    def test_stop_subcommand_kills_proc_with_sigkill_if_still_running_after_sigterm(
            self):
        # Arrange
        self._setup_both_pid_file_and_pids_exist()
        master_process, slave_process, slave_child_process = self._setup_processes(
        )
        master_process.terminate.side_effect = partial(
            self._successful_terminate_or_kill, master_process)

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self._assert_called_terminate(
            [master_process, slave_process, slave_child_process])
        self.assertFalse(master_process.kill.called)
        self.assertTrue(slave_process.kill.called)
        self.assertTrue(slave_child_process.kill.called)
Ejemplo n.º 18
0
class TestStopSubcommand(BaseUnitTestCase):

    def setUp(self):
        super().setUp()
        self._mock_os_path_exists = self.patch('os.path.exists')
        self._mock_psutil_pid_exists = self.patch('psutil.pid_exists')
        self._mock_psutil_process = self.patch('psutil.Process')

        self._fake_slave_pid_file_sys_path = join(os.getcwd(), 'slave_pid_file')
        self._fake_master_pid_file_sys_path = join(os.getcwd(), 'master_pid_file')
        Configuration['slave_pid_file'] = self._fake_slave_pid_file_sys_path
        Configuration['master_pid_file'] = self._fake_master_pid_file_sys_path

        self._fake_slave_pid = 1111
        self._fake_master_pid = 2222
        self._mock_open = mock_open()
        self._mock_open.side_effect = [
            StringIO(str(self._fake_slave_pid)),     # pretend to be fhe slave pid file object
            StringIO(str(self._fake_master_pid)),    # pretend to be the master pid file object
        ]

        self.patch('app.subcommands.stop_subcommand.open', new=self._mock_open, create=True)
        self._mock_os_remove = self.patch('os.remove')

        self._stop_subcommand = StopSubcommand()

        # setup the return value of time.time() and SIGTERM grace period so the test won't actually sleep
        self._stop_subcommand.SIGTERM_SIGKILL_GRACE_PERIOD_SEC = -1
        mock_time = self.patch('time.time')
        mock_time.return_value = 0

    def _setup_pid_file_does_not_exist(self):
        self._mock_os_path_exists.return_value = False

    def _setup_pid_file_exists_but_pid_does_not_exist(self):
        self._mock_os_path_exists.return_value = True
        self._mock_psutil_pid_exists.return_value = False

    def _setup_both_pid_file_and_pids_exist(self):
        self._mock_os_path_exists.return_value = True
        self._mock_psutil_pid_exists.return_value = True

    def test_stop_subcommand_does_not_call_terminate_if_pid_file_does_not_exist(self):
        # Arrange
        self._setup_pid_file_does_not_exist()

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self.assertFalse(self._mock_psutil_process.terminate.called)
        self.assertEqual(
            [
                call(self._fake_slave_pid_file_sys_path),
                call(self._fake_master_pid_file_sys_path),
            ],
            self._mock_os_path_exists.call_args_list,
        )

    def test_stop_subcommand_does_not_call_terminate_if_pid_does_not_exist(self):
        # Arrange
        self._setup_pid_file_exists_but_pid_does_not_exist()

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self.assertFalse(self._mock_psutil_process.terminate.called)
        self.assertEqual(
            [
                call(self._fake_slave_pid_file_sys_path),
                call(self._fake_master_pid_file_sys_path),
            ],
            self._mock_os_remove.call_args_list,
        )

    def test_stop_subcommand_does_not_call_terminate_if_pid_file_and_pid_exist_but_command_isnt_whitelisted(self):
        # Arrange
        self._setup_both_pid_file_and_pids_exist()
        self._setup_processes(
            master_cmdline=['python', './foo.py'],
            slave_cmdline=['python', './bar.py'],
        )

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self.assertFalse(self._mock_psutil_process.terminate.called)

    def _create_mock_process(self, pid, child_processes=None, cmdline=None):
        proc = Mock(psutil.Process)
        proc.pid = pid
        proc.is_running.return_value = True
        if cmdline:
            proc.cmdline.return_value = cmdline
        proc.children.return_value = child_processes if child_processes else []
        return proc

    def _setup_processes(self, master_cmdline=None, slave_cmdline=None):
        master_process = self._create_mock_process(
            self._fake_master_pid,
            cmdline=master_cmdline if master_cmdline else ['python', '-m', 'app', 'master'],
        )

        slave_child_process = self._create_mock_process(3333)
        slave_process = self._create_mock_process(
            self._fake_slave_pid,
            child_processes=[slave_child_process],
            cmdline=slave_cmdline if slave_cmdline else ['python', '-m', 'app', 'slave'],
        )

        self._mock_psutil_process.side_effect = [
            slave_process,
            master_process,
        ]

        return master_process, slave_process, slave_child_process

    def _assert_called_terminate(self, process_list):
        for proc in process_list:
            self.assertTrue(proc.terminate.called)

    @staticmethod
    def _successful_terminate_or_kill(proc):
        proc.is_running.return_value = False

    def test_stop_subcommand_kills_pid_with_sigterm_if_pid_file_and_pid_exist_and_command_is_whitelisted(self):
        # Arrange
        self._setup_both_pid_file_and_pids_exist()
        master_process, slave_process, slave_child_process = self._setup_processes()

        master_process.terminate.side_effect = partial(self._successful_terminate_or_kill, master_process)
        slave_process.terminate.side_effect = partial(self._successful_terminate_or_kill, slave_process)
        slave_child_process.terminate.side_effect = partial(self._successful_terminate_or_kill, slave_child_process)

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self._assert_called_terminate([master_process, slave_process, slave_child_process])
        self.assertFalse(master_process.kill.called)
        self.assertFalse(slave_process.kill.called)
        self.assertFalse(slave_child_process.kill.called)

    def test_stop_subcommand_kills_proc_with_sigkill_if_still_running_after_sigterm(self):
        # Arrange
        self._setup_both_pid_file_and_pids_exist()
        master_process, slave_process, slave_child_process = self._setup_processes()
        master_process.terminate.side_effect = partial(self._successful_terminate_or_kill, master_process)

        # Act
        self._stop_subcommand.run(None)

        # Assert
        self._assert_called_terminate([master_process, slave_process, slave_child_process])
        self.assertFalse(master_process.kill.called)
        self.assertTrue(slave_process.kill.called)
        self.assertTrue(slave_child_process.kill.called)