def test_times(self): """ Test the update_times method. """ from supervisor.states import ProcessStates from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) # add processes for info in ProcessInfoDatabase: process = ProcessStatus(info['group'], info['name'], self.supvisors) process.add_info('10.0.0.1', info.copy()) status.add_process(process) # get current process times ref_data = {process.namespec(): (process.state, info['now'], info['local_time'], info.get('uptime', None)) for process in status.processes.values() for info in [process.infos['10.0.0.1']]} # update times and check now = time.time() status.update_times(now + 10, now) self.assertEqual(now + 10, status.remote_time) self.assertEqual(now, status.local_time) # test process times: only RUNNING has an uptime new_data = {process.namespec(): (process.state, info['now'], info['local_time'], info.get('uptime', None)) for process in status.processes.values() for info in [process.infos['10.0.0.1']]} for namespec, new_info in new_data.items(): ref_info = ref_data[namespec] self.assertEqual(new_info[0], ref_info[0]) self.assertGreater(new_info[1], ref_info[1]) self.assertGreater(new_info[2], ref_info[2]) if new_info[0] in [ProcessStates.RUNNING, ProcessStates.STOPPING]: self.assertGreater(new_info[3], ref_info[3]) else: self.assertEqual(new_info[3], ref_info[3])
def test_times(self): """ Test the update_times method. """ from supervisor.states import ProcessStates from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) # add processes for info in database_copy(): process = ProcessStatus(info['group'], info['name'], self.supvisors) process.add_info('10.0.0.1', info) status.add_process(process) # get current process times ref_data = {process.namespec(): (process.state, info['now'], info['uptime']) for process in status.processes.values() for info in [process.infos['10.0.0.1']]} # update times and check now = int(time.time()) status.update_times(now + 10, now) self.assertEqual(now + 10, status.remote_time) self.assertEqual(now, status.local_time) # test process times: only RUNNING and STOPPING have a positive uptime new_data = {process.namespec(): (process.state, info['now'], info['uptime']) for process in status.processes.values() for info in [process.infos['10.0.0.1']]} for namespec, new_info in new_data.items(): ref_info = ref_data[namespec] self.assertEqual(new_info[0], ref_info[0]) self.assertGreater(new_info[1], ref_info[1]) if new_info[0] in [ProcessStates.RUNNING, ProcessStates.STOPPING]: self.assertGreater(new_info[2], ref_info[2]) else: self.assertEqual(new_info[2], ref_info[2])
def test_add_process(self): """ Test the add_process method. """ from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) info = any_process_info() process = ProcessStatus(info['group'], info['name'], self.supvisors) status.add_process(process) # check that process is stored self.assertIn(process.namespec(), status.processes.keys()) self.assertIs(process, status.processes[process.namespec()])
def test_namespec(self): """ Test of the process namspec. """ from supvisors.process import ProcessStatus # test namespec when group and name are different info = process_info_by_name('segv') process = ProcessStatus(info['group'], info['name'], self.supvisors) self.assertEqual('crash:segv', process.namespec()) # test namespec when group and name are identical info = process_info_by_name('firefox') process = ProcessStatus(info['group'], info['name'], self.supvisors) self.assertEqual('firefox', process.namespec())
def test_deployment_state(self): """ Test the Deployment state of the FSM. """ from supvisors.application import ApplicationStatus from supvisors.process import ProcessStatus from supvisors.statemachine import AbstractState, DeploymentState from supvisors.ttypes import ApplicationStates, SupvisorsStates state = DeploymentState(self.supvisors) self.assertIsInstance(state, AbstractState) # test enter method # test that start_applications is called only when local address is the master address with patch.object(self.supvisors.starter, 'start_applications') as mocked_starter: self.supvisors.context.master = False state.enter() self.assertEqual(0, mocked_starter.call_count) # now master address is local self.supvisors.context.master = True state.enter() self.assertEqual(1, mocked_starter.call_count) # create application context application = ApplicationStatus('sample_test_2', self.supvisors.logger) self.supvisors.context.applications['sample_test_2'] = application for info in database_copy(): if info['group'] == 'sample_test_2': process = ProcessStatus(info['group'], info['name'], self.supvisors) process.rules.start_sequence = len(process.namespec()) % 3 process.rules.stop_sequence = len(process.namespec()) % 3 + 1 process.add_info('10.0.0.1', info) application.add_process(process) # test application updates self.supvisors.context.master = False self.assertEqual(ApplicationStates.STOPPED, application.state) self.assertFalse(application.minor_failure) self.assertFalse(application.major_failure) self.assertDictEqual({}, application.start_sequence) self.assertDictEqual({}, application.stop_sequence) state.enter() application = self.supvisors.context.applications['sample_test_2'] self.assertEqual(ApplicationStates.RUNNING, application.state) self.assertTrue(application.minor_failure) self.assertFalse(application.major_failure) # list order may differ, so break down self.assertItemsEqual([0, 1], application.start_sequence.keys()) self.assertItemsEqual([ application.processes['yeux_01'], application.processes['yeux_00'] ], application.start_sequence[0]) self.assertItemsEqual([application.processes['sleep']], application.start_sequence[1]) self.assertItemsEqual([1, 2], application.stop_sequence.keys()) self.assertItemsEqual([ application.processes['yeux_01'], application.processes['yeux_00'] ], application.stop_sequence[1]) self.assertItemsEqual([application.processes['sleep']], application.stop_sequence[2]) # test next method # stay in DEPLOYMENT if local is master and a deployment is in progress, whatever the conflict status with patch.object(self.supvisors.starter, 'check_starting', return_value=False): for conflict in [True, False]: with patch.object(self.supvisors.context, 'conflicting', return_value=conflict): self.supvisors.context.master = True result = state.next() self.assertEqual(SupvisorsStates.DEPLOYMENT, result) # return OPERATION if local is not master and no conflict, whatever the starting status self.supvisors.context.master = False with patch.object(self.supvisors.context, 'conflicting', return_value=False): for starting in [True, False]: with patch.object(self.supvisors.starter, 'check_starting', return_value=starting): result = state.next() self.assertEqual(SupvisorsStates.OPERATION, result) # return OPERATION if a deployment is in progress and no conflict, whatever the master status with patch.object(self.supvisors.starter, 'check_starting', return_value=True): with patch.object(self.supvisors.context, 'conflicting', return_value=False): for master in [True, False]: self.supvisors.context.master = master result = state.next() self.assertEqual(SupvisorsStates.OPERATION, result) # return CONCILIATION if local is not master and conflict detected, whatever the starting status self.supvisors.context.master = False with patch.object(self.supvisors.context, 'conflicting', return_value=True): for starting in [True, False]: with patch.object(self.supvisors.starter, 'check_starting', return_value=starting): result = state.next() self.assertEqual(SupvisorsStates.CONCILIATION, result) # return CONCILIATION if a deployment is in progress and conflict detected, whatever the master status with patch.object(self.supvisors.starter, 'check_starting', return_value=True): with patch.object(self.supvisors.context, 'conflicting', return_value=True): for master in [True, False]: self.supvisors.context.master = master result = state.next() self.assertEqual(SupvisorsStates.CONCILIATION, result) # no exit implementation. just call it without test state.exit()
def test_deployment_state(self): """ Test the Deployment state of the FSM. """ from supvisors.application import ApplicationStatus from supvisors.process import ProcessStatus from supvisors.statemachine import AbstractState, DeploymentState from supvisors.ttypes import ApplicationStates, SupvisorsStates state = DeploymentState(self.supvisors) self.assertIsInstance(state, AbstractState) # test enter method # test that start_applications is called only when local address is the master address with patch.object(self.supvisors.starter, 'start_applications') as mocked_starter: self.supvisors.context.master = False state.enter() self.assertEqual(0, mocked_starter.call_count) # now master address is local self.supvisors.context.master = True state.enter() self.assertEqual(1, mocked_starter.call_count) # create application context application = ApplicationStatus('sample_test_2', self.supvisors.logger) self.supvisors.context.applications['sample_test_2'] = application for info in database_copy(): if info['group'] == 'sample_test_2': process = ProcessStatus(info['group'], info['name'], self.supvisors) process.rules.start_sequence = len(process.namespec()) % 3 process.rules.stop_sequence = len(process.namespec()) % 3 + 1 process.add_info('10.0.0.1', info) application.add_process(process) # test application updates self.supvisors.context.master = False self.assertEqual(ApplicationStates.STOPPED, application.state) self.assertFalse(application.minor_failure) self.assertFalse(application.major_failure) self.assertDictEqual({}, application.start_sequence) self.assertDictEqual({}, application.stop_sequence) state.enter() application = self.supvisors.context.applications['sample_test_2'] self.assertEqual(ApplicationStates.RUNNING, application.state) self.assertTrue(application.minor_failure) self.assertFalse(application.major_failure) # list order may differ, so break down self.assertItemsEqual([0, 1], application.start_sequence.keys()) self.assertItemsEqual([application.processes['yeux_01'], application.processes['yeux_00']], application.start_sequence[0]) self.assertItemsEqual([application.processes['sleep']], application.start_sequence[1]) self.assertItemsEqual([1, 2], application.stop_sequence.keys()) self.assertItemsEqual([application.processes['yeux_01'], application.processes['yeux_00']], application.stop_sequence[1]) self.assertItemsEqual([application.processes['sleep']], application.stop_sequence[2]) # test next method # stay in DEPLOYMENT if local is master and a starting is in progress, whatever the conflict status with patch.object(self.supvisors.starter, 'check_starting', return_value=False): for conflict in [True, False]: with patch.object(self.supvisors.context, 'conflicting', return_value=conflict): self.supvisors.context.master = True result = state.next() self.assertEqual(SupvisorsStates.DEPLOYMENT, result) # return OPERATION if local is not master and no conflict, whatever the starting status self.supvisors.context.master = False with patch.object(self.supvisors.context, 'conflicting', return_value=False): for starting in [True, False]: with patch.object(self.supvisors.starter, 'check_starting', return_value=starting): result = state.next() self.assertEqual(SupvisorsStates.OPERATION, result) # return OPERATION if a starting is in progress and no conflict, whatever the master status with patch.object(self.supvisors.starter, 'check_starting', return_value=True): with patch.object(self.supvisors.context, 'conflicting', return_value=False): for master in [True, False]: self.supvisors.context.master = master result = state.next() self.assertEqual(SupvisorsStates.OPERATION, result) # return CONCILIATION if local is not master and conflict detected, whatever the starting status self.supvisors.context.master = False with patch.object(self.supvisors.context, 'conflicting', return_value=True): for starting in [True, False]: with patch.object(self.supvisors.starter, 'check_starting', return_value=starting): result = state.next() self.assertEqual(SupvisorsStates.CONCILIATION, result) # return CONCILIATION if a starting is in progress and conflict detected, whatever the master status with patch.object(self.supvisors.starter, 'check_starting', return_value=True): with patch.object(self.supvisors.context, 'conflicting', return_value=True): for master in [True, False]: self.supvisors.context.master = master result = state.next() self.assertEqual(SupvisorsStates.CONCILIATION, result) # no exit implementation. just call it without test state.exit()