Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / words / test / test_jabberxmlstream.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Tests for L{twisted.words.protocols.jabber.xmlstream}.
6 """
7
8 from twisted.trial import unittest
9
10 from zope.interface.verify import verifyObject
11
12 from twisted.internet import defer, task
13 from twisted.internet.error import ConnectionLost
14 from twisted.internet.interfaces import IProtocolFactory
15 from twisted.python import failure
16 from twisted.test import proto_helpers
17 from twisted.words.test.test_xmlstream import GenericXmlStreamFactoryTestsMixin
18 from twisted.words.xish import domish
19 from twisted.words.protocols.jabber import error, ijabber, jid, xmlstream
20
21
22
23 NS_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls'
24
25
26
27 class HashPasswordTest(unittest.TestCase):
28     """
29     Tests for L{xmlstream.hashPassword}.
30     """
31
32     def test_basic(self):
33         """
34         The sid and secret are concatenated to calculate sha1 hex digest.
35         """
36         hash = xmlstream.hashPassword(u"12345", u"secret")
37         self.assertEqual('99567ee91b2c7cabf607f10cb9f4a3634fa820e0', hash)
38
39
40     def test_sidNotUnicode(self):
41         """
42         The session identifier must be a unicode object.
43         """
44         self.assertRaises(TypeError, xmlstream.hashPassword, "\xc2\xb92345",
45                                                              u"secret")
46
47
48     def test_passwordNotUnicode(self):
49         """
50         The password must be a unicode object.
51         """
52         self.assertRaises(TypeError, xmlstream.hashPassword, u"12345",
53                                                              "secr\xc3\xa9t")
54
55
56     def test_unicodeSecret(self):
57         """
58         The concatenated sid and password must be encoded to UTF-8 before hashing.
59         """
60         hash = xmlstream.hashPassword(u"12345", u"secr\u00e9t")
61         self.assertEqual('659bf88d8f8e179081f7f3b4a8e7d224652d2853', hash)
62
63
64
65 class IQTest(unittest.TestCase):
66     """
67     Tests both IQ and the associated IIQResponseTracker callback.
68     """
69
70     def setUp(self):
71         authenticator = xmlstream.ConnectAuthenticator('otherhost')
72         authenticator.namespace = 'testns'
73         self.xmlstream = xmlstream.XmlStream(authenticator)
74         self.clock = task.Clock()
75         self.xmlstream._callLater = self.clock.callLater
76         self.xmlstream.makeConnection(proto_helpers.StringTransport())
77         self.xmlstream.dataReceived(
78            "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "
79                           "xmlns='testns' from='otherhost' version='1.0'>")
80         self.iq = xmlstream.IQ(self.xmlstream, 'get')
81
82
83     def testBasic(self):
84         self.assertEqual(self.iq['type'], 'get')
85         self.assertTrue(self.iq['id'])
86
87
88     def testSend(self):
89         self.xmlstream.transport.clear()
90         self.iq.send()
91         self.assertEqual("<iq type='get' id='%s'/>" % self.iq['id'],
92                           self.xmlstream.transport.value())
93
94
95     def testResultResponse(self):
96         def cb(result):
97             self.assertEqual(result['type'], 'result')
98
99         d = self.iq.send()
100         d.addCallback(cb)
101
102         xs = self.xmlstream
103         xs.dataReceived("<iq type='result' id='%s'/>" % self.iq['id'])
104         return d
105
106
107     def testErrorResponse(self):
108         d = self.iq.send()
109         self.assertFailure(d, error.StanzaError)
110
111         xs = self.xmlstream
112         xs.dataReceived("<iq type='error' id='%s'/>" % self.iq['id'])
113         return d
114
115
116     def testNonTrackedResponse(self):
117         """
118         Test that untracked iq responses don't trigger any action.
119
120         Untracked means that the id of the incoming response iq is not
121         in the stream's C{iqDeferreds} dictionary.
122         """
123         xs = self.xmlstream
124         xmlstream.upgradeWithIQResponseTracker(xs)
125
126         # Make sure we aren't tracking any iq's.
127         self.assertFalse(xs.iqDeferreds)
128
129         # Set up a fallback handler that checks the stanza's handled attribute.
130         # If that is set to True, the iq tracker claims to have handled the
131         # response.
132         def cb(iq):
133             self.assertFalse(getattr(iq, 'handled', False))
134
135         xs.addObserver("/iq", cb, -1)
136
137         # Receive an untracked iq response
138         xs.dataReceived("<iq type='result' id='test'/>")
139
140
141     def testCleanup(self):
142         """
143         Test if the deferred associated with an iq request is removed
144         from the list kept in the L{XmlStream} object after it has
145         been fired.
146         """
147
148         d = self.iq.send()
149         xs = self.xmlstream
150         xs.dataReceived("<iq type='result' id='%s'/>" % self.iq['id'])
151         self.assertNotIn(self.iq['id'], xs.iqDeferreds)
152         return d
153
154
155     def testDisconnectCleanup(self):
156         """
157         Test if deferreds for iq's that haven't yet received a response
158         have their errback called on stream disconnect.
159         """
160
161         d = self.iq.send()
162         xs = self.xmlstream
163         xs.connectionLost("Closed by peer")
164         self.assertFailure(d, ConnectionLost)
165         return d
166
167
168     def testNoModifyingDict(self):
169         """
170         Test to make sure the errbacks cannot cause the iteration of the
171         iqDeferreds to blow up in our face.
172         """
173
174         def eb(failure):
175             d = xmlstream.IQ(self.xmlstream).send()
176             d.addErrback(eb)
177
178         d = self.iq.send()
179         d.addErrback(eb)
180         self.xmlstream.connectionLost("Closed by peer")
181         return d
182
183
184     def testRequestTimingOut(self):
185         """
186         Test that an iq request with a defined timeout times out.
187         """
188         self.iq.timeout = 60
189         d = self.iq.send()
190         self.assertFailure(d, xmlstream.TimeoutError)
191
192         self.clock.pump([1, 60])
193         self.assertFalse(self.clock.calls)
194         self.assertFalse(self.xmlstream.iqDeferreds)
195         return d
196
197
198     def testRequestNotTimingOut(self):
199         """
200         Test that an iq request with a defined timeout does not time out
201         when a response was received before the timeout period elapsed.
202         """
203         self.iq.timeout = 60
204         d = self.iq.send()
205         self.clock.callLater(1, self.xmlstream.dataReceived,
206                              "<iq type='result' id='%s'/>" % self.iq['id'])
207         self.clock.pump([1, 1])
208         self.assertFalse(self.clock.calls)
209         return d
210
211
212     def testDisconnectTimeoutCancellation(self):
213         """
214         Test if timeouts for iq's that haven't yet received a response
215         are cancelled on stream disconnect.
216         """
217
218         self.iq.timeout = 60
219         d = self.iq.send()
220
221         xs = self.xmlstream
222         xs.connectionLost("Closed by peer")
223         self.assertFailure(d, ConnectionLost)
224         self.assertFalse(self.clock.calls)
225         return d
226
227
228
229 class XmlStreamTest(unittest.TestCase):
230
231     def onStreamStart(self, obj):
232         self.gotStreamStart = True
233
234
235     def onStreamEnd(self, obj):
236         self.gotStreamEnd = True
237
238
239     def onStreamError(self, obj):
240         self.gotStreamError = True
241
242
243     def setUp(self):
244         """
245         Set up XmlStream and several observers.
246         """
247         self.gotStreamStart = False
248         self.gotStreamEnd = False
249         self.gotStreamError = False
250         xs = xmlstream.XmlStream(xmlstream.Authenticator())
251         xs.addObserver('//event/stream/start', self.onStreamStart)
252         xs.addObserver('//event/stream/end', self.onStreamEnd)
253         xs.addObserver('//event/stream/error', self.onStreamError)
254         xs.makeConnection(proto_helpers.StringTransportWithDisconnection())
255         xs.transport.protocol = xs
256         xs.namespace = 'testns'
257         xs.version = (1, 0)
258         self.xmlstream = xs
259
260
261     def test_sendHeaderBasic(self):
262         """
263         Basic test on the header sent by sendHeader.
264         """
265         xs = self.xmlstream
266         xs.sendHeader()
267         splitHeader = self.xmlstream.transport.value()[0:-1].split(' ')
268         self.assertIn("<stream:stream", splitHeader)
269         self.assertIn("xmlns:stream='http://etherx.jabber.org/streams'",
270                       splitHeader)
271         self.assertIn("xmlns='testns'", splitHeader)
272         self.assertIn("version='1.0'", splitHeader)
273         self.assertTrue(xs._headerSent)
274
275
276     def test_sendHeaderAdditionalNamespaces(self):
277         """
278         Test for additional namespace declarations.
279         """
280         xs = self.xmlstream
281         xs.prefixes['jabber:server:dialback'] = 'db'
282         xs.sendHeader()
283         splitHeader = self.xmlstream.transport.value()[0:-1].split(' ')
284         self.assertIn("<stream:stream", splitHeader)
285         self.assertIn("xmlns:stream='http://etherx.jabber.org/streams'",
286                       splitHeader)
287         self.assertIn("xmlns:db='jabber:server:dialback'", splitHeader)
288         self.assertIn("xmlns='testns'", splitHeader)
289         self.assertIn("version='1.0'", splitHeader)
290         self.assertTrue(xs._headerSent)
291
292
293     def test_sendHeaderInitiating(self):
294         """
295         Test addressing when initiating a stream.
296         """
297         xs = self.xmlstream
298         xs.thisEntity = jid.JID('thisHost')
299         xs.otherEntity = jid.JID('otherHost')
300         xs.initiating = True
301         xs.sendHeader()
302         splitHeader = xs.transport.value()[0:-1].split(' ')
303         self.assertIn("to='otherhost'", splitHeader)
304         self.assertIn("from='thishost'", splitHeader)
305
306
307     def test_sendHeaderReceiving(self):
308         """
309         Test addressing when receiving a stream.
310         """
311         xs = self.xmlstream
312         xs.thisEntity = jid.JID('thisHost')
313         xs.otherEntity = jid.JID('otherHost')
314         xs.initiating = False
315         xs.sid = 'session01'
316         xs.sendHeader()
317         splitHeader = xs.transport.value()[0:-1].split(' ')
318         self.assertIn("to='otherhost'", splitHeader)
319         self.assertIn("from='thishost'", splitHeader)
320         self.assertIn("id='session01'", splitHeader)
321
322
323     def test_receiveStreamError(self):
324         """
325         Test events when a stream error is received.
326         """
327         xs = self.xmlstream
328         xs.dataReceived("<stream:stream xmlns='jabber:client' "
329                         "xmlns:stream='http://etherx.jabber.org/streams' "
330                         "from='example.com' id='12345' version='1.0'>")
331         xs.dataReceived("<stream:error/>")
332         self.assertTrue(self.gotStreamError)
333         self.assertTrue(self.gotStreamEnd)
334
335
336     def test_sendStreamErrorInitiating(self):
337         """
338         Test sendStreamError on an initiating xmlstream with a header sent.
339
340         An error should be sent out and the connection lost.
341         """
342         xs = self.xmlstream
343         xs.initiating = True
344         xs.sendHeader()
345         xs.transport.clear()
346         xs.sendStreamError(error.StreamError('version-unsupported'))
347         self.assertNotEqual('', xs.transport.value())
348         self.assertTrue(self.gotStreamEnd)
349
350
351     def test_sendStreamErrorInitiatingNoHeader(self):
352         """
353         Test sendStreamError on an initiating xmlstream without having sent a
354         header.
355
356         In this case, no header should be generated. Also, the error should
357         not be sent out on the stream. Just closing the connection.
358         """
359         xs = self.xmlstream
360         xs.initiating = True
361         xs.transport.clear()
362         xs.sendStreamError(error.StreamError('version-unsupported'))
363         self.assertNot(xs._headerSent)
364         self.assertEqual('', xs.transport.value())
365         self.assertTrue(self.gotStreamEnd)
366
367
368     def test_sendStreamErrorReceiving(self):
369         """
370         Test sendStreamError on a receiving xmlstream with a header sent.
371
372         An error should be sent out and the connection lost.
373         """
374         xs = self.xmlstream
375         xs.initiating = False
376         xs.sendHeader()
377         xs.transport.clear()
378         xs.sendStreamError(error.StreamError('version-unsupported'))
379         self.assertNotEqual('', xs.transport.value())
380         self.assertTrue(self.gotStreamEnd)
381
382
383     def test_sendStreamErrorReceivingNoHeader(self):
384         """
385         Test sendStreamError on a receiving xmlstream without having sent a
386         header.
387
388         In this case, a header should be generated. Then, the error should
389         be sent out on the stream followed by closing the connection.
390         """
391         xs = self.xmlstream
392         xs.initiating = False
393         xs.transport.clear()
394         xs.sendStreamError(error.StreamError('version-unsupported'))
395         self.assertTrue(xs._headerSent)
396         self.assertNotEqual('', xs.transport.value())
397         self.assertTrue(self.gotStreamEnd)
398
399
400     def test_reset(self):
401         """
402         Test resetting the XML stream to start a new layer.
403         """
404         xs = self.xmlstream
405         xs.sendHeader()
406         stream = xs.stream
407         xs.reset()
408         self.assertNotEqual(stream, xs.stream)
409         self.assertNot(xs._headerSent)
410
411
412     def test_send(self):
413         """
414         Test send with various types of objects.
415         """
416         xs = self.xmlstream
417         xs.send('<presence/>')
418         self.assertEqual(xs.transport.value(), '<presence/>')
419
420         xs.transport.clear()
421         el = domish.Element(('testns', 'presence'))
422         xs.send(el)
423         self.assertEqual(xs.transport.value(), '<presence/>')
424
425         xs.transport.clear()
426         el = domish.Element(('http://etherx.jabber.org/streams', 'features'))
427         xs.send(el)
428         self.assertEqual(xs.transport.value(), '<stream:features/>')
429
430
431     def test_authenticator(self):
432         """
433         Test that the associated authenticator is correctly called.
434         """
435         connectionMadeCalls = []
436         streamStartedCalls = []
437         associateWithStreamCalls = []
438
439         class TestAuthenticator:
440             def connectionMade(self):
441                 connectionMadeCalls.append(None)
442
443             def streamStarted(self, rootElement):
444                 streamStartedCalls.append(rootElement)
445
446             def associateWithStream(self, xs):
447                 associateWithStreamCalls.append(xs)
448
449         a = TestAuthenticator()
450         xs = xmlstream.XmlStream(a)
451         self.assertEqual([xs], associateWithStreamCalls)
452         xs.connectionMade()
453         self.assertEqual([None], connectionMadeCalls)
454         xs.dataReceived("<stream:stream xmlns='jabber:client' "
455                         "xmlns:stream='http://etherx.jabber.org/streams' "
456                         "from='example.com' id='12345'>")
457         self.assertEqual(1, len(streamStartedCalls))
458         xs.reset()
459         self.assertEqual([None], connectionMadeCalls)
460
461
462
463 class TestError(Exception):
464     pass
465
466
467
468 class AuthenticatorTest(unittest.TestCase):
469     def setUp(self):
470         self.authenticator = xmlstream.Authenticator()
471         self.xmlstream = xmlstream.XmlStream(self.authenticator)
472
473
474     def test_streamStart(self):
475         """
476         Test streamStart to fill the appropriate attributes from the
477         stream header.
478         """
479         xs = self.xmlstream
480         xs.makeConnection(proto_helpers.StringTransport())
481         xs.dataReceived("<stream:stream xmlns='jabber:client' "
482                          "xmlns:stream='http://etherx.jabber.org/streams' "
483                          "from='example.org' to='example.com' id='12345' "
484                          "version='1.0'>")
485         self.assertEqual((1, 0), xs.version)
486         self.assertIdentical(None, xs.sid)
487         self.assertEqual('invalid', xs.namespace)
488         self.assertIdentical(None, xs.otherEntity)
489         self.assertEqual(None, xs.thisEntity)
490
491
492     def test_streamStartLegacy(self):
493         """
494         Test streamStart to fill the appropriate attributes from the
495         stream header for a pre-XMPP-1.0 header.
496         """
497         xs = self.xmlstream
498         xs.makeConnection(proto_helpers.StringTransport())
499         xs.dataReceived("<stream:stream xmlns='jabber:client' "
500                         "xmlns:stream='http://etherx.jabber.org/streams' "
501                         "from='example.com' id='12345'>")
502         self.assertEqual((0, 0), xs.version)
503
504
505     def test_streamBadVersionOneDigit(self):
506         """
507         Test streamStart to fill the appropriate attributes from the
508         stream header for a version with only one digit.
509         """
510         xs = self.xmlstream
511         xs.makeConnection(proto_helpers.StringTransport())
512         xs.dataReceived("<stream:stream xmlns='jabber:client' "
513                         "xmlns:stream='http://etherx.jabber.org/streams' "
514                         "from='example.com' id='12345' version='1'>")
515         self.assertEqual((0, 0), xs.version)
516
517
518     def test_streamBadVersionNoNumber(self):
519         """
520         Test streamStart to fill the appropriate attributes from the
521         stream header for a malformed version.
522         """
523         xs = self.xmlstream
524         xs.makeConnection(proto_helpers.StringTransport())
525         xs.dataReceived("<stream:stream xmlns='jabber:client' "
526                         "xmlns:stream='http://etherx.jabber.org/streams' "
527                         "from='example.com' id='12345' version='blah'>")
528         self.assertEqual((0, 0), xs.version)
529
530
531
532 class ConnectAuthenticatorTest(unittest.TestCase):
533
534     def setUp(self):
535         self.gotAuthenticated = False
536         self.initFailure = None
537         self.authenticator = xmlstream.ConnectAuthenticator('otherHost')
538         self.xmlstream = xmlstream.XmlStream(self.authenticator)
539         self.xmlstream.addObserver('//event/stream/authd', self.onAuthenticated)
540         self.xmlstream.addObserver('//event/xmpp/initfailed', self.onInitFailed)
541
542
543     def onAuthenticated(self, obj):
544         self.gotAuthenticated = True
545
546
547     def onInitFailed(self, failure):
548         self.initFailure = failure
549
550
551     def testSucces(self):
552         """
553         Test successful completion of an initialization step.
554         """
555         class Initializer:
556             def initialize(self):
557                 pass
558
559         init = Initializer()
560         self.xmlstream.initializers = [init]
561
562         self.authenticator.initializeStream()
563         self.assertEqual([], self.xmlstream.initializers)
564         self.assertTrue(self.gotAuthenticated)
565
566
567     def testFailure(self):
568         """
569         Test failure of an initialization step.
570         """
571         class Initializer:
572             def initialize(self):
573                 raise TestError
574
575         init = Initializer()
576         self.xmlstream.initializers = [init]
577
578         self.authenticator.initializeStream()
579         self.assertEqual([init], self.xmlstream.initializers)
580         self.assertFalse(self.gotAuthenticated)
581         self.assertNotIdentical(None, self.initFailure)
582         self.assertTrue(self.initFailure.check(TestError))
583
584
585     def test_streamStart(self):
586         """
587         Test streamStart to fill the appropriate attributes from the
588         stream header.
589         """
590         self.authenticator.namespace = 'testns'
591         xs = self.xmlstream
592         xs.makeConnection(proto_helpers.StringTransport())
593         xs.dataReceived("<stream:stream xmlns='jabber:client' "
594                          "xmlns:stream='http://etherx.jabber.org/streams' "
595                          "from='example.com' to='example.org' id='12345' "
596                          "version='1.0'>")
597         self.assertEqual((1, 0), xs.version)
598         self.assertEqual('12345', xs.sid)
599         self.assertEqual('testns', xs.namespace)
600         self.assertEqual('example.com', xs.otherEntity.host)
601         self.assertIdentical(None, xs.thisEntity)
602         self.assertNot(self.gotAuthenticated)
603         xs.dataReceived("<stream:features>"
604                           "<test xmlns='testns'/>"
605                         "</stream:features>")
606         self.assertIn(('testns', 'test'), xs.features)
607         self.assertTrue(self.gotAuthenticated)
608
609
610
611 class ListenAuthenticatorTest(unittest.TestCase):
612     """
613     Tests for L{xmlstream.ListenAuthenticator}
614     """
615
616     def setUp(self):
617         self.authenticator = xmlstream.ListenAuthenticator()
618         self.xmlstream = xmlstream.XmlStream(self.authenticator)
619
620
621     def test_streamStart(self):
622         """
623         Test streamStart to fill the appropriate attributes from the
624         stream header.
625         """
626         xs = self.xmlstream
627         xs.makeConnection(proto_helpers.StringTransport())
628         self.assertIdentical(None, xs.sid)
629         xs.dataReceived("<stream:stream xmlns='jabber:client' "
630                          "xmlns:stream='http://etherx.jabber.org/streams' "
631                          "from='example.org' to='example.com' id='12345' "
632                          "version='1.0'>")
633         self.assertEqual((1, 0), xs.version)
634         self.assertNotIdentical(None, xs.sid)
635         self.assertNotEquals('12345', xs.sid)
636         self.assertEqual('jabber:client', xs.namespace)
637         self.assertIdentical(None, xs.otherEntity)
638         self.assertEqual('example.com', xs.thisEntity.host)
639
640
641     def test_streamStartUnicodeSessionID(self):
642         """
643         The generated session id must be a unicode object.
644         """
645         xs = self.xmlstream
646         xs.makeConnection(proto_helpers.StringTransport())
647         xs.dataReceived("<stream:stream xmlns='jabber:client' "
648                          "xmlns:stream='http://etherx.jabber.org/streams' "
649                          "from='example.org' to='example.com' id='12345' "
650                          "version='1.0'>")
651         self.assertIsInstance(xs.sid, unicode)
652
653
654
655 class TLSInitiatingInitializerTest(unittest.TestCase):
656     def setUp(self):
657         self.output = []
658         self.done = []
659
660         self.savedSSL = xmlstream.ssl
661
662         self.authenticator = xmlstream.Authenticator()
663         self.xmlstream = xmlstream.XmlStream(self.authenticator)
664         self.xmlstream.send = self.output.append
665         self.xmlstream.connectionMade()
666         self.xmlstream.dataReceived("<stream:stream xmlns='jabber:client' "
667                         "xmlns:stream='http://etherx.jabber.org/streams' "
668                         "from='example.com' id='12345' version='1.0'>")
669         self.init = xmlstream.TLSInitiatingInitializer(self.xmlstream)
670
671
672     def tearDown(self):
673         xmlstream.ssl = self.savedSSL
674
675
676     def testWantedSupported(self):
677         """
678         Test start when TLS is wanted and the SSL library available.
679         """
680         self.xmlstream.transport = proto_helpers.StringTransport()
681         self.xmlstream.transport.startTLS = lambda ctx: self.done.append('TLS')
682         self.xmlstream.reset = lambda: self.done.append('reset')
683         self.xmlstream.sendHeader = lambda: self.done.append('header')
684
685         d = self.init.start()
686         d.addCallback(self.assertEqual, xmlstream.Reset)
687         starttls = self.output[0]
688         self.assertEqual('starttls', starttls.name)
689         self.assertEqual(NS_XMPP_TLS, starttls.uri)
690         self.xmlstream.dataReceived("<proceed xmlns='%s'/>" % NS_XMPP_TLS)
691         self.assertEqual(['TLS', 'reset', 'header'], self.done)
692
693         return d
694
695     if not xmlstream.ssl:
696         testWantedSupported.skip = "SSL not available"
697
698
699     def testWantedNotSupportedNotRequired(self):
700         """
701         Test start when TLS is wanted and the SSL library available.
702         """
703         xmlstream.ssl = None
704
705         d = self.init.start()
706         d.addCallback(self.assertEqual, None)
707         self.assertEqual([], self.output)
708
709         return d
710
711
712     def testWantedNotSupportedRequired(self):
713         """
714         Test start when TLS is wanted and the SSL library available.
715         """
716         xmlstream.ssl = None
717         self.init.required = True
718
719         d = self.init.start()
720         self.assertFailure(d, xmlstream.TLSNotSupported)
721         self.assertEqual([], self.output)
722
723         return d
724
725
726     def testNotWantedRequired(self):
727         """
728         Test start when TLS is not wanted, but required by the server.
729         """
730         tls = domish.Element(('urn:ietf:params:xml:ns:xmpp-tls', 'starttls'))
731         tls.addElement('required')
732         self.xmlstream.features = {(tls.uri, tls.name): tls}
733         self.init.wanted = False
734
735         d = self.init.start()
736         self.assertEqual([], self.output)
737         self.assertFailure(d, xmlstream.TLSRequired)
738
739         return d
740
741
742     def testNotWantedNotRequired(self):
743         """
744         Test start when TLS is not wanted, but required by the server.
745         """
746         tls = domish.Element(('urn:ietf:params:xml:ns:xmpp-tls', 'starttls'))
747         self.xmlstream.features = {(tls.uri, tls.name): tls}
748         self.init.wanted = False
749
750         d = self.init.start()
751         d.addCallback(self.assertEqual, None)
752         self.assertEqual([], self.output)
753         return d
754
755
756     def testFailed(self):
757         """
758         Test failed TLS negotiation.
759         """
760         # Pretend that ssl is supported, it isn't actually used when the
761         # server starts out with a failure in response to our initial
762         # C{starttls} stanza.
763         xmlstream.ssl = 1
764
765         d = self.init.start()
766         self.assertFailure(d, xmlstream.TLSFailed)
767         self.xmlstream.dataReceived("<failure xmlns='%s'/>" % NS_XMPP_TLS)
768         return d
769
770
771
772 class TestFeatureInitializer(xmlstream.BaseFeatureInitiatingInitializer):
773     feature = ('testns', 'test')
774
775     def start(self):
776         return defer.succeed(None)
777
778
779
780 class BaseFeatureInitiatingInitializerTest(unittest.TestCase):
781
782     def setUp(self):
783         self.xmlstream = xmlstream.XmlStream(xmlstream.Authenticator())
784         self.init = TestFeatureInitializer(self.xmlstream)
785
786
787     def testAdvertized(self):
788         """
789         Test that an advertized feature results in successful initialization.
790         """
791         self.xmlstream.features = {self.init.feature:
792                                    domish.Element(self.init.feature)}
793         return self.init.initialize()
794
795
796     def testNotAdvertizedRequired(self):
797         """
798         Test that when the feature is not advertized, but required by the
799         initializer, an exception is raised.
800         """
801         self.init.required = True
802         self.assertRaises(xmlstream.FeatureNotAdvertized, self.init.initialize)
803
804
805     def testNotAdvertizedNotRequired(self):
806         """
807         Test that when the feature is not advertized, and not required by the
808         initializer, the initializer silently succeeds.
809         """
810         self.init.required = False
811         self.assertIdentical(None, self.init.initialize())
812
813
814
815 class ToResponseTest(unittest.TestCase):
816
817     def test_toResponse(self):
818         """
819         Test that a response stanza is generated with addressing swapped.
820         """
821         stanza = domish.Element(('jabber:client', 'iq'))
822         stanza['type'] = 'get'
823         stanza['to'] = 'user1@example.com'
824         stanza['from'] = 'user2@example.com/resource'
825         stanza['id'] = 'stanza1'
826         response = xmlstream.toResponse(stanza, 'result')
827         self.assertNotIdentical(stanza, response)
828         self.assertEqual(response['from'], 'user1@example.com')
829         self.assertEqual(response['to'], 'user2@example.com/resource')
830         self.assertEqual(response['type'], 'result')
831         self.assertEqual(response['id'], 'stanza1')
832
833
834     def test_toResponseNoFrom(self):
835         """
836         Test that a response is generated from a stanza without a from address.
837         """
838         stanza = domish.Element(('jabber:client', 'iq'))
839         stanza['type'] = 'get'
840         stanza['to'] = 'user1@example.com'
841         response = xmlstream.toResponse(stanza)
842         self.assertEqual(response['from'], 'user1@example.com')
843         self.assertFalse(response.hasAttribute('to'))
844
845
846     def test_toResponseNoTo(self):
847         """
848         Test that a response is generated from a stanza without a to address.
849         """
850         stanza = domish.Element(('jabber:client', 'iq'))
851         stanza['type'] = 'get'
852         stanza['from'] = 'user2@example.com/resource'
853         response = xmlstream.toResponse(stanza)
854         self.assertFalse(response.hasAttribute('from'))
855         self.assertEqual(response['to'], 'user2@example.com/resource')
856
857
858     def test_toResponseNoAddressing(self):
859         """
860         Test that a response is generated from a stanza without any addressing.
861         """
862         stanza = domish.Element(('jabber:client', 'message'))
863         stanza['type'] = 'chat'
864         response = xmlstream.toResponse(stanza)
865         self.assertFalse(response.hasAttribute('to'))
866         self.assertFalse(response.hasAttribute('from'))
867
868
869     def test_noID(self):
870         """
871         Test that a proper response is generated without id attribute.
872         """
873         stanza = domish.Element(('jabber:client', 'message'))
874         response = xmlstream.toResponse(stanza)
875         self.assertFalse(response.hasAttribute('id'))
876
877
878     def test_noType(self):
879         """
880         Test that a proper response is generated without type attribute.
881         """
882         stanza = domish.Element(('jabber:client', 'message'))
883         response = xmlstream.toResponse(stanza)
884         self.assertFalse(response.hasAttribute('type'))
885
886
887 class DummyFactory(object):
888     """
889     Dummy XmlStream factory that only registers bootstrap observers.
890     """
891     def __init__(self):
892         self.callbacks = {}
893
894
895     def addBootstrap(self, event, callback):
896         self.callbacks[event] = callback
897
898
899
900 class DummyXMPPHandler(xmlstream.XMPPHandler):
901     """
902     Dummy XMPP subprotocol handler to count the methods are called on it.
903     """
904     def __init__(self):
905         self.doneMade = 0
906         self.doneInitialized = 0
907         self.doneLost = 0
908
909
910     def makeConnection(self, xs):
911         self.connectionMade()
912
913
914     def connectionMade(self):
915         self.doneMade += 1
916
917
918     def connectionInitialized(self):
919         self.doneInitialized += 1
920
921
922     def connectionLost(self, reason):
923         self.doneLost += 1
924
925
926
927 class FailureReasonXMPPHandler(xmlstream.XMPPHandler):
928     """
929     Dummy handler specifically for failure Reason tests.
930     """
931     def __init__(self):
932         self.gotFailureReason = False
933
934
935     def connectionLost(self, reason):
936         if isinstance(reason, failure.Failure):
937             self.gotFailureReason = True
938
939
940
941 class XMPPHandlerTest(unittest.TestCase):
942     """
943     Tests for L{xmlstream.XMPPHandler}.
944     """
945
946     def test_interface(self):
947         """
948         L{xmlstream.XMPPHandler} implements L{ijabber.IXMPPHandler}.
949         """
950         verifyObject(ijabber.IXMPPHandler, xmlstream.XMPPHandler())
951
952
953     def test_send(self):
954         """
955         Test that data is passed on for sending by the stream manager.
956         """
957         class DummyStreamManager(object):
958             def __init__(self):
959                 self.outlist = []
960
961             def send(self, data):
962                 self.outlist.append(data)
963
964         handler = xmlstream.XMPPHandler()
965         handler.parent = DummyStreamManager()
966         handler.send('<presence/>')
967         self.assertEqual(['<presence/>'], handler.parent.outlist)
968
969
970     def test_makeConnection(self):
971         """
972         Test that makeConnection saves the XML stream and calls connectionMade.
973         """
974         class TestXMPPHandler(xmlstream.XMPPHandler):
975             def connectionMade(self):
976                 self.doneMade = True
977
978         handler = TestXMPPHandler()
979         xs = xmlstream.XmlStream(xmlstream.Authenticator())
980         handler.makeConnection(xs)
981         self.assertTrue(handler.doneMade)
982         self.assertIdentical(xs, handler.xmlstream)
983
984
985     def test_connectionLost(self):
986         """
987         Test that connectionLost forgets the XML stream.
988         """
989         handler = xmlstream.XMPPHandler()
990         xs = xmlstream.XmlStream(xmlstream.Authenticator())
991         handler.makeConnection(xs)
992         handler.connectionLost(Exception())
993         self.assertIdentical(None, handler.xmlstream)
994
995
996
997 class XMPPHandlerCollectionTest(unittest.TestCase):
998     """
999     Tests for L{xmlstream.XMPPHandlerCollection}.
1000     """
1001
1002     def setUp(self):
1003         self.collection = xmlstream.XMPPHandlerCollection()
1004
1005
1006     def test_interface(self):
1007         """
1008         L{xmlstream.StreamManager} implements L{ijabber.IXMPPHandlerCollection}.
1009         """
1010         verifyObject(ijabber.IXMPPHandlerCollection, self.collection)
1011
1012
1013     def test_addHandler(self):
1014         """
1015         Test the addition of a protocol handler.
1016         """
1017         handler = DummyXMPPHandler()
1018         handler.setHandlerParent(self.collection)
1019         self.assertIn(handler, self.collection)
1020         self.assertIdentical(self.collection, handler.parent)
1021
1022
1023     def test_removeHandler(self):
1024         """
1025         Test removal of a protocol handler.
1026         """
1027         handler = DummyXMPPHandler()
1028         handler.setHandlerParent(self.collection)
1029         handler.disownHandlerParent(self.collection)
1030         self.assertNotIn(handler, self.collection)
1031         self.assertIdentical(None, handler.parent)
1032
1033
1034
1035 class StreamManagerTest(unittest.TestCase):
1036     """
1037     Tests for L{xmlstream.StreamManager}.
1038     """
1039
1040     def setUp(self):
1041         factory = DummyFactory()
1042         self.streamManager = xmlstream.StreamManager(factory)
1043
1044
1045     def test_basic(self):
1046         """
1047         Test correct initialization and setup of factory observers.
1048         """
1049         sm = self.streamManager
1050         self.assertIdentical(None, sm.xmlstream)
1051         self.assertEqual([], sm.handlers)
1052         self.assertEqual(sm._connected,
1053                           sm.factory.callbacks['//event/stream/connected'])
1054         self.assertEqual(sm._authd,
1055                           sm.factory.callbacks['//event/stream/authd'])
1056         self.assertEqual(sm._disconnected,
1057                           sm.factory.callbacks['//event/stream/end'])
1058         self.assertEqual(sm.initializationFailed,
1059                           sm.factory.callbacks['//event/xmpp/initfailed'])
1060
1061
1062     def test_connected(self):
1063         """
1064         Test that protocol handlers have their connectionMade method called
1065         when the XML stream is connected.
1066         """
1067         sm = self.streamManager
1068         handler = DummyXMPPHandler()
1069         handler.setHandlerParent(sm)
1070         xs = xmlstream.XmlStream(xmlstream.Authenticator())
1071         sm._connected(xs)
1072         self.assertEqual(1, handler.doneMade)
1073         self.assertEqual(0, handler.doneInitialized)
1074         self.assertEqual(0, handler.doneLost)
1075
1076
1077     def test_connectedLogTrafficFalse(self):
1078         """
1079         Test raw data functions unset when logTraffic is set to False.
1080         """
1081         sm = self.streamManager
1082         handler = DummyXMPPHandler()
1083         handler.setHandlerParent(sm)
1084         xs = xmlstream.XmlStream(xmlstream.Authenticator())
1085         sm._connected(xs)
1086         self.assertIdentical(None, xs.rawDataInFn)
1087         self.assertIdentical(None, xs.rawDataOutFn)
1088
1089
1090     def test_connectedLogTrafficTrue(self):
1091         """
1092         Test raw data functions set when logTraffic is set to True.
1093         """
1094         sm = self.streamManager
1095         sm.logTraffic = True
1096         handler = DummyXMPPHandler()
1097         handler.setHandlerParent(sm)
1098         xs = xmlstream.XmlStream(xmlstream.Authenticator())
1099         sm._connected(xs)
1100         self.assertNotIdentical(None, xs.rawDataInFn)
1101         self.assertNotIdentical(None, xs.rawDataOutFn)
1102
1103
1104     def test_authd(self):
1105         """
1106         Test that protocol handlers have their connectionInitialized method
1107         called when the XML stream is initialized.
1108         """
1109         sm = self.streamManager
1110         handler = DummyXMPPHandler()
1111         handler.setHandlerParent(sm)
1112         xs = xmlstream.XmlStream(xmlstream.Authenticator())
1113         sm._authd(xs)
1114         self.assertEqual(0, handler.doneMade)
1115         self.assertEqual(1, handler.doneInitialized)
1116         self.assertEqual(0, handler.doneLost)
1117
1118
1119     def test_disconnected(self):
1120         """
1121         Test that protocol handlers have their connectionLost method
1122         called when the XML stream is disconnected.
1123         """
1124         sm = self.streamManager
1125         handler = DummyXMPPHandler()
1126         handler.setHandlerParent(sm)
1127         xs = xmlstream.XmlStream(xmlstream.Authenticator())
1128         sm._disconnected(xs)
1129         self.assertEqual(0, handler.doneMade)
1130         self.assertEqual(0, handler.doneInitialized)
1131         self.assertEqual(1, handler.doneLost)
1132
1133
1134     def test_disconnectedReason(self):
1135         """
1136         A L{STREAM_END_EVENT} results in L{StreamManager} firing the handlers
1137         L{connectionLost} methods, passing a L{failure.Failure} reason.
1138         """
1139         sm = self.streamManager
1140         handler = FailureReasonXMPPHandler()
1141         handler.setHandlerParent(sm)
1142         xs = xmlstream.XmlStream(xmlstream.Authenticator())
1143         sm._disconnected(failure.Failure(Exception("no reason")))
1144         self.assertEqual(True, handler.gotFailureReason)
1145
1146
1147     def test_addHandler(self):
1148         """
1149         Test the addition of a protocol handler while not connected.
1150         """
1151         sm = self.streamManager
1152         handler = DummyXMPPHandler()
1153         handler.setHandlerParent(sm)
1154
1155         self.assertEqual(0, handler.doneMade)
1156         self.assertEqual(0, handler.doneInitialized)
1157         self.assertEqual(0, handler.doneLost)
1158
1159
1160     def test_addHandlerInitialized(self):
1161         """
1162         Test the addition of a protocol handler after the stream
1163         have been initialized.
1164
1165         Make sure that the handler will have the connected stream
1166         passed via C{makeConnection} and have C{connectionInitialized}
1167         called.
1168         """
1169         sm = self.streamManager
1170         xs = xmlstream.XmlStream(xmlstream.Authenticator())
1171         sm._connected(xs)
1172         sm._authd(xs)
1173         handler = DummyXMPPHandler()
1174         handler.setHandlerParent(sm)
1175
1176         self.assertEqual(1, handler.doneMade)
1177         self.assertEqual(1, handler.doneInitialized)
1178         self.assertEqual(0, handler.doneLost)
1179
1180
1181     def test_sendInitialized(self):
1182         """
1183         Test send when the stream has been initialized.
1184
1185         The data should be sent directly over the XML stream.
1186         """
1187         factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
1188         sm = xmlstream.StreamManager(factory)
1189         xs = factory.buildProtocol(None)
1190         xs.transport = proto_helpers.StringTransport()
1191         xs.connectionMade()
1192         xs.dataReceived("<stream:stream xmlns='jabber:client' "
1193                         "xmlns:stream='http://etherx.jabber.org/streams' "
1194                         "from='example.com' id='12345'>")
1195         xs.dispatch(xs, "//event/stream/authd")
1196         sm.send("<presence/>")
1197         self.assertEqual("<presence/>", xs.transport.value())
1198
1199
1200     def test_sendNotConnected(self):
1201         """
1202         Test send when there is no established XML stream.
1203
1204         The data should be cached until an XML stream has been established and
1205         initialized.
1206         """
1207         factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
1208         sm = xmlstream.StreamManager(factory)
1209         handler = DummyXMPPHandler()
1210         sm.addHandler(handler)
1211
1212         xs = factory.buildProtocol(None)
1213         xs.transport = proto_helpers.StringTransport()
1214         sm.send("<presence/>")
1215         self.assertEqual("", xs.transport.value())
1216         self.assertEqual("<presence/>", sm._packetQueue[0])
1217
1218         xs.connectionMade()
1219         self.assertEqual("", xs.transport.value())
1220         self.assertEqual("<presence/>", sm._packetQueue[0])
1221
1222         xs.dataReceived("<stream:stream xmlns='jabber:client' "
1223                         "xmlns:stream='http://etherx.jabber.org/streams' "
1224                         "from='example.com' id='12345'>")
1225         xs.dispatch(xs, "//event/stream/authd")
1226
1227         self.assertEqual("<presence/>", xs.transport.value())
1228         self.assertFalse(sm._packetQueue)
1229
1230
1231     def test_sendNotInitialized(self):
1232         """
1233         Test send when the stream is connected but not yet initialized.
1234
1235         The data should be cached until the XML stream has been initialized.
1236         """
1237         factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
1238         sm = xmlstream.StreamManager(factory)
1239         xs = factory.buildProtocol(None)
1240         xs.transport = proto_helpers.StringTransport()
1241         xs.connectionMade()
1242         xs.dataReceived("<stream:stream xmlns='jabber:client' "
1243                         "xmlns:stream='http://etherx.jabber.org/streams' "
1244                         "from='example.com' id='12345'>")
1245         sm.send("<presence/>")
1246         self.assertEqual("", xs.transport.value())
1247         self.assertEqual("<presence/>", sm._packetQueue[0])
1248
1249
1250     def test_sendDisconnected(self):
1251         """
1252         Test send after XML stream disconnection.
1253
1254         The data should be cached until a new XML stream has been established
1255         and initialized.
1256         """
1257         factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator())
1258         sm = xmlstream.StreamManager(factory)
1259         handler = DummyXMPPHandler()
1260         sm.addHandler(handler)
1261
1262         xs = factory.buildProtocol(None)
1263         xs.connectionMade()
1264         xs.transport = proto_helpers.StringTransport()
1265         xs.connectionLost(None)
1266
1267         sm.send("<presence/>")
1268         self.assertEqual("", xs.transport.value())
1269         self.assertEqual("<presence/>", sm._packetQueue[0])
1270
1271
1272
1273 class XmlStreamServerFactoryTest(GenericXmlStreamFactoryTestsMixin):
1274     """
1275     Tests for L{xmlstream.XmlStreamServerFactory}.
1276     """
1277
1278     def setUp(self):
1279         """
1280         Set up a server factory with a authenticator factory function.
1281         """
1282         class TestAuthenticator(object):
1283             def __init__(self):
1284                 self.xmlstreams = []
1285
1286             def associateWithStream(self, xs):
1287                 self.xmlstreams.append(xs)
1288
1289         def authenticatorFactory():
1290             return TestAuthenticator()
1291
1292         self.factory = xmlstream.XmlStreamServerFactory(authenticatorFactory)
1293
1294
1295     def test_interface(self):
1296         """
1297         L{XmlStreamServerFactory} is a L{Factory}.
1298         """
1299         verifyObject(IProtocolFactory, self.factory)
1300
1301
1302     def test_buildProtocolAuthenticatorInstantiation(self):
1303         """
1304         The authenticator factory should be used to instantiate the
1305         authenticator and pass it to the protocol.
1306
1307         The default protocol, L{XmlStream} stores the authenticator it is
1308         passed, and calls its C{associateWithStream} method. so we use that to
1309         check whether our authenticator factory is used and the protocol
1310         instance gets an authenticator.
1311         """
1312         xs = self.factory.buildProtocol(None)
1313         self.assertEqual([xs], xs.authenticator.xmlstreams)
1314
1315
1316     def test_buildProtocolXmlStream(self):
1317         """
1318         The protocol factory creates Jabber XML Stream protocols by default.
1319         """
1320         xs = self.factory.buildProtocol(None)
1321         self.assertIsInstance(xs, xmlstream.XmlStream)
1322
1323
1324     def test_buildProtocolTwice(self):
1325         """
1326         Subsequent calls to buildProtocol should result in different instances
1327         of the protocol, as well as their authenticators.
1328         """
1329         xs1 = self.factory.buildProtocol(None)
1330         xs2 = self.factory.buildProtocol(None)
1331         self.assertNotIdentical(xs1, xs2)
1332         self.assertNotIdentical(xs1.authenticator, xs2.authenticator)