[PATCH v2] TCPListen and TCPConnect test set added

Jiri Pirko jpirko at redhat.com
Tue Aug 14 14:11:44 UTC 2012


Applying: TCPListen and TCPConnect test set added
/home/jirka/work/lnst/.git/rebase-apply/patch:205: trailing whitespace.
    Test spawns server(s) listening for TCP connection(s) on port(s) defined by 
warning: 1 line adds whitespace errors.

But nevermind for now. I will fix this manually this time :)

Jiri

Mon, Aug 13, 2012 at 03:37:27PM CEST, jtluka at redhat.com wrote:
>Set of these tests provides possibility to test multiple TCP connections
>within two LNST commands. Data sent are random and every connection
>behaves differently in sense that number of packets is random as well.
>
>Following are two examples of commands in command sequence.
>
>    <define>
>        <alias name="my_range" value="10000-10100" />
>    </define>
>    <command machine_id="1" type="test" value="TCPListen" bg_id="1">
>        <options>
>            <option name="addr" value="{ip(1,1)}"/>
>            <option name="port_range" value="{$my_range}"/>
>        </options>
>    </command>
>    <command type="exec" value="sleep 5" />
>    <command machine_id="2" type="test" value="TCPConnect" bg_id="2">
>        <options>
>            <option name="addr" value="{ip(1,1)}"/>
>            <option name="port_range" value="{$my_range}"/>
>            <option name="sleep" value="0.5" />
>        </options>
>    </command>
>    <command machine_id="2" type="wait" value="2" />
>    <command machine_id="1" type="wait" value="1" />
>
>Repeated generation of connections can be achieved using following
>command (see 'cont' option):
>
>    <define>
>        <alias name="my_range" value="10000-10100" />
>    </define>
>    <command machine_id="1" type="test" value="TCPListen" bg_id="1">
>        <options>
>            <option name="addr" value="{ip(1,1)}"/>
>            <option name="port_range" value="{$my_range}"/>
>            <option name="cont" value="yes" />
>        </options>
>    </command>
>    <command type="exec" value="sleep 5" />
>    <command machine_id="2" type="test" value="TCPConnect" bg_id="2">
>        <options>
>            <option name="addr" value="{ip(1,1)}"/>
>            <option name="port_range" value="{$my_range}"/>
>            <option name="sleep" value="0.5" />
>            <option name="cont" value="yes" />
>        </options>
>    </command>
>    <command type="exec" value="sleep 60" />
>    <command machine_id="2" type="intr" value="2" />
>    <command machine_id="1" type="kill" value="1" />
>
>
>---
> Tests/TestTCPConnect.py |  167 +++++++++++++++++++++++++++++++++++++++++++++++
> Tests/TestTCPListen.py  |  127 +++++++++++++++++++++++++++++++++++
> 2 files changed, 294 insertions(+), 0 deletions(-)
> create mode 100644 Tests/TestTCPConnect.py
> create mode 100644 Tests/TestTCPListen.py
>
>diff --git a/Tests/TestTCPConnect.py b/Tests/TestTCPConnect.py
>new file mode 100644
>index 0000000..0a6c655
>--- /dev/null
>+++ b/Tests/TestTCPConnect.py
>@@ -0,0 +1,167 @@
>+"""
>+This module defines TCPConnect module
>+"""
>+
>+__author__ = """
>+jtluka at redhat.com (Jan Tluka)
>+"""
>+
>+import sys
>+import socket
>+import errno
>+from multiprocessing import Process, Lock
>+from signal import signal, SIGINT
>+from time import sleep
>+from random import randrange, sample
>+import logging
>+import re
>+from Common.TestsCommon import TestGeneric
>+
>+"""
>+Test description:
>+    Test spawns client(s) connecting to TCP port(s) defined by port or
>+    port_range option. When connected, the client sends random bursts of
>+    random data to server. If cont option is set the connections are initiated
>+    again and data is sent to server until interrupted by the controller.
>+
>+Parameters:
>+    addr ... mandatory, address to connect to
>+    port ... mandatory, port to send data
>+    sleep ... optional, sleep time between bursts, if undefined, the bursts
>+              are immediate
>+    cont ... optional, sets continuous mode of connecting, if set connections
>+             are infinitely re-spawned when closed
>+"""
>+
>+class ConnectionWorker():
>+    def __init__(self, host, port, sleep_time = None, continuous = None):
>+        self._tlock = Lock()
>+        self._terminate = 0
>+        self._host = host
>+        self._port = port
>+        self._sleep_time = sleep_time
>+        self._cont = continuous
>+        self._ascii = [chr(i) for i in range(0,255)]
>+
>+    def terminate(self):
>+        self._tlock.acquire()
>+        self._terminate=1
>+        self._tlock.release()
>+
>+    def run(self):
>+        loop = True
>+
>+        while loop:
>+            loop = (self._cont is not None)
>+            logging.debug("Starting connection to (%s) port %s " % (self._host,
>+                          self._port))
>+
>+            try:
>+                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>+                s.connect((self._host, self._port))
>+            except socket.error, msg:
>+                s.close()
>+                s = None
>+                logging.error(msg)
>+                return
>+
>+            for txs in range(10, randrange(20,100)):
>+                self._tlock.acquire()
>+                if self._terminate:
>+                    self._tlock.release()
>+                    logging.debug("Terminating connection on port %s" %
>+                                  self._port)
>+                    loop = False
>+                    break
>+                else:
>+                    self._tlock.release()
>+
>+                rnd_str = "".join(sample(self._ascii, len(self._ascii)))
>+                data = s.sendall(rnd_str)
>+                if (self._sleep_time):
>+                    sleep(self._sleep_time)
>+
>+            s.close()
>+
>+
>+class TestTCPConnect(TestGeneric):
>+    def _parse_options(self):
>+        addr = self.get_mopt("addr")
>+        if addr:
>+            self._host = addr
>+
>+        # either port or port_range should be set
>+        port = self.get_opt("port")
>+        if port:
>+            self._port = port
>+        else:
>+            port_range = self.get_opt("port_range")
>+            if port_range:
>+                self._port_range = port_range
>+            else:
>+                e = TestOptionMissing()
>+                raise e
>+
>+        sleep_time = float(self.get_opt("sleep"))
>+        if sleep_time:
>+            self._sleep_time = sleep_time
>+
>+        cont = self.get_opt("cont")
>+        if cont:
>+            self._cont = cont
>+
>+    def parse_port_range(self):
>+        if self._port_range == None:
>+            return []
>+
>+        for c in [',','-']:
>+            s = self._port_range.split(c)
>+            if len(s) == 2:
>+                break
>+
>+        if len(s) != 2:
>+            logging.error("Port range malformed! ", self._port_range)
>+
>+        low = int(s[0])
>+        high = int(s[1]) + 1
>+
>+        return range(low, high)
>+
>+    def _close_connections(self, signum, frame):
>+        logging.debug("Termination signal delivered ...")
>+        for cw in self._cw_instances:
>+            cw.terminate()
>+
>+    def _set_interrupt_handler(self):
>+        signal(SIGINT, self._close_connections)
>+
>+    def run(self):
>+        self._terminate = 0
>+        self._host = None
>+        self._port = None
>+        self._cont = None
>+        self._cw_instances = []
>+
>+        self._set_interrupt_handler()
>+
>+        self._parse_options()
>+
>+        ports = []
>+        if self._port:
>+            ports.extend(self._port)
>+        else:
>+            r = self.parse_port_range()
>+            ports.extend(r)
>+
>+        workers = []
>+        for p in ports:
>+            cw = ConnectionWorker(self._host, p, self._sleep_time, self._cont)
>+            self._cw_instances.append(cw)
>+
>+            w = Process(target=cw.run)
>+            w.start()
>+            workers.append(w)
>+
>+        logging.debug("Waiting for workers ...")
>+        for w in workers:
>+            w.join()
>diff --git a/Tests/TestTCPListen.py b/Tests/TestTCPListen.py
>new file mode 100644
>index 0000000..2b25f29
>--- /dev/null
>+++ b/Tests/TestTCPListen.py
>@@ -0,0 +1,127 @@
>+"""
>+This module defines TCPListen module
>+"""
>+
>+__author__ = """
>+jtluka at redhat.com (Jan Tluka)
>+"""
>+
>+import sys
>+import socket
>+import errno
>+import logging
>+import re
>+from multiprocessing import Process
>+from Common.TestsCommon import TestGeneric
>+
>+"""
>+Test description:
>+    Test spawns server(s) listening for TCP connection(s) on port(s) defined by 
>+    port or port_range options. When client connects to the port, server reads
>+    the data sent and close the connection when no more data is available.
>+    If cont option is set the connection is reopened and server reads data
>+    again.
>+
>+Parameters:
>+    addr ... optional, address to bind to, if undefined listen on all ifaces
>+    port ... mandatory, port to listen on
>+    cont ... optional, if set the listening port is reopened when the
>+             connection is closed
>+"""
>+
>+class TestTCPListen(TestGeneric):
>+    def __init__(self, command):
>+        self._addr = None
>+        self._port = None
>+        self._cont = None
>+        TestGeneric.__init__(self, command)
>+
>+    def _parse_options(self):
>+        addr = self.get_opt("addr")
>+        if addr:
>+            self._addr = addr
>+
>+        # either port or port_range should be set
>+        port = self.get_opt("port")
>+        if port:
>+            self._port = port
>+        else:
>+            port_range = self.get_opt("port_range")
>+            if port_range:
>+                self._port_range = port_range
>+            else:
>+                e = TestOptionMissing()
>+                raise e
>+
>+        cont = self.get_opt("cont")
>+        if cont:
>+            self._cont = cont
>+
>+    def _worker(self, host, port):
>+        logging.debug("Starting listener (%s) on port %s " % (host, port))
>+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>+
>+        try:
>+            s.bind((host, port))
>+            s.listen(1)
>+        except socket.error, msg:
>+            s.close()
>+            s = None
>+            logging.error(msg)
>+            return
>+
>+        loop = 1
>+
>+        while loop or self._cont:
>+            conn, addr = s.accept()
>+            logging.debug('Connected from ' + addr[0] + ' port:' +
>+                          str(addr[1]))
>+
>+            while 1:
>+                data = conn.recv(1024)
>+                if not data:
>+                    logging.debug('Client disconnected: ' + addr[0] +
>+                                  ' port:' + str(addr[1]))
>+                    break
>+
>+            conn.close()
>+            loop = 0
>+
>+    def _parse_port_range(self):
>+        if self._port_range == None:
>+            return []
>+
>+        for c in [',','-']:
>+            s = self._port_range.split(c)
>+            if len(s) == 2:
>+                break
>+
>+        if len(s) != 2:
>+            logging.error("Port range malformed! ", self._port_range)
>+
>+        low = int(s[0])
>+        high = int(s[1]) + 1
>+
>+        return range(low, high)
>+
>+    def run(self):
>+        self._parse_options()
>+
>+        ports = []
>+        if self._port:
>+            ports.extend(self._port)
>+        else:
>+            r = self._parse_port_range()
>+            ports.extend(r)
>+
>+        workers = []
>+
>+        for p in ports:
>+            w = Process(target=self._worker, args=(self._addr, p))
>+            w.start()
>+            workers.append(w)
>+
>+
>+        logging.debug("Waiting for workers ...")
>+        for w in workers:
>+            w.join()
>-- 
>1.7.6.5
>
>_______________________________________________
>LNST-developers mailing list
>LNST-developers at lists.fedorahosted.org
>https://lists.fedorahosted.org/mailman/listinfo/lnst-developers


More information about the LNST-developers mailing list