[PATCH v2] TCPListen and TCPConnect test set added

Jan Tluka jtluka at redhat.com
Tue Aug 14 14:22:48 UTC 2012


Tue, Aug 14, 2012 at 04:11:44PM CEST, jpirko at redhat.com wrote:
>
>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 :)

Thank you almighty!

>
>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