Example #1
0
 def starting(self):
     """Start the TCP client and optionally connect to host/post."""
     super(TCPClient, self).starting()
     server_host = expand(self.cfg.host, self.context)
     server_port = expand(self.cfg.port, self.context, int)
     self._client = Client(host=server_host, port=server_port)
     if self.cfg.connect_at_start:
         self.connect()
Example #2
0
def test_basic_server_client():
    # Start server
    server = Server()
    server.bind()
    assert server._listening is False
    server.serve()
    assert server._listening is True
    assert server.active_connections == 0
    assert server.accepted_connections == 0

    # No connection to accept
    assert server.accept_connection(timeout=0) == -1

    # Connect client
    client = Client(host=server.ip, port=server.port)
    client.connect()

    # Server accepts connection
    conn_idx = server.accept_connection()
    assert conn_idx == 0
    assert server.active_connections == 1
    assert server.accepted_connections == 1

    # Client sends message
    msg = b'Hello'
    _, size = client.send(msg)
    assert size == len(msg)

    # Server receives
    received = server.receive(size, conn_idx=conn_idx)
    assert received == msg

    # Server sends reply
    msg = b'World'
    server.send(msg, conn_idx)
    received = client.receive(1024)
    assert received == msg

    client.close()
    server.close()
Example #3
0
def test_two_clients():
    server = Server()
    server.bind()
    server.serve()

    client1 = Client(host=server.ip, port=server.port)
    client2 = Client(host=server.ip, port=server.port)

    # Client 1 connect and send message
    client1.connect()
    conn_1 = server.accept_connection(5)
    msg1 = b'Hello!'
    _, size1 = client1.send(msg1)

    # Client 2 connect and send message before server received msg from 1
    client2.connect()
    conn_2 = server.accept_connection(5)
    msg2 = b'Hey'
    _, size2 = client2.send(msg2)

    # Server responds to 1
    assert server.receive(size1, conn_idx=conn_1) == msg1
    resp1 = b'Yo1'
    server.send(resp1, conn_idx=conn_1)

    # Server responds to 2
    assert server.receive(size2, conn_idx=conn_2) == msg2
    resp2 = b'Yo2'
    server.send(resp2, conn_idx=conn_2)

    # Clients receiving responses
    assert client1.recv(1024) == resp1
    assert client2.recv(1024) == resp2

    client1.close()
    client2.close()
    server.close()
Example #4
0
class TCPClient(Driver):
    """
    TCP client driver.

    This is built on top of the
    :py:class:`testplan.common.utils.sockets.client.Client` class, which
    provides equivalent functionality and may be used outside of MultiTest.

    :param name: Name of TCPClient.
    :type name: ``str``
    :param host: Target host name. This can be a
        :py:class:`~testplan.common.utils.context.ContextValue`
        and will be expanded on runtime.
    :type host: ``str``
    :param port: Target port number. This can be a
        :py:class:`~testplan.common.utils.context.ContextValue`
        and will be expanded on runtime.
    :type port: ``int``
    :param interface: Interface to bind to.
    :type interface: ``NoneType`` or ``tuple``(``str, ``int``)
    :param connect_at_start: Connect to server on start. Default: True
    :type connect_at_start: ``bool``

    Also inherits all
    :py:class:`~testplan.testing.multitest.driver.base.Driver` options.
    """

    CONFIG = TCPClientConfig

    def __init__(self,
                 name,
                 host,
                 port,
                 interface=None,
                 connect_at_start=(True),
                 **options):
        options.update(self.filter_locals(locals()))
        super(TCPClient, self).__init__(**options)
        self._host = None
        self._port = None
        self._client = None

    @property
    def host(self):
        """Target host name."""
        return self._host

    @property
    def port(self):
        """Client port number assigned."""
        return self._port

    def connect(self):
        """
        Connect client.
        """
        self._client.connect()
        self._host, self._port = self._client.address

    def send_text(self, msg, standard="utf-8"):
        """
        Encodes to bytes and calls
        :py:meth:`TCPClient.send
        <testplan.testing.multitest.driver.tcp.client.TCPClient.send>`.
        """
        return self.send(bytes(msg.encode(standard)))

    def send(self, msg):
        """
        Sends bytes.

        :param msg: Message to be sent
        :type msg: ``bytes``

        :return: Number of bytes sent
        :rtype: ``int``
        """
        return self._client.send(msg)[1]

    def send_tsp(self, msg):
        """
        Sends bytes and returns also timestamp sent.

        :param msg: Message to be sent
        :type msg: ``bytes``

        :return: Timestamp when msg sent (in microseconds from epoch)
                 and number of bytes sent
        :rtype: ``tuple`` of ``long`` and ``int``
        """
        return self._client.send(msg)

    def receive_text(self, standard="utf-8", **kwargs):
        """
        Calls
        :py:meth:`TCPClient.receive
        <testplan.testing.multitest.driver.tcp.server.TCPClient.receive>`
        and decodes received bytes.
        """
        return self.receive(**kwargs).decode(standard)

    def receive(self, size=1024, timeout=30):
        """Receive bytes from the given connection."""
        received = None
        timeout_info = TimeoutExceptionInfo()
        try:
            received = self._client.receive(size, timeout=timeout or 0)
        except socket.timeout:
            if timeout is not None:
                raise TimeoutException(
                    "Timed out waiting for message on {0}. {1}".format(
                        self.cfg.name, timeout_info.msg()))
        return received

    def reconnect(self):
        """Client reconnect."""
        self._client.close()
        self.connect()

    def starting(self):
        """Start the TCP client and optionally connect to host/post."""
        super(TCPClient, self).starting()
        server_host = expand(self.cfg.host, self.context)
        server_port = expand(self.cfg.port, self.context, int)
        self._client = Client(host=server_host, port=server_port)
        if self.cfg.connect_at_start:
            self.connect()

    def stopping(self):
        """Close the client connection."""
        super(TCPClient, self).stopping()
        if self._client:
            self._client.close()

    def aborting(self):
        """Abort logic that stops the client."""
        if self._client:
            self._client.close()