source: wokkel/test/test_subprotocols.py @ 165:76a61f5aa343

Last change on this file since 165:76a61f5aa343 was 165:76a61f5aa343, checked in by Ralph Meijer <ralphm@…>, 8 years ago

Cleanups leading up to Wokkel 0.7.0.

As we now depend on Twisted 10.0.0 or higher, the following classes and
interfaces were deprecated:

This also resolves all Pyflakes warnings, changes links for www.xmpp.org to
xmpp.org and fixes the copyright notice in LICENSE to include 2012.

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