def test_submachines_machine(self): states, trans = make_submachines_machine(use_logging=False) hsm = HSM(states, trans) l0_start = get_state_by_sig(('left', 0, 'start'), hsm.flattened) s0_top = get_state_by_sig(('subs', 0, 'top'), hsm.flattened) s1_final = get_state_by_sig(('subs', 1, 'final'), hsm.flattened) tree = tree_from_state_set( set([l0_start, s0_top, s1_final]) ) assert len(tree) == 1 # only one root node assert self.extract_names(tree) == [ ('top', [ ('left', [ ('left[0].top', [ ('left[0].start', []) ]), ]), ('right', [ ('subs', [ ('subs[0].top', []), ('subs[1].top', [ ('subs[1].final', []), ]), ]), ]) ]), ]
def test_with_HSM_instance(self): states = { 'root': State({ 'left': State({ 'left_A': State(), 'left_B': State(), }), 'middle': State({ 'middle_A': State(), 'middle_B': State(), 'middle_C': State(), }), 'right': State({ 'right_A': State({ 'right_A_1': State(), 'deep': State(), 'right_A_2': State(), }), 'right_B': State(), }) }) } flattened = HSM(states, {}, skip_validation=True).flattened left_B = get_state_by_sig(('left_B',), flattened) deep = get_state_by_sig(('deep',), flattened) exits, parent, entries = get_path(deep, left_B) exits = [st.name for st in exits] entries = [st.name for st in entries] assert exits == ['deep', 'right_A', 'right'] assert parent.name == 'root' assert entries == ['left', 'left_B']
def test_miro_machine(self): states, trans = make_miro_machine(use_logging=False) hsm = HSM(states, trans) s1 = get_state_by_sig(('s11',), hsm.flattened) s211 = get_state_by_sig(('s211',), hsm.flattened) tree = tree_from_state_set( set([s1, s211]) ) assert len(tree) == 1 # only one root node assert self.extract_names(tree) == [ ('top', [ ('s', [ ('s1', [ ('s11', []) ]), ('s2', [ ('s21', [ ('s211', []), ]) ]) ]), # ('final', []), # final should NOT be in the tree ]) ]
def check(hsm, state_name, Event, foo_before, foo_expected, expected_leaf_state, expected_exits, expected_entries): mock_hsm = MockHSM() mock_hsm.data.foo = foo_before # state set and expected state set are not specified in the parameters list # so we'll build them on the fly - knowing the leaf states, state set is # path from root to that leaf state state_set = set( get_path_from_root( get_state_by_sig((state_name,), hsm.flattened))) expected_state_set = set( get_path_from_root( get_state_by_sig((expected_leaf_state,), hsm.flattened))) exit_actions, entry_actions, new_state_set = get_merged_sequences( state_set, Event(), hsm.trans, hsm.flattened, mock_hsm) exit_action_names = [str(act) for act in exit_actions] entry_action_names = [str(act) for act in entry_actions] assert exit_action_names == expected_exits assert entry_action_names == expected_entries assert new_state_set == expected_state_set # perform actions to update 'foo' value in mock_hsm.data [exit_act(None, mock_hsm) for exit_act in exit_actions] [entry_act(None, mock_hsm) for entry_act in entry_actions] if foo_expected != _: # only if we care about the value of 'foo' assert mock_hsm.data.foo == foo_expected
def test_after_reformat(self): states = { 'root': State({ 'left': State({ 'left_A': State(), 'left_B': State(), }), 'middle': State({ 'middle_A': State(), 'middle_B': State(), 'middle_C': State(), }), 'right': State({ 'right_A': State({ 'right_A_1': State(), 'right_A_2': State(), }), 'right_B': State(), }) }) } flattened = HSM(states, {}, skip_validation=True).flattened left_A = get_state_by_sig(('left_A',), flattened) left_B = get_state_by_sig(('left_B',), flattened) right_A_1 = get_state_by_sig(('right_A_1',), flattened) right_B = get_state_by_sig(('right_B',), flattened) assert get_common_parent(left_A, left_B).name == 'left' assert get_common_parent(left_A, right_A_1).name == 'root' assert get_common_parent(right_A_1, right_B).name == 'right'
def test_run(self, state_name, Event, foo_before, foo_expected, exp_responding_state, exp_transition_target): mock_hsm = MockHSM() mock_hsm.data.foo = foo_before state = get_state_by_sig((state_name,), self.hsm.flattened) tree = tree_from_state_set(set([state])) resps = get_responses(tree, Event(), self.hsm.trans, mock_hsm) if exp_responding_state is None: assert resps == [] else: assert len(resps) == 1 # no orthogonal regions in this HSM resp_subtrees, trans = zip(*resps) assert resp_subtrees[0][0].name == exp_responding_state tran = trans[0] if exp_transition_target is not None: assert State.sig_to_name(tran.target) == exp_transition_target else: assert tran.target is None tran.action(None, mock_hsm) # this call might change 'foo' value # event is not relevant if foo_expected != 'ignored': assert mock_hsm.data.foo == foo_expected
def test_with_HSM_instance(self): states = { 'root': State({ 'left': State({ 'left_A': State(), 'left_B': State(), }), 'middle': State({ 'middle_A': State(), 'middle_B': State(), 'middle_C': State(), }), 'right': State({ 'right_A': State({ 'right_A_1': State(), 'deep': State(), 'right_A_2': State(), }), 'right_B': State(), }) }) } flattened = HSM(states, {}, skip_validation=True).flattened deep = get_state_by_sig(('deep',), flattened) state_names = [state.name for state in get_path_from_root(deep)] assert state_names == ['root', 'right', 'right_A', 'deep']
def test_enter_right(self): expected_action_names = ['right-entry', 'right-Initial', 'subs-entry', 'subs[0].top-entry', 'subs[0].top-Initial', 'subs[0].start-entry', 'subs[1].top-entry', 'subs[1].top-Initial', 'subs[1].start-entry'] right = get_state_by_sig(('right',), self.hsm.flattened) seq = entry_sequence(right, self.hsm.trans, self.hsm.flattened, self.hsm) assert [str(act) for act in seq] == expected_action_names
def test_enter_B(self): mock = MockHSM() B_state = get_state_by_sig(('B',), self.hsm.flattened) for key in [3, 4, 5, 6, 'blah']: mock.data.foo = key expected_action_names = ['B-entry', 'B-Initial', 'C-entry'] seq = entry_sequence(B_state, self.hsm.trans, self.hsm.flattened, mock) assert [str(act) for act in seq] == expected_action_names
def check(hsm, states, Event, exp_resp_states, exp_tran_targets): state_set = set([get_state_by_sig(sig, hsm.flattened) for sig in states]) tree = tree_from_state_set(state_set) resps = get_responses(tree, Event(), hsm.trans, None) if exp_resp_states or exp_tran_targets: resp_subtrees, trans = zip(*resps) assert len(resp_subtrees) == len(exp_resp_states) resp_sigs = set([st.sig for st, _ in resp_subtrees]) assert resp_sigs == set(exp_resp_states) assert len(trans) == len(exp_tran_targets) target_ids = set([tr.target for tr in trans]) assert target_ids == set(exp_tran_targets) else: assert resps == []
def test_choice(self, states, event, exp_resp_states, exp_tran_targets): state_set = set([get_state_by_sig((name,), self.hsm.flattened) for name in states]) tree = tree_from_state_set(state_set) resps = get_responses(tree, event, self.hsm.trans, None) print resps if exp_resp_states or exp_tran_targets: resp_subtrees, trans = zip(*resps) assert len(resp_subtrees) == len(exp_resp_states) resp_names = set([st.name for st, _ in resp_subtrees]) assert resp_names == set(exp_resp_states) assert len(trans) == len(exp_tran_targets) target_ids = set([State.sig_to_name(tr.target) for tr in trans]) assert target_ids == set(exp_tran_targets) else: assert resps == []
def test_enter_A(self): mock = MockHSM() A_state = get_state_by_sig(('A',), self.hsm.flattened) for key in [1, 3, 4, 5, 6, 'asd']: mock.data.foo = key expected_action_names = ['A-entry', 'A-Initial', 'B-entry', 'C-entry'] seq = entry_sequence(A_state, self.hsm.trans, self.hsm.flattened, mock) assert [str(act) for act in seq] == expected_action_names mock.data.foo = 2 expected_action_names = ['A-entry', 'A-Initial', 'B-entry', 'B-Initial', 'C-entry'] seq = entry_sequence(A_state, self.hsm.trans, self.hsm.flattened, mock) assert [str(act) for act in seq] == expected_action_names
def test_enter_s2(self): expected_action_names = ['s2-entry', 's2-Initial', 's21-entry', 's211-entry'] s2 = get_state_by_sig(('s2',), self.hsm.flattened) seq = entry_sequence(s2, self.hsm.trans, self.hsm.flattened, self.hsm) assert [str(act) for act in seq] == expected_action_names
def assert_curr_state(hsm, leaf_name): """Check that HSM's state set is same as set of states from root to leaf""" exp_set = set( get_path_from_root( get_state_by_sig((leaf_name,), hsm.flattened))) assert hsm.current_state_set == exp_set
def test_get_state_by_sig_in_orthogonal(self): f = lambda tup: get_state_by_sig(tup, self.hsm.flattened) assert f(('ortho',)).sig == ('ortho',) assert f(('ortho', 0, 'sub1')).sig == ('ortho', 0, 'sub1') assert f(('ortho', 1, 'sub2')).sig == ('ortho', 1, 'sub2')
def test_get_state_by_sig(self): f = lambda nice: get_state_by_sig((nice,), self.hsm.flattened) assert f('top').name == 'top' assert f('left').name == 'left' assert f('mid_A').name == 'mid_A' assert f('right_B').name == 'right_B'