test_jabberxmlstream.py 42 KB

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