Example #1
0
 def test_send_to_server(self, _):
     self.WS = WebsocketClientComms(self.p, params)
     self.WS.conn = MagicMock()
     request = Get(None, None, ["block", "attr"])
     request.set_id(54)
     self.WS.send_to_server(request)
     self.WS.conn.write_message.assert_called_once_with(
         '{"typeid": "malcolm:core/Get:1.0", "id": 54, "endpoint": ["block", "attr"]}'
     )
 def test_subscribe_initial(self, _, _2):
     self.WS = WebsocketClientComms(self.p, params)
     self.WS.subscribe_server_blocks("conn")
     self.assertEqual(self.WS.loop.add_callback.call_count, 1)
     request = self.WS.loop.add_callback.call_args[0][1]
     self.assertEqual(request.id, 0)
     self.assertEqual(request.typeid, "malcolm:core/Subscribe:1.0")
     self.assertEqual(request.endpoint, [".", "blocks", "value"])
     self.assertEqual(request.delta, False)
    def test_on_message_logs_exception(self, _, _1, json_mock):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.log_exception = MagicMock()
        exception = Exception()
        json_mock.loads.side_effect = exception

        self.WS.on_message("test")

        self.WS.log_exception.assert_called_once_with(exception)
Example #4
0
 def test_subscribe_initial(self, _):
     self.WS = WebsocketClientComms(self.p, params)
     self.WS.send_to_server = MagicMock()
     self.WS.subscribe_server_blocks()
     self.assertEqual(self.WS.send_to_server.call_count, 1)
     request = self.WS.send_to_server.call_args[0][0]
     self.assertEqual(request.id, 0)
     self.assertEqual(request.typeid, "malcolm:core/Subscribe:1.0")
     self.assertEqual(request.endpoint, [".", "blocks", "value"])
     self.assertEqual(request.delta, False)
Example #5
0
    def test_start(self, ioloop_mock):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock()
        self.WS.start()

        self.assertEqual([call(self.WS.send_loop),
                          call(self.WS.loop.start)],
                         self.WS.process.spawn.call_args_list)
Example #6
0
    def test_wait(self, _):
        spawnable_mocks = [MagicMock(), MagicMock()]
        timeout = MagicMock()

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock(side_effect=spawnable_mocks)
        self.WS.start()
        self.WS.wait(timeout)

        spawnable_mocks[0].wait.assert_called_once_with(timeout=timeout)
        spawnable_mocks[1].wait.assert_called_once_with(timeout=timeout)
    def test_init(self, ioloop_mock, connect_mock):
        self.WS = WebsocketClientComms(self.p, params)

        self.assertEqual(self.p, self.WS.process)
        self.assertEqual("ws://test:1/ws", self.WS.url)
        self.assertEqual(ioloop_mock.current(), self.WS.loop)
        connect_mock.assert_called_once_with(
            self.WS.url,
            callback=self.WS.subscribe_server_blocks,
            on_message_callback=self.WS.on_message)
        self.assertEqual(connect_mock(), self.WS.conn)
    def test_stop(self, ioloop_mock, _):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.start()
        self.WS.stop()

        loop_mock.add_callback.assert_called_once_with(
            ioloop_mock.current().stop)
        self.WS.process.spawn.return_value.assert_not_called()
    def test_send_to_server(self, _, connect_mock, json_mock):
        self.WS = WebsocketClientComms(self.p, params)
        json_mock.reset_mock()
        result_mock = MagicMock()
        connect_mock().result.return_value = result_mock
        dumps_mock = MagicMock()
        json_mock.dumps.return_value = dumps_mock

        request_mock = MagicMock()
        self.WS.send_to_server(request_mock)

        json_mock.dumps.assert_called_once_with(request_mock.to_dict())
        result_mock.write_message.assert_called_once_with(dumps_mock)
Example #10
0
 def test_on_message(self, _):
     self.WS = WebsocketClientComms(self.p, params)
     request = MagicMock()
     self.WS.requests[11] = request
     response = Return(11, MagicMock(), "me")
     message = """{
     "typeid": "malcolm:core/Return:1.0",
     "id": 11,
     "value": "me"
     }"""
     self.WS.on_message(message)
     self.assertEquals(request.response_queue.put.call_count, 1)
     actual = request.response_queue.put.call_args[0][0]
     self.assertEquals(actual.to_dict(), response.to_dict())
 def test_init(self, ioloop_mock):
     self.WS = WebsocketClientComms(self.p, params)
     self.assertEqual(self.p, self.WS.process)
     self.assertEqual("ws://test:1/ws", self.WS.url)
     self.assertEqual(ioloop_mock.current(), self.WS.loop)
     self.WS.loop.add_callback.assert_called_once_with(
         self.WS.recv_loop)
 def test_send_to_server(self, _):
     self.WS = WebsocketClientComms(self.p, params)
     self.WS.conn = MagicMock()
     request = Get(None, None, ["block", "attr"])
     request.set_id(54)
     self.WS.send_to_server(request)
     self.WS.conn.write_message.assert_called_once_with(
         '{"typeid": "malcolm:core/Get:1.0", "id": 54, "endpoint": ["block", "attr"]}')
    def test_on_message(self, _, _1, json_mock, deserialize_mock):
        self.WS = WebsocketClientComms(self.p, params)

        message_dict = dict(name="TestMessage")
        json_mock.loads.return_value = message_dict

        response = MagicMock()
        response.id = 1
        deserialize_mock.return_value = response
        request_mock = MagicMock()
        self.WS.requests[1] = request_mock

        self.WS.on_message("TestMessage")

        json_mock.loads.assert_called_once_with("TestMessage",
                                                object_pairs_hook=OrderedDict)
        deserialize_mock.assert_called_once_with(message_dict, Response)
        request_mock.response_queue.put.assert_called_once_with(response)
    def test_start(self, ioloop_mock):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock()
        self.WS.start()

        self.assertEqual([call(self.WS.send_loop), call(self.WS.loop.start)],
                         self.WS.process.spawn.call_args_list)
 def test_subscribe_initial(self, _):
     self.WS = WebsocketClientComms(self.p, params)
     self.WS.send_to_server = MagicMock()
     self.WS.subscribe_server_blocks()
     self.assertEqual(self.WS.send_to_server.call_count, 1)
     request = self.WS.send_to_server.call_args[0][0]
     self.assertEqual(request.id, 0)
     self.assertEqual(request.typeid, "malcolm:core/Subscribe:1.0")
     self.assertEqual(request.endpoint, [".", "blocks", "value"])
     self.assertEqual(request.delta, False)
    def test_wait(self, _):
        spawnable_mocks = [MagicMock(), MagicMock()]
        timeout = MagicMock()

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock(side_effect=spawnable_mocks)
        self.WS.start()
        self.WS.wait(timeout)

        spawnable_mocks[0].wait.assert_called_once_with(timeout=timeout)
        spawnable_mocks[1].wait.assert_called_once_with(timeout=timeout)
    def test_stop(self, ioloop_mock):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.start()
        loop_mock.reset_mock()
        self.WS.stop()

        loop_mock.add_callback.assert_called_once_with(
            ioloop_mock.current().stop)
        self.WS.process.spawn.return_value.assert_not_called()
 def test_on_message(self, _):
     self.WS = WebsocketClientComms(self.p, params)
     request = MagicMock()
     self.WS.requests[11] = request
     response = Return(11, MagicMock(), "me")
     message = """{
     "typeid": "malcolm:core/Return:1.0",
     "id": 11,
     "value": "me"
     }"""
     self.WS.on_message(message)
     self.assertEquals(request.response_queue.put.call_count, 1)
     actual = request.response_queue.put.call_args[0][0]
     self.assertEquals(actual.to_dict(), response.to_dict())
 def setUp(self):
     self.sf = SyncFactory("sync")
     self.process = Process("proc", self.sf)
     DefaultController("hello",
                       self.process,
                       parts=dict(hello=HelloPart(self.process, None)))
     DefaultController("counter",
                       self.process,
                       parts=dict(counter=CounterPart(self.process, None)))
     WebsocketServerComms(self.process, dict(port=self.socket))
     self.process.start()
     self.process2 = Process("proc2", self.sf)
     WebsocketClientComms(self.process2,
                          dict(hostname="localhost", port=self.socket))
     self.process2.start()
 def setUp(self):
     sf = SyncFactory("sync")
     self.process = Process("proc", sf)
     Hello(self.process, dict(mri="hello"))
     Counter(self.process, dict(mri="counter"))
     self.process.add_comms(
         WebsocketServerComms(self.process, dict(port=self.socket)))
     self.process.start()
     # If we don't wait long enough, sometimes the websocket_connect()
     # in process2 will hang...
     time.sleep(0.1)
     self.process2 = Process("proc2", sf)
     self.process2.add_comms(
         WebsocketClientComms(self.process2,
                              dict(hostname="localhost", port=self.socket)))
     self.process2.start()
Example #21
0
def make_process():
    import sys
    import threading
    import argparse
    import logging
    from os import environ

    parser = argparse.ArgumentParser(
        description="Interactive shell for malcolm")
    parser.add_argument(
        '--client',
        '-c',
        help="Add a client to given server, like ws://localhost:8080 or pva")
    parser.add_argument(
        '--log',
        default="INFO",
        help="Lowest level of logs to see. One of: ERROR, WARNING, INFO, DEBUG "
        "Default is INFO")
    parser.add_argument(
        'yaml',
        nargs="?",
        help="The YAML file containing the blocks to be loaded")
    args = parser.parse_args()
    # assuming loglevel is bound to the string value obtained from the
    # command line argument. Convert to upper case to allow the user to
    # specify --log=DEBUG or --log=debug
    numeric_level = getattr(logging, args.log.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError('Invalid log level: %s' % args.log)
    logging.basicConfig(level=numeric_level)

    from malcolm.core import SyncFactory, Process
    from malcolm.yamlutil import make_include_creator

    sf = SyncFactory("Sync")

    if args.yaml:
        proc_name = os.path.basename(args.yaml).split(".")[-2]
        proc = Process(proc_name, sf)
        with open(args.yaml) as f:
            assembly = make_include_creator(f.read())
        params = assembly.MethodMeta.prepare_input_map()
        assembly(proc, params)
        proc_name = "%s - imalcolm" % proc_name
    else:
        proc = Process("Process", sf)
        proc_name = "imalcolm"
    # set terminal title
    sys.stdout.write("\x1b]0;%s\x07" % proc_name)

    if args.client:
        if args.client.startswith("ws://"):
            from malcolm.comms.websocket import WebsocketClientComms
            hostname, port = args.client[5:].split(":")
            comms = WebsocketClientComms(
                proc, dict(hostname=hostname, port=int(port)))
            proc.add_comms(comms)
        else:
            raise ValueError("Don't know how to create client to %s" %
                             args.client)

    def gui(block):
        global opener
        opener.open_gui(block, proc)

    try:
        environ['DISPLAY']
        # If this environment variable doesn't exist then there is probably no
        # X server for us to talk to.
    except KeyError:
        pass
    else:
        from PyQt4.Qt import QApplication

        # Start qt
        def start_qt():
            global app
            app = QApplication(sys.argv)
            app.setQuitOnLastWindowClosed(False)
            from malcolm.gui.guiopener import GuiOpener
            global opener
            opener = GuiOpener()
            app.exec_()

        qt_thread = threading.Thread(target=start_qt)
        qt_thread.start()

    return proc, gui
 def test_on_message_logs_exception(self, _):
     self.WS = WebsocketClientComms(self.p, params)
     self.WS.log_exception = MagicMock()
     self.WS.on_message("test")
     self.WS.log_exception.assert_called_once_with(
         'on_message(%r) failed', "test")
Example #23
0
 def test_on_message_logs_exception(self, _):
     self.WS = WebsocketClientComms(self.p, params)
     self.WS.log_exception = MagicMock()
     self.WS.on_message("test")
     self.WS.log_exception.assert_called_once_with('on_message(%r) failed',
                                                   "test")
class TestWSClientComms(unittest.TestCase):
    def setUp(self):
        self.p = MagicMock()

    @patch('malcolm.comms.websocket.websocketclientcomms.websocket_connect')
    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_init(self, ioloop_mock, connect_mock):
        self.WS = WebsocketClientComms(self.p, params)

        self.assertEqual(self.p, self.WS.process)
        self.assertEqual("ws://*****:*****@patch('malcolm.comms.websocket.websocketclientcomms.websocket_connect')
    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_subscribe_initial(self, _, _2):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.subscribe_server_blocks("conn")
        self.assertEqual(self.WS.loop.add_callback.call_count, 1)
        request = self.WS.loop.add_callback.call_args[0][1]
        self.assertEqual(request.id, 0)
        self.assertEqual(request.typeid, "malcolm:core/Subscribe:1.0")
        self.assertEqual(request.endpoint, [".", "blocks", "value"])
        self.assertEqual(request.delta, False)

    @patch('malcolm.comms.websocket.websocketclientcomms.deserialize_object')
    @patch('malcolm.comms.websocket.websocketclientcomms.json')
    @patch('malcolm.comms.websocket.websocketclientcomms.websocket_connect')
    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_on_message(self, _, _1, json_mock, deserialize_mock):
        self.WS = WebsocketClientComms(self.p, params)

        message_dict = dict(name="TestMessage")
        json_mock.loads.return_value = message_dict

        response = MagicMock()
        response.id = 1
        deserialize_mock.return_value = response
        request_mock = MagicMock()
        self.WS.requests[1] = request_mock

        self.WS.on_message("TestMessage")

        json_mock.loads.assert_called_once_with("TestMessage",
                                                object_pairs_hook=OrderedDict)
        deserialize_mock.assert_called_once_with(message_dict, Response)
        request_mock.response_queue.put.assert_called_once_with(response)

    @patch('malcolm.comms.websocket.websocketclientcomms.json')
    @patch('malcolm.comms.websocket.websocketclientcomms.websocket_connect')
    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_on_message_logs_exception(self, _, _1, json_mock):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.log_exception = MagicMock()
        exception = Exception()
        json_mock.loads.side_effect = exception

        self.WS.on_message("test")

        self.WS.log_exception.assert_called_once_with(exception)

    @patch('malcolm.comms.websocket.websocketclientcomms.json')
    @patch('malcolm.comms.websocket.websocketclientcomms.websocket_connect')
    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_send_to_server(self, _, connect_mock, json_mock):
        self.WS = WebsocketClientComms(self.p, params)
        json_mock.reset_mock()
        result_mock = MagicMock()
        connect_mock().result.return_value = result_mock
        dumps_mock = MagicMock()
        json_mock.dumps.return_value = dumps_mock

        request_mock = MagicMock()
        self.WS.send_to_server(request_mock)

        json_mock.dumps.assert_called_once_with(request_mock.to_dict())
        result_mock.write_message.assert_called_once_with(dumps_mock)

    @patch('malcolm.comms.websocket.websocketclientcomms.websocket_connect')
    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_start(self, ioloop_mock, _):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock()
        self.WS.start()

        self.assertEqual([call(self.WS.send_loop),
                          call(self.WS.loop.start)],
                         self.WS.process.spawn.call_args_list)

    @patch('malcolm.comms.websocket.websocketclientcomms.websocket_connect')
    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_stop(self, ioloop_mock, _):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.start()
        self.WS.stop()

        loop_mock.add_callback.assert_called_once_with(
            ioloop_mock.current().stop)
        self.WS.process.spawn.return_value.assert_not_called()

    @patch('malcolm.comms.websocket.websocketclientcomms.websocket_connect')
    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_wait(self, _, _2):
        spawnable_mocks = [MagicMock(), MagicMock()]
        timeout = MagicMock()

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock(side_effect=spawnable_mocks)
        self.WS.start()
        self.WS.wait(timeout)

        spawnable_mocks[0].wait.assert_called_once_with(timeout=timeout)
        spawnable_mocks[1].wait.assert_called_once_with(timeout=timeout)
Example #25
0
 def test_init(self, ioloop_mock):
     self.WS = WebsocketClientComms(self.p, params)
     self.assertEqual(self.p, self.WS.process)
     self.assertEqual("ws://test:1/ws", self.WS.url)
     self.assertEqual(ioloop_mock.current(), self.WS.loop)
     self.WS.loop.add_callback.assert_called_once_with(self.WS.recv_loop)
Example #26
0
class TestWSClientComms(unittest.TestCase):
    def setUp(self):
        self.p = MagicMock()

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_init(self, ioloop_mock):
        self.WS = WebsocketClientComms(self.p, params)
        self.assertEqual(self.p, self.WS.process)
        self.assertEqual("ws://*****:*****@patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_subscribe_initial(self, _):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.send_to_server = MagicMock()
        self.WS.subscribe_server_blocks()
        self.assertEqual(self.WS.send_to_server.call_count, 1)
        request = self.WS.send_to_server.call_args[0][0]
        self.assertEqual(request.id, 0)
        self.assertEqual(request.typeid, "malcolm:core/Subscribe:1.0")
        self.assertEqual(request.endpoint, [".", "blocks", "value"])
        self.assertEqual(request.delta, False)

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_on_message(self, _):
        self.WS = WebsocketClientComms(self.p, params)
        request = MagicMock()
        self.WS.requests[11] = request
        response = Return(11, MagicMock(), "me")
        message = """{
        "typeid": "malcolm:core/Return:1.0",
        "id": 11,
        "value": "me"
        }"""
        self.WS.on_message(message)
        self.assertEquals(request.response_queue.put.call_count, 1)
        actual = request.response_queue.put.call_args[0][0]
        self.assertEquals(actual.to_dict(), response.to_dict())

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_on_message_logs_exception(self, _):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.log_exception = MagicMock()
        self.WS.on_message("test")
        self.WS.log_exception.assert_called_once_with('on_message(%r) failed',
                                                      "test")

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_send_to_server(self, _):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.conn = MagicMock()
        request = Get(None, None, ["block", "attr"])
        request.set_id(54)
        self.WS.send_to_server(request)
        self.WS.conn.write_message.assert_called_once_with(
            '{"typeid": "malcolm:core/Get:1.0", "id": 54, "endpoint": ["block", "attr"]}'
        )

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_start(self, ioloop_mock):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock()
        self.WS.start()

        self.assertEqual([call(self.WS.send_loop),
                          call(self.WS.loop.start)],
                         self.WS.process.spawn.call_args_list)

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_stop(self, ioloop_mock):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.start()
        loop_mock.reset_mock()
        self.WS.stop()

        loop_mock.add_callback.assert_called_once_with(
            ioloop_mock.current().stop)
        self.WS.process.spawn.return_value.assert_not_called()

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_wait(self, _):
        spawnable_mocks = [MagicMock(), MagicMock()]
        timeout = MagicMock()

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock(side_effect=spawnable_mocks)
        self.WS.start()
        self.WS.wait(timeout)

        spawnable_mocks[0].wait.assert_called_once_with(timeout=timeout)
        spawnable_mocks[1].wait.assert_called_once_with(timeout=timeout)
class TestWSClientComms(unittest.TestCase):

    def setUp(self):
        self.p = MagicMock()

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_init(self, ioloop_mock):
        self.WS = WebsocketClientComms(self.p, params)
        self.assertEqual(self.p, self.WS.process)
        self.assertEqual("ws://*****:*****@patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_subscribe_initial(self, _):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.send_to_server = MagicMock()
        self.WS.subscribe_server_blocks()
        self.assertEqual(self.WS.send_to_server.call_count, 1)
        request = self.WS.send_to_server.call_args[0][0]
        self.assertEqual(request.id, 0)
        self.assertEqual(request.typeid, "malcolm:core/Subscribe:1.0")
        self.assertEqual(request.endpoint, [".", "blocks", "value"])
        self.assertEqual(request.delta, False)

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_on_message(self, _):
        self.WS = WebsocketClientComms(self.p, params)
        request = MagicMock()
        self.WS.requests[11] = request
        response = Return(11, MagicMock(), "me")
        message = """{
        "typeid": "malcolm:core/Return:1.0",
        "id": 11,
        "value": "me"
        }"""
        self.WS.on_message(message)
        self.assertEquals(request.response_queue.put.call_count, 1)
        actual = request.response_queue.put.call_args[0][0]
        self.assertEquals(actual.to_dict(), response.to_dict())

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_on_message_logs_exception(self, _):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.log_exception = MagicMock()
        self.WS.on_message("test")
        self.WS.log_exception.assert_called_once_with(
            'on_message(%r) failed', "test")

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_send_to_server(self, _):
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.conn = MagicMock()
        request = Get(None, None, ["block", "attr"])
        request.set_id(54)
        self.WS.send_to_server(request)
        self.WS.conn.write_message.assert_called_once_with(
            '{"typeid": "malcolm:core/Get:1.0", "id": 54, "endpoint": ["block", "attr"]}')

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_start(self, ioloop_mock):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock
        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock()
        self.WS.start()

        self.assertEqual([call(self.WS.send_loop), call(self.WS.loop.start)],
                         self.WS.process.spawn.call_args_list)

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_stop(self, ioloop_mock):
        loop_mock = MagicMock()
        ioloop_mock.current.return_value = loop_mock

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.start()
        loop_mock.reset_mock()
        self.WS.stop()

        loop_mock.add_callback.assert_called_once_with(
            ioloop_mock.current().stop)
        self.WS.process.spawn.return_value.assert_not_called()

    @patch('malcolm.comms.websocket.websocketclientcomms.IOLoop')
    def test_wait(self, _):
        spawnable_mocks = [MagicMock(), MagicMock()]
        timeout = MagicMock()

        self.WS = WebsocketClientComms(self.p, params)
        self.WS.process.spawn = MagicMock(side_effect=spawnable_mocks)
        self.WS.start()
        self.WS.wait(timeout)

        spawnable_mocks[0].wait.assert_called_once_with(timeout=timeout)
        spawnable_mocks[1].wait.assert_called_once_with(timeout=timeout)
def make_process():
    import argparse
    import logging
    import cothread

    cothread.iqt()
    cothread.input_hook._qapp.setQuitOnLastWindowClosed(False)

    parser = argparse.ArgumentParser(
        description="Interactive shell for malcolm")
    parser.add_argument(
        '--client',
        '-c',
        help="Add a client to given server, like ws://localhost:8080 or pva")
    parser.add_argument(
        '--log',
        default="INFO",
        help="Lowest level of logs to see. One of: ERROR, WARNING, INFO, DEBUG "
        "Default is INFO")
    parser.add_argument(
        'yaml',
        nargs="?",
        help="The YAML file containing the assemblies to be loaded")
    args = parser.parse_args()
    # assuming loglevel is bound to the string value obtained from the
    # command line argument. Convert to upper case to allow the user to
    # specify --log=DEBUG or --log=debug
    numeric_level = getattr(logging, args.log.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError('Invalid log level: %s' % args.log)
    logging.basicConfig(level=numeric_level)

    from malcolm.core import SyncFactory, Process
    from malcolm.assemblyutil import make_assembly
    from malcolm.gui.blockgui import BlockGui

    proc = Process("Process", SyncFactory("Sync"))
    guis = {}

    if args.yaml:
        with open(args.yaml) as f:
            assembly = make_assembly(f.read())
        assembly(proc, {})

    def gui(block):
        if block in guis:
            guis[block].show()
        else:
            guis[block] = BlockGui(proc, block)
        return guis[block]

    if args.client:
        if args.client.startswith("ws://"):
            from malcolm.comms.websocket import WebsocketClientComms
            hostname, port = args.client[5:].split(":")
            WebsocketClientComms(proc, dict(hostname=hostname, port=int(port)))
        else:
            raise ValueError("Don't know how to create client to %s" %
                             args.client)

    return proc, gui