示例#1
0
class StopwatchTests(unittest.TestCase):
    def setUp(self):
        with open("stopwatch.yaml") as f:
            sc = import_from_yaml(f)

        self.stopwatch = Interpreter(sc, initial_context=context)
        self.stopwatch.execute_once()

    def test_increase_elapsed_time(self):
        self.stopwatch.queue("start")
        self.stopwatch.execute()
        self.stopwatch.clock.time += 1
        self.stopwatch.execute()
        self.assertEqual(self.stopwatch.context["elapsed_time"], 1)

    def test_reset(self):
        self.stopwatch.queue("start")
        self.stopwatch.execute()
        self.stopwatch.clock.time += 1
        self.stopwatch.execute()
        self.assertEqual(self.stopwatch.context["elapsed_time"], 1)
        self.stopwatch.clock.time += 1
        self.stopwatch.execute()
        self.assertEqual(self.stopwatch.context["elapsed_time"], 2)

        self.stopwatch.queue("stop", "reset")
        self.stopwatch.execute_once()
        self.assertIn("stopped", self.stopwatch.configuration)
        self.assertIn("actual time", self.stopwatch.configuration)
        self.stopwatch.execute_once()
        self.assertIn("stopped", self.stopwatch.configuration)
        self.assertIn("actual time", self.stopwatch.configuration)
        self.assertEqual(self.stopwatch.context["elapsed_time"], 0)
class MicrowaveTests(unittest.TestCase):
    def setUp(self):
        with open('microwave.yaml') as f:
            sc = import_from_yaml(f)

        self.oven = Interpreter(sc)
        self.oven.execute_once()

    def test_no_heating_when_door_is_not_closed(self):
        self.oven.queue('door_opened', 'item_placed', 'timer_inc')
        self.oven.execute()

        self.oven.queue('cooking_start')

        for step in iter(self.oven.execute_once, None):
            for event in step.sent_events:
                self.assertNotEqual(event.name, 'heating_on')

        self.assertNotIn('cooking_mode', self.oven.configuration)

    def test_increase_timer(self):
        self.oven.queue('door_opened', 'item_placed', 'door_closed')

        events = 10 * ['timer_inc']
        self.oven.queue(*events)
        self.oven.execute()

        self.assertEqual(self.oven.context['timer'], 10)
示例#3
0
class RemoteElevatorTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator.yaml') as f:
            elevator = io.import_from_yaml(f)
        with open('docs/examples/elevator_buttons.yaml') as f:
            buttons = io.import_from_yaml(f)

        self.elevator = Interpreter(elevator)
        self.buttons = Interpreter(buttons)
        self.buttons.bind(self.elevator)

    def test_button(self):
        self.assertEqual(self.elevator.context['current'], 0)

        self.buttons.queue(Event('button_2_pushed'))
        self.buttons.execute()

        event = self.elevator._events.pop()
        self.assertEqual(event.name, 'floorSelected')
        self.assertEqual(event.data['floor'], 2)

        self.buttons.queue(Event('button_2_pushed'))
        self.buttons.execute()
        self.elevator.execute()

        self.assertEqual(self.elevator.context['current'], 2)

    def test_button_0_on_groundfloor(self):
        self.assertEqual(self.elevator.context['current'], 0)

        self.buttons.queue(Event('button_0_pushed'))
        self.buttons.execute()
        self.elevator.execute()

        self.assertEqual(self.elevator.context['current'], 0)
示例#4
0
class SimulatorSimpleTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/simple.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc, DummyEvaluator)
        # Stabilization
        self.interpreter.execute_once()

    def test_init(self):
        self.assertEqual(self.interpreter.configuration, ['root', 's1'])
        self.assertFalse(self.interpreter.final)

    def test_simple_configuration(self):
        self.interpreter.execute_once()  # Should do nothing!
        self.assertEqual(self.interpreter.configuration, ['root', 's1'])
        self.interpreter.queue(Event('goto s2'))
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's2'])
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's3'])

    def test_simple_entered(self):
        self.interpreter.queue(Event('goto s2'))
        self.assertEqual(self.interpreter.execute_once().entered_states, ['s2'])
        self.interpreter.queue(Event('goto final'))
        self.assertEqual(self.interpreter.execute_once().entered_states, ['s3'])
        self.assertEqual(self.interpreter.execute_once().entered_states, ['final'])
        self.assertEqual(self.interpreter.configuration, [])
        self.assertTrue(self.interpreter.final)

    def test_simple_final(self):
        self.interpreter.queue(Event('goto s2')).queue(Event('goto final'))
        self.interpreter.execute()
        self.assertTrue(self.interpreter.final)
示例#5
0
class InfiniteExecutionTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/infinite.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc)
        # Stabilization
        self.interpreter.execute_once()

    def test_three_steps(self):
        self.assertEqual(self.interpreter.configuration, ['root', 's1'])
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's2'])
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's1'])
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's2'])
        self.assertEqual(self.interpreter.context['x'],
                         2)  # x is incremented in s1.on_entry

    def test_auto_three_steps(self):
        self.interpreter.execute(max_steps=3)

        self.assertEqual(self.interpreter.configuration, ['root', 's2'])
        self.assertEqual(self.interpreter.context['x'],
                         2)  # x is incremented in s1.on_entry

    def test_auto_stop(self):
        self.interpreter.execute()

        self.assertTrue(self.interpreter.final)
        self.assertEqual(self.interpreter.context['x'], 100)
示例#6
0
class InternalTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/internal.yaml') as f:
            self.sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(self.sc)
        # Stabilization
        self.interpreter.execute_once()

    def testInternalSent(self):
        step = self.interpreter.execute_once()
        self.assertEqual(step.event.name, 'next')

    def testInternalBeforeExternal(self):
        self.interpreter.queue(Event('not_next'))
        step = self.interpreter.execute_once()
        self.assertEqual(step.event.name, 'next')

        step = self.interpreter.execute_once()
        self.assertEqual(step.event, None)
        self.assertEqual(step.entered_states, ['s2'])

        step = self.interpreter.execute_once()
        self.assertEqual(step.event.name, 'not_next')

    def testActiveGuard(self):
        self.interpreter.execute()
        self.assertTrue(self.interpreter.final)
示例#7
0
    def generic_test(self, condition: Condition, success_expected: bool, failure_expected: bool, delay: int = 0):
        statechart = Statechart('test')
        parallel_state = OrthogonalState('parallel_state')
        statechart.add_state(parallel_state, parent=None)

        initial_state = CompoundState('initial_state', initial='Cond')
        statechart.add_state(initial_state, "parallel_state")

        statechart.add_state(BasicState('success'), 'initial_state')
        statechart.add_state(BasicState('failure'), 'initial_state')

        condition.add_to(statechart=statechart,
                         id='Cond',
                         parent_id='initial_state',
                         status_id=parallel_state,
                         success_id='success',
                         failure_id='failure')

        interpreter = Interpreter(statechart)

        self.assertFalse('success' in interpreter.configuration)
        self.assertFalse('failure' in interpreter.configuration)

        interpreter.execute()

        interpreter.time += delay
        interpreter.queue(Event(Condition.STEP_ENDED_EVENT))
        interpreter.queue(Event(Condition.STEP_ENDED_EVENT))
        interpreter.execute()

        self.assertEqual(success_expected, 'success' in interpreter.configuration)
        self.assertEqual(failure_expected, 'failure' in interpreter.configuration)
示例#8
0
class MicrowaveTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/microwave/microwave.yaml') as f:
            sc = io.import_from_yaml(f)
        self.microwave = Interpreter(sc)

    def test_lamp_on(self):
        self.microwave.execute_once()
        self.microwave.queue(Event('door_opened'))
        step = self.microwave.execute_once()
        self.microwave.execute_once()
        self.assertEqual(step.sent_events[0].name, 'lamp_switch_on')

    def test_heating_on(self):
        self.microwave.execute_once()
        self.microwave.queue(Event('door_opened'))
        self.microwave.queue(Event('item_placed'))
        self.microwave.queue(Event('door_closed'))
        self.microwave.queue(Event('input_timer_inc'))
        self.microwave.execute()
        self.microwave.queue(Event('input_cooking_start'))
        step = self.microwave.execute_once()
        self.assertIn(Event('heating_on'), step.sent_events)
        self.assertIn(Event('lamp_switch_on'), step.sent_events)
        self.assertIn(Event('turntable_start'), step.sent_events)
示例#9
0
class InternalTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/internal.yaml') as f:
            self.sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(self.sc)
        # Stabilization
        self.interpreter.execute_once()

    def testInternalSent(self):
        step = self.interpreter.execute_once()
        self.assertEqual(step.event.name, 'next')

    def testInternalBeforeExternal(self):
        self.interpreter.queue(Event('not_next'))
        step = self.interpreter.execute_once()
        self.assertEqual(step.event.name, 'next')

        step = self.interpreter.execute_once()
        self.assertEqual(step.event, None)
        self.assertEqual(step.entered_states, ['s2'])

        step = self.interpreter.execute_once()
        self.assertEqual(step.event.name, 'not_next')

    def testActiveGuard(self):
        self.interpreter.execute()
        self.assertTrue(self.interpreter.final)
示例#10
0
class SimulatorHistoryTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/history.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc, evaluator_klass=DummyEvaluator)
        # Stabilization
        self.interpreter.execute_once()

    def test_memory(self):
        self.interpreter.queue(Event('next')).execute_once()
        self.assertEqual(sorted(self.interpreter.configuration), ['loop', 'root', 's2'])

        step = self.interpreter.queue(Event('pause')).execute_once()
        self.assertEqual(step.exited_states, ['s2', 'loop'])
        self.assertEqual(sorted(self.interpreter.configuration), ['pause', 'root'])

    def test_resume_memory(self):
        self.interpreter.queue(Event('next')).queue(Event('pause')).queue(Event('continue'))
        steps = self.interpreter.execute()
        step = steps[-1]

        self.assertEqual(step.entered_states, ['loop', 'loop.H', 's2'])
        self.assertEqual(step.exited_states, ['pause', 'loop.H'])
        self.assertEqual(sorted(self.interpreter.configuration), ['loop', 'root', 's2'])

    def test_after_memory(self):
        self.interpreter.queue(Event('next')).queue(Event('pause')).queue(Event('continue'))
        self.interpreter.queue(Event('next')).queue(Event('next'))
        self.interpreter.execute()
        self.assertEqual(sorted(self.interpreter.configuration), ['loop', 'root', 's1'])

        self.interpreter.queue(Event('pause')).queue(Event('stop'))
        self.interpreter.execute()
        self.assertTrue(self.interpreter.final)
示例#11
0
class MicrowaveTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/microwave/microwave.yaml') as f:
            sc = io.import_from_yaml(f)
        self.microwave = Interpreter(sc)

    def test_lamp_on(self):
        self.microwave.execute_once()
        self.microwave.queue(Event('door_opened'))
        step = self.microwave.execute_once()
        self.microwave.execute_once()
        self.assertEqual(step.sent_events[0].name, 'lamp_switch_on')

    def test_heating_on(self):
        self.microwave.execute_once()
        self.microwave.queue(Event('door_opened'))
        self.microwave.queue(Event('item_placed'))
        self.microwave.queue(Event('door_closed'))
        self.microwave.queue(Event('input_timer_inc'))
        self.microwave.execute()
        self.microwave.queue(Event('input_cooking_start'))
        step = self.microwave.execute_once()
        self.assertIn(Event('heating_on'), step.sent_events)
        self.assertIn(Event('lamp_switch_on'), step.sent_events)
        self.assertIn(Event('turntable_start'), step.sent_events)
示例#12
0
class InfiniteExecutionTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/infinite.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc)
        # Stabilization
        self.interpreter.execute_once()

    def test_three_steps(self):
        self.assertEqual(self.interpreter.configuration, ['root', 's1'])
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's2'])
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's1'])
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's2'])
        self.assertEqual(self.interpreter.context['x'], 2)  # x is incremented in s1.on_entry

    def test_auto_three_steps(self):
        self.interpreter.execute(max_steps=3)

        self.assertEqual(self.interpreter.configuration, ['root', 's2'])
        self.assertEqual(self.interpreter.context['x'], 2)  # x is incremented in s1.on_entry

    def test_auto_stop(self):
        self.interpreter.execute()

        self.assertTrue(self.interpreter.final)
        self.assertEqual(self.interpreter.context['x'], 100)
示例#13
0
class ElevatorTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator/elevator.yaml') as f:
            self.sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(self.sc)
        # Stabilization
        self.interpreter.execute_once()

    def test_init(self):
        self.assertEqual(len(self.interpreter.configuration), 5)

    def test_floor_selection(self):
        self.interpreter.queue(Event('floorSelected', floor=4)).execute_once()
        self.assertEqual(self.interpreter.context['destination'], 4)
        self.interpreter.execute_once()
        self.assertEqual(sorted(self.interpreter.configuration), [
            'active', 'doorsClosed', 'floorListener', 'floorSelecting',
            'movingElevator'
        ])

    def test_doorsOpen(self):
        self.interpreter.queue(Event('floorSelected', floor=4))
        self.interpreter.execute()
        self.assertEqual(self.interpreter.context['current'], 4)
        self.interpreter.time += 10
        self.interpreter.execute()

        self.assertTrue('doorsOpen' in self.interpreter.configuration)
        self.assertEqual(self.interpreter.context['current'], 0)
示例#14
0
class RemoteElevatorTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator/elevator.yaml') as f:
            elevator = io.import_from_yaml(f)
        with open('docs/examples/elevator/elevator_buttons.yaml') as f:
            buttons = io.import_from_yaml(f)

        self.elevator = Interpreter(elevator)
        self.buttons = Interpreter(buttons)
        self.buttons.bind(self.elevator)

    def test_button(self):
        self.assertEqual(self.elevator.context['current'], 0)

        self.buttons.queue(Event('button_2_pushed'))
        self.buttons.execute()

        event = self.elevator._external_events.pop()
        self.assertEqual(event.name, 'floorSelected')
        self.assertEqual(event.data['floor'], 2)

        self.buttons.queue(Event('button_2_pushed'))
        self.buttons.execute()
        self.elevator.execute()

        self.assertEqual(self.elevator.context['current'], 2)

    def test_button_0_on_groundfloor(self):
        self.assertEqual(self.elevator.context['current'], 0)

        self.buttons.queue(Event('button_0_pushed'))
        self.buttons.execute()
        self.elevator.execute()

        self.assertEqual(self.elevator.context['current'], 0)
示例#15
0
class ElevatorTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator.yaml') as f:
            self.sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(self.sc)
        # Stabilization
        self.interpreter.execute_once()

    def test_init(self):
        self.assertEqual(len(self.interpreter.configuration), 5)

    def test_floor_selection(self):
        self.interpreter.queue(Event('floorSelected', floor=4)).execute_once()
        self.assertEqual(self.interpreter.context['destination'], 4)
        self.interpreter.execute_once()
        self.assertEqual(sorted(self.interpreter.configuration), ['active', 'doorsClosed', 'floorListener', 'floorSelecting', 'movingElevator'])

    def test_doorsOpen(self):
        self.interpreter.queue(Event('floorSelected', floor=4))
        self.interpreter.execute()
        self.assertEqual(self.interpreter.context['current'], 4)
        self.interpreter.time += 10
        self.interpreter.execute()

        self.assertTrue('doorsOpen' in self.interpreter.configuration)
        self.assertEqual(self.interpreter.context['current'], 0)
示例#16
0
class WriterExecutionTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/writer_options.yaml') as f:
            self.sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(self.sc)

    def test_output(self):
        scenario = [
            Event('keyPress', key='bonjour '),
            Event('toggle'),
            Event('keyPress', key='a '),
            Event('toggle'),
            Event('toggle_bold'),
            Event('keyPress', key='tous !'),
            Event('leave')
        ]

        for event in scenario:
            self.interpreter.queue(event)

        self.interpreter.execute()

        self.assertTrue(self.interpreter.final)
        self.assertEqual(self.interpreter.context['output'], [
            'bonjour ', '[b]', '[i]', 'a ', '[/b]', '[/i]', '[b]', 'tous !',
            '[/b]'
        ])
示例#17
0
class MicrowaveTests(unittest.TestCase):
    def setUp(self):
        with open("microwave_controller.yaml") as f:
            sc = import_from_yaml(f)

        self.oven = Interpreter(sc, initial_context=context)
        self.oven.execute_once()

    def test_no_heating_when_door_is_not_closed(self):
        self.oven.queue("door_opened", "item_placed", "timer_inc")
        self.oven.execute()

        self.oven.queue("cooking_start")

        for step in iter(self.oven.execute_once, None):
            for event in step.sent_events:
                self.assertNotEqual(event.name, "heating_on")

        self.assertNotIn("cooking_mode", self.oven.configuration)

    def test_increase_timer(self):
        self.oven.queue("door_opened", "item_placed", "door_closed")

        events = 10 * ["timer_inc"]
        self.oven.queue(*events)
        self.oven.execute()

        self.assertEqual(self.oven.context["timer"], 10)
示例#18
0
class SimulatorHistoryTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/history.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc, evaluator_klass=DummyEvaluator)
        # Stabilization
        self.interpreter.execute_once()

    def test_memory(self):
        self.interpreter.queue(Event('next')).execute_once()
        self.assertEqual(sorted(self.interpreter.configuration), ['loop', 'root', 's2'])

        step = self.interpreter.queue(Event('pause')).execute_once()
        self.assertEqual(step.exited_states, ['s2', 'loop'])
        self.assertEqual(sorted(self.interpreter.configuration), ['pause', 'root'])

    def test_resume_memory(self):
        self.interpreter.queue(Event('next')).queue(Event('pause')).queue(Event('continue'))
        steps = self.interpreter.execute()
        step = steps[-1]

        self.assertEqual(step.entered_states, ['loop', 'loop.H', 's2'])
        self.assertEqual(step.exited_states, ['pause', 'loop.H'])
        self.assertEqual(sorted(self.interpreter.configuration), ['loop', 'root', 's2'])

    def test_after_memory(self):
        self.interpreter.queue(Event('next')).queue(Event('pause')).queue(Event('continue'))
        self.interpreter.queue(Event('next')).queue(Event('next'))
        self.interpreter.execute()
        self.assertEqual(sorted(self.interpreter.configuration), ['loop', 'root', 's1'])

        self.interpreter.queue(Event('pause')).queue(Event('stop'))
        self.interpreter.execute()
        self.assertTrue(self.interpreter.final)
示例#19
0
class RacerComponent(Component):
    def __init__(self, race_distance: int, sensor_distance: str,
                 racer_distance: str, events: str):
        super().__init__()

        self._racer_distance_topic = racer_distance
        self._racer = Racer()

        with open(SCRIPT_DIR / 'racer.yaml') as f:
            statechart = sismic.io.import_from_yaml(f)

        context = {'race_distance': race_distance, 'racer': self._racer}
        self._interpreter = Interpreter(statechart, initial_context=context)
        self._interpreter.execute()

        self._io.subscribe(sensor_distance, self._on_sensor_distance)
        self._io.subscribe(events, self._on_event)

    def _on_sensor_distance(self, distance: int):
        """
        :param distance: meters since sensor start
        """

        self._racer.sensor_distance = distance
        self._io.publish(self._racer_distance_topic,
                         distance=self._racer.distance)

        steps = self._interpreter.execute()
        if steps:
            print(steps)

    def _on_event(self, name: str, **kwargs):
        self._interpreter.queue(name, **kwargs)
示例#20
0
 def test_statechart_postcondition(self):
     sc = io.import_from_yaml(open('tests/yaml/simple.yaml'))
     sc.postconditions.append('False')
     interpreter = Interpreter(sc)
     interpreter.send(Event('goto s2')).send(Event('goto final'))
     with self.assertRaises(PostconditionFailed) as cm:
         interpreter.execute()
     self.assertTrue(isinstance(cm.exception.obj, StateChart))
示例#21
0
class WatchElevatorTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator.yaml') as f:
            sc = io.import_from_yaml(f)
        self.tested = Interpreter(sc)
        self.watcher = ExecutionWatcher(self.tested)

    def test_7th_floor_never_reached(self):
        with open('docs/examples/tester_elevator_7th_floor_never_reached.yaml'
                  ) as f:
            tester_sc = io.import_from_yaml(f)

        tester = self.watcher.watch_with(tester_sc)
        self.watcher.start()

        # Send elevator to 4th
        self.tested.queue(Event('floorSelected', floor=4)).execute()
        self.watcher.stop()
        self.assertFalse(tester.final)

    def test_7th_floor_never_reached_fails(self):
        with open('docs/examples/tester_elevator_7th_floor_never_reached.yaml'
                  ) as f:
            tester_sc = io.import_from_yaml(f)

        tester = self.watcher.watch_with(tester_sc)
        self.watcher.start()

        # Send elevator to 7th
        self.tested.queue(Event('floorSelected', floor=7)).execute()
        self.watcher.stop()
        self.assertTrue(tester.final)

    def test_destination_reached(self):
        with open(
                'docs/examples/tester_elevator_destination_reached.yaml') as f:
            tester_statechart = io.import_from_yaml(f)

        # Create the interpreter and the watcher
        watcher = ExecutionWatcher(self.tested)

        # Add the tester and start watching
        tester = watcher.watch_with(tester_statechart)
        watcher.start()

        # Send the elevator to 4th
        self.tested.queue(Event('floorSelected', floor=4)).execute(max_steps=2)
        self.assertEqual(tester.context['destinations'], [4])

        self.tested.execute()
        self.assertEqual(tester.context['destinations'], [])

        # Stop watching. The tester must be in a final state
        watcher.stop()

        self.assertFalse(tester.final)
示例#22
0
    def generic_temporal_test(self, expression: TemporalExpression, story: list, accept_after: bool):
        # Todo: convert the story list into a 'real' story that can be told to an interpreter
        statechart = expression.generate_statechart()
        interpreter = Interpreter(statechart)

        for event in story:
            interpreter.queue(event)

        interpreter.execute()

        self.assertEqual(len(interpreter.configuration) == 0, accept_after)
示例#23
0
    def test_after_memory(self):
        sc = io.import_from_yaml(open('tests/yaml/history.yaml'))
        interpreter = Interpreter(sc, DummyEvaluator)

        interpreter.send(Event('next')).send(Event('pause')).send(Event('continue'))
        interpreter.send(Event('next')).send(Event('next'))
        interpreter.execute()
        self.assertEqual(sorted(interpreter.configuration), ['loop', 's1'])

        interpreter.send(Event('pause')).send(Event('stop'))
        interpreter.execute()
        self.assertTrue(interpreter.final)
示例#24
0
    def test_doorsOpen(self):
        sc = io.import_from_yaml(open('docs/examples/elevator.yaml'))
        interpreter = Interpreter(sc)

        interpreter.send(Event('floorSelected', floor=4))
        interpreter.execute()
        self.assertEqual(interpreter._evaluator.context['current'], 4)
        interpreter.time += 10
        interpreter.execute()

        self.assertTrue('doorsOpen' in interpreter.configuration)
        self.assertEqual(interpreter._evaluator.context['current'], 0)
示例#25
0
class WatchElevatorTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator.yaml') as f:
            sc = io.import_from_yaml(f)
        self.tested = Interpreter(sc)
        self.watcher = ExecutionWatcher(self.tested)

    def test_7th_floor_never_reached(self):
        with open('docs/examples/tester_elevator_7th_floor_never_reached.yaml') as f:
            tester_sc = io.import_from_yaml(f)

        tester = self.watcher.watch_with(tester_sc)
        self.watcher.start()

        # Send elevator to 4th
        self.tested.queue(Event('floorSelected', floor=4)).execute()
        self.watcher.stop()
        self.assertFalse(tester.final)

    def test_7th_floor_never_reached_fails(self):
        with open('docs/examples/tester_elevator_7th_floor_never_reached.yaml') as f:
            tester_sc = io.import_from_yaml(f)

        tester = self.watcher.watch_with(tester_sc)
        self.watcher.start()

        # Send elevator to 7th
        self.tested.queue(Event('floorSelected', floor=7)).execute()
        self.watcher.stop()
        self.assertTrue(tester.final)

    def test_destination_reached(self):
        with open('docs/examples/tester_elevator_destination_reached.yaml') as f:
            tester_statechart = io.import_from_yaml(f)

        # Create the interpreter and the watcher
        watcher = ExecutionWatcher(self.tested)

        # Add the tester and start watching
        tester = watcher.watch_with(tester_statechart)
        watcher.start()

        # Send the elevator to 4th
        self.tested.queue(Event('floorSelected', floor=4)).execute(max_steps=2)
        self.assertEqual(tester.context['destinations'], [4])

        self.tested.execute()
        self.assertEqual(tester.context['destinations'], [])

        # Stop watching. The tester must be in a final state
        watcher.stop()

        self.assertFalse(tester.final)
示例#26
0
class PythonEvaluatorNestedContextTests(unittest.TestCase):
    def setUp(self):
        statechart = """
        statechart:
          name: test
          preamble: x = y = 1
          root state:
            name: root
            initial: s1
            states:
             - name: s1
               on entry: x, z = 2, 1
               transitions:
                - target: s2
                  guard: y == 1
                  action: a, z, y = 2, 2, 2
             - name: s2
        """
        sc = import_from_yaml(statechart)
        self.intp = Interpreter(sc)

    def test_initialization(self):
        self.assertEqual(self.intp.context.get('x'), 1)
        self.assertEqual(self.intp.context.get('y'), 1)
        with self.assertRaises(KeyError):
            _ = self.intp.context['z']
        with self.assertRaises(KeyError):
            _ = self.intp.context['a']

    def test_global_context(self):
        self.intp.execute()

        self.assertEqual(self.intp.context.get('x'), 2)
        self.assertEqual(self.intp.context.get('y'), 2)
        with self.assertRaises(KeyError):
            _ = self.intp.context['z']
        with self.assertRaises(KeyError):
            _ = self.intp.context['a']

    def test_nested_context(self):
        self.intp.execute()

        s1 = self.intp._evaluator.context_for('s1')
        self.assertEqual(s1['x'], 2)
        self.assertEqual(s1['y'], 2)
        self.assertEqual(s1['z'], 2)
        with self.assertRaises(KeyError):
            _ = s1['a']
示例#27
0
class PythonEvaluatorNestedContextTests(unittest.TestCase):
    def setUp(self):
        statechart = """
        statechart:
          name: test
          preamble: x = y = 1
          root state:
            name: root
            initial: s1
            states:
             - name: s1
               on entry: x, z = 2, 1
               transitions:
                - target: s2
                  guard: y == 1
                  action: a, z, y = 2, 2, 2
             - name: s2
        """
        sc = import_from_yaml(statechart)
        self.intp = Interpreter(sc)

    def test_initialization(self):
        self.assertEqual(self.intp.context.get('x'), 1)
        self.assertEqual(self.intp.context.get('y'), 1)
        with self.assertRaises(KeyError):
            _ = self.intp.context['z']
        with self.assertRaises(KeyError):
            _ = self.intp.context['a']

    def test_global_context(self):
        self.intp.execute()

        self.assertEqual(self.intp.context.get('x'), 2)
        self.assertEqual(self.intp.context.get('y'), 2)
        with self.assertRaises(KeyError):
            _ = self.intp.context['z']
        with self.assertRaises(KeyError):
            _ = self.intp.context['a']

    def test_nested_context(self):
        self.intp.execute()

        s1 = self.intp._evaluator.context_for('s1')
        self.assertEqual(s1['x'], 2)
        self.assertEqual(s1['y'], 2)
        self.assertEqual(s1['z'], 2)
        with self.assertRaises(KeyError):
            _ = s1['a']
示例#28
0
class SimulatorSimpleTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/simple.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc, evaluator_klass=DummyEvaluator)
        # Stabilization
        self.interpreter.execute_once()

    def test_init(self):
        self.assertEqual(self.interpreter.configuration, ['root', 's1'])
        self.assertFalse(self.interpreter.final)

    def test_queue(self):
        self.interpreter.queue(Event('e1'))
        self.assertEqual(self.interpreter._select_event(), Event('e1'))

        self.interpreter.queue(InternalEvent('e1'))
        self.assertEqual(self.interpreter._select_event(), InternalEvent('e1'))

        with self.assertRaises(ValueError):
            self.interpreter.queue('e1')

    def test_simple_configuration(self):
        self.interpreter.execute_once()  # Should do nothing!
        self.assertEqual(self.interpreter.configuration, ['root', 's1'])
        self.interpreter.queue(Event('goto s2'))
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's2'])
        self.interpreter.execute_once()
        self.assertEqual(self.interpreter.configuration, ['root', 's3'])

    def test_simple_entered(self):
        self.interpreter.queue(Event('goto s2'))
        self.assertEqual(self.interpreter.execute_once().entered_states,
                         ['s2'])
        self.interpreter.queue(Event('goto final'))
        self.assertEqual(self.interpreter.execute_once().entered_states,
                         ['s3'])
        self.assertEqual(self.interpreter.execute_once().entered_states,
                         ['final'])
        self.assertEqual(self.interpreter.configuration, [])
        self.assertTrue(self.interpreter.final)

    def test_simple_final(self):
        self.interpreter.queue(Event('goto s2')).queue(Event('goto final'))
        self.interpreter.execute()
        self.assertTrue(self.interpreter.final)
示例#29
0
class SimulatorDeepHistoryTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/deep_history.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc, evaluator_klass=DummyEvaluator)
        # Stabilization
        self.interpreter.execute_once()

    def test_deep_memory(self):
        self.interpreter.queue(Event('next1')).queue(Event('next2'))
        self.interpreter.execute()
        self.assertEqual(sorted(self.interpreter.configuration), ['active', 'concurrent_processes', 'process_1', 'process_2', 'root', 's12', 's22'])

        self.interpreter.queue(Event('error1'))
        self.interpreter.execute()
        self.assertEqual(self.interpreter.configuration, ['root', 'pause'])
        self.assertEqual(sorted(self.interpreter._memory['active.H*']), ['concurrent_processes', 'process_1', 'process_2', 's12', 's22'])

        self.interpreter.queue(Event('continue'))
        self.interpreter.execute()
        self.assertEqual(sorted(self.interpreter.configuration), ['active', 'concurrent_processes', 'process_1',
                                                           'process_2', 'root', 's12', 's22'])

    def test_entered_order(self):
        self.interpreter.queue(Event('next1')).queue(Event('next2')).queue(Event('pause'))
        step = self.interpreter.execute()[-1]

        self.assertEqual(step.entered_states, ['pause'])
        self.assertEqual(sorted(self.interpreter.configuration), ['pause', 'root'])

        step = self.interpreter.queue(Event('continue')).execute_once()
        self.assertTrue(step.entered_states.index('active') < step.entered_states.index('active.H*'))
        self.assertTrue(step.entered_states.index('active.H*') < step.entered_states.index('concurrent_processes'))
        self.assertTrue(step.entered_states.index('concurrent_processes') < step.entered_states.index('process_1'))
        self.assertTrue(step.entered_states.index('concurrent_processes') < step.entered_states.index('process_2'))
        self.assertTrue(step.entered_states.index('process_1') < step.entered_states.index('s12'))
        self.assertTrue(step.entered_states.index('process_2') < step.entered_states.index('s22'))

        self.interpreter.queue(Event('next1')).queue(Event('next2')).execute()
        self.assertTrue(self.interpreter.final)

    def test_exited_order(self):
        self.interpreter.queue(Event('next1')).queue(Event('next2')).queue(Event('pause'))
        step = self.interpreter.execute()[-1]

        self.assertEqual(step.exited_states, ['s12', 's22', 'process_1', 'process_2', 'concurrent_processes', 'active'])
        self.assertEqual(sorted(self.interpreter.configuration), ['pause', 'root'])

        step = self.interpreter.queue(Event('continue')).execute_once()
        self.assertEqual(step.exited_states, ['pause', 'active.H*'])

        self.interpreter.queue(Event('next1')).queue(Event('next2')).execute()
        self.assertTrue(self.interpreter.final)
示例#30
0
class SimulatorDeepHistoryTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/deep_history.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc, evaluator_klass=DummyEvaluator)
        # Stabilization
        self.interpreter.execute_once()

    def test_deep_memory(self):
        self.interpreter.queue(Event('next1')).queue(Event('next2'))
        self.interpreter.execute()
        self.assertEqual(sorted(self.interpreter.configuration), ['active', 'concurrent_processes', 'process_1', 'process_2', 'root', 's12', 's22'])

        self.interpreter.queue(Event('error1'))
        self.interpreter.execute()
        self.assertEqual(self.interpreter.configuration, ['root', 'pause'])
        self.assertEqual(sorted(self.interpreter._memory['active.H*']), ['concurrent_processes', 'process_1', 'process_2', 's12', 's22'])

        self.interpreter.queue(Event('continue'))
        self.interpreter.execute()
        self.assertEqual(sorted(self.interpreter.configuration), ['active', 'concurrent_processes', 'process_1',
                                                           'process_2', 'root', 's12', 's22'])

    def test_entered_order(self):
        self.interpreter.queue(Event('next1')).queue(Event('next2')).queue(Event('pause'))
        step = self.interpreter.execute()[-1]

        self.assertEqual(step.entered_states, ['pause'])
        self.assertEqual(sorted(self.interpreter.configuration), ['pause', 'root'])

        step = self.interpreter.queue(Event('continue')).execute_once()
        self.assertTrue(step.entered_states.index('active') < step.entered_states.index('active.H*'))
        self.assertTrue(step.entered_states.index('active.H*') < step.entered_states.index('concurrent_processes'))
        self.assertTrue(step.entered_states.index('concurrent_processes') < step.entered_states.index('process_1'))
        self.assertTrue(step.entered_states.index('concurrent_processes') < step.entered_states.index('process_2'))
        self.assertTrue(step.entered_states.index('process_1') < step.entered_states.index('s12'))
        self.assertTrue(step.entered_states.index('process_2') < step.entered_states.index('s22'))

        self.interpreter.queue(Event('next1')).queue(Event('next2')).execute()
        self.assertTrue(self.interpreter.final)

    def test_exited_order(self):
        self.interpreter.queue(Event('next1')).queue(Event('next2')).queue(Event('pause'))
        step = self.interpreter.execute()[-1]

        self.assertEqual(step.exited_states, ['s12', 's22', 'process_1', 'process_2', 'concurrent_processes', 'active'])
        self.assertEqual(sorted(self.interpreter.configuration), ['pause', 'root'])

        step = self.interpreter.queue(Event('continue')).execute_once()
        self.assertEqual(step.exited_states, ['pause', 'active.H*'])

        self.interpreter.queue(Event('next1')).queue(Event('next2')).execute()
        self.assertTrue(self.interpreter.final)
示例#31
0
    def test_resume_memory(self):
        sc = io.import_from_yaml(open('tests/yaml/history.yaml'))
        interpreter = Interpreter(sc, DummyEvaluator)

        interpreter.send(Event('next')).send(Event('pause')).send(Event('continue'))
        steps = interpreter.execute()
        step = steps[-1]

        self.assertEqual(step.entered_states, ['loop', 'loop.H', 's2'])
        self.assertEqual(step.exited_states, ['pause', 'loop.H'])
        self.assertEqual(sorted(interpreter.configuration), ['loop', 's2'])
示例#32
0
    def test_check_guard_failure(self):
        statechart = Statechart('statechart')
        statechart.add_state(OrthogonalState('parallel_state'), parent=None)

        initial_state = CompoundState('initial_state', initial='condition')
        statechart.add_state(initial_state, parent='parallel_state')
        statechart.add_state(BasicState('success'), parent='initial_state')
        statechart.add_state(BasicState('failure'), parent='initial_state')

        CheckGuard('x == 1').add_to(statechart=statechart,
                                    id='condition',
                                    parent_id='initial_state',
                                    status_id='parallel_state',
                                    success_id='success',
                                    failure_id='failure')

        interpreter = Interpreter(statechart)
        interpreter.context['x'] = 42

        interpreter.execute()
        self.assertFalse('success' in interpreter.configuration)
        self.assertTrue('failure' in interpreter.configuration)
示例#33
0
    def generic_test(self,
                     tested_statechart: Statechart,
                     events: list,
                     property: Condition,
                     expected_success: bool,
                     expected_failure: bool):
        from sismic.interpreter import log_trace
        tester_statechart = Statechart('tester_statechart')

        tester_statechart.add_state(OrthogonalState('parallel_state'), None)
        tester_statechart.add_state(CompoundState('testing_area', initial='property'), parent='parallel_state')
        tester_statechart.add_state(BasicState('success_state'), parent='testing_area')
        tester_statechart.add_state(BasicState('failure_state'), parent='testing_area')

        property.add_to(tester_statechart,
                        id='property',
                        parent_id='testing_area',
                        status_id='parallel_state',
                        success_id='success_state',
                        failure_id='failure_state')

        tester_interpreter = Interpreter(tester_statechart)

        self.assertFalse('success_state' in tester_interpreter.configuration)
        self.assertFalse('failure_state' in tester_interpreter.configuration)

        tested_interpreter = Interpreter(tested_statechart)
        trace = log_trace(tested_interpreter)

        for event in events:
            tested_interpreter.queue(event)

        tested_interpreter.execute()

        story = teststory_from_trace(trace)
        story.tell(tester_interpreter)

        self.assertEqual(expected_success, 'success_state' in tester_interpreter.configuration)
        self.assertEqual(expected_failure, 'failure_state' in tester_interpreter.configuration)
示例#34
0
class WriterExecutionTests(unittest.TestCase):
    def setUp(self):
        self.sc = io.import_from_yaml(open('docs/examples/writer_options.yaml'))
        self.interpreter = Interpreter(self.sc)

    def test_output(self):
        scenario = [
             Event('keyPress', key='bonjour '),
             Event('toggle'),
             Event('keyPress', key='a '),
             Event('toggle'),
             Event('toggle_bold'),
             Event('keyPress', key='tous !'),
             Event('leave')
        ]

        for event in scenario:
            self.interpreter.send(event)

        self.interpreter.execute()

        self.assertTrue(self.interpreter.final)
        self.assertEqual(self.interpreter.context['output'], ['bonjour ', '[b]', '[i]', 'a ', '[/b]', '[/i]', '[b]', 'tous !', '[/b]'])
示例#35
0
    def test_exited_order(self):
        sc = io.import_from_yaml(open('tests/yaml/deep_history.yaml'))
        interpreter = Interpreter(sc, DummyEvaluator)

        interpreter.send(Event('next1')).send(Event('next2')).send(Event('pause'))
        step = interpreter.execute()[-1]

        self.assertEqual(step.exited_states, ['s12', 's22', 'process_1', 'process_2', 'concurrent_processes', 'active'])
        self.assertEqual(sorted(interpreter.configuration), ['pause'])

        step = interpreter.send(Event('continue')).execute_once()
        self.assertEqual(step.exited_states, ['pause', 'active.H*'])

        interpreter.send(Event('next1')).send(Event('next2')).execute()
        self.assertTrue(interpreter.final)
示例#36
0
class ParallelExecutionTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/parallel.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc)
        # Stabilization
        self.interpreter.execute_once()

    def test_concurrent_transitions(self):
        step = self.interpreter.queue(Event('nextA')).execute_once()

        self.assertEqual(self.interpreter.configuration,
                         ['root', 's1', 'p1', 'p2', 'a1', 'a2'])
        self.assertLess(step.exited_states.index('initial1'),
                        step.exited_states.index('initial2'))
        self.assertLess(step.entered_states.index('a1'),
                        step.entered_states.index('a2'))

    def test_concurrent_transitions_nested_target(self):
        self.interpreter.queue(Event('nextA')).queue(Event('reset1'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration,
                         ['root', 's1', 'p1', 'p2', 'a2', 'initial1'])

    def test_unnested_transitions(self):
        self.interpreter.queue(Event('nextA')).queue(Event('nextA'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration,
                         ['root', 's1', 'p1', 'p2', 'a2', 'initial1'])

    def test_unnested_transitions_2(self):
        self.interpreter.queue(Event('nextA')).queue(Event('nextB'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration,
                         ['root', 's1', 'p1', 'p2', 'b1', 'b2'])

    def test_conflicting_transitions(self):
        self.interpreter.queue(Event('nextA')).queue(Event('nextB')).queue(
            Event('conflict1'))
        self.interpreter.execute_once()
        self.interpreter.execute_once()

        with self.assertRaises(exceptions.ConflictingTransitionsError):
            self.interpreter.execute_once()

    def test_conflicting_transitions_2(self):
        self.interpreter.queue(Event('nextA')).queue(Event('nextB')).queue(
            Event('conflict2'))
        self.interpreter.execute_once()
        self.interpreter.execute_once()

        with self.assertRaises(exceptions.ConflictingTransitionsError):
            self.interpreter.execute_once()
示例#37
0
class LogTraceTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator/elevator.yaml') as f:
            sc = io.import_from_yaml(f)
        self.tested = Interpreter(sc)
        self.steps = log_trace(self.tested)

    def test_empty_trace(self):
        self.assertEqual(self.steps, [])

    def test_nonempty_trace(self):
        self.tested.queue(Event('floorSelected', floor=4)).execute()
        self.assertTrue(len(self.steps) > 0)

    def test_log_content(self):
        self.tested.queue(Event('floorSelected', floor=4))
        steps = self.tested.execute()
        self.assertSequenceEqual(self.steps, steps)
示例#38
0
class LogTraceTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator/elevator.yaml') as f:
            sc = io.import_from_yaml(f)
        self.tested = Interpreter(sc)
        self.steps = log_trace(self.tested)

    def test_empty_trace(self):
        self.assertEqual(self.steps, [])

    def test_nonempty_trace(self):
        self.tested.queue(Event('floorSelected', floor=4)).execute()
        self.assertTrue(len(self.steps) > 0)

    def test_log_content(self):
        self.tested.queue(Event('floorSelected', floor=4))
        steps = self.tested.execute()
        self.assertSequenceEqual(self.steps, steps)
示例#39
0
    def tell(self, interpreter: Interpreter, *args, **kwargs) -> List[MacroStep]:
        """
        Tells the whole story to the interpreter.

        :param interpreter: an interpreter instance
        :param args: additional positional arguments that are passed to *interpreter.execute*.
        :param kwargs: additional keywords arguments that are passed to *interpreter.execute*.
        :return: the resulting trace of execution (a list of *MacroStep*)
        """
        trace = []  # type: List[MacroStep]
        for item in self:
            if isinstance(item, Event):
                interpreter.queue(item)
            elif isinstance(item, Pause):
                interpreter.time += item.duration
            step = interpreter.execute(*args, **kwargs)
            if step:
                trace.extend(step)
        return trace
示例#40
0
class ParallelExecutionTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/parallel.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc)
        # Stabilization
        self.interpreter.execute_once()

    def test_concurrent_transitions(self):
        step = self.interpreter.queue(Event('nextA')).execute_once()

        self.assertEqual(self.interpreter.configuration, ['root', 's1', 'p1', 'p2', 'a1', 'a2'])
        self.assertLess(step.exited_states.index('initial1'), step.exited_states.index('initial2'))
        self.assertLess(step.entered_states.index('a1'), step.entered_states.index('a2'))

    def test_concurrent_transitions_nested_target(self):
        self.interpreter.queue(Event('nextA')).queue(Event('reset1'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration, ['root', 's1', 'p1', 'p2', 'a2', 'initial1'])

    def test_unnested_transitions(self):
        self.interpreter.queue(Event('nextA')).queue(Event('nextA'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration, ['root', 's1', 'p1', 'p2', 'a2', 'initial1'])

    def test_unnested_transitions_2(self):
        self.interpreter.queue(Event('nextA')).queue(Event('nextB'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration, ['root', 's1', 'p1', 'p2', 'b1', 'b2'])

    def test_conflicting_transitions(self):
        self.interpreter.queue(Event('nextA')).queue(Event('nextB')).queue(Event('conflict1'))
        self.interpreter.execute_once()
        self.interpreter.execute_once()

        with self.assertRaises(exceptions.ConflictingTransitionsError):
            self.interpreter.execute_once()

    def test_conflicting_transitions_2(self):
        self.interpreter.queue(Event('nextA')).queue(Event('nextB')).queue(Event('conflict2'))
        self.interpreter.execute_once()
        self.interpreter.execute_once()

        with self.assertRaises(exceptions.ConflictingTransitionsError):
            self.interpreter.execute_once()
示例#41
0
    def test_deep_memory(self):
        sc = io.import_from_yaml(open('tests/yaml/deep_history.yaml'))
        interpreter = Interpreter(sc, DummyEvaluator)

        interpreter.send(Event('next1')).send(Event('next2'))
        interpreter.execute()
        self.assertEqual(sorted(interpreter.configuration), ['active', 'concurrent_processes', 'process_1', 'process_2', 's12', 's22'])

        interpreter.send(Event('error1'))
        interpreter.execute()
        self.assertEqual(interpreter.configuration, ['pause'])
        self.assertEqual(sorted(interpreter._memory['active.H*']), ['concurrent_processes', 'process_1', 'process_2', 's12', 's22'])

        interpreter.send(Event('continue'))
        interpreter.execute()
        self.assertEqual(sorted(interpreter.configuration), ['active', 'concurrent_processes', 'process_1',
                                                           'process_2', 's12', 's22'])
示例#42
0
class ParallelExecutionTests(unittest.TestCase):
    def setUp(self):
        self.sc = io.import_from_yaml(open('tests/yaml/parallel.yaml'))
        self.interpreter = Interpreter(self.sc)

    def test_concurrent_transitions(self):
        step = self.interpreter.send(Event('nextA')).execute_once()

        self.assertEqual(self.interpreter.configuration, ['s1', 'p1', 'p2', 'a1', 'a2'])
        self.assertLess(step.exited_states.index('initial1'), step.exited_states.index('initial2'))
        self.assertLess(step.entered_states.index('a1'), step.entered_states.index('a2'))

    def test_concurrent_transitions_nested_target(self):
        self.interpreter.send(Event('nextA')).send(Event('reset1'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration, ['s1', 'p1', 'p2', 'a2', 'initial1'])

    def test_unnested_transitions(self):
        self.interpreter.send(Event('nextA')).send(Event('nextA'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration, ['s1', 'p1', 'p2', 'a2', 'initial1'])

    def test_unnested_transitions_2(self):
        self.interpreter.send(Event('nextA')).send(Event('nextB'))
        self.interpreter.execute()

        self.assertEqual(self.interpreter.configuration, ['s1', 'p1', 'p2', 'b1', 'b2'])

    def test_conflicting_transitions(self):
        self.interpreter.send(Event('nextA')).send(Event('nextB')).send(Event('conflict1'))
        self.interpreter.execute_once()
        self.interpreter.execute_once()

        with self.assertRaises(Warning):
            self.interpreter.execute_once()

    def test_conflicting_transitions_2(self):
        self.interpreter.send(Event('nextA')).send(Event('nextB')).send(Event('conflict2'))
        self.interpreter.execute_once()
        self.interpreter.execute_once()

        with self.assertRaises(Warning):
            self.interpreter.execute_once()
示例#43
0
class Presenter:
    def __init__(self, view, model):
        with open(get_resource_path('statechart/watch.yml')) as f:
            statechart = yaml.load(f, Loader=IncludeLoader)
            statechart = import_from_yaml(text=yaml.dump(statechart))

        self.it = Interpreter(statechart)
        self.it.context["pr"] = self
        self.it.context["model"] = model
        self.it.clock.start()

        self._view = view
        self._view.schedule_once(self._run_interpreter, 0.1)
        self._view.set_event_callback(self.it.queue)

    def _run_interpreter(self):
        self._view.schedule_once(self._run_interpreter, 0.1)
        self.it.execute()

    def set_light(self, state):
        self._view.set_light(state)

    def _display_time(self, time, hour24):
        self._view.set_text("min", time.strftime("%M"))
        self._view.set_text("sec", time.strftime("%S"))

        if hour24:
            self._view.set_text("am_pm", time.strftime("%p"))
            self._view.set_text("hour", time.strftime("%I"))
        else:
            self._view.set_text("am_pm", "")
            self._view.set_text("hour", time.strftime("%H"))

    def _display_on_off(self, state):
        if state:
            self._view.set_text("sec", "ON")
        else:
            self._view.set_text("sec", "OFF")

    def update_disp_select(self, selected):
        for part in "hour", "min", "sec", "am_pm":
            if part == selected:
                self._view.set_text(part + "_sel", "-")
            else:
                self._view.set_text(part + "_sel", "")

    def update_display_time(self, time, hour24):
        self._display_time(time, hour24)

    def update_display_date(self, time):
        self._view.set_text("hour", time.strftime("%m"))
        self._view.set_text("min", time.strftime("%d"))
        self._view.set_text("sec", time.strftime("%y"))
        self._view.set_text("am_pm", time.strftime("%a"))

    def update_display_alarm(self, time, hour24, enabled):
        self._display_time(time, hour24)
        self._display_on_off(enabled)

    def update_display_chime(self, enabled):
        self._view.set_text("hour", "")
        self._view.set_text("min", "00")
        self._view.set_text("sec", "")
        self._view.set_text("am_pm", "")
        self._display_on_off(enabled)

    def update_display_stopwatch_zero(self):
        self._view.set_text("hour", "{:02}".format(0))
        self._view.set_text("min", "{:02}".format(0))
        self._view.set_text("sec", "{:02}".format(0))
        self._view.set_text("am_pm", "")

    def update_display_stopwatch(self, elapsed, stopped, time):
        if not stopped:
            elapsed += (datetime.datetime.today() - time)
        stopwatch_time = elapsed.total_seconds()

        total_mseconds = int(stopwatch_time * 1000)
        mseconds = total_mseconds % 1000
        total_seconds = total_mseconds // 1000
        seconds = total_seconds % 60
        total_minutes = total_seconds // 60
        minutes = total_minutes % 60

        self._view.set_text("hour", "{:02}".format(minutes))
        self._view.set_text("min", "{:02}".format(seconds))
        self._view.set_text("sec", "{:02}".format(mseconds // 10))
        self._view.set_text("am_pm", "")

    def update_mode_selection(self, mode):
        for ind in self._view.icons.keys():
            if mode.startswith(ind):
                self._view.set_text(ind, self._view.icons[ind])
            else:
                self._view.set_text(ind, "")

    def update_indication_state(self, enabled):
        for ind in self._view.icons.keys():
            if enabled[ind]:
                self._view.set_text(ind, self._view.icons[ind])
            else:
                self._view.set_text(ind, "")

    def play(self, name, loop=False):
        self._view.play(name, loop)

    def stop(self):
        self._view.stop()

    def run(self):
        self._view.run()
示例#44
0
class PythonEvaluatorSequenceConditionTests(unittest.TestCase):
    def setUp(self):
        self.sc = import_from_yaml("""
        statechart:
          name: test contract
          root state:
            name: root
            on entry: x = 1
            initial: s0
            states:
             - name: s0
               initial: s1
               transitions:
               - event: end
                 target: root
               states:
               - name: s1
                 transitions:
                   - target: s2
                     action: x = 2
                     event: e
               - name: s2
        """)

        self.root = self.sc.state_for('root')  # Will never be exited
        self.s0 = self.sc.state_for('s0')  # Will be exited on "end"
        self.s1 = self.sc.state_for('s1')  # Entered, and then exited on e.
        self.s2 = self.sc.state_for('s2')  # Entered when e
        self.intp = Interpreter(self.sc)

    def test_single_condition(self):
        self.root.sequences.append('"True"')
        self.intp.execute()

    def test_access_context(self):
        self.root.sequences.append('"x == 1"')
        self.intp.execute()

    def test_access_nested_context(self):
        self.s0.sequences.append('"x == 1" -> "x == 2"')
        self.intp.queue(Event('e')).queue(Event('end'))
        self.intp.execute()

    def test_fails_fast(self):
        self.s0.sequences.append('Failure')
        with self.assertRaises(SequentialConditionError):
            self.intp.execute()

    def test_fails_on_exit(self):
        self.s0.sequences.append('"x == 1" -> "x == 2" -> "x == 3"')
        self.intp.queue(Event('e'))
        self.intp.execute()
        self.intp.queue(Event('end'))
        with self.assertRaises(SequentialConditionError):
            self.intp.execute()
示例#45
0
 def test_do_not_raise(self):
     self.sc.invariants.append('False')
     interpreter = Interpreter(self.sc, ignore_contract=True)
     interpreter.send(Event('floorSelected', floor=4))
     interpreter.execute()
示例#46
0
class ElevatorContractTests(unittest.TestCase):
    def setUp(self):
        self.sc = io.import_from_yaml(open('docs/examples/elevator.yaml'))
        self.interpreter = Interpreter(self.sc)

    def test_no_error(self):
        self.interpreter.send(Event('floorSelected', floor=4))
        self.interpreter.execute()
        self.assertFalse(self.interpreter.final)

    def test_state_precondition(self):
        self.sc.states['movingUp'].preconditions.append('False')
        self.interpreter.send(Event('floorSelected', floor=4))
        with self.assertRaises(PreconditionFailed) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, StateMixin))

    def test_state_postcondition(self):
        self.sc.states['movingUp'].postconditions.append('False')
        self.interpreter.send(Event('floorSelected', floor=4))
        with self.assertRaises(PostconditionFailed) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, StateMixin))

    def test_state_invariant(self):
        self.sc.states['movingUp'].invariants.append('False')
        self.interpreter.send(Event('floorSelected', floor=4))
        with self.assertRaises(InvariantFailed) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, StateMixin))

    def test_transition_precondition(self):
        self.sc.states['floorSelecting'].transitions[0].preconditions.append('False')
        self.interpreter.send(Event('floorSelected', floor=4))
        with self.assertRaises(PreconditionFailed) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, Transition))

    def test_transition_postcondition(self):
        self.sc.states['floorSelecting'].transitions[0].postconditions.append('False')
        self.interpreter.send(Event('floorSelected', floor=4))
        with self.assertRaises(PostconditionFailed) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, Transition))

    def test_statechart_precondition(self):
        self.sc.preconditions.append('False')
        with self.assertRaises(PreconditionFailed) as cm:
            self.interpreter = Interpreter(self.sc)
        self.assertTrue(isinstance(cm.exception.obj, StateChart))

    def test_statechart_postcondition(self):
        sc = io.import_from_yaml(open('tests/yaml/simple.yaml'))
        sc.postconditions.append('False')
        interpreter = Interpreter(sc)
        interpreter.send(Event('goto s2')).send(Event('goto final'))
        with self.assertRaises(PostconditionFailed) as cm:
            interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, StateChart))

    def test_statechart_invariant(self):
        self.sc.invariants.append('False')
        self.interpreter.send(Event('floorSelected', floor=4))
        with self.assertRaises(InvariantFailed) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, StateChart))

    def test_do_not_raise(self):
        self.sc.invariants.append('False')
        interpreter = Interpreter(self.sc, ignore_contract=True)
        interpreter.send(Event('floorSelected', floor=4))
        interpreter.execute()
示例#47
0
class StopwatchApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('stopwatch.yaml') as f:
            statechart = import_from_yaml(f)
        self.interpreter = Interpreter(statechart, initial_time=time.time())

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        # Run the interpreter
        self.run()

    def run(self):
        # This function does essentially the same job than ``sismic.interpreter.run_in_background``
        # but uses Tkinter's mainloop instead of a Thread, which is more adequate.

        # Update internal clock and execute interpreter
        self.interpreter.time = time.time()
        self.interpreter.execute()

        # Queue a call every 100ms on tk's mainloop
        self.after(100, self.run)

        # Update the widget that contains the list of active states.
        self.w_states['text'] = 'active states: ' + ', '.join(self.interpreter.configuration)

    def create_widgets(self):
        self.pack()

        # Add buttons
        self.w_btn_start = tk.Button(self, text='start', command=self._start)
        self.w_btn_stop = tk.Button(self, text='stop', command=self._stop)
        self.w_btn_split = tk.Button(self, text='split', command=self._split)
        self.w_btn_unsplit = tk.Button(self, text='unsplit', command=self._unsplit)
        self.w_btn_reset = tk.Button(self, text='reset', command=self._reset)
        self.w_btn_quit = tk.Button(self, text='quit', command=self._quit)

        # Initial button states
        self.w_btn_stop['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.DISABLED

        # Pack
        self.w_btn_start.pack(side=tk.LEFT,)
        self.w_btn_stop.pack(side=tk.LEFT,)
        self.w_btn_split.pack(side=tk.LEFT,)
        self.w_btn_unsplit.pack(side=tk.LEFT,)
        self.w_btn_reset.pack(side=tk.LEFT,)
        self.w_btn_quit.pack(side=tk.LEFT,)

        # Active states label
        self.w_states = tk.Label(root)
        self.w_states.pack(side=tk.BOTTOM, fill=tk.X)

        # Timer label
        self.w_timer = tk.Label(root, font=("Helvetica", 16), pady=5)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

    def event_handler(self, event):
        # Update text widget when timer value is updated
        if event.name == 'refresh':
            self.w_timer['text'] = event.time

    def _start(self):
        self.interpreter.queue(Event('start'))
        self.w_btn_start['state'] = tk.DISABLED
        self.w_btn_stop['state'] = tk.NORMAL

    def _stop(self):
        self.interpreter.queue(Event('stop'))
        self.w_btn_start['state'] = tk.NORMAL
        self.w_btn_stop['state'] = tk.DISABLED

    def _reset(self):
        self.interpreter.queue(Event('reset'))

    def _split(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.NORMAL

    def _unsplit(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.NORMAL
        self.w_btn_unsplit['state'] = tk.DISABLED

    def _quit(self):
        self.master.destroy()
class StopwatchApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('stopwatch_external.yaml') as f:
            statechart = import_from_yaml(f)

        # Create a stopwatch object and pass it to the interpreter
        self.stopwatch = Stopwatch()
        self.interpreter = Interpreter(statechart,
                                       initial_context={'stopwatch': self.stopwatch},
                                       initial_time=time.time())

        # Run the interpreter
        self.run()

        # Update the stopwatch every 100ms
        self.after(100, self.update_stopwatch)

    def update_stopwatch(self):
        self.stopwatch.update(delta=0.1)
        self.after(100, self.update_stopwatch)

        # Update timer label
        self.w_timer['text'] = self.stopwatch.display()

    def run(self):
        # Queue a call every 100ms on tk's mainloop
        self.interpreter.execute()
        self.after(100, self.run)
        self.w_states['text'] = 'active states: ' + ', '.join(self.interpreter.configuration)

    def create_widgets(self):
        self.pack()

        # Add buttons
        self.w_btn_start = tk.Button(self, text='start', command=self._start)
        self.w_btn_stop = tk.Button(self, text='stop', command=self._stop)
        self.w_btn_split = tk.Button(self, text='split', command=self._split)
        self.w_btn_unsplit = tk.Button(self, text='unsplit', command=self._unsplit)
        self.w_btn_reset = tk.Button(self, text='reset', command=self._reset)
        self.w_btn_quit = tk.Button(self, text='quit', command=self._quit)

        # Initial button states
        self.w_btn_stop['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.DISABLED

        # Pack
        self.w_btn_start.pack(side=tk.LEFT,)
        self.w_btn_stop.pack(side=tk.LEFT,)
        self.w_btn_split.pack(side=tk.LEFT,)
        self.w_btn_unsplit.pack(side=tk.LEFT,)
        self.w_btn_reset.pack(side=tk.LEFT,)
        self.w_btn_quit.pack(side=tk.LEFT,)

        # Active states label
        self.w_states = tk.Label(root)
        self.w_states.pack(side=tk.BOTTOM, fill=tk.X)

        # Timer label
        self.w_timer = tk.Label(root, font=("Helvetica", 16), pady=5)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

    def _start(self):
        self.interpreter.queue(Event('start'))
        self.w_btn_start['state'] = tk.DISABLED
        self.w_btn_stop['state'] = tk.NORMAL

    def _stop(self):
        self.interpreter.queue(Event('stop'))
        self.w_btn_start['state'] = tk.NORMAL
        self.w_btn_stop['state'] = tk.DISABLED

    def _reset(self):
        self.interpreter.queue(Event('reset'))

    def _split(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.NORMAL

    def _unsplit(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.NORMAL
        self.w_btn_unsplit['state'] = tk.DISABLED

    def _quit(self):
        self.master.destroy()
示例#49
0
文件: microwave.py 项目: AvdN/sismic
class MicrowaveApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('microwave.yaml') as f:
            statechart = import_from_yaml(f)
        self.interpreter = Interpreter(statechart)

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        self.execute()

    def execute(self):
        self.interpreter.execute()

        # Update the widget that contains the list of active states.
        self.w_states['text'] = '\n'.join(self.interpreter.configuration)

        self.w_timer['text'] = 'M.timer: %d' % self.interpreter.context.get(
            'controller.timer', 'undefined')
        self.w_power['text'] = 'M.power: %d' % self.interpreter.context.get(
            'controller.power', 'undefined')

    def create_widgets(self):
        self.pack(fill=tk.BOTH)

        # MAIN frame containing all others
        left_frame = tk.Frame(self)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH)

        # INPUT frame
        input_frame = tk.LabelFrame(left_frame, text='INPUT BUTTONS')
        input_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        self.w_power_inc = tk.Button(input_frame,
                                     text='power +',
                                     command=partial(
                                         self.send_event,
                                         event_name='input_power_inc'))
        self.w_power_dec = tk.Button(input_frame,
                                     text='power -',
                                     command=partial(
                                         self.send_event,
                                         event_name='input_power_dec'))
        self.w_power_reset = tk.Button(input_frame,
                                       text='power reset',
                                       command=partial(
                                           self.send_event,
                                           event_name='input_power_reset'))

        self.w_power_inc.pack(side=tk.TOP, fill=tk.X)
        self.w_power_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_power_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_timer_inc = tk.Button(input_frame,
                                     text='timer +',
                                     command=partial(
                                         self.send_event,
                                         event_name='input_timer_inc'))
        self.w_timer_dec = tk.Button(input_frame,
                                     text='timer -',
                                     command=partial(
                                         self.send_event,
                                         event_name='input_timer_dec'))
        self.w_timer_reset = tk.Button(input_frame,
                                       text='timer 0',
                                       command=partial(
                                           self.send_event,
                                           event_name='input_timer_reset'))

        self.w_timer_inc.pack(side=tk.TOP, fill=tk.X,
                              pady=(8,
                                    0))  # leave some space before first button
        self.w_timer_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_timer_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_cooking_start = tk.Button(input_frame,
                                         text='start',
                                         command=partial(
                                             self.send_event,
                                             event_name='input_cooking_start'))
        self.w_cooking_stop = tk.Button(input_frame,
                                        text='stop',
                                        command=partial(
                                            self.send_event,
                                            event_name='input_cooking_stop'))

        self.w_cooking_start.pack(
            side=tk.TOP, fill=tk.X,
            pady=(8, 0))  # leave some space before first button
        self.w_cooking_stop.pack(side=tk.TOP, fill=tk.X)

        # SENSORS frame
        sensors_frame = tk.LabelFrame(left_frame, text='SENSORS')
        sensors_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # SENSORS > Clock frame
        clock_frame = tk.LabelFrame(sensors_frame, text='Clock')
        clock_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_clock = tk.Label(clock_frame)

        self.w_tick = tk.Button(clock_frame,
                                text='tick',
                                command=partial(self.send_event,
                                                event_name='timer_tick'))
        self.w_tick.pack(side=tk.TOP, fill=tk.X)

        # SENSORS > WeightSensor frame
        weight_frame = tk.LabelFrame(sensors_frame, text='WeightSensor')
        weight_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_weight = tk.Label(weight_frame)

        self.w_item_placed = tk.Button(weight_frame,
                                       text='place item',
                                       command=partial(
                                           self.send_event,
                                           event_name='item_placed'))
        self.w_item_removed = tk.Button(weight_frame,
                                        text='remove item',
                                        command=partial(
                                            self.send_event,
                                            event_name='item_removed'))

        self.w_item_placed.pack(side=tk.TOP, fill=tk.X)
        self.w_item_removed.pack(side=tk.TOP, fill=tk.X)

        # SENSORS > Door frame
        door_frame = tk.LabelFrame(sensors_frame, text='Door')
        door_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_door = tk.Label(door_frame)

        self.w_door_opened = tk.Button(door_frame,
                                       text='open door',
                                       command=partial(
                                           self.send_event,
                                           event_name='door_opened'))
        self.w_door_closed = tk.Button(door_frame,
                                       text='close door',
                                       command=partial(
                                           self.send_event,
                                           event_name='door_closed'))

        self.w_door_opened.pack(side=tk.TOP, fill=tk.X)
        self.w_door_closed.pack(side=tk.TOP, fill=tk.X)

        # ACTUATORS frame
        right_frame = tk.LabelFrame(self, text='ACTUATORS')
        right_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Display component
        display_frame = tk.LabelFrame(right_frame, text='Display')
        display_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_display = tk.Label(display_frame)
        self.w_display.pack(side=tk.TOP)

        # Lamp component
        lamp_frame = tk.LabelFrame(right_frame, text='Lamp')
        lamp_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_lamp = tk.Label(lamp_frame)
        self.w_lamp.pack(side=tk.TOP)

        # Heating component
        heating_frame = tk.LabelFrame(right_frame, text='Heating')
        heating_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_heating_power = tk.Label(heating_frame)
        self.w_heating_status = tk.Label(heating_frame)
        self.w_heating_power.pack(side=tk.TOP)
        self.w_heating_status.pack(side=tk.TOP)

        # Beeper component
        beep_frame = tk.LabelFrame(right_frame, text='Beeper')
        beep_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_beep = tk.Label(beep_frame)
        self.w_beep.pack(side=tk.TOP)

        # Turntable component
        turntable_frame = tk.LabelFrame(right_frame, text='Turntable')
        turntable_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_turntable = tk.Label(turntable_frame)
        self.w_turntable.pack(side=tk.TOP)

        # Oven controller statechart component
        controller_frame = tk.LabelFrame(self, text='Oven Controller')
        controller_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))
        # Microwave Controller Statechart status
        # statechart_frame = tk.LabelFrame(right_frame2, text='Controller')
        # statechart_frame.pack(side=tk.TOP, fill=tk.BOTH)

        states_frame = tk.LabelFrame(controller_frame, text='States')
        states_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_states = tk.Label(states_frame)
        self.w_states.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))

        variables_frame = tk.LabelFrame(controller_frame, text='Variables')
        variables_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_timer = tk.Label(variables_frame)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

        self.w_power = tk.Label(variables_frame)
        self.w_power.pack(side=tk.BOTTOM, fill=tk.X)

    def event_handler(self, event):
        name = event.name

        if name == 'lamp_switch_on':
            self.w_lamp['text'] = 'on'
        elif name == 'lamp_switch_off':
            self.w_lamp['text'] = 'off'
        elif name == 'display_set':
            self.w_display['text'] = event.text
        elif name == 'display_clear':
            self.w_display['text'] = ''
        elif name == 'heating_set_power':
            self.w_heating_power['text'] = event.power
        elif name == 'heating_on':
            self.w_heating_status['text'] = 'on'
        elif name == 'heating_off':
            self.w_heating_status['text'] = 'off'
        elif name == 'beep':
            self.w_beep['text'] = event.number
        elif name == 'turntable_start':
            self.w_turntable['text'] = 'on'
        elif name == 'turntable_stop':
            self.w_turntable['text'] = 'off'
        else:
            raise ValueError('Unknown event %s' % event)

    def send_event(self, event_name):
        self.interpreter.queue(Event(event_name))
        self.execute()

    def _quit(self):
        self.master.destroy()
示例#50
0
class StopwatchApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('stopwatch.yaml') as f:
            statechart = import_from_yaml(f)
        self.interpreter = Interpreter(statechart)
        self.interpreter.time = time.time()

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        # Run the interpreter
        self.run()

    def run(self):
        # This function does essentially the same job than ``sismic.interpreter.run_in_background``
        # but uses Tkinter's mainloop instead of a Thread, which is more adequate.

        # Update internal clock and execute interpreter
        self.interpreter.time = time.time()
        self.interpreter.execute()

        # Queue a call every 100ms on tk's mainloop
        self.after(100, self.run)

        # Update the widget that contains the list of active states.
        self.w_states['text'] = 'active states: ' + ', '.join(
            self.interpreter.configuration)

    def create_widgets(self):
        self.pack()

        # Add buttons
        self.w_btn_start = tk.Button(self, text='start', command=self._start)
        self.w_btn_stop = tk.Button(self, text='stop', command=self._stop)
        self.w_btn_split = tk.Button(self, text='split', command=self._split)
        self.w_btn_unsplit = tk.Button(self,
                                       text='unsplit',
                                       command=self._unsplit)
        self.w_btn_reset = tk.Button(self, text='reset', command=self._reset)
        self.w_btn_quit = tk.Button(self, text='quit', command=self._quit)

        # Initial button states
        self.w_btn_stop['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.DISABLED

        # Pack
        self.w_btn_start.pack(side=tk.LEFT, )
        self.w_btn_stop.pack(side=tk.LEFT, )
        self.w_btn_split.pack(side=tk.LEFT, )
        self.w_btn_unsplit.pack(side=tk.LEFT, )
        self.w_btn_reset.pack(side=tk.LEFT, )
        self.w_btn_quit.pack(side=tk.LEFT, )

        # Active states label
        self.w_states = tk.Label(root)
        self.w_states.pack(side=tk.BOTTOM, fill=tk.X)

        # Timer label
        self.w_timer = tk.Label(root, font=("Helvetica", 16), pady=5)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

    def event_handler(self, event):
        # Update text widget when timer value is updated
        if event.name == 'refresh':
            self.w_timer['text'] = event.time

    def _start(self):
        self.interpreter.queue(Event('start'))
        self.w_btn_start['state'] = tk.DISABLED
        self.w_btn_stop['state'] = tk.NORMAL

    def _stop(self):
        self.interpreter.queue(Event('stop'))
        self.w_btn_start['state'] = tk.NORMAL
        self.w_btn_stop['state'] = tk.DISABLED

    def _reset(self):
        self.interpreter.queue(Event('reset'))

    def _split(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.NORMAL

    def _unsplit(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.NORMAL
        self.w_btn_unsplit['state'] = tk.DISABLED

    def _quit(self):
        self.master.destroy()
示例#51
0
class ElevatorContractTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator/elevator.yaml') as f:
            self.sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(self.sc)

    def test_no_error(self):
        self.interpreter.queue(Event('floorSelected', floor=4))
        self.interpreter.execute()
        self.assertFalse(self.interpreter.final)

    def test_state_precondition(self):
        self.sc.state_for('movingUp').preconditions.append('False')
        self.interpreter.queue(Event('floorSelected', floor=4))
        with self.assertRaises(PreconditionError) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, StateMixin))

    def test_state_postcondition(self):
        self.sc.state_for('movingUp').postconditions.append('False')
        self.interpreter.queue(Event('floorSelected', floor=4))
        with self.assertRaises(PostconditionError) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, StateMixin))

    def test_state_invariant(self):
        self.sc.state_for('movingUp').invariants.append('False')
        self.interpreter.queue(Event('floorSelected', floor=4))
        with self.assertRaises(InvariantError) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, StateMixin))

    def test_transition_precondition(self):
        transitions = self.sc.transitions_from('floorSelecting')
        transitions[0].preconditions.append('False')
        self.interpreter.queue(Event('floorSelected', floor=4))
        with self.assertRaises(PreconditionError) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, Transition))

    def test_transition_postcondition(self):
        transitions = self.sc.transitions_from('floorSelecting')
        transitions[0].postconditions.append('False')
        self.interpreter.queue(Event('floorSelected', floor=4))
        with self.assertRaises(PostconditionError) as cm:
            self.interpreter.execute()
        self.assertTrue(isinstance(cm.exception.obj, Transition))

    def test_do_not_raise(self):
        self.interpreter = Interpreter(self.sc, ignore_contract=True)
        transitions = self.sc.transitions_from('floorSelecting')
        transitions[0].postconditions.append('False')
        self.interpreter.queue(Event('floorSelected', floor=4))
        self.interpreter.execute()
示例#52
0
class StopwatchApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('stopwatch_external.yaml') as f:
            statechart = import_from_yaml(f)

        # Create a stopwatch object and pass it to the interpreter
        self.stopwatch = Stopwatch()
        self.interpreter = Interpreter(
            statechart, initial_context={'stopwatch': self.stopwatch})
        self.interpreter.time = time.time()

        # Run the interpreter
        self.run()

        # Update the stopwatch every 100ms
        self.after(100, self.update_stopwatch)

    def update_stopwatch(self):
        self.stopwatch.update(delta=0.1)
        self.after(100, self.update_stopwatch)

        # Update timer label
        self.w_timer['text'] = self.stopwatch.display()

    def run(self):
        # Queue a call every 100ms on tk's mainloop
        self.interpreter.execute()
        self.after(100, self.run)
        self.w_states['text'] = 'active states: ' + ', '.join(
            self.interpreter.configuration)

    def create_widgets(self):
        self.pack()

        # Add buttons
        self.w_btn_start = tk.Button(self, text='start', command=self._start)
        self.w_btn_stop = tk.Button(self, text='stop', command=self._stop)
        self.w_btn_split = tk.Button(self, text='split', command=self._split)
        self.w_btn_unsplit = tk.Button(self,
                                       text='unsplit',
                                       command=self._unsplit)
        self.w_btn_reset = tk.Button(self, text='reset', command=self._reset)
        self.w_btn_quit = tk.Button(self, text='quit', command=self._quit)

        # Initial button states
        self.w_btn_stop['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.DISABLED

        # Pack
        self.w_btn_start.pack(side=tk.LEFT, )
        self.w_btn_stop.pack(side=tk.LEFT, )
        self.w_btn_split.pack(side=tk.LEFT, )
        self.w_btn_unsplit.pack(side=tk.LEFT, )
        self.w_btn_reset.pack(side=tk.LEFT, )
        self.w_btn_quit.pack(side=tk.LEFT, )

        # Active states label
        self.w_states = tk.Label(root)
        self.w_states.pack(side=tk.BOTTOM, fill=tk.X)

        # Timer label
        self.w_timer = tk.Label(root, font=("Helvetica", 16), pady=5)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

    def _start(self):
        self.interpreter.queue(Event('start'))
        self.w_btn_start['state'] = tk.DISABLED
        self.w_btn_stop['state'] = tk.NORMAL

    def _stop(self):
        self.interpreter.queue(Event('stop'))
        self.w_btn_start['state'] = tk.NORMAL
        self.w_btn_stop['state'] = tk.DISABLED

    def _reset(self):
        self.interpreter.queue(Event('reset'))

    def _split(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.NORMAL

    def _unsplit(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.NORMAL
        self.w_btn_unsplit['state'] = tk.DISABLED

    def _quit(self):
        self.master.destroy()
示例#53
0
class MicrowaveApplication(tk.Frame):
    def __init__(self, master, statechart, contracts, properties):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        statechart = import_from_yaml(statechart)
        self.interpreter = Interpreter(statechart,
                                       ignore_contract=not contracts)

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        # Bind execution watchers
        self.watcher = ExecutionWatcher(self.interpreter)
        for prop in properties if properties else []:
            self.watcher.watch_with(import_from_yaml(prop), fails_fast=True)
        self.watcher.start()

        # Hide disabled widgets
        for widget_name in DISABLED_WIDGETS:
            widget = getattr(self, widget_name)
            widget.pack_forget()

        self.on_autotick()
        self.execute()

    def execute(self):
        try:
            print(self.interpreter.execute())
        except ContractError as e:
            messagebox.showerror(
                'Contract error!', e.__class__.__name__ + '\n\n' +
                'The following assertion does not hold in ' + str(e.obj) +
                ':\n' + e.condition + '\n\n' + 'Step: \n' + str(e.step))
            self.master.destroy()
            raise
        except AssertionError as e:
            messagebox.showerror('Unsatisfied property', e.args[0])
            self.master.destroy()
            raise
        except Exception as e:
            messagebox.showerror(
                'Fatal error',
                e.__class__.__name__ + ' was raised during the execution.\n' +
                'See console for the traceback.')
            self.master.destroy()
            raise

        # Update the widget that contains the list of active states.
        self.w_states['text'] = '\n'.join(self.interpreter.configuration)

        self.w_context['text'] = '\n'.join([
            '%s: %s' % (key, self.interpreter.context[key])
            for key in sorted(self.interpreter.context)
        ])

    def create_widgets(self):
        self.pack(fill=tk.BOTH)

        # Statechart status
        controller_frame = tk.LabelFrame(self, text='CONTROLLER')
        controller_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=(8, 8))

        state_frame = tk.LabelFrame(controller_frame,
                                    text='Active configuration')
        state_frame.pack(side=tk.BOTTOM, fill=tk.X)

        self.w_states = tk.Label(state_frame)
        self.w_states.pack(side=tk.BOTTOM, fill=tk.X)

        context_frame = tk.LabelFrame(controller_frame, text='Context')
        context_frame.pack(side=tk.BOTTOM, fill=tk.X)

        self.w_context = tk.Label(context_frame)
        self.w_context.pack(side=tk.BOTTOM, fill=tk.X)

        #

        left_frame = tk.Frame(self)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH)

        # Input frame
        input_frame = tk.LabelFrame(left_frame, text='INPUT BUTTONS')
        input_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Sensor frame
        sensors_frame = tk.LabelFrame(left_frame, text='ACTUATORS')
        sensors_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Add buttons
        self.w_input_power_inc = tk.Button(input_frame,
                                           text='power +',
                                           command=partial(
                                               self.send_event,
                                               event_name='input_power_inc'))
        self.w_input_power_dec = tk.Button(input_frame,
                                           text='power -',
                                           command=partial(
                                               self.send_event,
                                               event_name='input_power_dec'))
        self.w_input_power_reset = tk.Button(
            input_frame,
            text='power 0',
            command=partial(self.send_event, event_name='input_power_reset'))

        self.w_input_timer_inc = tk.Button(input_frame,
                                           text='timer +',
                                           command=partial(
                                               self.send_event,
                                               event_name='input_timer_inc'))
        self.w_input_timer_dec = tk.Button(input_frame,
                                           text='timer -',
                                           command=partial(
                                               self.send_event,
                                               event_name='input_timer_dec'))
        self.w_input_timer_reset = tk.Button(
            input_frame,
            text='timer 0',
            command=partial(self.send_event, event_name='input_timer_reset'))

        self.w_input_cooking_start = tk.Button(
            input_frame,
            text='start',
            command=partial(self.send_event, event_name='input_cooking_start'))
        self.w_input_cooking_stop = tk.Button(
            input_frame,
            text='stop',
            command=partial(self.send_event, event_name='input_cooking_stop'))

        self.w_tick = tk.Button(sensors_frame,
                                text='tick',
                                command=partial(self.send_event,
                                                event_name='timer_tick'))
        self.v_autotick = tk.BooleanVar()
        self.v_autotick.set(True)
        self.w_autotick = tk.Checkbutton(sensors_frame,
                                         text='Auto-tick',
                                         var=self.v_autotick,
                                         command=self.on_autotick)

        self.w_item_placed = tk.Button(sensors_frame,
                                       text='place item',
                                       command=partial(
                                           self.send_event,
                                           event_name='item_placed'))
        self.w_item_removed = tk.Button(sensors_frame,
                                        text='remove item',
                                        command=partial(
                                            self.send_event,
                                            event_name='item_removed'))

        self.w_door_opened = tk.Button(sensors_frame,
                                       text='open door',
                                       command=partial(
                                           self.send_event,
                                           event_name='door_opened'))
        self.w_door_closed = tk.Button(sensors_frame,
                                       text='close door',
                                       command=partial(
                                           self.send_event,
                                           event_name='door_closed'))

        # Pack
        self.w_input_power_inc.pack(side=tk.TOP, fill=tk.X)
        self.w_input_power_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_input_power_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_input_timer_inc.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))
        self.w_input_timer_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_input_timer_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_input_cooking_start.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))
        self.w_input_cooking_stop.pack(side=tk.TOP, fill=tk.X)

        self.w_autotick.pack(side=tk.TOP, fill=tk.X)
        self.w_tick.pack(side=tk.TOP, fill=tk.X)

        self.w_item_placed.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))
        self.w_item_removed.pack(side=tk.TOP, fill=tk.X)

        self.w_door_opened.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))
        self.w_door_closed.pack(side=tk.TOP, fill=tk.X)

        right_frame = tk.LabelFrame(self, text='COMPONENTS')
        right_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Door component
        self.w_doorsensor_frame = tk.LabelFrame(right_frame, text='Door')
        self.w_doorsensor_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_doorsensor = tk.Label(self.w_doorsensor_frame)
        self.w_doorsensor.config(text='closed')
        self.w_doorsensor.pack(side=tk.TOP)

        # Weightsensor component
        self.w_weightsensor_frame = tk.LabelFrame(right_frame,
                                                  text='Weight sensor')
        self.w_weightsensor_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_weightsensor = tk.Label(self.w_weightsensor_frame)
        self.w_weightsensor.config(text='no item')
        self.w_weightsensor.pack(side=tk.TOP)

        # Display component
        self.w_display_frame = tk.LabelFrame(right_frame, text='Display')
        self.w_display_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_display = tk.Label(self.w_display_frame)
        self.w_display.pack(side=tk.TOP)

        # Lamp component
        self.w_lamp_frame = tk.LabelFrame(right_frame, text='Lamp')
        self.w_lamp_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_lamp = tk.Label(self.w_lamp_frame)
        self.w_lamp.pack(side=tk.TOP)

        # Heating component
        self.w_heating_frame = tk.LabelFrame(right_frame, text='Heating')
        self.w_heating_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_heating_power = tk.Label(self.w_heating_frame)
        self.w_heating_status = tk.Label(self.w_heating_frame)
        self.w_heating_power.pack(side=tk.TOP)
        self.w_heating_status.pack(side=tk.TOP)

        # Beeper component
        self.w_beep_frame = tk.LabelFrame(right_frame, text='Beeper')
        self.w_beep_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_beep = tk.Label(self.w_beep_frame)
        self.w_beep.pack(side=tk.TOP)

        # Turntable component
        self.w_turntable_frame = tk.LabelFrame(right_frame, text='Turntable')
        self.w_turntable_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_turntable = tk.Label(self.w_turntable_frame)
        self.w_turntable.pack(side=tk.TOP)

    def event_handler(self, event):
        name = event.name

        if name == 'lamp_switch_on':
            self.w_lamp['text'] = 'on'
        elif name == 'lamp_switch_off':
            self.w_lamp['text'] = 'off'
        elif name == 'display_set':
            self.w_display['text'] = event.text
        elif name == 'display_clear':
            self.w_display['text'] = ''
        elif name == 'heating_set_power':
            self.w_heating_power['text'] = event.power
        elif name == 'heating_on':
            self.w_heating_status['text'] = 'on'
        elif name == 'heating_off':
            self.w_heating_status['text'] = 'off'
        elif name == 'beep':
            self.w_beep['text'] = event.number
        elif name == 'turntable_start':
            self.w_turntable['text'] = 'on'
        elif name == 'turntable_stop':
            self.w_turntable['text'] = 'off'
        else:
            raise ValueError('Unknown event %s' % event)

    def on_autotick(self):
        if self.v_autotick.get():
            self.send_event('timer_tick')
            self.after(1000, self.on_autotick)

    def send_event(self, event_name):
        if event_name == 'item_placed':
            self.w_weightsensor.config(text='item detected')
        elif event_name == 'item_removed':
            self.w_weightsensor.config(text='no item')
        elif event_name == 'door_opened':
            self.w_doorsensor.config(text='open')
        elif event_name == 'door_closed':
            self.w_doorsensor.config(text='closed')

        self.interpreter.queue(Event(event_name))
        self.execute()

    def _quit(self):
        self.master.destroy()