Use constants for runner state machine event names
Instead of using strings it is better if we can use constants (that may be the same/adjusted strings) and use those instead in the state machine used in the runner. The names are adjusted (and the state graph diagram and docstring) to reflect names that fit better with there intended meaning and usage. Change-Id: Iaf229d6e37730545ba9f2708d118697cb7145992
This commit is contained in:

committed by
Joshua Harlow

parent
4561710908
commit
1ed0f22fd3
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
@@ -27,6 +27,17 @@ _UNDEFINED = 'UNDEFINED'
|
|||||||
_GAME_OVER = 'GAME_OVER'
|
_GAME_OVER = 'GAME_OVER'
|
||||||
_META_STATES = (_GAME_OVER, _UNDEFINED)
|
_META_STATES = (_GAME_OVER, _UNDEFINED)
|
||||||
|
|
||||||
|
# Event name constants the state machine uses.
|
||||||
|
_SCHEDULE = 'schedule_next'
|
||||||
|
_WAIT = 'wait_finished'
|
||||||
|
_ANALYZE = 'examine_finished'
|
||||||
|
_FINISH = 'completed'
|
||||||
|
_FAILED = 'failed'
|
||||||
|
_SUSPENDED = 'suspended'
|
||||||
|
_SUCCESS = 'success'
|
||||||
|
_REVERTED = 'reverted'
|
||||||
|
_START = 'start'
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -45,25 +56,25 @@ class _MachineBuilder(object):
|
|||||||
|
|
||||||
NOTE(harlowja): the machine states that this build will for are::
|
NOTE(harlowja): the machine states that this build will for are::
|
||||||
|
|
||||||
+--------------+-----------+------------+----------+---------+
|
+--------------+------------------+------------+----------+---------+
|
||||||
Start | Event | End | On Enter | On Exit
|
Start | Event | End | On Enter | On Exit
|
||||||
+--------------+-----------+------------+----------+---------+
|
+--------------+------------------+------------+----------+---------+
|
||||||
ANALYZING | finished | GAME_OVER | |
|
ANALYZING | completed | GAME_OVER | |
|
||||||
ANALYZING | schedule | SCHEDULING | |
|
ANALYZING | schedule_next | SCHEDULING | |
|
||||||
ANALYZING | wait | WAITING | |
|
ANALYZING | wait_finished | WAITING | |
|
||||||
FAILURE[$] | | | |
|
FAILURE[$] | | | |
|
||||||
GAME_OVER | failed | FAILURE | |
|
GAME_OVER | failed | FAILURE | |
|
||||||
GAME_OVER | reverted | REVERTED | |
|
GAME_OVER | reverted | REVERTED | |
|
||||||
GAME_OVER | success | SUCCESS | |
|
GAME_OVER | success | SUCCESS | |
|
||||||
GAME_OVER | suspended | SUSPENDED | |
|
GAME_OVER | suspended | SUSPENDED | |
|
||||||
RESUMING | schedule | SCHEDULING | |
|
RESUMING | schedule_next | SCHEDULING | |
|
||||||
REVERTED[$] | | | |
|
REVERTED[$] | | | |
|
||||||
SCHEDULING | wait | WAITING | |
|
SCHEDULING | wait_finished | WAITING | |
|
||||||
SUCCESS[$] | | | |
|
SUCCESS[$] | | | |
|
||||||
SUSPENDED[$] | | | |
|
SUSPENDED[$] | | | |
|
||||||
UNDEFINED[^] | start | RESUMING | |
|
UNDEFINED[^] | start | RESUMING | |
|
||||||
WAITING | analyze | ANALYZING | |
|
WAITING | examine_finished | ANALYZING | |
|
||||||
+--------------+-----------+------------+----------+---------+
|
+--------------+------------------+------------+----------+---------+
|
||||||
|
|
||||||
Between any of these yielded states (minus ``GAME_OVER`` and ``UNDEFINED``)
|
Between any of these yielded states (minus ``GAME_OVER`` and ``UNDEFINED``)
|
||||||
if the engine has been suspended or the engine has failed (due to a
|
if the engine has been suspended or the engine has failed (due to a
|
||||||
@@ -90,17 +101,17 @@ class _MachineBuilder(object):
|
|||||||
def resume(old_state, new_state, event):
|
def resume(old_state, new_state, event):
|
||||||
memory.next_nodes.update(self._completer.resume())
|
memory.next_nodes.update(self._completer.resume())
|
||||||
memory.next_nodes.update(self._analyzer.get_next_nodes())
|
memory.next_nodes.update(self._analyzer.get_next_nodes())
|
||||||
return 'schedule'
|
return _SCHEDULE
|
||||||
|
|
||||||
def game_over(old_state, new_state, event):
|
def game_over(old_state, new_state, event):
|
||||||
if memory.failures:
|
if memory.failures:
|
||||||
return 'failed'
|
return _FAILED
|
||||||
if self._analyzer.get_next_nodes():
|
if self._analyzer.get_next_nodes():
|
||||||
return 'suspended'
|
return _SUSPENDED
|
||||||
elif self._analyzer.is_success():
|
elif self._analyzer.is_success():
|
||||||
return 'success'
|
return _SUCCESS
|
||||||
else:
|
else:
|
||||||
return 'reverted'
|
return _REVERTED
|
||||||
|
|
||||||
def schedule(old_state, new_state, event):
|
def schedule(old_state, new_state, event):
|
||||||
if self.runnable() and memory.next_nodes:
|
if self.runnable() and memory.next_nodes:
|
||||||
@@ -111,7 +122,7 @@ class _MachineBuilder(object):
|
|||||||
if failures:
|
if failures:
|
||||||
memory.failures.extend(failures)
|
memory.failures.extend(failures)
|
||||||
memory.next_nodes.clear()
|
memory.next_nodes.clear()
|
||||||
return 'wait'
|
return _WAIT
|
||||||
|
|
||||||
def wait(old_state, new_state, event):
|
def wait(old_state, new_state, event):
|
||||||
# TODO(harlowja): maybe we should start doing 'yield from' this
|
# TODO(harlowja): maybe we should start doing 'yield from' this
|
||||||
@@ -122,7 +133,7 @@ class _MachineBuilder(object):
|
|||||||
timeout)
|
timeout)
|
||||||
memory.done.update(done)
|
memory.done.update(done)
|
||||||
memory.not_done = not_done
|
memory.not_done = not_done
|
||||||
return 'analyze'
|
return _ANALYZE
|
||||||
|
|
||||||
def analyze(old_state, new_state, event):
|
def analyze(old_state, new_state, event):
|
||||||
next_nodes = set()
|
next_nodes = set()
|
||||||
@@ -145,11 +156,11 @@ class _MachineBuilder(object):
|
|||||||
next_nodes.update(more_nodes)
|
next_nodes.update(more_nodes)
|
||||||
if self.runnable() and next_nodes and not memory.failures:
|
if self.runnable() and next_nodes and not memory.failures:
|
||||||
memory.next_nodes.update(next_nodes)
|
memory.next_nodes.update(next_nodes)
|
||||||
return 'schedule'
|
return _SCHEDULE
|
||||||
elif memory.not_done:
|
elif memory.not_done:
|
||||||
return 'wait'
|
return _WAIT
|
||||||
else:
|
else:
|
||||||
return 'finished'
|
return _FINISH
|
||||||
|
|
||||||
def on_exit(old_state, event):
|
def on_exit(old_state, event):
|
||||||
LOG.debug("Exiting old state '%s' in response to event '%s'",
|
LOG.debug("Exiting old state '%s' in response to event '%s'",
|
||||||
@@ -178,23 +189,23 @@ class _MachineBuilder(object):
|
|||||||
m.add_state(st.WAITING, **watchers)
|
m.add_state(st.WAITING, **watchers)
|
||||||
m.add_state(st.FAILURE, terminal=True, **watchers)
|
m.add_state(st.FAILURE, terminal=True, **watchers)
|
||||||
|
|
||||||
m.add_transition(_GAME_OVER, st.REVERTED, 'reverted')
|
m.add_transition(_GAME_OVER, st.REVERTED, _REVERTED)
|
||||||
m.add_transition(_GAME_OVER, st.SUCCESS, 'success')
|
m.add_transition(_GAME_OVER, st.SUCCESS, _SUCCESS)
|
||||||
m.add_transition(_GAME_OVER, st.SUSPENDED, 'suspended')
|
m.add_transition(_GAME_OVER, st.SUSPENDED, _SUSPENDED)
|
||||||
m.add_transition(_GAME_OVER, st.FAILURE, 'failed')
|
m.add_transition(_GAME_OVER, st.FAILURE, _FAILED)
|
||||||
m.add_transition(_UNDEFINED, st.RESUMING, 'start')
|
m.add_transition(_UNDEFINED, st.RESUMING, _START)
|
||||||
m.add_transition(st.ANALYZING, _GAME_OVER, 'finished')
|
m.add_transition(st.ANALYZING, _GAME_OVER, _FINISH)
|
||||||
m.add_transition(st.ANALYZING, st.SCHEDULING, 'schedule')
|
m.add_transition(st.ANALYZING, st.SCHEDULING, _SCHEDULE)
|
||||||
m.add_transition(st.ANALYZING, st.WAITING, 'wait')
|
m.add_transition(st.ANALYZING, st.WAITING, _WAIT)
|
||||||
m.add_transition(st.RESUMING, st.SCHEDULING, 'schedule')
|
m.add_transition(st.RESUMING, st.SCHEDULING, _SCHEDULE)
|
||||||
m.add_transition(st.SCHEDULING, st.WAITING, 'wait')
|
m.add_transition(st.SCHEDULING, st.WAITING, _WAIT)
|
||||||
m.add_transition(st.WAITING, st.ANALYZING, 'analyze')
|
m.add_transition(st.WAITING, st.ANALYZING, _ANALYZE)
|
||||||
|
|
||||||
m.add_reaction(_GAME_OVER, 'finished', game_over)
|
m.add_reaction(_GAME_OVER, _FINISH, game_over)
|
||||||
m.add_reaction(st.ANALYZING, 'analyze', analyze)
|
m.add_reaction(st.ANALYZING, _ANALYZE, analyze)
|
||||||
m.add_reaction(st.RESUMING, 'start', resume)
|
m.add_reaction(st.RESUMING, _START, resume)
|
||||||
m.add_reaction(st.SCHEDULING, 'schedule', schedule)
|
m.add_reaction(st.SCHEDULING, _SCHEDULE, schedule)
|
||||||
m.add_reaction(st.WAITING, 'wait', wait)
|
m.add_reaction(st.WAITING, _WAIT, wait)
|
||||||
|
|
||||||
m.freeze()
|
m.freeze()
|
||||||
return (m, memory)
|
return (m, memory)
|
||||||
@@ -231,7 +242,7 @@ class Runner(object):
|
|||||||
def run_iter(self, timeout=None):
|
def run_iter(self, timeout=None):
|
||||||
"""Runs the nodes using a built state machine."""
|
"""Runs the nodes using a built state machine."""
|
||||||
machine, memory = self.builder.build(timeout=timeout)
|
machine, memory = self.builder.build(timeout=timeout)
|
||||||
for (_prior_state, new_state) in machine.run_iter('start'):
|
for (_prior_state, new_state) in machine.run_iter(_START):
|
||||||
# NOTE(harlowja): skip over meta-states.
|
# NOTE(harlowja): skip over meta-states.
|
||||||
if new_state not in _META_STATES:
|
if new_state not in _META_STATES:
|
||||||
if new_state == st.FAILURE:
|
if new_state == st.FAILURE:
|
||||||
|
@@ -41,6 +41,12 @@ class DummyRuntime(object):
|
|||||||
self.storage = None
|
self.storage = None
|
||||||
|
|
||||||
|
|
||||||
|
def clean_event(name):
|
||||||
|
name = name.replace("_", " ")
|
||||||
|
name = name.strip()
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
def make_machine(start_state, transitions, disallowed):
|
def make_machine(start_state, transitions, disallowed):
|
||||||
machine = fsm.FSM(start_state)
|
machine = fsm.FSM(start_state)
|
||||||
machine.add_state(start_state)
|
machine.add_state(start_state)
|
||||||
@@ -129,6 +135,7 @@ def main():
|
|||||||
}
|
}
|
||||||
nodes = {}
|
nodes = {}
|
||||||
for (start_state, on_event, end_state) in source:
|
for (start_state, on_event, end_state) in source:
|
||||||
|
on_event = clean_event(on_event)
|
||||||
if start_state not in nodes:
|
if start_state not in nodes:
|
||||||
start_node_attrs = node_attrs.copy()
|
start_node_attrs = node_attrs.copy()
|
||||||
text_color = map_color(internal_states, start_state)
|
text_color = map_color(internal_states, start_state)
|
||||||
@@ -145,7 +152,7 @@ def main():
|
|||||||
g.add_node(nodes[end_state])
|
g.add_node(nodes[end_state])
|
||||||
if options.engines:
|
if options.engines:
|
||||||
edge_attrs = {
|
edge_attrs = {
|
||||||
'label': "on %s" % on_event
|
'label': on_event,
|
||||||
}
|
}
|
||||||
if 'reverted' in on_event:
|
if 'reverted' in on_event:
|
||||||
edge_attrs['fontcolor'] = 'darkorange'
|
edge_attrs['fontcolor'] = 'darkorange'
|
||||||
|
Reference in New Issue
Block a user