Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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()
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
    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()
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
    def test_variables_are_passed_to_callable_script_as_args(self):
        robot_mock = create_robot_mock()

        mock = Mock()

        sm = ScriptManager(robot_mock)
        sm.assign('mock', mock)
        sm.assign('test', self)
        sm.assign('RobotInterface', RobotInterface)

        def _script(test, robot, mock, **kwargs):
            test.assertIsInstance(robot, RobotInterface)
            mock()

        sm.add_script(ScriptDescriptor('test', _script, 0))

        sm['test'].start()
        sm['test'].cleanup()

        self.assertEqual(1, mock.call_count)
Exemplo n.º 8
0
    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)
Exemplo n.º 9
0
    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()
Exemplo n.º 10
0
    def from_string(config_string):
        try:
            json_config = json.loads(config_string)
        except JSONDecodeError as e:
            raise ConfigError('Received configuration is not a valid json string') from e

        config = RobotConfig()
        try:
            robot_config = dict_get_first(json_config, ['robotConfig', 'robotconfig'])
            blockly_list = dict_get_first(json_config, ['blocklyList', 'blocklylist'])
        except KeyError as e:
            raise ConfigError('Received configuration is missing required parts') from e

        try:
            i = 0
            for script in blockly_list:
                _log(f'Processing script #{i}')
                runnable = RobotConfig.create_runnable(script)

                assignments = script['assignments']
                # script names are mostly relevant for logging
                if 'analog' in assignments:
                    for analog_assignment in assignments['analog']:
                        channels = ', '.join(map(str, analog_assignment['channels']))
                        script_name = f'[script {i}] analog channels {channels}'
                        priority = analog_assignment['priority']
                        config.controller.analog.append({
                            'channels': analog_assignment['channels'],
                            'script': ScriptDescriptor(script_name, runnable, priority)})
                        i += 1

                if 'buttons' in assignments:
                    for button_assignment in assignments['buttons']:
                        button_id = button_assignment['id']
                        script_name = f'[script {i}] button {button_id}'
                        priority = button_assignment['priority']
                        config.controller.buttons[button_id] = ScriptDescriptor(script_name, runnable, priority)
                        i += 1

                if 'background' in assignments:
                    script_name = f'[script {i}] background'
                    priority = assignments['background']
                    config.background_scripts.append(ScriptDescriptor(script_name, runnable, priority))
                    i += 1
        except (TypeError, IndexError, KeyError, ValueError) as e:
            raise ConfigError('Failed to decode received controller configuration') from e

        try:
            i = 1
            motors = robot_config.get('motors', []) if type(robot_config) is dict else []
            for motor in motors:
                if not motor:
                    motor = {'type': 0}

                if motor['type'] == 2:
                    # drivetrain
                    motor_type = motor_types[2][motor['side']][motor['reversed']]
                    config.drivetrain[motor_sides[motor['side']]].append(i)

                else:
                    motor_type = motor_types[motor['type']]

                if motor_type is not None:
                    config.motors.names[motor['name']] = i

                config.motors[i] = motor_type
                i += 1
        except (TypeError, IndexError, KeyError, ValueError) as e:
            raise ConfigError('Failed to decode received motor configuration') from e

        try:
            i = 1
            sensors = robot_config.get('sensors', []) if type(robot_config) is dict else []
            for sensor in sensors:
                if not sensor:
                    sensor = {'type': 0}

                sensor_type = sensor_types[sensor['type']]

                if sensor_type is not None:
                    config.sensors.names[sensor['name']] = i

                config.sensors[i] = sensor_type
                i += 1

        except (TypeError, IndexError, KeyError, ValueError) as e:
            raise ConfigError('Failed to decode received sensor configuration') from e

        return config