From a4ba22fecc8db468377ab14f5652e4176f0488b7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 7 Dec 2016 09:30:49 -0500 Subject: DRTVWR-418: Revamp testrunner to shutdown server Thread at end. Instead of having testrunner.run()'s caller pass a Thread object on which to run the caller's server instance's serve_forever() method, just pass the server instance. testrunner.run() now constructs the Thread. This API change allows run() to also call shutdown() on the server instance when done, and then join() the Thread. The hope is that this will avoid the Python runtime forcing the process termination code to 1 due to forcibly killing the daemon thread still running serve_forever(). While at it, eliminate calls to testrunner.freeport() -- just make the runtime pick a suitable port instead. --- indra/newview/tests/test_llxmlrpc_peer.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'indra/newview/tests/test_llxmlrpc_peer.py') diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py index 281b72a058..12394ad1d9 100755 --- a/indra/newview/tests/test_llxmlrpc_peer.py +++ b/indra/newview/tests/test_llxmlrpc_peer.py @@ -35,11 +35,20 @@ from threading import Thread from SimpleXMLRPCServer import SimpleXMLRPCServer mydir = os.path.dirname(__file__) # expected to be .../indra/newview/tests/ -sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) -sys.path.insert(1, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests")) -from testrunner import freeport, run, debug +sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests")) +from testrunner import run, debug class TestServer(SimpleXMLRPCServer): + # This server_bind() override is borrowed and simplified from + # BaseHTTPServer.HTTPServer.server_bind(): we want to capture the actual + # server port. BaseHTTPServer.HTTPServer.server_bind() stores the actual + # port in a server_port attribute, but SimpleXMLRPCServer isn't derived + # from HTTPServer. So do it ourselves. + def server_bind(self): + """Override server_bind to store the server port.""" + SimpleXMLRPCServer.server_bind(self) + self.server_port = self.socket.getsockname()[1] + def _dispatch(self, method, params): try: func = getattr(self, method) @@ -67,15 +76,11 @@ class TestServer(SimpleXMLRPCServer): pass if __name__ == "__main__": - # Instantiate a TestServer 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. - xmlrpcd, port = freeport(xrange(8000, 8020), - lambda port: TestServer(('127.0.0.1', port))) + # Make the runtime choose an available port. + xmlrpcd = TestServer(('127.0.0.1', 0)) # 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="xmlrpc", target=xmlrpcd.serve_forever), *sys.argv[1:])) + os.environ["PORT"] = str(xmlrpcd.server_port) + sys.exit(run(server_inst=xmlrpcd, *sys.argv[1:])) -- cgit v1.2.3 From 5bb456d80cfbcdfe87526510f3b8297d315afdd8 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 7 Dec 2016 14:10:32 -0500 Subject: DRTVWR-418: Apparently (some) Windows hosts still need freeport(). This is the function in indra/llmessage/tests/testrunner.py that iterates through ports in a specified range, looking for an available one. Other platforms understand a specification of port 0 to mean: "You pick one. I'll just use whichever one you picked." --- indra/newview/tests/test_llxmlrpc_peer.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'indra/newview/tests/test_llxmlrpc_peer.py') diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py index 12394ad1d9..cff40aa4c2 100755 --- a/indra/newview/tests/test_llxmlrpc_peer.py +++ b/indra/newview/tests/test_llxmlrpc_peer.py @@ -31,12 +31,11 @@ $/LicenseInfo$ import os import sys -from threading import Thread from SimpleXMLRPCServer import SimpleXMLRPCServer mydir = os.path.dirname(__file__) # expected to be .../indra/newview/tests/ sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests")) -from testrunner import run, debug +from testrunner import freeport, run, debug class TestServer(SimpleXMLRPCServer): # This server_bind() override is borrowed and simplified from @@ -76,8 +75,18 @@ class TestServer(SimpleXMLRPCServer): pass if __name__ == "__main__": - # Make the runtime choose an available port. - xmlrpcd = TestServer(('127.0.0.1', 0)) + # function to make a server with specified port + make_server = lambda port: TestServer(('127.0.0.1', port)) + + if not sys.platform.startswith("win"): + # Instantiate a TestServer on a port chosen by the runtime. + xmlrpcd = make_server(0) + else: + # "Then there's Windows" + # Instantiate a TestServer on the first free port in the specified + # port range. + xmlrpcd, port = freeport(xrange(8000, 8020), make_server) + # 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 -- cgit v1.2.3