Esempio n. 1
0
def test_lock_state_machine(caplog):

    state_machine = StateMachine()

    @lock_state_machine
    def custom_function(object, number):
        raise AttributeError("Test error")

    State.custom_method = custom_function

    state1 = ExecutionState("s1")
    state_machine.root_state = state1

    try:
        state1.custom_method(5)
    except Exception as e:
        import traceback
        print("Could not stop state machine: {0} {1}".format(
            e, traceback.format_exc()))

    assert global_lock_counter == 0

    state1.add_outcome("outcome1", 3)
    assert len(state1.outcomes) == 4

    assert_logger_warnings_and_errors(caplog)
Esempio n. 2
0
def test_state_machine_manager(caplog):
    state_machine = StateMachine()

    state1 = ExecutionState("s1")
    state_machine.root_state = state1

    manager = StateMachineManager.instance([state_machine])

    sm_id = manager.get_sm_id_for_root_state_id('FakeId')
    assert (sm_id is None)
    assert_logger_warnings_and_errors(caplog)
Esempio n. 3
0
def test_lock_state_machine(caplog):

    state_machine = StateMachine()

    @lock_state_machine
    def custom_function(object, number):
        raise AttributeError("Test error")

    State.custom_method = custom_function

    state1 = ExecutionState("s1")
    state_machine.root_state = state1

    try:
        state1.custom_method(5)
    except Exception, e:
        import traceback
        print "Could not stop state machine: {0} {1}".format(
            e.message, traceback.format_exc())
Esempio n. 4
0
def load_state_machine_from_path(base_path, state_machine_id=None):
    """Loads a state machine from the given path

    :param base_path: An optional base path for the state machine.
    :return: a tuple of the loaded container state, the version of the state and the creation time
    :raises ValueError: if the provided path does not contain a valid state machine
    """
    logger.debug("Loading state machine from path {0}...".format(base_path))

    state_machine_file_path = os.path.join(base_path, STATEMACHINE_FILE)
    state_machine_file_path_old = os.path.join(base_path,
                                               STATEMACHINE_FILE_OLD)

    # was the root state specified as state machine base_path to load from?
    if not os.path.exists(state_machine_file_path) and not os.path.exists(
            state_machine_file_path_old):

        # catch the case that a state machine root file is handed
        if os.path.exists(base_path) and os.path.isfile(base_path):
            base_path = os.path.dirname(base_path)
            state_machine_file_path = os.path.join(base_path,
                                                   STATEMACHINE_FILE)
            state_machine_file_path_old = os.path.join(base_path,
                                                       STATEMACHINE_FILE_OLD)

        if not os.path.exists(state_machine_file_path) and not os.path.exists(
                state_machine_file_path_old):
            raise ValueError(
                "Provided path doesn't contain a valid state machine: {0}".
                format(base_path))

    if os.path.exists(state_machine_file_path):
        state_machine_dict = storage_utils.load_objects_from_json(
            state_machine_file_path)
        if 'used_rafcon_version' in state_machine_dict:
            previously_used_rafcon_version = StrictVersion(
                state_machine_dict['used_rafcon_version']).version
            active_rafcon_version = StrictVersion(rafcon.__version__).version

            rafcon_newer_than_sm_version = "You are trying to load a state machine that was stored with an older " \
                                           "version of RAFCON ({0}) than the one you are using ({1}).".format(
                                            state_machine_dict['used_rafcon_version'], rafcon.__version__)
            rafcon_older_than_sm_version = "You are trying to load a state machine that was stored with an newer " \
                                           "version of RAFCON ({0}) than the one you are using ({1}).".format(
                                            state_machine_dict['used_rafcon_version'], rafcon.__version__)
            note_about_possible_incompatibility = "The state machine will be loaded with no guarantee of success."

            if active_rafcon_version[0] > previously_used_rafcon_version[0]:
                # this is the default case
                # for a list of breaking changes please see: doc/breaking_changes.rst
                # logger.warn(rafcon_newer_than_sm_version)
                # logger.warn(note_about_possible_incompatibility)
                pass
            if active_rafcon_version[0] == previously_used_rafcon_version[0]:
                if active_rafcon_version[1] > previously_used_rafcon_version[1]:
                    # this is the default case
                    # for a list of breaking changes please see: doc/breaking_changes.rst
                    # logger.info(rafcon_newer_than_sm_version)
                    # logger.info(note_about_possible_incompatibility)
                    pass
                elif active_rafcon_version[
                        1] == previously_used_rafcon_version[1]:
                    # Major and minor version of RAFCON and the state machine match
                    # It should be safe to load the state machine, as the patch level does not change the format
                    pass
                else:
                    logger.warn(rafcon_older_than_sm_version)
                    logger.warn(note_about_possible_incompatibility)
            else:
                logger.warn(rafcon_older_than_sm_version)
                logger.warn(note_about_possible_incompatibility)

        state_machine = StateMachine.from_dict(state_machine_dict,
                                               state_machine_id)
        if "root_state_storage_id" not in state_machine_dict:
            root_state_storage_id = state_machine_dict['root_state_id']
            state_machine.supports_saving_state_names = False
        else:
            root_state_storage_id = state_machine_dict['root_state_storage_id']

    # TODO: Remove this with next minor release
    else:
        stream = file(state_machine_file_path_old, 'r')
        tmp_dict = yaml.load(stream)
        if "root_state" in tmp_dict:
            root_state_storage_id = tmp_dict['root_state']
        else:
            root_state_storage_id = tmp_dict['root_state_id']
        version = tmp_dict['version']
        # Prevents storage as datetime object
        creation_time = str(tmp_dict['creation_time'])
        if 'last_update' not in tmp_dict:
            last_update = creation_time
        else:
            last_update = tmp_dict['last_update']
        state_machine = StateMachine(version=version,
                                     creation_time=creation_time,
                                     last_update=last_update,
                                     state_machine_id=state_machine_id)
        state_machine.supports_saving_state_names = False

    root_state_path = os.path.join(base_path, root_state_storage_id)
    state_machine.file_system_path = base_path
    dirty_states = []
    state_machine.root_state = load_state_recursively(
        parent=state_machine,
        state_path=root_state_path,
        dirty_states=dirty_states)
    if len(dirty_states) > 0:
        state_machine.marked_dirty = True
    else:
        state_machine.marked_dirty = False

    hierarchy_level = 0
    number_of_states, hierarchy_level = state_machine.root_state.get_states_statistics(
        hierarchy_level)
    logger.debug(
        "Loaded state machine ({1}) has {0} states. (Max hierarchy level {2})".
        format(number_of_states, base_path, hierarchy_level))
    logger.debug("Loaded state machine ({1}) has {0} transitions.".format(
        state_machine.root_state.get_number_of_transitions(), base_path))

    return state_machine