Source code for examples.testablestatemachines.testablestatemachine

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
TODO: modul doc string


This is an example state machine following this article:

http://accu.org/index.php/journals/1548

"""

__version__ = "1.0.3.0"
__author__ = "dr0iddr0id {at} gmail [dot] com (C) 2010"

from operator import methodcaller

import symplehfsm
from symplehfsm import Structure
from symplehfsm import SympleDictHFSM
from symplehfsm import BaseHFSMTests

# ------------------------------------------------------------------------------


# ------------------------------------------------------------------------------
[docs]class Events(object): dark = 0 light = 1 movement = 2 no_movement = 3 timeout = 4 # ------------------------------------------------------------------------------
[docs]class Actions(object):
[docs] def lamp_off(self): print("lamp off")
[docs] def lamp_on(self): print("lamp on")
[docs] def start_timer(self): print("starting timer") # ------------------------------------------------------------------------------
[docs]def main(): structure = Structure() # state, parent, initial, entry, exit structure.add_state("parent", None, False) structure.add_state( "day", "parent", True) structure.add_state( "night", "parent", False) structure.add_state( "off", "night", True) structure.add_state( "moving", "night", False) structure.add_state( "timing", "night", False) # handling state, event, next state, action, guard structure.add_trans( "day", "dark", "night") structure.add_trans( "night", "light", "day", methodcaller("lamp_off")) structure.add_trans( "off", "movement", "moving", methodcaller("lamp_on")) structure.add_trans("moving", "no_movement", "timing", methodcaller("start_timer")) structure.add_trans("timing", "timeout", "off", methodcaller("lamp_off")) structure.add_trans("timing", "movement", "moving") actions = Actions() sm = SympleDictHFSM(structure, actions) sm.init(False) # run a event sequence sm.handle_event("dark") sm.handle_event("movement") sm.handle_event("no_movement") sm.handle_event("movement") sm.handle_event("no_movement") sm.handle_event("timeout") sm.handle_event("light") sm.handle_event("dark")
if __name__ == "__main__": main() # ------------------------------------------------------------------------------ # class MyStateMachine(SympleDictHFSM, Events): # # instantiate the states and tarnsitions only once for all instances of MyStateMahine # state_day = "day" # state_night = "night" # state_off = "off" # state_moving = "moving" # state_timing = "timing" # def __init__(self, actions): # SympleDictHFSM.__init__(self) # self.actions = actions # self.init(self.state_day, self) # def dark(self): # f = operator.methodcaller('dark', self) # self.handle_event(f, self) # def light(self): # f = operator.methodcaller('light', self) # self.handle_event(f, self) # def movement(self): # f = operator.methodcaller('movement', self) # self.handle_event(f, self) # def no_movement(self): # f = operator.methodcaller('no_movement', self) # self.handle_event(f, self) # def timeout(self): # f = operator.methodcaller('timeout', self) # self.handle_event(f, self) # # ------------------------------------------------------------------------------ # class MyStateMachineTests(BaseHFSMTests): # class AEnum(object): # LAMPON = "lamp_on" # LAMPOFF ="lamp_off" # STARTTIMER = "start_timer" # # make it read only # AEnum.__setattr__ = None # # -- transition tests -- # # def setUp(self): # self.actions = MyStateMachineTests.RecordingActions() # self.state_machine = MyStateMachine(self.actions) # def test_trans_day_dark(self): # # init: s0 -> s11: s0.entry, s1.entry, s11.entry # # title, starting_state, event_func, expected_state, expected_actions): # # { "Day + dark -> off", START_DAY, StateMachine::Dark, "Off", 0 }, # v = self.TestVector("day + dark", MyStateMachine.state_day, self.state_machine.dark, MyStateMachine.state_off, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_day_light(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Day + light -> no change", START_DAY, StateMachine::Light, "Day", 0 }, # v = self.TestVector("day + light", MyStateMachine.state_day, self.state_machine.light, MyStateMachine.state_day, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_day_movement(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Day + movement -> no change", START_DAY, StateMachine::Movement, "Day", 0 }, # v = self.TestVector("day + movement", MyStateMachine.state_day, self.state_machine.movement, MyStateMachine.state_day, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_day_no_movement(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Day + no_movement -> no change", START_DAY, StateMachine::NoMovement, "Day", 0 }, # v = self.TestVector("day + nomovement", MyStateMachine.state_day, self.state_machine.no_movement, MyStateMachine.state_day, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_day_timeout(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Day + timeout -> no change", START_DAY, StateMachine::Timeout, "Day", 0 }, # v = self.TestVector("day + timeout", MyStateMachine.state_day, self.state_machine.timeout, MyStateMachine.state_day, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_off_dark(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Off + dark -> no change", START_OFF, StateMachine::Dark, "Off", 0 }, # v = self.TestVector("off + dark", MyStateMachine.state_off, self.state_machine.dark, MyStateMachine.state_off, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_off_light(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Off + light -> lamp off; day", START_OFF, StateMachine::Light, "Day", &L_Off }, # v = self.TestVector("off + light -> lamp off; day", MyStateMachine.state_off, self.state_machine.light, MyStateMachine.state_day, [self.AEnum.LAMPOFF]) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_off_movement(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Off + movement -> lamp on; moving", START_OFF, StateMachine::Movement, "Moving", &L_On }, # v = self.TestVector("off + movement -> lamp on; moving", MyStateMachine.state_off, self.state_machine.movement, MyStateMachine.state_moving, [self.AEnum.LAMPON]) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_off_no_movement(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Off + no_movement -> no change", START_OFF, StateMachine::NoMovement, "Off", 0 }, # v = self.TestVector("off + nomovement", MyStateMachine.state_off, self.state_machine.no_movement, MyStateMachine.state_off, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_off_timeout(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Off + timeout -> no change", START_OFF, StateMachine::Timeout, "Off", 0 }, # v = self.TestVector("off + timeout", MyStateMachine.state_off, self.state_machine.timeout, MyStateMachine.state_off, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_moving_dark(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Moving + dark -> no change", START_MOVING, StateMachine::Dark, "Moving", 0 }, # v = self.TestVector("moving + dark", MyStateMachine.state_moving, self.state_machine.dark, MyStateMachine.state_moving, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_moving_light(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Moving + light -> lamp off; day", START_MOVING, StateMachine::Light, "Day", &L_Off }, # v = self.TestVector("moving + light -> lamp off, day", MyStateMachine.state_moving, self.state_machine.light, MyStateMachine.state_day, [self.AEnum.LAMPOFF]) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_moving_movement(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Moving + movement -> no change", START_MOVING, StateMachine::Movement, "Moving", 0 }, # v = self.TestVector("moving + movement", MyStateMachine.state_moving, self.state_machine.movement, MyStateMachine.state_moving, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_moving_no_movement(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Moving + no_movement -> timing", START_MOVING, StateMachine::NoMovement, "Timing", &Start_T }, # v = self.TestVector("moving + no_movement -> timing", MyStateMachine.state_moving, self.state_machine.no_movement, MyStateMachine.state_timing, [self.AEnum.STARTTIMER]) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_moving_timout(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Moving + timeout -> no change", START_MOVING, StateMachine::Timeout, "Moving", 0 }, # v = self.TestVector("moving + timeout", MyStateMachine.state_moving, self.state_machine.timeout, MyStateMachine.state_moving, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_timing_dark(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Timing + dark -> no change", START_TIMING, StateMachine::Dark, "Timing", 0 }, # v = self.TestVector("timing + dark", MyStateMachine.state_timing, self.state_machine.dark, MyStateMachine.state_timing, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_timing_light(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Timing + light -> lamp off; day", START_TIMING, StateMachine::Light, "Day", &L_Off }, # v = self.TestVector("timing + light", MyStateMachine.state_timing, self.state_machine.light, MyStateMachine.state_day, [self.AEnum.LAMPOFF]) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_timing_movement(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Timing + movement -> no change", START_TIMING, StateMachine::Movement, "Timing", 0 }, # v = self.TestVector("timing + movement", MyStateMachine.state_timing, self.state_machine.movement, MyStateMachine.state_moving, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_timing_no_movement(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Timing + no_movement -> no change", START_TIMING, StateMachine::NoMovement, "Timing", 0 }, # v = self.TestVector("timing + no movement ", MyStateMachine.state_timing, self.state_machine.no_movement, MyStateMachine.state_timing, []) # self.prove_one_transition(self.state_machine, self.actions, v) # def test_trans_timing_timout(self): # # title, starting_state, event_func, expected_state, expected_actions): # # { "Timing + timeout -> lamp off; off", START_TIMING, StateMachine::Timeout, "Off", &L_Off }, # v = self.TestVector("timing + timeout -> lamp off: off", MyStateMachine.state_timing, self.state_machine.timeout, MyStateMachine.state_off, [self.AEnum.LAMPOFF]) # self.prove_one_transition(self.state_machine, self.actions, v) # # ------------------------------------------------------------------------------ # def test_sequence(self): # self.prove_transition_sequence("rout1", # MyStateMachine.state_day, # [self.state_machine.dark, \ # self.state_machine.movement, \ # self.state_machine.no_movement, \ # self.state_machine.movement, \ # self.state_machine.no_movement, \ # self.state_machine.timeout], # MyStateMachine.state_off, # [self.AEnum.LAMPON, self.AEnum.STARTTIMER, self.AEnum.STARTTIMER, self.AEnum.LAMPOFF], # self.state_machine, # self.actions) # # ------------------------------------------------------------------------------