blob: 4dff4159e2466b78f939593e01c28f7b5517f989 [file] [log] [blame]
Georg Brandle6daafb2007-12-09 22:39:12 +00001from DocXMLRPCServer import DocXMLRPCServer
2import httplib
R. David Murrayf28fd242010-02-23 00:24:49 +00003import sys
Georg Brandle6daafb2007-12-09 22:39:12 +00004from test import test_support
Victor Stinner6a102812010-04-27 23:55:59 +00005threading = test_support.import_module('threading')
Georg Brandle6daafb2007-12-09 22:39:12 +00006import unittest
Georg Brandle6daafb2007-12-09 22:39:12 +00007
R. David Murrayf28fd242010-02-23 00:24:49 +00008def make_request_and_skipIf(condition, reason):
Serhiy Storchaka0f8f7842014-12-01 18:16:30 +02009 # If we skip the test, we have to make a request because
R. David Murrayf28fd242010-02-23 00:24:49 +000010 # the server created in setUp blocks expecting one to come in.
11 if not condition:
12 return lambda func: func
13 def decorator(func):
14 def make_request_and_skip(self):
15 self.client.request("GET", "/")
16 self.client.getresponse()
17 raise unittest.SkipTest(reason)
18 return make_request_and_skip
19 return decorator
20
21
Martin Panter3911d832016-08-18 06:12:22 +000022def make_server():
Hirokazu Yamamotob7df32e2008-10-03 16:18:42 +000023 serv = DocXMLRPCServer(("localhost", 0), logRequests=False)
Georg Brandle6daafb2007-12-09 22:39:12 +000024
Hirokazu Yamamotob7df32e2008-10-03 16:18:42 +000025 try:
Georg Brandle6daafb2007-12-09 22:39:12 +000026 # Add some documentation
27 serv.set_server_title("DocXMLRPCServer Test Documentation")
28 serv.set_server_name("DocXMLRPCServer Test Docs")
29 serv.set_server_documentation(
Ezio Melottiaa980582010-01-23 23:04:36 +000030 "This is an XML-RPC server's documentation, but the server "
31 "can be used by POSTing to /RPC2. Try self.add, too.")
Georg Brandle6daafb2007-12-09 22:39:12 +000032
33 # Create and register classes and functions
34 class TestClass(object):
35 def test_method(self, arg):
36 """Test method's docs. This method truly does very little."""
37 self.arg = arg
38
39 serv.register_introspection_functions()
40 serv.register_instance(TestClass())
41
42 def add(x, y):
43 """Add two instances together. This follows PEP008, but has nothing
44 to do with RFC1952. Case should matter: pEp008 and rFC1952. Things
45 that start with http and ftp should be auto-linked, too:
46 http://google.com.
47 """
48 return x + y
49
50 serv.register_function(add)
51 serv.register_function(lambda x, y: x-y)
Martin Panter3911d832016-08-18 06:12:22 +000052 return serv
53 except:
Georg Brandle6daafb2007-12-09 22:39:12 +000054 serv.server_close()
Martin Panter3911d832016-08-18 06:12:22 +000055 raise
Georg Brandle6daafb2007-12-09 22:39:12 +000056
57class DocXMLRPCHTTPGETServer(unittest.TestCase):
58 def setUp(self):
59 # Enable server feedback
60 DocXMLRPCServer._send_traceback_header = True
61
Martin Panter3911d832016-08-18 06:12:22 +000062 self.serv = make_server()
63 self.thread = threading.Thread(target=self.serv.serve_forever)
64 self.thread.start()
Georg Brandle6daafb2007-12-09 22:39:12 +000065
Martin Panter3911d832016-08-18 06:12:22 +000066 PORT = self.serv.server_address[1]
Georg Brandle6daafb2007-12-09 22:39:12 +000067 self.client = httplib.HTTPConnection("localhost:%d" % PORT)
68
69 def tearDown(self):
70 self.client.close()
71
Georg Brandle6daafb2007-12-09 22:39:12 +000072 # Disable server feedback
73 DocXMLRPCServer._send_traceback_header = False
Martin Panter3911d832016-08-18 06:12:22 +000074 self.serv.shutdown()
75 self.thread.join()
76 self.serv.server_close()
Georg Brandle6daafb2007-12-09 22:39:12 +000077
78 def test_valid_get_response(self):
79 self.client.request("GET", "/")
80 response = self.client.getresponse()
81
82 self.assertEqual(response.status, 200)
83 self.assertEqual(response.getheader("Content-type"), "text/html")
84
Andrew Svetlov4bb142b2012-12-18 21:27:37 +020085 # Server raises an exception if we don't start to read the data
Georg Brandle6daafb2007-12-09 22:39:12 +000086 response.read()
87
88 def test_invalid_get_response(self):
89 self.client.request("GET", "/spam")
90 response = self.client.getresponse()
91
92 self.assertEqual(response.status, 404)
93 self.assertEqual(response.getheader("Content-type"), "text/plain")
94
95 response.read()
96
97 def test_lambda(self):
98 """Test that lambda functionality stays the same. The output produced
99 currently is, I suspect invalid because of the unencoded brackets in the
100 HTML, "<lambda>".
101
102 The subtraction lambda method is tested.
103 """
104 self.client.request("GET", "/")
105 response = self.client.getresponse()
106
Ezio Melottiaa980582010-01-23 23:04:36 +0000107 self.assertIn('<dl><dt><a name="-&lt;lambda&gt;"><strong>'
108 '&lt;lambda&gt;</strong></a>(x, y)</dt></dl>',
109 response.read())
Georg Brandle6daafb2007-12-09 22:39:12 +0000110
R. David Murrayf28fd242010-02-23 00:24:49 +0000111 @make_request_and_skipIf(sys.flags.optimize >= 2,
112 "Docstrings are omitted with -O2 and above")
Georg Brandle6daafb2007-12-09 22:39:12 +0000113 def test_autolinking(self):
R. David Murrayf28fd242010-02-23 00:24:49 +0000114 """Test that the server correctly automatically wraps references to
115 PEPS and RFCs with links, and that it linkifies text starting with
116 http or ftp protocol prefixes.
Georg Brandle6daafb2007-12-09 22:39:12 +0000117
118 The documentation for the "add" method contains the test material.
119 """
120 self.client.request("GET", "/")
121 response = self.client.getresponse()
122
Ezio Melottiaa980582010-01-23 23:04:36 +0000123 self.assertIn(
124 ('<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd>'
125 '<tt>Add&nbsp;two&nbsp;instances&nbsp;together.&nbsp;This&nbsp;'
126 'follows&nbsp;<a href="http://www.python.org/dev/peps/pep-0008/">'
127 'PEP008</a>,&nbsp;but&nbsp;has&nbsp;nothing<br>\nto&nbsp;do&nbsp;'
128 'with&nbsp;<a href="http://www.rfc-editor.org/rfc/rfc1952.txt">'
129 'RFC1952</a>.&nbsp;Case&nbsp;should&nbsp;matter:&nbsp;pEp008&nbsp;'
130 'and&nbsp;rFC1952.&nbsp;&nbsp;Things<br>\nthat&nbsp;start&nbsp;'
131 'with&nbsp;http&nbsp;and&nbsp;ftp&nbsp;should&nbsp;be&nbsp;'
132 'auto-linked,&nbsp;too:<br>\n<a href="http://google.com">'
133 'http://google.com</a>.</tt></dd></dl>'), response.read())
Georg Brandle6daafb2007-12-09 22:39:12 +0000134
R. David Murrayf28fd242010-02-23 00:24:49 +0000135 @make_request_and_skipIf(sys.flags.optimize >= 2,
136 "Docstrings are omitted with -O2 and above")
Georg Brandle6daafb2007-12-09 22:39:12 +0000137 def test_system_methods(self):
Martin Panter3d36f0f2016-07-28 02:37:04 +0000138 """Test the presence of three consecutive system.* methods.
Georg Brandle6daafb2007-12-09 22:39:12 +0000139
R. David Murrayf28fd242010-02-23 00:24:49 +0000140 This also tests their use of parameter type recognition and the
141 systems related to that process.
Georg Brandle6daafb2007-12-09 22:39:12 +0000142 """
143 self.client.request("GET", "/")
144 response = self.client.getresponse()
145
Ezio Melottiaa980582010-01-23 23:04:36 +0000146 self.assertIn(
147 ('<dl><dt><a name="-system.listMethods"><strong>system.listMethods'
148 '</strong></a>()</dt><dd><tt><a href="#-system.listMethods">system'
149 '.listMethods</a>()&nbsp;=&gt;&nbsp;[\'add\',&nbsp;\'subtract\','
150 '&nbsp;\'multiple\']<br>\n&nbsp;<br>\nReturns&nbsp;a&nbsp;list'
151 '&nbsp;of&nbsp;the&nbsp;methods&nbsp;supported&nbsp;by&nbsp;the'
152 '&nbsp;server.</tt></dd></dl>\n <dl><dt><a name="-system.methodHelp">'
153 '<strong>system.methodHelp</strong></a>(method_name)</dt><dd><tt>'
154 '<a href="#-system.methodHelp">system.methodHelp</a>(\'add\')&nbsp;'
155 '=&gt;&nbsp;"Adds&nbsp;two&nbsp;integers&nbsp;together"<br>\n&nbsp;'
156 '<br>\nReturns&nbsp;a&nbsp;string&nbsp;containing&nbsp;documentation'
157 '&nbsp;for&nbsp;the&nbsp;specified&nbsp;method.</tt></dd></dl>\n '
158 '<dl><dt><a name="-system.methodSignature"><strong>system.'
159 'methodSignature</strong></a>(method_name)</dt><dd><tt><a href="#-'
160 'system.methodSignature">system.methodSignature</a>(\'add\')&nbsp;'
161 '=&gt;&nbsp;[double,&nbsp;int,&nbsp;int]<br>\n&nbsp;<br>\nReturns'
162 '&nbsp;a&nbsp;list&nbsp;describing&nbsp;the&nbsp;signature&nbsp;of'
163 '&nbsp;the&nbsp;method.&nbsp;In&nbsp;the<br>\nabove&nbsp;example,'
164 '&nbsp;the&nbsp;add&nbsp;method&nbsp;takes&nbsp;two&nbsp;integers'
165 '&nbsp;as&nbsp;arguments<br>\nand&nbsp;returns&nbsp;a&nbsp;double'
166 '&nbsp;result.<br>\n&nbsp;<br>\nThis&nbsp;server&nbsp;does&nbsp;'
167 'NOT&nbsp;support&nbsp;system.methodSignature.</tt></dd></dl>'),
168 response.read())
Georg Brandle6daafb2007-12-09 22:39:12 +0000169
170 def test_autolink_dotted_methods(self):
171 """Test that selfdot values are made strong automatically in the
172 documentation."""
173 self.client.request("GET", "/")
174 response = self.client.getresponse()
175
Ezio Melottiaa980582010-01-23 23:04:36 +0000176 self.assertIn("""Try&nbsp;self.<strong>add</strong>,&nbsp;too.""",
177 response.read())
Georg Brandle6daafb2007-12-09 22:39:12 +0000178
179def test_main():
180 test_support.run_unittest(DocXMLRPCHTTPGETServer)
181
182if __name__ == '__main__':
183 test_main()