コード例 #1
0
    def test_transition_action_function_with_event(self, empty_statechart):
        self.state = False

        def set_state(event):
            self.state = event.data['state']

        sc = empty_statechart
        initial = InitialState(sc)
        default = State(name='default', context=sc)
        next = State(name='next', context=sc)

        Transition(start=initial, end=default)
        Transition(start=default, end=next, event='next', action=set_state)

        sc.start()
        sc.dispatch(Event(name='next', data={'state': True}))

        assert self.state
コード例 #2
0
    def test_activate_initial_state(self):
        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)
        Transition(start=initial_state, end=default_state)
        startchart.start()

        initial_state.activate(metadata=startchart._metadata, event=None)
        assert startchart.is_active('default')
コード例 #3
0
def simple_statechart():
    sc = Statechart('simple')
    sc.init = InitialState(sc)
    sc.state = State(name='state', context=sc)
    sc.final = FinalState(sc)

    Transition(start=sc.init, end=sc.state)
    Transition(start=sc.state, end=sc.final, event=Event('finish'))

    return sc
コード例 #4
0
    def test_transition_from_finished_composite_state(self):
        statechart = Statechart(name='statechart')
        statechart_init = InitialState(statechart)

        composite_state = CompositeState(name='composite', context=statechart)
        comp_init = InitialState(composite_state)
        a = State(name='a', context=composite_state)
        comp_final = FinalState(composite_state)

        Transition(start=statechart_init, end=composite_state)
        Transition(start=comp_init, end=a)
        Transition(start=a, end=comp_final, event=Event('e'))

        b = State(name='b', context=statechart)
        Transition(start=composite_state, end=b)

        statechart.start()
        assert statechart.is_active('a')
        statechart.dispatch(Event('e'))
        assert statechart.is_active('b')
コード例 #5
0
    def test_choice_state_transitions(self, state_name, expected_state_name):
        def is_a(**kwargs):
            return state_name == 'a'

        statechart = Statechart(name='statechart')
        init = InitialState(statechart)

        state_a = State(name='a', context=statechart)
        state_b = State(name='b', context=statechart)

        choice = ChoiceState(context=statechart)

        Transition(start=init, end=choice)

        Transition(start=choice, end=state_a, event=None, guard=is_a)
        Transition(start=choice, end=state_b, event=None, guard=None)  # else

        statechart.start()

        assert statechart.is_active(expected_state_name)
コード例 #6
0
    def test_transition_action_function_with_metadata(self, empty_statechart):
        sc = empty_statechart
        sc.metadata.state = True

        self.state = False

        def set_state(event):
            self.state = sc.metadata.state

        initial = InitialState(sc)
        default = State(name='default', context=sc)
        next = State(name='next', context=sc)

        Transition(start=initial, end=default)
        Transition(start=default, end=next, event='next', action=set_state)

        sc.start()
        sc.dispatch(Event('next'))

        assert self.state
コード例 #7
0
    def test_transition_action_function(self, empty_statechart):
        self.state = False

        def set_state(state):
            self.state = bool(state)

        set_true = partial(set_state, True)

        sc = empty_statechart
        initial = InitialState(sc)
        default = State(name='default', context=sc)
        next = State(name='next', context=sc)

        Transition(start=initial, end=default)
        Transition(start=default, end=next, event='next', action=set_true)

        sc.start()
        sc.dispatch(Event('next'))

        assert self.state
コード例 #8
0
    def test_transition_from_initial_state_with_guard_condition(self):
        class MyGuard(Guard):
            def check(self, metadata, event):
                return False

        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)

        with pytest.raises(RuntimeError):
            Transition(start=initial_state, end=default_state, event=None, guard=MyGuard())
コード例 #9
0
    def composite(name, context):
        composite = CompositeState(name=name, context=context)
        composite.init = InitialState(composite)
        composite.state = State(name='state', context=composite)
        composite.final = FinalState(composite)

        Transition(start=composite.init, end=composite.state)
        Transition(start=composite.state,
                   end=composite.final,
                   event=Event('finish'))

        return composite
コード例 #10
0
    def test_create_cyclic_transition(self, empty_statechart):
        next_state = State(name='next', context=empty_statechart)
        transition = Transition(start=next_state, end=next_state)

        # The transition should be added to the initial state's list of
        # outgoing transitions.
        assert transition in next_state._transitions

        # When executed, the transition should be setup to deactivate the
        # next state and to re-activate it.
        assert next_state in transition.deactivate
        assert next_state in transition.activate
コード例 #11
0
    def test_transition_from_initial_state_with_guard_condition(self):
        startchart = Statechart(name='statechart')
        initial_state = InitialState(startchart)
        default_state = State(name='default', context=startchart)

        def my_guard(**kwargs):
            return False

        with pytest.raises(RuntimeError):
            Transition(start=initial_state,
                       end=default_state,
                       event=None,
                       guard=my_guard)
コード例 #12
0
    def test_create_transition(self, empty_statechart):
        initial_state = InitialState(empty_statechart)
        next_state = State(name='next', context=empty_statechart)
        transition = Transition(start=initial_state, end=next_state)

        # The transition should be added to the initial state's list of
        # outgoing transitions
        assert transition in initial_state.transitions

        # When executed, the transition should be setup to deactivate the
        # initial state and to activate the next state
        assert initial_state in transition.deactivate
        assert next_state in transition.activate
コード例 #13
0
    def test_default_transition_isnt_executed_from_unfinished_composite_state(
            self):
        statechart = Statechart(name='statechart')
        statechart_init = InitialState(statechart)

        composite_state = CompositeState(name='composite', context=statechart)
        comp_init = InitialState(composite_state)
        a = State(name='a', context=composite_state)

        Transition(start=statechart_init, end=composite_state)
        Transition(start=comp_init, end=a)

        b = State(name='b', context=statechart)

        Transition(start=composite_state, end=b)

        statechart.start()

        assert statechart.is_active('a')

        statechart.dispatch(Event('e'))

        assert statechart.is_active('a')
コード例 #14
0
    def test_light_switch(self):
        """
                      --Flick-->
        init ---> Off            On
                      <--Flick--   Entry: Light = ON
                                   Exit: Light = OFF
                                   Internal:
                                     Flick: Count++
        """
        class On(State):
            def __init__(self, name, context, data):
                State.__init__(self, name=name, context=context)
                self.data = data

            def entry(self, event):
                self.data['light'] = 'on'

            def exit(self, event):
                self.data['light'] = 'off'

            def handle_internal(self, event):
                if event.name == 'flick':
                    self.data['on_count'] += 1

        sm = Statechart(name='sm')
        data = dict(light='off', on_count=0)
        sm.initial_state = InitialState(context=sm)
        off = State(name='off', context=sm)
        on = On(name='on', context=sm, data=data)

        Transition(start=sm.initial_state, end=off)
        Transition(start=off, end=on, event=Event('flick'))
        Transition(start=on, end=off, event=Event('flick'))

        sm.start()

        assert data['light'] == 'off'

        sm.dispatch(Event('flick'))
        assert data['light'] == 'on'

        assert data['on_count'] == 0

        sm.dispatch(Event('flick'))
        assert data['light'] == 'off'

        assert data['on_count'] == 1
コード例 #15
0
    def test_simple_statechart_finished(self):
        statechart = Statechart(name='statechart')
        init = InitialState(statechart)
        default = State(name='default', context=statechart)
        final = FinalState(statechart)

        finish = Event('finish')

        Transition(start=init, end=default)
        Transition(start=default, end=final, event=finish)
        statechart.start()

        assert statechart.is_active('default')
        assert not statechart.is_finished()

        statechart.dispatch(finish)

        assert statechart.is_finished()
コード例 #16
0
    def test_active_states(self):
        statechart = Statechart(name='a')
        statechart_init = InitialState(statechart)

        b = CompositeState(name='b', context=statechart)
        b_init = InitialState(b)

        c = CompositeState(name='c', context=b)
        c_init = InitialState(c)

        d = State(name='d', context=c)

        Transition(start=statechart_init, end=b)
        Transition(start=b_init, end=c)
        Transition(start=c_init, end=d)

        statechart.start()
        assert statechart.active_states() == [statechart, b, c, d]
コード例 #17
0
    def test_top_level_internal_transition(self, empty_statechart):
        sc = empty_statechart
        sc_init = InitialState(sc)

        cs = CompositeState(name='cs', context=sc)
        cs_init = InitialState(cs)
        cs_default = State(name='cs_default', context=cs)

        Transition(start=sc_init, end=cs)
        Transition(start=cs_init, end=cs_default)

        test_event = Event('internal-event-trigger')
        InternalTransition(state=cs, event=test_event)

        sc.start()

        assert sc.is_active('cs_default')

        sc.dispatch(test_event)

        assert sc.is_active('cs_default')
コード例 #18
0
    def test_activate_shallow_history_state(self):
        """
        statechart:

        statechart_init
                  |
        *** csa **********************          *** csb *************
        *                            *          *                   *
        *  csa_init-csa_hist         *          *  csb_init         *
        *              |             *  --J-->  *     |             *
        *              A  --I-->  B  *  <--K--  *     C  --L-->  D  *
        *                            *          *                   *
        ******************************          *********************
        """

        # Top level states
        statechart = Statechart(name='statechart')
        csa = CompositeState(name='csa', context=statechart)
        csb = CompositeState(name='csb', context=statechart)

        # Child states
        # statechart
        statechart_init = InitialState(statechart)
        # csa
        csa_init = InitialState(csa)
        csa_hist = ShallowHistoryState(context=csa)
        A = State(name='A', context=csa)
        B = State(name='B', context=csa)
        # csb
        csb_init = InitialState(csb)
        C = State(name='C', context=csb)
        D = State(name='D', context=csb)

        # Events
        I = Event(name='I')
        J = Event(name='J')
        K = Event(name='K')
        L = Event(name='L')

        # Transitions between states & event triggers
        Transition(start=statechart_init, end=csa)
        Transition(start=csa_init, end=csa_hist)
        Transition(start=csa_hist, end=A)
        Transition(start=A, end=B, event=I)
        Transition(start=csa, end=csb, event=J)
        Transition(start=csb, end=csa, event=K)
        Transition(start=csb_init, end=C)
        Transition(start=C, end=D, event=L)

        # Execute statechart
        statechart.start()
        statechart.dispatch(I)

        # Assert we have reached state B, history should restore this state
        assert statechart.is_active('B')

        statechart.dispatch(J)

        # Assert we have reached state C
        assert statechart.is_active('C')

        statechart.dispatch(K)

        # Assert the history state has restored state B
        assert statechart.is_active('B')
コード例 #19
0
    def test_activate_multiple_shallow_history_states(self):
        """
        statechart:

        statechart_init
               |
        *** csa *****************************************************          *** csc *************
        *                                                           *          *                   *
        *  csa_init--csa_hist                                       *          *  csc_init         *
        *               |                                           *  --K-->  *     |             *
        *               A  --I-->  *** csb ***********************  *  <--L--  *     D  --M-->  E  *
        *                          *                             *  *          *                   *
        *                          *  csb_init--csb_hist         *  *          *********************
        *                          *               |             *  *
        *                          *               B  --J-->  C  *  *
        *                          *                             *  *
        *                          *******************************  *
        *                                                           *
        *************************************************************
        """
        # Top level states
        statechart = Statechart(name='statechart')
        csa = CompositeState(name='csa', context=statechart)
        csb = CompositeState(name='csb', context=csa)
        csc = CompositeState(name='csc', context=statechart)

        # Child states
        # statechart
        statechart_init = InitialState(statechart)

        # csa
        csa_init = InitialState(csa)
        csa_hist = ShallowHistoryState(context=csa)
        A = State(name='A', context=csa)
        # csb
        csb_init = InitialState(csb)
        csb_hist = ShallowHistoryState(context=csb)
        B = State(name='B', context=csb)
        C = State(name='C', context=csb)
        # csc
        csc_init = InitialState(csc)
        D = State(name='D', context=csc)
        E = State(name='E', context=csc)

        # Events
        I = Event(name='I')
        J = Event(name='J')
        K = Event(name='K')
        L = Event(name='L')
        M = Event(name='M')

        # Transitions between states & event triggers
        Transition(start=statechart_init, end=csa)
        Transition(start=csa_init, end=csa_hist)
        Transition(start=csa_hist, end=A)
        Transition(start=A, end=csb, event=I)
        Transition(start=csb_init, end=csb_hist)
        Transition(start=csb_hist, end=B)
        Transition(start=B, end=C, event=J)
        Transition(start=csa, end=csc, event=K)
        Transition(start=csc, end=csa, event=L)
        Transition(start=csc_init, end=D)
        Transition(start=D, end=E, event=M)

        # Execute statechart
        statechart.start()
        statechart.dispatch(I)

        assert statechart.is_active('B')

        statechart.dispatch(J)

        # Assert we have reached state C, csb's history state should restore
        # this state
        assert statechart.is_active('C')

        statechart.dispatch(K)

        # Assert we have reached state D
        assert statechart.is_active('D')

        statechart.dispatch(L)

        # Assert the history state has restored state C
        assert statechart.is_active('C')
コード例 #20
0
 def test_create_state(self):
     statechart = Statechart(name='statechart')
     State(name='anon', context=statechart)
コード例 #21
0
    def test_keyboard_example(self):
        """
        Test classic concurrent state keyboard example with concurrent states
        for caps, num and scroll lock.

        init - -
               |
               v
        -- keyboard --------------------------------------
        |                                                |
        |  init ---> --caps lock off --                  |
        |        --- |                | <--              |
        |        |   -----------------|   |              |
        |  caps lock pressed       caps lock pressed     |
        |        |   -- caps lock on --   |              |
        |        --> |                | ---              |
        |            ------------------                  |
        |                                                |
        --------------------------------------------------
        |                                                |
        |  init ---> --num lock off ---                  |
        |        --- |                | <--              |
        |        |   -----------------|   |              |
        |  num lock pressed      num lock pressed        |
        |        |   -- num lock on ---   |              |
        |        --> |                | ---              |
        |            ------------------                  |
        |                                                |
        --------------------------------------------------
        |                                                |
        |  init ---> -- scroll lock off --               |
        |        --- |                    | <--          |
        |        |   ---------------------|   |          |
        |  scroll lock pressed      scroll lock pressed  |
        |        |   -- scroll lock on ---|   |          |
        |        --> |                    | ---          |
        |            ----------------------              |
        |                                                |
        --------------------------------------------------
        """
        statechart = Statechart(name='statechart')

        start_state = InitialState(statechart)
        keyboard = ConcurrentState(name='keyboard', context=statechart)
        Transition(start=start_state, end=keyboard)

        caps_lock = CompositeState(name='caps_lock', context=keyboard)
        caps_lock_initial = InitialState(caps_lock)
        caps_lock_on = State(name='caps_lock_on', context=caps_lock)
        caps_lock_off = State(name='caps_lock_off', context=caps_lock)
        caps_lock_pressed = Event(name='caps_lock_pressed')
        Transition(start=caps_lock_initial, end=caps_lock_off)
        Transition(start=caps_lock_on,
                   end=caps_lock_off,
                   event=caps_lock_pressed)
        Transition(start=caps_lock_off,
                   end=caps_lock_on,
                   event=caps_lock_pressed)

        num_lock = CompositeState(name='num_lock', context=keyboard)
        num_lock_initial = InitialState(num_lock)
        num_lock_on = State(name='num_lock_on', context=num_lock)
        num_lock_off = State(name='num_lock_off', context=num_lock)
        num_lock_pressed = Event(name='num_lock_pressed')
        Transition(start=num_lock_initial, end=num_lock_off)
        Transition(start=num_lock_on, end=num_lock_off, event=num_lock_pressed)
        Transition(start=num_lock_off, end=num_lock_on, event=num_lock_pressed)

        scroll_lock = CompositeState(name='scroll_lock', context=keyboard)
        scroll_lock_initial = InitialState(scroll_lock)
        scroll_lock_on = State(name='scroll_lock_on', context=scroll_lock)
        scroll_lock_off = State(name='scroll_lock_off', context=scroll_lock)
        scroll_lock_pressed = Event(name='scroll_lock_pressed')
        Transition(start=scroll_lock_initial, end=scroll_lock_off)
        Transition(start=scroll_lock_on,
                   end=scroll_lock_off,
                   event=scroll_lock_pressed)
        Transition(start=scroll_lock_off,
                   end=scroll_lock_on,
                   event=scroll_lock_pressed)

        statechart.start()

        assert statechart.is_active('keyboard')
        assert statechart.is_active('caps_lock_off')
        assert statechart.is_active('num_lock_off')
        assert statechart.is_active('scroll_lock_off')

        statechart.dispatch(event=caps_lock_pressed)
        assert statechart.is_active('caps_lock_on')

        statechart.dispatch(event=num_lock_pressed)
        assert statechart.is_active('num_lock_on')

        statechart.dispatch(event=scroll_lock_pressed)
        assert statechart.is_active('scroll_lock_on')

        statechart.dispatch(event=caps_lock_pressed)
        assert statechart.is_active('caps_lock_off')

        statechart.dispatch(event=num_lock_pressed)
        assert statechart.is_active('num_lock_off')

        statechart.dispatch(event=scroll_lock_pressed)
        assert statechart.is_active('scroll_lock_off')
コード例 #22
0
 def __init__(self, name, context, data):
     State.__init__(self, name=name, context=context)
     self.data = data
コード例 #23
0
ファイル: test_states.py プロジェクト: leighmck/statechart
 def __init__(self, name, context):
     State.__init__(self, name=name, context=context)
     self.dispatch_called = False
     self.metadata = None
     self.event = None
コード例 #24
0
 def __init__(self, name, context):
     State.__init__(self, name=name, context=context)
     self.dispatch_called = False
     self.metadata = None
     self.event = None
コード例 #25
0
 def test_create_state_without_parent(self):
     with pytest.raises(RuntimeError):
         State(name='anon', context=None)
コード例 #26
0
    def test_deep_local_transitions(self, empty_statechart):
        sc = empty_statechart
        init = InitialState(sc)

        top = CompositeState(name='top', context=sc)
        top_init = InitialState(top)
        middle_a = CompositeState(name='middle_a', context=top)
        middle_b = CompositeState(name='middle_b', context=top)

        middle_a_init = InitialState(middle_a)
        bottom_a1 = State(name='bottom_a1', context=middle_a)
        bottom_a2 = State(name='bottom_a2', context=middle_a)

        middle_b_init = InitialState(middle_b)
        bottom_b1 = State(name='bottom_b1', context=middle_b)
        bottom_b2 = State(name='bottom_b2', context=middle_b)

        # Setup default transitions
        Transition(start=init, end=top)
        Transition(start=top_init, end=middle_a)
        Transition(start=middle_a_init, end=bottom_a1)
        Transition(start=middle_b_init, end=bottom_b1)

        # Setup events to trigger transitions
        a_to_b = Event('a_to_b')
        a1_to_a2 = Event('a1_to_a2')
        b1_to_b2 = Event('b1_to_b2')
        top_to_middle_a = Event('top_to_middle_a')
        top_to_middle_b = Event('top_to_middle_b')
        middle_a_to_a1 = Event('middle_a_to_a1')
        middle_a_to_a2 = Event('middle_a_to_a2')
        middle_b_to_b1 = Event('middle_b_to_b1')
        middle_b_to_b2 = Event('middle_b_to_b2')

        # Setup external transitions
        Transition(start=middle_a, end=middle_b, event=a_to_b)
        Transition(start=bottom_a1, end=bottom_a2, event=a1_to_a2)
        Transition(start=bottom_a1, end=bottom_a2, event=b1_to_b2)

        # Setup local transitions
        Transition(start=top, end=middle_a, event=top_to_middle_a)
        Transition(start=top, end=middle_b, event=top_to_middle_b)

        Transition(start=middle_a, end=bottom_a1, event=middle_a_to_a1)
        Transition(start=middle_a, end=bottom_a2, event=middle_a_to_a2)

        Transition(start=middle_b, end=bottom_b1, event=middle_b_to_b1)
        Transition(start=middle_b, end=bottom_b2, event=middle_b_to_b2)

        sc.start()

        assert sc.is_active('top')
        assert sc.is_active('middle_a')
        assert sc.is_active('bottom_a1')

        sc.dispatch(middle_a_to_a2)

        assert sc.is_active('top')
        assert sc.is_active('middle_a')
        assert sc.is_active('bottom_a2')

        sc.dispatch(top_to_middle_b)

        assert sc.is_active('top')
        assert sc.is_active('middle_b')
        assert sc.is_active('bottom_b1')

        sc.dispatch(top_to_middle_a)

        assert sc.is_active('top')
        assert sc.is_active('middle_a')
        assert sc.is_active('bottom_a1')

        sc.dispatch(a_to_b)

        assert sc.is_active('top')
        assert sc.is_active('middle_b')
        assert sc.is_active('bottom_b1')

        sc.dispatch(middle_b_to_b2)

        assert sc.is_active('top')
        assert sc.is_active('middle_b')
        assert sc.is_active('bottom_b2')