[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