blob: 24c36cf304a9da33ce15cbbf1e27fec82c9af8ce [file] [log] [blame]
Facundo Batista5a3b5242007-07-13 10:43:44 +00001import base64
Fred Drakeba613c32005-02-10 18:33:30 +00002import datetime
Skip Montanaro3e7bba92001-10-19 16:06:52 +00003import sys
Facundo Batista5a3b5242007-07-13 10:43:44 +00004import time
Skip Montanaro419abda2001-10-01 17:47:44 +00005import unittest
6import xmlrpclib
Facundo Batistaa53872b2007-08-14 13:35:00 +00007import SimpleXMLRPCServer
8import threading
Barry Warsaw04f357c2002-07-23 19:04:11 +00009from test import test_support
Skip Montanaro419abda2001-10-01 17:47:44 +000010
Fred Drake22c07062005-02-11 17:59:08 +000011try:
12 unicode
13except NameError:
14 have_unicode = False
15else:
16 have_unicode = True
17
Skip Montanaro419abda2001-10-01 17:47:44 +000018alist = [{'astring': 'foo@bar.baz.spam',
19 'afloat': 7283.43,
Skip Montanaro3e7bba92001-10-19 16:06:52 +000020 'anint': 2**20,
21 'ashortlong': 2L,
Skip Montanaro419abda2001-10-01 17:47:44 +000022 'anotherlist': ['.zyx.41'],
23 'abase64': xmlrpclib.Binary("my dog has fleas"),
24 'boolean': xmlrpclib.False,
Andrew M. Kuchlingb12d97c2004-06-05 12:33:27 +000025 'unicode': u'\u4000\u6000\u8000',
26 u'ukey\u4000': 'regular value',
Fred Drakeba613c32005-02-10 18:33:30 +000027 'datetime1': xmlrpclib.DateTime('20050210T11:41:23'),
28 'datetime2': xmlrpclib.DateTime(
29 (2005, 02, 10, 11, 41, 23, 0, 1, -1)),
30 'datetime3': xmlrpclib.DateTime(
31 datetime.datetime(2005, 02, 10, 11, 41, 23)),
Facundo Batista5a3b5242007-07-13 10:43:44 +000032 'datetime4': xmlrpclib.DateTime(
33 datetime.date(2005, 02, 10)),
34 'datetime5': xmlrpclib.DateTime(
35 datetime.time(11, 41, 23)),
Skip Montanaro419abda2001-10-01 17:47:44 +000036 }]
37
38class XMLRPCTestCase(unittest.TestCase):
39
40 def test_dump_load(self):
41 self.assertEquals(alist,
42 xmlrpclib.loads(xmlrpclib.dumps((alist,)))[0][0])
43
Fred Drakeba613c32005-02-10 18:33:30 +000044 def test_dump_bare_datetime(self):
Skip Montanaro174dd222005-05-14 20:54:16 +000045 # This checks that an unwrapped datetime.date object can be handled
46 # by the marshalling code. This can't be done via test_dump_load()
47 # since with use_datetime set to 1 the unmarshaller would create
48 # datetime objects for the 'datetime[123]' keys as well
Fred Drakeba613c32005-02-10 18:33:30 +000049 dt = datetime.datetime(2005, 02, 10, 11, 41, 23)
50 s = xmlrpclib.dumps((dt,))
Skip Montanaro174dd222005-05-14 20:54:16 +000051 (newdt,), m = xmlrpclib.loads(s, use_datetime=1)
52 self.assertEquals(newdt, dt)
Fred Drakeba613c32005-02-10 18:33:30 +000053 self.assertEquals(m, None)
54
Skip Montanaro174dd222005-05-14 20:54:16 +000055 (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
56 self.assertEquals(newdt, xmlrpclib.DateTime('20050210T11:41:23'))
57
58 def test_dump_bare_date(self):
59 # This checks that an unwrapped datetime.date object can be handled
60 # by the marshalling code. This can't be done via test_dump_load()
61 # since the unmarshaller produces a datetime object
62 d = datetime.datetime(2005, 02, 10, 11, 41, 23).date()
63 s = xmlrpclib.dumps((d,))
64 (newd,), m = xmlrpclib.loads(s, use_datetime=1)
65 self.assertEquals(newd.date(), d)
66 self.assertEquals(newd.time(), datetime.time(0, 0, 0))
67 self.assertEquals(m, None)
68
69 (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
70 self.assertEquals(newdt, xmlrpclib.DateTime('20050210T00:00:00'))
71
72 def test_dump_bare_time(self):
73 # This checks that an unwrapped datetime.time object can be handled
74 # by the marshalling code. This can't be done via test_dump_load()
75 # since the unmarshaller produces a datetime object
76 t = datetime.datetime(2005, 02, 10, 11, 41, 23).time()
77 s = xmlrpclib.dumps((t,))
78 (newt,), m = xmlrpclib.loads(s, use_datetime=1)
79 today = datetime.datetime.now().date().strftime("%Y%m%d")
80 self.assertEquals(newt.time(), t)
81 self.assertEquals(newt.date(), datetime.datetime.now().date())
82 self.assertEquals(m, None)
83
84 (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
85 self.assertEquals(newdt, xmlrpclib.DateTime('%sT11:41:23'%today))
86
Andrew M. Kuchlingbdb39012005-12-04 19:11:17 +000087 def test_bug_1164912 (self):
88 d = xmlrpclib.DateTime()
Tim Peters536cf992005-12-25 23:18:31 +000089 ((new_d,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((d,),
Andrew M. Kuchlingbdb39012005-12-04 19:11:17 +000090 methodresponse=True))
91 self.assert_(isinstance(new_d.value, str))
92
93 # Check that the output of dumps() is still an 8-bit string
94 s = xmlrpclib.dumps((new_d,), methodresponse=True)
95 self.assert_(isinstance(s, str))
96
Martin v. Löwis07529352006-11-19 18:51:54 +000097 def test_newstyle_class(self):
98 class T(object):
99 pass
100 t = T()
101 t.x = 100
102 t.y = "Hello"
103 ((t2,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((t,)))
104 self.assertEquals(t2, t.__dict__)
105
Skip Montanaro3e7bba92001-10-19 16:06:52 +0000106 def test_dump_big_long(self):
107 self.assertRaises(OverflowError, xmlrpclib.dumps, (2L**99,))
108
109 def test_dump_bad_dict(self):
110 self.assertRaises(TypeError, xmlrpclib.dumps, ({(1,2,3): 1},))
111
Facundo Batista5a3b5242007-07-13 10:43:44 +0000112 def test_dump_recursive_seq(self):
113 l = [1,2,3]
114 t = [3,4,5,l]
115 l.append(t)
116 self.assertRaises(TypeError, xmlrpclib.dumps, (l,))
117
118 def test_dump_recursive_dict(self):
119 d = {'1':1, '2':1}
120 t = {'3':3, 'd':d}
121 d['t'] = t
122 self.assertRaises(TypeError, xmlrpclib.dumps, (d,))
123
Skip Montanaro3e7bba92001-10-19 16:06:52 +0000124 def test_dump_big_int(self):
125 if sys.maxint > 2L**31-1:
126 self.assertRaises(OverflowError, xmlrpclib.dumps,
127 (int(2L**34),))
128
Facundo Batista5a3b5242007-07-13 10:43:44 +0000129 xmlrpclib.dumps((xmlrpclib.MAXINT, xmlrpclib.MININT))
130 self.assertRaises(OverflowError, xmlrpclib.dumps, (xmlrpclib.MAXINT+1,))
131 self.assertRaises(OverflowError, xmlrpclib.dumps, (xmlrpclib.MININT-1,))
132
133 def dummy_write(s):
134 pass
135
136 m = xmlrpclib.Marshaller()
137 m.dump_int(xmlrpclib.MAXINT, dummy_write)
138 m.dump_int(xmlrpclib.MININT, dummy_write)
139 self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MAXINT+1, dummy_write)
140 self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MININT-1, dummy_write)
141
142
Andrew M. Kuchling0b852032003-04-25 00:27:24 +0000143 def test_dump_none(self):
144 value = alist + [None]
145 arg1 = (alist + [None],)
146 strg = xmlrpclib.dumps(arg1, allow_none=True)
147 self.assertEquals(value,
148 xmlrpclib.loads(strg)[0][0])
149 self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,))
150
Fred Drake22c07062005-02-11 17:59:08 +0000151 def test_default_encoding_issues(self):
152 # SF bug #1115989: wrong decoding in '_stringify'
153 utf8 = """<?xml version='1.0' encoding='iso-8859-1'?>
154 <params>
155 <param><value>
156 <string>abc \x95</string>
157 </value></param>
158 <param><value>
159 <struct>
160 <member>
161 <name>def \x96</name>
162 <value><string>ghi \x97</string></value>
163 </member>
164 </struct>
165 </value></param>
166 </params>
167 """
Tim Petersf754f5f2005-04-08 18:00:59 +0000168
169 # sys.setdefaultencoding() normally doesn't exist after site.py is
170 # loaded. reload(sys) is the way to get it back.
Fred Drake22c07062005-02-11 17:59:08 +0000171 old_encoding = sys.getdefaultencoding()
Tim Petersf754f5f2005-04-08 18:00:59 +0000172 setdefaultencoding_existed = hasattr(sys, "setdefaultencoding")
Fred Drake22c07062005-02-11 17:59:08 +0000173 reload(sys) # ugh!
174 sys.setdefaultencoding("iso-8859-1")
175 try:
176 (s, d), m = xmlrpclib.loads(utf8)
177 finally:
178 sys.setdefaultencoding(old_encoding)
Tim Petersf754f5f2005-04-08 18:00:59 +0000179 if not setdefaultencoding_existed:
180 del sys.setdefaultencoding
181
Fred Drake22c07062005-02-11 17:59:08 +0000182 items = d.items()
183 if have_unicode:
184 self.assertEquals(s, u"abc \x95")
185 self.assert_(isinstance(s, unicode))
186 self.assertEquals(items, [(u"def \x96", u"ghi \x97")])
187 self.assert_(isinstance(items[0][0], unicode))
188 self.assert_(isinstance(items[0][1], unicode))
189 else:
190 self.assertEquals(s, "abc \xc2\x95")
191 self.assertEquals(items, [("def \xc2\x96", "ghi \xc2\x97")])
192
Facundo Batista5a3b5242007-07-13 10:43:44 +0000193
194class HelperTestCase(unittest.TestCase):
195 def test_escape(self):
196 self.assertEqual(xmlrpclib.escape("a&b"), "a&amp;b")
197 self.assertEqual(xmlrpclib.escape("a<b"), "a&lt;b")
198 self.assertEqual(xmlrpclib.escape("a>b"), "a&gt;b")
199
200class FaultTestCase(unittest.TestCase):
201 def test_repr(self):
202 f = xmlrpclib.Fault(42, 'Test Fault')
203 self.assertEqual(repr(f), "<Fault 42: 'Test Fault'>")
204 self.assertEqual(repr(f), str(f))
205
206 def test_dump_fault(self):
207 f = xmlrpclib.Fault(42, 'Test Fault')
208 s = xmlrpclib.dumps((f,))
209 (newf,), m = xmlrpclib.loads(s)
210 self.assertEquals(newf, {'faultCode': 42, 'faultString': 'Test Fault'})
211 self.assertEquals(m, None)
212
213 s = xmlrpclib.Marshaller().dumps(f)
214 self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, s)
215
216
217class DateTimeTestCase(unittest.TestCase):
218 def test_default(self):
219 t = xmlrpclib.DateTime()
220
221 def test_time(self):
222 d = 1181399930.036952
223 t = xmlrpclib.DateTime(d)
224 self.assertEqual(str(t), time.strftime("%Y%m%dT%H:%M:%S", time.localtime(d)))
225
226 def test_time_tuple(self):
227 d = (2007,6,9,10,38,50,5,160,0)
228 t = xmlrpclib.DateTime(d)
229 self.assertEqual(str(t), '20070609T10:38:50')
230
231 def test_time_struct(self):
232 d = time.localtime(1181399930.036952)
233 t = xmlrpclib.DateTime(d)
234 self.assertEqual(str(t), time.strftime("%Y%m%dT%H:%M:%S", d))
235
236 def test_datetime_datetime(self):
237 d = datetime.datetime(2007,1,2,3,4,5)
238 t = xmlrpclib.DateTime(d)
239 self.assertEqual(str(t), '20070102T03:04:05')
240
241 def test_datetime_date(self):
242 d = datetime.date(2007,9,8)
243 t = xmlrpclib.DateTime(d)
244 self.assertEqual(str(t), '20070908T00:00:00')
245
246 def test_datetime_time(self):
247 d = datetime.time(13,17,19)
248 # allow for date rollover by checking today's or tomorrow's dates
249 dd1 = datetime.datetime.now().date()
250 dd2 = dd1 + datetime.timedelta(days=1)
251 vals = (dd1.strftime('%Y%m%dT13:17:19'),
252 dd2.strftime('%Y%m%dT13:17:19'))
253 t = xmlrpclib.DateTime(d)
254 self.assertEqual(str(t) in vals, True)
255
256 def test_repr(self):
257 d = datetime.datetime(2007,1,2,3,4,5)
258 t = xmlrpclib.DateTime(d)
259 val ="<DateTime '20070102T03:04:05' at %x>" % id(t)
260 self.assertEqual(repr(t), val)
261
262 def test_decode(self):
263 d = ' 20070908T07:11:13 '
264 t1 = xmlrpclib.DateTime()
265 t1.decode(d)
266 tref = xmlrpclib.DateTime(datetime.datetime(2007,9,8,7,11,13))
267 self.assertEqual(t1, tref)
268
269 t2 = xmlrpclib._datetime(d)
270 self.assertEqual(t1, tref)
271
272class BinaryTestCase(unittest.TestCase):
273 def test_default(self):
274 t = xmlrpclib.Binary()
275 self.assertEqual(str(t), '')
276
277 def test_string(self):
278 d = '\x01\x02\x03abc123\xff\xfe'
279 t = xmlrpclib.Binary(d)
280 self.assertEqual(str(t), d)
281
282 def test_decode(self):
283 d = '\x01\x02\x03abc123\xff\xfe'
284 de = base64.encodestring(d)
285 t1 = xmlrpclib.Binary()
286 t1.decode(de)
287 self.assertEqual(str(t1), d)
288
289 t2 = xmlrpclib._binary(de)
290 self.assertEqual(str(t2), d)
291
292
Facundo Batistaa53872b2007-08-14 13:35:00 +0000293PORT = None
Skip Montanaro419abda2001-10-01 17:47:44 +0000294
Facundo Batistaa53872b2007-08-14 13:35:00 +0000295def http_server(evt, numrequests):
296 class TestInstanceClass:
297 def div(self, x, y):
298 '''This is the div function'''
299 return x // y
300
301
302 serv = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 0),
303 logRequests=False, bind_and_activate=False)
304
305 try:
306 serv.socket.settimeout(3)
307 serv.server_bind()
308 global PORT
309 PORT = serv.socket.getsockname()[1]
310 serv.server_activate()
311 serv.register_introspection_functions()
312 serv.register_multicall_functions()
313 serv.register_function(pow)
314 serv.register_function(lambda x,y: x+y, 'add')
315 serv.register_instance(TestInstanceClass())
316
317 # handle up to 'numrequests' requests
318 while numrequests > 0:
319 serv.handle_request()
320 numrequests -= 1
321
322 except socket.timeout:
323 pass
324 finally:
325 serv.socket.close()
326 PORT = None
327 evt.set()
328
329
330class HTTPTestCase(unittest.TestCase):
331 def setUp(self):
332 self.evt = threading.Event()
333 # start server thread to handle just one request
334 threading.Thread(target=http_server, args=(self.evt,2)).start()
335
336 # wait for port to be assigned to server
337 n = 1000
338 while n > 0 and PORT is None:
339 time.sleep(0.001)
340 n -= 1
341
342 time.sleep(0.5)
343
344 def tearDown(self):
345 # wait on the server thread to terminate
346 self.evt.wait()
347
348 def test_simple1(self):
349 p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
350 self.assertEqual(p.pow(6,8), 6**8)
351
352 def test_introspection1(self):
353 p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
354 meth = p.system.listMethods()
355 expected_methods = set(['pow', 'div', 'add', 'system.listMethods',
356 'system.methodHelp', 'system.methodSignature', 'system.multicall'])
357 self.assertEqual(set(meth), expected_methods)
358
359 def test_introspection2(self):
360 p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
361 divhelp = p.system.methodHelp('div')
362 self.assertEqual(divhelp, 'This is the div function')
363
364 def test_introspection3(self):
365 # the SimpleXMLRPCServer doesn't support signatures, but
366 # at least check that we can try
367 p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
368 divsig = p.system.methodSignature('div')
369 self.assertEqual(divsig, 'signatures not supported')
370
371 def test_multicall(self):
372 p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
373 multicall = xmlrpclib.MultiCall(p)
374 multicall.add(2,3)
375 multicall.pow(6,8)
376 multicall.div(127,42)
377 add_result, pow_result, div_result = multicall()
378 self.assertEqual(add_result, 2+3)
379 self.assertEqual(pow_result, 6**8)
380 self.assertEqual(div_result, 127//42)
381
382
383def test_main():
384 xmlrpc_tests = [XMLRPCTestCase, HelperTestCase, DateTimeTestCase,
385 BinaryTestCase, FaultTestCase]
386
387 # The test cases against a SimpleXMLRPCServer raise a socket error
388 # 10035 (WSAEWOULDBLOCK) in the server thread handle_request call when
389 # run on Windows. This only happens on the first test to run, but it
390 # fails every time and so these tests are skipped on win32 platforms.
391 if sys.platform != 'win32':
392 xmlrpc_tests.append(HTTPTestCase)
393
394 test_support.run_unittest(*xmlrpc_tests)
Skip Montanaro419abda2001-10-01 17:47:44 +0000395
396if __name__ == "__main__":
397 test_main()