diff options
Diffstat (limited to 'indra/llmessage/tests/test_llsdmessage_peer.py')
-rwxr-xr-x[-rw-r--r--] | indra/llmessage/tests/test_llsdmessage_peer.py | 133 |
1 files changed, 100 insertions, 33 deletions
diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index 86d5761b1b..e45249b1cb 100644..100755 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python """\ @file test_llsdmessage_peer.py @author Nat Goodspeed @@ -7,8 +7,25 @@ the command line, returning its result code. While that executable is running, we provide dummy local services for use by C++ tests. -$LicenseInfo:firstyear=2008&license=viewergpl$ -Copyright (c) 2008, Linden Research, Inc. +$LicenseInfo:firstyear=2008&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2010, Linden Research, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; +version 2.1 of the License only. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ @@ -21,7 +38,10 @@ 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, VERBOSE +import time + +_storage=None class TestHTTPRequestHandler(BaseHTTPRequestHandler): """This subclass of BaseHTTPRequestHandler is to receive and echo @@ -55,52 +75,99 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): ## # assuming that the underlying XML parser reads its input file ## # incrementally. Unfortunately I haven't been able to make it work. ## tree = xml_parse(self.rfile) -## debug("Finished raw parse\n") -## debug("parsed XML tree %s\n" % tree) -## debug("parsed root node %s\n" % tree.getroot()) -## debug("root node tag %s\n" % tree.getroot().tag) +## debug("Finished raw parse") +## debug("parsed XML tree %s", tree) +## debug("parsed root node %s", tree.getroot()) +## debug("root node tag %s", tree.getroot().tag) ## return llsd.to_python(tree.getroot()) - def do_GET(self): + def do_HEAD(self): + self.do_GET(withdata=False) + + def do_GET(self, withdata=True): # Of course, don't attempt to read data. - self.answer(dict(reply="success", status=500, - reason="Your GET operation requested failure")) + data = dict(reply="success", body="avatar", random=17) + self.answer(data, withdata=withdata) def do_POST(self): # Read the provided POST data. self.answer(self.read_xml()) - def answer(self, data): - if "fail" not in self.path: - response = llsd.format_xml(data.get("reply", llsd.LLSD("success"))) - self.send_response(200) - self.send_header("Content-type", "application/llsd+xml") - self.send_header("Content-Length", str(len(response))) - self.end_headers() - self.wfile.write(response) - else: # fail requested + def do_PUT(self): + # Read the provided PUT data. + self.answer(self.read_xml()) + + def answer(self, data, withdata=True): + global _storage + debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path) + if "fail" in self.path or "test/error" in self.path: # 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", "Your request specified failure status %s " "without providing a reason" % status))[1]) + debug("fail requested: %s: %r", status, reason) self.send_error(status, reason) + else: + if "web/echo" in self.path: + pass + elif "test/timeout" in self.path: + time.sleep(5.0) + return + elif "test/storage" in self.path: + if "GET" == self.command: + data = _storage + else: + _storage = data + data = "ok" + else: + data = data.copy() # we're going to modify + # Ensure there's a "reply" key in data, even if there wasn't before + data["reply"] = data.get("reply", llsd.LLSD("success")) + response = llsd.format_xml(data) + debug("success: %s", response) + self.send_response(200) + self.send_header("Content-type", "application/llsd+xml") + self.send_header("Content-Length", str(len(response))) + self.end_headers() + if withdata: + self.wfile.write(response) + + if not VERBOSE: + # When VERBOSE is set, skip both these overrides because they exist to + # suppress output. - def log_request(self, code, size=None): - # For present purposes, we don't want the request splattered onto - # stderr, as it would upset devs watching the test run - pass + def log_request(self, code, size=None): + # For present purposes, we don't want the request splattered onto + # stderr, as it would upset devs watching the test run + pass - def log_error(self, format, *args): - # Suppress error output as well - pass + def log_error(self, format, *args): + # 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() +class Server(HTTPServer): + # This pernicious flag is on by default in HTTPServer. But proper + # operation of freeport() absolutely depends on it being off. + allow_reuse_address = False if __name__ == "__main__": - sys.exit(run(server=TestHTTPServer(name="httpd"), *sys.argv[1:])) + # 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)) + # 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:])) |