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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)