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_json_rpc(self, mock_socket, mock_uuid): mock_uuid.return_value = '2' connection = ControlClient(host='127.0.0.1', port='10001') connection.json_rpc('foo') mock_socket.assert_has_calls( [call(), call().connect('tcp://127.0.0.1:10001'), call().send_json({'method': 'foo', 'params': (), 'jsonrpc': '2.0', 'id': '2'}), call().recv_json()])
def test_get_remote_object_works(self, mock_socket): client = ControlClient(host='127.0.0.1', port='10001') with patch.object(client, 'json_rpc') as json_rpc_mock: json_rpc_mock.return_value = ({'id': 2, 'result': {'class': 'Test', 'methods': ['a:set', 'a:get', 'setTest']}}, 2) obj = client.get_object() self.assertTrue(hasattr(type(obj), 'a')) self.assertTrue(hasattr(obj, 'setTest')) json_rpc_mock.assert_has_calls([call(':api')])
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_zmq_socket_uses_timeout(self, mock_zmq_context): timeout = 100 ControlClient(host="127.0.0.1", port="10002", timeout=timeout) mock_zmq_context.assert_has_calls([ call().setsockopt(zmq.SNDTIMEO, timeout), call().setsockopt(zmq.RCVTIMEO, timeout), ])
def testjson_rpc(self, mock_socket, mock_uuid): mock_uuid.return_value = '2' connection = ControlClient(host='127.0.0.1', port='10001') connection.json_rpc('foo') mock_socket.assert_has_calls([ call(), call().connect('tcp://127.0.0.1:10001'), call().send_json({ 'method': 'foo', 'params': (), 'jsonrpc': '2.0', 'id': '2' }), call().recv_json() ])
def test_json_rpc(self, mock_socket, mock_uuid): mock_uuid.return_value = "2" connection = ControlClient(host="127.0.0.1", port="10001") connection.json_rpc("foo") mock_socket.assert_has_calls([ call(), call().connect("tcp://127.0.0.1:10001"), call().send_json({ "method": "foo", "params": (), "jsonrpc": "2.0", "id": "2" }), call().recv_json(), ])
def test_get_remote_object_raises_exception(self, mock_socket): client = ControlClient(host="127.0.0.1", port="10001") with patch.object(client, "json_rpc") as json_rpc_mock: json_rpc_mock.return_value = ({"id": 2}, 2) self.assertRaises(ProtocolException, client.get_object) json_rpc_mock.assert_has_calls([call(":api")])
def test_get_remote_object_raises_exception(self, mock_socket): client = ControlClient(host='127.0.0.1', port='10001') with patch.object(client, 'json_rpc') as json_rpc_mock: json_rpc_mock.return_value = ({'id': 2}, 2) self.assertRaises(ProtocolException, client.get_object) json_rpc_mock.assert_has_calls([call(':api')])
def test_get_remote_object_works(self, mock_socket): client = ControlClient(host='127.0.0.1', port='10001') with patch.object(client, 'json_rpc') as json_rpc_mock: json_rpc_mock.return_value = ({ 'id': 2, 'result': { 'class': 'Test', 'methods': ['a:set', 'a:get', 'setTest'] } }, 2) obj = client.get_object() self.assertTrue(hasattr(type(obj), 'a')) self.assertTrue(hasattr(obj, 'setTest')) json_rpc_mock.assert_has_calls([call(':api')])
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')])
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_works(self, mock_socket): client = ControlClient(host="127.0.0.1", port="10001") with patch.object(client, "json_rpc") as json_rpc_mock: json_rpc_mock.return_value = ( { "id": 2, "result": { "class": "Test", "methods": ["a:set", "a:get", "setTest"], }, }, 2, ) obj = client.get_object() self.assertTrue(hasattr(type(obj), "a")) self.assertTrue(hasattr(obj, "setTest")) json_rpc_mock.assert_has_calls([call(":api")])
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 control_simulation(argument_list=None): args = parser.parse_args(argument_list or sys.argv[1:]) remote = ControlClient(*args.rpc_host.split(':')).get_object_collection() if not args.object: list_objects(remote) else: if not args.member: show_api(remote, args.object) else: response = call_method(remote, args.object, args.member, args.arguments) if response is not None or args.print_none: print(response)
def test_json_rpc_timeout_raises(self, mock_socket, mock_uuid): def zmq_again(self): raise zmq.error.Again() raising_send = Mock(side_effect=zmq_again) mock_uuid.return_value = '2' connection = ControlClient(host='127.0.0.1', port='10001') connection._socket.send_json = raising_send self.assertRaises(ProtocolException, connection.json_rpc, 'foo') raising_send.assert_called_once_with({ 'method': 'foo', 'params': (), 'jsonrpc': '2.0', 'id': '2' })
def test_json_rpc_timeout_raises(self, mock_socket, mock_uuid): def zmq_again(self): raise zmq.error.Again() raising_send = Mock(side_effect=zmq_again) mock_uuid.return_value = "2" connection = ControlClient(host="127.0.0.1", port="10001") connection._socket.send_json = raising_send self.assertRaises(ProtocolException, connection.json_rpc, "foo") raising_send.assert_called_once_with({ "method": "foo", "params": (), "jsonrpc": "2.0", "id": "2" })
def control_simulation(argument_list=None): args = parser.parse_args(argument_list or sys.argv[1:]) if args.version: print(__version__) return try: remote = ControlClient(*args.rpc_host.split(":"), timeout=args.timeout).get_object_collection() if not args.object: list_objects(remote) else: if not args.member: show_api(remote, args.object) else: response = call_method(remote, args.object, args.member, args.arguments) if response is not None or args.print_none: print(response) except ProtocolException as e: print("\n".join(("An error occurred:", str(e))))
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)])
optional_args.add_argument('-h', '--h', action='help', help='Shows this help message and exits.') __doc__ = 'To interact with the control server of a running simulation, use this script. ' \ 'Usage:\n\n.. code-block:: none\n\n{}'.format(get_usage_text(parser, indent=4)) args = parser.parse_args() if args.version: print(__version__) exit() try: remote = ControlClient(*args.rpc_host.split(':'), timeout=args.timeout).get_object_collection() if not args.object: list_objects(remote) else: if not args.member: show_api(remote, args.object) else: response = call_method(remote, args.object, args.member, args.arguments) if response is not None or args.print_none: print(response) except ProtocolException as e: print('\n'.join(('An error occurred:', str(e))))