14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport base64
24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport datetime
34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport sys
44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport time
54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport unittest
64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport xmlrpclib
74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport SimpleXMLRPCServer
84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport mimetools
94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport httplib
104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport socket
114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport StringIO
124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport os
134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport re
144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom test import test_support
154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotry:
174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    import threading
184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoexcept ImportError:
194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    threading = None
204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotry:
224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    unicode
234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoexcept NameError:
244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    have_unicode = False
254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoelse:
264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    have_unicode = True
274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoalist = [{'astring': 'foo@bar.baz.spam',
294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'afloat': 7283.43,
304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'anint': 2**20,
314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'ashortlong': 2L,
324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'anotherlist': ['.zyx.41'],
334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'abase64': xmlrpclib.Binary("my dog has fleas"),
344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'boolean': xmlrpclib.False,
354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'unicode': u'\u4000\u6000\u8000',
364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          u'ukey\u4000': 'regular value',
374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'datetime1': xmlrpclib.DateTime('20050210T11:41:23'),
384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'datetime2': xmlrpclib.DateTime(
394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                        (2005, 02, 10, 11, 41, 23, 0, 1, -1)),
404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          'datetime3': xmlrpclib.DateTime(
414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                        datetime.datetime(2005, 02, 10, 11, 41, 23)),
424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao          }]
434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass XMLRPCTestCase(unittest.TestCase):
454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_load(self):
474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(alist,
484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                         xmlrpclib.loads(xmlrpclib.dumps((alist,)))[0][0])
494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_bare_datetime(self):
514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # This checks that an unwrapped datetime.date object can be handled
524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # by the marshalling code.  This can't be done via test_dump_load()
534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # since with use_datetime set to 1 the unmarshaller would create
544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # datetime objects for the 'datetime[123]' keys as well
554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        dt = datetime.datetime(2005, 02, 10, 11, 41, 23)
564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        s = xmlrpclib.dumps((dt,))
574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        (newdt,), m = xmlrpclib.loads(s, use_datetime=1)
584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(newdt, dt)
594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(m, None)
604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(newdt, xmlrpclib.DateTime('20050210T11:41:23'))
634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_datetime_before_1900(self):
654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # same as before but with a date before 1900
664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        dt = datetime.datetime(1, 02, 10, 11, 41, 23)
674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        s = xmlrpclib.dumps((dt,))
684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        (newdt,), m = xmlrpclib.loads(s, use_datetime=1)
694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(newdt, dt)
704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(m, None)
714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(newdt, xmlrpclib.DateTime('00010210T11:41:23'))
744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_cmp_datetime_DateTime(self):
764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        now = datetime.datetime.now()
774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        dt = xmlrpclib.DateTime(now.timetuple())
784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertTrue(dt == now)
794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertTrue(now == dt)
804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        then = now + datetime.timedelta(seconds=4)
814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertTrue(then >= dt)
824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertTrue(dt < then)
834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_bug_1164912 (self):
854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = xmlrpclib.DateTime()
864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        ((new_d,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((d,),
874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                            methodresponse=True))
884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertIsInstance(new_d.value, str)
894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Check that the output of dumps() is still an 8-bit string
914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        s = xmlrpclib.dumps((new_d,), methodresponse=True)
924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertIsInstance(s, str)
934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_newstyle_class(self):
954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        class T(object):
964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            pass
974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = T()
984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t.x = 100
994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t.y = "Hello"
1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        ((t2,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((t,)))
1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(t2, t.__dict__)
1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_big_long(self):
1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(OverflowError, xmlrpclib.dumps, (2L**99,))
1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_bad_dict(self):
1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(TypeError, xmlrpclib.dumps, ({(1,2,3): 1},))
1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_recursive_seq(self):
1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        l = [1,2,3]
1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = [3,4,5,l]
1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        l.append(t)
1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(TypeError, xmlrpclib.dumps, (l,))
1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_recursive_dict(self):
1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = {'1':1, '2':1}
1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = {'3':3, 'd':d}
1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d['t'] = t
1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(TypeError, xmlrpclib.dumps, (d,))
1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_big_int(self):
1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if sys.maxint > 2L**31-1:
1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertRaises(OverflowError, xmlrpclib.dumps,
1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                              (int(2L**34),))
1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        xmlrpclib.dumps((xmlrpclib.MAXINT, xmlrpclib.MININT))
1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(OverflowError, xmlrpclib.dumps, (xmlrpclib.MAXINT+1,))
1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(OverflowError, xmlrpclib.dumps, (xmlrpclib.MININT-1,))
1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def dummy_write(s):
1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            pass
1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        m = xmlrpclib.Marshaller()
1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        m.dump_int(xmlrpclib.MAXINT, dummy_write)
1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        m.dump_int(xmlrpclib.MININT, dummy_write)
1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MAXINT+1, dummy_write)
1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MININT-1, dummy_write)
1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_none(self):
1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        value = alist + [None]
1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        arg1 = (alist + [None],)
1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        strg = xmlrpclib.dumps(arg1, allow_none=True)
1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(value,
1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                         xmlrpclib.loads(strg)[0][0])
1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,))
1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_default_encoding_issues(self):
1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # SF bug #1115989: wrong decoding in '_stringify'
1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        utf8 = """<?xml version='1.0' encoding='iso-8859-1'?>
1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                  <params>
1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    <param><value>
1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                      <string>abc \x95</string>
1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                      </value></param>
1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    <param><value>
1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                      <struct>
1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                        <member>
1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                          <name>def \x96</name>
1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                          <value><string>ghi \x97</string></value>
1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                          </member>
1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                        </struct>
1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                      </value></param>
1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                  </params>
1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                  """
1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # sys.setdefaultencoding() normally doesn't exist after site.py is
1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # loaded.  Import a temporary fresh copy to get access to it
1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # but then restore the original copy to avoid messing with
1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # other potentially modified sys module attributes
1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        old_encoding = sys.getdefaultencoding()
1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        with test_support.CleanImport('sys'):
1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            import sys as temp_sys
1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            temp_sys.setdefaultencoding("iso-8859-1")
1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            try:
1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                (s, d), m = xmlrpclib.loads(utf8)
1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            finally:
1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                temp_sys.setdefaultencoding(old_encoding)
1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        items = d.items()
1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if have_unicode:
1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(s, u"abc \x95")
1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertIsInstance(s, unicode)
1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(items, [(u"def \x96", u"ghi \x97")])
1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertIsInstance(items[0][0], unicode)
1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertIsInstance(items[0][1], unicode)
1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        else:
1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(s, "abc \xc2\x95")
1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(items, [("def \xc2\x96", "ghi \xc2\x97")])
1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass HelperTestCase(unittest.TestCase):
1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_escape(self):
1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(xmlrpclib.escape("a&b"), "a&amp;b")
1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(xmlrpclib.escape("a<b"), "a&lt;b")
1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(xmlrpclib.escape("a>b"), "a&gt;b")
1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass FaultTestCase(unittest.TestCase):
1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_repr(self):
1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        f = xmlrpclib.Fault(42, 'Test Fault')
2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(repr(f), "<Fault 42: 'Test Fault'>")
2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(repr(f), str(f))
2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dump_fault(self):
2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        f = xmlrpclib.Fault(42, 'Test Fault')
2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        s = xmlrpclib.dumps((f,))
2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        (newf,), m = xmlrpclib.loads(s)
2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(newf, {'faultCode': 42, 'faultString': 'Test Fault'})
2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(m, None)
2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        s = xmlrpclib.Marshaller().dumps(f)
2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, s)
2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass DateTimeTestCase(unittest.TestCase):
2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_default(self):
2164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.DateTime()
2174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_time(self):
2194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = 1181399930.036952
2204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.DateTime(d)
2214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(str(t), time.strftime("%Y%m%dT%H:%M:%S", time.localtime(d)))
2224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_time_tuple(self):
2244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = (2007,6,9,10,38,50,5,160,0)
2254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.DateTime(d)
2264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(str(t), '20070609T10:38:50')
2274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_time_struct(self):
2294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = time.localtime(1181399930.036952)
2304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.DateTime(d)
2314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(str(t),  time.strftime("%Y%m%dT%H:%M:%S", d))
2324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_datetime_datetime(self):
2344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = datetime.datetime(2007,1,2,3,4,5)
2354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.DateTime(d)
2364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(str(t), '20070102T03:04:05')
2374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_repr(self):
2394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = datetime.datetime(2007,1,2,3,4,5)
2404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.DateTime(d)
2414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        val ="<DateTime '20070102T03:04:05' at %x>" % id(t)
2424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(repr(t), val)
2434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_decode(self):
2454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = ' 20070908T07:11:13  '
2464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t1 = xmlrpclib.DateTime()
2474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t1.decode(d)
2484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        tref = xmlrpclib.DateTime(datetime.datetime(2007,9,8,7,11,13))
2494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(t1, tref)
2504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t2 = xmlrpclib._datetime(d)
2524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(t1, tref)
2534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass BinaryTestCase(unittest.TestCase):
2554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_default(self):
2564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.Binary()
2574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(str(t), '')
2584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_string(self):
2604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = '\x01\x02\x03abc123\xff\xfe'
2614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.Binary(d)
2624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(str(t), d)
2634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_decode(self):
2654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        d = '\x01\x02\x03abc123\xff\xfe'
2664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        de = base64.encodestring(d)
2674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t1 = xmlrpclib.Binary()
2684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t1.decode(de)
2694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(str(t1), d)
2704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t2 = xmlrpclib._binary(de)
2724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(str(t2), d)
2734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2754adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoADDR = PORT = URL = None
2764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# The evt is set twice.  First when the server is ready to serve.
2784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Second when the server has been shutdown.  The user must clear
2794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# the event after it has been set the first time to catch the second set.
2804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef http_server(evt, numrequests, requestHandler=None):
2814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    class TestInstanceClass:
2824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def div(self, x, y):
2834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return x // y
2844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def _methodHelp(self, name):
2864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if name == 'div':
2874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                return 'This is the div function'
2884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def my_function():
2904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''This is my function'''
2914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return True
2924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
2934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    class MyXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
2944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def get_request(self):
2954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # Ensure the socket is always non-blocking.  On Linux, socket
2964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # attributes are not inherited like they are on *BSD and Windows.
2974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            s, port = self.socket.accept()
2984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            s.setblocking(True)
2994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return s, port
3004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    if not requestHandler:
3024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        requestHandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler
3034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    serv = MyXMLRPCServer(("localhost", 0), requestHandler,
3044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                          logRequests=False, bind_and_activate=False)
3054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    try:
3064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.socket.settimeout(3)
3074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.server_bind()
3084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        global ADDR, PORT, URL
3094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        ADDR, PORT = serv.socket.getsockname()
3104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #connect to IP address directly.  This avoids socket.create_connection()
3114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #trying to connect to "localhost" using all address families, which
3124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #causes slowdown e.g. on vista which supports AF_INET6.  The server listens
3134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #on AF_INET only.
3144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        URL = "http://%s:%d"%(ADDR, PORT)
3154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.server_activate()
3164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.register_introspection_functions()
3174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.register_multicall_functions()
3184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.register_function(pow)
3194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.register_function(lambda x,y: x+y, 'add')
3204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.register_function(my_function)
3214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.register_instance(TestInstanceClass())
3224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        evt.set()
3234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # handle up to 'numrequests' requests
3254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        while numrequests > 0:
3264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            serv.handle_request()
3274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            numrequests -= 1
3284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    except socket.timeout:
3304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        pass
3314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    finally:
3324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.socket.close()
3334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        PORT = None
3344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        evt.set()
3354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef http_multi_server(evt, numrequests, requestHandler=None):
3374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    class TestInstanceClass:
3384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def div(self, x, y):
3394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return x // y
3404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def _methodHelp(self, name):
3424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if name == 'div':
3434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                return 'This is the div function'
3444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def my_function():
3464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        '''This is my function'''
3474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return True
3484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    class MyXMLRPCServer(SimpleXMLRPCServer.MultiPathXMLRPCServer):
3504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def get_request(self):
3514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # Ensure the socket is always non-blocking.  On Linux, socket
3524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # attributes are not inherited like they are on *BSD and Windows.
3534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            s, port = self.socket.accept()
3544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            s.setblocking(True)
3554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return s, port
3564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    if not requestHandler:
3584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        requestHandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler
3594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    class MyRequestHandler(requestHandler):
3604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        rpc_paths = []
3614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    serv = MyXMLRPCServer(("localhost", 0), MyRequestHandler,
3634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                          logRequests=False, bind_and_activate=False)
3644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    serv.socket.settimeout(3)
3654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    serv.server_bind()
3664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    try:
3674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        global ADDR, PORT, URL
3684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        ADDR, PORT = serv.socket.getsockname()
3694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #connect to IP address directly.  This avoids socket.create_connection()
3704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #trying to connect to "localhost" using all address families, which
3714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #causes slowdown e.g. on vista which supports AF_INET6.  The server listens
3724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #on AF_INET only.
3734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        URL = "http://%s:%d"%(ADDR, PORT)
3744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.server_activate()
3754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        paths = ["/foo", "/foo/bar"]
3764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        for path in paths:
3774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            d = serv.add_dispatcher(path, SimpleXMLRPCServer.SimpleXMLRPCDispatcher())
3784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            d.register_introspection_functions()
3794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            d.register_multicall_functions()
3804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.get_dispatcher(paths[0]).register_function(pow)
3814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.get_dispatcher(paths[1]).register_function(lambda x,y: x+y, 'add')
3824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        evt.set()
3834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # handle up to 'numrequests' requests
3854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        while numrequests > 0:
3864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            serv.handle_request()
3874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            numrequests -= 1
3884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    except socket.timeout:
3904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        pass
3914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    finally:
3924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv.socket.close()
3934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        PORT = None
3944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        evt.set()
3954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
3964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# This function prevents errors like:
3974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#    <ProtocolError for localhost:57527/RPC2: 500 Internal Server Error>
3984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef is_unavailable_exception(e):
3994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    '''Returns True if the given ProtocolError is the product of a server-side
4004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao       exception caused by the 'temporarily unavailable' response sometimes
4014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao       given by operations on non-blocking sockets.'''
4024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # sometimes we get a -1 error code and/or empty headers
4044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    try:
4054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if e.errcode == -1 or e.headers is None:
4064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return True
4074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        exc_mess = e.headers.get('X-exception')
4084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    except AttributeError:
4094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Ignore socket.errors here.
4104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        exc_mess = str(e)
4114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    if exc_mess and 'temporarily unavailable' in exc_mess.lower():
4134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return True
4144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    return False
4164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao@unittest.skipUnless(threading, 'Threading required for this test.')
4184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass BaseServerTestCase(unittest.TestCase):
4194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    requestHandler = None
4204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    request_count = 1
4214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    threadFunc = staticmethod(http_server)
4224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def setUp(self):
4244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # enable traceback reporting
4254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True
4264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.evt = threading.Event()
4284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # start server thread to handle requests
4294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv_args = (self.evt, self.request_count, self.requestHandler)
4304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        threading.Thread(target=self.threadFunc, args=serv_args).start()
4314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # wait for the server to be ready
4334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.evt.wait(10)
4344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.evt.clear()
4354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def tearDown(self):
4374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # wait on the server thread to terminate
4384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.evt.wait(10)
4394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # disable traceback reporting
4414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = False
4424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# NOTE: The tests in SimpleServerTestCase will ignore failures caused by
4444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# "temporarily unavailable" exceptions raised in SimpleXMLRPCServer.  This
4454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# condition occurs infrequently on some platforms, frequently on others, and
4464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# is apparently caused by using SimpleXMLRPCServer with a non-blocking socket
4474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# If the server class is updated at some point in the future to handle this
4484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# situation more gracefully, these tests should be modified appropriately.
4494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass SimpleServerTestCase(BaseServerTestCase):
4514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_simple1(self):
4524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
4534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
4544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(p.pow(6,8), 6**8)
4554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
4564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
4574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
4584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
4594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
4604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_nonascii(self):
4624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        start_string = 'P\N{LATIN SMALL LETTER Y WITH CIRCUMFLEX}t'
4634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        end_string = 'h\N{LATIN SMALL LETTER O WITH HORN}n'
4644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
4664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
4674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(p.add(start_string, end_string),
4684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                             start_string + end_string)
4694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error) as e:
4704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket unavailable errors.
4714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
4724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
4734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
4744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_unicode_host(self):
4764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        server = xmlrpclib.ServerProxy(u"http://%s:%d/RPC2"%(ADDR, PORT))
4774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(server.add("a", u"\xe9"), u"a\xe9")
4784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    # [ch] The test 404 is causing lots of false alarms.
4804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def XXXtest_404(self):
4814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # send POST with httplib, it should return 404 header and
4824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # 'Not Found' message.
4834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        conn = httplib.HTTPConnection(ADDR, PORT)
4844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        conn.request('POST', '/this-is-not-valid')
4854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        response = conn.getresponse()
4864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        conn.close()
4874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(response.status, 404)
4894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(response.reason, 'Not Found')
4904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
4914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_introspection1(self):
4924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
4934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
4944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            meth = p.system.listMethods()
4954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            expected_methods = set(['pow', 'div', 'my_function', 'add',
4964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                    'system.listMethods', 'system.methodHelp',
4974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                    'system.methodSignature', 'system.multicall'])
4984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(set(meth), expected_methods)
4994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
5004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
5014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
5024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
5034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_introspection2(self):
5064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
5074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # test _methodHelp()
5084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
5094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            divhelp = p.system.methodHelp('div')
5104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(divhelp, 'This is the div function')
5114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
5124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
5134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
5144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
5154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    @unittest.skipIf(sys.flags.optimize >= 2,
5184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                     "Docstrings are omitted with -O2 and above")
5194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_introspection3(self):
5204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
5214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # test native doc
5224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
5234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            myfunction = p.system.methodHelp('my_function')
5244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(myfunction, 'This is my function')
5254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
5264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
5274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
5284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
5294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_introspection4(self):
5324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # the SimpleXMLRPCServer doesn't support signatures, but
5334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # at least check that we can try making the call
5344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
5354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
5364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            divsig = p.system.methodSignature('div')
5374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(divsig, 'signatures not supported')
5384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
5394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
5404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
5414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
5424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_multicall(self):
5454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
5464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
5474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            multicall = xmlrpclib.MultiCall(p)
5484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            multicall.add(2,3)
5494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            multicall.pow(6,8)
5504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            multicall.div(127,42)
5514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            add_result, pow_result, div_result = multicall()
5524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(add_result, 2+3)
5534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(pow_result, 6**8)
5544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(div_result, 127//42)
5554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
5564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
5574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
5584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
5594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_non_existing_multicall(self):
5624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
5634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
5644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            multicall = xmlrpclib.MultiCall(p)
5654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            multicall.this_is_not_exists()
5664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            result = multicall()
5674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # result.results contains;
5694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # [{'faultCode': 1, 'faultString': '<type \'exceptions.Exception\'>:'
5704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            #   'method "this_is_not_exists" is not supported'>}]
5714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(result.results[0]['faultCode'], 1)
5734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(result.results[0]['faultString'],
5744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                '<type \'exceptions.Exception\'>:method "this_is_not_exists" '
5754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                'is not supported')
5764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
5774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
5784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
5794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
5804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
5814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_dotted_attribute(self):
5834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Raises an AttributeError because private methods are not allowed.
5844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(AttributeError,
5854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                          SimpleXMLRPCServer.resolve_dotted_attribute, str, '__add')
5864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertTrue(SimpleXMLRPCServer.resolve_dotted_attribute(str, 'title'))
5884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Get the test to run faster by sending a request with test_simple1.
5894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # This avoids waiting for the socket timeout.
5904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.test_simple1()
5914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_partial_post(self):
5934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Check that a partial POST doesn't make the server loop: issue #14001.
5944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        conn = httplib.HTTPConnection(ADDR, PORT)
5954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        conn.request('POST', '/RPC2 HTTP/1.0\r\nContent-Length: 100\r\n\r\nbye')
5964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        conn.close()
5974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
5984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass MultiPathServerTestCase(BaseServerTestCase):
5994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    threadFunc = staticmethod(http_multi_server)
6004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    request_count = 2
6014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_path1(self):
6024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(URL+"/foo")
6034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(xmlrpclib.Fault, p.add, 6, 8)
6054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_path2(self):
6064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(URL+"/foo/bar")
6074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.add(6,8), 6+8)
6084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(xmlrpclib.Fault, p.pow, 6, 8)
6094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism
6114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#does indeed serve subsequent requests on the same connection
6124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass BaseKeepaliveServerTestCase(BaseServerTestCase):
6134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #a request handler that supports keep-alive and logs requests into a
6144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #class variable
6154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
6164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        parentClass = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler
6174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        protocol_version = 'HTTP/1.1'
6184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        myRequests = []
6194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def handle(self):
6204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.myRequests.append([])
6214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.reqidx = len(self.myRequests)-1
6224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return self.parentClass.handle(self)
6234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def handle_one_request(self):
6244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            result = self.parentClass.handle_one_request(self)
6254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.myRequests[self.reqidx].append(self.raw_requestline)
6264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return result
6274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    requestHandler = RequestHandler
6294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def setUp(self):
6304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #clear request log
6314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.RequestHandler.myRequests = []
6324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return BaseServerTestCase.setUp(self)
6334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism
6354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#does indeed serve subsequent requests on the same connection
6364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass KeepaliveServerTestCase1(BaseKeepaliveServerTestCase):
6374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_two(self):
6384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(URL)
6394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #do three requests.
6404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #they should have all been handled by a single request handler
6454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(len(self.RequestHandler.myRequests), 1)
6464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #check that we did at least two (the third may be pending append
6484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #due to thread scheduling)
6494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertGreaterEqual(len(self.RequestHandler.myRequests[-1]), 2)
6504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#test special attribute access on the serverproxy, through the __call__
6524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#function.
6534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass KeepaliveServerTestCase2(BaseKeepaliveServerTestCase):
6544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #ask for two keepalive requests to be handled.
6554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    request_count=2
6564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_close(self):
6584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(URL)
6594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #do some requests with close.
6604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p("close")() #this should trigger a new keep-alive request
6644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #they should have all been two request handlers, each having logged at least
6694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #two complete requests
6704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(len(self.RequestHandler.myRequests), 2)
6714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertGreaterEqual(len(self.RequestHandler.myRequests[-1]), 2)
6724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertGreaterEqual(len(self.RequestHandler.myRequests[-2]), 2)
6734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_transport(self):
6754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(URL)
6764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #do some requests with close.
6774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p("transport").close() #same as above, really.
6794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
6804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(len(self.RequestHandler.myRequests), 2)
6814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#A test case that verifies that gzip encoding works in both directions
6834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#(for a request and the response)
6844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass GzipServerTestCase(BaseServerTestCase):
6854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #a request handler that supports keep-alive and logs requests into a
6864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    #class variable
6874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
6884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        parentClass = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler
6894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        protocol_version = 'HTTP/1.1'
6904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def do_POST(self):
6924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            #store content of last request in class
6934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.__class__.content_length = int(self.headers["content-length"])
6944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return self.parentClass.do_POST(self)
6954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    requestHandler = RequestHandler
6964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
6974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    class Transport(xmlrpclib.Transport):
6984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        #custom transport, stores the response length for our perusal
6994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        fake_gzip = False
7004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def parse_response(self, response):
7014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.response_length=int(response.getheader("content-length", 0))
7024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return xmlrpclib.Transport.parse_response(self, response)
7034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        def send_content(self, connection, body):
7054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if self.fake_gzip:
7064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                #add a lone gzip header to induce decode error remotely
7074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                connection.putheader("Content-Encoding", "gzip")
7084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return xmlrpclib.Transport.send_content(self, connection, body)
7094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def setUp(self):
7114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        BaseServerTestCase.setUp(self)
7124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_gzip_request(self):
7144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = self.Transport()
7154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t.encode_threshold = None
7164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(URL, transport=t)
7174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
7184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        a = self.RequestHandler.content_length
7194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t.encode_threshold = 0 #turn on request encoding
7204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
7214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        b = self.RequestHandler.content_length
7224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertTrue(a>b)
7234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_bad_gzip_request(self):
7254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = self.Transport()
7264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t.encode_threshold = None
7274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t.fake_gzip = True
7284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(URL, transport=t)
7294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        cm = self.assertRaisesRegexp(xmlrpclib.ProtocolError,
7304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                     re.compile(r"\b400\b"))
7314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        with cm:
7324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p.pow(6, 8)
7334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_gsip_response(self):
7354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = self.Transport()
7364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(URL, transport=t)
7374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        old = self.requestHandler.encode_threshold
7384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.requestHandler.encode_threshold = None #no encoding
7394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
7404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        a = t.response_length
7414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.requestHandler.encode_threshold = 0 #always encode
7424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p.pow(6,8), 6**8)
7434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        b = t.response_length
7444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.requestHandler.encode_threshold = old
7454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertTrue(a>b)
7464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#Test special attributes of the ServerProxy object
7484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass ServerProxyTestCase(unittest.TestCase):
7494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def setUp(self):
7504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        unittest.TestCase.setUp(self)
7514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if threading:
7524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.url = URL
7534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        else:
7544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # Without threading, http_server() and http_multi_server() will not
7554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # be executed and URL is still equal to None. 'http://' is a just
7564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # enough to choose the scheme (HTTP)
7574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.url = 'http://'
7584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_close(self):
7604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(self.url)
7614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p('close')(), None)
7624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_transport(self):
7644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        t = xmlrpclib.Transport()
7654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        p = xmlrpclib.ServerProxy(self.url, transport=t)
7664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(p('transport'), t)
7674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# This is a contrived way to make a failure occur on the server side
7694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# in order to test the _send_traceback_header flag on the server
7704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass FailingMessageClass(mimetools.Message):
7714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def __getitem__(self, key):
7724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        key = key.lower()
7734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        if key == 'content-length':
7744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return 'I am broken'
7754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return mimetools.Message.__getitem__(self, key)
7764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao@unittest.skipUnless(threading, 'Threading required for this test.')
7794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass FailingServerTestCase(unittest.TestCase):
7804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def setUp(self):
7814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.evt = threading.Event()
7824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # start server thread to handle requests
7834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        serv_args = (self.evt, 1)
7844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        threading.Thread(target=http_server, args=serv_args).start()
7854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # wait for the server to be ready
7874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.evt.wait()
7884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.evt.clear()
7894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def tearDown(self):
7914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # wait on the server thread to terminate
7924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.evt.wait()
7934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # reset flag
7944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = False
7954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # reset message class
7964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = mimetools.Message
7974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
7984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_basic(self):
7994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # check that flag is false by default
8004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        flagval = SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header
8014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(flagval, False)
8024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # enable traceback reporting
8044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True
8054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # test a call that shouldn't fail just as a smoke test
8074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
8084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
8094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(p.pow(6,8), 6**8)
8104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
8114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
8124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e):
8134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # protocol error; provide additional information in test output
8144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
8154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_fail_no_info(self):
8174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # use the broken message class
8184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = FailingMessageClass
8194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
8214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
8224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p.pow(6,8)
8234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
8244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
8254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e) and hasattr(e, "headers"):
8264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # The two server-side error headers shouldn't be sent back in this case
8274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertTrue(e.headers.get("X-exception") is None)
8284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertTrue(e.headers.get("X-traceback") is None)
8294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        else:
8304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.fail('ProtocolError not raised')
8314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_fail_with_info(self):
8334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # use the broken message class
8344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.MessageClass = FailingMessageClass
8354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Check that errors in the server send back exception/traceback
8374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # info when flag is set
8384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True
8394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
8414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p = xmlrpclib.ServerProxy(URL)
8424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            p.pow(6,8)
8434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except (xmlrpclib.ProtocolError, socket.error), e:
8444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # ignore failures due to non-blocking socket 'unavailable' errors
8454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            if not is_unavailable_exception(e) and hasattr(e, "headers"):
8464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                # We should get error info in the response
8474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                expected_err = "invalid literal for int() with base 10: 'I am broken'"
8484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertEqual(e.headers.get("x-exception"), expected_err)
8494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.assertTrue(e.headers.get("x-traceback") is not None)
8504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        else:
8514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.fail('ProtocolError not raised')
8524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass CGIHandlerTestCase(unittest.TestCase):
8544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def setUp(self):
8554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.cgi = SimpleXMLRPCServer.CGIXMLRPCRequestHandler()
8564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def tearDown(self):
8584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.cgi = None
8594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_cgi_get(self):
8614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        with test_support.EnvironmentVarGuard() as env:
8624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            env['REQUEST_METHOD'] = 'GET'
8634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # if the method is GET and no request_text is given, it runs handle_get
8644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # get sysout output
8654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            with test_support.captured_stdout() as data_out:
8664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                self.cgi.handle_request()
8674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            # parse Status header
8694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            data_out.seek(0)
8704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            handle = data_out.read()
8714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            status = handle.split()[1]
8724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            message = ' '.join(handle.split()[2:4])
8734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(status, '400')
8754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.assertEqual(message, 'Bad Request')
8764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_cgi_xmlrpc_response(self):
8794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        data = """<?xml version='1.0'?>
8804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        <methodCall>
8814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            <methodName>test_method</methodName>
8824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            <params>
8834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                <param>
8844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    <value><string>foo</string></value>
8854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                </param>
8864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                <param>
8874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                    <value><string>bar</string></value>
8884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                </param>
8894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            </params>
8904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        </methodCall>
8914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        """
8924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
8934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        with test_support.EnvironmentVarGuard() as env, \
8944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao             test_support.captured_stdout() as data_out, \
8954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao             test_support.captured_stdin() as data_in:
8964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            data_in.write(data)
8974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            data_in.seek(0)
8984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            env['CONTENT_LENGTH'] = str(len(data))
8994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            self.cgi.handle_request()
9004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        data_out.seek(0)
9014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # will respond exception, if so, our goal is achieved ;)
9034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        handle = data_out.read()
9044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # start with 44th char so as not to get http header, we just need only xml
9064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, handle[44:])
9074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Also test the content-length returned  by handle_request
9094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Using the same test method inorder to avoid all the datapassing
9104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # boilerplate code.
9114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        # Test for bug: http://bugs.python.org/issue5040
9124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        content = handle[handle.find("<?xml"):]
9144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertEqual(
9164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            int(re.search('Content-Length: (\d+)', handle).group(1)),
9174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            len(content))
9184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass FakeSocket:
9214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def __init__(self):
9234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.data = StringIO.StringIO()
9244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def send(self, buf):
9264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.data.write(buf)
9274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return len(buf)
9284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def sendall(self, buf):
9304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.data.write(buf)
9314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def getvalue(self):
9334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return self.data.getvalue()
9344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def makefile(self, x='r', y=-1):
9364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        raise RuntimeError
9374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def close(self):
9394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        pass
9404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass FakeTransport(xmlrpclib.Transport):
9424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    """A Transport instance that records instead of sending a request.
9434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    This class replaces the actual socket used by httplib with a
9454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    FakeSocket object that records the request.  It doesn't provide a
9464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    response.
9474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    """
9484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def make_connection(self, host):
9504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        conn = xmlrpclib.Transport.make_connection(self, host)
9514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        conn.sock = self.fake_socket = FakeSocket()
9524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return conn
9534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass TransportSubclassTestCase(unittest.TestCase):
9554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def issue_request(self, transport_class):
9574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        """Return an HTTP request made via transport_class."""
9584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        transport = transport_class()
9594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        proxy = xmlrpclib.ServerProxy("http://example.com/",
9604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                                      transport=transport)
9614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        try:
9624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            proxy.pow(6, 8)
9634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        except RuntimeError:
9644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            return transport.fake_socket.getvalue()
9654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        return None
9664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_custom_user_agent(self):
9684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        class TestTransport(FakeTransport):
9694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            def send_user_agent(self, conn):
9714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                xmlrpclib.Transport.send_user_agent(self, conn)
9724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                conn.putheader("X-Test", "test_custom_user_agent")
9734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        req = self.issue_request(TestTransport)
9754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertIn("X-Test: test_custom_user_agent\r\n", req)
9764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_send_host(self):
9784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        class TestTransport(FakeTransport):
9794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            def send_host(self, conn, host):
9814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                xmlrpclib.Transport.send_host(self, conn, host)
9824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                conn.putheader("X-Test", "test_send_host")
9834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        req = self.issue_request(TestTransport)
9854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertIn("X-Test: test_send_host\r\n", req)
9864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_send_request(self):
9884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        class TestTransport(FakeTransport):
9894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            def send_request(self, conn, url, body):
9914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                xmlrpclib.Transport.send_request(self, conn, url, body)
9924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                conn.putheader("X-Test", "test_send_request")
9934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        req = self.issue_request(TestTransport)
9954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertIn("X-Test: test_send_request\r\n", req)
9964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
9974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    def test_send_content(self):
9984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        class TestTransport(FakeTransport):
9994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
10004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao            def send_content(self, conn, body):
10014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                conn.putheader("X-Test", "test_send_content")
10024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao                xmlrpclib.Transport.send_content(self, conn, body)
10034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
10044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        req = self.issue_request(TestTransport)
10054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        self.assertIn("X-Test: test_send_content\r\n", req)
10064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
10074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao@test_support.reap_threads
10084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef test_main():
10094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    xmlrpc_tests = [XMLRPCTestCase, HelperTestCase, DateTimeTestCase,
10104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao         BinaryTestCase, FaultTestCase, TransportSubclassTestCase]
10114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    xmlrpc_tests.append(SimpleServerTestCase)
10124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    xmlrpc_tests.append(KeepaliveServerTestCase1)
10134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    xmlrpc_tests.append(KeepaliveServerTestCase2)
10144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    try:
10154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        import gzip
10164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        xmlrpc_tests.append(GzipServerTestCase)
10174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    except ImportError:
10184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao        pass #gzip not supported in this build
10194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    xmlrpc_tests.append(MultiPathServerTestCase)
10204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    xmlrpc_tests.append(ServerProxyTestCase)
10214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    xmlrpc_tests.append(FailingServerTestCase)
10224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    xmlrpc_tests.append(CGIHandlerTestCase)
10234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
10244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    test_support.run_unittest(*xmlrpc_tests)
10254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao
10264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif __name__ == "__main__":
10274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao    test_main()
1028