source: wokkel/test/test_subprotocols.py @ 194:f1b586df427b

Last change on this file since 194:f1b586df427b was 194:f1b586df427b, checked in by Ralph Meijer <ralphm@…>, 4 years ago

imported patch py3-subprotocols.patch

  • Property exe set to *
File size: 30.0 KB
Line 
1# Copyright (c) Ralph Meijer.
2# See LICENSE for details.
3
4"""
5Tests for L{wokkel.subprotocols}
6"""
7
8from __future__ import division, absolute_import
9
10from zope.interface.verify import verifyObject
11
12from twisted.trial import unittest
13from twisted.test import proto_helpers
14from twisted.internet import defer, task
15from twisted.internet.error import ConnectionDone
16from twisted.python import failure
17from twisted.words.xish import domish
18from twisted.words.protocols.jabber import error, ijabber, xmlstream
19
20from wokkel import generic, subprotocols
21
22class DeprecationTest(unittest.TestCase):
23    """
24    Deprecation test for L{wokkel.subprotocols}.
25    """
26
27    def lookForDeprecationWarning(self, testmethod, attributeName, newName):
28        """
29        Importing C{testmethod} emits a deprecation warning.
30        """
31        warningsShown = self.flushWarnings([testmethod])
32        self.assertEqual(len(warningsShown), 1)
33        self.assertIdentical(warningsShown[0]['category'], DeprecationWarning)
34        self.assertEqual(
35            warningsShown[0]['message'],
36            "wokkel.subprotocols." + attributeName + " "
37            "was deprecated in Wokkel 0.7.0: Use " + newName + " instead.")
38
39
40    def test_xmppHandlerCollection(self):
41        """
42        L{subprotocols.XMPPHandlerCollection} is deprecated.
43        """
44        from wokkel.subprotocols import XMPPHandlerCollection
45        XMPPHandlerCollection
46        self.lookForDeprecationWarning(
47                self.test_xmppHandlerCollection,
48                "XMPPHandlerCollection",
49                "twisted.words.protocols.jabber.xmlstream."
50                    "XMPPHandlerCollection")
51
52
53
54class DummyFactory(object):
55    """
56    Dummy XmlStream factory that only registers bootstrap observers.
57    """
58    def __init__(self):
59        self.callbacks = {}
60
61
62    def addBootstrap(self, event, callback):
63        self.callbacks[event] = callback
64
65
66
67class DummyXMPPHandler(subprotocols.XMPPHandler):
68    """
69    Dummy XMPP subprotocol handler to count the methods are called on it.
70    """
71    def __init__(self):
72        self.doneMade = 0
73        self.doneInitialized = 0
74        self.doneLost = 0
75
76
77    def makeConnection(self, xs):
78        self.connectionMade()
79
80
81    def connectionMade(self):
82        self.doneMade += 1
83
84
85    def connectionInitialized(self):
86        self.doneInitialized += 1
87
88
89    def connectionLost(self, reason):
90        self.doneLost += 1
91
92
93
94class FailureReasonXMPPHandler(subprotocols.XMPPHandler):
95    """
96    Dummy handler specifically for failure Reason tests.
97    """
98    def __init__(self):
99        self.gotFailureReason = False
100
101
102    def connectionLost(self, reason):
103        if isinstance(reason, failure.Failure):
104            self.gotFailureReason = True
105
106
107
108class IQGetStanza(generic.Stanza):
109    timeout = None
110
111    stanzaKind = 'iq'
112    stanzaType = 'get'
113    stanzaID = 'test'
114
115
116
117class XMPPHandlerTest(unittest.TestCase):
118    """
119    Tests for L{subprotocols.XMPPHandler}.
120    """
121
122    def test_interface(self):
123        """
124        L{xmlstream.XMPPHandler} implements L{ijabber.IXMPPHandler}.
125        """
126        verifyObject(ijabber.IXMPPHandler, subprotocols.XMPPHandler())
127
128
129    def test_send(self):
130        """
131        Test that data is passed on for sending by the stream manager.
132        """
133        class DummyStreamManager(object):
134            def __init__(self):
135                self.outlist = []
136
137            def send(self, data):
138                self.outlist.append(data)
139
140        handler = subprotocols.XMPPHandler()
141        handler.parent = DummyStreamManager()
142        handler.send('<presence/>')
143        self.assertEquals(['<presence/>'], handler.parent.outlist)
144
145
146    def test_makeConnection(self):
147        """
148        Test that makeConnection saves the XML stream and calls connectionMade.
149        """
150        class TestXMPPHandler(subprotocols.XMPPHandler):
151            def connectionMade(self):
152                self.doneMade = True
153
154        handler = TestXMPPHandler()
155        xs = xmlstream.XmlStream(xmlstream.Authenticator())
156        handler.makeConnection(xs)
157        self.assertTrue(handler.doneMade)
158        self.assertIdentical(xs, handler.xmlstream)
159
160
161    def test_connectionLost(self):
162        """
163        Test that connectionLost forgets the XML stream.
164        """
165        handler = subprotocols.XMPPHandler()
166        xs = xmlstream.XmlStream(xmlstream.Authenticator())
167        handler.makeConnection(xs)
168        handler.connectionLost(Exception())
169        self.assertIdentical(None, handler.xmlstream)
170
171
172    def test_request(self):
173        """
174        A request is passed up to the stream manager.
175        """
176        class DummyStreamManager(object):
177            def __init__(self):
178                self.requests = []
179
180            def request(self, request):
181                self.requests.append(request)
182                return defer.succeed(None)
183
184        handler = subprotocols.XMPPHandler()
185        handler.parent = DummyStreamManager()
186        request = IQGetStanza()
187        d = handler.request(request)
188        self.assertEquals(1, len(handler.parent.requests))
189        self.assertIdentical(request, handler.parent.requests[-1])
190        return d
191
192
193
194class StreamManagerTest(unittest.TestCase):
195    """
196    Tests for L{subprotocols.StreamManager}.
197    """
198
199    def setUp(self):
200        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
201        self.clock = task.Clock()
202        self.streamManager = subprotocols.StreamManager(factory, self.clock)
203        self.xmlstream = factory.buildProtocol(None)
204        self.transport = proto_helpers.StringTransport()
205        self.xmlstream.transport = self.transport
206
207        self.request = IQGetStanza()
208
209    def _streamStarted(self):
210        """
211        Bring the test stream to the initialized state.
212        """
213        self.xmlstream.connectionMade()
214        self.xmlstream.dataReceived(
215                b"<stream:stream xmlns='jabber:client' "
216                    b"xmlns:stream='http://etherx.jabber.org/streams' "
217                    b"from='example.com' id='12345'>")
218        self.xmlstream.dispatch(self.xmlstream, "//event/stream/authd")
219
220
221    def test_basic(self):
222        """
223        Test correct initialization and setup of factory observers.
224        """
225        factory = DummyFactory()
226        sm = subprotocols.StreamManager(factory)
227        self.assertIdentical(None, sm.xmlstream)
228        self.assertEquals([], sm.handlers)
229        self.assertEquals(sm._connected,
230                          sm.factory.callbacks['//event/stream/connected'])
231        self.assertEquals(sm._authd,
232                          sm.factory.callbacks['//event/stream/authd'])
233        self.assertEquals(sm._disconnected,
234                          sm.factory.callbacks['//event/stream/end'])
235        self.assertEquals(sm.initializationFailed,
236                          sm.factory.callbacks['//event/xmpp/initfailed'])
237
238
239    def test_connected(self):
240        """
241        Test that protocol handlers have their connectionMade method called
242        when the XML stream is connected.
243        """
244        sm = self.streamManager
245        handler = DummyXMPPHandler()
246        handler.setHandlerParent(sm)
247        xs = xmlstream.XmlStream(xmlstream.Authenticator())
248        sm._connected(xs)
249        self.assertEquals(1, handler.doneMade)
250        self.assertEquals(0, handler.doneInitialized)
251        self.assertEquals(0, handler.doneLost)
252
253
254    def test_connectedLogTrafficFalse(self):
255        """
256        Test raw data functions unset when logTraffic is set to False.
257        """
258        sm = self.streamManager
259        handler = DummyXMPPHandler()
260        handler.setHandlerParent(sm)
261        xs = xmlstream.XmlStream(xmlstream.Authenticator())
262        sm._connected(xs)
263        self.assertIdentical(None, xs.rawDataInFn)
264        self.assertIdentical(None, xs.rawDataOutFn)
265
266
267    def test_connectedLogTrafficTrue(self):
268        """
269        Test raw data functions set when logTraffic is set to True.
270        """
271        sm = self.streamManager
272        sm.logTraffic = True
273        handler = DummyXMPPHandler()
274        handler.setHandlerParent(sm)
275        xs = xmlstream.XmlStream(xmlstream.Authenticator())
276        sm._connected(xs)
277        self.assertNotIdentical(None, xs.rawDataInFn)
278        self.assertNotIdentical(None, xs.rawDataOutFn)
279
280
281    def test_authd(self):
282        """
283        Test that protocol handlers have their connectionInitialized method
284        called when the XML stream is initialized.
285        """
286        sm = self.streamManager
287        handler = DummyXMPPHandler()
288        handler.setHandlerParent(sm)
289        xs = xmlstream.XmlStream(xmlstream.Authenticator())
290        sm._authd(xs)
291        self.assertEquals(0, handler.doneMade)
292        self.assertEquals(1, handler.doneInitialized)
293        self.assertEquals(0, handler.doneLost)
294
295
296    def test_disconnected(self):
297        """
298        Protocol handlers have connectionLost called on stream disconnect.
299        """
300        sm = self.streamManager
301        handler = DummyXMPPHandler()
302        handler.setHandlerParent(sm)
303        sm._disconnected(None)
304        self.assertEquals(0, handler.doneMade)
305        self.assertEquals(0, handler.doneInitialized)
306        self.assertEquals(1, handler.doneLost)
307
308
309    def test_disconnectedReason(self):
310        """
311        A L{STREAM_END_EVENT} results in L{StreamManager} firing the handlers
312        L{connectionLost} methods, passing a L{failure.Failure} reason.
313        """
314        sm = self.streamManager
315        handler = FailureReasonXMPPHandler()
316        handler.setHandlerParent(sm)
317        xmlstream.XmlStream(xmlstream.Authenticator())
318        sm._disconnected(failure.Failure(Exception("no reason")))
319        self.assertEquals(True, handler.gotFailureReason)
320
321
322    def test_addHandler(self):
323        """
324        Test the addition of a protocol handler while not connected.
325        """
326        sm = self.streamManager
327        handler = DummyXMPPHandler()
328        handler.setHandlerParent(sm)
329
330        self.assertEquals(0, handler.doneMade)
331        self.assertEquals(0, handler.doneInitialized)
332        self.assertEquals(0, handler.doneLost)
333
334
335    def test_addHandlerConnected(self):
336        """
337        Adding a handler when connected doesn't call connectionInitialized.
338        """
339        sm = self.streamManager
340        xs = xmlstream.XmlStream(xmlstream.Authenticator())
341        sm._connected(xs)
342        handler = DummyXMPPHandler()
343        handler.setHandlerParent(sm)
344
345        self.assertEquals(1, handler.doneMade)
346        self.assertEquals(0, handler.doneInitialized)
347        self.assertEquals(0, handler.doneLost)
348
349
350    def test_addHandlerConnectedNested(self):
351        """
352        Adding a handler in connectionMade doesn't cause 2nd call.
353        """
354        class NestingHandler(DummyXMPPHandler):
355            nestedHandler = None
356
357            def connectionMade(self):
358                DummyXMPPHandler.connectionMade(self)
359                self.nestedHandler = DummyXMPPHandler()
360                self.nestedHandler.setHandlerParent(self.parent)
361
362        sm = self.streamManager
363        xs = xmlstream.XmlStream(xmlstream.Authenticator())
364        handler = NestingHandler()
365        handler.setHandlerParent(sm)
366        sm._connected(xs)
367
368        self.assertEquals(1, handler.doneMade)
369        self.assertEquals(0, handler.doneInitialized)
370        self.assertEquals(0, handler.doneLost)
371
372        self.assertEquals(1, handler.nestedHandler.doneMade)
373        self.assertEquals(0, handler.nestedHandler.doneInitialized)
374        self.assertEquals(0, handler.nestedHandler.doneLost)
375
376
377
378    def test_addHandlerInitialized(self):
379        """
380        Test the addition of a protocol handler after the stream
381        have been initialized.
382
383        Make sure that the handler will have the connected stream
384        passed via C{makeConnection} and have C{connectionInitialized}
385        called.
386        """
387        sm = self.streamManager
388        xs = xmlstream.XmlStream(xmlstream.Authenticator())
389        sm._connected(xs)
390        sm._authd(xs)
391        handler = DummyXMPPHandler()
392        handler.setHandlerParent(sm)
393
394        self.assertEquals(1, handler.doneMade)
395        self.assertEquals(1, handler.doneInitialized)
396        self.assertEquals(0, handler.doneLost)
397
398
399    def test_addHandlerInitializedNested(self):
400        """
401        Adding a handler in connectionInitialized doesn't cause 2nd call.
402        """
403        class NestingHandler(DummyXMPPHandler):
404            nestedHandler = None
405
406            def connectionInitialized(self):
407                DummyXMPPHandler.connectionInitialized(self)
408                self.nestedHandler = DummyXMPPHandler()
409                self.nestedHandler.setHandlerParent(self.parent)
410
411        sm = self.streamManager
412        xs = xmlstream.XmlStream(xmlstream.Authenticator())
413        handler = NestingHandler()
414        handler.setHandlerParent(sm)
415        sm._connected(xs)
416        sm._authd(xs)
417
418        self.assertEquals(1, handler.doneMade)
419        self.assertEquals(1, handler.doneInitialized)
420        self.assertEquals(0, handler.doneLost)
421
422        self.assertEquals(1, handler.nestedHandler.doneMade)
423        self.assertEquals(1, handler.nestedHandler.doneInitialized)
424        self.assertEquals(0, handler.nestedHandler.doneLost)
425
426
427    def test_addHandlerConnectionLostNested(self):
428        """
429        Adding a handler in connectionLost doesn't call connectionLost there.
430        """
431        class NestingHandler(DummyXMPPHandler):
432            nestedHandler = None
433
434            def connectionLost(self, reason):
435                DummyXMPPHandler.connectionLost(self, reason)
436                self.nestedHandler = DummyXMPPHandler()
437                self.nestedHandler.setHandlerParent(self.parent)
438
439        sm = self.streamManager
440        xs = xmlstream.XmlStream(xmlstream.Authenticator())
441        handler = NestingHandler()
442        handler.setHandlerParent(sm)
443        sm._connected(xs)
444        sm._authd(xs)
445        sm._disconnected(xs)
446
447        self.assertEquals(1, handler.doneMade)
448        self.assertEquals(1, handler.doneInitialized)
449        self.assertEquals(1, handler.doneLost)
450
451        self.assertEquals(0, handler.nestedHandler.doneMade)
452        self.assertEquals(0, handler.nestedHandler.doneInitialized)
453        self.assertEquals(0, handler.nestedHandler.doneLost)
454
455
456
457    def test_removeHandler(self):
458        """
459        Test removal of protocol handler.
460        """
461        sm = self.streamManager
462        handler = DummyXMPPHandler()
463        handler.setHandlerParent(sm)
464        handler.disownHandlerParent(sm)
465        self.assertNotIn(handler, sm)
466        self.assertIdentical(None, handler.parent)
467
468
469    def test_sendInitialized(self):
470        """
471        Test send when the stream has been initialized.
472
473        The data should be sent directly over the XML stream.
474        """
475        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
476        sm = subprotocols.StreamManager(factory)
477        xs = factory.buildProtocol(None)
478        xs.transport = proto_helpers.StringTransport()
479        xs.connectionMade()
480        xs.dataReceived(b"<stream:stream xmlns='jabber:client' "
481                        b"xmlns:stream='http://etherx.jabber.org/streams' "
482                        b"from='example.com' id='12345'>")
483        xs.dispatch(xs, "//event/stream/authd")
484        sm.send("<presence/>")
485        self.assertEquals(b"<presence/>", xs.transport.value())
486
487
488    def test_sendNotConnected(self):
489        """
490        Test send when there is no established XML stream.
491
492        The data should be cached until an XML stream has been established and
493        initialized.
494        """
495        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
496        sm = subprotocols.StreamManager(factory)
497        handler = DummyXMPPHandler()
498        sm.addHandler(handler)
499
500        xs = factory.buildProtocol(None)
501        xs.transport = proto_helpers.StringTransport()
502        sm.send("<presence/>")
503        self.assertEquals(b"", xs.transport.value())
504        self.assertEquals("<presence/>", sm._packetQueue[0])
505
506        xs.connectionMade()
507        self.assertEquals(b"", xs.transport.value())
508        self.assertEquals("<presence/>", sm._packetQueue[0])
509
510        xs.dataReceived(b"<stream:stream xmlns='jabber:client' "
511                        b"xmlns:stream='http://etherx.jabber.org/streams' "
512                        b"from='example.com' id='12345'>")
513        xs.dispatch(xs, "//event/stream/authd")
514
515        self.assertEquals(b"<presence/>", xs.transport.value())
516        self.assertFalse(sm._packetQueue)
517
518
519    def test_sendNotInitialized(self):
520        """
521        Test send when the stream is connected but not yet initialized.
522
523        The data should be cached until the XML stream has been initialized.
524        """
525        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
526        sm = subprotocols.StreamManager(factory)
527        xs = factory.buildProtocol(None)
528        xs.transport = proto_helpers.StringTransport()
529        xs.connectionMade()
530        xs.dataReceived(b"<stream:stream xmlns='jabber:client' "
531                        b"xmlns:stream='http://etherx.jabber.org/streams' "
532                        b"from='example.com' id='12345'>")
533        sm.send("<presence/>")
534        self.assertEquals(b"", xs.transport.value())
535        self.assertEquals("<presence/>", sm._packetQueue[0])
536
537
538    def test_sendDisconnected(self):
539        """
540        Test send after XML stream disconnection.
541
542        The data should be cached until a new XML stream has been established
543        and initialized.
544        """
545        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
546        sm = subprotocols.StreamManager(factory)
547        handler = DummyXMPPHandler()
548        sm.addHandler(handler)
549
550        xs = factory.buildProtocol(None)
551        xs.connectionMade()
552        xs.transport = proto_helpers.StringTransport()
553        xs.connectionLost(None)
554
555        sm.send("<presence/>")
556        self.assertEquals(b"", xs.transport.value())
557        self.assertEquals("<presence/>", sm._packetQueue[0])
558
559
560    def test_requestSendInitialized(self):
561        """
562        A request is sent out over the wire when the stream is initialized.
563        """
564        self._streamStarted()
565
566        self.streamManager.request(self.request)
567        self.assertTrue(self.transport.value())
568
569
570    def test_requestSendInitializedFreshID(self):
571        """
572        A request without an ID gets a fresh one upon send.
573        """
574        self._streamStarted()
575
576        self.request.stanzaID = None
577        self.streamManager.request(self.request)
578        self.assertNotIdentical(None, self.request.stanzaID)
579        self.assertTrue(self.transport.value())
580
581
582    def test_requestSendNotConnected(self):
583        """
584        A request is queued until a stream is initialized.
585        """
586        handler = DummyXMPPHandler()
587        self.streamManager.addHandler(handler)
588
589        self.streamManager.request(self.request)
590
591        xs = self.xmlstream
592        self.assertEquals(b"", xs.transport.value())
593
594        xs.connectionMade()
595        self.assertEquals(b"", xs.transport.value())
596
597        xs.dataReceived(b"<stream:stream xmlns='jabber:client' "
598                        b"xmlns:stream='http://etherx.jabber.org/streams' "
599                        b"from='example.com' id='12345'>")
600        xs.dispatch(xs, "//event/stream/authd")
601
602        self.assertTrue(self.transport.value())
603        self.assertFalse(self.streamManager._packetQueue)
604
605
606    def test_requestResultResponse(self):
607        """
608        A result response gets the request deferred fired with the response.
609        """
610        def cb(result):
611            self.assertEquals(result['type'], 'result')
612
613        self._streamStarted()
614        d = self.streamManager.request(self.request)
615        d.addCallback(cb)
616
617        xs = self.xmlstream
618        xs.dataReceived(b"<iq type='result' id='test'/>")
619        return d
620
621
622    def test_requestErrorResponse(self):
623        """
624        An error response gets the request deferred fired with a failure.
625        """
626        self._streamStarted()
627        d = self.streamManager.request(self.request)
628        self.assertFailure(d, error.StanzaError)
629
630        xs = self.xmlstream
631        xs.dataReceived(b"<iq type='error' id='test'/>")
632        return d
633
634
635    def test_requestNonTrackedResponse(self):
636        """
637        Test that untracked iq responses don't trigger any action.
638
639        Untracked means that the id of the incoming response iq is not
640        in the stream's C{iqDeferreds} dictionary.
641        """
642        # Set up a fallback handler that checks the stanza's handled attribute.
643        # If that is set to True, the iq tracker claims to have handled the
644        # response.
645        dispatched = []
646        def cb(iq):
647            dispatched.append(iq)
648
649        self._streamStarted()
650        self.xmlstream.addObserver("/iq", cb, -1)
651
652        # Receive an untracked iq response
653        self.xmlstream.dataReceived(b"<iq type='result' id='other'/>")
654        self.assertEquals(1, len(dispatched))
655        self.assertFalse(getattr(dispatched[-1], 'handled', False))
656
657
658    def test_requestCleanup(self):
659        """
660        Test if the deferred associated with an iq request is removed
661        from the list kept in the L{XmlStream} object after it has
662        been fired.
663        """
664        self._streamStarted()
665        d = self.streamManager.request(self.request)
666        xs = self.xmlstream
667        xs.dataReceived(b"<iq type='result' id='test'/>")
668        self.assertNotIn('test', self.streamManager._iqDeferreds)
669        return d
670
671
672    def test_requestDisconnectCleanup(self):
673        """
674        Test if deferreds for iq's that haven't yet received a response
675        have their errback called on stream disconnect.
676        """
677        d = self.streamManager.request(self.request)
678        xs = self.xmlstream
679        xs.connectionLost(failure.Failure(ConnectionDone()))
680        self.assertFailure(d, ConnectionDone)
681        return d
682
683
684    def test_requestNoModifyingDict(self):
685        """
686        Test to make sure the errbacks cannot cause the iteration of the
687        iqDeferreds to blow up in our face.
688        """
689
690        def eb(failure):
691            d = xmlstream.IQ(self.xmlstream).send()
692            d.addErrback(eb)
693
694        d = self.streamManager.request(self.request)
695        d.addErrback(eb)
696        self.xmlstream.connectionLost(failure.Failure(ConnectionDone()))
697        return d
698
699
700    def test_requestTimingOut(self):
701        """
702        Test that an iq request with a defined timeout times out.
703        """
704        self.request.timeout = 60
705        d = self.streamManager.request(self.request)
706        self.assertFailure(d, xmlstream.TimeoutError)
707
708        self.clock.pump([1, 60])
709        self.assertFalse(self.clock.calls)
710        self.assertFalse(self.streamManager._iqDeferreds)
711        return d
712
713
714    def test_requestNotTimingOut(self):
715        """
716        Test that an iq request with a defined timeout does not time out
717        when a response was received before the timeout period elapsed.
718        """
719        self._streamStarted()
720        self.request.timeout = 60
721        d = self.streamManager.request(self.request)
722        self.clock.callLater(1, self.xmlstream.dataReceived,
723                                b"<iq type='result' id='test'/>")
724        self.clock.pump([1, 1])
725        self.assertFalse(self.clock.calls)
726        return d
727
728
729    def test_requestDisconnectTimeoutCancellation(self):
730        """
731        Test if timeouts for iq's that haven't yet received a response
732        are cancelled on stream disconnect.
733        """
734
735        self.request.timeout = 60
736        d = self.streamManager.request(self.request)
737
738        self.xmlstream.connectionLost(failure.Failure(ConnectionDone()))
739        self.assertFailure(d, ConnectionDone)
740        self.assertFalse(self.clock.calls)
741        return d
742
743
744    def test_requestNotIQ(self):
745        """
746        The request stanza must be an iq.
747        """
748        stanza = generic.Stanza()
749        stanza.stanzaKind = 'message'
750
751        d = self.streamManager.request(stanza)
752        self.assertFailure(d, ValueError)
753
754
755    def test_requestNotResult(self):
756        """
757        The request stanza cannot be of type 'result'.
758        """
759        stanza = generic.Stanza()
760        stanza.stanzaKind = 'iq'
761        stanza.stanzaType = 'result'
762
763        d = self.streamManager.request(stanza)
764        self.assertFailure(d, ValueError)
765
766
767    def test_requestNotError(self):
768        """
769        The request stanza cannot be of type 'error'.
770        """
771        stanza = generic.Stanza()
772        stanza.stanzaKind = 'iq'
773        stanza.stanzaType = 'error'
774
775        d = self.streamManager.request(stanza)
776        self.assertFailure(d, ValueError)
777
778
779
780class DummyIQHandler(subprotocols.IQHandlerMixin):
781    iqHandlers = {'/iq[@type="get"]': 'onGet'}
782
783    def __init__(self):
784        self.output = []
785        self.xmlstream = xmlstream.XmlStream(xmlstream.Authenticator())
786        self.xmlstream.send = self.output.append
787
788    def send(self, obj):
789        self.xmlstream.send(obj)
790
791
792class IQHandlerTest(unittest.TestCase):
793
794    def test_match(self):
795        """
796        Test that the matching handler gets called.
797        """
798
799        class Handler(DummyIQHandler):
800            called = False
801
802            def onGet(self, iq):
803                self.called = True
804
805        iq = domish.Element((None, 'iq'))
806        iq['type'] = 'get'
807        iq['id'] = 'r1'
808        handler = Handler()
809        handler.handleRequest(iq)
810        self.assertTrue(handler.called)
811
812    def test_noMatch(self):
813        """
814        Test that the matching handler gets called.
815        """
816
817        class Handler(DummyIQHandler):
818            called = False
819
820            def onGet(self, iq):
821                self.called = True
822
823        iq = domish.Element((None, 'iq'))
824        iq['type'] = 'set'
825        iq['id'] = 'r1'
826        handler = Handler()
827        handler.handleRequest(iq)
828        self.assertFalse(handler.called)
829
830    def test_success(self):
831        """
832        Test response when the request is handled successfully.
833        """
834
835        class Handler(DummyIQHandler):
836            def onGet(self, iq):
837                return None
838
839        iq = domish.Element((None, 'iq'))
840        iq['type'] = 'get'
841        iq['id'] = 'r1'
842        handler = Handler()
843        handler.handleRequest(iq)
844        response = handler.output[-1]
845        self.assertEquals(None, response.uri)
846        self.assertEquals('iq', response.name)
847        self.assertEquals('result', response['type'])
848
849    def test_successPayload(self):
850        """
851        Test response when the request is handled successfully with payload.
852        """
853
854        class Handler(DummyIQHandler):
855            payload = domish.Element(('testns', 'foo'))
856
857            def onGet(self, iq):
858                return self.payload
859
860        iq = domish.Element((None, 'iq'))
861        iq['type'] = 'get'
862        iq['id'] = 'r1'
863        handler = Handler()
864        handler.handleRequest(iq)
865        response = handler.output[-1]
866        self.assertEquals(None, response.uri)
867        self.assertEquals('iq', response.name)
868        self.assertEquals('result', response['type'])
869        payload = next(response.elements())
870        self.assertEqual(handler.payload, payload)
871
872    def test_successDeferred(self):
873        """
874        Test response when where the handler was a deferred.
875        """
876
877        class Handler(DummyIQHandler):
878            def onGet(self, iq):
879                return defer.succeed(None)
880
881        iq = domish.Element((None, 'iq'))
882        iq['type'] = 'get'
883        iq['id'] = 'r1'
884        handler = Handler()
885        handler.handleRequest(iq)
886        response = handler.output[-1]
887        self.assertEquals(None, response.uri)
888        self.assertEquals('iq', response.name)
889        self.assertEquals('result', response['type'])
890
891    def test_failure(self):
892        """
893        Test response when the request is handled unsuccessfully.
894        """
895
896        class Handler(DummyIQHandler):
897            def onGet(self, iq):
898                raise error.StanzaError('forbidden')
899
900        iq = domish.Element((None, 'iq'))
901        iq['type'] = 'get'
902        iq['id'] = 'r1'
903        handler = Handler()
904        handler.handleRequest(iq)
905        response = handler.output[-1]
906        self.assertEquals(None, response.uri)
907        self.assertEquals('iq', response.name)
908        self.assertEquals('error', response['type'])
909        e = error.exceptionFromStanza(response)
910        self.assertEquals('forbidden', e.condition)
911
912    def test_failureUnknown(self):
913        """
914        Test response when the request handler raises a non-stanza-error.
915        """
916
917        class TestError(Exception):
918            pass
919
920        class Handler(DummyIQHandler):
921            def onGet(self, iq):
922                raise TestError()
923
924        iq = domish.Element((None, 'iq'))
925        iq['type'] = 'get'
926        iq['id'] = 'r1'
927        handler = Handler()
928        handler.handleRequest(iq)
929        response = handler.output[-1]
930        self.assertEquals(None, response.uri)
931        self.assertEquals('iq', response.name)
932        self.assertEquals('error', response['type'])
933        e = error.exceptionFromStanza(response)
934        self.assertEquals('internal-server-error', e.condition)
935        self.assertEquals(1, len(self.flushLoggedErrors(TestError)))
936
937    def test_notImplemented(self):
938        """
939        Test response when the request is recognised but not implemented.
940        """
941
942        class Handler(DummyIQHandler):
943            def onGet(self, iq):
944                raise NotImplementedError()
945
946        iq = domish.Element((None, 'iq'))
947        iq['type'] = 'get'
948        iq['id'] = 'r1'
949        handler = Handler()
950        handler.handleRequest(iq)
951        response = handler.output[-1]
952        self.assertEquals(None, response.uri)
953        self.assertEquals('iq', response.name)
954        self.assertEquals('error', response['type'])
955        e = error.exceptionFromStanza(response)
956        self.assertEquals('feature-not-implemented', e.condition)
957
958    def test_noHandler(self):
959        """
960        Test when the request is not recognised.
961        """
962
963        iq = domish.Element((None, 'iq'))
964        iq['type'] = 'set'
965        iq['id'] = 'r1'
966        handler = DummyIQHandler()
967        handler.handleRequest(iq)
968        response = handler.output[-1]
969        self.assertEquals(None, response.uri)
970        self.assertEquals('iq', response.name)
971        self.assertEquals('error', response['type'])
972        e = error.exceptionFromStanza(response)
973        self.assertEquals('feature-not-implemented', e.condition)
Note: See TracBrowser for help on using the repository browser.