def setup_pidfile(self,
                   pid=None,
                   exit_code=None,
                   tests_failed=None,
                   use_second_read=False):
     contents = drone_manager.PidfileContents()
     if pid is not None:
         contents.process = drone_manager.Process('myhost', pid)
     contents.exit_status = exit_code
     contents.num_tests_failed = tests_failed
     self.mock_drone_manager.get_pidfile_contents.expect_call(
         self.pidfile_id,
         use_second_read=use_second_read).and_return(contents)
Пример #2
0
    def setUp(self):
        self.god = mock.mock_god()
        self.god.stub_with(drones, 'AUTOTEST_INSTALL_DIR',
                           self._DRONE_INSTALL_DIR)
        self.manager = drone_manager.DroneManager()
        self.god.stub_with(self.manager, '_results_dir', self._RESULTS_DIR)

        # we don't want this to ever actually get called
        self.god.stub_function(drones, 'get_drone')
        # we don't want the DroneManager to go messing with global config
        def do_nothing():
            pass
        self.god.stub_with(self.manager, 'refresh_drone_configs', do_nothing)

        # set up some dummy drones
        self.mock_drone = MockDrone('mock_drone')
        self.manager._drones[self.mock_drone.name] = self.mock_drone
        self.results_drone = MockDrone('results_drone', 0, 10)
        self.manager._results_drone = self.results_drone

        self.mock_drone_process = drone_manager.Process(self.mock_drone.name, 0)
class PidfileRunMonitorTest(unittest.TestCase):
    execution_tag = 'test_tag'
    pid = 12345
    process = drone_manager.Process('myhost', pid)
    num_tests_failed = 1

    def setUp(self):
        self.god = mock.mock_god()
        self.mock_drone_manager = self.god.create_mock_class(
            drone_manager.DroneManager, 'drone_manager')
        self.god.stub_with(drone_manager, '_the_instance',
                           self.mock_drone_manager)
        self.god.stub_with(pidfile_monitor, '_get_pidfile_timeout_secs',
                           self._mock_get_pidfile_timeout_secs)

        self.pidfile_id = object()

        (self.mock_drone_manager.get_pidfile_id_from.expect_call(
            self.execution_tag,
            pidfile_name=drone_manager.AUTOSERV_PID_FILE).and_return(
                self.pidfile_id))

        self.monitor = pidfile_monitor.PidfileRunMonitor()
        self.monitor.attach_to_existing_process(self.execution_tag)

    def tearDown(self):
        self.god.unstub_all()

    def _mock_get_pidfile_timeout_secs(self):
        return 300

    def setup_pidfile(self,
                      pid=None,
                      exit_code=None,
                      tests_failed=None,
                      use_second_read=False):
        contents = drone_manager.PidfileContents()
        if pid is not None:
            contents.process = drone_manager.Process('myhost', pid)
        contents.exit_status = exit_code
        contents.num_tests_failed = tests_failed
        self.mock_drone_manager.get_pidfile_contents.expect_call(
            self.pidfile_id,
            use_second_read=use_second_read).and_return(contents)

    def set_not_yet_run(self):
        self.setup_pidfile()

    def set_empty_pidfile(self):
        self.setup_pidfile()

    def set_running(self, use_second_read=False):
        self.setup_pidfile(self.pid, use_second_read=use_second_read)

    def set_complete(self, error_code, use_second_read=False):
        self.setup_pidfile(self.pid,
                           error_code,
                           self.num_tests_failed,
                           use_second_read=use_second_read)

    def _check_monitor(self, expected_pid, expected_exit_status,
                       expected_num_tests_failed):
        if expected_pid is None:
            self.assertEquals(self.monitor._state.process, None)
        else:
            self.assertEquals(self.monitor._state.process.pid, expected_pid)
        self.assertEquals(self.monitor._state.exit_status,
                          expected_exit_status)
        self.assertEquals(self.monitor._state.num_tests_failed,
                          expected_num_tests_failed)

        self.god.check_playback()

    def _test_read_pidfile_helper(self, expected_pid, expected_exit_status,
                                  expected_num_tests_failed):
        self.monitor._read_pidfile()
        self._check_monitor(expected_pid, expected_exit_status,
                            expected_num_tests_failed)

    def _get_expected_tests_failed(self, expected_exit_status):
        if expected_exit_status is None:
            expected_tests_failed = None
        else:
            expected_tests_failed = self.num_tests_failed
        return expected_tests_failed

    def test_read_pidfile(self):
        self.set_not_yet_run()
        self._test_read_pidfile_helper(None, None, None)

        self.set_empty_pidfile()
        self._test_read_pidfile_helper(None, None, None)

        self.set_running()
        self._test_read_pidfile_helper(self.pid, None, None)

        self.set_complete(123)
        self._test_read_pidfile_helper(self.pid, 123, self.num_tests_failed)

    def test_read_pidfile_error(self):
        self.mock_drone_manager.get_pidfile_contents.expect_call(
            self.pidfile_id, use_second_read=False).and_return(
                drone_manager.InvalidPidfile('error'))
        self.assertRaises(pidfile_monitor.PidfileRunMonitor._PidfileException,
                          self.monitor._read_pidfile)
        self.god.check_playback()

    def setup_is_running(self, is_running):
        self.mock_drone_manager.is_process_running.expect_call(
            self.process).and_return(is_running)

    def _test_get_pidfile_info_helper(self, expected_pid, expected_exit_status,
                                      expected_num_tests_failed):
        self.monitor._get_pidfile_info()
        self._check_monitor(expected_pid, expected_exit_status,
                            expected_num_tests_failed)

    def test_get_pidfile_info(self):
        """
        normal cases for get_pidfile_info
        """
        # running
        self.set_running()
        self.setup_is_running(True)
        self._test_get_pidfile_info_helper(self.pid, None, None)

        # exited during check
        self.set_running()
        self.setup_is_running(False)
        self.set_complete(123, use_second_read=True)  # pidfile gets read again
        self._test_get_pidfile_info_helper(self.pid, 123,
                                           self.num_tests_failed)

        # completed
        self.set_complete(123)
        self._test_get_pidfile_info_helper(self.pid, 123,
                                           self.num_tests_failed)

    def test_get_pidfile_info_running_no_proc(self):
        """
        pidfile shows process running, but no proc exists
        """
        # running but no proc
        self.set_running()
        self.setup_is_running(False)
        self.set_running(use_second_read=True)
        self._test_get_pidfile_info_helper(self.pid, 1, 0)
        self.assertTrue(self.monitor.lost_process)

    def test_get_pidfile_info_not_yet_run(self):
        """
        pidfile hasn't been written yet
        """
        self.set_not_yet_run()
        self._test_get_pidfile_info_helper(None, None, None)

    def test_process_failed_to_write_pidfile(self):
        self.set_not_yet_run()
        self.monitor._start_time = (
            time.time() - pidfile_monitor._get_pidfile_timeout_secs() - 1)
        self._test_get_pidfile_info_helper(None, 1, 0)
        self.assertTrue(self.monitor.lost_process)