• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from DocXMLRPCServer import DocXMLRPCServer
2import httplib
3import sys
4from test import test_support
5threading = test_support.import_module('threading')
6import unittest
7
8def make_request_and_skipIf(condition, reason):
9    # If we skip the test, we have to make a request because
10    # 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
22def make_server():
23    serv = DocXMLRPCServer(("localhost", 0), logRequests=False)
24
25    try:
26        # Add some documentation
27        serv.set_server_title("DocXMLRPCServer Test Documentation")
28        serv.set_server_name("DocXMLRPCServer Test Docs")
29        serv.set_server_documentation(
30            "This is an XML-RPC server's documentation, but the server "
31            "can be used by POSTing to /RPC2. Try self.add, too.")
32
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)
52        return serv
53    except:
54        serv.server_close()
55        raise
56
57class DocXMLRPCHTTPGETServer(unittest.TestCase):
58    def setUp(self):
59        # Enable server feedback
60        DocXMLRPCServer._send_traceback_header = True
61
62        self.serv = make_server()
63        self.thread = threading.Thread(target=self.serv.serve_forever)
64        self.thread.start()
65
66        PORT = self.serv.server_address[1]
67        self.client = httplib.HTTPConnection("localhost:%d" % PORT)
68
69    def tearDown(self):
70        self.client.close()
71
72        # Disable server feedback
73        DocXMLRPCServer._send_traceback_header = False
74        self.serv.shutdown()
75        self.thread.join()
76        self.serv.server_close()
77
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
85        # Server raises an exception if we don't start to read the data
86        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
107        self.assertIn('<dl><dt><a name="-&lt;lambda&gt;"><strong>'
108                      '&lt;lambda&gt;</strong></a>(x, y)</dt></dl>',
109                      response.read())
110
111    @make_request_and_skipIf(sys.flags.optimize >= 2,
112                     "Docstrings are omitted with -O2 and above")
113    def test_autolinking(self):
114        """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.
117
118        The documentation for the "add" method contains the test material.
119        """
120        self.client.request("GET", "/")
121        response = self.client.getresponse()
122
123        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())
134
135    @make_request_and_skipIf(sys.flags.optimize >= 2,
136                     "Docstrings are omitted with -O2 and above")
137    def test_system_methods(self):
138        """Test the presence of three consecutive system.* methods.
139
140        This also tests their use of parameter type recognition and the
141        systems related to that process.
142        """
143        self.client.request("GET", "/")
144        response = self.client.getresponse()
145
146        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())
169
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
176        self.assertIn("""Try&nbsp;self.<strong>add</strong>,&nbsp;too.""",
177                      response.read())
178
179def test_main():
180    test_support.run_unittest(DocXMLRPCHTTPGETServer)
181
182if __name__ == '__main__':
183    test_main()
184