From: <zy...@us...> - 2010-10-06 22:00:30
|
Revision: 7137 http://jython.svn.sourceforge.net/jython/?rev=7137&view=rev Author: zyasoft Date: 2010-10-06 22:00:23 +0000 (Wed, 06 Oct 2010) Log Message: ----------- Added socket server test (navie multithreaded server, thread pool using client) to verify that the memory leak for #1662 remains fixed. Modified Paths: -------------- trunk/jython/Lib/test/test_threading_jy.py Added Paths: ----------- trunk/jython/Lib/test/socketserver_test.py Added: trunk/jython/Lib/test/socketserver_test.py =================================================================== --- trunk/jython/Lib/test/socketserver_test.py (rev 0) +++ trunk/jython/Lib/test/socketserver_test.py 2010-10-06 22:00:23 UTC (rev 7137) @@ -0,0 +1,59 @@ +# Used by test_threading_jy.py to verify no memory leaks in using a +# relatively large number of threads. This is of course an absolutely +# silly way to write real code on the JVM :), use a thread pool. So +# just for testing. +# +# However, the client here does use a thread pool. +# +# TODO monitor heap consumption too from appropriate MBean. Then we +# could presumably be adaptive or something clever like that. +# +# Test for http://bugs.jython.org/issue1660 + +import socket +import threading +import SocketServer +import time +from java.lang import Runtime +from java.util.concurrent import Executors, ExecutorCompletionService + +class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): + + def handle(self): + data = self.request.recv(1024) + cur_thread = threading.currentThread() + response = "%s: %s" % (cur_thread.getName(), data) + self.request.send(response) + +class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): + "mix together" + +def client(ip, port, message): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((ip, port)) + sock.send(message) + response = sock.recv(1024) + # print threading.currentThread().getName(), response + sock.close() + +if __name__ == "__main__": + # ephemeral ports should work on every Java system now + HOST, PORT = "localhost", 0 + + server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) + ip, port = server.server_address + + # Start a daemon thread with the server -- that thread will then start one + # more thread for each request + server_thread = threading.Thread(target=server.serve_forever) + server_thread.setDaemon(True) + server_thread.start() + + # create a client pool to run all client requests + pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1) + ecs = ExecutorCompletionService(pool) + for i in xrange(4000): # empirically, this will exhaust heap when run with 16m heap + ecs.submit(lambda: client(ip, port, "Hello World %i" % i)) + ecs.take() # wait until we have a thread available in the pool + pool.shutdown() + Modified: trunk/jython/Lib/test/test_threading_jy.py =================================================================== --- trunk/jython/Lib/test/test_threading_jy.py 2010-10-05 22:26:34 UTC (rev 7136) +++ trunk/jython/Lib/test/test_threading_jy.py 2010-10-06 22:00:23 UTC (rev 7137) @@ -4,11 +4,15 @@ """ from __future__ import with_statement +import random +import subprocess +import sys +import threading +import time import unittest + +from subprocess import PIPE, Popen from test import test_support -import threading -import time -import random from threading import Condition, Lock, Thread from java.lang import Thread as JThread, InterruptedException @@ -84,8 +88,24 @@ self.assertEqual(joined_threads, num_threads) +class MemoryLeakTestCase(unittest.TestCase): + def test_socket_server(self): + # run socketserver with a small amount of memory; verify it exits cleanly + + + rc = subprocess.call([sys.executable, + "-J-Xmx32m", + test_support.findfile("socketserver_test.py")]) + # stdout=PIPE) + self.assertEquals(rc, 0) + + def test_main(): - test_support.run_unittest(JavaIntegrationTestCase, ThreadingTestCase, TwistedTestCase) + test_support.run_unittest( + JavaIntegrationTestCase, + MemoryLeakTestCase, + ThreadingTestCase, + TwistedTestCase) if __name__ == "__main__": This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |