[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