blob: d0b604cccbc310e389b80bb5ebfee0d546a231b8 [file] [log] [blame]
Georg Brandl38eceaa2008-05-26 11:14:17 +00001from xmlrpc.server import DocXMLRPCServer
Georg Brandl24420152008-05-26 16:32:26 +00002import http.client
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003from test import support
Christian Heimes2f1019e2007-12-10 16:18:49 +00004import threading
5import time
6import unittest
Christian Heimes2f1019e2007-12-10 16:18:49 +00007
8PORT = None
9
10def server(evt, numrequests):
Benjamin Petersonf10a79a2008-10-11 00:49:57 +000011 serv = DocXMLRPCServer(("localhost", 0), logRequests=False)
Christian Heimes2f1019e2007-12-10 16:18:49 +000012
Benjamin Petersonf10a79a2008-10-11 00:49:57 +000013 try:
Christian Heimes2f1019e2007-12-10 16:18:49 +000014 global PORT
15 PORT = serv.socket.getsockname()[1]
16
17 # Add some documentation
18 serv.set_server_title("DocXMLRPCServer Test Documentation")
19 serv.set_server_name("DocXMLRPCServer Test Docs")
20 serv.set_server_documentation(
Ezio Melottib58e0bd2010-01-23 15:40:09 +000021 "This is an XML-RPC server's documentation, but the server "
22 "can be used by POSTing to /RPC2. Try self.add, too.")
Christian Heimes2f1019e2007-12-10 16:18:49 +000023
24 # Create and register classes and functions
25 class TestClass(object):
26 def test_method(self, arg):
27 """Test method's docs. This method truly does very little."""
28 self.arg = arg
29
30 serv.register_introspection_functions()
31 serv.register_instance(TestClass())
32
33 def add(x, y):
34 """Add two instances together. This follows PEP008, but has nothing
35 to do with RFC1952. Case should matter: pEp008 and rFC1952. Things
36 that start with http and ftp should be auto-linked, too:
37 http://google.com.
38 """
39 return x + y
40
41 serv.register_function(add)
42 serv.register_function(lambda x, y: x-y)
43
44 while numrequests > 0:
45 serv.handle_request()
46 numrequests -= 1
47 except socket.timeout:
48 pass
49 finally:
50 serv.server_close()
51 PORT = None
52 evt.set()
53
54class DocXMLRPCHTTPGETServer(unittest.TestCase):
55 def setUp(self):
Antoine Pitroud52656b2009-10-30 17:34:49 +000056 self._threads = support.threading_setup()
Christian Heimes2f1019e2007-12-10 16:18:49 +000057 # Enable server feedback
58 DocXMLRPCServer._send_traceback_header = True
59
60 self.evt = threading.Event()
61 threading.Thread(target=server, args=(self.evt, 1)).start()
62
63 # wait for port to be assigned
64 n = 1000
65 while n > 0 and PORT is None:
66 time.sleep(0.001)
67 n -= 1
68
Georg Brandl24420152008-05-26 16:32:26 +000069 self.client = http.client.HTTPConnection("localhost:%d" % PORT)
Christian Heimes2f1019e2007-12-10 16:18:49 +000070
71 def tearDown(self):
72 self.client.close()
73
74 self.evt.wait()
75
76 # Disable server feedback
77 DocXMLRPCServer._send_traceback_header = False
Antoine Pitroud52656b2009-10-30 17:34:49 +000078 support.threading_cleanup(*self._threads)
Christian Heimes2f1019e2007-12-10 16:18:49 +000079
80 def test_valid_get_response(self):
81 self.client.request("GET", "/")
82 response = self.client.getresponse()
83
84 self.assertEqual(response.status, 200)
85 self.assertEqual(response.getheader("Content-type"), "text/html")
86
87 # Server throws an exception if we don't start to read the data
88 response.read()
89
90 def test_invalid_get_response(self):
91 self.client.request("GET", "/spam")
92 response = self.client.getresponse()
93
94 self.assertEqual(response.status, 404)
95 self.assertEqual(response.getheader("Content-type"), "text/plain")
96
97 response.read()
98
99 def test_lambda(self):
100 """Test that lambda functionality stays the same. The output produced
101 currently is, I suspect invalid because of the unencoded brackets in the
102 HTML, "<lambda>".
103
104 The subtraction lambda method is tested.
105 """
106 self.client.request("GET", "/")
107 response = self.client.getresponse()
108
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000109 self.assertIn((b'<dl><dt><a name="-&lt;lambda&gt;"><strong>'
110 b'&lt;lambda&gt;</strong></a>(x, y)</dt></dl>'),
111 response.read())
Christian Heimes2f1019e2007-12-10 16:18:49 +0000112
113 def test_autolinking(self):
114 """Test that the server correctly automatically wraps references to PEPS
115 and RFCs with links, and that it linkifies text starting with http or
116 ftp protocol prefixes.
117
118 The documentation for the "add" method contains the test material.
119 """
120 self.client.request("GET", "/")
Christian Heimes2202f872008-02-06 14:31:34 +0000121 response = self.client.getresponse().read()
Christian Heimes2f1019e2007-12-10 16:18:49 +0000122
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000123 self.assertIn(
124 (b'<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd>'
125 b'<tt>Add&nbsp;two&nbsp;instances&nbsp;together.&nbsp;This&nbsp;'
126 b'follows&nbsp;<a href="http://www.python.org/dev/peps/pep-0008/">'
127 b'PEP008</a>,&nbsp;but&nbsp;has&nbsp;nothing<br>\nto&nbsp;do&nbsp;'
128 b'with&nbsp;<a href="http://www.rfc-editor.org/rfc/rfc1952.txt">'
129 b'RFC1952</a>.&nbsp;Case&nbsp;should&nbsp;matter:&nbsp;pEp008&nbsp;'
130 b'and&nbsp;rFC1952.&nbsp;&nbsp;Things<br>\nthat&nbsp;start&nbsp;'
131 b'with&nbsp;http&nbsp;and&nbsp;ftp&nbsp;should&nbsp;be&nbsp;'
132 b'auto-linked,&nbsp;too:<br>\n<a href="http://google.com">'
133 b'http://google.com</a>.</tt></dd></dl>'), response)
Christian Heimes2f1019e2007-12-10 16:18:49 +0000134
135 def test_system_methods(self):
136 """Test the precense of three consecutive system.* methods.
137
138 This also tests their use of parameter type recognition and the systems
139 related to that process.
140 """
141 self.client.request("GET", "/")
Christian Heimesa5535f22007-12-10 20:18:07 +0000142 response = self.client.getresponse().read()
Christian Heimes2f1019e2007-12-10 16:18:49 +0000143
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000144 self.assertIn(
145 (b'<dl><dt><a name="-system.methodHelp"><strong>system.methodHelp'
146 b'</strong></a>(method_name)</dt><dd><tt><a href="#-system.method'
147 b'Help">system.methodHelp</a>(\'add\')&nbsp;=&gt;&nbsp;"Adds&nbsp;'
148 b'two&nbsp;integers&nbsp;together"<br>\n&nbsp;<br>\nReturns&nbsp;a'
149 b'&nbsp;string&nbsp;containing&nbsp;documentation&nbsp;for&nbsp;'
150 b'the&nbsp;specified&nbsp;method.</tt></dd></dl>\n<dl><dt><a name'
151 b'="-system.methodSignature"><strong>system.methodSignature</strong>'
152 b'</a>(method_name)</dt><dd><tt><a href="#-system.methodSignature">'
153 b'system.methodSignature</a>(\'add\')&nbsp;=&gt;&nbsp;[double,&nbsp;'
154 b'int,&nbsp;int]<br>\n&nbsp;<br>\nReturns&nbsp;a&nbsp;list&nbsp;'
155 b'describing&nbsp;the&nbsp;signature&nbsp;of&nbsp;the&nbsp;method.'
156 b'&nbsp;In&nbsp;the<br>\nabove&nbsp;example,&nbsp;the&nbsp;add&nbsp;'
157 b'method&nbsp;takes&nbsp;two&nbsp;integers&nbsp;as&nbsp;arguments'
158 b'<br>\nand&nbsp;returns&nbsp;a&nbsp;double&nbsp;result.<br>\n&nbsp;'
159 b'<br>\nThis&nbsp;server&nbsp;does&nbsp;NOT&nbsp;support&nbsp;system'
160 b'.methodSignature.</tt></dd></dl>\n<dl><dt><a name="-test_method">'
161 b'<strong>test_method</strong></a>(arg)</dt><dd><tt>Test&nbsp;'
162 b'method\'s&nbsp;docs.&nbsp;This&nbsp;method&nbsp;truly&nbsp;does'
163 b'&nbsp;very&nbsp;little.</tt></dd></dl>'), response)
Christian Heimes2f1019e2007-12-10 16:18:49 +0000164
165 def test_autolink_dotted_methods(self):
166 """Test that selfdot values are made strong automatically in the
167 documentation."""
168 self.client.request("GET", "/")
169 response = self.client.getresponse()
170
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000171 self.assertIn(b"""Try&nbsp;self.<strong>add</strong>,&nbsp;too.""",
172 response.read())
Christian Heimes2f1019e2007-12-10 16:18:49 +0000173
174def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000175 support.run_unittest(DocXMLRPCHTTPGETServer)
Christian Heimes2f1019e2007-12-10 16:18:49 +0000176
177if __name__ == '__main__':
178 test_main()