Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(604)

Side by Side Diff: third_party/twisted_8_1/twisted/web/test/test_xmlrpc.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.web.test.test_xmlrpc -*-
2 #
3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6 """
7 Test XML-RPC support.
8 """
9
10 try:
11 import xmlrpclib
12 except ImportError:
13 xmlrpclib = None
14 class XMLRPC: pass
15 else:
16 from twisted.web import xmlrpc
17 from twisted.web.xmlrpc import XMLRPC, addIntrospection, _QueryFactory
18
19 from twisted.trial import unittest
20 from twisted.web import server, static, client, error, http
21 from twisted.internet import reactor, defer
22 from twisted.internet.error import ConnectionDone
23 from twisted.python import failure
24
25
26 class TestRuntimeError(RuntimeError):
27 pass
28
29 class TestValueError(ValueError):
30 pass
31
32
33
34 class Test(XMLRPC):
35
36 FAILURE = 666
37 NOT_FOUND = 23
38 SESSION_EXPIRED = 42
39
40 # the doc string is part of the test
41 def xmlrpc_add(self, a, b):
42 """
43 This function add two numbers.
44 """
45 return a + b
46
47 xmlrpc_add.signature = [['int', 'int', 'int'],
48 ['double', 'double', 'double']]
49
50 # the doc string is part of the test
51 def xmlrpc_pair(self, string, num):
52 """
53 This function puts the two arguments in an array.
54 """
55 return [string, num]
56
57 xmlrpc_pair.signature = [['array', 'string', 'int']]
58
59 # the doc string is part of the test
60 def xmlrpc_defer(self, x):
61 """Help for defer."""
62 return defer.succeed(x)
63
64 def xmlrpc_deferFail(self):
65 return defer.fail(TestValueError())
66
67 # don't add a doc string, it's part of the test
68 def xmlrpc_fail(self):
69 raise TestRuntimeError
70
71 def xmlrpc_fault(self):
72 return xmlrpc.Fault(12, "hello")
73
74 def xmlrpc_deferFault(self):
75 return defer.fail(xmlrpc.Fault(17, "hi"))
76
77 def xmlrpc_complex(self):
78 return {"a": ["b", "c", 12, []], "D": "foo"}
79
80 def xmlrpc_dict(self, map, key):
81 return map[key]
82
83 def _getFunction(self, functionPath):
84 try:
85 return XMLRPC._getFunction(self, functionPath)
86 except xmlrpc.NoSuchFunction:
87 if functionPath.startswith("SESSION"):
88 raise xmlrpc.Fault(self.SESSION_EXPIRED,
89 "Session non-existant/expired.")
90 else:
91 raise
92
93 xmlrpc_dict.help = 'Help for dict.'
94
95 class TestAuthHeader(Test):
96 """
97 This is used to get the header info so that we can test
98 authentication.
99 """
100 def __init__(self):
101 Test.__init__(self)
102 self.request = None
103
104 def render(self, request):
105 self.request = request
106 return Test.render(self, request)
107
108 def xmlrpc_authinfo(self):
109 return self.request.getUser(), self.request.getPassword()
110
111
112 class TestQueryProtocol(xmlrpc.QueryProtocol):
113 """
114 QueryProtocol for tests that saves headers received inside the factory.
115 """
116 def handleHeader(self, key, val):
117 self.factory.headers[key.lower()] = val
118
119
120 class TestQueryFactory(xmlrpc._QueryFactory):
121 """
122 QueryFactory using L{TestQueryProtocol} for saving headers.
123 """
124 protocol = TestQueryProtocol
125
126 def __init__(self, *args, **kwargs):
127 self.headers = {}
128 xmlrpc._QueryFactory.__init__(self, *args, **kwargs)
129
130
131 class XMLRPCTestCase(unittest.TestCase):
132
133 def setUp(self):
134 self.p = reactor.listenTCP(0, server.Site(Test()),
135 interface="127.0.0.1")
136 self.port = self.p.getHost().port
137 self.factories = []
138
139 def tearDown(self):
140 self.factories = []
141 return self.p.stopListening()
142
143 def queryFactory(self, *args, **kwargs):
144 """
145 Specific queryFactory for proxy that uses our custom
146 L{TestQueryFactory}, and save factories.
147 """
148 factory = TestQueryFactory(*args, **kwargs)
149 self.factories.append(factory)
150 return factory
151
152 def proxy(self):
153 p = xmlrpc.Proxy("http://127.0.0.1:%d/" % self.port)
154 p.queryFactory = self.queryFactory
155 return p
156
157 def test_results(self):
158 inputOutput = [
159 ("add", (2, 3), 5),
160 ("defer", ("a",), "a"),
161 ("dict", ({"a": 1}, "a"), 1),
162 ("pair", ("a", 1), ["a", 1]),
163 ("complex", (), {"a": ["b", "c", 12, []], "D": "foo"})]
164
165 dl = []
166 for meth, args, outp in inputOutput:
167 d = self.proxy().callRemote(meth, *args)
168 d.addCallback(self.assertEquals, outp)
169 dl.append(d)
170 return defer.DeferredList(dl, fireOnOneErrback=True)
171
172 def test_errors(self):
173 """
174 Verify that for each way a method exposed via XML-RPC can fail, the
175 correct 'Content-type' header is set in the response and that the
176 client-side Deferred is errbacked with an appropriate C{Fault}
177 instance.
178 """
179 dl = []
180 for code, methodName in [(666, "fail"), (666, "deferFail"),
181 (12, "fault"), (23, "noSuchMethod"),
182 (17, "deferFault"), (42, "SESSION_TEST")]:
183 d = self.proxy().callRemote(methodName)
184 d = self.assertFailure(d, xmlrpc.Fault)
185 d.addCallback(lambda exc, code=code:
186 self.assertEquals(exc.faultCode, code))
187 dl.append(d)
188 d = defer.DeferredList(dl, fireOnOneErrback=True)
189 def cb(ign):
190 for factory in self.factories:
191 self.assertEquals(factory.headers['content-type'],
192 'text/xml')
193 self.flushLoggedErrors(TestRuntimeError, TestValueError)
194 d.addCallback(cb)
195 return d
196
197 def test_errorGet(self):
198 """
199 A classic GET on the xml server should return a NOT_ALLOWED.
200 """
201 d = client.getPage("http://127.0.0.1:%d/" % (self.port,))
202 d = self.assertFailure(d, error.Error)
203 d.addCallback(
204 lambda exc: self.assertEquals(int(exc.args[0]), http.NOT_ALLOWED))
205 return d
206
207 def test_errorXMLContent(self):
208 """
209 Test that an invalid XML input returns an L{xmlrpc.Fault}.
210 """
211 d = client.getPage("http://127.0.0.1:%d/" % (self.port,),
212 method="POST", postdata="foo")
213 def cb(result):
214 self.assertRaises(xmlrpc.Fault, xmlrpclib.loads, result)
215 d.addCallback(cb)
216 return d
217
218
219 class XMLRPCTestCase2(XMLRPCTestCase):
220 """
221 Test with proxy that doesn't add a slash.
222 """
223
224 def proxy(self):
225 p = xmlrpc.Proxy("http://127.0.0.1:%d" % self.port)
226 p.queryFactory = self.queryFactory
227 return p
228
229
230
231 class XMLRPCAllowNoneTestCase(unittest.TestCase):
232 """
233 Test with allowNone set to True.
234
235 These are not meant to be exhaustive serialization tests, since
236 L{xmlrpclib} does all of the actual serialization work. They are just
237 meant to exercise a few codepaths to make sure we are calling into
238 xmlrpclib correctly.
239 """
240
241 def setUp(self):
242 self.p = reactor.listenTCP(
243 0, server.Site(Test(allowNone=True)), interface="127.0.0.1")
244 self.port = self.p.getHost().port
245
246
247 def tearDown(self):
248 return self.p.stopListening()
249
250
251 def proxy(self):
252 return xmlrpc.Proxy("http://127.0.0.1:%d" % (self.port,),
253 allowNone=True)
254
255
256 def test_deferredNone(self):
257 """
258 Test that passing a C{None} as an argument to a remote method and
259 returning a L{Deferred} which fires with C{None} properly passes
260 </nil> over the network if allowNone is set to True.
261 """
262 d = self.proxy().callRemote('defer', None)
263 d.addCallback(self.assertEquals, None)
264 return d
265
266
267 def test_dictWithNoneValue(self):
268 """
269 Test that return a C{dict} with C{None} as a value works properly.
270 """
271 d = self.proxy().callRemote('defer', {'a': None})
272 d.addCallback(self.assertEquals, {'a': None})
273 return d
274
275
276
277 class XMLRPCTestAuthenticated(XMLRPCTestCase):
278 """
279 Test with authenticated proxy. We run this with the same inout/ouput as
280 above.
281 """
282 user = "username"
283 password = "asecret"
284
285 def setUp(self):
286 self.p = reactor.listenTCP(0, server.Site(TestAuthHeader()),
287 interface="127.0.0.1")
288 self.port = self.p.getHost().port
289 self.factories = []
290
291
292 def test_authInfoInURL(self):
293 p = xmlrpc.Proxy("http://%s:%s@127.0.0.1:%d/" % (
294 self.user, self.password, self.port))
295 d = p.callRemote("authinfo")
296 d.addCallback(self.assertEquals, [self.user, self.password])
297 return d
298
299
300 def test_explicitAuthInfo(self):
301 p = xmlrpc.Proxy("http://127.0.0.1:%d/" % (
302 self.port,), self.user, self.password)
303 d = p.callRemote("authinfo")
304 d.addCallback(self.assertEquals, [self.user, self.password])
305 return d
306
307
308 def test_explicitAuthInfoOverride(self):
309 p = xmlrpc.Proxy("http://wrong:info@127.0.0.1:%d/" % (
310 self.port,), self.user, self.password)
311 d = p.callRemote("authinfo")
312 d.addCallback(self.assertEquals, [self.user, self.password])
313 return d
314
315
316 class XMLRPCTestIntrospection(XMLRPCTestCase):
317
318 def setUp(self):
319 xmlrpc = Test()
320 addIntrospection(xmlrpc)
321 self.p = reactor.listenTCP(0, server.Site(xmlrpc),interface="127.0.0.1")
322 self.port = self.p.getHost().port
323 self.factories = []
324
325 def test_listMethods(self):
326
327 def cbMethods(meths):
328 meths.sort()
329 self.failUnlessEqual(
330 meths,
331 ['add', 'complex', 'defer', 'deferFail',
332 'deferFault', 'dict', 'fail', 'fault',
333 'pair', 'system.listMethods',
334 'system.methodHelp',
335 'system.methodSignature'])
336
337 d = self.proxy().callRemote("system.listMethods")
338 d.addCallback(cbMethods)
339 return d
340
341 def test_methodHelp(self):
342 inputOutputs = [
343 ("defer", "Help for defer."),
344 ("fail", ""),
345 ("dict", "Help for dict.")]
346
347 dl = []
348 for meth, expected in inputOutputs:
349 d = self.proxy().callRemote("system.methodHelp", meth)
350 d.addCallback(self.assertEquals, expected)
351 dl.append(d)
352 return defer.DeferredList(dl, fireOnOneErrback=True)
353
354 def test_methodSignature(self):
355 inputOutputs = [
356 ("defer", ""),
357 ("add", [['int', 'int', 'int'],
358 ['double', 'double', 'double']]),
359 ("pair", [['array', 'string', 'int']])]
360
361 dl = []
362 for meth, expected in inputOutputs:
363 d = self.proxy().callRemote("system.methodSignature", meth)
364 d.addCallback(self.assertEquals, expected)
365 dl.append(d)
366 return defer.DeferredList(dl, fireOnOneErrback=True)
367
368
369 class XMLRPCClientErrorHandling(unittest.TestCase):
370 """
371 Test error handling on the xmlrpc client.
372 """
373 def setUp(self):
374 self.resource = static.File(__file__)
375 self.resource.isLeaf = True
376 self.port = reactor.listenTCP(0, server.Site(self.resource),
377 interface='127.0.0.1')
378
379 def tearDown(self):
380 return self.port.stopListening()
381
382 def test_erroneousResponse(self):
383 """
384 Test that calling the xmlrpc client on a static http server raises
385 an exception.
386 """
387 proxy = xmlrpc.Proxy("http://127.0.0.1:%d/" %
388 (self.port.getHost().port,))
389 return self.assertFailure(proxy.callRemote("someMethod"), Exception)
390
391
392
393 class TestQueryFactoryParseResponse(unittest.TestCase):
394 """
395 Test the behaviour of L{_QueryFactory.parseResponse}.
396 """
397
398 def setUp(self):
399 # The _QueryFactory that we are testing. We don't care about any
400 # of the constructor parameters.
401 self.queryFactory = _QueryFactory(
402 path=None, host=None, method='POST', user=None, password=None,
403 allowNone=False, args=())
404 # An XML-RPC response that will parse without raising an error.
405 self.goodContents = xmlrpclib.dumps(('',))
406 # An 'XML-RPC response' that will raise a parsing error.
407 self.badContents = 'invalid xml'
408 # A dummy 'reason' to pass to clientConnectionLost. We don't care
409 # what it is.
410 self.reason = failure.Failure(ConnectionDone())
411
412
413 def test_parseResponseCallbackSafety(self):
414 """
415 We can safely call L{_QueryFactory.clientConnectionLost} as a callback
416 of L{_QueryFactory.parseResponse}.
417 """
418 d = self.queryFactory.deferred
419 # The failure mode is that this callback raises an AlreadyCalled
420 # error. We have to add it now so that it gets called synchronously
421 # and triggers the race condition.
422 d.addCallback(self.queryFactory.clientConnectionLost, self.reason)
423 self.queryFactory.parseResponse(self.goodContents)
424 return d
425
426
427 def test_parseResponseErrbackSafety(self):
428 """
429 We can safely call L{_QueryFactory.clientConnectionLost} as an errback
430 of L{_QueryFactory.parseResponse}.
431 """
432 d = self.queryFactory.deferred
433 # The failure mode is that this callback raises an AlreadyCalled
434 # error. We have to add it now so that it gets called synchronously
435 # and triggers the race condition.
436 d.addErrback(self.queryFactory.clientConnectionLost, self.reason)
437 self.queryFactory.parseResponse(self.badContents)
438 return d
439
440
441 def test_badStatusErrbackSafety(self):
442 """
443 We can safely call L{_QueryFactory.clientConnectionLost} as an errback
444 of L{_QueryFactory.badStatus}.
445 """
446 d = self.queryFactory.deferred
447 # The failure mode is that this callback raises an AlreadyCalled
448 # error. We have to add it now so that it gets called synchronously
449 # and triggers the race condition.
450 d.addErrback(self.queryFactory.clientConnectionLost, self.reason)
451 self.queryFactory.badStatus('status', 'message')
452 return d
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/web/test/test_xml.py ('k') | third_party/twisted_8_1/twisted/web/topfiles/NEWS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698