[PATCH v2] TCPListen and TCPConnect test set added

Jiri Pirko jpirko at redhat.com
Wed Aug 15 12:29:51 UTC 2012


Wed, Aug 15, 2012 at 02:21:58PM CEST, rpazdera at redhat.com wrote:
>On Tue, Aug 14, 2012 at 04:22:48PM +0200, Jan Tluka wrote:
>> 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.
>
>Those whitespace errors can be *really* annoying ...
>
>I have them them in almost every patch I create.
>Are there any tools or methods for avoiding them?


Correct editor setup ? ;)

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