14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport base64
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport datetime
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport time
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport xmlrpclib
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport SimpleXMLRPCServer
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport mimetools
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport httplib
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport socket
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport StringIO
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport re
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test import test_support
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtry:
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    import threading
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexcept ImportError:
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    threading = None
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtry:
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    unicode
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexcept NameError:
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    have_unicode = False
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmelse:
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    have_unicode = True
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmalist = [{'astring': 'foo@bar.baz.spam',
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'afloat': 7283.43,
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'anint': 2**20,
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'ashortlong': 2L,
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'anotherlist': ['.zyx.41'],
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'abase64': xmlrpclib.Binary("my dog has fleas"),
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'boolean': xmlrpclib.False,
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'unicode': u'\u4000\u6000\u8000',
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          u'ukey\u4000': 'regular value',
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'datetime1': xmlrpclib.DateTime('20050210T11:41:23'),
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'datetime2': xmlrpclib.DateTime(
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        (2005, 02, 10, 11, 41, 23, 0, 1, -1)),
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          'datetime3': xmlrpclib.DateTime(
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        datetime.datetime(2005, 02, 10, 11, 41, 23)),
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm          }]
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass XMLRPCTestCase(unittest.TestCase):
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_load(self):
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(alist,
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         xmlrpclib.loads(xmlrpclib.dumps((alist,)))[0][0])
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_bare_datetime(self):
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This checks that an unwrapped datetime.date object can be handled
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # by the marshalling code.  This can't be done via test_dump_load()
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # since with use_datetime set to 1 the unmarshaller would create
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # datetime objects for the 'datetime[123]' keys as well
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = datetime.datetime(2005, 02, 10, 11, 41, 23)
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = xmlrpclib.dumps((dt,))
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (newdt,), m = xmlrpclib.loads(s, use_datetime=1)
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(newdt, dt)
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m, None)
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(newdt, xmlrpclib.DateTime('20050210T11:41:23'))
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_datetime_before_1900(self):
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # same as before but with a date before 1900
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = datetime.datetime(1, 02, 10, 11, 41, 23)
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = xmlrpclib.dumps((dt,))
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (newdt,), m = xmlrpclib.loads(s, use_datetime=1)
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(newdt, dt)
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m, None)
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(newdt, xmlrpclib.DateTime('00010210T11:41:23'))
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_cmp_datetime_DateTime(self):
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        now = datetime.datetime.now()
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dt = xmlrpclib.DateTime(now.timetuple())
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(dt == now)
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(now == dt)
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        then = now + datetime.timedelta(seconds=4)
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(then >= dt)
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(dt < then)
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bug_1164912 (self):
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = xmlrpclib.DateTime()
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ((new_d,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((d,),
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                            methodresponse=True))
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(new_d.value, str)
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check that the output of dumps() is still an 8-bit string
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = xmlrpclib.dumps((new_d,), methodresponse=True)
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIsInstance(s, str)
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_newstyle_class(self):
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class T(object):
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = T()
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.x = 100
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.y = "Hello"
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ((t2,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((t,)))
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t2, t.__dict__)
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_big_long(self):
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, xmlrpclib.dumps, (2L**99,))
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_bad_dict(self):
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, xmlrpclib.dumps, ({(1,2,3): 1},))
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_recursive_seq(self):
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        l = [1,2,3]
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = [3,4,5,l]
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        l.append(t)
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, xmlrpclib.dumps, (l,))
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_recursive_dict(self):
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = {'1':1, '2':1}
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = {'3':3, 'd':d}
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d['t'] = t
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, xmlrpclib.dumps, (d,))
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_big_int(self):
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if sys.maxint > 2L**31-1:
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertRaises(OverflowError, xmlrpclib.dumps,
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              (int(2L**34),))
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        xmlrpclib.dumps((xmlrpclib.MAXINT, xmlrpclib.MININT))
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, xmlrpclib.dumps, (xmlrpclib.MAXINT+1,))
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, xmlrpclib.dumps, (xmlrpclib.MININT-1,))
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def dummy_write(s):
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m = xmlrpclib.Marshaller()
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.dump_int(xmlrpclib.MAXINT, dummy_write)
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        m.dump_int(xmlrpclib.MININT, dummy_write)
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MAXINT+1, dummy_write)
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MININT-1, dummy_write)
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_none(self):
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        value = alist + [None]
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        arg1 = (alist + [None],)
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        strg = xmlrpclib.dumps(arg1, allow_none=True)
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(value,
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         xmlrpclib.loads(strg)[0][0])
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,))
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_default_encoding_issues(self):
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # SF bug #1115989: wrong decoding in '_stringify'
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        utf8 = """<?xml version='1.0' encoding='iso-8859-1'?>
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  <params>
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    <param><value>
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      <string>abc \x95</string>
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      </value></param>
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    <param><value>
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      <struct>
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        <member>
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          <name>def \x96</name>
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          <value><string>ghi \x97</string></value>
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          </member>
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                        </struct>
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                      </value></param>
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  </params>
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                  """
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # sys.setdefaultencoding() normally doesn't exist after site.py is
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # loaded.  Import a temporary fresh copy to get access to it
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # but then restore the original copy to avoid messing with
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # other potentially modified sys module attributes
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        old_encoding = sys.getdefaultencoding()
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with test_support.CleanImport('sys'):
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            import sys as temp_sys
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            temp_sys.setdefaultencoding("iso-8859-1")
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                (s, d), m = xmlrpclib.loads(utf8)
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            finally:
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                temp_sys.setdefaultencoding(old_encoding)
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        items = d.items()
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if have_unicode:
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(s, u"abc \x95")
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertIsInstance(s, unicode)
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(items, [(u"def \x96", u"ghi \x97")])
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertIsInstance(items[0][0], unicode)
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertIsInstance(items[0][1], unicode)
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(s, "abc \xc2\x95")
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(items, [("def \xc2\x96", "ghi \xc2\x97")])
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass HelperTestCase(unittest.TestCase):
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_escape(self):
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(xmlrpclib.escape("a&b"), "a&amp;b")
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(xmlrpclib.escape("a<b"), "a&lt;b")
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(xmlrpclib.escape("a>b"), "a&gt;b")
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass FaultTestCase(unittest.TestCase):
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_repr(self):
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = xmlrpclib.Fault(42, 'Test Fault')
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(f), "<Fault 42: 'Test Fault'>")
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(f), str(f))
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dump_fault(self):
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        f = xmlrpclib.Fault(42, 'Test Fault')
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = xmlrpclib.dumps((f,))
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        (newf,), m = xmlrpclib.loads(s)
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(newf, {'faultCode': 42, 'faultString': 'Test Fault'})
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(m, None)
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        s = xmlrpclib.Marshaller().dumps(f)
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, s)
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass DateTimeTestCase(unittest.TestCase):
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_default(self):
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.DateTime()
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_time(self):
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = 1181399930.036952
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.DateTime(d)
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t), time.strftime("%Y%m%dT%H:%M:%S", time.localtime(d)))
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_time_tuple(self):
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = (2007,6,9,10,38,50,5,160,0)
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.DateTime(d)
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t), '20070609T10:38:50')
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_time_struct(self):
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = time.localtime(1181399930.036952)
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.DateTime(d)
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t),  time.strftime("%Y%m%dT%H:%M:%S", d))
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_datetime_datetime(self):
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = datetime.datetime(2007,1,2,3,4,5)
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.DateTime(d)
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t), '20070102T03:04:05')
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_repr(self):
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = datetime.datetime(2007,1,2,3,4,5)
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.DateTime(d)
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        val ="<DateTime '20070102T03:04:05' at %x>" % id(t)
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(repr(t), val)
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_decode(self):
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = ' 20070908T07:11:13  '
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = xmlrpclib.DateTime()
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1.decode(d)
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tref = xmlrpclib.DateTime(datetime.datetime(2007,9,8,7,11,13))
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, tref)
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = xmlrpclib._datetime(d)
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(t1, tref)
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BinaryTestCase(unittest.TestCase):
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_default(self):
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.Binary()
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t), '')
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_string(self):
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = '\x01\x02\x03abc123\xff\xfe'
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.Binary(d)
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t), d)
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_decode(self):
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        d = '\x01\x02\x03abc123\xff\xfe'
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        de = base64.encodestring(d)
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1 = xmlrpclib.Binary()
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t1.decode(de)
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t1), d)
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t2 = xmlrpclib._binary(de)
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(str(t2), d)
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmADDR = PORT = URL = None
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The evt is set twice.  First when the server is ready to serve.
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Second when the server has been shutdown.  The user must clear
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# the event after it has been set the first time to catch the second set.
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef http_server(evt, numrequests, requestHandler=None):
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class TestInstanceClass:
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def div(self, x, y):
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return x // y
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def _methodHelp(self, name):
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if name == 'div':
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 'This is the div function'
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def my_function():
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        '''This is my function'''
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return True
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class MyXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def get_request(self):
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Ensure the socket is always non-blocking.  On Linux, socket
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # attributes are not inherited like they are on *BSD and Windows.
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s, port = self.socket.accept()
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s.setblocking(True)
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return s, port
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not requestHandler:
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        requestHandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    serv = MyXMLRPCServer(("localhost", 0), requestHandler,
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          logRequests=False, bind_and_activate=False)
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.socket.settimeout(3)
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.server_bind()
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        global ADDR, PORT, URL
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ADDR, PORT = serv.socket.getsockname()
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #connect to IP address directly.  This avoids socket.create_connection()
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #trying to connect to to "localhost" using all address families, which
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #causes slowdown e.g. on vista which supports AF_INET6.  The server listens
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #on AF_INET only.
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        URL = "http://%s:%d"%(ADDR, PORT)
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.server_activate()
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.register_introspection_functions()
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.register_multicall_functions()
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.register_function(pow)
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.register_function(lambda x,y: x+y, 'add')
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.register_function(my_function)
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.register_instance(TestInstanceClass())
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        evt.set()
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # handle up to 'numrequests' requests
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        while numrequests > 0:
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            serv.handle_request()
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            numrequests -= 1
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except socket.timeout:
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pass
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    finally:
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.socket.close()
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PORT = None
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        evt.set()
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef http_multi_server(evt, numrequests, requestHandler=None):
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class TestInstanceClass:
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def div(self, x, y):
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return x // y
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def _methodHelp(self, name):
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if name == 'div':
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return 'This is the div function'
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def my_function():
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        '''This is my function'''
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return True
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class MyXMLRPCServer(SimpleXMLRPCServer.MultiPathXMLRPCServer):
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def get_request(self):
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Ensure the socket is always non-blocking.  On Linux, socket
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # attributes are not inherited like they are on *BSD and Windows.
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s, port = self.socket.accept()
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            s.setblocking(True)
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return s, port
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if not requestHandler:
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        requestHandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class MyRequestHandler(requestHandler):
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        rpc_paths = []
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    serv = MyXMLRPCServer(("localhost", 0), MyRequestHandler,
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          logRequests=False, bind_and_activate=False)
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    serv.socket.settimeout(3)
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    serv.server_bind()
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        global ADDR, PORT, URL
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ADDR, PORT = serv.socket.getsockname()
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #connect to IP address directly.  This avoids socket.create_connection()
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #trying to connect to to "localhost" using all address families, which
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #causes slowdown e.g. on vista which supports AF_INET6.  The server listens
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #on AF_INET only.
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        URL = "http://%s:%d"%(ADDR, PORT)
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.server_activate()
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        paths = ["/foo", "/foo/bar"]
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for path in paths:
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d = serv.add_dispatcher(path, SimpleXMLRPCServer.SimpleXMLRPCDispatcher())
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d.register_introspection_functions()
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            d.register_multicall_functions()
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.get_dispatcher(paths[0]).register_function(pow)
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.get_dispatcher(paths[1]).register_function(lambda x,y: x+y, 'add')
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        evt.set()
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # handle up to 'numrequests' requests
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        while numrequests > 0:
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            serv.handle_request()
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            numrequests -= 1
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except socket.timeout:
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pass
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    finally:
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv.socket.close()
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        PORT = None
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        evt.set()
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# This function prevents errors like:
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#    <ProtocolError for localhost:57527/RPC2: 500 Internal Server Error>
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef is_unavailable_exception(e):
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    '''Returns True if the given ProtocolError is the product of a server-side
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       exception caused by the 'temporarily unavailable' response sometimes
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm       given by operations on non-blocking sockets.'''
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # sometimes we get a -1 error code and/or empty headers
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if e.errcode == -1 or e.headers is None:
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return True
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exc_mess = e.headers.get('X-exception')
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except AttributeError:
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Ignore socket.errors here.
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exc_mess = str(e)
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if exc_mess and 'temporarily unavailable' in exc_mess.lower():
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return True
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return False
4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm@unittest.skipUnless(threading, 'Threading required for this test.')
4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BaseServerTestCase(unittest.TestCase):
4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    requestHandler = None
4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    request_count = 1
4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    threadFunc = staticmethod(http_server)
4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # enable traceback reporting
4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True
4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.evt = threading.Event()
4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # start server thread to handle requests
4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv_args = (self.evt, self.request_count, self.requestHandler)
4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        threading.Thread(target=self.threadFunc, args=serv_args).start()
4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # wait for the server to be ready
4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.evt.wait(10)
4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.evt.clear()
4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # wait on the server thread to terminate
4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.evt.wait(10)
4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # disable traceback reporting
4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = False
4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# NOTE: The tests in SimpleServerTestCase will ignore failures caused by
4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# "temporarily unavailable" exceptions raised in SimpleXMLRPCServer.  This
4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# condition occurs infrequently on some platforms, frequently on others, and
4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# is apparently caused by using SimpleXMLRPCServer with a non-blocking socket
4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# If the server class is updated at some point in the future to handle this
4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# situation more gracefully, these tests should be modified appropriately.
4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass SimpleServerTestCase(BaseServerTestCase):
4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_simple1(self):
4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(p.pow(6,8), 6**8)
4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_nonascii(self):
4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        start_string = 'P\N{LATIN SMALL LETTER Y WITH CIRCUMFLEX}t'
4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        end_string = 'h\N{LATIN SMALL LETTER O WITH HORN}n'
4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(p.add(start_string, end_string),
4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             start_string + end_string)
4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error) as e:
4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket unavailable errors.
4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # [ch] The test 404 is causing lots of false alarms.
4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def XXXtest_404(self):
4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # send POST with httplib, it should return 404 header and
4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # 'Not Found' message.
4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        conn = httplib.HTTPConnection(ADDR, PORT)
4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        conn.request('POST', '/this-is-not-valid')
4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        response = conn.getresponse()
4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        conn.close()
4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(response.status, 404)
4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(response.reason, 'Not Found')
4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_introspection1(self):
4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            meth = p.system.listMethods()
4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            expected_methods = set(['pow', 'div', 'my_function', 'add',
4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                    'system.listMethods', 'system.methodHelp',
4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                    'system.methodSignature', 'system.multicall'])
4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(set(meth), expected_methods)
4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_introspection2(self):
5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # test _methodHelp()
5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            divhelp = p.system.methodHelp('div')
5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(divhelp, 'This is the div function')
5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    @unittest.skipIf(sys.flags.optimize >= 2,
5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     "Docstrings are omitted with -O2 and above")
5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_introspection3(self):
5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # test native doc
5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            myfunction = p.system.methodHelp('my_function')
5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(myfunction, 'This is my function')
5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_introspection4(self):
5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # the SimpleXMLRPCServer doesn't support signatures, but
5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # at least check that we can try making the call
5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            divsig = p.system.methodSignature('div')
5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(divsig, 'signatures not supported')
5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_multicall(self):
5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            multicall = xmlrpclib.MultiCall(p)
5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            multicall.add(2,3)
5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            multicall.pow(6,8)
5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            multicall.div(127,42)
5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            add_result, pow_result, div_result = multicall()
5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(add_result, 2+3)
5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(pow_result, 6**8)
5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(div_result, 127//42)
5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_non_existing_multicall(self):
5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            multicall = xmlrpclib.MultiCall(p)
5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            multicall.this_is_not_exists()
5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            result = multicall()
5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # result.results contains;
5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # [{'faultCode': 1, 'faultString': '<type \'exceptions.Exception\'>:'
5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #   'method "this_is_not_exists" is not supported'>}]
5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(result.results[0]['faultCode'], 1)
5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(result.results[0]['faultString'],
5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                '<type \'exceptions.Exception\'>:method "this_is_not_exists" '
5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'is not supported')
5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_dotted_attribute(self):
5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Raises an AttributeError because private methods are not allowed.
5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(AttributeError,
5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                          SimpleXMLRPCServer.resolve_dotted_attribute, str, '__add')
5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(SimpleXMLRPCServer.resolve_dotted_attribute(str, 'title'))
5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Get the test to run faster by sending a request with test_simple1.
5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # This avoids waiting for the socket timeout.
5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.test_simple1()
5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass MultiPathServerTestCase(BaseServerTestCase):
5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    threadFunc = staticmethod(http_multi_server)
5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    request_count = 2
5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_path1(self):
5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(URL+"/foo")
5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(xmlrpclib.Fault, p.add, 6, 8)
5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_path2(self):
5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(URL+"/foo/bar")
5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.add(6,8), 6+8)
5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(xmlrpclib.Fault, p.pow, 6, 8)
6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism
6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#does indeed serve subsequent requests on the same connection
6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BaseKeepaliveServerTestCase(BaseServerTestCase):
6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #a request handler that supports keep-alive and logs requests into a
6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #class variable
6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        parentClass = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler
6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        protocol_version = 'HTTP/1.1'
6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        myRequests = []
6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def handle(self):
6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.myRequests.append([])
6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.reqidx = len(self.myRequests)-1
6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return self.parentClass.handle(self)
6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def handle_one_request(self):
6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            result = self.parentClass.handle_one_request(self)
6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.myRequests[self.reqidx].append(self.raw_requestline)
6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return result
6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    requestHandler = RequestHandler
6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #clear request log
6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.RequestHandler.myRequests = []
6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return BaseServerTestCase.setUp(self)
6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism
6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#does indeed serve subsequent requests on the same connection
6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass KeepaliveServerTestCase1(BaseKeepaliveServerTestCase):
6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_two(self):
6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(URL)
6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #do three requests.
6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #they should have all been handled by a single request handler
6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(self.RequestHandler.myRequests), 1)
6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #check that we did at least two (the third may be pending append
6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #due to thread scheduling)
6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertGreaterEqual(len(self.RequestHandler.myRequests[-1]), 2)
6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#test special attribute access on the serverproxy, through the __call__
6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#function.
6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass KeepaliveServerTestCase2(BaseKeepaliveServerTestCase):
6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #ask for two keepalive requests to be handled.
6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    request_count=2
6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_close(self):
6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(URL)
6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #do some requests with close.
6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p("close")() #this should trigger a new keep-alive request
6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #they should have all been two request handlers, each having logged at least
6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #two complete requests
6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(self.RequestHandler.myRequests), 2)
6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertGreaterEqual(len(self.RequestHandler.myRequests[-1]), 2)
6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertGreaterEqual(len(self.RequestHandler.myRequests[-2]), 2)
6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_transport(self):
6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(URL)
6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #do some requests with close.
6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p("transport").close() #same as above, really.
6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(self.RequestHandler.myRequests), 2)
6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#A test case that verifies that gzip encoding works in both directions
6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#(for a request and the response)
6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass GzipServerTestCase(BaseServerTestCase):
6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #a request handler that supports keep-alive and logs requests into a
6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    #class variable
6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        parentClass = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler
6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        protocol_version = 'HTTP/1.1'
6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def do_POST(self):
6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            #store content of last request in class
6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.__class__.content_length = int(self.headers["content-length"])
6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return self.parentClass.do_POST(self)
6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    requestHandler = RequestHandler
6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    class Transport(xmlrpclib.Transport):
6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #custom transport, stores the response length for our perusal
6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        fake_gzip = False
6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def parse_response(self, response):
6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.response_length=int(response.getheader("content-length", 0))
6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return xmlrpclib.Transport.parse_response(self, response)
6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        def send_content(self, connection, body):
6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if self.fake_gzip:
6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                #add a lone gzip header to induce decode error remotely
6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                connection.putheader("Content-Encoding", "gzip")
6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return xmlrpclib.Transport.send_content(self, connection, body)
7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        BaseServerTestCase.setUp(self)
7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_gzip_request(self):
7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.Transport()
7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.encode_threshold = None
7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(URL, transport=t)
7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = self.RequestHandler.content_length
7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.encode_threshold = 0 #turn on request encoding
7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = self.RequestHandler.content_length
7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(a>b)
7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_bad_gzip_request(self):
7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.Transport()
7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.encode_threshold = None
7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t.fake_gzip = True
7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(URL, transport=t)
7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cm = self.assertRaisesRegexp(xmlrpclib.ProtocolError,
7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                     re.compile(r"\b400\b"))
7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with cm:
7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p.pow(6, 8)
7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_gsip_response(self):
7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = self.Transport()
7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(URL, transport=t)
7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        old = self.requestHandler.encode_threshold
7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.requestHandler.encode_threshold = None #no encoding
7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = t.response_length
7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.requestHandler.encode_threshold = 0 #always encode
7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p.pow(6,8), 6**8)
7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        b = t.response_length
7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.requestHandler.encode_threshold = old
7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(a>b)
7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#Test special attributes of the ServerProxy object
7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass ServerProxyTestCase(unittest.TestCase):
7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        unittest.TestCase.setUp(self)
7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if threading:
7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.url = URL
7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # Without threading, http_server() and http_multi_server() will not
7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # be executed and URL is still equal to None. 'http://' is a just
7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # enough to choose the scheme (HTTP)
7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.url = 'http://'
7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_close(self):
7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(self.url)
7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p('close')(), None)
7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_transport(self):
7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        t = xmlrpclib.Transport()
7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        p = xmlrpclib.ServerProxy(self.url, transport=t)
7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(p('transport'), t)
7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# This is a contrived way to make a failure occur on the server side
7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# in order to test the _send_traceback_header flag on the server
7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass FailingMessageClass(mimetools.Message):
7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __getitem__(self, key):
7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        key = key.lower()
7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if key == 'content-length':
7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return 'I am broken'
7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return mimetools.Message.__getitem__(self, key)
7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm@unittest.skipUnless(threading, 'Threading required for this test.')
7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass FailingServerTestCase(unittest.TestCase):
7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.evt = threading.Event()
7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # start server thread to handle requests
7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        serv_args = (self.evt, 1)
7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        threading.Thread(target=http_server, args=serv_args).start()
7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # wait for the server to be ready
7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.evt.wait()
7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.evt.clear()
7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # wait on the server thread to terminate
7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.evt.wait()
7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # reset flag
7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = False
7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # reset message class
7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = mimetools.Message
7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_basic(self):
7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check that flag is false by default
7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        flagval = SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header
7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(flagval, False)
7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # enable traceback reporting
7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True
7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # test a call that shouldn't fail just as a smoke test
7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(p.pow(6,8), 6**8)
8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e):
8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # protocol error; provide additional information in test output
8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_fail_no_info(self):
8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # use the broken message class
8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = FailingMessageClass
8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p.pow(6,8)
8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e) and hasattr(e, "headers"):
8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # The two server-side error headers shouldn't be sent back in this case
8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertTrue(e.headers.get("X-exception") is None)
8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertTrue(e.headers.get("X-traceback") is None)
8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail('ProtocolError not raised')
8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_fail_with_info(self):
8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # use the broken message class
8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = FailingMessageClass
8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Check that errors in the server send back exception/traceback
8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # info when flag is set
8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True
8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p = xmlrpclib.ServerProxy(URL)
8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            p.pow(6,8)
8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except (xmlrpclib.ProtocolError, socket.error), e:
8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # ignore failures due to non-blocking socket 'unavailable' errors
8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if not is_unavailable_exception(e) and hasattr(e, "headers"):
8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                # We should get error info in the response
8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                expected_err = "invalid literal for int() with base 10: 'I am broken'"
8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertEqual(e.headers.get("x-exception"), expected_err)
8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertTrue(e.headers.get("x-traceback") is not None)
8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail('ProtocolError not raised')
8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass CGIHandlerTestCase(unittest.TestCase):
8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.cgi = SimpleXMLRPCServer.CGIXMLRPCRequestHandler()
8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.cgi = None
8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_cgi_get(self):
8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with test_support.EnvironmentVarGuard() as env:
8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            env['REQUEST_METHOD'] = 'GET'
8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # if the method is GET and no request_text is given, it runs handle_get
8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # get sysout output
8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            with test_support.captured_stdout() as data_out:
8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.cgi.handle_request()
8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # parse Status header
8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            data_out.seek(0)
8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            handle = data_out.read()
8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            status = handle.split()[1]
8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            message = ' '.join(handle.split()[2:4])
8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(status, '400')
8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(message, 'Bad Request')
8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_cgi_xmlrpc_response(self):
8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        data = """<?xml version='1.0'?>
8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        <methodCall>
8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            <methodName>test_method</methodName>
8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            <params>
8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                <param>
8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    <value><string>foo</string></value>
8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                </param>
8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                <param>
8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                    <value><string>bar</string></value>
8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                </param>
8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            </params>
8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        </methodCall>
8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """
8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with test_support.EnvironmentVarGuard() as env, \
8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm             test_support.captured_stdout() as data_out, \
8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm             test_support.captured_stdin() as data_in:
8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            data_in.write(data)
8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            data_in.seek(0)
8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            env['CONTENT_LENGTH'] = str(len(data))
8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.cgi.handle_request()
8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        data_out.seek(0)
8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # will respond exception, if so, our goal is achieved ;)
8944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        handle = data_out.read()
8954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # start with 44th char so as not to get http header, we just need only xml
8974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, handle[44:])
8984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
8994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Also test the content-length returned  by handle_request
9004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Using the same test method inorder to avoid all the datapassing
9014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # boilerplate code.
9024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Test for bug: http://bugs.python.org/issue5040
9034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        content = handle[handle.find("<?xml"):]
9054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(
9074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            int(re.search('Content-Length: (\d+)', handle).group(1)),
9084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            len(content))
9094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass FakeSocket:
9124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __init__(self):
9144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.data = StringIO.StringIO()
9154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def send(self, buf):
9174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.data.write(buf)
9184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return len(buf)
9194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def sendall(self, buf):
9214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.data.write(buf)
9224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def getvalue(self):
9244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.data.getvalue()
9254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def makefile(self, x='r', y=-1):
9274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise RuntimeError
9284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def close(self):
9304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pass
9314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass FakeTransport(xmlrpclib.Transport):
9334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """A Transport instance that records instead of sending a request.
9344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    This class replaces the actual socket used by httplib with a
9364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    FakeSocket object that records the request.  It doesn't provide a
9374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    response.
9384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """
9394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def make_connection(self, host):
9414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        conn = xmlrpclib.Transport.make_connection(self, host)
9424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        conn.sock = self.fake_socket = FakeSocket()
9434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return conn
9444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TransportSubclassTestCase(unittest.TestCase):
9464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def issue_request(self, transport_class):
9484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Return an HTTP request made via transport_class."""
9494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        transport = transport_class()
9504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        proxy = xmlrpclib.ServerProxy("http://example.com/",
9514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                      transport=transport)
9524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
9534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            proxy.pow(6, 8)
9544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except RuntimeError:
9554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return transport.fake_socket.getvalue()
9564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return None
9574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_custom_user_agent(self):
9594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class TestTransport(FakeTransport):
9604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def send_user_agent(self, conn):
9624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                xmlrpclib.Transport.send_user_agent(self, conn)
9634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                conn.putheader("X-Test", "test_custom_user_agent")
9644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        req = self.issue_request(TestTransport)
9664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIn("X-Test: test_custom_user_agent\r\n", req)
9674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_send_host(self):
9694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class TestTransport(FakeTransport):
9704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def send_host(self, conn, host):
9724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                xmlrpclib.Transport.send_host(self, conn, host)
9734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                conn.putheader("X-Test", "test_send_host")
9744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        req = self.issue_request(TestTransport)
9764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIn("X-Test: test_send_host\r\n", req)
9774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_send_request(self):
9794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class TestTransport(FakeTransport):
9804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def send_request(self, conn, url, body):
9824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                xmlrpclib.Transport.send_request(self, conn, url, body)
9834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                conn.putheader("X-Test", "test_send_request")
9844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        req = self.issue_request(TestTransport)
9864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIn("X-Test: test_send_request\r\n", req)
9874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_send_content(self):
9894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        class TestTransport(FakeTransport):
9904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            def send_content(self, conn, body):
9924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                conn.putheader("X-Test", "test_send_content")
9934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                xmlrpclib.Transport.send_content(self, conn, body)
9944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        req = self.issue_request(TestTransport)
9964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertIn("X-Test: test_send_content\r\n", req)
9974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
9984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm@test_support.reap_threads
9994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main():
10004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    xmlrpc_tests = [XMLRPCTestCase, HelperTestCase, DateTimeTestCase,
10014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm         BinaryTestCase, FaultTestCase, TransportSubclassTestCase]
10024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    xmlrpc_tests.append(SimpleServerTestCase)
10034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    xmlrpc_tests.append(KeepaliveServerTestCase1)
10044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    xmlrpc_tests.append(KeepaliveServerTestCase2)
10054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    try:
10064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import gzip
10074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        xmlrpc_tests.append(GzipServerTestCase)
10084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    except ImportError:
10094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        pass #gzip not supported in this build
10104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    xmlrpc_tests.append(MultiPathServerTestCase)
10114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    xmlrpc_tests.append(ServerProxyTestCase)
10124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    xmlrpc_tests.append(FailingServerTestCase)
10134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    xmlrpc_tests.append(CGIHandlerTestCase)
10144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_support.run_unittest(*xmlrpc_tests)
10164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
10174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == "__main__":
10184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_main()
1019