1
# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
Tests for L{twisted.words.protocols.jabber.error}.
8
from twisted.trial import unittest
10
from twisted.words.protocols.jabber import error
11
from twisted.words.xish import domish
13
NS_XML = 'http://www.w3.org/XML/1998/namespace'
14
NS_STREAMS = 'http://etherx.jabber.org/streams'
15
NS_XMPP_STREAMS = 'urn:ietf:params:xml:ns:xmpp-streams'
16
NS_XMPP_STANZAS = 'urn:ietf:params:xml:ns:xmpp-stanzas'
18
class BaseErrorTest(unittest.TestCase):
20
def test_getElementPlain(self):
22
Test getting an element for a plain error.
24
e = error.BaseError('feature-not-implemented')
25
element = e.getElement()
26
self.assertIdentical(element.uri, None)
27
self.assertEquals(len(element.children), 1)
29
def test_getElementText(self):
31
Test getting an element for an error with a text.
33
e = error.BaseError('feature-not-implemented', 'text')
34
element = e.getElement()
35
self.assertEquals(len(element.children), 2)
36
self.assertEquals(unicode(element.text), 'text')
37
self.assertEquals(element.text.getAttribute((NS_XML, 'lang')), None)
39
def test_getElementTextLang(self):
41
Test getting an element for an error with a text and language.
43
e = error.BaseError('feature-not-implemented', 'text', 'en_US')
44
element = e.getElement()
45
self.assertEquals(len(element.children), 2)
46
self.assertEquals(unicode(element.text), 'text')
47
self.assertEquals(element.text[(NS_XML, 'lang')], 'en_US')
49
def test_getElementAppCondition(self):
51
Test getting an element for an error with an app specific condition.
53
ac = domish.Element(('testns', 'myerror'))
54
e = error.BaseError('feature-not-implemented', appCondition=ac)
55
element = e.getElement()
56
self.assertEquals(len(element.children), 2)
57
self.assertEquals(element.myerror, ac)
59
class StreamErrorTest(unittest.TestCase):
61
def test_getElementPlain(self):
63
Test namespace of the element representation of an error.
65
e = error.StreamError('feature-not-implemented')
66
element = e.getElement()
67
self.assertEquals(element.uri, NS_STREAMS)
69
def test_getElementConditionNamespace(self):
71
Test that the error condition element has the correct namespace.
73
e = error.StreamError('feature-not-implemented')
74
element = e.getElement()
75
self.assertEquals(NS_XMPP_STREAMS, getattr(element, 'feature-not-implemented').uri)
77
def test_getElementTextNamespace(self):
79
Test that the error text element has the correct namespace.
81
e = error.StreamError('feature-not-implemented', 'text')
82
element = e.getElement()
83
self.assertEquals(NS_XMPP_STREAMS, element.text.uri)
85
class StanzaErrorTest(unittest.TestCase):
87
def test_getElementPlain(self):
89
Test getting an element for a plain stanza error.
91
e = error.StanzaError('feature-not-implemented')
92
element = e.getElement()
93
self.assertEquals(element.uri, None)
94
self.assertEquals(element['type'], 'cancel')
95
self.assertEquals(element['code'], '501')
97
def test_getElementType(self):
99
Test getting an element for a stanza error with a given type.
101
e = error.StanzaError('feature-not-implemented', 'auth')
102
element = e.getElement()
103
self.assertEquals(element.uri, None)
104
self.assertEquals(element['type'], 'auth')
105
self.assertEquals(element['code'], '501')
107
def test_getElementConditionNamespace(self):
109
Test that the error condition element has the correct namespace.
111
e = error.StanzaError('feature-not-implemented')
112
element = e.getElement()
113
self.assertEquals(NS_XMPP_STANZAS, getattr(element, 'feature-not-implemented').uri)
115
def test_getElementTextNamespace(self):
117
Test that the error text element has the correct namespace.
119
e = error.StanzaError('feature-not-implemented', text='text')
120
element = e.getElement()
121
self.assertEquals(NS_XMPP_STANZAS, element.text.uri)
123
def test_toResponse(self):
125
Test an error response is generated from a stanza.
127
The addressing on the (new) response stanza should be reversed, an
128
error child (with proper properties) added and the type set to
131
stanza = domish.Element(('jabber:client', 'message'))
132
stanza['type'] = 'chat'
133
stanza['to'] = 'user1@example.com'
134
stanza['from'] = 'user2@example.com/resource'
135
e = error.StanzaError('service-unavailable')
136
response = e.toResponse(stanza)
137
self.assertNotIdentical(response, stanza)
138
self.assertEqual(response['from'], 'user1@example.com')
139
self.assertEqual(response['to'], 'user2@example.com/resource')
140
self.assertEqual(response['type'], 'error')
141
self.assertEqual(response.error.children[0].name,
142
'service-unavailable')
143
self.assertEqual(response.error['type'], 'cancel')
144
self.assertNotEqual(stanza.children, response.children)
146
class ParseErrorTest(unittest.TestCase):
149
self.error = domish.Element((None, 'error'))
151
def test_empty(self):
153
Test parsing of the empty error element.
155
result = error._parseError(self.error, 'errorns')
156
self.assertEqual({'condition': None,
159
'appCondition': None}, result)
161
def test_condition(self):
163
Test parsing of an error element with a condition.
165
self.error.addElement(('errorns', 'bad-request'))
166
result = error._parseError(self.error, 'errorns')
167
self.assertEqual('bad-request', result['condition'])
171
Test parsing of an error element with a text.
173
text = self.error.addElement(('errorns', 'text'))
174
text.addContent('test')
175
result = error._parseError(self.error, 'errorns')
176
self.assertEqual('test', result['text'])
177
self.assertEqual(None, result['textLang'])
179
def test_textLang(self):
181
Test parsing of an error element with a text with a defined language.
183
text = self.error.addElement(('errorns', 'text'))
184
text[NS_XML, 'lang'] = 'en_US'
185
text.addContent('test')
186
result = error._parseError(self.error, 'errorns')
187
self.assertEqual('en_US', result['textLang'])
189
def test_textLangInherited(self):
191
Test parsing of an error element with a text with inherited language.
193
text = self.error.addElement(('errorns', 'text'))
194
self.error[NS_XML, 'lang'] = 'en_US'
195
text.addContent('test')
196
result = error._parseError(self.error, 'errorns')
197
self.assertEqual('en_US', result['textLang'])
198
test_textLangInherited.todo = "xml:lang inheritance not implemented"
200
def test_appCondition(self):
202
Test parsing of an error element with an app specific condition.
204
condition = self.error.addElement(('testns', 'condition'))
205
result = error._parseError(self.error, 'errorns')
206
self.assertEqual(condition, result['appCondition'])
208
def test_appConditionMultiple(self):
210
Test parsing of an error element with multiple app specific conditions.
212
condition = self.error.addElement(('testns', 'condition'))
213
condition2 = self.error.addElement(('testns', 'condition2'))
214
result = error._parseError(self.error, 'errorns')
215
self.assertEqual(condition2, result['appCondition'])
217
class ExceptionFromStanzaTest(unittest.TestCase):
219
def test_basic(self):
221
Test basic operations of exceptionFromStanza.
223
Given a realistic stanza, check if a sane exception is returned.
228
from='pubsub.shakespeare.lit'
229
to='francisco@denmark.lit/barracks'
231
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
234
<error type='cancel'>
235
<feature-not-implemented
236
xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
237
<unsupported xmlns='http://jabber.org/protocol/pubsub#errors'
238
feature='retrieve-subscriptions'/>
243
stanza = domish.Element((None, 'stanza'))
244
p = stanza.addElement(('http://jabber.org/protocol/pubsub', 'pubsub'))
245
p.addElement('subscriptions')
246
e = stanza.addElement('error')
248
e.addElement((NS_XMPP_STANZAS, 'feature-not-implemented'))
249
uc = e.addElement(('http://jabber.org/protocol/pubsub#errors',
251
uc['feature'] = 'retrieve-subscriptions'
253
result = error.exceptionFromStanza(stanza)
254
self.assert_(isinstance(result, error.StanzaError))
255
self.assertEquals('feature-not-implemented', result.condition)
256
self.assertEquals('cancel', result.type)
257
self.assertEquals(uc, result.appCondition)
258
self.assertEquals([p], result.children)
260
def test_legacy(self):
262
Test legacy operations of exceptionFromStanza.
264
Given a realistic stanza with only legacy (pre-XMPP) error information,
265
check if a sane exception is returned.
269
<message type='error'
270
to='piers@pipetree.com/Home'
271
from='qmacro@jaber.org'>
272
<body>Are you there?</body>
273
<error code='502'>Unable to resolve hostname.</error>
276
stanza = domish.Element((None, 'stanza'))
277
p = stanza.addElement('body', content='Are you there?')
278
e = stanza.addElement('error', content='Unable to resolve hostname.')
281
result = error.exceptionFromStanza(stanza)
282
self.assert_(isinstance(result, error.StanzaError))
283
self.assertEquals('service-unavailable', result.condition)
284
self.assertEquals('wait', result.type)
285
self.assertEquals('Unable to resolve hostname.', result.text)
286
self.assertEquals([p], result.children)
288
class ExceptionFromStreamErrorTest(unittest.TestCase):
290
def test_basic(self):
292
Test basic operations of exceptionFromStreamError.
294
Given a realistic stream error, check if a sane exception is returned.
298
<stream:error xmlns:stream='http://etherx.jabber.org/streams'>
299
<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
303
e = domish.Element(('http://etherx.jabber.org/streams', 'error'))
304
e.addElement((NS_XMPP_STREAMS, 'xml-not-well-formed'))
306
result = error.exceptionFromStreamError(e)
307
self.assert_(isinstance(result, error.StreamError))
308
self.assertEquals('xml-not-well-formed', result.condition)