From 8e8eb76eb9d0efabc82fec194f6edb4838c49955 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 10 May 2011 08:21:21 -0400 Subject: CHOP-661: add and use code to listen on next available server port. In indra/llmessage/tests/testrunner.py, introduce new freeport() function to try a caller-specified expression (such as instantiating an object that will listen on a server port) with a range of candidate port numbers until the expression produces a value instead of EADDRINUSE exception. Change test_llsdmessage_peer.py and test_llxmlrpc_peer.py to use freeport() to construct their server class inline BEFORE launching the thread that will run it, then pass that server's serve_forever method to daemon thread. Also set os.environ["PORT"] to selected environment variable before running subject test program. In indra/llmessage/tests/commtest.h, introduce commtest_data::getport() to read port number from specified environment variable, throwing exception if variable not set or non-numeric. Construct default LLHost from getport("PORT") instead of hardcoded constant. Change indra/newview/tests/llxmlrpclistener_test.cpp to use commtest_data:: getport("PORT") instead of hardcoded constant. Also use LLSD::with() rather than older LLSD::insert() syntax. HOWEVER -- I am irritated to discover that llxmlrpclistener_test IS NOT RUN or even built by newview/CMakeLists.txt! It's not even commented out -- it's entirely deleted! I am determined to restore this test. However, as it will take some fiddling with new link-time dependencies, that will be a separate commit. --- indra/llmessage/tests/test_llsdmessage_peer.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'indra/llmessage/tests/test_llsdmessage_peer.py') diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index 580ee7f8b4..cea5032111 100644 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -38,7 +38,7 @@ mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tes sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) from indra.util.fastest_elementtree import parse as xml_parse from indra.base import llsd -from testrunner import run, debug +from testrunner import freeport, run, debug class TestHTTPRequestHandler(BaseHTTPRequestHandler): """This subclass of BaseHTTPRequestHandler is to receive and echo @@ -97,6 +97,10 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): self.wfile.write(response) else: # fail requested status = data.get("status", 500) + # self.responses maps an int status to a (short, long) pair of + # strings. We want the longer string. That's why we pass a string + # pair to get(): the [1] will select the second string, whether it + # came from self.responses or from our default pair. reason = data.get("reason", self.responses.get(status, ("fail requested", @@ -113,11 +117,17 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): # Suppress error output as well pass -class TestHTTPServer(Thread): - def run(self): - httpd = HTTPServer(('127.0.0.1', 8000), TestHTTPRequestHandler) - debug("Starting HTTP server...\n") - httpd.serve_forever() - if __name__ == "__main__": - sys.exit(run(server=TestHTTPServer(name="httpd"), *sys.argv[1:])) + # Instantiate an HTTPServer(TestHTTPRequestHandler) on the first free port + # in the specified port range. Doing this inline is better than in a + # daemon thread: if it blows up here, we'll get a traceback. If it blew up + # in some other thread, the traceback would get eaten and we'd run the + # subject test program anyway. + httpd, port = freeport(xrange(8000, 8020), + lambda port: HTTPServer(('127.0.0.1', port), TestHTTPRequestHandler)) + # Pass the selected port number to the subject test program via the + # environment. We don't want to impose requirements on the test program's + # command-line parsing -- and anyway, for C++ integration tests, that's + # performed in TUT code rather than our own. + os.environ["PORT"] = str(port) + sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), *sys.argv[1:])) -- cgit v1.3