Exemplo n.º 1
0
class LewisControlClientDevice(DeviceMixinBase):
    parameters = {
        'host':
        Param('HOST:PORT string for JSON-RPC connection.',
              type=host,
              settable=False,
              mandatory=True),
        'remoteobj':
        Param('Name of remote object to mirror.',
              type=str,
              settable=False,
              mandatory=True,
              userparam=False)
    }

    _client = None
    _obj = None

    def doPreinit(self, mode):
        if mode != SIMULATION:
            host, port = self.host.split(':')
            self._client = ControlClient(host, port)
            remote_objects = self._client.get_object_collection()

            if self.remoteobj not in remote_objects.keys():
                raise ConfigurationError('No such object on {}: {}'.format(
                    self.host, self.remoteobj))

            self._obj = remote_objects[self.remoteobj]
    def test_get_remote_object_collection(self, mock_socket):
        client = ControlClient(host='127.0.0.1', port='10001')

        returned_object = Mock()
        returned_object.get_objects = Mock(return_value=['obj1', 'obj2'])

        with patch.object(client, 'get_object') as get_object_mock:
            get_object_mock.side_effect = [
                returned_object, 'obj1_object', 'obj2_object'
            ]

            objects = client.get_object_collection()

            self.assertTrue('obj1' in objects)
            self.assertTrue('obj2' in objects)

            returned_object.get_objects.assert_has_calls([call()])
            get_object_mock.assert_has_calls(
                [call(''), call('obj1'), call('obj2')])
    def test_get_remote_object_collection(self, mock_socket):
        client = ControlClient(host='127.0.0.1', port='10001')

        returned_object = Mock()
        returned_object.get_objects = Mock(return_value=['obj1', 'obj2'])

        with patch.object(client, 'get_object') as get_object_mock:
            get_object_mock.side_effect = [returned_object, 'obj1_object', 'obj2_object']

            objects = client.get_object_collection()

            self.assertTrue('obj1' in objects)
            self.assertTrue('obj2' in objects)

            returned_object.get_objects.assert_has_calls([call()])
            get_object_mock.assert_has_calls(
                [call(''),
                 call('obj1'),
                 call('obj2')])
Exemplo n.º 4
0
    def test_get_remote_object_collection(self, mock_socket):
        client = ControlClient(host="127.0.0.1", port="10001")

        returned_object = Mock()
        returned_object.get_objects = Mock(return_value=["obj1", "obj2"])

        with patch.object(client, "get_object") as get_object_mock:
            get_object_mock.side_effect = [
                returned_object,
                "obj1_object",
                "obj2_object",
            ]

            objects = client.get_object_collection()

            self.assertTrue("obj1" in objects)
            self.assertTrue("obj2" in objects)

            returned_object.get_objects.assert_has_calls([call()])
            get_object_mock.assert_has_calls(
                [call(""), call("obj1"), call("obj2")])
class LewisLauncher(EmulatorLauncher):
    """
    Launches Lewis.
    """

    _DEFAULT_PY_PATH = os.path.join("C:\\", "Instrument", "Apps", "Python3")
    _DEFAULT_LEWIS_PATH = os.path.join(_DEFAULT_PY_PATH, "scripts")

    def __init__(self, test_name, device, var_dir, port, options):
        """
        Constructor that also launches Lewis.

        Args:
            test_name: name of test we are creating device emulator for
            device: device to start
            var_dir: location of directory to write log file and macros directories
            port: the port to use
        """
        super(LewisLauncher, self).__init__(test_name, device, var_dir, port,
                                            options)

        self._lewis_path = options.get("lewis_path",
                                       LewisLauncher._DEFAULT_LEWIS_PATH)
        self._python_path = options.get(
            "python_path",
            os.path.join(LewisLauncher._DEFAULT_PY_PATH, "python.exe"))
        self._lewis_protocol = options.get("lewis_protocol", "stream")
        self._lewis_additional_path = options.get("lewis_additional_path",
                                                  DEVICE_EMULATOR_PATH)
        self._lewis_package = options.get("lewis_package", "lewis_emulators")
        self._default_timeout = options.get("default_timeout", 5)
        self._speed = options.get("speed", 100)

        self._process = None
        self._logFile = None
        self._connected = None

    def _close(self):
        """
        Closes the Lewis session by killing the process.
        """
        print("Terminating Lewis")
        if self._process is not None:
            self._process.terminate()
        if self._logFile is not None:
            self._logFile.close()
            print("Lewis log written to {0}".format(self._log_filename()))

    def _open(self):
        """
        Start the lewis emulator.

        :param port: the port on which to run lewis
        :return:
        """

        self._control_port = str(get_free_ports(1)[0])
        lewis_command_line = [
            self._python_path, "-m", "lewis", "-r",
            "127.0.0.1:{control_port}".format(control_port=self._control_port)
        ]
        lewis_command_line.extend([
            "-p",
            "{protocol}: {{bind_address: 127.0.0.1, port: {port}}}".format(
                protocol=self._lewis_protocol, port=self._port)
        ])
        if self._lewis_additional_path is not None:
            lewis_command_line.extend(["-a", self._lewis_additional_path])
        if self._lewis_package is not None:
            lewis_command_line.extend(["-k", self._lewis_package])

        # Set lewis speed
        lewis_command_line.extend(["-e", str(self._speed), self._device])

        print("Starting Lewis")
        self._logFile = open(self._log_filename(), "w")
        self._logFile.write("Started Lewis with '{0}'\n".format(
            " ".join(lewis_command_line)))

        self._process = subprocess.Popen(
            lewis_command_line,
            creationflags=subprocess.CREATE_NEW_CONSOLE,
            stdout=self._logFile,
            stderr=subprocess.STDOUT)
        self._connected = True

        self.remote = ControlClient("127.0.0.1", self._control_port)

    def _log_filename(self):
        return log_filename(self._test_name, "lewis", self._emulator_id, False,
                            self._var_dir)

    def check(self):
        """
        Check that the lewis emulator is running.

        :return: True if it is running; False otherwise
        """
        if self._process.poll() is None:
            return True
        print("Lewis has terminated! It said:")
        stdoutdata, stderrdata = self._process.communicate()
        sys.stderr.write(stderrdata)
        sys.stdout.write(stdoutdata)
        return False

    def _convert_to_string_for_backdoor(self, value):
        """
        Convert the value given to a string for the backdoor. If the type is a string suround with quotes otherwise
        pass it raw, e.g. for a number.
        Args:
            value: value to convert

        Returns: value as a string for the backdoor

        """
        return "'{}'".format(value) if isinstance(value, str) else str(value)

    def backdoor_set_on_device(self, variable_name, value, *_, **__):
        """
        Set a value in the device using the lewis backdoor.

        :param variable_name: name of variable to set
        :param value: new value it should have
        :return:
        """
        self.backdoor_command([
            "device",
            str(variable_name),
            self._convert_to_string_for_backdoor(value)
        ])

    def backdoor_run_function_on_device(self, function_name, arguments=None):
        """
        Run a function in lewis using the back door on a device.

        :param function_name: name of the function to call
        :param arguments: an iterable of the arguments for the function; None means no arguments. Arguments will
            automatically be turned into json
        :return:
        """
        command = ["device", function_name]
        if arguments is not None:
            command.extend([
                self._convert_to_string_for_backdoor(argument)
                for argument in arguments
            ])

        return self.backdoor_command(command)

    def backdoor_command(self, lewis_command):
        """
        Send a command to the backdoor of lewis.

        :param lewis_command: array of command line arguments to send
        :return: lines from the command output
        """
        try:
            return call_method(self.remote.get_object_collection(),
                               lewis_command[0], lewis_command[1],
                               lewis_command[2:])
        except Exception as e:
            sys.stderr.write(f"Error using backdoor: {e}\n")

    def backdoor_emulator_disconnect_device(self):
        """
        Disconnect the emulated device.

        :return:
        """
        if self._connected:
            self.backdoor_command(["simulation", "disconnect_device"])
        self._connected = False

    def backdoor_emulator_connect_device(self):
        """
        Connect the emulated device.

        :return:
        """
        if not self._connected:
            self.backdoor_command(["simulation", "connect_device"])
        self._connected = True

    def backdoor_get_from_device(self, variable_name, *_, **__):
        """
        Return the string of a value on a device from lewis.
        :param variable_name: name of the variable
        :return: the variables value
        """
        # backdoor_command returns a list of bytes and join takes str so convert them here
        return self.backdoor_command(["device", str(variable_name)])