1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport base64 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport datetime 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport time 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport unittest 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport xmlrpclib 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport SimpleXMLRPCServer 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport mimetools 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport httplib 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport socket 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport StringIO 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport os 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport re 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test import test_support 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry: 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import threading 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept ImportError: 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh threading = None 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry: 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh unicode 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept NameError: 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh have_unicode = False 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehelse: 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh have_unicode = True 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehalist = [{'astring': 'foo@bar.baz.spam', 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'afloat': 7283.43, 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'anint': 2**20, 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'ashortlong': 2L, 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'anotherlist': ['.zyx.41'], 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'abase64': xmlrpclib.Binary("my dog has fleas"), 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'boolean': xmlrpclib.False, 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'unicode': u'\u4000\u6000\u8000', 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh u'ukey\u4000': 'regular value', 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'datetime1': xmlrpclib.DateTime('20050210T11:41:23'), 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'datetime2': xmlrpclib.DateTime( 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (2005, 02, 10, 11, 41, 23, 0, 1, -1)), 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'datetime3': xmlrpclib.DateTime( 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh datetime.datetime(2005, 02, 10, 11, 41, 23)), 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh }] 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass XMLRPCTestCase(unittest.TestCase): 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_load(self): 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(alist, 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpclib.loads(xmlrpclib.dumps((alist,)))[0][0]) 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_bare_datetime(self): 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This checks that an unwrapped datetime.date object can be handled 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # by the marshalling code. This can't be done via test_dump_load() 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # since with use_datetime set to 1 the unmarshaller would create 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # datetime objects for the 'datetime[123]' keys as well 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = datetime.datetime(2005, 02, 10, 11, 41, 23) 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = xmlrpclib.dumps((dt,)) 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (newdt,), m = xmlrpclib.loads(s, use_datetime=1) 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(newdt, dt) 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(m, None) 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (newdt,), m = xmlrpclib.loads(s, use_datetime=0) 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(newdt, xmlrpclib.DateTime('20050210T11:41:23')) 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_datetime_before_1900(self): 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # same as before but with a date before 1900 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = datetime.datetime(1, 02, 10, 11, 41, 23) 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = xmlrpclib.dumps((dt,)) 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (newdt,), m = xmlrpclib.loads(s, use_datetime=1) 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(newdt, dt) 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(m, None) 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (newdt,), m = xmlrpclib.loads(s, use_datetime=0) 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(newdt, xmlrpclib.DateTime('00010210T11:41:23')) 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_cmp_datetime_DateTime(self): 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh now = datetime.datetime.now() 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dt = xmlrpclib.DateTime(now.timetuple()) 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(dt == now) 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(now == dt) 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh then = now + datetime.timedelta(seconds=4) 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(then >= dt) 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(dt < then) 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bug_1164912 (self): 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = xmlrpclib.DateTime() 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ((new_d,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((d,), 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh methodresponse=True)) 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(new_d.value, str) 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check that the output of dumps() is still an 8-bit string 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = xmlrpclib.dumps((new_d,), methodresponse=True) 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(s, str) 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_newstyle_class(self): 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class T(object): 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = T() 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.x = 100 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.y = "Hello" 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ((t2,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((t,))) 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t2, t.__dict__) 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_big_long(self): 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, xmlrpclib.dumps, (2L**99,)) 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_bad_dict(self): 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, xmlrpclib.dumps, ({(1,2,3): 1},)) 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_recursive_seq(self): 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l = [1,2,3] 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = [3,4,5,l] 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l.append(t) 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, xmlrpclib.dumps, (l,)) 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_recursive_dict(self): 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = {'1':1, '2':1} 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = {'3':3, 'd':d} 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d['t'] = t 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, xmlrpclib.dumps, (d,)) 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_big_int(self): 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if sys.maxint > 2L**31-1: 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, xmlrpclib.dumps, 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (int(2L**34),)) 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpclib.dumps((xmlrpclib.MAXINT, xmlrpclib.MININT)) 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, xmlrpclib.dumps, (xmlrpclib.MAXINT+1,)) 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, xmlrpclib.dumps, (xmlrpclib.MININT-1,)) 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def dummy_write(s): 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh m = xmlrpclib.Marshaller() 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh m.dump_int(xmlrpclib.MAXINT, dummy_write) 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh m.dump_int(xmlrpclib.MININT, dummy_write) 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MAXINT+1, dummy_write) 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MININT-1, dummy_write) 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_none(self): 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh value = alist + [None] 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh arg1 = (alist + [None],) 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh strg = xmlrpclib.dumps(arg1, allow_none=True) 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(value, 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpclib.loads(strg)[0][0]) 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,)) 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_default_encoding_issues(self): 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # SF bug #1115989: wrong decoding in '_stringify' 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh utf8 = """<?xml version='1.0' encoding='iso-8859-1'?> 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <params> 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <param><value> 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <string>abc \x95</string> 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </value></param> 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <param><value> 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <struct> 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <member> 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <name>def \x96</name> 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <value><string>ghi \x97</string></value> 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </member> 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </struct> 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </value></param> 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </params> 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # sys.setdefaultencoding() normally doesn't exist after site.py is 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # loaded. Import a temporary fresh copy to get access to it 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # but then restore the original copy to avoid messing with 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # other potentially modified sys module attributes 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh old_encoding = sys.getdefaultencoding() 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with test_support.CleanImport('sys'): 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import sys as temp_sys 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh temp_sys.setdefaultencoding("iso-8859-1") 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (s, d), m = xmlrpclib.loads(utf8) 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh temp_sys.setdefaultencoding(old_encoding) 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh items = d.items() 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if have_unicode: 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(s, u"abc \x95") 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(s, unicode) 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(items, [(u"def \x96", u"ghi \x97")]) 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(items[0][0], unicode) 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIsInstance(items[0][1], unicode) 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(s, "abc \xc2\x95") 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(items, [("def \xc2\x96", "ghi \xc2\x97")]) 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass HelperTestCase(unittest.TestCase): 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_escape(self): 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(xmlrpclib.escape("a&b"), "a&b") 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(xmlrpclib.escape("a<b"), "a<b") 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(xmlrpclib.escape("a>b"), "a>b") 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass FaultTestCase(unittest.TestCase): 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_repr(self): 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f = xmlrpclib.Fault(42, 'Test Fault') 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(f), "<Fault 42: 'Test Fault'>") 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(f), str(f)) 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dump_fault(self): 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f = xmlrpclib.Fault(42, 'Test Fault') 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = xmlrpclib.dumps((f,)) 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (newf,), m = xmlrpclib.loads(s) 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(newf, {'faultCode': 42, 'faultString': 'Test Fault'}) 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(m, None) 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s = xmlrpclib.Marshaller().dumps(f) 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, s) 212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass DateTimeTestCase(unittest.TestCase): 215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_default(self): 216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.DateTime() 217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_time(self): 219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = 1181399930.036952 220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.DateTime(d) 221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), time.strftime("%Y%m%dT%H:%M:%S", time.localtime(d))) 222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_time_tuple(self): 224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = (2007,6,9,10,38,50,5,160,0) 225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.DateTime(d) 226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), '20070609T10:38:50') 227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_time_struct(self): 229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = time.localtime(1181399930.036952) 230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.DateTime(d) 231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), time.strftime("%Y%m%dT%H:%M:%S", d)) 232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_datetime_datetime(self): 234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = datetime.datetime(2007,1,2,3,4,5) 235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.DateTime(d) 236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), '20070102T03:04:05') 237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_repr(self): 239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = datetime.datetime(2007,1,2,3,4,5) 240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.DateTime(d) 241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh val ="<DateTime '20070102T03:04:05' at %x>" % id(t) 242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(repr(t), val) 243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_decode(self): 245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = ' 20070908T07:11:13 ' 246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = xmlrpclib.DateTime() 247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1.decode(d) 248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tref = xmlrpclib.DateTime(datetime.datetime(2007,9,8,7,11,13)) 249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, tref) 250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = xmlrpclib._datetime(d) 252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(t1, tref) 253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass BinaryTestCase(unittest.TestCase): 255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_default(self): 256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.Binary() 257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), '') 258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_string(self): 260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = '\x01\x02\x03abc123\xff\xfe' 261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.Binary(d) 262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t), d) 263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_decode(self): 265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = '\x01\x02\x03abc123\xff\xfe' 266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh de = base64.encodestring(d) 267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1 = xmlrpclib.Binary() 268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t1.decode(de) 269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t1), d) 270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t2 = xmlrpclib._binary(de) 272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(str(t2), d) 273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehADDR = PORT = URL = None 276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# The evt is set twice. First when the server is ready to serve. 278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Second when the server has been shutdown. The user must clear 279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# the event after it has been set the first time to catch the second set. 280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef http_server(evt, numrequests, requestHandler=None): 281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class TestInstanceClass: 282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def div(self, x, y): 283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return x // y 284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _methodHelp(self, name): 286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if name == 'div': 287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'This is the div function' 288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def my_function(): 290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh '''This is my function''' 291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return True 292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class MyXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer): 294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_request(self): 295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure the socket is always non-blocking. On Linux, socket 296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # attributes are not inherited like they are on *BSD and Windows. 297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s, port = self.socket.accept() 298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s.setblocking(True) 299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return s, port 300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not requestHandler: 302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh requestHandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler 303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv = MyXMLRPCServer(("localhost", 0), requestHandler, 304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh logRequests=False, bind_and_activate=False) 305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.socket.settimeout(3) 307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.server_bind() 308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh global ADDR, PORT, URL 309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ADDR, PORT = serv.socket.getsockname() 310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #connect to IP address directly. This avoids socket.create_connection() 311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #trying to connect to "localhost" using all address families, which 312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #causes slowdown e.g. on vista which supports AF_INET6. The server listens 313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #on AF_INET only. 314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh URL = "http://%s:%d"%(ADDR, PORT) 315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.server_activate() 316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.register_introspection_functions() 317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.register_multicall_functions() 318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.register_function(pow) 319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.register_function(lambda x,y: x+y, 'add') 320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.register_function(my_function) 321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.register_instance(TestInstanceClass()) 322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh evt.set() 323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # handle up to 'numrequests' requests 325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while numrequests > 0: 326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.handle_request() 327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh numrequests -= 1 328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except socket.timeout: 330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.socket.close() 333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh PORT = None 334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh evt.set() 335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef http_multi_server(evt, numrequests, requestHandler=None): 337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class TestInstanceClass: 338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def div(self, x, y): 339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return x // y 340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _methodHelp(self, name): 342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if name == 'div': 343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'This is the div function' 344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def my_function(): 346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh '''This is my function''' 347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return True 348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class MyXMLRPCServer(SimpleXMLRPCServer.MultiPathXMLRPCServer): 350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_request(self): 351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ensure the socket is always non-blocking. On Linux, socket 352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # attributes are not inherited like they are on *BSD and Windows. 353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s, port = self.socket.accept() 354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh s.setblocking(True) 355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return s, port 356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not requestHandler: 358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh requestHandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler 359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class MyRequestHandler(requestHandler): 360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rpc_paths = [] 361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv = MyXMLRPCServer(("localhost", 0), MyRequestHandler, 363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh logRequests=False, bind_and_activate=False) 364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.socket.settimeout(3) 365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.server_bind() 366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh global ADDR, PORT, URL 368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ADDR, PORT = serv.socket.getsockname() 369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #connect to IP address directly. This avoids socket.create_connection() 370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #trying to connect to "localhost" using all address families, which 371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #causes slowdown e.g. on vista which supports AF_INET6. The server listens 372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #on AF_INET only. 373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh URL = "http://%s:%d"%(ADDR, PORT) 374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.server_activate() 375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh paths = ["/foo", "/foo/bar"] 376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for path in paths: 377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d = serv.add_dispatcher(path, SimpleXMLRPCServer.SimpleXMLRPCDispatcher()) 378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d.register_introspection_functions() 379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh d.register_multicall_functions() 380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.get_dispatcher(paths[0]).register_function(pow) 381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.get_dispatcher(paths[1]).register_function(lambda x,y: x+y, 'add') 382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh evt.set() 383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # handle up to 'numrequests' requests 385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while numrequests > 0: 386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.handle_request() 387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh numrequests -= 1 388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except socket.timeout: 390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv.socket.close() 393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh PORT = None 394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh evt.set() 395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# This function prevents errors like: 397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# <ProtocolError for localhost:57527/RPC2: 500 Internal Server Error> 398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef is_unavailable_exception(e): 399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh '''Returns True if the given ProtocolError is the product of a server-side 400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh exception caused by the 'temporarily unavailable' response sometimes 401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh given by operations on non-blocking sockets.''' 402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # sometimes we get a -1 error code and/or empty headers 404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if e.errcode == -1 or e.headers is None: 406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return True 407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh exc_mess = e.headers.get('X-exception') 408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Ignore socket.errors here. 410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh exc_mess = str(e) 411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if exc_mess and 'temporarily unavailable' in exc_mess.lower(): 413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return True 414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return False 416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh@unittest.skipUnless(threading, 'Threading required for this test.') 418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass BaseServerTestCase(unittest.TestCase): 419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh requestHandler = None 420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh request_count = 1 421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh threadFunc = staticmethod(http_server) 422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def setUp(self): 424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # enable traceback reporting 425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True 426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.evt = threading.Event() 428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # start server thread to handle requests 429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv_args = (self.evt, self.request_count, self.requestHandler) 430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh threading.Thread(target=self.threadFunc, args=serv_args).start() 431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # wait for the server to be ready 433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.evt.wait(10) 434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.evt.clear() 435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tearDown(self): 437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # wait on the server thread to terminate 438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.evt.wait(10) 439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # disable traceback reporting 441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = False 442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# NOTE: The tests in SimpleServerTestCase will ignore failures caused by 444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# "temporarily unavailable" exceptions raised in SimpleXMLRPCServer. This 445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# condition occurs infrequently on some platforms, frequently on others, and 446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# is apparently caused by using SimpleXMLRPCServer with a non-blocking socket 447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# If the server class is updated at some point in the future to handle this 448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# situation more gracefully, these tests should be modified appropriately. 449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass SimpleServerTestCase(BaseServerTestCase): 451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_simple1(self): 452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_nonascii(self): 462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start_string = 'P\N{LATIN SMALL LETTER Y WITH CIRCUMFLEX}t' 463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh end_string = 'h\N{LATIN SMALL LETTER O WITH HORN}n' 464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.add(start_string, end_string), 468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start_string + end_string) 469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error) as e: 470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket unavailable errors. 471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_unicode_host(self): 476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh server = xmlrpclib.ServerProxy(u"http://%s:%d/RPC2"%(ADDR, PORT)) 477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(server.add("a", u"\xe9"), u"a\xe9") 478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # [ch] The test 404 is causing lots of false alarms. 480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def XXXtest_404(self): 481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # send POST with httplib, it should return 404 header and 482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 'Not Found' message. 483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn = httplib.HTTPConnection(ADDR, PORT) 484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.request('POST', '/this-is-not-valid') 485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh response = conn.getresponse() 486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.close() 487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(response.status, 404) 489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(response.reason, 'Not Found') 490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_introspection1(self): 492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh meth = p.system.listMethods() 495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected_methods = set(['pow', 'div', 'my_function', 'add', 496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'system.listMethods', 'system.methodHelp', 497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'system.methodSignature', 'system.multicall']) 498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(set(meth), expected_methods) 499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_introspection2(self): 506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # test _methodHelp() 508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh divhelp = p.system.methodHelp('div') 510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(divhelp, 'This is the div function') 511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh @unittest.skipIf(sys.flags.optimize >= 2, 518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Docstrings are omitted with -O2 and above") 519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_introspection3(self): 520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # test native doc 522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh myfunction = p.system.methodHelp('my_function') 524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(myfunction, 'This is my function') 525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_introspection4(self): 532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the SimpleXMLRPCServer doesn't support signatures, but 533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # at least check that we can try making the call 534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh divsig = p.system.methodSignature('div') 537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(divsig, 'signatures not supported') 538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_multicall(self): 545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh multicall = xmlrpclib.MultiCall(p) 548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh multicall.add(2,3) 549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh multicall.pow(6,8) 550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh multicall.div(127,42) 551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh add_result, pow_result, div_result = multicall() 552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(add_result, 2+3) 553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(pow_result, 6**8) 554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(div_result, 127//42) 555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 561ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_non_existing_multicall(self): 562ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 563ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 564ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh multicall = xmlrpclib.MultiCall(p) 565ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh multicall.this_is_not_exists() 566ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result = multicall() 567ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 568ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # result.results contains; 569ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # [{'faultCode': 1, 'faultString': '<type \'exceptions.Exception\'>:' 570ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 'method "this_is_not_exists" is not supported'>}] 571ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 572ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(result.results[0]['faultCode'], 1) 573ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(result.results[0]['faultString'], 574ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh '<type \'exceptions.Exception\'>:method "this_is_not_exists" ' 575ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'is not supported') 576ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 577ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 578ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 579ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 580ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 581ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 582ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_dotted_attribute(self): 583ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Raises an AttributeError because private methods are not allowed. 584ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(AttributeError, 585ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.resolve_dotted_attribute, str, '__add') 586ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 587ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(SimpleXMLRPCServer.resolve_dotted_attribute(str, 'title')) 588ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Get the test to run faster by sending a request with test_simple1. 589ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This avoids waiting for the socket timeout. 590ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.test_simple1() 591ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 592ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_partial_post(self): 593ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check that a partial POST doesn't make the server loop: issue #14001. 594ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn = httplib.HTTPConnection(ADDR, PORT) 595ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.request('POST', '/RPC2 HTTP/1.0\r\nContent-Length: 100\r\n\r\nbye') 596ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.close() 597ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 598ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass MultiPathServerTestCase(BaseServerTestCase): 599ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh threadFunc = staticmethod(http_multi_server) 600ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh request_count = 2 601ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_path1(self): 602ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL+"/foo") 603ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 604ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(xmlrpclib.Fault, p.add, 6, 8) 605ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_path2(self): 606ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL+"/foo/bar") 607ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.add(6,8), 6+8) 608ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(xmlrpclib.Fault, p.pow, 6, 8) 609ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 610ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism 611ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#does indeed serve subsequent requests on the same connection 612ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass BaseKeepaliveServerTestCase(BaseServerTestCase): 613ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #a request handler that supports keep-alive and logs requests into a 614ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #class variable 615ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): 616ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parentClass = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler 617ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh protocol_version = 'HTTP/1.1' 618ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh myRequests = [] 619ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def handle(self): 620ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.myRequests.append([]) 621ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.reqidx = len(self.myRequests)-1 622ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.parentClass.handle(self) 623ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def handle_one_request(self): 624ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh result = self.parentClass.handle_one_request(self) 625ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.myRequests[self.reqidx].append(self.raw_requestline) 626ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return result 627ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 628ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh requestHandler = RequestHandler 629ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def setUp(self): 630ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #clear request log 631ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.RequestHandler.myRequests = [] 632ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return BaseServerTestCase.setUp(self) 633ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 634ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism 635ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#does indeed serve subsequent requests on the same connection 636ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass KeepaliveServerTestCase1(BaseKeepaliveServerTestCase): 637ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_two(self): 638ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 639ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #do three requests. 640ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 641ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 642ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 643ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 644ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #they should have all been handled by a single request handler 645ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(self.RequestHandler.myRequests), 1) 646ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 647ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #check that we did at least two (the third may be pending append 648ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #due to thread scheduling) 649ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertGreaterEqual(len(self.RequestHandler.myRequests[-1]), 2) 650ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 651ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#test special attribute access on the serverproxy, through the __call__ 652ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#function. 653ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass KeepaliveServerTestCase2(BaseKeepaliveServerTestCase): 654ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #ask for two keepalive requests to be handled. 655ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh request_count=2 656ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 657ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_close(self): 658ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 659ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #do some requests with close. 660ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 661ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 662ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 663ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p("close")() #this should trigger a new keep-alive request 664ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 665ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 666ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 667ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 668ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #they should have all been two request handlers, each having logged at least 669ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #two complete requests 670ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(self.RequestHandler.myRequests), 2) 671ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertGreaterEqual(len(self.RequestHandler.myRequests[-1]), 2) 672ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertGreaterEqual(len(self.RequestHandler.myRequests[-2]), 2) 673ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 674ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_transport(self): 675ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 676ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #do some requests with close. 677ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 678ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p("transport").close() #same as above, really. 679ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 680ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(len(self.RequestHandler.myRequests), 2) 681ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 682ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#A test case that verifies that gzip encoding works in both directions 683ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#(for a request and the response) 684ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass GzipServerTestCase(BaseServerTestCase): 685ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #a request handler that supports keep-alive and logs requests into a 686ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #class variable 687ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): 688ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parentClass = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler 689ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh protocol_version = 'HTTP/1.1' 690ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 691ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def do_POST(self): 692ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #store content of last request in class 693ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__class__.content_length = int(self.headers["content-length"]) 694ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.parentClass.do_POST(self) 695ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh requestHandler = RequestHandler 696ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 697ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class Transport(xmlrpclib.Transport): 698ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #custom transport, stores the response length for our perusal 699ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fake_gzip = False 700ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def parse_response(self, response): 701ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.response_length=int(response.getheader("content-length", 0)) 702ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return xmlrpclib.Transport.parse_response(self, response) 703ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 704ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def send_content(self, connection, body): 705ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.fake_gzip: 706ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh #add a lone gzip header to induce decode error remotely 707ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh connection.putheader("Content-Encoding", "gzip") 708ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return xmlrpclib.Transport.send_content(self, connection, body) 709ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 710ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def setUp(self): 711ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh BaseServerTestCase.setUp(self) 712ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 713ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_gzip_request(self): 714ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.Transport() 715ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.encode_threshold = None 716ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL, transport=t) 717ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 718ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = self.RequestHandler.content_length 719ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.encode_threshold = 0 #turn on request encoding 720ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 721ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = self.RequestHandler.content_length 722ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(a>b) 723ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 724ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_bad_gzip_request(self): 725ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.Transport() 726ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.encode_threshold = None 727ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t.fake_gzip = True 728ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL, transport=t) 729ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cm = self.assertRaisesRegexp(xmlrpclib.ProtocolError, 730ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh re.compile(r"\b400\b")) 731ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with cm: 732ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p.pow(6, 8) 733ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 734ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_gsip_response(self): 735ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = self.Transport() 736ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL, transport=t) 737ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh old = self.requestHandler.encode_threshold 738ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.requestHandler.encode_threshold = None #no encoding 739ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 740ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = t.response_length 741ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.requestHandler.encode_threshold = 0 #always encode 742ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 743ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = t.response_length 744ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.requestHandler.encode_threshold = old 745ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(a>b) 746ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 747ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#Test special attributes of the ServerProxy object 748ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass ServerProxyTestCase(unittest.TestCase): 749ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def setUp(self): 750ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh unittest.TestCase.setUp(self) 751ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if threading: 752ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.url = URL 753ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 754ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Without threading, http_server() and http_multi_server() will not 755ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # be executed and URL is still equal to None. 'http://' is a just 756ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # enough to choose the scheme (HTTP) 757ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.url = 'http://' 758ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 759ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_close(self): 760ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(self.url) 761ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p('close')(), None) 762ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 763ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_transport(self): 764ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh t = xmlrpclib.Transport() 765ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(self.url, transport=t) 766ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p('transport'), t) 767ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 768ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# This is a contrived way to make a failure occur on the server side 769ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# in order to test the _send_traceback_header flag on the server 770ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass FailingMessageClass(mimetools.Message): 771ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __getitem__(self, key): 772ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh key = key.lower() 773ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if key == 'content-length': 774ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'I am broken' 775ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return mimetools.Message.__getitem__(self, key) 776ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 777ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 778ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh@unittest.skipUnless(threading, 'Threading required for this test.') 779ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass FailingServerTestCase(unittest.TestCase): 780ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def setUp(self): 781ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.evt = threading.Event() 782ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # start server thread to handle requests 783ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh serv_args = (self.evt, 1) 784ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh threading.Thread(target=http_server, args=serv_args).start() 785ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 786ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # wait for the server to be ready 787ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.evt.wait() 788ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.evt.clear() 789ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 790ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tearDown(self): 791ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # wait on the server thread to terminate 792ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.evt.wait() 793ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # reset flag 794ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = False 795ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # reset message class 796ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = mimetools.Message 797ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 798ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_basic(self): 799ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # check that flag is false by default 800ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flagval = SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header 801ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(flagval, False) 802ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 803ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # enable traceback reporting 804ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True 805ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 806ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # test a call that shouldn't fail just as a smoke test 807ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 808ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 809ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(p.pow(6,8), 6**8) 810ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 811ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 812ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e): 813ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # protocol error; provide additional information in test output 814ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 815ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 816ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_fail_no_info(self): 817ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # use the broken message class 818ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = FailingMessageClass 819ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 820ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 821ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 822ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p.pow(6,8) 823ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 824ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 825ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e) and hasattr(e, "headers"): 826ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The two server-side error headers shouldn't be sent back in this case 827ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(e.headers.get("X-exception") is None) 828ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(e.headers.get("X-traceback") is None) 829ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 830ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail('ProtocolError not raised') 831ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 832ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_fail_with_info(self): 833ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # use the broken message class 834ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = FailingMessageClass 835ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 836ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check that errors in the server send back exception/traceback 837ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # info when flag is set 838ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True 839ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 840ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 841ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p = xmlrpclib.ServerProxy(URL) 842ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh p.pow(6,8) 843ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (xmlrpclib.ProtocolError, socket.error), e: 844ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # ignore failures due to non-blocking socket 'unavailable' errors 845ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not is_unavailable_exception(e) and hasattr(e, "headers"): 846ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # We should get error info in the response 847ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expected_err = "invalid literal for int() with base 10: 'I am broken'" 848ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(e.headers.get("x-exception"), expected_err) 849ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertTrue(e.headers.get("x-traceback") is not None) 850ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 851ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fail('ProtocolError not raised') 852ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 853ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass CGIHandlerTestCase(unittest.TestCase): 854ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def setUp(self): 855ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.cgi = SimpleXMLRPCServer.CGIXMLRPCRequestHandler() 856ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 857ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def tearDown(self): 858ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.cgi = None 859ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 860ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_cgi_get(self): 861ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with test_support.EnvironmentVarGuard() as env: 862ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh env['REQUEST_METHOD'] = 'GET' 863ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # if the method is GET and no request_text is given, it runs handle_get 864ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # get sysout output 865ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with test_support.captured_stdout() as data_out: 866ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.cgi.handle_request() 867ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 868ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # parse Status header 869ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh data_out.seek(0) 870ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh handle = data_out.read() 871ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh status = handle.split()[1] 872ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message = ' '.join(handle.split()[2:4]) 873ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 874ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(status, '400') 875ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual(message, 'Bad Request') 876ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 877ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 878ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_cgi_xmlrpc_response(self): 879ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh data = """<?xml version='1.0'?> 880ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <methodCall> 881ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <methodName>test_method</methodName> 882ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <params> 883ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <param> 884ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <value><string>foo</string></value> 885ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </param> 886ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <param> 887ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh <value><string>bar</string></value> 888ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </param> 889ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </params> 890ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh </methodCall> 891ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 892ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 893ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with test_support.EnvironmentVarGuard() as env, \ 894ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test_support.captured_stdout() as data_out, \ 895ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test_support.captured_stdin() as data_in: 896ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh data_in.write(data) 897ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh data_in.seek(0) 898ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh env['CONTENT_LENGTH'] = str(len(data)) 899ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.cgi.handle_request() 900ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh data_out.seek(0) 901ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 902ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # will respond exception, if so, our goal is achieved ;) 903ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh handle = data_out.read() 904ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 905ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # start with 44th char so as not to get http header, we just need only xml 906ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, handle[44:]) 907ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 908ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Also test the content-length returned by handle_request 909ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Using the same test method inorder to avoid all the datapassing 910ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # boilerplate code. 911ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Test for bug: http://bugs.python.org/issue5040 912ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 913ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh content = handle[handle.find("<?xml"):] 914ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 915ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertEqual( 916ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int(re.search('Content-Length: (\d+)', handle).group(1)), 917ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh len(content)) 918ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 919ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 920ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass FakeSocket: 921ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 922ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self): 923ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.data = StringIO.StringIO() 924ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 925ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def send(self, buf): 926ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.data.write(buf) 927ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return len(buf) 928ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 929ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def sendall(self, buf): 930ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.data.write(buf) 931ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 932ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def getvalue(self): 933ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.data.getvalue() 934ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 935ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def makefile(self, x='r', y=-1): 936ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise RuntimeError 937ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 938ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def close(self): 939ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 940ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 941ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass FakeTransport(xmlrpclib.Transport): 942ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """A Transport instance that records instead of sending a request. 943ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 944ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh This class replaces the actual socket used by httplib with a 945ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh FakeSocket object that records the request. It doesn't provide a 946ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh response. 947ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 948ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 949ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def make_connection(self, host): 950ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn = xmlrpclib.Transport.make_connection(self, host) 951ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.sock = self.fake_socket = FakeSocket() 952ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return conn 953ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 954ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TransportSubclassTestCase(unittest.TestCase): 955ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 956ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def issue_request(self, transport_class): 957ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Return an HTTP request made via transport_class.""" 958ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh transport = transport_class() 959ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh proxy = xmlrpclib.ServerProxy("http://example.com/", 960ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh transport=transport) 961ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 962ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh proxy.pow(6, 8) 963ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except RuntimeError: 964ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return transport.fake_socket.getvalue() 965ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 966ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 967ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_custom_user_agent(self): 968ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class TestTransport(FakeTransport): 969ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 970ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def send_user_agent(self, conn): 971ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpclib.Transport.send_user_agent(self, conn) 972ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.putheader("X-Test", "test_custom_user_agent") 973ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 974ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh req = self.issue_request(TestTransport) 975ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIn("X-Test: test_custom_user_agent\r\n", req) 976ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 977ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_send_host(self): 978ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class TestTransport(FakeTransport): 979ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 980ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def send_host(self, conn, host): 981ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpclib.Transport.send_host(self, conn, host) 982ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.putheader("X-Test", "test_send_host") 983ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 984ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh req = self.issue_request(TestTransport) 985ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIn("X-Test: test_send_host\r\n", req) 986ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 987ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_send_request(self): 988ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class TestTransport(FakeTransport): 989ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 990ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def send_request(self, conn, url, body): 991ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpclib.Transport.send_request(self, conn, url, body) 992ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.putheader("X-Test", "test_send_request") 993ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 994ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh req = self.issue_request(TestTransport) 995ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIn("X-Test: test_send_request\r\n", req) 996ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 997ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_send_content(self): 998ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class TestTransport(FakeTransport): 999ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1000ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def send_content(self, conn, body): 1001ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh conn.putheader("X-Test", "test_send_content") 1002ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpclib.Transport.send_content(self, conn, body) 1003ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1004ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh req = self.issue_request(TestTransport) 1005ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.assertIn("X-Test: test_send_content\r\n", req) 1006ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1007ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh@test_support.reap_threads 1008ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test_main(): 1009ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests = [XMLRPCTestCase, HelperTestCase, DateTimeTestCase, 1010ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh BinaryTestCase, FaultTestCase, TransportSubclassTestCase] 1011ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests.append(SimpleServerTestCase) 1012ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests.append(KeepaliveServerTestCase1) 1013ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests.append(KeepaliveServerTestCase2) 1014ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 1015ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import gzip 1016ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests.append(GzipServerTestCase) 1017ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except ImportError: 1018ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass #gzip not supported in this build 1019ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests.append(MultiPathServerTestCase) 1020ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests.append(ServerProxyTestCase) 1021ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests.append(FailingServerTestCase) 1022ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh xmlrpc_tests.append(CGIHandlerTestCase) 1023ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1024ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test_support.run_unittest(*xmlrpc_tests) 1025ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 1026ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == "__main__": 1027ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test_main() 1028