def test_on_enter_on_exit(self): def on_exit(state, event): exit_transitions.append((state, event)) def on_enter(state, event): enter_transitions.append((state, event)) enter_transitions = [] exit_transitions = [] m = fsm.FSM('start') m.add_state('start', on_exit=on_exit) m.add_state('down', on_enter=on_enter, on_exit=on_exit) m.add_state('up', on_enter=on_enter, on_exit=on_exit) m.add_transition('start', 'down', 'beat') m.add_transition('down', 'up', 'jump') m.add_transition('up', 'down', 'fall') m.initialize() m.process_event('beat') m.process_event('jump') m.process_event('fall') self.assertEqual([('down', 'beat'), ('up', 'jump'), ('down', 'fall')], enter_transitions) self.assertEqual([('down', 'jump'), ('up', 'fall')], exit_transitions)
def setUp(self): super(FSMTest, self).setUp() self.jumper = fsm.FSM("down") self.jumper.add_state('up') self.jumper.add_state('down') self.jumper.add_transition('down', 'up', 'jump') self.jumper.add_transition('up', 'down', 'fall')
def test_target_state_stable(self): # Test to verify that adding a new state with a 'target' state pointing # to a 'stable' state does not raise an exception m = fsm.FSM('working') m.add_state('working', stable=True) m.add_state('foo', target='working') m.initialize()
def test_bad_transition(self): m = fsm.FSM('unknown') m.add_state('unknown') m.add_state('fire') self.assertRaises(excp.NotFound, m.add_transition, 'unknown', 'something', 'boom') self.assertRaises(excp.NotFound, m.add_transition, 'something', 'unknown', 'boom')
def test_copy_clears_current(self): c = fsm.FSM() c.add_state('up') c.initialize('up') d = c.copy() self.assertEqual('up', c.current_state) self.assertEqual(None, d.current_state)
def setUp(self): super(FSMTest, self).setUp() m = fsm.FSM() m.add_state('working', stable=True) m.add_state('daydream') m.add_state('wakeup', target='working') m.add_state('play', stable=True) m.add_transition('wakeup', 'working', 'walk') self.fsm = m
def test_copy_states(self): c = fsm.FSM() self.assertEqual(0, len(c.states)) c.add_state('up') self.assertEqual(1, len(c.states)) deep = c.copy() shallow = c.copy(shallow=True) c.add_state('down') c.add_transition('up', 'down', 'fall') self.assertEqual(2, len(c.states)) # deep copy created new members, so change is not visible self.assertEqual(1, len(deep.states)) self.assertNotEqual(c._transitions, deep._transitions) # but a shallow copy references the same state object self.assertEqual(2, len(shallow.states)) self.assertEqual(c._transitions, shallow._transitions)
"""Used to log when a state is exited.""" LOG.debug("Exiting old state '%s' in response to event '%s'", old_state, event) def on_enter(new_state, event): """Used to log when entering a state.""" LOG.debug("Entering new state '%s' in response to event '%s'", new_state, event) watchers = {} watchers['on_exit'] = on_exit watchers['on_enter'] = on_enter machine = fsm.FSM() # Add stable states machine.add_state(ENROLL, stable=True, **watchers) machine.add_state(MANAGEABLE, stable=True, **watchers) machine.add_state(AVAILABLE, stable=True, **watchers) machine.add_state(ACTIVE, stable=True, **watchers) machine.add_state(ERROR, stable=True, **watchers) # Add verifying state machine.add_state(VERIFYING, target=MANAGEABLE, **watchers) # Add deploy* states # NOTE(deva): Juno shows a target_provision_state of DEPLOYDONE # this is changed in Kilo to ACTIVE machine.add_state(DEPLOYING, target=ACTIVE, **watchers)
def test_duplicate_state(self): m = fsm.FSM('unknown') m.add_state('unknown') self.assertRaises(excp.Duplicate, m.add_state, 'unknown')
def test_contains(self): m = fsm.FSM('unknown') self.assertNotIn('unknown', m) m.add_state('unknown') self.assertIn('unknown', m)
def test_invalid_callbacks(self): m = fsm.FSM('working') m.add_state('working') m.add_state('broken') self.assertRaises(ValueError, m.add_state, 'b', on_enter=2) self.assertRaises(ValueError, m.add_state, 'b', on_exit=2)