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