def test_event_propagate_enter_exit(): data = [] m = StateMachine('m') s0 = StateMachine('s0') s1 = StateMachine('s1') s2 = StateMachine('s2') s3 = StateMachine('s3') s4 = State('s4') def do(state, event): event.cargo['source_event'].cargo['data'].append(state) assert state == m.leaf_state def do_with_propagate(state, event): event.cargo['source_event'].cargo['data'].append(state) event.propagate = True assert state == m.leaf_state 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]
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]
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'))
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]
def test_state_instance_passed_to_an_event_handler(): 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) def on_enter(state, event): source_event = event.cargo['source_event'] source_event.cargo['test_list'].append(('enter', state)) assert state == m.leaf_state def on_exit(state, event): source_event = event.cargo['source_event'] source_event.cargo['test_list'].append(('exit', state)) assert state == m.leaf_state def before(state, event): assert state == s1 assert state == m.leaf_state def action(state, event): assert state == s1 assert state == m.leaf_state def after(state, event): assert state == s2 assert state == m.leaf_state def on_internal(state, event): assert state == s1 assert state == m.leaf_state def do(state, event): # It's an action on the top machine, the `leaf_state` is NOT `state` assert state != m.leaf_state assert state == m def condition(state, event): assert state == s1 assert state == m.leaf_state return True 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'))