def test_preemption_of_all_state_machines_at_once(gui): gui(initialize_global_variables) with pytest.warns(log.RAFCONDeprecationWarning) as deprecations_warnings: from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager import rafcon.gui.singleton as gui_singleton menubar_ctrl = gui_singleton.main_window_controller.get_controller( 'menu_bar_controller') gui( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path( os.path.join("unit_test_state_machines", "all_dialogs_parallel_preempted"))) gui(menubar_ctrl.on_start_activate, None, None) duration_waited = 0. period = 0.1 while not state_machine_execution_engine.finished_or_stopped(): time.sleep(period) duration_waited += period if duration_waited > 3.: gui(menubar_ctrl.on_stop_activate, None, None) raise RuntimeError( "The state machine should finish in less then {0}".format( duration_waited)) print( "Run duration of execute_preemption_of_all_state_machines_at_once was: {0}" .format(duration_waited)) assert len([ record for record in deprecations_warnings if record.category is log.RAFCONDeprecationWarning ]) == 4
def execute_preemption_of_all_state_machines_at_once(): from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager import rafcon.gui.singleton as gui_singleton menubar_ctrl = gui_singleton.main_window_controller.get_controller( 'menu_bar_controller') call_gui_callback( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path( os.path.join("unit_test_state_machines", "all_dialogs_parallel_preempted"))) testing_utils.wait_for_gui() call_gui_callback(menubar_ctrl.on_start_activate, None, None) duration_waited = 0. period = 0.1 while not state_machine_execution_engine.finished_or_stopped(): time.sleep(period) duration_waited += period if duration_waited > 3.: call_gui_callback(menubar_ctrl.on_stop_activate, None, None) raise RuntimeError( "The state machine should finish in less then {0}".format( duration_waited)) print( "Run duration of execute_preemption_of_all_state_machines_at_once was: {0}" .format(duration_waited))
def test_backward_stepping_preemptive_state(gui): gui(initialize_global_variables) from rafcon.core.singleton import state_machine_execution_engine menubar_ctrl = gui.singletons.main_window_controller.menu_bar_controller state_machine = gui( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path(os.path.join("unit_test_state_machines", "backward_step_preemtive_test")) ) testing_utils.wait_for_gui() # reset the synchronization counter; although the tests run in different processes they share their memory # as the import statements are at the top of the file and not inside the parallel called functions with state_machine_execution_engine._status.execution_condition_variable: state_machine_execution_engine.synchronization_counter = 0 gui(menubar_ctrl.on_step_mode_activate, None, None) current_state_machine_id = gui.singletons.state_machine_manager.active_state_machine_id state_machines_editor_tab_status_check(current_state_machine_id, active=True) # execution start is synchronous wait_for_execution_engine_sync_counter(1, logger) # forward for i in range(3): gui(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(2, logger) gui(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) # preemptive concurrency state must be finished before the next step while not state_machine.get_state_by_path("AOURYA/LXEMOO").final_outcome: time.sleep(0.010) gui(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) # "take turn" state reached # backward for i in range(1): gui(menubar_ctrl.on_backward_step_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) for i in range(3): gui(menubar_ctrl.on_backward_step_activate, None, None) wait_for_execution_engine_sync_counter(2, logger) state_machines_editor_tab_status_check(current_state_machine_id, active=True) gui(menubar_ctrl.on_backward_step_activate, None, None) while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) # stop or finished are asynchronous but the call_gui_callback makes the check synchronous gui(state_machines_editor_tab_status_check, current_state_machine_id, False) gui(verify_execute_preemptive_state_forwards_backwards)
def clean_history(self, widget, event=None): """Triggered when the 'Clean History' button is clicked. Empties the execution history tree by adjusting the start index and updates tree store and view. """ self.history_tree_store.clear() selected_sm_m = self.model.get_selected_state_machine_model() if selected_sm_m: # the core may continue running without the GUI and for this it needs its execution histories if state_machine_execution_engine.finished_or_stopped(): selected_sm_m.state_machine.destroy_execution_histories() self.update()
def execute_preemptive_state_forwards_backwards(): from rafcon.core.singleton import state_machine_execution_engine import rafcon.gui.singleton as gui_singleton menubar_ctrl = gui_singleton.main_window_controller.get_controller( 'menu_bar_controller') call_gui_callback( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path( os.path.join("unit_test_state_machines", "backward_step_preemtive_test"))) testing_utils.wait_for_gui() # reset the synchronization counter; although the tests run in different processes they share their memory # as the import statements are at the top of the file and not inside the parallel called functions state_machine_execution_engine.synchronization_lock.acquire() state_machine_execution_engine.synchronization_counter = 0 state_machine_execution_engine.synchronization_lock.release() call_gui_callback(menubar_ctrl.on_step_mode_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) # forward for i in range(3): call_gui_callback(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(2, logger) for i in range(2): call_gui_callback(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) # "take turn" state reached # backward for i in range(1): call_gui_callback(menubar_ctrl.on_backward_step_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) for i in range(3): call_gui_callback(menubar_ctrl.on_backward_step_activate, None, None) wait_for_execution_engine_sync_counter(2, logger) call_gui_callback(menubar_ctrl.on_backward_step_activate, None, None) while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) call_gui_callback(verify_execute_preemptive_state_forwards_backwards) call_gui_callback(menubar_ctrl.on_stop_activate, None)
def start(self, state_machine_id=None, start_state_path=None): assert state_machine_id if not state_machine_execution_engine.finished_or_stopped(): # this is a resume self.set_execution_mode(StateMachineExecutionStatus.STARTED) pass else: self.set_execution_mode(StateMachineExecutionStatus.STARTED) # if the first call of a start is a resume (e.g. if the remote server started and paused the sm) # then setting the active_state_machine_id will fail as during execution it must not be changed # thus we use the protected setter here self.state_machine_manager._active_state_machine_id = state_machine_id if start_state_path: logger.info("Starting state machine on remote server from path {0} ...".format(start_state_path)) protocol = Protocol(MessageType.COMMAND, str(self.status.execution_mode.value) + "@" + start_state_path) self.send_current_execution_mode(protocol) else: logger.info("Starting state machine on remote server ...") self.send_current_execution_mode()
def execute_dynamic_state_insertion(state_machine_name="dynamic_library_insertion"): from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager import rafcon.gui.singleton as gui_singleton menubar_ctrl = gui_singleton.main_window_controller.get_controller('menu_bar_controller') sm = call_gui_callback( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path(os.path.join("unit_test_state_machines", state_machine_name)) ) testing_utils.wait_for_gui() call_gui_callback(menubar_ctrl.on_start_activate, None, None) testing_utils.wait_for_gui() while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) call_gui_callback(menubar_ctrl.on_stop_activate, None)
def test_backward_stepping_library_state(gui): gui(initialize_global_variables) from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager import rafcon.gui.singleton as gui_singleton menubar_ctrl = gui_singleton.main_window_controller.menu_bar_controller sm = gui( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path(os.path.join("unit_test_state_machines", "backward_step_library_execution_test")) ) testing_utils.wait_for_gui() # reset the synchronization counter; although the tests run in different processes they share their memory # as the import statements are at the top of the file and not inside the parallel called functions with state_machine_execution_engine._status.execution_condition_variable: state_machine_execution_engine.synchronization_counter = 0 gui(menubar_ctrl.on_step_mode_activate, None, None) current_state_machine_id = gui_singleton.state_machine_manager.active_state_machine_id state_machines_editor_tab_status_check(current_state_machine_id, active=True) # execution start is synchronous wait_for_execution_engine_sync_counter(1, logger) # forward for i in range(5): gui(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) # backward for i in range(4): gui(menubar_ctrl.on_backward_step_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) gui(menubar_ctrl.on_backward_step_activate, None, None) while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) for key, sd in sm.root_state.scoped_data.items(): if sd.name == "beer_count": assert sd.value == 100 # stop or finished are asynchronous but the call_gui_callback makes the check synchronous gui(state_machines_editor_tab_status_check, current_state_machine_id, False)
def execute_library_state_forwards_backwards(): from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager import rafcon.gui.singleton as gui_singleton menubar_ctrl = gui_singleton.main_window_controller.get_controller( 'menu_bar_controller') call_gui_callback( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path( os.path.join("unit_test_state_machines", "backward_step_library_execution_test"))) testing_utils.wait_for_gui() # reset the synchronization counter; although the tests run in different processes they share their memory # as the import statements are at the top of the file and not inside the parallel called functions state_machine_execution_engine.synchronization_lock.acquire() state_machine_execution_engine.synchronization_counter = 0 state_machine_execution_engine.synchronization_lock.release() call_gui_callback(menubar_ctrl.on_step_mode_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) # forward for i in range(5): call_gui_callback(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) # backward for i in range(4): call_gui_callback(menubar_ctrl.on_backward_step_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) call_gui_callback(menubar_ctrl.on_backward_step_activate, None, None) sm = state_machine_manager.get_active_state_machine() while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) for key, sd in sm.root_state.scoped_data.iteritems(): if sd.name == "beer_count": assert sd.value == 100 call_gui_callback(menubar_ctrl.on_stop_activate, None)
def execute_dynamic_state_insertion(state_machine_name="dynamic_library_insertion"): from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager import rafcon.gui.singleton as gui_singleton menubar_ctrl = gui_singleton.main_window_controller.get_controller('menu_bar_controller') sm = call_gui_callback( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path(os.path.join("unit_test_state_machines", state_machine_name)) ) testing_utils.wait_for_gui() # TODO check -> without call_gui_callback wait_for_gui should be without effect call_gui_callback(menubar_ctrl.on_start_activate, None, None) current_state_machine_id = gui_singleton.state_machine_manager.active_state_machine_id state_machines_editor_tab_status_check(current_state_machine_id, active=True) # execution start is synchronous testing_utils.wait_for_gui() # TODO check -> without call_gui_callback wait_for_gui should be without effect while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) # stop or finished are asynchronous but the call_gui_callback makes the check synchronous call_gui_callback(state_machines_editor_tab_status_check, current_state_machine_id, False)
def on_close_clicked(self, event, state_machine_m, result, force=False): """Triggered when the close button of a state machine tab is clicked Closes state machine if it is saved. Otherwise gives the user the option to 'Close without Saving' or to 'Cancel the Close Operation' :param state_machine_m: The selected state machine model. """ from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager force = True if event is not None and hasattr(event, 'state') \ and event.get_state() & Gdk.ModifierType.SHIFT_MASK \ and event.get_state() & Gdk.ModifierType.CONTROL_MASK else force def remove_state_machine_m(): state_machine_id = state_machine_m.state_machine.state_machine_id if state_machine_id in self.model.state_machine_manager.state_machines: self.model.state_machine_manager.remove_state_machine( state_machine_id) def push_sm_running_dialog(): message_string = "The state machine is still running. Are you sure you want to close?" dialog = RAFCONButtonDialog(message_string, ["Stop and close", "Cancel"], message_type=Gtk.MessageType.QUESTION, parent=self.get_root_window()) response_id = dialog.run() dialog.destroy() if response_id == 1: logger.debug("State machine execution is being stopped") state_machine_execution_engine.stop() state_machine_execution_engine.join() # wait for gui is needed; otherwise the signals related to the execution engine cannot # be processed properly by the state machine under destruction rafcon.gui.utils.wait_for_gui() remove_state_machine_m() return True elif response_id == 2: logger.debug("State machine execution will keep running") return False def push_sm_dirty_dialog(): sm_id = state_machine_m.state_machine.state_machine_id root_state_name = state_machine_m.root_state.state.name message_string = "There are unsaved changes in the state machine '{0}' with id {1}. Do you want to close " \ "the state machine anyway?".format(root_state_name, sm_id) dialog = RAFCONButtonDialog(message_string, ["Close without saving", "Cancel"], message_type=Gtk.MessageType.QUESTION, parent=self.get_root_window()) response_id = dialog.run() dialog.destroy() if response_id == 1: # Close without saving pressed remove_state_machine_m() return True else: logger.debug("Closing of state machine canceled") return False # sm running if not state_machine_execution_engine.finished_or_stopped() and \ state_machine_manager.active_state_machine_id == state_machine_m.state_machine.state_machine_id: return push_sm_running_dialog() # close is forced -> sm not saved elif force: remove_state_machine_m() return True # sm dirty -> save sm request dialog elif state_machine_m.state_machine.marked_dirty: return push_sm_dirty_dialog() else: remove_state_machine_m() return True
def test_backward_stepping_barrier_state(gui): gui(initialize_global_variables) from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager import rafcon.gui.singleton as gui_singleton menubar_ctrl = gui_singleton.main_window_controller.get_controller('menu_bar_controller') sm = gui( menubar_ctrl.on_open_activate, None, None, testing_utils.get_test_sm_path(os.path.join("unit_test_state_machines", "backward_step_barrier_test")) ) testing_utils.wait_for_gui() # reset the synchronization counter; although the tests run in different processes they share their memory # as the import statements are at the top of the file and not inside the parallel called functions with state_machine_execution_engine._status.execution_condition_variable: state_machine_execution_engine.synchronization_counter = 0 gui(menubar_ctrl.on_step_mode_activate, sm.state_machine_id, None) wait_for_execution_engine_sync_counter(1, logger) for i in range(2): gui(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(3, logger) gui(menubar_ctrl.on_step_over_activate, None, None) wait_for_execution_engine_sync_counter(3, logger) gui(menubar_ctrl.on_step_out_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) for i in range(3): gui(menubar_ctrl.on_step_into_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) # backward for i in range(3): gui(menubar_ctrl.on_backward_step_activate, None, None) wait_for_execution_engine_sync_counter(1, logger) print("cp1") for i in range(4): gui(menubar_ctrl.on_backward_step_activate, None, None) wait_for_execution_engine_sync_counter(3, logger) print("cp2") gui(menubar_ctrl.on_backward_step_activate, None, None) print("cp3") while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) print("cp4") testing_utils.wait_for_gui() print("cp5") for key, sd in sm.root_state.scoped_data.items(): if sd.name == "beer_number": assert sd.value == 100 elif sd.name == "wine_number": assert sd.value == 40 elif sd.name == "whiskey_number": assert sd.value == 20 gui.expected_warnings = 3 gui(menubar_ctrl.on_stop_activate, None)
def iter_execution_modes(): """ Test execution modes - The execution history widget should be updated always if a mode is changed and not STARTED - the execution mode change from step mode to pause should not cause a step (change of current active state) - or the opposite from pause to step mode should not cause a step (change of current active state) """ from rafcon.core.singleton import state_machine_execution_engine, state_machine_manager import rafcon.gui.singleton as gui_singleton from rafcon.gui.controllers.menu_bar import MenuBarController from rafcon.gui.controllers.execution_history import ExecutionHistoryTreeController menubar_ctrl = gui_singleton.main_window_controller.get_controller( 'menu_bar_controller') assert isinstance(menubar_ctrl, MenuBarController) execution_history_ctrl = gui_singleton.main_window_controller.get_controller( 'execution_history_ctrl') assert isinstance(execution_history_ctrl, ExecutionHistoryTreeController) testing_utils.call_gui_callback(testing_utils.wait_for_gui) sm, remove_t_id, add_start_state_id = testing_utils.call_gui_callback( create_state_machine) sm_id = testing_utils.call_gui_callback( state_machine_manager.add_state_machine, sm) testing_utils.call_gui_callback(testing_utils.wait_for_gui) sm_m = gui_singleton.state_machine_manager_model.state_machines[sm_id] def wait_for_sync_counter_change_and_wait_for_gui(current_sync_counter): # if current_sync_counter is None: # current_sync_counter = state_machine_execution_engine.synchronization_counter assert current_sync_counter is not None print("##### before {0} #####".format(current_sync_counter)) while current_sync_counter == state_machine_execution_engine.synchronization_counter: time.sleep(0.1) print("##### in wait {0} #####".format( state_machine_execution_engine.synchronization_counter)) print("##### after {0} #####".format( state_machine_execution_engine.synchronization_counter)) testing_utils.call_gui_callback(testing_utils.wait_for_gui) from gtkmvc3.observer import Observer class ActiveStateObserver(Observer): def __init__(self, model): Observer.__init__(self) self.model = model self.observe_model(model) self.last_execution_change_at_state = None def reset(self): self.last_execution_change_at_state = None @Observer.observe("state_machine", after=True) def execution_change(self, model, prop_name, info): from rafcon.gui.utils.notification_overview import NotificationOverview overview = NotificationOverview(info) if overview['method_name'][-1] == 'state_execution_status': # print("CURRENT STATE: {0}".format(overview['model'][-1].state.get_path())) self.last_execution_change_at_state = overview['model'][ -1].state.get_path() execution_observer = call_gui_callback(ActiveStateObserver, sm_m) ############################################################ print( "{0}# EXAMPLE #1: toggle from STEP MODE to PAUSE and back and RUN till finished{0}" .format('\n' + 40 * '#' + '\n')) ############################################################ # check that new execution history is shown in widget number_of_executions_before = len( execution_history_ctrl.history_tree_store) print("history length before: {0}\n".format(number_of_executions_before)) current_sync_counter = state_machine_execution_engine.synchronization_counter testing_utils.call_gui_callback(menubar_ctrl.on_step_mode_activate, None) wait_for_sync_counter_change_and_wait_for_gui(current_sync_counter) number_of_executions_after = len(execution_history_ctrl.history_tree_store) print("history length after1: {0}\n".format(number_of_executions_after)) # Rico's old code: # in the gui this works but here it often fails without sleep; TODO: this cannot be! # i1 = 0. # this while will never work! number_of_executions_before/after hold number copies and no references to numbers! # while not number_of_executions_before + 1 == number_of_executions_after and not i1 > 2.: # time.sleep(0.1) # i1 += 0.1 # print("history length after2: {0}\n".format(number_of_executions_after)) # this must not work! the execution history is not observing the state_machine itself but the execution_engine # and we should not change that for performance reasons! # assert number_of_executions_before + 1 == number_of_executions_after # active state should not change from step mode to pause -> this can cause bad situations with a robot in the loop last_active_state = execution_observer.last_execution_change_at_state print("last active state {0}".format(last_active_state)) testing_utils.call_gui_callback(menubar_ctrl.on_pause_activate, None) testing_utils.call_gui_callback(testing_utils.wait_for_gui) current_active_state = execution_observer.last_execution_change_at_state print("last active state {0}".format(last_active_state)) print("current active state {0} {1}".format( current_active_state, last_active_state == current_active_state)) assert last_active_state == current_active_state # active state should not change from pause to step mode -> this can cause bad situations with a robot in the loop last_active_state = execution_observer.last_execution_change_at_state print("last active state {0}".format(last_active_state)) testing_utils.call_gui_callback(menubar_ctrl.on_step_mode_activate, None) testing_utils.call_gui_callback(testing_utils.wait_for_gui) current_active_state = execution_observer.last_execution_change_at_state print("last active state {0}".format(last_active_state)) print("current active state {0} {1}".format( current_active_state, last_active_state == current_active_state)) assert last_active_state == current_active_state # finish the state machine testing_utils.call_gui_callback(menubar_ctrl.on_start_activate, None) while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) testing_utils.call_gui_callback( testing_utils.wait_for_gui) # propagate securely the stop ############################################################ print("{0}# EXAMPLE #2: RUN root state till finished{0}".format('\n' + 40 * '#' + '\n')) ############################################################ # check that new execution history is shown in widget -> if not shown you may look into the wrong history # Look out! if you want to work with the execution history either trigger a execution command or use reload testing_utils.call_gui_callback(execution_history_ctrl.reload_history, None) number_of_executions_before = len( execution_history_ctrl.history_tree_store) print("history length before: {0}\n".format(number_of_executions_before)) testing_utils.call_gui_callback(menubar_ctrl.on_start_activate, None) while not state_machine_execution_engine.finished_or_stopped(): time.sleep(0.1) testing_utils.call_gui_callback(testing_utils.wait_for_gui) testing_utils.call_gui_callback(execution_history_ctrl.reload_history, None) number_of_executions_after = len(execution_history_ctrl.history_tree_store) print("history length after: {0}\n".format(number_of_executions_after)) assert number_of_executions_before + 1 == number_of_executions_after # REMOVE ONE TRANSITION testing_utils.call_gui_callback(sm_m.root_state.state.remove_transition, remove_t_id) # ############################################################ # TODO uncomment and include into test # print("{0}# EXAMPLE #3: RUN and PAUSE{0}".format('\n' + 40 * '#' + '\n')) # ############################################################ # # check that new execution history is shown in widget -> if not shown you may look into the wrong history # number_of_executions_before = len(execution_history_ctrl.history_tree_store) # print("history length before: {0}\n".format(number_of_executions_before)) # current_sync_counter = state_machine_execution_engine.synchronization_counter # testing_utils.call_gui_callback(menubar_ctrl.on_start_activate, None) # wait_for_sync_counter_change_and_wait_for_gui(current_sync_counter) # # time.sleep(0.5) # TODO why I need this sleeps # testing_utils.call_gui_callback(menubar_ctrl.on_pause_activate, None) # testing_utils.call_gui_callback(testing_utils.wait_for_gui) # time.sleep(0.5) # TODO why I need this sleeps # # number_of_executions_after = len(execution_history_ctrl.history_tree_store) # print("history length after: {0}\n".format(number_of_executions_after)) # # this works currently with the gui but here it often fails # assert number_of_executions_before + 1 == number_of_executions_after # testing_utils.call_gui_callback(menubar_ctrl.on_stop_activate, None) # print("\nSTOPPED FINISHED {0}\n".format(state_machine_execution_engine.finished_or_stopped())) # while not state_machine_execution_engine.finished_or_stopped(): # time.sleep(0.1) # print("\nSTOPPED FINISHED {0}\n".format(state_machine_execution_engine.finished_or_stopped())) # testing_utils.call_gui_callback(testing_utils.wait_for_gui) # propagate securely the stop # print("\nSTOPPED FINISHED {0} {1}\n".format(state_machine_execution_engine.finished_or_stopped(), state_machine_execution_engine)) # time.sleep(0.5) # TODO why I need this sleeps -- and why it is so crazy hard to confirm stop but it is running while next start in next test # # ############################################################ # print("{0}# EXAMPLE #4: RUN and STOP{0}".format('\n' + 40 * '#' + '\n')) # ############################################################ # # check that new execution history is shown in widget -> if not shown you may look into the wrong history # number_of_executions_before = len(execution_history_ctrl.history_tree_store) # print("history length before: {0}\n".format(number_of_executions_before)) # current_sync_counter = state_machine_execution_engine.synchronization_counter # testing_utils.call_gui_callback(menubar_ctrl.on_start_activate, None) # wait_for_sync_counter_change_and_wait_for_gui(current_sync_counter) # number_of_executions_after = len(execution_history_ctrl.history_tree_store) # print("history length after: {0}\n".format(number_of_executions_after)) # testing_utils.call_gui_callback(menubar_ctrl.on_stop_activate, None) # while not state_machine_execution_engine.finished_or_stopped(): # time.sleep(0.1) # testing_utils.call_gui_callback(testing_utils.wait_for_gui) # testing_utils.wait_for_gui() # number_of_executions_after = len(execution_history_ctrl.history_tree_store) # # this works currently with the gui # assert number_of_executions_before + 1 == number_of_executions_after # testing_utils.call_gui_callback(testing_utils.wait_for_gui) ############################################################ print( "{0}# EXAMPLE #5: step mode (step over) with first state hierarchy state {0}" .format('\n' + 40 * '#' + '\n')) ############################################################ # testing_utils.call_gui_callback(sm_m.root_state.state.__setattr__, 'start_state_id', add_start_state_id) testing_utils.call_gui_callback(testing_utils.wait_for_gui) testing_utils.call_gui_callback(execution_observer.reset) # check that execution does a step over even if the first state is a hierarchy state last_active_state = execution_observer.last_execution_change_at_state print("#0 {0}".format(last_active_state)) current_sync_counter = state_machine_execution_engine.synchronization_counter testing_utils.call_gui_callback(menubar_ctrl.on_step_mode_activate, None) wait_for_sync_counter_change_and_wait_for_gui(current_sync_counter) current_active_state = execution_observer.last_execution_change_at_state print("#1 {0}".format(current_active_state)) current_sync_counter = state_machine_execution_engine.synchronization_counter testing_utils.call_gui_callback(menubar_ctrl.on_step_over_activate, None) wait_for_sync_counter_change_and_wait_for_gui(current_sync_counter) after_so1_current_active_state = execution_observer.last_execution_change_at_state print("#2 {0}".format(after_so1_current_active_state)) current_sync_counter = state_machine_execution_engine.synchronization_counter testing_utils.call_gui_callback(menubar_ctrl.on_step_over_activate, None) wait_for_sync_counter_change_and_wait_for_gui(current_sync_counter) after_so2_current_active_state = execution_observer.last_execution_change_at_state print("#3 {0}".format(after_so2_current_active_state)) current_sync_counter = state_machine_execution_engine.synchronization_counter testing_utils.call_gui_callback(menubar_ctrl.on_step_over_activate, None) wait_for_sync_counter_change_and_wait_for_gui(current_sync_counter) after_so3_current_active_state = execution_observer.last_execution_change_at_state print("#4 {0}".format(after_so3_current_active_state)) assert not last_active_state == current_active_state assert len(after_so2_current_active_state.split('/')) == len( after_so1_current_active_state.split('/')) assert len(after_so3_current_active_state.split('/')) == len( after_so2_current_active_state.split('/')) execution_observer.relieve_model(sm_m) return