merge nats even newer fix for the llcorehttp test

master
Oz Linden 2016-12-07 10:09:58 -05:00
commit 232c359854
5 changed files with 93 additions and 65 deletions

View File

@ -1509,10 +1509,6 @@ void HttpRequestTestObjectType::test<14>()
ensure("Request executed in reasonable time", count < limit);
ensure("One handler invocation for request", mHandlerCalls == 1);
#if LL_WINDOWS
skip("This test causes our dummy server test_llcorehttp_peer.py to fail");
#endif
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
handle = req->requestStopThread(handlerp);

View File

@ -48,7 +48,7 @@ from llbase import llsd
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
"llmessage", "tests"))
from testrunner import freeport, run, debug, VERBOSE
from testrunner import run, debug, VERBOSE
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
"""This subclass of BaseHTTPRequestHandler is to receive and echo
@ -303,22 +303,17 @@ if __name__ == "__main__":
if option == "-V" or option == "--valgrind":
do_valgrind = True
# Instantiate a Server(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: Server(('127.0.0.1', port), TestHTTPRequestHandler))
# Instantiate a Server(TestHTTPRequestHandler) on a port chosen by the
# runtime.
httpd = Server(('127.0.0.1', 0), 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["LL_TEST_PORT"] = str(port)
debug("$LL_TEST_PORT = %s", port)
os.environ["LL_TEST_PORT"] = str(httpd.server_port)
debug("$LL_TEST_PORT = %s", httpd.server_port)
if do_valgrind:
args = ["valgrind", "--log-file=./valgrind.log"] + args
path_search = True
sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), use_path=path_search, *args))
sys.exit(run(server_inst=httpd, use_path=path_search, *args))

View File

@ -36,7 +36,7 @@ from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from llbase.fastest_elementtree import parse as xml_parse
from llbase import llsd
from testrunner import freeport, run, debug, VERBOSE
from testrunner import run, debug, VERBOSE
import time
_storage=None
@ -155,17 +155,13 @@ class Server(HTTPServer):
allow_reuse_address = False
if __name__ == "__main__":
# Instantiate a Server(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: Server(('127.0.0.1', port), TestHTTPRequestHandler))
# Instantiate a Server(TestHTTPRequestHandler) on a port chosen by the
# runtime.
httpd = Server(('127.0.0.1', 0), 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)
debug("$PORT = %s", port)
sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), *sys.argv[1:]))
os.environ["PORT"] = str(httpd.server_port)
debug("$PORT = %s", httpd.server_port)
sys.exit(run(server_inst=httpd, *sys.argv[1:]))

View File

@ -27,13 +27,12 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
$/LicenseInfo$
"""
from __future__ import with_statement
import os
import sys
import re
import errno
import socket
from threading import Thread
VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "0") # default to quiet
# Support usage such as INTEGRATION_TEST_VERBOSE=off -- distressing to user if
@ -47,6 +46,9 @@ if VERBOSE:
else:
debug = lambda *args: None
class Error(Exception):
pass
def freeport(portlist, expr):
"""
Find a free server port to use. Specifically, evaluate 'expr' (a
@ -141,39 +143,73 @@ def freeport(portlist, expr):
raise
def run(*args, **kwds):
"""All positional arguments collectively form a command line, executed as
a synchronous child process.
In addition, pass server=new_thread_instance as an explicit keyword (to
differentiate it from an additional command-line argument).
new_thread_instance should be an instantiated but not yet started Thread
subclass instance, e.g.:
run("python", "-c", 'print "Hello, world!"', server=TestHTTPServer(name="httpd"))
"""
# If there's no server= keyword arg, don't start a server thread: simply
# run a child process.
Run a specified command as a synchronous child process, optionally
launching a server Thread during the run.
All positional arguments collectively form a command line. The first
positional argument names the program file to execute.
Returns the termination code of the child process.
In addition, you may pass keyword-only arguments:
use_path=True: allow a simple filename as command and search PATH for that
filename. Otherwise the command must be a full pathname.
server_inst: an instance of a subclass of SocketServer.BaseServer.
When you pass server_inst, its serve_forever() method is called on a
separate Thread before the child process is run. It is shutdown() when the
child process terminates.
"""
# server= keyword arg is discontinued
try:
thread = kwds.pop("server")
except KeyError:
pass
else:
# Start server thread. Note that this and all other comm server
# threads should be daemon threads: we'll let them run "forever,"
# confident that the whole process will terminate when the main thread
# terminates, which will be when the child process terminates.
raise Error("Obsolete call to testrunner.run(): pass server_inst=, not server=")
try:
server_inst = kwds.pop("server_inst")
except KeyError:
# We're not starting a thread, so shutdown() is a no-op.
shutdown = lambda: None
else:
# Make a Thread on which to call server_inst.serve_forever().
thread = Thread(name="server", target=server_inst.serve_forever)
# Make this a "daemon" thread.
thread.setDaemon(True)
thread.start()
# choice of os.spawnv():
# - [v vs. l] pass a list of args vs. individual arguments,
# - [no p] don't use the PATH because we specifically want to invoke the
# executable passed as our first arg,
# - [no e] child should inherit this process's environment.
debug("Running %s...", " ".join(args))
if kwds.get("use_path", False):
rc = os.spawnvp(os.P_WAIT, args[0], args)
else:
rc = os.spawnv(os.P_WAIT, args[0], args)
debug("%s returned %s", args[0], rc)
return rc
# We used to simply call sys.exit() with the daemon thread still
# running -- but in recent versions of Python 2, even when you call
# sys.exit(0), apparently killing the thread causes the Python runtime
# to force the process termination code to 1. So try to play nice.
def shutdown():
# evidently this call blocks until shutdown is complete
server_inst.shutdown()
# which should make it straightforward to join()
thread.join()
try:
# choice of os.spawnv():
# - [v vs. l] pass a list of args vs. individual arguments,
# - [no p] don't use the PATH because we specifically want to invoke the
# executable passed as our first arg,
# - [no e] child should inherit this process's environment.
debug("Running %s...", " ".join(args))
if kwds.get("use_path", False):
rc = os.spawnvp(os.P_WAIT, args[0], args)
else:
rc = os.spawnv(os.P_WAIT, args[0], args)
debug("%s returned %s", args[0], rc)
return rc
finally:
shutdown()
# ****************************************************************************
# test code -- manual at this point, see SWAT-564

View File

@ -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:]))