예제 #1
0
def test_previous_state_event_none():
    m = StateMachine('m')
    s0 = StateMachine('s0')
    s1 = StateMachine('s1')
    s11 = State('s11')
    s12 = State('s12')

    m.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s1.add_state(s11, initial=True)
    s1.add_state(s12)

    m.add_transition(s0, s12, events='a')

    m.initialize()

    assert list(m.leaf_state_stack.deque) == []
    m.dispatch(_e('a'))
    assert list(m.leaf_state_stack.deque) == [s11]

    try:
        m.set_previous_leaf_state(event=None)
    except Exception as exc:
        assert not exc
    assert list(m.leaf_state_stack.deque) == [s11, s12]
예제 #2
0
def test_previous_state_with_source_event():
    def do(state, event):
        event.cargo['source_event'].cargo['data'].append(state)

    def do_with_propagate(state, event):
        event.cargo['source_event'].cargo['data'].append(state)
        event.propagate = True

    m = StateMachine('m')
    s0 = StateMachine('s0')
    s1 = StateMachine('s1')
    s11 = State('s11')
    s12 = State('s12')

    m.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s1.add_state(s11, initial=True)
    s1.add_state(s12)

    for state in s0, s1, s11, s12:
        state.handlers = {'enter': do, 'exit': do}

    m.add_transition(s0, s12, events='a')

    m.initialize()

    data = []
    assert list(m.leaf_state_stack.deque) == []
    m.dispatch(_e('a', data=data))
    assert list(m.leaf_state_stack.deque) == [s11]

    data = []
    m.set_previous_leaf_state(event=_e('a', data=data))
    assert list(m.leaf_state_stack.deque) == [s11, s12]
    assert data == [s12, s11]
예제 #3
0
def test_internal_transition():
    class Foo(object):
        def __init__(self):
            self.value = False

    foo = Foo()

    def on_enter(state, event):
        foo.value = True

    def on_exit(state, event):
        foo.value = True

    idling = State('idling')
    idling.handlers = {
        'enter': on_enter,
        'exit': on_exit,
    }

    sm = StateMachine('sm')
    sm.add_state(idling, initial=True)
    sm.add_transition(idling, None, events=['internal_transition'])
    sm.add_transition(idling, idling, events=['external_transition'])
    sm.initialize()
    sm.dispatch(_e('internal_transition'))
    assert foo.value is False
    sm.dispatch(_e('external_transition'))
    assert foo.value is True
예제 #4
0
def test_hsm_simple_hsm_transition():
    sm = StateMachine('sm')
    s0 = StateMachine('s0')
    s1 = StateMachine('s1')
    s2 = StateMachine('s2')
    s0.add_state(s1)
    s0.add_state(s2)
    s0.add_transition(s1, s2, events='a')
    s0.add_transition(s2, s1, events='a')
    s11 = State('s11')
    s12 = State('s12')
    sm.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s0.add_state(s2)
    s1.add_state(s11, initial=True)
    sm.initialize()
    assert sm.state == s0
    assert s0.state == s1
    assert s1.state == s11
    assert sm.leaf_state == s11

    sm.dispatch(_e('a'))
    assert sm.state == s0
    assert s0.state == s2
    assert sm.leaf_state == s2

    sm.dispatch(_e('a'))
    assert sm.state == s0
    assert s0.state == s1
    assert s1.state == s11
    assert sm.leaf_state == s11
예제 #5
0
def test_state_stack_high_tree():
    sm = StateMachine('sm')
    s0 = StateMachine('s0')
    s01 = StateMachine('s01')
    s011 = StateMachine('s011')
    s0111 = State('s0111')
    s0112 = State('s0112')
    s0113 = StateMachine('s0113')
    s01131 = State('s01131')

    sm.add_state(s0, initial=True)
    s0.add_state(s01, initial=True)
    s01.add_state(s011, initial=True)
    s011.add_state(s0111, initial=True)
    s011.add_state(s0112)
    s011.add_state(s0113)
    s0113.add_state(s01131, initial=True)

    s011.add_transition(s0111, s0113, events=['a'])
    sm.initialize()

    assert sm.leaf_state == s0111
    sm.dispatch(_e('a'))
    assert list(sm.state_stack.deque) == []
    assert list(s0.state_stack.deque) == []
    assert list(s01.state_stack.deque) == []
    assert list(s011.state_stack.deque) == [s0111]
    assert list(s011.leaf_state_stack.deque) == []
    assert list(s0113.state_stack.deque) == []
    assert list(sm.leaf_state_stack.deque) == [s0111]
예제 #6
0
def test_transition_from_and_to_machine_itself():
    sm = StateMachine('sm')
    s1 = State('s1')
    s2 = State('s2')
    sm.add_state(s1, initial=True)
    sm.add_state(s2)

    with pytest.raises(StateMachineException) as exc:
        sm.add_transition(sm, s1, events=['sm->s1'])
    expected = (
        'Machine "sm" error: Unable to add transition from unknown state "sm"')
    assert expected in str(exc.value)
    sm.add_transition(s1, sm, events=['s1->sm'])
    sm.initialize()

    assert sm.state == s1
    sm.dispatch(_e('sm->s1'))
    assert sm.state == s1
    assert list(sm.state_stack.deque) == []
    sm.dispatch(_e('s1->sm'))
    assert sm.state == s1
    assert list(sm.state_stack.deque) == [s1]
    sm.dispatch(_e('sm->s1'))
    assert sm.state == s1
    assert list(sm.state_stack.deque) == [s1]
    sm.dispatch(_e('s1->sm'))
    assert sm.state == s1
    assert list(sm.state_stack.deque) == [s1, s1]
예제 #7
0
def test_state_can_handle_hashable_types():
    my_mock = mock.Mock()
    test_set = frozenset([1, 2])

    m = StateMachine('m')
    s0 = State('s0')
    s1 = State('s1')

    m.add_state(s0, initial=True)
    m.add_state(s1)

    def do(state, event):
        my_mock(state, event.name)
        assert event.state_machine == m

    for state in s0, s1:
        state.handlers = {'&': do, frozenset([1, 2]): do}

    m.add_transition(s0, s1, events=['&', test_set])
    m.add_transition(s1, s0, events=['&', test_set])
    m.initialize()
    assert m.leaf_state == s0
    m.dispatch(_e('&'))
    assert m.leaf_state == s1
    assert my_mock.call_args[0] == (s0, '&')
    m.dispatch(_e(test_set))
    assert m.leaf_state == s0
    assert my_mock.call_args[0] == (s1, test_set)
    m.dispatch(_e(test_set))
    assert m.leaf_state == s1
    m.dispatch(_e('&'))
    assert m.leaf_state == s0
    assert my_mock.call_count == 4
예제 #8
0
def test_revert_to_previous_state():
    m = StateMachine('m')
    off = State('Off')
    on = State('On')
    m.add_state(off, initial=True)
    m.add_state(on)
    m.add_transition(on, off, events=['off'])
    m.add_transition(off, on, events=['on'])
    m.initialize()
    off.handlers = {
        'test_no_history': lambda s, e: m.revert_to_previous_leaf_state()
    }

    assert m.leaf_state == off
    try:
        m.dispatch(_e('test_no_history'))
    except Exception as exc:
        assert not exc
    assert m.leaf_state == off
    assert list(m.leaf_state_stack.deque) == []

    m.dispatch(_e('on'))
    assert m.leaf_state == on
    assert list(m.leaf_state_stack.deque) == [off]
    m.dispatch(_e('off'))
    assert m.leaf_state == off
    assert list(m.leaf_state_stack.deque) == [off, on]

    try:
        m.dispatch(_e('test_no_history'))
    except Exception as exc:
        assert not exc
    assert m.leaf_state == on
    assert list(m.leaf_state_stack.deque) == [off, on]
예제 #9
0
def test_transition_on_any_event():
    m = StateMachine('m')
    s0 = State('s0')
    s1 = State('s1')
    m.add_state(s0, initial=True)
    m.add_state(s1)
    m.add_transition(s0, s1, events=[any_event])
    m.add_transition(s1, s0, events=[any_event])
    m.initialize()

    assert m.leaf_state == s0
    m.dispatch(_e('whatever'))
    assert m.leaf_state == s1
    m.dispatch(_e('whatever'))
    assert m.leaf_state == s0
예제 #10
0
def test_set_previous_state_no_history():
    m = StateMachine('m')
    off = State('Off')
    m.add_state(off, initial=True)
    m.initialize()
    off.handlers = {
        'test_no_history': lambda s, e: m.set_previous_leaf_state()
    }

    assert m.leaf_state == off
    try:
        m.dispatch(_e('test_no_history'))
    except Exception as exc:
        assert not exc
    assert m.leaf_state == off
    assert list(m.leaf_state_stack.deque) == []
예제 #11
0
def test_state_stack():
    sm = StateMachine('sm')
    s1 = State('s1')
    s2 = State('s2')
    s3 = StateMachine('s3')
    s31 = State('s31')
    s32 = State('s32')

    sm.add_state(s1, initial=True)
    sm.add_state(s2)
    sm.add_state(s3)
    s3.add_state(s31, initial=True)
    s3.add_state(s32)

    sm.add_transition(s1, s2, events=['s1->s2'])
    sm.add_transition(s2, s1, events=['s2->s1'])
    sm.add_transition(s1, s3, events=['a'])
    s3.add_transition(s31, s32, events=['b'])
    sm.initialize()

    assert sm.state == s1
    assert sm.leaf_state == s1

    sm.dispatch(_e('s1->s2'))
    assert sm.state == s2
    assert sm.leaf_state == s2
    assert list(sm.state_stack.deque) == [s1]

    sm.dispatch(_e('s2->s1'))
    assert sm.state == s1
    assert sm.leaf_state == s1
    assert list(sm.state_stack.deque) == [s1, s2]

    sm.dispatch(_e('a'))
    assert sm.state == s3
    assert sm.leaf_state == s31
    assert s3.leaf_state == s31
    assert list(sm.state_stack.deque) == [s1, s2, s1]
    assert list(s3.state_stack.deque) == []

    sm.dispatch(_e('b'))
    assert sm.state == s3
    assert sm.leaf_state == s32
    assert s3.state == s32
    assert s3.leaf_state == s32
    assert list(sm.state_stack.deque) == [s1, s2, s1]
    assert list(s3.state_stack.deque) == [s31]

    # Brute force rollback of the previous state
    s3.state = s3.state_stack.pop()
    sm.state = sm.state_stack.pop()
    assert sm.state == s1
    assert sm.leaf_state == s1
    assert s3.state == s31
    assert s3.leaf_state == s31
    assert list(sm.state_stack.deque) == [s1, s2]
    assert list(s3.state_stack.deque) == []
예제 #12
0
def test_transition_to_history():
    oven = StateMachine('Oven')
    door_closed = StateMachine('DoorClosed')
    door_open = State('DoorOpen')
    heating = StateMachine('Heating')
    toasting = State('Toasting')
    baking = State('Baking')
    off = State('Off')

    oven.add_state(door_closed, initial=True)
    oven.add_state(door_open)
    door_closed.add_state(off, initial=True)
    door_closed.add_state(heating)
    heating.add_state(baking, initial=True)
    heating.add_state(toasting)

    oven.add_transition(door_closed, toasting, events=['toast'])
    oven.add_transition(door_closed, baking, events=['bake'])
    oven.add_transition(door_closed, off, events=['off', 'timeout'])
    oven.add_transition(door_closed, door_open, events=['open'])

    door_open.handlers = {'close': lambda s, e: oven.set_previous_leaf_state()}

    oven.initialize()

    assert oven.leaf_state == off
    oven.dispatch(_e('open'))
    assert oven.leaf_state == door_open
    try:
        oven.dispatch(_e('close'))
    except Exception as exc:
        assert not exc
    assert oven.leaf_state == off
    assert list(oven.leaf_state_stack.deque) == [off, door_open]

    oven.dispatch(_e('bake'))
    assert oven.leaf_state == baking
    oven.dispatch(_e('open'))
    assert oven.leaf_state == door_open
    try:
        oven.dispatch(_e('close'))
    except Exception as exc:
        assert not exc
    assert oven.leaf_state == baking
    expected = [off, door_open, off, baking, door_open]
    assert list(oven.leaf_state_stack.deque) == expected
예제 #13
0
def test_state_machine_reference_present_in_event_with_nested_machines():
    m = StateMachine('m')
    s0 = StateMachine('s0')
    s1 = StateMachine('s1')
    s2 = State('s2')

    m.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s1.add_state(s2, initial=True)

    def do(state, event):
        assert event.state_machine == m

    for state in s0, s1, s2:
        state.handlers = {'enter': do, 'exit': do, 'do': do}

    m.add_transition(s0, s2, events=['do'])
    m.initialize()
    m.dispatch(_e('do'))
예제 #14
0
def test_add_transition_event_with_input():
    sm = StateMachine('sm')
    s1 = State('s1')
    s2 = State('s2')
    s3 = State('s3')
    sm.add_state(s1, initial=True)
    sm.add_state(s2)
    sm.add_state(s3)

    sm.add_transition(s1, s2, events=['a'], input=['go_to_s2'])
    sm.add_transition(s1, s3, events=['a'], input=['go_to_s3'])
    sm.add_transition(s2, s1, events=['a'])
    sm.add_transition(s3, s1, events=['a'])
    sm.initialize()

    assert sm.state == s1
    sm.dispatch(_e('a', input='go_to_s2'))
    assert sm.state == s2
    sm.dispatch(_e('a'))
    assert sm.state == s1
    sm.dispatch(_e('a', input='go_to_s3'))
    assert sm.state == s3
    sm.dispatch(_e('a'))
    assert sm.state == s1
예제 #15
0
def test_event_propagate_enter_exit():
    data = []

    def do(state, event):
        event.cargo['source_event'].cargo['data'].append(state)

    def do_with_propagate(state, event):
        event.cargo['source_event'].cargo['data'].append(state)
        event.propagate = True

    m = StateMachine('m')
    s0 = StateMachine('s0')
    s1 = StateMachine('s1')
    s2 = StateMachine('s2')
    s3 = StateMachine('s3')
    s4 = State('s4')

    m.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s1.add_state(s2, initial=True)
    s2.add_state(s3, initial=True)
    s3.add_state(s4, initial=True)

    m.add_transition(s0, s0, events='a')

    for state in s0, s1, s2, s3, s4:
        state.handlers = {'enter': do, 'exit': do}

    m.initialize()

    m.dispatch(_e('a', data=data))
    assert data == [s4, s3, s2, s1, s0, s0, s1, s2, s3, s4]

    data = []
    s1.handlers = {}
    s3.handlers = {}
    m.dispatch(_e('a', data=data))
    assert data == [s4, s2, s0, s0, s2, s4]

    # Never propagate exit/enter events, even if propagate is set to True
    data = []
    s4.handlers = {'enter': do_with_propagate, 'exit': do_with_propagate}
    m.dispatch(_e('a', data=data))
    assert data == [s4, s2, s0, s0, s2, s4]
예제 #16
0
파일: test_pysm.py 프로젝트: micronext/pysm
def test_revert_to_previous_state_not_reverting_after_first_iteration():
    m = StateMachine('m')
    one = State('One')
    two = State('Two')
    three = State('Three')
    four = State('Four')
    m.add_state(one, initial=True)
    m.add_state(two)
    m.add_state(three)
    m.add_state(four)
    m.add_transition(one, two, events=['switch_to_two'])
    m.add_transition(two, three, events=['switch_to_three'])
    m.add_transition(three, four, events=['switch_to_four'])
    m.initialize()
    for state in [one, two, three, four]:
        state.handlers = {
            'test_no_history': lambda s, e: m.revert_to_previous_leaf_state()
        }

    assert m.leaf_state == one
    assert list(m.leaf_state_stack.deque) == []

    m.dispatch(_e('switch_to_two'))
    m.dispatch(_e('switch_to_three'))
    m.dispatch(_e('switch_to_four'))
    assert m.leaf_state == four
    assert list(m.leaf_state_stack.deque) == [one, two, three]

    try:
        m.dispatch(_e('test_no_history'))
    except Exception as exc:
        assert not exc
    assert m.leaf_state == three
    assert list(m.leaf_state_stack.deque) == [one, two]

    try:
        m.dispatch(_e('test_no_history'))
    except Exception as exc:
        assert not exc
    assert m.leaf_state == two
    assert list(m.leaf_state_stack.deque) == [one]

    try:
        m.dispatch(_e('test_no_history'))
    except Exception as exc:
        assert not exc
    assert m.leaf_state == one
    assert list(m.leaf_state_stack.deque) == []

    try:
        m.dispatch(_e('test_no_history'))
    except Exception as exc:
        assert not exc
    assert m.leaf_state == one
    assert list(m.leaf_state_stack.deque) == []
예제 #17
0
def test_event_propagate():
    data = []

    def do(state, event):
        event.cargo['data'].append(state)

    def do_with_propagate(state, event):
        event.cargo['data'].append(state)
        event.propagate = True

    m = StateMachine('m')
    s0 = StateMachine('s0')
    s1 = StateMachine('s1')
    s2 = StateMachine('s2')
    s3 = StateMachine('s3')
    s4 = State('s4')

    m.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s1.add_state(s2, initial=True)
    s2.add_state(s3, initial=True)
    s3.add_state(s4, initial=True)

    for state in s0, s1, s2, s3, s4:
        state.handlers = {'do': do}

    m.initialize()

    # No propagate by default
    m.dispatch(_e('do', data=data))
    assert data == [s4]

    # Should propagate only to the next state that can handle the event
    data = []
    s4.handlers = {'do': do_with_propagate}
    m.dispatch(_e('do', data=data))
    assert data == [s4, s3]

    data = []
    s4.handlers = {'do': do_with_propagate}
    s3.handlers = {}
    m.dispatch(_e('do', data=data))
    assert data == [s4, s2]

    data = []
    s4.handlers = {'do': do_with_propagate}
    s3.handlers = {'do': do}
    m.dispatch(_e('do', data=data))
    assert data == [s4, s3]

    data = []
    s4.handlers = {}
    s3.handlers = {}
    m.dispatch(_e('do', data=data))
    assert data == [s2]

    data = []
    s4.handlers = {}
    s3.handlers = {}
    s2.handlers = {'do': do_with_propagate}
    m.dispatch(_e('do', data=data))
    assert data == [s2, s1]
예제 #18
0
def test_internal_vs_external_transitions():
    test_list = []

    class Foo(object):
        value = True

    def on_enter(state, event):
        test_list.append(('enter', state))

    def on_exit(state, event):
        test_list.append(('exit', state))

    def set_foo(state, event):
        Foo.value = True
        test_list.append('set_foo')

    def unset_foo(state, event):
        Foo.value = False
        test_list.append('unset_foo')

    def action_i(state, event):
        test_list.append('action_i')
        return True

    def action_j(state, event):
        test_list.append('action_j')
        return True

    def action_k(state, event):
        test_list.append('action_k')
        return True

    def action_l(state, event):
        test_list.append('action_l')

    def action_m(state, event):
        test_list.append('action_m')

    def action_n(state, event):
        test_list.append('action_n')
        return True

    m = StateMachine('m')
    # exit = m.add_state('exit', terminal=True)
    s0 = StateMachine('s0')
    s1 = StateMachine('s1')
    s2 = StateMachine('s2')

    s11 = State('s11')
    s21 = StateMachine('s21')
    s211 = State('s211')
    s212 = State('s212')

    m.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s0.add_state(s2)
    s1.add_state(s11, initial=True)
    s2.add_state(s21, initial=True)
    s21.add_state(s211, initial=True)
    s21.add_state(s212)

    states = [m, s0, s1, s11, s2, s21, s211, s212]
    for state in states:
        state.handlers = {'enter': on_enter, 'exit': on_exit}

    s0.add_transition(s1, s1, events='a')
    s0.add_transition(s1, s11, events='b')
    s2.add_transition(s21, s211, events='b')
    s0.add_transition(s1, s2, events='c')
    s0.add_transition(s2, s1, events='c')
    s0.add_transition(s1, s0, events='d')
    s21.add_transition(s211, s21, events='d')
    m.add_transition(s0, s211, events='e')
    m.add_transition(s0, s212, events='z')
    s0.add_transition(s2, s11, events='f')
    s0.add_transition(s1, s211, events='f')
    s1.add_transition(s11, s211, events='g')
    s21.add_transition(s211, s0, events='g')

    m.initialize()

    # Internal transitions
    m.add_transition(s0, None, events='i', action=action_i)
    s0.add_transition(s1, None, events='j', action=action_j)
    s0.add_transition(s2, None, events='k', action=action_k)
    s1.add_transition(s11, None, events='n', action=action_n)
    s1.add_transition(s11,
                      None,
                      events='h',
                      condition=lambda s, e: Foo.value is True,
                      action=unset_foo)
    s2.add_transition(s21,
                      None,
                      events='l',
                      condition=lambda s, e: Foo.value is True,
                      action=action_l)
    s21.add_transition(s211, None, events='m', action=action_m)
    # External transition
    s2.add_transition(s21,
                      s21,
                      events='h',
                      condition=lambda s, e: Foo.value is False,
                      action=set_foo)

    m.initialize()

    test_list[:] = []
    m.dispatch(_e('i'))
    assert test_list == ['action_i']
    assert m.leaf_state == s11

    test_list[:] = []
    m.dispatch(_e('j'))
    assert test_list == ['action_j']
    assert m.leaf_state == s11

    test_list[:] = []
    m.dispatch(_e('n'))
    assert test_list == ['action_n']
    assert m.leaf_state == s11

    # This transition toggles state between s11 and s211
    m.dispatch(_e('c'))
    assert m.leaf_state == s211

    test_list[:] = []
    m.dispatch(_e('i'))
    assert test_list == ['action_i']
    assert m.leaf_state == s211

    test_list[:] = []
    m.dispatch(_e('k'))
    assert test_list == ['action_k']
    assert m.leaf_state == s211

    test_list[:] = []
    m.dispatch(_e('m'))
    assert test_list == ['action_m']
    assert m.leaf_state == s211

    test_list[:] = []
    m.dispatch(_e('n'))
    assert test_list == []
    assert m.leaf_state == s211

    # This transition toggles state between s11 and s211
    m.dispatch(_e('c'))
    assert m.leaf_state == s11

    test_list[:] = []
    assert Foo.value is True
    m.dispatch(_e('h'))
    assert Foo.value is False
    assert test_list == ['unset_foo']
    assert m.leaf_state == s11

    test_list[:] = []
    m.dispatch(_e('h'))
    assert test_list == []  # Do nothing if foo is False
    assert m.leaf_state == s11

    # This transition toggles state between s11 and s211
    m.dispatch(_e('c'))
    assert m.leaf_state == s211

    test_list[:] = []
    assert Foo.value is False
    m.dispatch(_e('h'))
    assert test_list == [('exit', s211), ('exit', s21), 'set_foo',
                         ('enter', s21), ('enter', s211)]
    assert Foo.value is True
    assert m.leaf_state == s211

    test_list[:] = []
    m.dispatch(_e('h'))
    assert test_list == []
    assert m.leaf_state == s211
예제 #19
0
def test_enter_exit_on_transitions():
    test_list = []

    def on_enter(state, event):
        test_list.append(('enter', state))

    def on_exit(state, event):
        test_list.append(('exit', state))

    m = StateMachine('m')
    # exit = m.add_state('exit', terminal=True)
    s0 = StateMachine('s0')
    s1 = StateMachine('s1')
    s2 = StateMachine('s2')

    s11 = State('s11')
    s21 = StateMachine('s21')
    s211 = State('s211')
    s212 = State('s212')

    m.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s0.add_state(s2)
    s1.add_state(s11, initial=True)
    s2.add_state(s21, initial=True)
    s21.add_state(s211, initial=True)
    s21.add_state(s212)

    states = [m, s0, s1, s11, s2, s21, s211, s212]
    for state in states:
        state.handlers = {'enter': on_enter, 'exit': on_exit}

    s0.add_transition(s1, s1, events='a')
    s0.add_transition(s1, s11, events='b')
    s2.add_transition(s21, s211, events='b')
    s0.add_transition(s1, s2, events='c')
    s0.add_transition(s2, s1, events='c')
    s0.add_transition(s1, s0, events='d')
    s21.add_transition(s211, s21, events='d')
    m.add_transition(s0, s211, events='e')
    m.add_transition(s0, s212, events='z')
    s0.add_transition(s2, s11, events='f')
    s0.add_transition(s1, s211, events='f')
    s1.add_transition(s11, s211, events='g')
    s21.add_transition(s211, s0, events='g')

    m.initialize()

    test_list[:] = []
    m.dispatch(_e('a'))
    assert test_list == [('exit', s11), ('exit', s1), ('enter', s1),
                         ('enter', s11)]

    test_list[:] = []
    m.dispatch(_e('b'))
    assert test_list == [('exit', s11), ('enter', s11)]
    m.dispatch(_e('c'))
    test_list[:] = []
    m.dispatch(_e('b'))
    assert test_list == [('exit', s211), ('enter', s211)]
    m.dispatch(_e('c'))

    test_list[:] = []
    m.dispatch(_e('c'))
    assert test_list == [('exit', s11), ('exit', s1), ('enter', s2),
                         ('enter', s21), ('enter', s211)]
    test_list[:] = []
    m.dispatch(_e('c'))
    assert test_list == [('exit', s211), ('exit', s21), ('exit', s2),
                         ('enter', s1), ('enter', s11)]

    test_list[:] = []
    m.dispatch(_e('d'))
    assert test_list == [('exit', s11), ('exit', s1), ('enter', s1),
                         ('enter', s11)]
    m.dispatch(_e('c'))
    test_list[:] = []
    m.dispatch(_e('d'))
    assert test_list == [('exit', s211), ('enter', s211)]
    m.dispatch(_e('c'))

    test_list[:] = []
    m.dispatch(_e('e'))
    assert test_list == [('exit', s11), ('exit', s1), ('enter', s2),
                         ('enter', s21), ('enter', s211)]
    test_list[:] = []
    m.dispatch(_e('e'))
    assert test_list == [('exit', s211), ('exit', s21), ('exit', s2),
                         ('enter', s2), ('enter', s21), ('enter', s211)]

    test_list[:] = []
    m.dispatch(_e('f'))
    assert test_list == [('exit', s211), ('exit', s21), ('exit', s2),
                         ('enter', s1), ('enter', s11)]
    test_list[:] = []
    m.dispatch(_e('f'))
    assert test_list == [('exit', s11), ('exit', s1), ('enter', s2),
                         ('enter', s21), ('enter', s211)]

    test_list[:] = []
    m.dispatch(_e('g'))
    assert test_list == [('exit', s211), ('exit', s21), ('exit', s2),
                         ('enter', s1), ('enter', s11)]
    test_list[:] = []
    m.dispatch(_e('g'))
    assert test_list == [('exit', s11), ('exit', s1), ('enter', s2),
                         ('enter', s21), ('enter', s211)]

    test_list[:] = []
    m.dispatch(_e('z'))
    assert test_list == [('exit', s211), ('exit', s21), ('exit', s2),
                         ('enter', s2), ('enter', s21), ('enter', s212)]
    assert m.leaf_state == s212

    test_list[:] = []
    m.dispatch(_e('c'))
    assert test_list == [('exit', s212), ('exit', s21), ('exit', s2),
                         ('enter', s1), ('enter', s11)]
    assert m.leaf_state == s11

    test_list[:] = []
    m.dispatch(_e('g'))
    assert m.leaf_state == s211
    assert test_list == [('exit', s11), ('exit', s1), ('enter', s2),
                         ('enter', s21), ('enter', s211)]
    assert m.leaf_state == s211
예제 #20
0
def test_new_sm():
    run_call_mock = mock.Mock()
    stop_call_mock = mock.Mock()
    idling_mock = mock.Mock()
    running_mock = mock.Mock()
    action_mock = mock.Mock()

    class Idling(State):
        # @event('run')
        def run(self, state, event):
            run_call_mock(self, event.input, event.cargo)

        def do(self, state, event):
            entity = event.cargo['entity']
            entity.do()

        def on_enter(self, state, event):
            idling_mock(self, 'on_enter')

        def on_exit(self, state, event):
            idling_mock(self, 'on_exit')

        def register_handlers(self):
            self.handlers = {
                'run': self.run,
                'do': self.do,
                'enter': self.on_enter,
                'exit': self.on_exit,
            }

    def stop(state, event):
        stop_call_mock('stopping...', event.cargo)

    def do(state, event):
        entity = event.cargo['entity']
        entity.do()

    def enter(state, event):
        running_mock('running, enter')

    def exit(state, event):
        running_mock('running, exit')

    def update(state, event):
        print('update', event)

    def do_on_transition(state, event):
        action_mock('action on transition')

    class Entity(object):
        def do(self):
            print(self, self.do)

    idling = Idling('idling')
    running = State('running')
    running.handlers = {
        'stop': stop,
        'do': do,
        'update': update,
        'enter': enter,
        'exit': exit,
    }

    entity = Entity()

    sm = StateMachine('sm')
    sm.add_state(idling, initial=True)
    sm.add_state(running)
    sm.add_transition(idling, running, events=['run'], action=do_on_transition)
    sm.add_transition(running, idling, events=['stop'])
    sm.initialize()
    assert sm.state == idling
    sm.dispatch(_e('run'))
    assert sm.state == running
    assert run_call_mock.call_count == 1
    assert run_call_mock.call_args[0] == (idling, None, {})
    assert idling_mock.call_count == 1
    assert idling_mock.call_args[0] == (idling, 'on_exit')
    assert running_mock.call_count == 1
    assert running_mock.call_args[0] == ('running, enter', )
    assert action_mock.call_count == 1
    assert action_mock.call_args[0] == ('action on transition', )

    # Nothing should happen - running state has no 'run' handler
    sm.dispatch(_e('run'))
    assert sm.state == running
    assert run_call_mock.call_count == 1
    assert run_call_mock.call_args[0] == (idling, None, {})

    sm.dispatch(_e('stop'))
    assert sm.state == idling
    assert idling_mock.call_count == 2
    assert idling_mock.call_args[0] == (idling, 'on_enter')
    assert running_mock.call_count == 2
    assert running_mock.call_args[0] == ('running, exit', )
    assert stop_call_mock.call_count == 1
    assert stop_call_mock.call_args[0] == ('stopping...', {})

    # Unknown events must be ignored
    sm.dispatch(_e('blah'))
    sm.dispatch(_e('blah blah'))
    assert sm.state == idling
예제 #21
0
def test_conditions():
    class Bool(object):
        def __init__(self):
            self.value = True

        def get(self, state, event):
            return self.value

    bool_a = Bool()
    bool_b = Bool()

    def run(event):
        print('runninng...')

    idling = State('idling')
    running = State('running')
    stopped = State('stopped')
    broken = State('broken')

    sm = StateMachine('sm')
    sm.add_state(idling, initial=True)
    sm.add_state(running)
    sm.add_state(stopped)
    sm.add_state(broken)
    sm.add_transition(idling, running, events=['run'], condition=bool_a.get)
    sm.add_transition(idling, stopped, events=['run'], condition=bool_b.get)
    sm.add_transition(running, idling, events=['idle'])
    sm.add_transition(stopped, idling, events=['idle'])
    sm.add_transition(broken, idling, events=['idle'])
    sm.initialize()

    # Expect no change
    bool_a.value = False
    bool_b.value = False
    assert sm.state == idling
    sm.dispatch(_e('run'))
    assert sm.state == idling
    sm.dispatch(_e('idle'))
    assert sm.state == idling

    # Expect first transition
    bool_a.value = True
    bool_b.value = False
    assert sm.state == idling
    sm.dispatch(_e('run'))
    assert sm.state == running
    sm.dispatch(_e('idle'))
    assert sm.state == idling

    # Expect first transition
    bool_a.value = True
    bool_b.value = True
    assert sm.state == idling
    sm.dispatch(_e('run'))
    assert sm.state == running
    sm.dispatch(_e('idle'))
    assert sm.state == idling

    # Expect second  transition
    bool_a.value = False
    bool_b.value = True
    assert sm.state == idling
    sm.dispatch(_e('run'))
    assert sm.state == stopped
    sm.dispatch(_e('idle'))
    assert sm.state == idling

    sm.add_transition(idling, broken, events=['run'])
    # Expect transition to state without condition
    bool_a.value = False
    bool_b.value = False
    assert sm.state == idling
    sm.dispatch(_e('run'))
    assert sm.state == broken
    sm.dispatch(_e('idle'))
    assert sm.state == idling
        print("1 Despertarse")
        print("2 Dormirse")
        print("3 Saltar")
        print("4 Morir")
        print("\nQue deberia hacer Pepe?", end=" ")
        opc = input()
        os.system('cls')
        try:
            opc = int(opc)
            if (opc < 1 or opc > 4):
                print("Lanzo Exception", opc)
                raise Exception("del 1 al 4 weon")
            else:
                if (sm.state == despierto):
                    if (opc == 1):
                        sm.dispatch(Event('Cafe'))
                    if (opc == 2):
                        sm.dispatch(Event('Acostarse'))
                    if (opc == 3):
                        sm.dispatch(Event('Saltar'))

                elif (sm.state == dormido):
                    if (opc == 1):
                        sm.dispatch(Event('Despertarse'))
                    if (opc == 2):
                        print(
                            "ERROR: Loco no podes dormir si ya estas dormido")
                    if (opc == 3):
                        print("ERROR: Pepe no sufre de sonambulismo")

                elif (sm.state == saltado):
예제 #23
0
def test_state_instance_passed_to_an_event_handler():
    def on_enter(state, event):
        source_event = event.cargo['source_event']
        source_event.cargo['test_list'].append(('enter', state))

    def on_exit(state, event):
        source_event = event.cargo['source_event']
        source_event.cargo['test_list'].append(('exit', state))

    def before(state, event):
        assert state == s1

    def action(state, event):
        assert state == s1

    def after(state, event):
        assert state == s2

    def on_internal(state, event):
        assert state == s1

    def do(state, event):
        assert state == m

    def condition(state, event):
        assert state == s1
        return True

    m = StateMachine('m')
    s0 = StateMachine('s0')
    s1 = State('s1')
    s2 = State('s2')
    m.add_state(s0, initial=True)
    s0.add_state(s1, initial=True)
    s0.add_state(s2)

    m.add_transition(s0, s0, events='a')
    s0.add_transition(s1,
                      None,
                      events=['internal'],
                      before=on_internal,
                      action=on_internal,
                      after=on_internal)
    s0.add_transition(s1,
                      s2,
                      events='b',
                      before=before,
                      action=action,
                      after=after,
                      condition=condition)
    s0.add_transition(s2, s1, events='b')

    for state in [m, s0, s1, s2]:
        state.handlers = {'enter': on_enter, 'exit': on_exit}

    m.handlers = {'do': do}

    m.initialize()

    test_list = []
    m.dispatch(_e('a', test_list=test_list))
    assert test_list == [('exit', s1), ('exit', s0), ('enter', s0),
                         ('enter', s1)]

    m.dispatch(_e('b', test_list=test_list))
    m.dispatch(_e('do'))
    m.dispatch(_e('b', test_list=test_list))

    m.dispatch(_e('internal'))