blob: d48058ca6304378e0a4ae3a937a91877528ab66a [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(
21"""This is an XML-RPC server's documentation, but the server can be used by
22POSTing to /RPC2. Try self.add, too.""")
23
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
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000109 self.assertTrue(
Christian Heimesa5535f22007-12-10 20:18:07 +0000110b"""<dl><dt><a name="-&lt;lambda&gt;"><strong>&lt;lambda&gt;</strong></a>(x, y)</dt></dl>"""
Christian Heimes2f1019e2007-12-10 16:18:49 +0000111 in response.read())
112
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
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000123 self.assertTrue( # This is ugly ... how can it be made better?
Christian Heimes2202f872008-02-06 14:31:34 +0000124b"""<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd><tt>Add&nbsp;two&nbsp;instances&nbsp;together.&nbsp;This&nbsp;follows&nbsp;<a href="http://www.python.org/dev/peps/pep-0008/">PEP008</a>,&nbsp;but&nbsp;has&nbsp;nothing<br>\nto&nbsp;do&nbsp;with&nbsp;<a href="http://www.rfc-editor.org/rfc/rfc1952.txt">RFC1952</a>.&nbsp;Case&nbsp;should&nbsp;matter:&nbsp;pEp008&nbsp;and&nbsp;rFC1952.&nbsp;&nbsp;Things<br>\nthat&nbsp;start&nbsp;with&nbsp;http&nbsp;and&nbsp;ftp&nbsp;should&nbsp;be&nbsp;auto-linked,&nbsp;too:<br>\n<a href="http://google.com">http://google.com</a>.</tt></dd></dl>"""
125 in response, response)
Christian Heimes2f1019e2007-12-10 16:18:49 +0000126
127 def test_system_methods(self):
128 """Test the precense of three consecutive system.* methods.
129
130 This also tests their use of parameter type recognition and the systems
131 related to that process.
132 """
133 self.client.request("GET", "/")
Christian Heimesa5535f22007-12-10 20:18:07 +0000134 response = self.client.getresponse().read()
Christian Heimes2f1019e2007-12-10 16:18:49 +0000135
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000136 self.assertTrue(
Christian Heimesa5535f22007-12-10 20:18:07 +0000137b"""<dl><dt><a name="-system.methodHelp"><strong>system.methodHelp</strong></a>(method_name)</dt><dd><tt><a href="#-system.methodHelp">system.methodHelp</a>(\'add\')&nbsp;=&gt;&nbsp;"Adds&nbsp;two&nbsp;integers&nbsp;together"<br>\n&nbsp;<br>\nReturns&nbsp;a&nbsp;string&nbsp;containing&nbsp;documentation&nbsp;for&nbsp;the&nbsp;specified&nbsp;method.</tt></dd></dl>\n<dl><dt><a name="-system.methodSignature"><strong>system.methodSignature</strong></a>(method_name)</dt><dd><tt><a href="#-system.methodSignature">system.methodSignature</a>(\'add\')&nbsp;=&gt;&nbsp;[double,&nbsp;int,&nbsp;int]<br>\n&nbsp;<br>\nReturns&nbsp;a&nbsp;list&nbsp;describing&nbsp;the&nbsp;signature&nbsp;of&nbsp;the&nbsp;method.&nbsp;In&nbsp;the<br>\nabove&nbsp;example,&nbsp;the&nbsp;add&nbsp;method&nbsp;takes&nbsp;two&nbsp;integers&nbsp;as&nbsp;arguments<br>\nand&nbsp;returns&nbsp;a&nbsp;double&nbsp;result.<br>\n&nbsp;<br>\nThis&nbsp;server&nbsp;does&nbsp;NOT&nbsp;support&nbsp;system.methodSignature.</tt></dd></dl>\n<dl><dt><a name="-test_method"><strong>test_method</strong></a>(arg)</dt><dd><tt>Test&nbsp;method\'s&nbsp;docs.&nbsp;This&nbsp;method&nbsp;truly&nbsp;does&nbsp;very&nbsp;little.</tt></dd></dl>""" in response)
Christian Heimes2f1019e2007-12-10 16:18:49 +0000138
139 def test_autolink_dotted_methods(self):
140 """Test that selfdot values are made strong automatically in the
141 documentation."""
142 self.client.request("GET", "/")
143 response = self.client.getresponse()
144
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000145 self.assertTrue(b"""Try&nbsp;self.<strong>add</strong>,&nbsp;too.""" in
Christian Heimes2f1019e2007-12-10 16:18:49 +0000146 response.read())
147
148def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000149 support.run_unittest(DocXMLRPCHTTPGETServer)
Christian Heimes2f1019e2007-12-10 16:18:49 +0000150
151if __name__ == '__main__':
152 test_main()