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