1 | from DocXMLRPCServer import DocXMLRPCServer
|
---|
2 | import httplib
|
---|
3 | import sys
|
---|
4 | from test import test_support
|
---|
5 | threading = test_support.import_module('threading')
|
---|
6 | import time
|
---|
7 | import socket
|
---|
8 | import unittest
|
---|
9 |
|
---|
10 | PORT = None
|
---|
11 |
|
---|
12 | def make_request_and_skipIf(condition, reason):
|
---|
13 | # If we skip the test, we have to make a request because the
|
---|
14 | # the server created in setUp blocks expecting one to come in.
|
---|
15 | if not condition:
|
---|
16 | return lambda func: func
|
---|
17 | def decorator(func):
|
---|
18 | def make_request_and_skip(self):
|
---|
19 | self.client.request("GET", "/")
|
---|
20 | self.client.getresponse()
|
---|
21 | raise unittest.SkipTest(reason)
|
---|
22 | return make_request_and_skip
|
---|
23 | return decorator
|
---|
24 |
|
---|
25 |
|
---|
26 | def server(evt, numrequests):
|
---|
27 | serv = DocXMLRPCServer(("localhost", 0), logRequests=False)
|
---|
28 |
|
---|
29 | try:
|
---|
30 | global PORT
|
---|
31 | PORT = serv.socket.getsockname()[1]
|
---|
32 |
|
---|
33 | # Add some documentation
|
---|
34 | serv.set_server_title("DocXMLRPCServer Test Documentation")
|
---|
35 | serv.set_server_name("DocXMLRPCServer Test Docs")
|
---|
36 | serv.set_server_documentation(
|
---|
37 | "This is an XML-RPC server's documentation, but the server "
|
---|
38 | "can be used by POSTing to /RPC2. Try self.add, too.")
|
---|
39 |
|
---|
40 | # Create and register classes and functions
|
---|
41 | class TestClass(object):
|
---|
42 | def test_method(self, arg):
|
---|
43 | """Test method's docs. This method truly does very little."""
|
---|
44 | self.arg = arg
|
---|
45 |
|
---|
46 | serv.register_introspection_functions()
|
---|
47 | serv.register_instance(TestClass())
|
---|
48 |
|
---|
49 | def add(x, y):
|
---|
50 | """Add two instances together. This follows PEP008, but has nothing
|
---|
51 | to do with RFC1952. Case should matter: pEp008 and rFC1952. Things
|
---|
52 | that start with http and ftp should be auto-linked, too:
|
---|
53 | http://google.com.
|
---|
54 | """
|
---|
55 | return x + y
|
---|
56 |
|
---|
57 | serv.register_function(add)
|
---|
58 | serv.register_function(lambda x, y: x-y)
|
---|
59 |
|
---|
60 | while numrequests > 0:
|
---|
61 | serv.handle_request()
|
---|
62 | numrequests -= 1
|
---|
63 | except socket.timeout:
|
---|
64 | pass
|
---|
65 | finally:
|
---|
66 | serv.server_close()
|
---|
67 | PORT = None
|
---|
68 | evt.set()
|
---|
69 |
|
---|
70 | class DocXMLRPCHTTPGETServer(unittest.TestCase):
|
---|
71 | def setUp(self):
|
---|
72 | self._threads = test_support.threading_setup()
|
---|
73 | # Enable server feedback
|
---|
74 | DocXMLRPCServer._send_traceback_header = True
|
---|
75 |
|
---|
76 | self.evt = threading.Event()
|
---|
77 | threading.Thread(target=server, args=(self.evt, 1)).start()
|
---|
78 |
|
---|
79 | # wait for port to be assigned
|
---|
80 | n = 1000
|
---|
81 | while n > 0 and PORT is None:
|
---|
82 | time.sleep(0.001)
|
---|
83 | n -= 1
|
---|
84 |
|
---|
85 | self.client = httplib.HTTPConnection("localhost:%d" % PORT)
|
---|
86 |
|
---|
87 | def tearDown(self):
|
---|
88 | self.client.close()
|
---|
89 |
|
---|
90 | self.evt.wait()
|
---|
91 |
|
---|
92 | # Disable server feedback
|
---|
93 | DocXMLRPCServer._send_traceback_header = False
|
---|
94 | test_support.threading_cleanup(*self._threads)
|
---|
95 |
|
---|
96 | def test_valid_get_response(self):
|
---|
97 | self.client.request("GET", "/")
|
---|
98 | response = self.client.getresponse()
|
---|
99 |
|
---|
100 | self.assertEqual(response.status, 200)
|
---|
101 | self.assertEqual(response.getheader("Content-type"), "text/html")
|
---|
102 |
|
---|
103 | # Server raises an exception if we don't start to read the data
|
---|
104 | response.read()
|
---|
105 |
|
---|
106 | def test_invalid_get_response(self):
|
---|
107 | self.client.request("GET", "/spam")
|
---|
108 | response = self.client.getresponse()
|
---|
109 |
|
---|
110 | self.assertEqual(response.status, 404)
|
---|
111 | self.assertEqual(response.getheader("Content-type"), "text/plain")
|
---|
112 |
|
---|
113 | response.read()
|
---|
114 |
|
---|
115 | def test_lambda(self):
|
---|
116 | """Test that lambda functionality stays the same. The output produced
|
---|
117 | currently is, I suspect invalid because of the unencoded brackets in the
|
---|
118 | HTML, "<lambda>".
|
---|
119 |
|
---|
120 | The subtraction lambda method is tested.
|
---|
121 | """
|
---|
122 | self.client.request("GET", "/")
|
---|
123 | response = self.client.getresponse()
|
---|
124 |
|
---|
125 | self.assertIn('<dl><dt><a name="-<lambda>"><strong>'
|
---|
126 | '<lambda></strong></a>(x, y)</dt></dl>',
|
---|
127 | response.read())
|
---|
128 |
|
---|
129 | @make_request_and_skipIf(sys.flags.optimize >= 2,
|
---|
130 | "Docstrings are omitted with -O2 and above")
|
---|
131 | def test_autolinking(self):
|
---|
132 | """Test that the server correctly automatically wraps references to
|
---|
133 | PEPS and RFCs with links, and that it linkifies text starting with
|
---|
134 | http or ftp protocol prefixes.
|
---|
135 |
|
---|
136 | The documentation for the "add" method contains the test material.
|
---|
137 | """
|
---|
138 | self.client.request("GET", "/")
|
---|
139 | response = self.client.getresponse()
|
---|
140 |
|
---|
141 | self.assertIn(
|
---|
142 | ('<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd>'
|
---|
143 | '<tt>Add two instances together. This '
|
---|
144 | 'follows <a href="http://www.python.org/dev/peps/pep-0008/">'
|
---|
145 | 'PEP008</a>, but has nothing<br>\nto do '
|
---|
146 | 'with <a href="http://www.rfc-editor.org/rfc/rfc1952.txt">'
|
---|
147 | 'RFC1952</a>. Case should matter: pEp008 '
|
---|
148 | 'and rFC1952. Things<br>\nthat start '
|
---|
149 | 'with http and ftp should be '
|
---|
150 | 'auto-linked, too:<br>\n<a href="http://google.com">'
|
---|
151 | 'http://google.com</a>.</tt></dd></dl>'), response.read())
|
---|
152 |
|
---|
153 | @make_request_and_skipIf(sys.flags.optimize >= 2,
|
---|
154 | "Docstrings are omitted with -O2 and above")
|
---|
155 | def test_system_methods(self):
|
---|
156 | """Test the precense of three consecutive system.* methods.
|
---|
157 |
|
---|
158 | This also tests their use of parameter type recognition and the
|
---|
159 | systems related to that process.
|
---|
160 | """
|
---|
161 | self.client.request("GET", "/")
|
---|
162 | response = self.client.getresponse()
|
---|
163 |
|
---|
164 | self.assertIn(
|
---|
165 | ('<dl><dt><a name="-system.listMethods"><strong>system.listMethods'
|
---|
166 | '</strong></a>()</dt><dd><tt><a href="#-system.listMethods">system'
|
---|
167 | '.listMethods</a>() => [\'add\', \'subtract\','
|
---|
168 | ' \'multiple\']<br>\n <br>\nReturns a list'
|
---|
169 | ' of the methods supported by the'
|
---|
170 | ' server.</tt></dd></dl>\n <dl><dt><a name="-system.methodHelp">'
|
---|
171 | '<strong>system.methodHelp</strong></a>(method_name)</dt><dd><tt>'
|
---|
172 | '<a href="#-system.methodHelp">system.methodHelp</a>(\'add\') '
|
---|
173 | '=> "Adds two integers together"<br>\n '
|
---|
174 | '<br>\nReturns a string containing documentation'
|
---|
175 | ' for the specified method.</tt></dd></dl>\n '
|
---|
176 | '<dl><dt><a name="-system.methodSignature"><strong>system.'
|
---|
177 | 'methodSignature</strong></a>(method_name)</dt><dd><tt><a href="#-'
|
---|
178 | 'system.methodSignature">system.methodSignature</a>(\'add\') '
|
---|
179 | '=> [double, int, int]<br>\n <br>\nReturns'
|
---|
180 | ' a list describing the signature of'
|
---|
181 | ' the method. In the<br>\nabove example,'
|
---|
182 | ' the add method takes two integers'
|
---|
183 | ' as arguments<br>\nand returns a double'
|
---|
184 | ' result.<br>\n <br>\nThis server does '
|
---|
185 | 'NOT support system.methodSignature.</tt></dd></dl>'),
|
---|
186 | response.read())
|
---|
187 |
|
---|
188 | def test_autolink_dotted_methods(self):
|
---|
189 | """Test that selfdot values are made strong automatically in the
|
---|
190 | documentation."""
|
---|
191 | self.client.request("GET", "/")
|
---|
192 | response = self.client.getresponse()
|
---|
193 |
|
---|
194 | self.assertIn("""Try self.<strong>add</strong>, too.""",
|
---|
195 | response.read())
|
---|
196 |
|
---|
197 | def test_main():
|
---|
198 | test_support.run_unittest(DocXMLRPCHTTPGETServer)
|
---|
199 |
|
---|
200 | if __name__ == '__main__':
|
---|
201 | test_main()
|
---|