def test_get_initial_state_is_none(self): _, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) model_def.data[SMConsts.INITIAL_STATE] = None init_state = model_def.get_initial_state() assert_is_none(init_state)
def _test_image_generation( self, filename: str = None, path_only: bool = False) -> None: """ Instantiate a state machine and generate an image of the state machine. Args: filename (str): Filespec of file to store image path_only (str): Only generate the current image path Returns: None """ # Set up state machine configuration model_file = self.SIMPLE_MACHINE_DEF_FILE def_file, model_cfg, model_def = setup_state_machine_definitions( model_file) expected_model_name = get_model_name_from_raw_file(def_file) # Build state machine obj_model = ImportCheck() sm = StateMachine(data_model=model_def, object_model=obj_model) sm.configure_state_machine() # Generate image image_name = sm.generate_image(filename=filename, path_only=path_only) # Assure image filename is correct and file exists filename = filename or os.path.abspath(f"{expected_model_name}.png") assert_equals(filename, image_name) assert_true(os.path.exists(image_name)) # Verify image is deleted os.remove(image_name) assert_false(os.path.exists(image_name))
def test_get_transitions_for_valid_state(self): _, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) transitions = model_def.get_transitions(self.VALID_TEST_STATE) assert_equals(len(transitions), self.NUMBER_OF_TRANSITIONS) assert_true(isinstance(transitions[0], dict)) assert_in(self.VALID_TRANSITION_NAME, [x[SMConsts.TRIGGER_NAME] for x in transitions])
def test_get_transition_info_by_name_invalid_state_and_name(self): cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) trigger_info = model_def.get_transition_info_by_name( state_name=self.INVALID_TEST_STATE, trigger_name=self.INVALID_TEST_STATE) assert_equals(trigger_info, {})
def test_validate_multi_triggers(self): cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) triggers = model_def.get_multi_triggers() validated_triggers = model_def.validate_multi_triggers(triggers) assert_true(isinstance(validated_triggers, list)) assert_true(validated_triggers)
def test_get_state_definition_with_non_existing_state(self): _, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) state_def = model_def.get_state_definition( state=self.INVALID_TEST_STATE) assert_true(isinstance(state_def, dict)) assert_equals(state_def, {})
def test_validate_initial_state_with_invalid_state(self): model_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) # Set initial state to an invalid state model_def.data[SMConsts.INITIAL_STATE] = self.INVALID_TEST_STATE # Validate the initial state, should return False assert_false(ValidateData(model_def).validate_initial_state())
def test_validate_all_transitions_with_no_states(self): model_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) # Remove all states (and transitions) model_def.data[SMConsts.DEFINITION] = {} # Validate the transitions (there are none!), should return False assert_false(ValidateData(model_def).validate_all_transitions())
def test__get_callback__does_not_exist(self): def_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) obj_model = ImportCheck() sm = StateMachine(data_model=model_def, object_model=obj_model) # Should raise AttributeError since the method does not exist. sm._get_callback('object_model.undefined_test_routine')
def test_get_all_triggers(self): cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) expected_triggers = get_triggers_from_raw_file(cfg_file) reported_triggers = model_def.get_all_triggers() logging.info(f"EXPECTED TRIGGERS: {expected_triggers}") logging.info(f"REPORTED TRIGGERS: {reported_triggers}") assert_equals(set(expected_triggers) ^ set(reported_triggers), set())
def test_validate_initial_state_with_none_value(self): model_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) # Set the initial state to None (should be equivalent # to invalid state) model_def.data[SMConsts.INITIAL_STATE] = None # Validate the initial state, should return False assert_false(ValidateData(model_def).validate_initial_state())
def test_get_state_validation_methods_valid_state(self): _, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) validations = model_def.get_state_validation_methods( self.VALID_TEST_STATE) assert_true(isinstance(validations, list)) assert_equals(len(validations), 2) assert_true(isinstance(validations[0], dict)) assert_equals(validations[0][SMConsts.NAME], self.VALID_TEST_STATE.lower())
def test_get_model_name(self): def_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) sm = StateMachine(data_model=model_def, object_model=None) expected_model_name = get_model_name_from_raw_file(def_file) logging.info(f"Expected Model Name: {expected_model_name}") logging.info(f"Actual Model Name: {sm.name}") assert_equals(sm.name, expected_model_name)
def test_model(self): # This tests a large percentage of the configure_state_machine. # Testing all paths is dependent on the model definition, and # general_sample.yaml contains the necessary conditions/definitions # to traverse all logic conditions. def_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) sm = StateMachine(data_model=model_def, object_model=None) sm.configure_state_machine() assert_true(isinstance(sm, StateMachine))
def test_get_list_of_states(self): cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) expected_states = get_states_from_raw_file(yaml_file=cfg_file) returned_states = model_def.get_list_of_states() logging.info(f"Expected States: {expected_states}") logging.info(f"Returned States: {returned_states}") assert_equals(set(expected_states) ^ set(returned_states), set())
def test__set_execution_description_no_args(self): def_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) expected_model_name = get_model_name_from_raw_file(def_file) obj_model = ImportCheck() sm = StateMachine(data_model=model_def, object_model=obj_model) sm.configure_state_machine() sm._set_execution_description() assert_equals(sm.description, expected_model_name)
def test_get_transition_info_by_name_valid_state_and_name(self): cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) trigger_info = model_def.get_transition_info_by_name( state_name=self.VALID_TEST_STATE, trigger_name=self.VALID_TRANSITION_NAME) transitions = model_def.get_transitions( self.VALID_TEST_STATE)[self.VALID_TRANSITION_INDEX] for key, value in transitions.items(): assert_true(key in trigger_info) assert_equals(value, trigger_info[key])
def test_validate_initial_state_that_does_not_have_transitions(self): model_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) model_def.data[SMConsts.INITIAL_STATE] = self.VALID_TEST_STATE # Remove all transitions from initial_state definition state_def = model_def.data[SMConsts.DEFINITION][ self.VALID_TEST_STATE_INDEX] state_def[self.VALID_TEST_STATE][SMConsts.TRANSITIONS] = [] # Validate the initial state, should return False assert_false(ValidateData(model_def).validate_initial_state())
def test_get_transition_info_for_valid_state(self): cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) transitions = model_def.get_transitions(self.VALID_TEST_STATE) trans_tuple = (t_name, t_dest, t_method) = \ model_def.get_transition_info(transitions[0]) logging.info(f"Expected transition Data (not in order): " f"{set(list(transitions[0].values()))}") logging.info(f"Received transition Data tuple: {set(trans_tuple)}") assert_equals(t_name, transitions[0][SMConsts.TRIGGER_NAME]) assert_equals(t_dest, transitions[0][SMConsts.DESTINATION_STATE]) assert_equals(t_method, transitions[0][SMConsts.CHANGE_STATE_ROUTINE])
def test_get_state_definition_with_existing_state(self): _, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) state_def = model_def.get_state_definition(state=self.VALID_TEST_STATE) logging.info(f"STATE NAME: {self.VALID_TEST_STATE}") logging.info(f"EXPECTED STATE DESCRIPTION: " f"{self.VALID_TEST_STATE_DESCRIPTION}") logging.info(state_def) assert_true(isinstance(state_def, dict)) assert_equals(state_def[SMConsts.DESCRIPTION], self.VALID_TEST_STATE_DESCRIPTION)
def test_get_multi_triggers(self): expected_trigger_names = [ 'multi_trigger_test_from_all', 'multi_trigger_test_from_select_states'] cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) triggers = model_def.get_multi_triggers() trigger_names = [x.get(SMConsts.TRIGGER_NAME) for x in triggers] assert_true(isinstance(triggers, list)) assert_true(triggers) assert_equals(expected_trigger_names, trigger_names)
def test__get_callback__exists(self): def_file, model_cfg, model_def = setup_state_machine_definitions( self.SIMPLE_MACHINE_DEF_FILE) obj_model = ImportCheck() sm = StateMachine(data_model=model_def, object_model=obj_model) api = sm._get_callback('object_model.test_routine') # Verify the routine returned a Callable reference. assert_true(callable(api)) # Execute the API. It should return the default value, which is False assert_equals(api(), ImportCheck.DEFAULT_RESPONSE)
def test_get_transition_info_for_undefined_transition(self): error_msg = 'Not Found' cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) transitions = model_def.get_transitions(self.VALID_TEST_STATE) transitions[0] = {} trans_tuple = model_def.get_transition_info(transitions[0]) logging.info(f"Expected transition Data (not in order): " f"{[error_msg for _ in range(3)]}") logging.info(f"Received transition Data tuple: {set(trans_tuple)}") for msg in trans_tuple: assert_equals(msg, error_msg)
def _setup_state_machine_for_execution(filename): def_file, model_cfg, model_def = setup_state_machine_definitions( filename) obj_model = ImportCheck() sm = StateMachine(data_model=model_def, object_model=obj_model) sm.configure_state_machine() # Get data about transition configuration trans_data = model_def.get_transitions(sm.machine.initial)[0] callback_routine = trans_data[SMConsts.CHANGE_STATE_ROUTINE] # Setup state machine to execute transition trigger_name = trans_data[SMConsts.TRIGGER_NAME] sm.current_step = PathStep( trigger=trigger_name, trigger_id=f'from_{sm.machine.initial}') return sm, trigger_name, callback_routine
def test_get_state_definitions(self): _, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) defs = model_def.get_state_definitions() # Get all of the states (but remove the entries prefixed with # the StateMachineConstants.NON_STATE_PREFIX) test_model = model_cfg.data[SMConsts.DEFINITION] test_model = [x for x in test_model if not list(x.keys())[0].startswith( SMConsts.NON_STATE_PREFIX)] num_states = len(test_model) logging.debug(f"\nExpected Number of States: {num_states}:\n" f"{test_model}") logging.debug(f"Received: {len(defs)}:\n{defs}") assert_true(defs, isinstance(defs, list)) assert_equals(len(defs), num_states)
def test_validate_all_transitions_with_an_invalid_transition(self): bogus_transition = { SMConsts.CHANGE_STATE_ROUTINE: 'object_model.unlock_server', SMConsts.DESTINATION_STATE: self.INVALID_TEST_STATE, SMConsts.TRIGGER_NAME: 'BOGUS' } # Not pretty, but to meet PEP-8 line length, save to a tuple, # and then assign vars based on the tuple model_tuple = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) (model_file, model_cfg, model_def) = model_tuple # Add a transition (to any state) that points to an # unknown/undefined state state_def = model_def.data[SMConsts.DEFINITION][ self.VALID_TEST_STATE_INDEX] state_def[self.VALID_TEST_STATE][SMConsts.TRANSITIONS].append( bogus_transition) # Validate the transitions, should return False assert_false(ValidateData(model_def).validate_all_transitions())
def test_get_initial_state(self): _, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) init_state = model_def.get_initial_state() assert_equals(init_state, model_cfg.data[SMConsts.INITIAL_STATE])
def test_get_model_name(self): _, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) model_name = model_def.get_model_name() assert_equals(model_name, model_cfg.data[SMConsts.MODEL_NAME])
def test_validate_path_with_invalid_path(self): cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) path = get_states_from_raw_file(yaml_file=cfg_file) assert_false(model_def.validate_path(path))
def test_get_transition_info_for_invalid_state(self): cfg_file, model_cfg, model_def = setup_state_machine_definitions( self.MACHINE_DEFINITION_FILE) transitions = model_def.get_transitions(self.INVALID_TEST_STATE) assert_equals(transitions, [])