[PATCH] TCPListen and TCPConnect test set added

Jan Tluka jtluka at redhat.com
Fri Aug 10 12:09:49 UTC 2012


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..05579c2
--- /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..c9492f1
--- /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 c
+             onnection 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



More information about the LNST-developers mailing list