aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/tests/test_llsdmessage_peer.py
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmessage/tests/test_llsdmessage_peer.py')
-rw-r--r--linden/indra/llmessage/tests/test_llsdmessage_peer.py153
1 files changed, 153 insertions, 0 deletions
diff --git a/linden/indra/llmessage/tests/test_llsdmessage_peer.py b/linden/indra/llmessage/tests/test_llsdmessage_peer.py
new file mode 100644
index 0000000..655169d
--- /dev/null
+++ b/linden/indra/llmessage/tests/test_llsdmessage_peer.py
@@ -0,0 +1,153 @@
1#!/usr/bin/python
2"""\
3@file test_llsdmessage_peer.py
4@author Nat Goodspeed
5@date 2008-10-09
6@brief This script asynchronously runs the executable (with args) specified on
7 the command line, returning its result code. While that executable is
8 running, we provide dummy local services for use by C++ tests.
9
10$LicenseInfo:firstyear=2008&license=viewergpl$
11
12Copyright (c) 2008-2009, Linden Research, Inc.
13
14Second Life Viewer Source Code
15The source code in this file ("Source Code") is provided by Linden Lab
16to you under the terms of the GNU General Public License, version 2.0
17("GPL"), unless you have obtained a separate licensing agreement
18("Other License"), formally executed by you and Linden Lab. Terms of
19the GPL can be found in doc/GPL-license.txt in this distribution, or
20online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
21
22There are special exceptions to the terms and conditions of the GPL as
23it is applied to this Source Code. View the full text of the exception
24in the file doc/FLOSS-exception.txt in this software distribution, or
25online at
26http://secondlifegrid.net/programs/open_source/licensing/flossexception
27
28By copying, modifying or distributing this software, you acknowledge
29that you have read and understood your obligations described above,
30and agree to abide by those obligations.
31
32ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
33WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
34COMPLETENESS OR PERFORMANCE.
35$/LicenseInfo$
36"""
37
38import os
39import sys
40from threading import Thread
41from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
42mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tests/
43sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
44from indra.util.fastest_elementtree import parse as xml_parse
45from indra.base import llsd
46
47def debug(*args):
48 sys.stdout.writelines(args)
49 sys.stdout.flush()
50# comment out the line below to enable debug output
51debug = lambda *args: None
52
53class TestHTTPRequestHandler(BaseHTTPRequestHandler):
54 """This subclass of BaseHTTPRequestHandler is to receive and echo
55 LLSD-flavored messages sent by the C++ LLHTTPClient.
56 """
57 def read(self):
58 # The following logic is adapted from the library module
59 # SimpleXMLRPCServer.py.
60 # Get arguments by reading body of request.
61 # We read this in chunks to avoid straining
62 # socket.read(); around the 10 or 15Mb mark, some platforms
63 # begin to have problems (bug #792570).
64 try:
65 size_remaining = int(self.headers["content-length"])
66 except (KeyError, ValueError):
67 return ""
68 max_chunk_size = 10*1024*1024
69 L = []
70 while size_remaining:
71 chunk_size = min(size_remaining, max_chunk_size)
72 chunk = self.rfile.read(chunk_size)
73 L.append(chunk)
74 size_remaining -= len(chunk)
75 return ''.join(L)
76 # end of swiped read() logic
77
78 def read_xml(self):
79 # This approach reads the entire POST data into memory first
80 return llsd.parse(self.read())
81## # This approach attempts to stream in the LLSD XML from self.rfile,
82## # assuming that the underlying XML parser reads its input file
83## # incrementally. Unfortunately I haven't been able to make it work.
84## tree = xml_parse(self.rfile)
85## debug("Finished raw parse\n")
86## debug("parsed XML tree %s\n" % tree)
87## debug("parsed root node %s\n" % tree.getroot())
88## debug("root node tag %s\n" % tree.getroot().tag)
89## return llsd.to_python(tree.getroot())
90
91 def do_GET(self):
92 # Of course, don't attempt to read data.
93 self.answer(dict(reply="success", status=500,
94 reason="Your GET operation requested failure"))
95
96 def do_POST(self):
97 # Read the provided POST data.
98 self.answer(self.read_xml())
99
100 def answer(self, data):
101 if "fail" not in self.path:
102 response = llsd.format_xml(data.get("reply", llsd.LLSD("success")))
103 self.send_response(200)
104 self.send_header("Content-type", "application/llsd+xml")
105 self.send_header("Content-Length", str(len(response)))
106 self.end_headers()
107 self.wfile.write(response)
108 else: # fail requested
109 status = data.get("status", 500)
110 reason = data.get("reason",
111 self.responses.get(status,
112 ("fail requested",
113 "Your request specified failure status %s "
114 "without providing a reason" % status))[1])
115 self.send_error(status, reason)
116
117 def log_request(self, code, size=None):
118 # For present purposes, we don't want the request splattered onto
119 # stderr, as it would upset devs watching the test run
120 pass
121
122 def log_error(self, format, *args):
123 # Suppress error output as well
124 pass
125
126class TestHTTPServer(Thread):
127 def run(self):
128 httpd = HTTPServer(('127.0.0.1', 8000), TestHTTPRequestHandler)
129 debug("Starting HTTP server...\n")
130 httpd.serve_forever()
131
132def main(*args):
133 # Start HTTP server thread. Note that this and all other comm server
134 # threads should be daemon threads: we'll let them run "forever,"
135 # confident that the whole process will terminate when the main thread
136 # terminates, which will be when the test executable child process
137 # terminates.
138 httpThread = TestHTTPServer(name="httpd")
139 httpThread.setDaemon(True)
140 httpThread.start()
141 # choice of os.spawnv():
142 # - [v vs. l] pass a list of args vs. individual arguments,
143 # - [no p] don't use the PATH because we specifically want to invoke the
144 # executable passed as our first arg,
145 # - [no e] child should inherit this process's environment.
146 debug("Running %s...\n" % (" ".join(args)))
147 sys.stdout.flush()
148 rc = os.spawnv(os.P_WAIT, args[0], args)
149 debug("%s returned %s\n" % (args[0], rc))
150 return rc
151
152if __name__ == "__main__":
153 sys.exit(main(*sys.argv[1:]))