def test_waiting_for_single_state(self):
        c = HasStateMachine("C")
        self.sm.transition(VState.State1, VEvent.Event1, None, VState.State2)
        c.add_stateMachine(self.sm)
        c.loop_run()
        start = time.time()

        def post_msg1():
            cothread.Sleep(0.1)
            self.sm.post(VEvent.Event1)
        cothread.Spawn(post_msg1)
        c.wait_until(VState.State2, timeout=0.2)
        end = time.time()
        self.assertAlmostEqual(start + 0.1, end, delta=0.01)
        self.assertEqual(self.sm.state, VState.State2)
 def test_raising_error_notifies_status(self):
     mock_exception = MagicMock()
     self.sm.log_exception = mock_exception
     c = HasStateMachine("C")
     trans = MagicMock(side_effect=ValueError("My Error Message"))
     self.sm.transition(VState.State1, VEvent.Event1, trans, VState.State2)
     c.add_stateMachine(self.sm)
     c.add_listener(self.callback)
     c.loop_run()
     self.sm.post(VEvent.Event1)
     cothread.Yield()
     self.assertEquals(self.sm.state, VState.Err)
     self.assertEquals(self.states, [VState.Err])
     self.assertEquals(self.messages, ["My Error Message"])
     mock_exception.assert_called_once_with(
         'Handler raised error: My Error Message')
     mock_exception.reset_mock()
    def test_want_changes_works(self):
        c = HasStateMachine("C")
        self.i = 0

        def trans():
            self.i += 1
            if self.i == 1:
                # Change message
                return VState.State1, "Message"
            elif self.i == 2:
                # No change
                return VState.State1, "Message"
            elif self.i == 3:
                # State change
                return VState.State2, "Message"
            elif self.i == 4:
                # Both change
                return VState.State1, "New Message"

        self.sm.transition(VState, VEvent.Event1, trans, VState)
        c.add_stateMachine(self.sm)
        c.add_listener(self.callback)
        c.loop_run()
        t = self.sm.timeStamp

        def check_output(states, messages, t):
            self.reset_cb_lists()
            self.sm.post(VEvent.Event1)
            cothread.Yield()
            self.assertEquals(self.states, states)
            self.assertEquals(self.messages, messages)
            self.assertEqual(len(self.timeStamps), 1)
            self.assertNotEqual(self.timeStamps[0], t)
            return self.timeStamps[0]

        # Change message
        t = check_output([], ["Message"], t)
        # No change
        t = check_output([], [], t)
        # Change state
        t = check_output([VState.State2], [], t)
        # Change both
        t = check_output([VState.State1], ["New Message"], t)