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_isolation(self): """ Test the in_isolation method. """ from supvisors.address import AddressStatus from supvisors.ttypes import AddressStates status = AddressStatus('10.0.0.1', self.supvisors.logger) for state in self.all_states: status._state = state self.assertTrue(status.in_isolation() and state in [AddressStates.ISOLATING, AddressStates.ISOLATED] or not status.in_isolation() and state not in [AddressStates.ISOLATING, AddressStates.ISOLATED])
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_pid_process(self): """ Test the pid_process method. """ from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) 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) # check the namespec and pid of the running processes self.assertItemsEqual([('sample_test_1:xfontsel', 80879), ('sample_test_2:yeux_01', 80882)], status.pid_processes())
def test_pid_process(self): """ Test the pid_process method. """ from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) 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) # check the namespec and pid of the running processes self.assertItemsEqual([('sample_test_1:xfontsel', 80879), ('sample_test_2:yeux_01', 80882)], status.pid_processes())
def test_running_process(self): """ Test the running_process method. """ from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) 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) # check the name of the running processes self.assertItemsEqual(['late_segv','segv', 'xfontsel', 'yeux_01'], [proc.process_name for proc in status.running_processes()])
def test_running_process(self): """ Test the running_process method. """ from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) 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) # check the name of the running processes self.assertItemsEqual(['late_segv','segv', 'xfontsel', 'yeux_01'], [proc.process_name for proc in status.running_processes()])
def test_serialization(self): """ Test the serial method used to get a serializable form of AddressStatus. """ import pickle from supvisors.address import AddressStatus from supvisors.ttypes import AddressStates # create address status instance status = AddressStatus('10.0.0.1', self.supvisors.logger) status._state = AddressStates.RUNNING status.checked = True status.remote_time = 50 status.local_time = 60 # test to_json method serialized = status.serial() self.assertDictEqual( serialized, { 'address_name': '10.0.0.1', 'loading': 0, 'statecode': 2, 'statename': 'RUNNING', 'remote_time': 50, 'local_time': 60 }) # test that returned structure is serializable using pickle dumped = pickle.dumps(serialized) loaded = pickle.loads(dumped) self.assertDictEqual(serialized, loaded)
def test_create(self): """ Test the values set at construction. """ from supvisors.address import AddressStatus from supvisors.ttypes import AddressStates status = AddressStatus('10.0.0.1', self.supvisors.logger) # test all AddressStatus values self.assertIs(self.supvisors.logger, status.logger) self.assertEqual('10.0.0.1', status.address_name) self.assertEqual(AddressStates.UNKNOWN, status.state) self.assertEqual(0, status.remote_time) self.assertEqual(0, status.local_time) self.assertDictEqual({}, status.processes)
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 setUp(self): """ Create a Supvisors-like structure. """ from supvisors.address import AddressStatus from supvisors.ttypes import AddressStates self.supvisors = MockedSupvisors() # assign addresses in context addresses = self.supvisors.context.addresses for address_name in self.supvisors.address_mapper.addresses: addresses[address_name] = AddressStatus(address_name, self.supvisors.logger) addresses['127.0.0.1']._state = AddressStates.RUNNING addresses['10.0.0.1']._state = AddressStates.SILENT addresses['10.0.0.2']._state = AddressStates.RUNNING addresses['10.0.0.3']._state = AddressStates.ISOLATING addresses['10.0.0.4']._state = AddressStates.RUNNING addresses['10.0.0.5']._state = AddressStates.ISOLATED
def test_loading(self): """ Test the loading method. """ from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) 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) # check the loading of the address: gives 5 (1 per running process) by default because no rule has been loaded self.assertEqual(4, status.loading()) # change expected_loading of any stopped process process = random.choice([proc for proc in status.processes.values() if proc.stopped()]) process.rules.expected_loading = 50 self.assertEqual(4, status.loading()) # change expected_loading of any running process process = random.choice([proc for proc in status.processes.values() if proc.running()]) process.rules.expected_loading = 50 self.assertEqual(53, status.loading())
def test_transitions(self): """ Test the state transitions of AddressStatus. """ from supvisors.address import AddressStatus from supvisors.ttypes import AddressStates, InvalidTransition status = AddressStatus('10.0.0.1', self.supvisors.logger) for state1 in self.all_states: for state2 in self.all_states: # check all possible transitions from each state status._state = state1 if state2 in status._Transitions[state1]: status.state = state2 self.assertEqual(state2, status.state) self.assertEqual(AddressStates._to_string(state2), status.state_string()) elif state1 == state2: self.assertEqual(state1, status.state) else: with self.assertRaises(InvalidTransition): status.state = state2
def test_serialization(self): """ Test the serial method used to get a serializable form of AddressStatus. """ import pickle from supvisors.address import AddressStatus from supvisors.ttypes import AddressStates # create address status instance status = AddressStatus('10.0.0.1', self.supvisors.logger) status._state = AddressStates.RUNNING status.checked = True status.remote_time = 50 status.local_time = 60 # test to_json method serialized = status.serial() self.assertDictEqual(serialized, {'address_name': '10.0.0.1', 'loading': 0, 'statecode': 2, 'statename': 'RUNNING', 'remote_time': 50, 'local_time':60}) # test that returned structure is serializable using pickle dumped = pickle.dumps(serialized) loaded = pickle.loads(dumped) self.assertDictEqual(serialized, loaded)
def test_loading(self): """ Test the loading method. """ from supvisors.address import AddressStatus from supvisors.process import ProcessStatus status = AddressStatus('10.0.0.1', self.supvisors.logger) 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) # check the loading of the address: gives 5 (1 per running process) by default because no rule has been loaded self.assertEqual(4, status.loading()) # change expected_loading of any stopped process process = random.choice([proc for proc in status.processes.values() if proc.stopped()]) process.rules.expected_loading = 50 self.assertEqual(4, status.loading()) # change expected_loading of any running process process = random.choice([proc for proc in status.processes.values() if proc.running()]) process.rules.expected_loading = 50 self.assertEqual(53, status.loading())
def test_operation_state(self): """ Test the Operation state of the FSM. """ from supvisors.address import AddressStatus from supvisors.statemachine import AbstractState, OperationState from supvisors.ttypes import AddressStates, SupvisorsStates state = OperationState(self.supvisors) self.assertIsInstance(state, AbstractState) # no enter implementation. just call it without test state.enter() # test next method # do not leave OPERATION state if a starting or a stopping is in progress with patch.object(self.supvisors.starter, 'check_starting', return_value=False): result = state.next() self.assertEqual(SupvisorsStates.OPERATION, result) with patch.object(self.supvisors.stopper, 'check_stopping', return_value=False): result = state.next() self.assertEqual(SupvisorsStates.OPERATION, result) # create address context for address_name in self.supvisors.address_mapper.addresses: address = AddressStatus(address_name, self.supvisors.logger) self.supvisors.context.addresses[address_name] = address # declare local and master address running self.supvisors.context.master_address = '10.0.0.3' self.supvisors.context.addresses[ '127.0.0.1']._state = AddressStates.RUNNING self.supvisors.context.addresses[ '10.0.0.3']._state = AddressStates.RUNNING # consider that no starting or stopping is in progress with patch.object(self.supvisors.starter, 'check_starting', return_value=True): with patch.object(self.supvisors.stopper, 'check_stopping', return_value=True): # stay in OPERATION if local address and master address are RUNNING and no conflict with patch.object(self.supvisors.context, 'conflicting', return_value=False): result = state.next() self.assertEqual(SupvisorsStates.OPERATION, result) # transit to CONCILIATION if local address and master address are RUNNING and conflict detected with patch.object(self.supvisors.context, 'conflicting', return_value=True): result = state.next() self.assertEqual(SupvisorsStates.CONCILIATION, result) # transit to INITIALIZATION state if the local address or master address is not RUNNING self.supvisors.context.addresses[ '127.0.0.1']._state = AddressStates.SILENT result = state.next() self.assertEqual(SupvisorsStates.INITIALIZATION, result) self.supvisors.context.addresses[ '127.0.0.1']._state = AddressStates.RUNNING self.supvisors.context.addresses[ '10.0.0.3']._state = AddressStates.SILENT result = state.next() self.assertEqual(SupvisorsStates.INITIALIZATION, result) # no exit implementation. just call it without test state.exit()
def test_conciliation_state(self): """ Test the Conciliation state of the FSM. """ from supvisors.address import AddressStatus from supvisors.statemachine import AbstractState, ConciliationState from supvisors.ttypes import AddressStates, SupvisorsStates state = ConciliationState(self.supvisors) self.assertIsInstance(state, AbstractState) # test enter method with patch.object(self.supvisors.context, 'conflicts', return_value=[1, 2, 3]): with patch( 'supvisors.statemachine.conciliate') as mocked_conciliate: # nothing done if local is not master self.supvisors.context.master = False state.enter() self.assertEqual(0, mocked_conciliate.call_count) # conciliation called if local is master self.supvisors.context.master = True state.enter() self.assertEqual(1, mocked_conciliate.call_count) self.assertEqual(call(self.supvisors, 0, [1, 2, 3]), mocked_conciliate.call_args) # test next method (quite similar to OPERATION state) # do not leave CONCILIATION state if a starting or a stopping is in progress with patch.object(self.supvisors.starter, 'check_starting', return_value=False): result = state.next() self.assertEqual(SupvisorsStates.CONCILIATION, result) with patch.object(self.supvisors.stopper, 'check_stopping', return_value=False): result = state.next() self.assertEqual(SupvisorsStates.CONCILIATION, result) # create address context for address_name in self.supvisors.address_mapper.addresses: address = AddressStatus(address_name, self.supvisors.logger) self.supvisors.context.addresses[address_name] = address # declare local and master address running self.supvisors.context.master_address = '10.0.0.3' self.supvisors.context.addresses[ '127.0.0.1']._state = AddressStates.RUNNING self.supvisors.context.addresses[ '10.0.0.3']._state = AddressStates.RUNNING # consider that no starting or stopping is in progress with patch.object(self.supvisors.starter, 'check_starting', return_value=True): with patch.object(self.supvisors.stopper, 'check_stopping', return_value=True): # stay in CONCILIATION if local address and master address are RUNNING and conflict still detected with patch.object(self.supvisors.context, 'conflicting', return_value=True): result = state.next() self.assertEqual(SupvisorsStates.CONCILIATION, result) # transit to OPERATION if local address and master address are RUNNING and no conflict detected with patch.object(self.supvisors.context, 'conflicting', return_value=False): result = state.next() self.assertEqual(SupvisorsStates.OPERATION, result) # transit to INITIALIZATION state if the local address or master address is not RUNNING self.supvisors.context.addresses[ '127.0.0.1']._state = AddressStates.SILENT result = state.next() self.assertEqual(SupvisorsStates.INITIALIZATION, result) self.supvisors.context.addresses[ '127.0.0.1']._state = AddressStates.RUNNING self.supvisors.context.addresses[ '10.0.0.3']._state = AddressStates.SILENT result = state.next() self.assertEqual(SupvisorsStates.INITIALIZATION, result) # no exit implementation. just call it without test state.exit()