[Patches] [ python-Patches-419145 ] SocketServer test (UDP/TCP Thread/Fork)

noreply@sourceforge.net noreply@sourceforge.net
Sat, 28 Jul 2001 14:38:36 -0700


Patches item #419145, was opened at 2001-04-26 07:29
You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=419145&group_id=5470

Category: None
Group: None
Status: Open
Resolution: None
Priority: 5
Submitted By: Luke Kenneth Casson Leighton (lkcl)
Assigned to: Nobody/Anonymous (nobody)
Summary: SocketServer test (UDP/TCP Thread/Fork)

Initial Comment:
this is a _completely_ inappropriate location to put in
a 
patch: stupid-netscape word-wraps it.  well, too bad :)

--- src/Python-2.1/Lib/SocketServer.py  Wed Apr 11
05:02:05 2001
+++ SocketServer2.py    Thu Apr 26 16:23:32 2001
@@ -110,15 +110,22 @@

 BaseServer:
 - split generic "request" functionality out into
BaseServer class.
-  Copyright (C) 2000  Luke Kenneth Casson Leighton
<lkcl@samba.org>

   example: read entries from a SQL database (requires
overriding
   get_request() to return a table entry from the
database).
   entry is processed by a RequestHandlerClass.

+Test Method:
+simple echo server, ForkingTCPServer and
ThreadingTCPServer.
+send data on port 10000, it will be received back,
verbatim.
+run test with --client to create 20 such test
connections,
+which will send 20 tests each and expect them to be
received.
+
+TODO: write a UDPServer test, too.
+
 """

-# Author of the BaseServer patch: Luke Kenneth Casson
Leighton
+# Author of the BaseServer and test() patch: Luke
Kenneth Casson Leighton

 __version__ = "0.3"

@@ -555,3 +562,171 @@

     def finish(self):
         self.socket.sendto(self.wfile.getvalue(),
self.client_address)
+
+
+class EchoHandler:
+   """ an example handler that reads data from a
socket
+       and sends it back.
+   """
+
+   def handle(self):
+       """ simple read line, write it.
+           we don't even do a select on the socket,
just read
+           it.
+       """
+       eof = None
+       data = None
+
+       print 'received connection request'
+       data = self.rfile.readline()
+       print 'received data:', repr(data)
+       self.wfile.write(data)
+       self.wfile.flush()
+
+class
EchoUDPHandler(EchoHandler,DatagramRequestHandler):
pass
+class
EchoTCPHandler(EchoHandler,StreamRequestHandler): pass
+
+
+class TestConnection:
+   """ simple test connector, has send and recv
methods.
+       code is ripped / stripped from HTTPConnection
:)
+   """
+
+   def __init__(self, host, port=None,
socket_type=socket.SOCK_STREAM):
+       self.sock = None
+       self.host = host
+       self.port = port
+       self.socket_type = socket_type
+
+   def connect(self):
+       """Connect to the host and port specified in
__init__."""
+       self.sock = socket.socket(socket.AF_INET,
self.socket_type)
+       self.sock.connect((self.host, self.port))
+
+       # hmm, don't know enough about UDP / python to
know if
+       # this works as expected!
+       self.fp = self.sock.makefile('wrb', 0)
+
+   def close(self):
+       """Close the connection to the server."""
+       if self.sock:
+           self.sock.close()   # close it manually...
there may be other refs
+           self.sock = None
+
+   def send(self, str):
+       """Send `str' to the server."""
+       if self.sock is None:
+           self.connect()
+
+       try:
+           self.fp.write(str)
+       except socket.error, v:
+           if v[0] == 32:  # Broken pipe
+               self.close()
+           raise
+
+   def read(self, len=0):
+       """read from socket
+       """
+       return self.fp.read(len)
+
+
+def test():
+   """ test method for SocketServer.py
+   """
+
+   def test_client_fn(server_addr='127.0.0.1',
server_port=10000,
+                      sock_type=socket.SOCK_STREAM):
+
+       clients = []
+       for n in range(20):
+           clients.append(TestConnection(server_addr,
server_port, sock_type))
+
+       for i in range(len(clients)):
+           c = clients[i]
+           c.send("echo test %d\n" % i)
+
+       for i in range(len(clients)):
+           c = clients[i]
+           expected_data = "echo test %d\n" % i
+           data = c.read(len(expected_data))
+           if data != expected_data:
+               print "client %d failed test"
+
+
+   def test_server_fn(ServerClass, server_addr,
HandlerClass):
+
+       srv = ServerClass(('', 10000), HandlerClass)
+       srv.max_children = 50
+       srv.serve_forever()
+   
+   def usage():
+       print "usage: --client, -c a test client"
+       print "       --thread-server, -t to run a
threading server"
+       print "       --fork-server, -f to run a
forking server"
+       print "       --udp, to run a UDP server"
+       print "       --tcp to run a TCP server"
+       sys.exit(0)
+
+   from getopt import getopt
+
+   if len(sys.argv) == 1:
+       usage()
+
+   opts, args = getopt(sys.argv[1:], 'hftc',
+                       ['help', 'fork-server',
'thread-server',
+                                  'udp', 'tcp',
+                                  'client'])
+
+   threading = None
+   forking = None
+   tcp = None
+   udp = None
+   testclass = None
+   testhandlerclass = None
+   sock_type = None
+   testclient = None
+
+   for (opt, value) in opts:
+
+       if opt == '--help' or opt == '-h':
+           usage()
+
+       if opt == '--tcp':
+           tcp = 1
+           sock_type = socket.SOCK_STREAM
+
+       if opt == '--udp':
+           udp = 1
+           sock_type = socket.SOCK_DGRAM
+
+       if opt == '--fork-server' or opt == '-f':
+           forking = 1
+
+       if opt == '--thread-server' or opt == '-t':
+           threading = 1
+
+       if opt == '--client' or opt == '-c':
+           testclient = 1
+
+   if tcp and forking:
+       testclass = ForkingTCPServer
+       testhandlerclass = EchoTCPHandler
+   if tcp and threading:
+       testclass = ThreadingTCPServer
+       testhandlerclass = EchoTCPHandler
+   if udp and forking:
+       testclass = ForkingUDPServer
+       testhandlerclass = EchoUDPHandler
+   if udp and threading:
+       testclass = ThreadingUDPServer
+       testhandlerclass = EchoUDPHandler
+
+   if testclass:
+       test_server_fn(testclass, 10000,
testhandlerclass)
+
+   if testclient:
+       test_client_fn('127.0.0.1', 10000, sock_type)
+
+if __name__ == '__main__':
+   test()

----------------------------------------------------------------------

>Comment By: Guido van Rossum (gvanrossum)
Date: 2001-07-28 14:38

Message:
Logged In: YES 
user_id=6380

Thanks, Martin.

I don't like having this much test code in the module, and
the important part of the test is done by
test_socketmodule.py, but I think there's one aspect that
this test code does better: it starts 20 test clients in
parallel.

Maybe that idea could be merged into test_socketmodule.py.


----------------------------------------------------------------------

Comment By: Martin v. Löwis (loewis)
Date: 2001-07-28 10:45

Message:
Logged In: YES 
user_id=21627

I've attached the patch as a proper diff file. Is it still 
needed even though we have test_socketserver.py?


----------------------------------------------------------------------

You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=419145&group_id=5470