def test_resetting_the_manager_stops_running_scripts(self): robot_mock = create_robot_mock() stopped_mock = Mock() sm = ScriptManager(robot_mock) sm.add_script( ScriptDescriptor( 'test', str_to_func(''' while not ctx.stop_requested: pass '''), 0)) sm.add_script( ScriptDescriptor( 'test2', str_to_func(''' while not ctx.stop_requested: pass '''), 0)) # first call, make sure the script runs sm['test'].on_stopped(stopped_mock) sm['test2'].on_stopped(stopped_mock) sm['test'].start() sm['test2'].start() sm.reset() self.assertEqual(2, stopped_mock.call_count)
def test_script_can_stop_other_scripts(self): robot_mock = create_robot_mock() mock1 = Mock() mock2 = Mock() second_running_evt = Event() sm = ScriptManager(robot_mock) sm.add_script( ScriptDescriptor( 'test1', str_to_func(''' mock() second_running.wait() while not ctx.stop_requested: Control.terminate_all() '''), 0)) sm.add_script( ScriptDescriptor( 'test2', str_to_func(''' second_running.set() mock() while not ctx.stop_requested: time.sleep(0.01) '''), 0)) sm['test1'].assign('mock', mock1) sm['test1'].assign('second_running', second_running_evt) sm['test2'].assign('second_running', second_running_evt) sm['test2'].assign('mock', mock2) try: # first call, make sure the script runs script1_stopped = Event() script2_stopped = Event() sm['test1'].on_stopped(script1_stopped.set) sm['test2'].on_stopped(script2_stopped.set) sm['test1'].start() sm['test2'].start() script1_stopped.wait(1) script2_stopped.wait(1) # scripts started? self.assertEqual(1, mock1.call_count) self.assertEqual(1, mock2.call_count) # scripts stopped? self.assertFalse(sm['test1'].is_running) self.assertFalse(sm['test2'].is_running) finally: sm.reset()
def test_script_can_stop_itself(self): robot_mock = create_robot_mock() cont = Event() mock = Mock() sm = ScriptManager(robot_mock) sm.add_script( ScriptDescriptor( 'test', str_to_func(''' while not ctx.stop_requested: mock() Control.terminate() mock() '''), 0)) sm.assign('mock', mock) sm['test'].on_stopped(cont.set) # first call, make sure the script runs sm['test'].start().wait() if not cont.wait(2): self.fail() sm.reset() self.assertEqual(1, mock.call_count)
def test_overwriting_a_script_stops_the_previous_one(self): robot_mock = create_robot_mock() mock = Mock() stopped_mock = Mock() sm = ScriptManager(robot_mock) sm.add_script( ScriptDescriptor( 'test', str_to_func(''' while not ctx.stop_requested: pass mock()'''), 0)) sm.assign('mock', mock) # first call, make sure the script runs sm['test'].on_stopped(stopped_mock) sm['test'].start() # add second script sm.add_script(ScriptDescriptor('test', str_to_func('mock()'), 0)) # stops the first script # check that the first script ran and was stopped self.assertEqual(1, mock.call_count) self.assertEqual(1, stopped_mock.call_count) # run and check second script sm['test'].on_stopped(stopped_mock) sm['test'].start() # test that stop also stops a script sm['test'].stop() sm['test'].cleanup() self.assertEqual(2, mock.call_count) self.assertEqual(2, stopped_mock.call_count)
def test_crashing_script_calls_stopped_handler(self): robot_mock = create_robot_mock() cont = Event() sm = ScriptManager(robot_mock) sm.add_script( ScriptDescriptor('test', str_to_func('''raise Excepti'''), 0)) sm['test'].on_stopped(cont.set) # first call, make sure the script runs sm['test'].start().wait() if not cont.wait(2): self.fail("Script.on_stopped handler was not called") sm.reset()
def on_message_updated(self, message: ReceivedLongMessage): message_type = message.message_type self._log(f'Received message: {message_type}') if message_type == LongMessageType.TEST_KIT: test_script_source = message.data.decode() self._log(f'Running test script: {test_script_source}') script_descriptor = ScriptDescriptor( "test_kit", str_to_func(test_script_source), 0) def start_script(): self._log("Starting new test script") handle = self._robot._scripts.add_script(script_descriptor) handle.on_stopped(partial(self._robot.configure, None)) # start can't run in on_stopped handler because overwriting script causes deadlock self._robot.run_in_background(handle.start) self._robot.configure(empty_robot_config, start_script) elif message_type == LongMessageType.CONFIGURATION_DATA: message_data = message.data.decode() self._log(f'New configuration: {message_data}') try: parsed_config = RobotConfig.from_string(message_data) if self._ignore_config: self._log('New configuration ignored') else: self._robot.configure(parsed_config, self._robot.start_remote_controller) except ConfigError: self._log(traceback.format_exc()) elif message_type == LongMessageType.FRAMEWORK_DATA: self._robot.robot.status.robot_status = RobotStatus.Updating self._progress.set_indeterminate() self._robot.request_update() elif message_type == LongMessageType.ASSET_DATA: extract_asset_longmessage(self._storage, self._asset_dir)
def test_string_script_can_access_assigned_variables(self): robot_mock = create_robot_mock() mock = Mock() sm = ScriptManager(robot_mock) sm.assign('mock', mock) sm.assign('test', self) sm.assign('RobotInterface', RobotInterface) sm.add_script( ScriptDescriptor( 'test', str_to_func(''' test.assertIsInstance(robot, RobotInterface) mock()'''), 0)) sm['test'].start() sm['test'].cleanup() self.assertEqual(1, mock.call_count)
def test_script_input_dict_is_passed_as_variables(self): robot_mock = create_robot_mock() mock = Mock() sm = ScriptManager(robot_mock) sm.add_script(ScriptDescriptor('test', str_to_func('mock()'), 0)) script = sm['test'] script.start(mock=mock) script.stop().wait(2) self.assertEqual(1, mock.call_count) with self.subTest('Input is not remmebered'): script.start() # mock shall not be called again script.stop().wait(2) self.assertEqual(1, mock.call_count) script.cleanup()
def create_runnable(script): try: script_name = dict_get_first(script, ['builtinScriptName', 'builtinscriptname']) _log(f'Use builtin script: {script_name}') try: return builtin_scripts[script_name] except KeyError as e: raise KeyError(f'Builtin script "{script_name}" does not exist') from e except KeyError: try: source_b64_encoded = dict_get_first(script, ['pythonCode', 'pythoncode']) code = b64_decode_str(source_b64_encoded) _log(f'Use python code as script: {code}') code = code.replace('import time\n', '') return str_to_func(code) except KeyError as e: raise KeyError('Neither builtinScriptName, nor pythonCode is present for a script') from e