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="-<lambda>"><strong>' 108 '<lambda></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 two instances together. This ' 126 'follows <a href="http://www.python.org/dev/peps/pep-0008/">' 127 'PEP008</a>, but has nothing<br>\nto do ' 128 'with <a href="http://www.rfc-editor.org/rfc/rfc1952.txt">' 129 'RFC1952</a>. Case should matter: pEp008 ' 130 'and rFC1952. Things<br>\nthat start ' 131 'with http and ftp should be ' 132 'auto-linked, 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>() => [\'add\', \'subtract\',' 150 ' \'multiple\']<br>\n <br>\nReturns a list' 151 ' of the methods supported by the' 152 ' 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\') ' 155 '=> "Adds two integers together"<br>\n ' 156 '<br>\nReturns a string containing documentation' 157 ' for the specified 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\') ' 161 '=> [double, int, int]<br>\n <br>\nReturns' 162 ' a list describing the signature of' 163 ' the method. In the<br>\nabove example,' 164 ' the add method takes two integers' 165 ' as arguments<br>\nand returns a double' 166 ' result.<br>\n <br>\nThis server does ' 167 'NOT support 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 self.<strong>add</strong>, too.""", 177 response.read()) 178 179def test_main(): 180 test_support.run_unittest(DocXMLRPCHTTPGETServer) 181 182if __name__ == '__main__': 183 test_main() 184