Mercurial > sat_tmp
comparison wokkel/test/test_pubsub.py @ 10:2cd4f0ab9ad1
add tests for sat.tmp.wokkel
author | souliane <souliane@mailoo.org> |
---|---|
date | Tue, 14 Jul 2015 15:22:02 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9:9a4c367b22bb | 10:2cd4f0ab9ad1 |
---|---|
1 # Copyright (c) Ralph Meijer. | |
2 # See LICENSE for details. | |
3 | |
4 """ | |
5 Tests for L{wokkel.pubsub} | |
6 """ | |
7 | |
8 from zope.interface import verify | |
9 | |
10 from twisted.trial import unittest | |
11 from twisted.internet import defer | |
12 from twisted.words.xish import domish | |
13 from twisted.words.protocols.jabber import error | |
14 from twisted.words.protocols.jabber.jid import JID | |
15 from twisted.words.protocols.jabber.xmlstream import toResponse | |
16 | |
17 from wokkel import data_form, disco, iwokkel, shim | |
18 from wokkel.generic import parseXml | |
19 from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub | |
20 | |
21 from sat.tmp.wokkel import pubsub | |
22 | |
23 NS_PUBSUB = 'http://jabber.org/protocol/pubsub' | |
24 NS_PUBSUB_NODE_CONFIG = 'http://jabber.org/protocol/pubsub#node_config' | |
25 NS_PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors' | |
26 NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event' | |
27 NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner' | |
28 NS_PUBSUB_META_DATA = 'http://jabber.org/protocol/pubsub#meta-data' | |
29 NS_PUBSUB_SUBSCRIBE_OPTIONS = 'http://jabber.org/protocol/pubsub#subscribe_options' | |
30 | |
31 def calledAsync(fn): | |
32 """ | |
33 Function wrapper that fires a deferred upon calling the given function. | |
34 """ | |
35 d = defer.Deferred() | |
36 | |
37 def func(*args, **kwargs): | |
38 try: | |
39 result = fn(*args, **kwargs) | |
40 except: | |
41 d.errback() | |
42 else: | |
43 d.callback(result) | |
44 | |
45 return d, func | |
46 | |
47 | |
48 class SubscriptionTest(unittest.TestCase): | |
49 """ | |
50 Tests for L{pubsub.Subscription}. | |
51 """ | |
52 | |
53 def test_fromElement(self): | |
54 """ | |
55 fromElement parses a subscription from XML DOM. | |
56 """ | |
57 xml = """ | |
58 <subscription node='test' jid='user@example.org/Home' | |
59 subscription='pending'/> | |
60 """ | |
61 subscription = pubsub.Subscription.fromElement(parseXml(xml)) | |
62 self.assertEqual('test', subscription.nodeIdentifier) | |
63 self.assertEqual(JID('user@example.org/Home'), subscription.subscriber) | |
64 self.assertEqual('pending', subscription.state) | |
65 self.assertIdentical(None, subscription.subscriptionIdentifier) | |
66 | |
67 | |
68 def test_fromElementWithSubscriptionIdentifier(self): | |
69 """ | |
70 A subscription identifier in the subscription should be parsed, too. | |
71 """ | |
72 xml = """ | |
73 <subscription node='test' jid='user@example.org/Home' subid='1234' | |
74 subscription='pending'/> | |
75 """ | |
76 subscription = pubsub.Subscription.fromElement(parseXml(xml)) | |
77 self.assertEqual('1234', subscription.subscriptionIdentifier) | |
78 | |
79 | |
80 def test_toElement(self): | |
81 """ | |
82 Rendering a Subscription should yield the proper attributes. | |
83 """ | |
84 subscription = pubsub.Subscription('test', | |
85 JID('user@example.org/Home'), | |
86 'pending') | |
87 element = subscription.toElement() | |
88 self.assertEqual('subscription', element.name) | |
89 self.assertEqual(None, element.uri) | |
90 self.assertEqual('test', element.getAttribute('node')) | |
91 self.assertEqual('user@example.org/Home', element.getAttribute('jid')) | |
92 self.assertEqual('pending', element.getAttribute('subscription')) | |
93 self.assertFalse(element.hasAttribute('subid')) | |
94 | |
95 | |
96 def test_toElementEmptyNodeIdentifier(self): | |
97 """ | |
98 The empty node identifier should not yield a node attribute. | |
99 """ | |
100 subscription = pubsub.Subscription('', | |
101 JID('user@example.org/Home'), | |
102 'pending') | |
103 element = subscription.toElement() | |
104 self.assertFalse(element.hasAttribute('node')) | |
105 | |
106 | |
107 def test_toElementWithSubscriptionIdentifier(self): | |
108 """ | |
109 The subscription identifier, if set, is in the subid attribute. | |
110 """ | |
111 subscription = pubsub.Subscription('test', | |
112 JID('user@example.org/Home'), | |
113 'pending', | |
114 subscriptionIdentifier='1234') | |
115 element = subscription.toElement() | |
116 self.assertEqual('1234', element.getAttribute('subid')) | |
117 | |
118 | |
119 | |
120 class PubSubClientTest(unittest.TestCase): | |
121 timeout = 2 | |
122 | |
123 def setUp(self): | |
124 self.stub = XmlStreamStub() | |
125 self.protocol = pubsub.PubSubClient() | |
126 self.protocol.xmlstream = self.stub.xmlstream | |
127 self.protocol.connectionInitialized() | |
128 | |
129 | |
130 def test_interface(self): | |
131 """ | |
132 Do instances of L{pubsub.PubSubClient} provide L{iwokkel.IPubSubClient}? | |
133 """ | |
134 verify.verifyObject(iwokkel.IPubSubClient, self.protocol) | |
135 | |
136 | |
137 def test_eventItems(self): | |
138 """ | |
139 Test receiving an items event resulting in a call to itemsReceived. | |
140 """ | |
141 message = domish.Element((None, 'message')) | |
142 message['from'] = 'pubsub.example.org' | |
143 message['to'] = 'user@example.org/home' | |
144 event = message.addElement((NS_PUBSUB_EVENT, 'event')) | |
145 items = event.addElement('items') | |
146 items['node'] = 'test' | |
147 item1 = items.addElement('item') | |
148 item1['id'] = 'item1' | |
149 item2 = items.addElement('retract') | |
150 item2['id'] = 'item2' | |
151 item3 = items.addElement('item') | |
152 item3['id'] = 'item3' | |
153 | |
154 def itemsReceived(event): | |
155 self.assertEquals(JID('user@example.org/home'), event.recipient) | |
156 self.assertEquals(JID('pubsub.example.org'), event.sender) | |
157 self.assertEquals('test', event.nodeIdentifier) | |
158 self.assertEquals([item1, item2, item3], event.items) | |
159 | |
160 d, self.protocol.itemsReceived = calledAsync(itemsReceived) | |
161 self.stub.send(message) | |
162 return d | |
163 | |
164 | |
165 def test_eventItemsCollection(self): | |
166 """ | |
167 Test receiving an items event resulting in a call to itemsReceived. | |
168 """ | |
169 message = domish.Element((None, 'message')) | |
170 message['from'] = 'pubsub.example.org' | |
171 message['to'] = 'user@example.org/home' | |
172 event = message.addElement((NS_PUBSUB_EVENT, 'event')) | |
173 items = event.addElement('items') | |
174 items['node'] = 'test' | |
175 | |
176 headers = shim.Headers([('Collection', 'collection')]) | |
177 message.addChild(headers) | |
178 | |
179 def itemsReceived(event): | |
180 self.assertEquals(JID('user@example.org/home'), event.recipient) | |
181 self.assertEquals(JID('pubsub.example.org'), event.sender) | |
182 self.assertEquals('test', event.nodeIdentifier) | |
183 self.assertEquals({'Collection': ['collection']}, event.headers) | |
184 | |
185 d, self.protocol.itemsReceived = calledAsync(itemsReceived) | |
186 self.stub.send(message) | |
187 return d | |
188 | |
189 | |
190 def test_eventItemsError(self): | |
191 """ | |
192 An error message with embedded event should not be handled. | |
193 | |
194 This test uses an items event, which should not result in itemsReceived | |
195 being called. In general message.handled should be False. | |
196 """ | |
197 message = domish.Element((None, 'message')) | |
198 message['from'] = 'pubsub.example.org' | |
199 message['to'] = 'user@example.org/home' | |
200 message['type'] = 'error' | |
201 event = message.addElement((NS_PUBSUB_EVENT, 'event')) | |
202 items = event.addElement('items') | |
203 items['node'] = 'test' | |
204 | |
205 class UnexpectedCall(Exception): | |
206 pass | |
207 | |
208 def itemsReceived(event): | |
209 raise UnexpectedCall("Unexpected call to itemsReceived") | |
210 | |
211 self.protocol.itemsReceived = itemsReceived | |
212 self.stub.send(message) | |
213 self.assertFalse(message.handled) | |
214 | |
215 | |
216 def test_eventDelete(self): | |
217 """ | |
218 Test receiving a delete event resulting in a call to deleteReceived. | |
219 """ | |
220 message = domish.Element((None, 'message')) | |
221 message['from'] = 'pubsub.example.org' | |
222 message['to'] = 'user@example.org/home' | |
223 event = message.addElement((NS_PUBSUB_EVENT, 'event')) | |
224 delete = event.addElement('delete') | |
225 delete['node'] = 'test' | |
226 | |
227 def deleteReceived(event): | |
228 self.assertEquals(JID('user@example.org/home'), event.recipient) | |
229 self.assertEquals(JID('pubsub.example.org'), event.sender) | |
230 self.assertEquals('test', event.nodeIdentifier) | |
231 | |
232 d, self.protocol.deleteReceived = calledAsync(deleteReceived) | |
233 self.stub.send(message) | |
234 return d | |
235 | |
236 | |
237 def test_eventDeleteRedirect(self): | |
238 """ | |
239 Test receiving a delete event with a redirect URI. | |
240 """ | |
241 message = domish.Element((None, 'message')) | |
242 message['from'] = 'pubsub.example.org' | |
243 message['to'] = 'user@example.org/home' | |
244 event = message.addElement((NS_PUBSUB_EVENT, 'event')) | |
245 delete = event.addElement('delete') | |
246 delete['node'] = 'test' | |
247 uri = 'xmpp:pubsub.example.org?;node=test2' | |
248 delete.addElement('redirect')['uri'] = uri | |
249 | |
250 def deleteReceived(event): | |
251 self.assertEquals(JID('user@example.org/home'), event.recipient) | |
252 self.assertEquals(JID('pubsub.example.org'), event.sender) | |
253 self.assertEquals('test', event.nodeIdentifier) | |
254 self.assertEquals(uri, event.redirectURI) | |
255 | |
256 d, self.protocol.deleteReceived = calledAsync(deleteReceived) | |
257 self.stub.send(message) | |
258 return d | |
259 | |
260 | |
261 def test_event_purge(self): | |
262 """ | |
263 Test receiving a purge event resulting in a call to purgeReceived. | |
264 """ | |
265 message = domish.Element((None, 'message')) | |
266 message['from'] = 'pubsub.example.org' | |
267 message['to'] = 'user@example.org/home' | |
268 event = message.addElement((NS_PUBSUB_EVENT, 'event')) | |
269 items = event.addElement('purge') | |
270 items['node'] = 'test' | |
271 | |
272 def purgeReceived(event): | |
273 self.assertEquals(JID('user@example.org/home'), event.recipient) | |
274 self.assertEquals(JID('pubsub.example.org'), event.sender) | |
275 self.assertEquals('test', event.nodeIdentifier) | |
276 | |
277 d, self.protocol.purgeReceived = calledAsync(purgeReceived) | |
278 self.stub.send(message) | |
279 return d | |
280 | |
281 | |
282 def test_createNode(self): | |
283 """ | |
284 Test sending create request. | |
285 """ | |
286 | |
287 def cb(nodeIdentifier): | |
288 self.assertEquals('test', nodeIdentifier) | |
289 | |
290 d = self.protocol.createNode(JID('pubsub.example.org'), 'test') | |
291 d.addCallback(cb) | |
292 | |
293 iq = self.stub.output[-1] | |
294 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
295 self.assertEquals('set', iq.getAttribute('type')) | |
296 self.assertEquals('pubsub', iq.pubsub.name) | |
297 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
298 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
299 'create', NS_PUBSUB)) | |
300 self.assertEquals(1, len(children)) | |
301 child = children[0] | |
302 self.assertEquals('test', child['node']) | |
303 | |
304 response = toResponse(iq, 'result') | |
305 self.stub.send(response) | |
306 return d | |
307 | |
308 | |
309 def test_createNodeInstant(self): | |
310 """ | |
311 Test sending create request resulting in an instant node. | |
312 """ | |
313 | |
314 def cb(nodeIdentifier): | |
315 self.assertEquals('test', nodeIdentifier) | |
316 | |
317 d = self.protocol.createNode(JID('pubsub.example.org')) | |
318 d.addCallback(cb) | |
319 | |
320 iq = self.stub.output[-1] | |
321 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
322 'create', NS_PUBSUB)) | |
323 child = children[0] | |
324 self.assertFalse(child.hasAttribute('node')) | |
325 | |
326 response = toResponse(iq, 'result') | |
327 command = response.addElement((NS_PUBSUB, 'pubsub')) | |
328 create = command.addElement('create') | |
329 create['node'] = 'test' | |
330 self.stub.send(response) | |
331 return d | |
332 | |
333 | |
334 def test_createNodeRenamed(self): | |
335 """ | |
336 Test sending create request resulting in renamed node. | |
337 """ | |
338 | |
339 def cb(nodeIdentifier): | |
340 self.assertEquals('test2', nodeIdentifier) | |
341 | |
342 d = self.protocol.createNode(JID('pubsub.example.org'), 'test') | |
343 d.addCallback(cb) | |
344 | |
345 iq = self.stub.output[-1] | |
346 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
347 'create', NS_PUBSUB)) | |
348 child = children[0] | |
349 self.assertEquals('test', child['node']) | |
350 | |
351 response = toResponse(iq, 'result') | |
352 command = response.addElement((NS_PUBSUB, 'pubsub')) | |
353 create = command.addElement('create') | |
354 create['node'] = 'test2' | |
355 self.stub.send(response) | |
356 return d | |
357 | |
358 | |
359 def test_createNodeWithSender(self): | |
360 """ | |
361 Test sending create request from a specific JID. | |
362 """ | |
363 | |
364 d = self.protocol.createNode(JID('pubsub.example.org'), 'test', | |
365 sender=JID('user@example.org')) | |
366 | |
367 iq = self.stub.output[-1] | |
368 self.assertEquals('user@example.org', iq['from']) | |
369 | |
370 response = toResponse(iq, 'result') | |
371 self.stub.send(response) | |
372 return d | |
373 | |
374 | |
375 def test_createNodeWithConfig(self): | |
376 """ | |
377 Test sending create request with configuration options | |
378 """ | |
379 | |
380 options = { | |
381 'pubsub#title': 'Princely Musings (Atom)', | |
382 'pubsub#deliver_payloads': True, | |
383 'pubsub#persist_items': '1', | |
384 'pubsub#max_items': '10', | |
385 'pubsub#access_model': 'open', | |
386 'pubsub#type': 'http://www.w3.org/2005/Atom', | |
387 } | |
388 | |
389 d = self.protocol.createNode(JID('pubsub.example.org'), 'test', | |
390 sender=JID('user@example.org'), | |
391 options=options) | |
392 | |
393 iq = self.stub.output[-1] | |
394 | |
395 # check if there is exactly one configure element | |
396 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
397 'configure', NS_PUBSUB)) | |
398 self.assertEqual(1, len(children)) | |
399 | |
400 # check that it has a configuration form | |
401 form = data_form.findForm(children[0], NS_PUBSUB_NODE_CONFIG) | |
402 self.assertEqual('submit', form.formType) | |
403 | |
404 | |
405 response = toResponse(iq, 'result') | |
406 self.stub.send(response) | |
407 return d | |
408 | |
409 | |
410 def test_deleteNode(self): | |
411 """ | |
412 Test sending delete request. | |
413 """ | |
414 | |
415 d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test') | |
416 | |
417 iq = self.stub.output[-1] | |
418 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
419 self.assertEquals('set', iq.getAttribute('type')) | |
420 self.assertEquals('pubsub', iq.pubsub.name) | |
421 self.assertEquals(NS_PUBSUB_OWNER, iq.pubsub.uri) | |
422 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
423 'delete', NS_PUBSUB_OWNER)) | |
424 self.assertEquals(1, len(children)) | |
425 child = children[0] | |
426 self.assertEquals('test', child['node']) | |
427 | |
428 response = toResponse(iq, 'result') | |
429 self.stub.send(response) | |
430 return d | |
431 | |
432 | |
433 def test_deleteNodeWithSender(self): | |
434 """ | |
435 Test sending delete request. | |
436 """ | |
437 | |
438 d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test', | |
439 sender=JID('user@example.org')) | |
440 | |
441 iq = self.stub.output[-1] | |
442 self.assertEquals('user@example.org', iq['from']) | |
443 | |
444 response = toResponse(iq, 'result') | |
445 self.stub.send(response) | |
446 return d | |
447 | |
448 | |
449 def test_publish(self): | |
450 """ | |
451 Test sending publish request. | |
452 """ | |
453 | |
454 item = pubsub.Item() | |
455 d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item]) | |
456 | |
457 iq = self.stub.output[-1] | |
458 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
459 self.assertEquals('set', iq.getAttribute('type')) | |
460 self.assertEquals('pubsub', iq.pubsub.name) | |
461 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
462 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
463 'publish', NS_PUBSUB)) | |
464 self.assertEquals(1, len(children)) | |
465 child = children[0] | |
466 self.assertEquals('test', child['node']) | |
467 items = list(domish.generateElementsQNamed(child.children, | |
468 'item', NS_PUBSUB)) | |
469 self.assertEquals(1, len(items)) | |
470 self.assertIdentical(item, items[0]) | |
471 | |
472 response = toResponse(iq, 'result') | |
473 self.stub.send(response) | |
474 return d | |
475 | |
476 | |
477 def test_publishNoItems(self): | |
478 """ | |
479 Test sending publish request without items. | |
480 """ | |
481 | |
482 d = self.protocol.publish(JID('pubsub.example.org'), 'test') | |
483 | |
484 iq = self.stub.output[-1] | |
485 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
486 self.assertEquals('set', iq.getAttribute('type')) | |
487 self.assertEquals('pubsub', iq.pubsub.name) | |
488 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
489 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
490 'publish', NS_PUBSUB)) | |
491 self.assertEquals(1, len(children)) | |
492 child = children[0] | |
493 self.assertEquals('test', child['node']) | |
494 | |
495 response = toResponse(iq, 'result') | |
496 self.stub.send(response) | |
497 return d | |
498 | |
499 | |
500 def test_publishWithSender(self): | |
501 """ | |
502 Test sending publish request from a specific JID. | |
503 """ | |
504 | |
505 item = pubsub.Item() | |
506 d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item], | |
507 JID('user@example.org')) | |
508 | |
509 iq = self.stub.output[-1] | |
510 self.assertEquals('user@example.org', iq['from']) | |
511 | |
512 response = toResponse(iq, 'result') | |
513 self.stub.send(response) | |
514 return d | |
515 | |
516 | |
517 def test_subscribe(self): | |
518 """ | |
519 Test sending subscription request. | |
520 """ | |
521 d = self.protocol.subscribe(JID('pubsub.example.org'), 'test', | |
522 JID('user@example.org')) | |
523 | |
524 iq = self.stub.output[-1] | |
525 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
526 self.assertEquals('set', iq.getAttribute('type')) | |
527 self.assertEquals('pubsub', iq.pubsub.name) | |
528 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
529 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
530 'subscribe', NS_PUBSUB)) | |
531 self.assertEquals(1, len(children)) | |
532 child = children[0] | |
533 self.assertEquals('test', child['node']) | |
534 self.assertEquals('user@example.org', child['jid']) | |
535 | |
536 response = toResponse(iq, 'result') | |
537 pubsub = response.addElement((NS_PUBSUB, 'pubsub')) | |
538 subscription = pubsub.addElement('subscription') | |
539 subscription['node'] = 'test' | |
540 subscription['jid'] = 'user@example.org' | |
541 subscription['subscription'] = 'subscribed' | |
542 self.stub.send(response) | |
543 return d | |
544 | |
545 | |
546 def test_subscribeReturnsSubscription(self): | |
547 """ | |
548 A successful subscription should return a Subscription instance. | |
549 """ | |
550 def cb(subscription): | |
551 self.assertEqual(JID('user@example.org'), subscription.subscriber) | |
552 | |
553 d = self.protocol.subscribe(JID('pubsub.example.org'), 'test', | |
554 JID('user@example.org')) | |
555 d.addCallback(cb) | |
556 | |
557 iq = self.stub.output[-1] | |
558 | |
559 response = toResponse(iq, 'result') | |
560 pubsub = response.addElement((NS_PUBSUB, 'pubsub')) | |
561 subscription = pubsub.addElement('subscription') | |
562 subscription['node'] = 'test' | |
563 subscription['jid'] = 'user@example.org' | |
564 subscription['subscription'] = 'subscribed' | |
565 self.stub.send(response) | |
566 return d | |
567 | |
568 | |
569 def test_subscribePending(self): | |
570 """ | |
571 Test sending subscription request that results in a pending | |
572 subscription. | |
573 """ | |
574 d = self.protocol.subscribe(JID('pubsub.example.org'), 'test', | |
575 JID('user@example.org')) | |
576 | |
577 iq = self.stub.output[-1] | |
578 response = toResponse(iq, 'result') | |
579 command = response.addElement((NS_PUBSUB, 'pubsub')) | |
580 subscription = command.addElement('subscription') | |
581 subscription['node'] = 'test' | |
582 subscription['jid'] = 'user@example.org' | |
583 subscription['subscription'] = 'pending' | |
584 self.stub.send(response) | |
585 self.assertFailure(d, pubsub.SubscriptionPending) | |
586 return d | |
587 | |
588 | |
589 def test_subscribeUnconfigured(self): | |
590 """ | |
591 Test sending subscription request that results in an unconfigured | |
592 subscription. | |
593 """ | |
594 d = self.protocol.subscribe(JID('pubsub.example.org'), 'test', | |
595 JID('user@example.org')) | |
596 | |
597 iq = self.stub.output[-1] | |
598 response = toResponse(iq, 'result') | |
599 command = response.addElement((NS_PUBSUB, 'pubsub')) | |
600 subscription = command.addElement('subscription') | |
601 subscription['node'] = 'test' | |
602 subscription['jid'] = 'user@example.org' | |
603 subscription['subscription'] = 'unconfigured' | |
604 self.stub.send(response) | |
605 self.assertFailure(d, pubsub.SubscriptionUnconfigured) | |
606 return d | |
607 | |
608 | |
609 def test_subscribeWithOptions(self): | |
610 options = {'pubsub#deliver': False} | |
611 | |
612 d = self.protocol.subscribe(JID('pubsub.example.org'), 'test', | |
613 JID('user@example.org'), | |
614 options=options) | |
615 iq = self.stub.output[-1] | |
616 | |
617 # Check options present | |
618 childNames = [] | |
619 for element in iq.pubsub.elements(): | |
620 if element.uri == NS_PUBSUB: | |
621 childNames.append(element.name) | |
622 | |
623 self.assertEqual(['subscribe', 'options'], childNames) | |
624 form = data_form.findForm(iq.pubsub.options, | |
625 NS_PUBSUB_SUBSCRIBE_OPTIONS) | |
626 self.assertEqual('submit', form.formType) | |
627 form.typeCheck({'pubsub#deliver': {'type': 'boolean'}}) | |
628 self.assertEqual(options, form.getValues()) | |
629 | |
630 # Send response | |
631 response = toResponse(iq, 'result') | |
632 pubsub = response.addElement((NS_PUBSUB, 'pubsub')) | |
633 subscription = pubsub.addElement('subscription') | |
634 subscription['node'] = 'test' | |
635 subscription['jid'] = 'user@example.org' | |
636 subscription['subscription'] = 'subscribed' | |
637 self.stub.send(response) | |
638 | |
639 return d | |
640 | |
641 | |
642 def test_subscribeWithSender(self): | |
643 """ | |
644 Test sending subscription request from a specific JID. | |
645 """ | |
646 d = self.protocol.subscribe(JID('pubsub.example.org'), 'test', | |
647 JID('user@example.org'), | |
648 sender=JID('user@example.org')) | |
649 | |
650 iq = self.stub.output[-1] | |
651 self.assertEquals('user@example.org', iq['from']) | |
652 | |
653 response = toResponse(iq, 'result') | |
654 pubsub = response.addElement((NS_PUBSUB, 'pubsub')) | |
655 subscription = pubsub.addElement('subscription') | |
656 subscription['node'] = 'test' | |
657 subscription['jid'] = 'user@example.org' | |
658 subscription['subscription'] = 'subscribed' | |
659 self.stub.send(response) | |
660 return d | |
661 | |
662 | |
663 def test_subscribeReturningSubscriptionIdentifier(self): | |
664 """ | |
665 Test sending subscription request with subscription identifier. | |
666 """ | |
667 def cb(subscription): | |
668 self.assertEqual('1234', subscription.subscriptionIdentifier) | |
669 | |
670 d = self.protocol.subscribe(JID('pubsub.example.org'), 'test', | |
671 JID('user@example.org')) | |
672 d.addCallback(cb) | |
673 | |
674 iq = self.stub.output[-1] | |
675 | |
676 response = toResponse(iq, 'result') | |
677 pubsub = response.addElement((NS_PUBSUB, 'pubsub')) | |
678 subscription = pubsub.addElement('subscription') | |
679 subscription['node'] = 'test' | |
680 subscription['jid'] = 'user@example.org' | |
681 subscription['subscription'] = 'subscribed' | |
682 subscription['subid'] = '1234' | |
683 self.stub.send(response) | |
684 return d | |
685 | |
686 | |
687 def test_unsubscribe(self): | |
688 """ | |
689 Test sending unsubscription request. | |
690 """ | |
691 d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test', | |
692 JID('user@example.org')) | |
693 | |
694 iq = self.stub.output[-1] | |
695 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
696 self.assertEquals('set', iq.getAttribute('type')) | |
697 self.assertEquals('pubsub', iq.pubsub.name) | |
698 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
699 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
700 'unsubscribe', NS_PUBSUB)) | |
701 self.assertEquals(1, len(children)) | |
702 child = children[0] | |
703 self.assertEquals('test', child['node']) | |
704 self.assertEquals('user@example.org', child['jid']) | |
705 | |
706 self.stub.send(toResponse(iq, 'result')) | |
707 return d | |
708 | |
709 | |
710 def test_unsubscribeWithSender(self): | |
711 """ | |
712 Test sending unsubscription request from a specific JID. | |
713 """ | |
714 d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test', | |
715 JID('user@example.org'), | |
716 sender=JID('user@example.org')) | |
717 | |
718 iq = self.stub.output[-1] | |
719 self.assertEquals('user@example.org', iq['from']) | |
720 self.stub.send(toResponse(iq, 'result')) | |
721 return d | |
722 | |
723 | |
724 def test_unsubscribeWithSubscriptionIdentifier(self): | |
725 """ | |
726 Test sending unsubscription request with subscription identifier. | |
727 """ | |
728 d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test', | |
729 JID('user@example.org'), | |
730 subscriptionIdentifier='1234') | |
731 | |
732 iq = self.stub.output[-1] | |
733 child = iq.pubsub.unsubscribe | |
734 self.assertEquals('1234', child['subid']) | |
735 | |
736 self.stub.send(toResponse(iq, 'result')) | |
737 return d | |
738 | |
739 | |
740 def test_items(self): | |
741 """ | |
742 Test sending items request. | |
743 """ | |
744 def cb(items): | |
745 self.assertEquals([], items) | |
746 | |
747 d = self.protocol.items(JID('pubsub.example.org'), 'test') | |
748 d.addCallback(cb) | |
749 | |
750 iq = self.stub.output[-1] | |
751 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
752 self.assertEquals('get', iq.getAttribute('type')) | |
753 self.assertEquals('pubsub', iq.pubsub.name) | |
754 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
755 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
756 'items', NS_PUBSUB)) | |
757 self.assertEquals(1, len(children)) | |
758 child = children[0] | |
759 self.assertEquals('test', child['node']) | |
760 | |
761 response = toResponse(iq, 'result') | |
762 items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items') | |
763 items['node'] = 'test' | |
764 | |
765 self.stub.send(response) | |
766 | |
767 return d | |
768 | |
769 | |
770 def test_itemsMaxItems(self): | |
771 """ | |
772 Test sending items request, with limit on the number of items. | |
773 """ | |
774 def cb(items): | |
775 self.assertEquals(2, len(items)) | |
776 self.assertEquals([item1, item2], items) | |
777 | |
778 d = self.protocol.items(JID('pubsub.example.org'), 'test', maxItems=2) | |
779 d.addCallback(cb) | |
780 | |
781 iq = self.stub.output[-1] | |
782 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
783 self.assertEquals('get', iq.getAttribute('type')) | |
784 self.assertEquals('pubsub', iq.pubsub.name) | |
785 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
786 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
787 'items', NS_PUBSUB)) | |
788 self.assertEquals(1, len(children)) | |
789 child = children[0] | |
790 self.assertEquals('test', child['node']) | |
791 self.assertEquals('2', child['max_items']) | |
792 | |
793 response = toResponse(iq, 'result') | |
794 items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items') | |
795 items['node'] = 'test' | |
796 item1 = items.addElement('item') | |
797 item1['id'] = 'item1' | |
798 item2 = items.addElement('item') | |
799 item2['id'] = 'item2' | |
800 | |
801 self.stub.send(response) | |
802 | |
803 return d | |
804 | |
805 | |
806 def test_itemsWithItemIdentifiers(self): | |
807 """ | |
808 Test sending items request with item identifiers. | |
809 """ | |
810 def cb(items): | |
811 self.assertEquals(2, len(items)) | |
812 self.assertEquals([item1, item2], items) | |
813 | |
814 d = self.protocol.items(JID('pubsub.example.org'), 'test', | |
815 itemIdentifiers=['item1', 'item2']) | |
816 d.addCallback(cb) | |
817 | |
818 iq = self.stub.output[-1] | |
819 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
820 self.assertEquals('get', iq.getAttribute('type')) | |
821 self.assertEquals('pubsub', iq.pubsub.name) | |
822 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
823 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
824 'items', NS_PUBSUB)) | |
825 self.assertEquals(1, len(children)) | |
826 child = children[0] | |
827 self.assertEquals('test', child['node']) | |
828 itemIdentifiers = [item.getAttribute('id') for item in | |
829 domish.generateElementsQNamed(child.children, 'item', | |
830 NS_PUBSUB)] | |
831 self.assertEquals(['item1', 'item2'], itemIdentifiers) | |
832 | |
833 response = toResponse(iq, 'result') | |
834 items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items') | |
835 items['node'] = 'test' | |
836 item1 = items.addElement('item') | |
837 item1['id'] = 'item1' | |
838 item2 = items.addElement('item') | |
839 item2['id'] = 'item2' | |
840 | |
841 self.stub.send(response) | |
842 | |
843 return d | |
844 | |
845 | |
846 def test_itemsWithSubscriptionIdentifier(self): | |
847 """ | |
848 Test sending items request with a subscription identifier. | |
849 """ | |
850 | |
851 d = self.protocol.items(JID('pubsub.example.org'), 'test', | |
852 subscriptionIdentifier='1234') | |
853 | |
854 iq = self.stub.output[-1] | |
855 child = iq.pubsub.items | |
856 self.assertEquals('1234', child['subid']) | |
857 | |
858 response = toResponse(iq, 'result') | |
859 items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items') | |
860 items['node'] = 'test' | |
861 | |
862 self.stub.send(response) | |
863 return d | |
864 | |
865 | |
866 def test_itemsWithSender(self): | |
867 """ | |
868 Test sending items request from a specific JID. | |
869 """ | |
870 | |
871 d = self.protocol.items(JID('pubsub.example.org'), 'test', | |
872 sender=JID('user@example.org')) | |
873 | |
874 iq = self.stub.output[-1] | |
875 self.assertEquals('user@example.org', iq['from']) | |
876 | |
877 response = toResponse(iq, 'result') | |
878 items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items') | |
879 items['node'] = 'test' | |
880 | |
881 self.stub.send(response) | |
882 return d | |
883 | |
884 | |
885 def test_retractItems(self): | |
886 """ | |
887 Test sending items retraction. | |
888 """ | |
889 d = self.protocol.retractItems(JID('pubsub.example.org'), 'test', | |
890 itemIdentifiers=['item1', 'item2']) | |
891 | |
892 iq = self.stub.output[-1] | |
893 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) | |
894 self.assertEquals('set', iq.getAttribute('type')) | |
895 self.assertEquals('pubsub', iq.pubsub.name) | |
896 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) | |
897 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
898 'retract', NS_PUBSUB)) | |
899 self.assertEquals(1, len(children)) | |
900 child = children[0] | |
901 self.assertEquals('test', child['node']) | |
902 itemIdentifiers = [item.getAttribute('id') for item in | |
903 domish.generateElementsQNamed(child.children, 'item', | |
904 NS_PUBSUB)] | |
905 self.assertEquals(['item1', 'item2'], itemIdentifiers) | |
906 | |
907 self.stub.send(toResponse(iq, 'result')) | |
908 return d | |
909 | |
910 | |
911 def test_retractItemsWithSender(self): | |
912 """ | |
913 Test retracting items request from a specific JID. | |
914 """ | |
915 d = self.protocol.retractItems(JID('pubsub.example.org'), 'test', | |
916 itemIdentifiers=['item1', 'item2'], | |
917 sender=JID('user@example.org')) | |
918 | |
919 iq = self.stub.output[-1] | |
920 self.assertEquals('user@example.org', iq['from']) | |
921 | |
922 self.stub.send(toResponse(iq, 'result')) | |
923 return d | |
924 | |
925 | |
926 def test_getOptions(self): | |
927 def cb(form): | |
928 self.assertEqual('form', form.formType) | |
929 self.assertEqual(NS_PUBSUB_SUBSCRIBE_OPTIONS, form.formNamespace) | |
930 field = form.fields['pubsub#deliver'] | |
931 self.assertEqual('boolean', field.fieldType) | |
932 self.assertIdentical(True, field.value) | |
933 self.assertEqual('Enable delivery?', field.label) | |
934 | |
935 d = self.protocol.getOptions(JID('pubsub.example.org'), 'test', | |
936 JID('user@example.org'), | |
937 sender=JID('user@example.org')) | |
938 d.addCallback(cb) | |
939 | |
940 iq = self.stub.output[-1] | |
941 self.assertEqual('pubsub.example.org', iq.getAttribute('to')) | |
942 self.assertEqual('get', iq.getAttribute('type')) | |
943 self.assertEqual('pubsub', iq.pubsub.name) | |
944 self.assertEqual(NS_PUBSUB, iq.pubsub.uri) | |
945 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
946 'options', NS_PUBSUB)) | |
947 self.assertEqual(1, len(children)) | |
948 child = children[0] | |
949 self.assertEqual('test', child['node']) | |
950 | |
951 self.assertEqual(0, len(child.children)) | |
952 | |
953 # Send response | |
954 form = data_form.Form('form', formNamespace=NS_PUBSUB_SUBSCRIBE_OPTIONS) | |
955 form.addField(data_form.Field('boolean', var='pubsub#deliver', | |
956 label='Enable delivery?', | |
957 value=True)) | |
958 response = toResponse(iq, 'result') | |
959 response.addElement((NS_PUBSUB, 'pubsub')) | |
960 response.pubsub.addElement('options') | |
961 response.pubsub.options.addChild(form.toElement()) | |
962 self.stub.send(response) | |
963 | |
964 return d | |
965 | |
966 | |
967 def test_getOptionsWithSubscriptionIdentifier(self): | |
968 """ | |
969 Getting options with a subid should have the subid in the request. | |
970 """ | |
971 | |
972 d = self.protocol.getOptions(JID('pubsub.example.org'), 'test', | |
973 JID('user@example.org'), | |
974 sender=JID('user@example.org'), | |
975 subscriptionIdentifier='1234') | |
976 | |
977 iq = self.stub.output[-1] | |
978 child = iq.pubsub.options | |
979 self.assertEqual('1234', child['subid']) | |
980 | |
981 # Send response | |
982 form = data_form.Form('form', formNamespace=NS_PUBSUB_SUBSCRIBE_OPTIONS) | |
983 form.addField(data_form.Field('boolean', var='pubsub#deliver', | |
984 label='Enable delivery?', | |
985 value=True)) | |
986 response = toResponse(iq, 'result') | |
987 response.addElement((NS_PUBSUB, 'pubsub')) | |
988 response.pubsub.addElement('options') | |
989 response.pubsub.options.addChild(form.toElement()) | |
990 self.stub.send(response) | |
991 | |
992 return d | |
993 | |
994 | |
995 def test_setOptions(self): | |
996 """ | |
997 setOptions should send out a options-set request. | |
998 """ | |
999 options = {'pubsub#deliver': False} | |
1000 | |
1001 d = self.protocol.setOptions(JID('pubsub.example.org'), 'test', | |
1002 JID('user@example.org'), | |
1003 options, | |
1004 sender=JID('user@example.org')) | |
1005 | |
1006 iq = self.stub.output[-1] | |
1007 self.assertEqual('pubsub.example.org', iq.getAttribute('to')) | |
1008 self.assertEqual('set', iq.getAttribute('type')) | |
1009 self.assertEqual('pubsub', iq.pubsub.name) | |
1010 self.assertEqual(NS_PUBSUB, iq.pubsub.uri) | |
1011 children = list(domish.generateElementsQNamed(iq.pubsub.children, | |
1012 'options', NS_PUBSUB)) | |
1013 self.assertEqual(1, len(children)) | |
1014 child = children[0] | |
1015 self.assertEqual('test', child['node']) | |
1016 | |
1017 form = data_form.findForm(child, NS_PUBSUB_SUBSCRIBE_OPTIONS) | |
1018 self.assertEqual('submit', form.formType) | |
1019 form.typeCheck({'pubsub#deliver': {'type': 'boolean'}}) | |
1020 self.assertEqual(options, form.getValues()) | |
1021 | |
1022 response = toResponse(iq, 'result') | |
1023 self.stub.send(response) | |
1024 | |
1025 return d | |
1026 | |
1027 | |
1028 def test_setOptionsWithSubscriptionIdentifier(self): | |
1029 """ | |
1030 setOptions should send out a options-set request with subid. | |
1031 """ | |
1032 options = {'pubsub#deliver': False} | |
1033 | |
1034 d = self.protocol.setOptions(JID('pubsub.example.org'), 'test', | |
1035 JID('user@example.org'), | |
1036 options, | |
1037 subscriptionIdentifier='1234', | |
1038 sender=JID('user@example.org')) | |
1039 | |
1040 iq = self.stub.output[-1] | |
1041 child = iq.pubsub.options | |
1042 self.assertEqual('1234', child['subid']) | |
1043 | |
1044 form = data_form.findForm(child, NS_PUBSUB_SUBSCRIBE_OPTIONS) | |
1045 self.assertEqual('submit', form.formType) | |
1046 form.typeCheck({'pubsub#deliver': {'type': 'boolean'}}) | |
1047 self.assertEqual(options, form.getValues()) | |
1048 | |
1049 response = toResponse(iq, 'result') | |
1050 self.stub.send(response) | |
1051 | |
1052 return d | |
1053 | |
1054 | |
1055 class PubSubRequestTest(unittest.TestCase): | |
1056 | |
1057 def test_fromElementUnknown(self): | |
1058 """ | |
1059 An unknown verb raises NotImplementedError. | |
1060 """ | |
1061 | |
1062 xml = """ | |
1063 <iq type='set' to='pubsub.example.org' | |
1064 from='user@example.org'> | |
1065 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1066 <non-existing-verb/> | |
1067 </pubsub> | |
1068 </iq> | |
1069 """ | |
1070 | |
1071 self.assertRaises(NotImplementedError, | |
1072 pubsub.PubSubRequest.fromElement, parseXml(xml)) | |
1073 | |
1074 | |
1075 def test_fromElementKnownBadCombination(self): | |
1076 """ | |
1077 Multiple verbs in an unknown configuration raises NotImplementedError. | |
1078 """ | |
1079 | |
1080 xml = """ | |
1081 <iq type='set' to='pubsub.example.org' | |
1082 from='user@example.org'> | |
1083 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1084 <publish/> | |
1085 <create/> | |
1086 </pubsub> | |
1087 </iq> | |
1088 """ | |
1089 | |
1090 self.assertRaises(NotImplementedError, | |
1091 pubsub.PubSubRequest.fromElement, parseXml(xml)) | |
1092 | |
1093 def test_fromElementPublish(self): | |
1094 """ | |
1095 Test parsing a publish request. | |
1096 """ | |
1097 | |
1098 xml = """ | |
1099 <iq type='set' to='pubsub.example.org' | |
1100 from='user@example.org'> | |
1101 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1102 <publish node='test'/> | |
1103 </pubsub> | |
1104 </iq> | |
1105 """ | |
1106 | |
1107 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1108 self.assertEqual('publish', request.verb) | |
1109 self.assertEqual(JID('user@example.org'), request.sender) | |
1110 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1111 self.assertEqual('test', request.nodeIdentifier) | |
1112 self.assertEqual([], request.items) | |
1113 | |
1114 | |
1115 def test_fromElementPublishItems(self): | |
1116 """ | |
1117 Test parsing a publish request with items. | |
1118 """ | |
1119 | |
1120 xml = """ | |
1121 <iq type='set' to='pubsub.example.org' | |
1122 from='user@example.org'> | |
1123 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1124 <publish node='test'> | |
1125 <item id="item1"/> | |
1126 <item id="item2"/> | |
1127 </publish> | |
1128 </pubsub> | |
1129 </iq> | |
1130 """ | |
1131 | |
1132 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1133 self.assertEqual(2, len(request.items)) | |
1134 self.assertEqual(u'item1', request.items[0]["id"]) | |
1135 self.assertEqual(u'item2', request.items[1]["id"]) | |
1136 | |
1137 | |
1138 def test_fromElementPublishItemsOptions(self): | |
1139 """ | |
1140 Test parsing a publish request with items and options. | |
1141 | |
1142 Note that publishing options are not supported, but passing them | |
1143 shouldn't affect processing of the publish request itself. | |
1144 """ | |
1145 | |
1146 xml = """ | |
1147 <iq type='set' to='pubsub.example.org' | |
1148 from='user@example.org'> | |
1149 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1150 <publish node='test'> | |
1151 <item id="item1"/> | |
1152 <item id="item2"/> | |
1153 </publish> | |
1154 <publish-options/> | |
1155 </pubsub> | |
1156 </iq> | |
1157 """ | |
1158 | |
1159 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1160 self.assertEqual(2, len(request.items)) | |
1161 self.assertEqual(u'item1', request.items[0]["id"]) | |
1162 self.assertEqual(u'item2', request.items[1]["id"]) | |
1163 | |
1164 def test_fromElementPublishNoNode(self): | |
1165 """ | |
1166 A publish request to the root node should raise an exception. | |
1167 """ | |
1168 xml = """ | |
1169 <iq type='set' to='pubsub.example.org' | |
1170 from='user@example.org'> | |
1171 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1172 <publish/> | |
1173 </pubsub> | |
1174 </iq> | |
1175 """ | |
1176 | |
1177 err = self.assertRaises(error.StanzaError, | |
1178 pubsub.PubSubRequest.fromElement, | |
1179 parseXml(xml)) | |
1180 self.assertEqual('bad-request', err.condition) | |
1181 self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri) | |
1182 self.assertEqual('nodeid-required', err.appCondition.name) | |
1183 | |
1184 | |
1185 def test_fromElementSubscribe(self): | |
1186 """ | |
1187 Test parsing a subscription request. | |
1188 """ | |
1189 | |
1190 xml = """ | |
1191 <iq type='set' to='pubsub.example.org' | |
1192 from='user@example.org'> | |
1193 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1194 <subscribe node='test' jid='user@example.org/Home'/> | |
1195 </pubsub> | |
1196 </iq> | |
1197 """ | |
1198 | |
1199 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1200 self.assertEqual('subscribe', request.verb) | |
1201 self.assertEqual(JID('user@example.org'), request.sender) | |
1202 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1203 self.assertEqual('test', request.nodeIdentifier) | |
1204 self.assertEqual(JID('user@example.org/Home'), request.subscriber) | |
1205 | |
1206 | |
1207 def test_fromElementSubscribeEmptyNode(self): | |
1208 """ | |
1209 Test parsing a subscription request to the root node. | |
1210 """ | |
1211 | |
1212 xml = """ | |
1213 <iq type='set' to='pubsub.example.org' | |
1214 from='user@example.org'> | |
1215 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1216 <subscribe jid='user@example.org/Home'/> | |
1217 </pubsub> | |
1218 </iq> | |
1219 """ | |
1220 | |
1221 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1222 self.assertEqual('', request.nodeIdentifier) | |
1223 | |
1224 | |
1225 def test_fromElementSubscribeNoJID(self): | |
1226 """ | |
1227 Subscribe requests without a JID should raise a bad-request exception. | |
1228 """ | |
1229 xml = """ | |
1230 <iq type='set' to='pubsub.example.org' | |
1231 from='user@example.org'> | |
1232 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1233 <subscribe node='test'/> | |
1234 </pubsub> | |
1235 </iq> | |
1236 """ | |
1237 err = self.assertRaises(error.StanzaError, | |
1238 pubsub.PubSubRequest.fromElement, | |
1239 parseXml(xml)) | |
1240 self.assertEqual('bad-request', err.condition) | |
1241 self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri) | |
1242 self.assertEqual('jid-required', err.appCondition.name) | |
1243 | |
1244 | |
1245 def test_fromElementSubscribeWithOptions(self): | |
1246 """ | |
1247 Test parsing a subscription request. | |
1248 """ | |
1249 | |
1250 xml = """ | |
1251 <iq type='set' to='pubsub.example.org' | |
1252 from='user@example.org'> | |
1253 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1254 <subscribe node='test' jid='user@example.org/Home'/> | |
1255 <options> | |
1256 <x xmlns="jabber:x:data" type='submit'> | |
1257 <field var='FORM_TYPE' type='hidden'> | |
1258 <value>http://jabber.org/protocol/pubsub#subscribe_options</value> | |
1259 </field> | |
1260 <field var='pubsub#deliver' type='boolean' | |
1261 label='Enable delivery?'> | |
1262 <value>1</value> | |
1263 </field> | |
1264 </x> | |
1265 </options> | |
1266 </pubsub> | |
1267 </iq> | |
1268 """ | |
1269 | |
1270 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1271 self.assertEqual('subscribe', request.verb) | |
1272 request.options.typeCheck({'pubsub#deliver': {'type': 'boolean'}}) | |
1273 self.assertEqual({'pubsub#deliver': True}, request.options.getValues()) | |
1274 | |
1275 | |
1276 def test_fromElementSubscribeWithOptionsBadFormType(self): | |
1277 """ | |
1278 The options form should have the right type. | |
1279 """ | |
1280 | |
1281 xml = """ | |
1282 <iq type='set' to='pubsub.example.org' | |
1283 from='user@example.org'> | |
1284 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1285 <subscribe node='test' jid='user@example.org/Home'/> | |
1286 <options> | |
1287 <x xmlns="jabber:x:data" type='result'> | |
1288 <field var='FORM_TYPE' type='hidden'> | |
1289 <value>http://jabber.org/protocol/pubsub#subscribe_options</value> | |
1290 </field> | |
1291 <field var='pubsub#deliver' type='boolean' | |
1292 label='Enable delivery?'> | |
1293 <value>1</value> | |
1294 </field> | |
1295 </x> | |
1296 </options> | |
1297 </pubsub> | |
1298 </iq> | |
1299 """ | |
1300 | |
1301 err = self.assertRaises(error.StanzaError, | |
1302 pubsub.PubSubRequest.fromElement, | |
1303 parseXml(xml)) | |
1304 self.assertEqual('bad-request', err.condition) | |
1305 self.assertEqual("Unexpected form type 'result'", err.text) | |
1306 self.assertEqual(None, err.appCondition) | |
1307 | |
1308 | |
1309 def test_fromElementSubscribeWithOptionsEmpty(self): | |
1310 """ | |
1311 When no (suitable) form is found, the options are empty. | |
1312 """ | |
1313 | |
1314 xml = """ | |
1315 <iq type='set' to='pubsub.example.org' | |
1316 from='user@example.org'> | |
1317 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1318 <subscribe node='test' jid='user@example.org/Home'/> | |
1319 <options/> | |
1320 </pubsub> | |
1321 </iq> | |
1322 """ | |
1323 | |
1324 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1325 self.assertEqual('subscribe', request.verb) | |
1326 self.assertEqual({}, request.options.getValues()) | |
1327 | |
1328 | |
1329 def test_fromElementUnsubscribe(self): | |
1330 """ | |
1331 Test parsing an unsubscription request. | |
1332 """ | |
1333 | |
1334 xml = """ | |
1335 <iq type='set' to='pubsub.example.org' | |
1336 from='user@example.org'> | |
1337 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1338 <unsubscribe node='test' jid='user@example.org/Home'/> | |
1339 </pubsub> | |
1340 </iq> | |
1341 """ | |
1342 | |
1343 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1344 self.assertEqual('unsubscribe', request.verb) | |
1345 self.assertEqual(JID('user@example.org'), request.sender) | |
1346 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1347 self.assertEqual('test', request.nodeIdentifier) | |
1348 self.assertEqual(JID('user@example.org/Home'), request.subscriber) | |
1349 | |
1350 | |
1351 def test_fromElementUnsubscribeWithSubscriptionIdentifier(self): | |
1352 """ | |
1353 Test parsing an unsubscription request with subscription identifier. | |
1354 """ | |
1355 | |
1356 xml = """ | |
1357 <iq type='set' to='pubsub.example.org' | |
1358 from='user@example.org'> | |
1359 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1360 <unsubscribe node='test' jid='user@example.org/Home' | |
1361 subid='1234'/> | |
1362 </pubsub> | |
1363 </iq> | |
1364 """ | |
1365 | |
1366 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1367 self.assertEqual('1234', request.subscriptionIdentifier) | |
1368 | |
1369 | |
1370 def test_fromElementUnsubscribeNoJID(self): | |
1371 """ | |
1372 Unsubscribe requests without a JID should raise a bad-request exception. | |
1373 """ | |
1374 xml = """ | |
1375 <iq type='set' to='pubsub.example.org' | |
1376 from='user@example.org'> | |
1377 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1378 <unsubscribe node='test'/> | |
1379 </pubsub> | |
1380 </iq> | |
1381 """ | |
1382 err = self.assertRaises(error.StanzaError, | |
1383 pubsub.PubSubRequest.fromElement, | |
1384 parseXml(xml)) | |
1385 self.assertEqual('bad-request', err.condition) | |
1386 self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri) | |
1387 self.assertEqual('jid-required', err.appCondition.name) | |
1388 | |
1389 | |
1390 def test_fromElementOptionsGet(self): | |
1391 """ | |
1392 Test parsing a request for getting subscription options. | |
1393 """ | |
1394 | |
1395 xml = """ | |
1396 <iq type='get' to='pubsub.example.org' | |
1397 from='user@example.org'> | |
1398 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1399 <options node='test' jid='user@example.org/Home'/> | |
1400 </pubsub> | |
1401 </iq> | |
1402 """ | |
1403 | |
1404 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1405 self.assertEqual('optionsGet', request.verb) | |
1406 self.assertEqual(JID('user@example.org'), request.sender) | |
1407 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1408 self.assertEqual('test', request.nodeIdentifier) | |
1409 self.assertEqual(JID('user@example.org/Home'), request.subscriber) | |
1410 | |
1411 | |
1412 def test_fromElementOptionsGetWithSubscriptionIdentifier(self): | |
1413 """ | |
1414 Test parsing a request for getting subscription options with subid. | |
1415 """ | |
1416 | |
1417 xml = """ | |
1418 <iq type='get' to='pubsub.example.org' | |
1419 from='user@example.org'> | |
1420 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1421 <options node='test' jid='user@example.org/Home' | |
1422 subid='1234'/> | |
1423 </pubsub> | |
1424 </iq> | |
1425 """ | |
1426 | |
1427 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1428 self.assertEqual('1234', request.subscriptionIdentifier) | |
1429 | |
1430 | |
1431 def test_fromElementOptionsSet(self): | |
1432 """ | |
1433 Test parsing a request for setting subscription options. | |
1434 """ | |
1435 | |
1436 xml = """ | |
1437 <iq type='set' to='pubsub.example.org' | |
1438 from='user@example.org'> | |
1439 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1440 <options node='test' jid='user@example.org/Home'> | |
1441 <x xmlns='jabber:x:data' type='submit'> | |
1442 <field var='FORM_TYPE' type='hidden'> | |
1443 <value>http://jabber.org/protocol/pubsub#subscribe_options</value> | |
1444 </field> | |
1445 <field var='pubsub#deliver'><value>1</value></field> | |
1446 </x> | |
1447 </options> | |
1448 </pubsub> | |
1449 </iq> | |
1450 """ | |
1451 | |
1452 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1453 self.assertEqual('optionsSet', request.verb) | |
1454 self.assertEqual(JID('user@example.org'), request.sender) | |
1455 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1456 self.assertEqual('test', request.nodeIdentifier) | |
1457 self.assertEqual(JID('user@example.org/Home'), request.subscriber) | |
1458 self.assertEqual({'pubsub#deliver': '1'}, request.options.getValues()) | |
1459 | |
1460 | |
1461 def test_fromElementOptionsSetWithSubscriptionIdentifier(self): | |
1462 """ | |
1463 Test parsing a request for setting subscription options with subid. | |
1464 """ | |
1465 | |
1466 xml = """ | |
1467 <iq type='set' to='pubsub.example.org' | |
1468 from='user@example.org'> | |
1469 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1470 <options node='test' jid='user@example.org/Home' | |
1471 subid='1234'> | |
1472 <x xmlns='jabber:x:data' type='submit'> | |
1473 <field var='FORM_TYPE' type='hidden'> | |
1474 <value>http://jabber.org/protocol/pubsub#subscribe_options</value> | |
1475 </field> | |
1476 <field var='pubsub#deliver'><value>1</value></field> | |
1477 </x> | |
1478 </options> | |
1479 </pubsub> | |
1480 </iq> | |
1481 """ | |
1482 | |
1483 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1484 self.assertEqual('1234', request.subscriptionIdentifier) | |
1485 | |
1486 | |
1487 def test_fromElementOptionsSetCancel(self): | |
1488 """ | |
1489 Test parsing a request for cancelling setting subscription options. | |
1490 """ | |
1491 | |
1492 xml = """ | |
1493 <iq type='set' to='pubsub.example.org' | |
1494 from='user@example.org'> | |
1495 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1496 <options node='test' jid='user@example.org/Home'> | |
1497 <x xmlns='jabber:x:data' type='cancel'/> | |
1498 </options> | |
1499 </pubsub> | |
1500 </iq> | |
1501 """ | |
1502 | |
1503 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1504 self.assertEqual('cancel', request.options.formType) | |
1505 | |
1506 | |
1507 def test_fromElementOptionsSetBadFormType(self): | |
1508 """ | |
1509 On a options set request unknown fields should be ignored. | |
1510 """ | |
1511 | |
1512 xml = """ | |
1513 <iq type='set' to='pubsub.example.org' | |
1514 from='user@example.org'> | |
1515 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1516 <options node='test' jid='user@example.org/Home'> | |
1517 <x xmlns='jabber:x:data' type='result'> | |
1518 <field var='FORM_TYPE' type='hidden'> | |
1519 <value>http://jabber.org/protocol/pubsub#subscribe_options</value> | |
1520 </field> | |
1521 <field var='pubsub#deliver'><value>1</value></field> | |
1522 </x> | |
1523 </options> | |
1524 </pubsub> | |
1525 </iq> | |
1526 """ | |
1527 | |
1528 err = self.assertRaises(error.StanzaError, | |
1529 pubsub.PubSubRequest.fromElement, | |
1530 parseXml(xml)) | |
1531 self.assertEqual('bad-request', err.condition) | |
1532 self.assertEqual("Unexpected form type 'result'", err.text) | |
1533 self.assertEqual(None, err.appCondition) | |
1534 | |
1535 | |
1536 def test_fromElementOptionsSetNoForm(self): | |
1537 """ | |
1538 On a options set request a form is required. | |
1539 """ | |
1540 | |
1541 xml = """ | |
1542 <iq type='set' to='pubsub.example.org' | |
1543 from='user@example.org'> | |
1544 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1545 <options node='test' jid='user@example.org/Home'/> | |
1546 </pubsub> | |
1547 </iq> | |
1548 """ | |
1549 err = self.assertRaises(error.StanzaError, | |
1550 pubsub.PubSubRequest.fromElement, | |
1551 parseXml(xml)) | |
1552 self.assertEqual('bad-request', err.condition) | |
1553 self.assertEqual(None, err.appCondition) | |
1554 | |
1555 | |
1556 def test_fromElementSubscriptions(self): | |
1557 """ | |
1558 Test parsing a request for all subscriptions. | |
1559 """ | |
1560 | |
1561 xml = """ | |
1562 <iq type='get' to='pubsub.example.org' | |
1563 from='user@example.org'> | |
1564 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1565 <subscriptions/> | |
1566 </pubsub> | |
1567 </iq> | |
1568 """ | |
1569 | |
1570 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1571 self.assertEqual('subscriptions', request.verb) | |
1572 self.assertEqual(JID('user@example.org'), request.sender) | |
1573 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1574 | |
1575 | |
1576 def test_fromElementAffiliations(self): | |
1577 """ | |
1578 Test parsing a request for all affiliations. | |
1579 """ | |
1580 | |
1581 xml = """ | |
1582 <iq type='get' to='pubsub.example.org' | |
1583 from='user@example.org'> | |
1584 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1585 <affiliations/> | |
1586 </pubsub> | |
1587 </iq> | |
1588 """ | |
1589 | |
1590 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1591 self.assertEqual('affiliations', request.verb) | |
1592 self.assertEqual(JID('user@example.org'), request.sender) | |
1593 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1594 | |
1595 | |
1596 def test_fromElementCreate(self): | |
1597 """ | |
1598 Test parsing a request to create a node. | |
1599 """ | |
1600 | |
1601 xml = """ | |
1602 <iq type='set' to='pubsub.example.org' | |
1603 from='user@example.org'> | |
1604 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1605 <create node='mynode'/> | |
1606 </pubsub> | |
1607 </iq> | |
1608 """ | |
1609 | |
1610 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1611 self.assertEqual('create', request.verb) | |
1612 self.assertEqual(JID('user@example.org'), request.sender) | |
1613 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1614 self.assertEqual('mynode', request.nodeIdentifier) | |
1615 self.assertIdentical(None, request.options) | |
1616 | |
1617 | |
1618 def test_fromElementCreateInstant(self): | |
1619 """ | |
1620 Test parsing a request to create an instant node. | |
1621 """ | |
1622 | |
1623 xml = """ | |
1624 <iq type='set' to='pubsub.example.org' | |
1625 from='user@example.org'> | |
1626 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1627 <create/> | |
1628 </pubsub> | |
1629 </iq> | |
1630 """ | |
1631 | |
1632 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1633 self.assertIdentical(None, request.nodeIdentifier) | |
1634 | |
1635 | |
1636 def test_fromElementCreateConfigureEmpty(self): | |
1637 """ | |
1638 Test parsing a request to create a node with an empty configuration. | |
1639 """ | |
1640 | |
1641 xml = """ | |
1642 <iq type='set' to='pubsub.example.org' | |
1643 from='user@example.org'> | |
1644 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1645 <create node='mynode'/> | |
1646 <configure/> | |
1647 </pubsub> | |
1648 </iq> | |
1649 """ | |
1650 | |
1651 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1652 self.assertEqual({}, request.options.getValues()) | |
1653 self.assertEqual(u'mynode', request.nodeIdentifier) | |
1654 | |
1655 | |
1656 def test_fromElementCreateConfigureEmptyWrongOrder(self): | |
1657 """ | |
1658 Test parsing a request to create a node and configure, wrong order. | |
1659 | |
1660 The C{configure} element should come after the C{create} request, | |
1661 but we should accept both orders. | |
1662 """ | |
1663 | |
1664 xml = """ | |
1665 <iq type='set' to='pubsub.example.org' | |
1666 from='user@example.org'> | |
1667 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1668 <configure/> | |
1669 <create node='mynode'/> | |
1670 </pubsub> | |
1671 </iq> | |
1672 """ | |
1673 | |
1674 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1675 self.assertEqual({}, request.options.getValues()) | |
1676 self.assertEqual(u'mynode', request.nodeIdentifier) | |
1677 | |
1678 | |
1679 def test_fromElementCreateConfigure(self): | |
1680 """ | |
1681 Test parsing a request to create a node. | |
1682 """ | |
1683 | |
1684 xml = """ | |
1685 <iq type='set' to='pubsub.example.org' | |
1686 from='user@example.org'> | |
1687 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1688 <create node='mynode'/> | |
1689 <configure> | |
1690 <x xmlns='jabber:x:data' type='submit'> | |
1691 <field var='FORM_TYPE' type='hidden'> | |
1692 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
1693 </field> | |
1694 <field var='pubsub#access_model'><value>open</value></field> | |
1695 <field var='pubsub#persist_items'><value>0</value></field> | |
1696 </x> | |
1697 </configure> | |
1698 </pubsub> | |
1699 </iq> | |
1700 """ | |
1701 | |
1702 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1703 values = request.options | |
1704 self.assertIn('pubsub#access_model', values) | |
1705 self.assertEqual(u'open', values['pubsub#access_model']) | |
1706 self.assertIn('pubsub#persist_items', values) | |
1707 self.assertEqual(u'0', values['pubsub#persist_items']) | |
1708 | |
1709 | |
1710 def test_fromElementCreateConfigureBadFormType(self): | |
1711 """ | |
1712 The form of a node creation request should have the right type. | |
1713 """ | |
1714 | |
1715 xml = """ | |
1716 <iq type='set' to='pubsub.example.org' | |
1717 from='user@example.org'> | |
1718 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1719 <create node='mynode'/> | |
1720 <configure> | |
1721 <x xmlns='jabber:x:data' type='result'> | |
1722 <field var='FORM_TYPE' type='hidden'> | |
1723 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
1724 </field> | |
1725 <field var='pubsub#access_model'><value>open</value></field> | |
1726 <field var='pubsub#persist_items'><value>0</value></field> | |
1727 </x> | |
1728 </configure> | |
1729 </pubsub> | |
1730 </iq> | |
1731 """ | |
1732 | |
1733 err = self.assertRaises(error.StanzaError, | |
1734 pubsub.PubSubRequest.fromElement, | |
1735 parseXml(xml)) | |
1736 self.assertEqual('bad-request', err.condition) | |
1737 self.assertEqual("Unexpected form type 'result'", err.text) | |
1738 self.assertEqual(None, err.appCondition) | |
1739 | |
1740 | |
1741 def test_fromElementDefault(self): | |
1742 """ | |
1743 Parsing default node configuration request sets required attributes. | |
1744 | |
1745 Besides C{verb}, C{sender} and C{recipient}, we expect C{nodeType} | |
1746 to be set. If not passed it receives the default C{u'leaf'}. | |
1747 """ | |
1748 | |
1749 xml = """ | |
1750 <iq type='get' to='pubsub.example.org' | |
1751 from='user@example.org'> | |
1752 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
1753 <default/> | |
1754 </pubsub> | |
1755 </iq> | |
1756 """ | |
1757 | |
1758 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1759 self.assertEquals(u'default', request.verb) | |
1760 self.assertEquals(JID('user@example.org'), request.sender) | |
1761 self.assertEquals(JID('pubsub.example.org'), request.recipient) | |
1762 self.assertEquals(u'leaf', request.nodeType) | |
1763 | |
1764 | |
1765 def test_fromElementDefaultCollection(self): | |
1766 """ | |
1767 Parsing default request for collection sets nodeType to collection. | |
1768 """ | |
1769 | |
1770 xml = """ | |
1771 <iq type='get' to='pubsub.example.org' | |
1772 from='user@example.org'> | |
1773 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
1774 <default> | |
1775 <x xmlns='jabber:x:data' type='submit'> | |
1776 <field var='FORM_TYPE' type='hidden'> | |
1777 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
1778 </field> | |
1779 <field var='pubsub#node_type'> | |
1780 <value>collection</value> | |
1781 </field> | |
1782 </x> | |
1783 </default> | |
1784 | |
1785 </pubsub> | |
1786 </iq> | |
1787 """ | |
1788 | |
1789 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1790 self.assertEquals('collection', request.nodeType) | |
1791 | |
1792 | |
1793 def test_fromElementConfigureGet(self): | |
1794 """ | |
1795 Test parsing a node configuration get request. | |
1796 """ | |
1797 | |
1798 xml = """ | |
1799 <iq type='get' to='pubsub.example.org' | |
1800 from='user@example.org'> | |
1801 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
1802 <configure node='test'/> | |
1803 </pubsub> | |
1804 </iq> | |
1805 """ | |
1806 | |
1807 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1808 self.assertEqual('configureGet', request.verb) | |
1809 self.assertEqual(JID('user@example.org'), request.sender) | |
1810 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1811 self.assertEqual('test', request.nodeIdentifier) | |
1812 | |
1813 | |
1814 def test_fromElementConfigureSet(self): | |
1815 """ | |
1816 On a node configuration set request the Data Form is parsed. | |
1817 """ | |
1818 | |
1819 xml = """ | |
1820 <iq type='set' to='pubsub.example.org' | |
1821 from='user@example.org'> | |
1822 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
1823 <configure node='test'> | |
1824 <x xmlns='jabber:x:data' type='submit'> | |
1825 <field var='FORM_TYPE' type='hidden'> | |
1826 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
1827 </field> | |
1828 <field var='pubsub#deliver_payloads'><value>0</value></field> | |
1829 <field var='pubsub#persist_items'><value>1</value></field> | |
1830 </x> | |
1831 </configure> | |
1832 </pubsub> | |
1833 </iq> | |
1834 """ | |
1835 | |
1836 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1837 self.assertEqual('configureSet', request.verb) | |
1838 self.assertEqual(JID('user@example.org'), request.sender) | |
1839 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1840 self.assertEqual('test', request.nodeIdentifier) | |
1841 self.assertEqual({'pubsub#deliver_payloads': '0', | |
1842 'pubsub#persist_items': '1'}, | |
1843 request.options.getValues()) | |
1844 | |
1845 | |
1846 def test_fromElementConfigureSetCancel(self): | |
1847 """ | |
1848 The node configuration is cancelled, so no options. | |
1849 """ | |
1850 | |
1851 xml = """ | |
1852 <iq type='set' to='pubsub.example.org' | |
1853 from='user@example.org'> | |
1854 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
1855 <configure node='test'> | |
1856 <x xmlns='jabber:x:data' type='cancel'/> | |
1857 </configure> | |
1858 </pubsub> | |
1859 </iq> | |
1860 """ | |
1861 | |
1862 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1863 self.assertEqual('cancel', request.options.formType) | |
1864 | |
1865 | |
1866 def test_fromElementConfigureSetBadFormType(self): | |
1867 """ | |
1868 The form of a node configuraton set request should have the right type. | |
1869 """ | |
1870 | |
1871 xml = """ | |
1872 <iq type='set' to='pubsub.example.org' | |
1873 from='user@example.org'> | |
1874 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
1875 <configure node='test'> | |
1876 <x xmlns='jabber:x:data' type='result'> | |
1877 <field var='FORM_TYPE' type='hidden'> | |
1878 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
1879 </field> | |
1880 <field var='pubsub#deliver_payloads'><value>0</value></field> | |
1881 <field var='x-myfield'><value>1</value></field> | |
1882 </x> | |
1883 </configure> | |
1884 </pubsub> | |
1885 </iq> | |
1886 """ | |
1887 | |
1888 err = self.assertRaises(error.StanzaError, | |
1889 pubsub.PubSubRequest.fromElement, | |
1890 parseXml(xml)) | |
1891 self.assertEqual('bad-request', err.condition) | |
1892 self.assertEqual("Unexpected form type 'result'", err.text) | |
1893 self.assertEqual(None, err.appCondition) | |
1894 | |
1895 | |
1896 def test_fromElementConfigureSetNoForm(self): | |
1897 """ | |
1898 On a node configuration set request a form is required. | |
1899 """ | |
1900 | |
1901 xml = """ | |
1902 <iq type='set' to='pubsub.example.org' | |
1903 from='user@example.org'> | |
1904 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
1905 <configure node='test'/> | |
1906 </pubsub> | |
1907 </iq> | |
1908 """ | |
1909 err = self.assertRaises(error.StanzaError, | |
1910 pubsub.PubSubRequest.fromElement, | |
1911 parseXml(xml)) | |
1912 self.assertEqual('bad-request', err.condition) | |
1913 self.assertEqual(None, err.appCondition) | |
1914 | |
1915 | |
1916 def test_fromElementItems(self): | |
1917 """ | |
1918 Test parsing an items request. | |
1919 """ | |
1920 xml = """ | |
1921 <iq type='get' to='pubsub.example.org' | |
1922 from='user@example.org'> | |
1923 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1924 <items node='test'/> | |
1925 </pubsub> | |
1926 </iq> | |
1927 """ | |
1928 | |
1929 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1930 self.assertEqual('items', request.verb) | |
1931 self.assertEqual(JID('user@example.org'), request.sender) | |
1932 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1933 self.assertEqual('test', request.nodeIdentifier) | |
1934 self.assertIdentical(None, request.maxItems) | |
1935 self.assertIdentical(None, request.subscriptionIdentifier) | |
1936 self.assertEqual([], request.itemIdentifiers) | |
1937 | |
1938 | |
1939 def test_fromElementItemsSubscriptionIdentifier(self): | |
1940 """ | |
1941 Test parsing an items request with subscription identifier. | |
1942 """ | |
1943 xml = """ | |
1944 <iq type='get' to='pubsub.example.org' | |
1945 from='user@example.org'> | |
1946 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1947 <items node='test' subid='1234'/> | |
1948 </pubsub> | |
1949 </iq> | |
1950 """ | |
1951 | |
1952 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1953 self.assertEqual('1234', request.subscriptionIdentifier) | |
1954 | |
1955 | |
1956 def test_fromElementRetract(self): | |
1957 """ | |
1958 Test parsing a retract request. | |
1959 """ | |
1960 | |
1961 xml = """ | |
1962 <iq type='set' to='pubsub.example.org' | |
1963 from='user@example.org'> | |
1964 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
1965 <retract node='test'> | |
1966 <item id='item1'/> | |
1967 <item id='item2'/> | |
1968 </retract> | |
1969 </pubsub> | |
1970 </iq> | |
1971 """ | |
1972 | |
1973 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1974 self.assertEqual('retract', request.verb) | |
1975 self.assertEqual(JID('user@example.org'), request.sender) | |
1976 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1977 self.assertEqual('test', request.nodeIdentifier) | |
1978 self.assertEqual(['item1', 'item2'], request.itemIdentifiers) | |
1979 | |
1980 | |
1981 def test_fromElementPurge(self): | |
1982 """ | |
1983 Test parsing a purge request. | |
1984 """ | |
1985 | |
1986 xml = """ | |
1987 <iq type='set' to='pubsub.example.org' | |
1988 from='user@example.org'> | |
1989 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
1990 <purge node='test'/> | |
1991 </pubsub> | |
1992 </iq> | |
1993 """ | |
1994 | |
1995 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
1996 self.assertEqual('purge', request.verb) | |
1997 self.assertEqual(JID('user@example.org'), request.sender) | |
1998 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
1999 self.assertEqual('test', request.nodeIdentifier) | |
2000 | |
2001 | |
2002 def test_fromElementDelete(self): | |
2003 """ | |
2004 Test parsing a delete request. | |
2005 """ | |
2006 | |
2007 xml = """ | |
2008 <iq type='set' to='pubsub.example.org' | |
2009 from='user@example.org'> | |
2010 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
2011 <delete node='test'/> | |
2012 </pubsub> | |
2013 </iq> | |
2014 """ | |
2015 | |
2016 request = pubsub.PubSubRequest.fromElement(parseXml(xml)) | |
2017 self.assertEqual('delete', request.verb) | |
2018 self.assertEqual(JID('user@example.org'), request.sender) | |
2019 self.assertEqual(JID('pubsub.example.org'), request.recipient) | |
2020 self.assertEqual('test', request.nodeIdentifier) | |
2021 | |
2022 | |
2023 | |
2024 class PubSubServiceTest(unittest.TestCase, TestableRequestHandlerMixin): | |
2025 """ | |
2026 Tests for L{pubsub.PubSubService}. | |
2027 """ | |
2028 | |
2029 def setUp(self): | |
2030 self.stub = XmlStreamStub() | |
2031 self.resource = pubsub.PubSubResource() | |
2032 self.service = pubsub.PubSubService(self.resource) | |
2033 self.service.send = self.stub.xmlstream.send | |
2034 | |
2035 def test_interface(self): | |
2036 """ | |
2037 Do instances of L{pubsub.PubSubService} provide L{iwokkel.IPubSubService}? | |
2038 """ | |
2039 verify.verifyObject(iwokkel.IPubSubService, self.service) | |
2040 | |
2041 | |
2042 def test_interfaceIDisco(self): | |
2043 """ | |
2044 Do instances of L{pubsub.PubSubService} provide L{iwokkel.IDisco}? | |
2045 """ | |
2046 verify.verifyObject(iwokkel.IDisco, self.service) | |
2047 | |
2048 | |
2049 def test_connectionMade(self): | |
2050 """ | |
2051 Verify setup of observers in L{pubsub.connectionMade}. | |
2052 """ | |
2053 requests = [] | |
2054 | |
2055 def handleRequest(iq): | |
2056 requests.append(iq) | |
2057 | |
2058 self.service.xmlstream = self.stub.xmlstream | |
2059 self.service.handleRequest = handleRequest | |
2060 self.service.connectionMade() | |
2061 | |
2062 for namespace in (NS_PUBSUB, NS_PUBSUB_OWNER): | |
2063 for stanzaType in ('get', 'set'): | |
2064 iq = domish.Element((None, 'iq')) | |
2065 iq['type'] = stanzaType | |
2066 iq.addElement((namespace, 'pubsub')) | |
2067 self.stub.xmlstream.dispatch(iq) | |
2068 | |
2069 self.assertEqual(4, len(requests)) | |
2070 | |
2071 | |
2072 def test_getDiscoInfo(self): | |
2073 """ | |
2074 Test getDiscoInfo calls getNodeInfo and returns some minimal info. | |
2075 """ | |
2076 def cb(info): | |
2077 discoInfo = disco.DiscoInfo() | |
2078 for item in info: | |
2079 discoInfo.append(item) | |
2080 self.assertIn(('pubsub', 'service'), discoInfo.identities) | |
2081 self.assertIn(disco.NS_DISCO_ITEMS, discoInfo.features) | |
2082 | |
2083 d = self.service.getDiscoInfo(JID('user@example.org/home'), | |
2084 JID('pubsub.example.org'), '') | |
2085 d.addCallback(cb) | |
2086 return d | |
2087 | |
2088 | |
2089 def test_getDiscoInfoNodeType(self): | |
2090 """ | |
2091 Test getDiscoInfo with node type. | |
2092 """ | |
2093 def cb(info): | |
2094 discoInfo = disco.DiscoInfo() | |
2095 for item in info: | |
2096 discoInfo.append(item) | |
2097 self.assertIn(('pubsub', 'collection'), discoInfo.identities) | |
2098 | |
2099 def getInfo(requestor, target, nodeIdentifier): | |
2100 return defer.succeed({'type': 'collection', | |
2101 'meta-data': {}}) | |
2102 | |
2103 self.resource.getInfo = getInfo | |
2104 d = self.service.getDiscoInfo(JID('user@example.org/home'), | |
2105 JID('pubsub.example.org'), '') | |
2106 d.addCallback(cb) | |
2107 return d | |
2108 | |
2109 | |
2110 def test_getDiscoInfoMetaData(self): | |
2111 """ | |
2112 Test getDiscoInfo with returned meta data. | |
2113 """ | |
2114 def cb(info): | |
2115 discoInfo = disco.DiscoInfo() | |
2116 for item in info: | |
2117 discoInfo.append(item) | |
2118 | |
2119 self.assertIn(('pubsub', 'leaf'), discoInfo.identities) | |
2120 self.assertIn(NS_PUBSUB_META_DATA, discoInfo.extensions) | |
2121 form = discoInfo.extensions[NS_PUBSUB_META_DATA] | |
2122 self.assertIn('pubsub#node_type', form.fields) | |
2123 | |
2124 def getInfo(requestor, target, nodeIdentifier): | |
2125 metaData = [{'var': 'pubsub#persist_items', | |
2126 'label': 'Persist items to storage', | |
2127 'value': True}] | |
2128 return defer.succeed({'type': 'leaf', 'meta-data': metaData}) | |
2129 | |
2130 self.resource.getInfo = getInfo | |
2131 d = self.service.getDiscoInfo(JID('user@example.org/home'), | |
2132 JID('pubsub.example.org'), '') | |
2133 d.addCallback(cb) | |
2134 return d | |
2135 | |
2136 | |
2137 def test_getDiscoInfoResourceFeatures(self): | |
2138 """ | |
2139 Test getDiscoInfo with the resource features. | |
2140 """ | |
2141 def cb(info): | |
2142 discoInfo = disco.DiscoInfo() | |
2143 for item in info: | |
2144 discoInfo.append(item) | |
2145 self.assertIn('http://jabber.org/protocol/pubsub#publish', | |
2146 discoInfo.features) | |
2147 | |
2148 self.resource.features = ['publish'] | |
2149 d = self.service.getDiscoInfo(JID('user@example.org/home'), | |
2150 JID('pubsub.example.org'), '') | |
2151 d.addCallback(cb) | |
2152 return d | |
2153 | |
2154 | |
2155 def test_getDiscoInfoBadResponse(self): | |
2156 """ | |
2157 If getInfo returns invalid response, it should be logged, then ignored. | |
2158 """ | |
2159 def cb(info): | |
2160 self.assertEquals([], info) | |
2161 self.assertEqual(1, len(self.flushLoggedErrors(TypeError))) | |
2162 | |
2163 def getInfo(requestor, target, nodeIdentifier): | |
2164 return defer.succeed('bad response') | |
2165 | |
2166 self.resource.getInfo = getInfo | |
2167 d = self.service.getDiscoInfo(JID('user@example.org/home'), | |
2168 JID('pubsub.example.org'), 'test') | |
2169 d.addCallback(cb) | |
2170 return d | |
2171 | |
2172 | |
2173 def test_getDiscoInfoException(self): | |
2174 """ | |
2175 If getInfo returns invalid response, it should be logged, then ignored. | |
2176 """ | |
2177 def cb(info): | |
2178 self.assertEquals([], info) | |
2179 self.assertEqual(1, len(self.flushLoggedErrors(NotImplementedError))) | |
2180 | |
2181 def getInfo(requestor, target, nodeIdentifier): | |
2182 return defer.fail(NotImplementedError()) | |
2183 | |
2184 self.resource.getInfo = getInfo | |
2185 d = self.service.getDiscoInfo(JID('user@example.org/home'), | |
2186 JID('pubsub.example.org'), 'test') | |
2187 d.addCallback(cb) | |
2188 return d | |
2189 | |
2190 | |
2191 def test_getDiscoItemsRoot(self): | |
2192 """ | |
2193 Test getDiscoItems on the root node. | |
2194 """ | |
2195 def getNodes(requestor, service, nodeIdentifier): | |
2196 return defer.succeed(['node1', 'node2']) | |
2197 | |
2198 def cb(items): | |
2199 self.assertEqual(2, len(items)) | |
2200 item1, item2 = items | |
2201 | |
2202 self.assertEqual(JID('pubsub.example.org'), item1.entity) | |
2203 self.assertEqual('node1', item1.nodeIdentifier) | |
2204 | |
2205 self.assertEqual(JID('pubsub.example.org'), item2.entity) | |
2206 self.assertEqual('node2', item2.nodeIdentifier) | |
2207 | |
2208 self.resource.getNodes = getNodes | |
2209 d = self.service.getDiscoItems(JID('user@example.org/home'), | |
2210 JID('pubsub.example.org'), | |
2211 '') | |
2212 d.addCallback(cb) | |
2213 return d | |
2214 | |
2215 | |
2216 def test_getDiscoItemsRootHideNodes(self): | |
2217 """ | |
2218 Test getDiscoItems on the root node. | |
2219 """ | |
2220 def getNodes(requestor, service, nodeIdentifier): | |
2221 raise Exception("Unexpected call to getNodes") | |
2222 | |
2223 def cb(items): | |
2224 self.assertEqual([], items) | |
2225 | |
2226 self.service.hideNodes = True | |
2227 self.resource.getNodes = getNodes | |
2228 d = self.service.getDiscoItems(JID('user@example.org/home'), | |
2229 JID('pubsub.example.org'), | |
2230 '') | |
2231 d.addCallback(cb) | |
2232 return d | |
2233 | |
2234 | |
2235 def test_getDiscoItemsNonRoot(self): | |
2236 """ | |
2237 Test getDiscoItems on a non-root node. | |
2238 """ | |
2239 def getNodes(requestor, service, nodeIdentifier): | |
2240 return defer.succeed(['node1', 'node2']) | |
2241 | |
2242 def cb(items): | |
2243 self.assertEqual(2, len(items)) | |
2244 | |
2245 self.resource.getNodes = getNodes | |
2246 d = self.service.getDiscoItems(JID('user@example.org/home'), | |
2247 JID('pubsub.example.org'), | |
2248 'test') | |
2249 d.addCallback(cb) | |
2250 return d | |
2251 | |
2252 | |
2253 def test_on_publish(self): | |
2254 """ | |
2255 A publish request should result in L{PubSubService.publish} being | |
2256 called. | |
2257 """ | |
2258 | |
2259 xml = """ | |
2260 <iq type='set' to='pubsub.example.org' | |
2261 from='user@example.org'> | |
2262 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2263 <publish node='test'/> | |
2264 </pubsub> | |
2265 </iq> | |
2266 """ | |
2267 | |
2268 def publish(request): | |
2269 return defer.succeed(None) | |
2270 | |
2271 self.resource.publish = publish | |
2272 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2273 return self.handleRequest(xml) | |
2274 | |
2275 | |
2276 def test_on_subscribe(self): | |
2277 """ | |
2278 A successful subscription should return the current subscription. | |
2279 """ | |
2280 | |
2281 xml = """ | |
2282 <iq type='set' to='pubsub.example.org' | |
2283 from='user@example.org'> | |
2284 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2285 <subscribe node='test' jid='user@example.org/Home'/> | |
2286 </pubsub> | |
2287 </iq> | |
2288 """ | |
2289 | |
2290 def subscribe(request): | |
2291 return defer.succeed(pubsub.Subscription(request.nodeIdentifier, | |
2292 request.subscriber, | |
2293 'subscribed')) | |
2294 | |
2295 def cb(element): | |
2296 self.assertEqual('pubsub', element.name) | |
2297 self.assertEqual(NS_PUBSUB, element.uri) | |
2298 subscription = element.subscription | |
2299 self.assertEqual(NS_PUBSUB, subscription.uri) | |
2300 self.assertEqual('test', subscription['node']) | |
2301 self.assertEqual('user@example.org/Home', subscription['jid']) | |
2302 self.assertEqual('subscribed', subscription['subscription']) | |
2303 | |
2304 self.resource.subscribe = subscribe | |
2305 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2306 d = self.handleRequest(xml) | |
2307 d.addCallback(cb) | |
2308 return d | |
2309 | |
2310 | |
2311 def test_on_subscribeEmptyNode(self): | |
2312 """ | |
2313 A successful subscription on root node should return no node attribute. | |
2314 """ | |
2315 | |
2316 xml = """ | |
2317 <iq type='set' to='pubsub.example.org' | |
2318 from='user@example.org'> | |
2319 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2320 <subscribe jid='user@example.org/Home'/> | |
2321 </pubsub> | |
2322 </iq> | |
2323 """ | |
2324 | |
2325 def subscribe(request): | |
2326 return defer.succeed(pubsub.Subscription(request.nodeIdentifier, | |
2327 request.subscriber, | |
2328 'subscribed')) | |
2329 | |
2330 def cb(element): | |
2331 self.assertFalse(element.subscription.hasAttribute('node')) | |
2332 | |
2333 self.resource.subscribe = subscribe | |
2334 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2335 d = self.handleRequest(xml) | |
2336 d.addCallback(cb) | |
2337 return d | |
2338 | |
2339 | |
2340 def test_on_subscribeSubscriptionIdentifier(self): | |
2341 """ | |
2342 If a subscription returns a subid, this should be available. | |
2343 """ | |
2344 | |
2345 xml = """ | |
2346 <iq type='set' to='pubsub.example.org' | |
2347 from='user@example.org'> | |
2348 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2349 <subscribe node='test' jid='user@example.org/Home'/> | |
2350 </pubsub> | |
2351 </iq> | |
2352 """ | |
2353 | |
2354 def subscribe(request): | |
2355 subscription = pubsub.Subscription(request.nodeIdentifier, | |
2356 request.subscriber, | |
2357 'subscribed', | |
2358 subscriptionIdentifier='1234') | |
2359 return defer.succeed(subscription) | |
2360 | |
2361 def cb(element): | |
2362 self.assertEqual('1234', element.subscription.getAttribute('subid')) | |
2363 | |
2364 self.resource.subscribe = subscribe | |
2365 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2366 d = self.handleRequest(xml) | |
2367 d.addCallback(cb) | |
2368 return d | |
2369 | |
2370 | |
2371 def test_on_unsubscribe(self): | |
2372 """ | |
2373 A successful unsubscription should return an empty response. | |
2374 """ | |
2375 | |
2376 xml = """ | |
2377 <iq type='set' to='pubsub.example.org' | |
2378 from='user@example.org'> | |
2379 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2380 <unsubscribe node='test' jid='user@example.org/Home'/> | |
2381 </pubsub> | |
2382 </iq> | |
2383 """ | |
2384 | |
2385 def unsubscribe(request): | |
2386 return defer.succeed(None) | |
2387 | |
2388 def cb(element): | |
2389 self.assertIdentical(None, element) | |
2390 | |
2391 self.resource.unsubscribe = unsubscribe | |
2392 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2393 d = self.handleRequest(xml) | |
2394 d.addCallback(cb) | |
2395 return d | |
2396 | |
2397 | |
2398 def test_on_unsubscribeSubscriptionIdentifier(self): | |
2399 """ | |
2400 A successful unsubscription with subid should return an empty response. | |
2401 """ | |
2402 | |
2403 xml = """ | |
2404 <iq type='set' to='pubsub.example.org' | |
2405 from='user@example.org'> | |
2406 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2407 <unsubscribe node='test' jid='user@example.org/Home' subid='1234'/> | |
2408 </pubsub> | |
2409 </iq> | |
2410 """ | |
2411 | |
2412 def unsubscribe(request): | |
2413 self.assertEqual('1234', request.subscriptionIdentifier) | |
2414 return defer.succeed(None) | |
2415 | |
2416 def cb(element): | |
2417 self.assertIdentical(None, element) | |
2418 | |
2419 self.resource.unsubscribe = unsubscribe | |
2420 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2421 d = self.handleRequest(xml) | |
2422 d.addCallback(cb) | |
2423 return d | |
2424 | |
2425 | |
2426 def test_on_optionsGet(self): | |
2427 """ | |
2428 Getting subscription options is not supported. | |
2429 """ | |
2430 | |
2431 xml = """ | |
2432 <iq type='get' to='pubsub.example.org' | |
2433 from='user@example.org'> | |
2434 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2435 <options node='test' jid='user@example.org/Home'/> | |
2436 </pubsub> | |
2437 </iq> | |
2438 """ | |
2439 | |
2440 def cb(result): | |
2441 self.assertEquals('feature-not-implemented', result.condition) | |
2442 self.assertEquals('unsupported', result.appCondition.name) | |
2443 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
2444 | |
2445 d = self.handleRequest(xml) | |
2446 self.assertFailure(d, error.StanzaError) | |
2447 d.addCallback(cb) | |
2448 return d | |
2449 | |
2450 | |
2451 def test_on_optionsSet(self): | |
2452 """ | |
2453 Setting subscription options is not supported. | |
2454 """ | |
2455 | |
2456 xml = """ | |
2457 <iq type='set' to='pubsub.example.org' | |
2458 from='user@example.org'> | |
2459 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2460 <options node='test' jid='user@example.org/Home'> | |
2461 <x xmlns='jabber:x:data' type='submit'> | |
2462 <field var='FORM_TYPE' type='hidden'> | |
2463 <value>http://jabber.org/protocol/pubsub#subscribe_options</value> | |
2464 </field> | |
2465 <field var='pubsub#deliver'><value>1</value></field> | |
2466 </x> | |
2467 </options> | |
2468 </pubsub> | |
2469 </iq> | |
2470 """ | |
2471 | |
2472 def cb(result): | |
2473 self.assertEquals('feature-not-implemented', result.condition) | |
2474 self.assertEquals('unsupported', result.appCondition.name) | |
2475 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
2476 | |
2477 d = self.handleRequest(xml) | |
2478 self.assertFailure(d, error.StanzaError) | |
2479 d.addCallback(cb) | |
2480 return d | |
2481 | |
2482 | |
2483 def test_on_subscriptions(self): | |
2484 """ | |
2485 A subscriptions request should result in | |
2486 L{PubSubService.subscriptions} being called and the result prepared | |
2487 for the response. | |
2488 """ | |
2489 | |
2490 xml = """ | |
2491 <iq type='get' to='pubsub.example.org' | |
2492 from='user@example.org'> | |
2493 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2494 <subscriptions/> | |
2495 </pubsub> | |
2496 </iq> | |
2497 """ | |
2498 | |
2499 def subscriptions(request): | |
2500 subscription = pubsub.Subscription('test', JID('user@example.org'), | |
2501 'subscribed') | |
2502 return defer.succeed([subscription]) | |
2503 | |
2504 def cb(element): | |
2505 self.assertEqual('pubsub', element.name) | |
2506 self.assertEqual(NS_PUBSUB, element.uri) | |
2507 self.assertEqual(NS_PUBSUB, element.subscriptions.uri) | |
2508 children = list(element.subscriptions.elements()) | |
2509 self.assertEqual(1, len(children)) | |
2510 subscription = children[0] | |
2511 self.assertEqual('subscription', subscription.name) | |
2512 self.assertEqual(NS_PUBSUB, subscription.uri, NS_PUBSUB) | |
2513 self.assertEqual('user@example.org', subscription['jid']) | |
2514 self.assertEqual('test', subscription['node']) | |
2515 self.assertEqual('subscribed', subscription['subscription']) | |
2516 | |
2517 self.resource.subscriptions = subscriptions | |
2518 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2519 d = self.handleRequest(xml) | |
2520 d.addCallback(cb) | |
2521 return d | |
2522 | |
2523 | |
2524 def test_on_subscriptionsWithSubscriptionIdentifier(self): | |
2525 """ | |
2526 A subscriptions request response should include subids, if set. | |
2527 """ | |
2528 | |
2529 xml = """ | |
2530 <iq type='get' to='pubsub.example.org' | |
2531 from='user@example.org'> | |
2532 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2533 <subscriptions/> | |
2534 </pubsub> | |
2535 </iq> | |
2536 """ | |
2537 | |
2538 def subscriptions(request): | |
2539 subscription = pubsub.Subscription('test', JID('user@example.org'), | |
2540 'subscribed', | |
2541 subscriptionIdentifier='1234') | |
2542 return defer.succeed([subscription]) | |
2543 | |
2544 def cb(element): | |
2545 subscription = element.subscriptions.subscription | |
2546 self.assertEqual('1234', subscription['subid']) | |
2547 | |
2548 self.resource.subscriptions = subscriptions | |
2549 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2550 d = self.handleRequest(xml) | |
2551 d.addCallback(cb) | |
2552 return d | |
2553 | |
2554 | |
2555 def test_on_affiliations(self): | |
2556 """ | |
2557 A subscriptions request should result in | |
2558 L{PubSubService.affiliations} being called and the result prepared | |
2559 for the response. | |
2560 """ | |
2561 | |
2562 xml = """ | |
2563 <iq type='get' to='pubsub.example.org' | |
2564 from='user@example.org'> | |
2565 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2566 <affiliations/> | |
2567 </pubsub> | |
2568 </iq> | |
2569 """ | |
2570 | |
2571 def affiliations(request): | |
2572 affiliation = ('test', 'owner') | |
2573 return defer.succeed([affiliation]) | |
2574 | |
2575 def cb(element): | |
2576 self.assertEqual('pubsub', element.name) | |
2577 self.assertEqual(NS_PUBSUB, element.uri) | |
2578 self.assertEqual(NS_PUBSUB, element.affiliations.uri) | |
2579 children = list(element.affiliations.elements()) | |
2580 self.assertEqual(1, len(children)) | |
2581 affiliation = children[0] | |
2582 self.assertEqual('affiliation', affiliation.name) | |
2583 self.assertEqual(NS_PUBSUB, affiliation.uri) | |
2584 self.assertEqual('test', affiliation['node']) | |
2585 self.assertEqual('owner', affiliation['affiliation']) | |
2586 | |
2587 self.resource.affiliations = affiliations | |
2588 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2589 d = self.handleRequest(xml) | |
2590 d.addCallback(cb) | |
2591 return d | |
2592 | |
2593 | |
2594 def test_on_create(self): | |
2595 """ | |
2596 Replies to create node requests don't return the created node. | |
2597 """ | |
2598 | |
2599 xml = """ | |
2600 <iq type='set' to='pubsub.example.org' | |
2601 from='user@example.org'> | |
2602 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2603 <create node='mynode'/> | |
2604 </pubsub> | |
2605 </iq> | |
2606 """ | |
2607 | |
2608 def create(request): | |
2609 return defer.succeed(request.nodeIdentifier) | |
2610 | |
2611 def cb(element): | |
2612 self.assertIdentical(None, element) | |
2613 | |
2614 self.resource.create = create | |
2615 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2616 d = self.handleRequest(xml) | |
2617 d.addCallback(cb) | |
2618 return d | |
2619 | |
2620 | |
2621 def test_on_createChanged(self): | |
2622 """ | |
2623 Replies to create node requests return the created node if changed. | |
2624 """ | |
2625 | |
2626 xml = """ | |
2627 <iq type='set' to='pubsub.example.org' | |
2628 from='user@example.org'> | |
2629 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2630 <create node='mynode'/> | |
2631 </pubsub> | |
2632 </iq> | |
2633 """ | |
2634 | |
2635 def create(request): | |
2636 return defer.succeed(u'myrenamednode') | |
2637 | |
2638 def cb(element): | |
2639 self.assertEqual('pubsub', element.name) | |
2640 self.assertEqual(NS_PUBSUB, element.uri) | |
2641 self.assertEqual(NS_PUBSUB, element.create.uri) | |
2642 self.assertEqual(u'myrenamednode', | |
2643 element.create.getAttribute('node')) | |
2644 | |
2645 self.resource.create = create | |
2646 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2647 d = self.handleRequest(xml) | |
2648 d.addCallback(cb) | |
2649 return d | |
2650 | |
2651 | |
2652 def test_on_createInstant(self): | |
2653 """ | |
2654 Replies to create instant node requests return the created node. | |
2655 """ | |
2656 | |
2657 xml = """ | |
2658 <iq type='set' to='pubsub.example.org' | |
2659 from='user@example.org'> | |
2660 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2661 <create/> | |
2662 </pubsub> | |
2663 </iq> | |
2664 """ | |
2665 | |
2666 def create(request): | |
2667 return defer.succeed(u'random') | |
2668 | |
2669 def cb(element): | |
2670 self.assertEqual('pubsub', element.name) | |
2671 self.assertEqual(NS_PUBSUB, element.uri) | |
2672 self.assertEqual(NS_PUBSUB, element.create.uri) | |
2673 self.assertEqual(u'random', element.create.getAttribute('node')) | |
2674 | |
2675 self.resource.create = create | |
2676 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2677 d = self.handleRequest(xml) | |
2678 d.addCallback(cb) | |
2679 return d | |
2680 | |
2681 | |
2682 def test_on_createWithConfig(self): | |
2683 """ | |
2684 On a node create with configuration request the Data Form is parsed and | |
2685 L{PubSubResource.create} is called with the passed options. | |
2686 """ | |
2687 | |
2688 xml = """ | |
2689 <iq type='set' to='pubsub.example.org' | |
2690 from='user@example.org'> | |
2691 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
2692 <create node='mynode'/> | |
2693 <configure> | |
2694 <x xmlns='jabber:x:data' type='submit'> | |
2695 <field var='FORM_TYPE' type='hidden'> | |
2696 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
2697 </field> | |
2698 <field var='pubsub#deliver_payloads'><value>0</value></field> | |
2699 <field var='pubsub#persist_items'><value>1</value></field> | |
2700 </x> | |
2701 </configure> | |
2702 </pubsub> | |
2703 </iq> | |
2704 """ | |
2705 | |
2706 def getConfigurationOptions(): | |
2707 return { | |
2708 "pubsub#persist_items": | |
2709 {"type": "boolean", | |
2710 "label": "Persist items to storage"}, | |
2711 "pubsub#deliver_payloads": | |
2712 {"type": "boolean", | |
2713 "label": "Deliver payloads with event notifications"} | |
2714 } | |
2715 | |
2716 def create(request): | |
2717 self.assertEqual({'pubsub#deliver_payloads': False, | |
2718 'pubsub#persist_items': True}, | |
2719 request.options.getValues()) | |
2720 return defer.succeed(None) | |
2721 | |
2722 self.resource.getConfigurationOptions = getConfigurationOptions | |
2723 self.resource.create = create | |
2724 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2725 return self.handleRequest(xml) | |
2726 | |
2727 | |
2728 def test_on_default(self): | |
2729 """ | |
2730 A default request returns default options filtered by available fields. | |
2731 """ | |
2732 | |
2733 xml = """ | |
2734 <iq type='get' to='pubsub.example.org' | |
2735 from='user@example.org'> | |
2736 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
2737 <default/> | |
2738 </pubsub> | |
2739 </iq> | |
2740 """ | |
2741 fieldDefs = { | |
2742 "pubsub#persist_items": | |
2743 {"type": "boolean", | |
2744 "label": "Persist items to storage"}, | |
2745 "pubsub#deliver_payloads": | |
2746 {"type": "boolean", | |
2747 "label": "Deliver payloads with event notifications"} | |
2748 } | |
2749 | |
2750 def getConfigurationOptions(): | |
2751 return fieldDefs | |
2752 | |
2753 def default(request): | |
2754 return defer.succeed({'pubsub#persist_items': 'false', | |
2755 'x-myfield': '1'}) | |
2756 | |
2757 def cb(element): | |
2758 self.assertEquals('pubsub', element.name) | |
2759 self.assertEquals(NS_PUBSUB_OWNER, element.uri) | |
2760 self.assertEquals(NS_PUBSUB_OWNER, element.default.uri) | |
2761 form = data_form.Form.fromElement(element.default.x) | |
2762 self.assertEquals(NS_PUBSUB_NODE_CONFIG, form.formNamespace) | |
2763 form.typeCheck(fieldDefs) | |
2764 self.assertIn('pubsub#persist_items', form.fields) | |
2765 self.assertFalse(form.fields['pubsub#persist_items'].value) | |
2766 self.assertNotIn('x-myfield', form.fields) | |
2767 | |
2768 self.resource.getConfigurationOptions = getConfigurationOptions | |
2769 self.resource.default = default | |
2770 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2771 d = self.handleRequest(xml) | |
2772 d.addCallback(cb) | |
2773 return d | |
2774 | |
2775 | |
2776 def test_on_defaultUnknownNodeType(self): | |
2777 """ | |
2778 Unknown node types yield non-acceptable. | |
2779 | |
2780 Both C{getConfigurationOptions} and C{default} must not be called. | |
2781 """ | |
2782 | |
2783 xml = """ | |
2784 <iq type='get' to='pubsub.example.org' | |
2785 from='user@example.org'> | |
2786 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
2787 <default> | |
2788 <x xmlns='jabber:x:data' type='submit'> | |
2789 <field var='FORM_TYPE' type='hidden'> | |
2790 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
2791 </field> | |
2792 <field var='pubsub#node_type'> | |
2793 <value>unknown</value> | |
2794 </field> | |
2795 </x> | |
2796 </default> | |
2797 | |
2798 </pubsub> | |
2799 </iq> | |
2800 """ | |
2801 | |
2802 def getConfigurationOptions(): | |
2803 self.fail("Unexpected call to getConfigurationOptions") | |
2804 | |
2805 def default(request): | |
2806 self.fail("Unexpected call to default") | |
2807 | |
2808 def cb(result): | |
2809 self.assertEquals('not-acceptable', result.condition) | |
2810 | |
2811 self.resource.getConfigurationOptions = getConfigurationOptions | |
2812 self.resource.default = default | |
2813 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2814 d = self.handleRequest(xml) | |
2815 self.assertFailure(d, error.StanzaError) | |
2816 d.addCallback(cb) | |
2817 return d | |
2818 | |
2819 | |
2820 def test_on_configureGet(self): | |
2821 """ | |
2822 On a node configuration get | |
2823 requestL{PubSubResource.configureGet} is called and results in a | |
2824 data form with the configuration. | |
2825 """ | |
2826 | |
2827 xml = """ | |
2828 <iq type='get' to='pubsub.example.org' | |
2829 from='user@example.org'> | |
2830 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
2831 <configure node='test'/> | |
2832 </pubsub> | |
2833 </iq> | |
2834 """ | |
2835 | |
2836 def getConfigurationOptions(): | |
2837 return { | |
2838 "pubsub#persist_items": | |
2839 {"type": "boolean", | |
2840 "label": "Persist items to storage"}, | |
2841 "pubsub#deliver_payloads": | |
2842 {"type": "boolean", | |
2843 "label": "Deliver payloads with event notifications"}, | |
2844 "pubsub#owner": | |
2845 {"type": "jid-single", | |
2846 "label": "Owner of the node"} | |
2847 } | |
2848 | |
2849 def configureGet(request): | |
2850 return defer.succeed({'pubsub#deliver_payloads': '0', | |
2851 'pubsub#persist_items': '1', | |
2852 'pubsub#owner': JID('user@example.org'), | |
2853 'x-myfield': 'a'}) | |
2854 | |
2855 def cb(element): | |
2856 self.assertEqual('pubsub', element.name) | |
2857 self.assertEqual(NS_PUBSUB_OWNER, element.uri) | |
2858 self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri) | |
2859 form = data_form.Form.fromElement(element.configure.x) | |
2860 self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace) | |
2861 fields = form.fields | |
2862 | |
2863 self.assertIn('pubsub#deliver_payloads', fields) | |
2864 field = fields['pubsub#deliver_payloads'] | |
2865 self.assertEqual('boolean', field.fieldType) | |
2866 field.typeCheck() | |
2867 self.assertEqual(False, field.value) | |
2868 | |
2869 self.assertIn('pubsub#persist_items', fields) | |
2870 field = fields['pubsub#persist_items'] | |
2871 self.assertEqual('boolean', field.fieldType) | |
2872 field.typeCheck() | |
2873 self.assertEqual(True, field.value) | |
2874 | |
2875 self.assertIn('pubsub#owner', fields) | |
2876 field = fields['pubsub#owner'] | |
2877 self.assertEqual('jid-single', field.fieldType) | |
2878 field.typeCheck() | |
2879 self.assertEqual(JID('user@example.org'), field.value) | |
2880 | |
2881 self.assertNotIn('x-myfield', fields) | |
2882 | |
2883 self.resource.getConfigurationOptions = getConfigurationOptions | |
2884 self.resource.configureGet = configureGet | |
2885 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2886 d = self.handleRequest(xml) | |
2887 d.addCallback(cb) | |
2888 return d | |
2889 | |
2890 | |
2891 def test_on_configureSet(self): | |
2892 """ | |
2893 On a node configuration set request the Data Form is parsed and | |
2894 L{PubSubResource.configureSet} is called with the passed options. | |
2895 """ | |
2896 | |
2897 xml = """ | |
2898 <iq type='set' to='pubsub.example.org' | |
2899 from='user@example.org'> | |
2900 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
2901 <configure node='test'> | |
2902 <x xmlns='jabber:x:data' type='submit'> | |
2903 <field var='FORM_TYPE' type='hidden'> | |
2904 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
2905 </field> | |
2906 <field var='pubsub#deliver_payloads'><value>0</value></field> | |
2907 <field var='pubsub#persist_items'><value>1</value></field> | |
2908 </x> | |
2909 </configure> | |
2910 </pubsub> | |
2911 </iq> | |
2912 """ | |
2913 | |
2914 def getConfigurationOptions(): | |
2915 return { | |
2916 "pubsub#persist_items": | |
2917 {"type": "boolean", | |
2918 "label": "Persist items to storage"}, | |
2919 "pubsub#deliver_payloads": | |
2920 {"type": "boolean", | |
2921 "label": "Deliver payloads with event notifications"} | |
2922 } | |
2923 | |
2924 def configureSet(request): | |
2925 self.assertEqual({'pubsub#deliver_payloads': False, | |
2926 'pubsub#persist_items': True}, | |
2927 request.options.getValues()) | |
2928 return defer.succeed(None) | |
2929 | |
2930 self.resource.getConfigurationOptions = getConfigurationOptions | |
2931 self.resource.configureSet = configureSet | |
2932 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2933 return self.handleRequest(xml) | |
2934 | |
2935 | |
2936 def test_on_configureSetCancel(self): | |
2937 """ | |
2938 The node configuration is cancelled, | |
2939 L{PubSubResource.configureSet} not called. | |
2940 """ | |
2941 | |
2942 xml = """ | |
2943 <iq type='set' to='pubsub.example.org' | |
2944 from='user@example.org'> | |
2945 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
2946 <configure node='test'> | |
2947 <x xmlns='jabber:x:data' type='cancel'> | |
2948 <field var='FORM_TYPE' type='hidden'> | |
2949 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
2950 </field> | |
2951 </x> | |
2952 </configure> | |
2953 </pubsub> | |
2954 </iq> | |
2955 """ | |
2956 | |
2957 def configureSet(request): | |
2958 self.fail("Unexpected call to setConfiguration") | |
2959 | |
2960 self.resource.configureSet = configureSet | |
2961 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
2962 return self.handleRequest(xml) | |
2963 | |
2964 | |
2965 def test_on_configureSetIgnoreUnknown(self): | |
2966 """ | |
2967 On a node configuration set request unknown fields should be ignored. | |
2968 """ | |
2969 | |
2970 xml = """ | |
2971 <iq type='set' to='pubsub.example.org' | |
2972 from='user@example.org'> | |
2973 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
2974 <configure node='test'> | |
2975 <x xmlns='jabber:x:data' type='submit'> | |
2976 <field var='FORM_TYPE' type='hidden'> | |
2977 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
2978 </field> | |
2979 <field var='pubsub#deliver_payloads'><value>0</value></field> | |
2980 <field var='x-myfield'><value>1</value></field> | |
2981 </x> | |
2982 </configure> | |
2983 </pubsub> | |
2984 </iq> | |
2985 """ | |
2986 | |
2987 def getConfigurationOptions(): | |
2988 return { | |
2989 "pubsub#persist_items": | |
2990 {"type": "boolean", | |
2991 "label": "Persist items to storage"}, | |
2992 "pubsub#deliver_payloads": | |
2993 {"type": "boolean", | |
2994 "label": "Deliver payloads with event notifications"} | |
2995 } | |
2996 | |
2997 def configureSet(request): | |
2998 self.assertEquals(['pubsub#deliver_payloads'], | |
2999 request.options.keys()) | |
3000 | |
3001 self.resource.getConfigurationOptions = getConfigurationOptions | |
3002 self.resource.configureSet = configureSet | |
3003 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
3004 return self.handleRequest(xml) | |
3005 | |
3006 | |
3007 def test_on_configureSetBadFormType(self): | |
3008 """ | |
3009 On a node configuration set request unknown fields should be ignored. | |
3010 """ | |
3011 | |
3012 xml = """ | |
3013 <iq type='set' to='pubsub.example.org' | |
3014 from='user@example.org'> | |
3015 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3016 <configure node='test'> | |
3017 <x xmlns='jabber:x:data' type='result'> | |
3018 <field var='FORM_TYPE' type='hidden'> | |
3019 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
3020 </field> | |
3021 <field var='pubsub#deliver_payloads'><value>0</value></field> | |
3022 <field var='x-myfield'><value>1</value></field> | |
3023 </x> | |
3024 </configure> | |
3025 </pubsub> | |
3026 </iq> | |
3027 """ | |
3028 | |
3029 def cb(result): | |
3030 self.assertEquals('bad-request', result.condition) | |
3031 self.assertEqual("Unexpected form type 'result'", result.text) | |
3032 | |
3033 d = self.handleRequest(xml) | |
3034 self.assertFailure(d, error.StanzaError) | |
3035 d.addCallback(cb) | |
3036 return d | |
3037 | |
3038 | |
3039 def test_on_items(self): | |
3040 """ | |
3041 On a items request, return all items for the given node. | |
3042 """ | |
3043 xml = """ | |
3044 <iq type='get' to='pubsub.example.org' | |
3045 from='user@example.org'> | |
3046 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3047 <items node='test'/> | |
3048 </pubsub> | |
3049 </iq> | |
3050 """ | |
3051 | |
3052 def items(request): | |
3053 return defer.succeed([pubsub.Item('current')]) | |
3054 | |
3055 def cb(element): | |
3056 self.assertEqual(NS_PUBSUB, element.uri) | |
3057 self.assertEqual(NS_PUBSUB, element.items.uri) | |
3058 self.assertEqual(1, len(element.items.children)) | |
3059 item = element.items.children[-1] | |
3060 self.assertTrue(domish.IElement.providedBy(item)) | |
3061 self.assertEqual('item', item.name) | |
3062 self.assertEqual(NS_PUBSUB, item.uri) | |
3063 self.assertEqual('current', item['id']) | |
3064 | |
3065 self.resource.items = items | |
3066 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
3067 d = self.handleRequest(xml) | |
3068 d.addCallback(cb) | |
3069 return d | |
3070 | |
3071 | |
3072 def test_on_retract(self): | |
3073 """ | |
3074 A retract request should result in L{PubSubResource.retract} | |
3075 being called. | |
3076 """ | |
3077 | |
3078 xml = """ | |
3079 <iq type='set' to='pubsub.example.org' | |
3080 from='user@example.org'> | |
3081 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3082 <retract node='test'> | |
3083 <item id='item1'/> | |
3084 <item id='item2'/> | |
3085 </retract> | |
3086 </pubsub> | |
3087 </iq> | |
3088 """ | |
3089 | |
3090 def retract(request): | |
3091 return defer.succeed(None) | |
3092 | |
3093 self.resource.retract = retract | |
3094 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
3095 return self.handleRequest(xml) | |
3096 | |
3097 | |
3098 def test_on_purge(self): | |
3099 """ | |
3100 A purge request should result in L{PubSubResource.purge} being | |
3101 called. | |
3102 """ | |
3103 | |
3104 xml = """ | |
3105 <iq type='set' to='pubsub.example.org' | |
3106 from='user@example.org'> | |
3107 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3108 <purge node='test'/> | |
3109 </pubsub> | |
3110 </iq> | |
3111 """ | |
3112 | |
3113 def purge(request): | |
3114 return defer.succeed(None) | |
3115 | |
3116 self.resource.purge = purge | |
3117 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
3118 return self.handleRequest(xml) | |
3119 | |
3120 | |
3121 def test_on_delete(self): | |
3122 """ | |
3123 A delete request should result in L{PubSubResource.delete} being | |
3124 called. | |
3125 """ | |
3126 | |
3127 xml = """ | |
3128 <iq type='set' to='pubsub.example.org' | |
3129 from='user@example.org'> | |
3130 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3131 <delete node='test'/> | |
3132 </pubsub> | |
3133 </iq> | |
3134 """ | |
3135 | |
3136 def delete(request): | |
3137 return defer.succeed(None) | |
3138 | |
3139 self.resource.delete = delete | |
3140 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
3141 return self.handleRequest(xml) | |
3142 | |
3143 | |
3144 def test_notifyPublish(self): | |
3145 """ | |
3146 Publish notifications are sent to the subscribers. | |
3147 """ | |
3148 subscriber = JID('user@example.org') | |
3149 subscriptions = [pubsub.Subscription('test', subscriber, 'subscribed')] | |
3150 items = [pubsub.Item('current')] | |
3151 notifications = [(subscriber, subscriptions, items)] | |
3152 self.service.notifyPublish(JID('pubsub.example.org'), 'test', | |
3153 notifications) | |
3154 message = self.stub.output[-1] | |
3155 | |
3156 self.assertEquals('message', message.name) | |
3157 self.assertIdentical(None, message.uri) | |
3158 self.assertEquals('user@example.org', message['to']) | |
3159 self.assertEquals('pubsub.example.org', message['from']) | |
3160 self.assertTrue(message.event) | |
3161 self.assertEquals(NS_PUBSUB_EVENT, message.event.uri) | |
3162 self.assertTrue(message.event.items) | |
3163 self.assertEquals(NS_PUBSUB_EVENT, message.event.items.uri) | |
3164 self.assertTrue(message.event.items.hasAttribute('node')) | |
3165 self.assertEquals('test', message.event.items['node']) | |
3166 itemElements = list(domish.generateElementsQNamed( | |
3167 message.event.items.children, 'item', NS_PUBSUB_EVENT)) | |
3168 self.assertEquals(1, len(itemElements)) | |
3169 self.assertEquals('current', itemElements[0].getAttribute('id')) | |
3170 | |
3171 | |
3172 def test_notifyPublishCollection(self): | |
3173 """ | |
3174 Publish notifications are sent to the subscribers of collections. | |
3175 | |
3176 The node the item was published to is on the C{items} element, while | |
3177 the subscribed-to node is in the C{'Collections'} SHIM header. | |
3178 """ | |
3179 subscriber = JID('user@example.org') | |
3180 subscriptions = [pubsub.Subscription('', subscriber, 'subscribed')] | |
3181 items = [pubsub.Item('current')] | |
3182 notifications = [(subscriber, subscriptions, items)] | |
3183 self.service.notifyPublish(JID('pubsub.example.org'), 'test', | |
3184 notifications) | |
3185 message = self.stub.output[-1] | |
3186 | |
3187 self.assertTrue(message.event.items.hasAttribute('node')) | |
3188 self.assertEquals('test', message.event.items['node']) | |
3189 headers = shim.extractHeaders(message) | |
3190 self.assertIn('Collection', headers) | |
3191 self.assertIn('', headers['Collection']) | |
3192 | |
3193 | |
3194 def test_notifyDelete(self): | |
3195 """ | |
3196 Subscribers should be sent a delete notification. | |
3197 """ | |
3198 subscriptions = [JID('user@example.org')] | |
3199 self.service.notifyDelete(JID('pubsub.example.org'), 'test', | |
3200 subscriptions) | |
3201 message = self.stub.output[-1] | |
3202 | |
3203 self.assertEquals('message', message.name) | |
3204 self.assertIdentical(None, message.uri) | |
3205 self.assertEquals('user@example.org', message['to']) | |
3206 self.assertEquals('pubsub.example.org', message['from']) | |
3207 self.assertTrue(message.event) | |
3208 self.assertEqual(NS_PUBSUB_EVENT, message.event.uri) | |
3209 self.assertTrue(message.event.delete) | |
3210 self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri) | |
3211 self.assertTrue(message.event.delete.hasAttribute('node')) | |
3212 self.assertEqual('test', message.event.delete['node']) | |
3213 | |
3214 | |
3215 def test_notifyDeleteRedirect(self): | |
3216 """ | |
3217 Subscribers should be sent a delete notification with redirect. | |
3218 """ | |
3219 redirectURI = 'xmpp:pubsub.example.org?;node=test2' | |
3220 subscriptions = [JID('user@example.org')] | |
3221 self.service.notifyDelete(JID('pubsub.example.org'), 'test', | |
3222 subscriptions, redirectURI) | |
3223 message = self.stub.output[-1] | |
3224 | |
3225 self.assertEquals('message', message.name) | |
3226 self.assertIdentical(None, message.uri) | |
3227 self.assertEquals('user@example.org', message['to']) | |
3228 self.assertEquals('pubsub.example.org', message['from']) | |
3229 self.assertTrue(message.event) | |
3230 self.assertEqual(NS_PUBSUB_EVENT, message.event.uri) | |
3231 self.assertTrue(message.event.delete) | |
3232 self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri) | |
3233 self.assertTrue(message.event.delete.hasAttribute('node')) | |
3234 self.assertEqual('test', message.event.delete['node']) | |
3235 self.assertTrue(message.event.delete.redirect) | |
3236 self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri) | |
3237 self.assertTrue(message.event.delete.redirect.hasAttribute('uri')) | |
3238 self.assertEqual(redirectURI, message.event.delete.redirect['uri']) | |
3239 | |
3240 | |
3241 def test_on_subscriptionsGet(self): | |
3242 """ | |
3243 Getting subscription options is not supported. | |
3244 """ | |
3245 | |
3246 xml = """ | |
3247 <iq type='get' to='pubsub.example.org' | |
3248 from='user@example.org'> | |
3249 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3250 <subscriptions/> | |
3251 </pubsub> | |
3252 </iq> | |
3253 """ | |
3254 | |
3255 def cb(result): | |
3256 self.assertEquals('feature-not-implemented', result.condition) | |
3257 self.assertEquals('unsupported', result.appCondition.name) | |
3258 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3259 self.assertEquals('manage-subscriptions', | |
3260 result.appCondition['feature']) | |
3261 | |
3262 d = self.handleRequest(xml) | |
3263 self.assertFailure(d, error.StanzaError) | |
3264 d.addCallback(cb) | |
3265 return d | |
3266 | |
3267 | |
3268 def test_on_subscriptionsSet(self): | |
3269 """ | |
3270 Setting subscription options is not supported. | |
3271 """ | |
3272 | |
3273 xml = """ | |
3274 <iq type='set' to='pubsub.example.org' | |
3275 from='user@example.org'> | |
3276 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3277 <subscriptions/> | |
3278 </pubsub> | |
3279 </iq> | |
3280 """ | |
3281 | |
3282 def cb(result): | |
3283 self.assertEquals('feature-not-implemented', result.condition) | |
3284 self.assertEquals('unsupported', result.appCondition.name) | |
3285 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3286 self.assertEquals('manage-subscriptions', | |
3287 result.appCondition['feature']) | |
3288 | |
3289 d = self.handleRequest(xml) | |
3290 self.assertFailure(d, error.StanzaError) | |
3291 d.addCallback(cb) | |
3292 return d | |
3293 | |
3294 | |
3295 def test_on_affiliationsGet(self): | |
3296 """ | |
3297 Getting node affiliations should have. | |
3298 """ | |
3299 | |
3300 xml = """ | |
3301 <iq type='get' to='pubsub.example.org' | |
3302 from='user@example.org'> | |
3303 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3304 <affiliations node='test'/> | |
3305 </pubsub> | |
3306 </iq> | |
3307 """ | |
3308 | |
3309 def affiliationsGet(request): | |
3310 self.assertEquals('test', request.nodeIdentifier) | |
3311 return defer.succeed({JID('user@example.org'): 'owner'}) | |
3312 | |
3313 def cb(element): | |
3314 self.assertEquals(u'pubsub', element.name) | |
3315 self.assertEquals(NS_PUBSUB_OWNER, element.uri) | |
3316 self.assertEquals(NS_PUBSUB_OWNER, element.affiliations.uri) | |
3317 self.assertEquals(u'test', element.affiliations[u'node']) | |
3318 children = list(element.affiliations.elements()) | |
3319 self.assertEquals(1, len(children)) | |
3320 affiliation = children[0] | |
3321 self.assertEquals(u'affiliation', affiliation.name) | |
3322 self.assertEquals(NS_PUBSUB_OWNER, affiliation.uri) | |
3323 self.assertEquals(u'user@example.org', affiliation[u'jid']) | |
3324 self.assertEquals(u'owner', affiliation[u'affiliation']) | |
3325 | |
3326 self.resource.affiliationsGet = affiliationsGet | |
3327 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
3328 d = self.handleRequest(xml) | |
3329 d.addCallback(cb) | |
3330 return d | |
3331 | |
3332 | |
3333 def test_on_affiliationsGetEmptyNode(self): | |
3334 """ | |
3335 Getting node affiliations without node should assume empty node. | |
3336 """ | |
3337 | |
3338 xml = """ | |
3339 <iq type='get' to='pubsub.example.org' | |
3340 from='user@example.org'> | |
3341 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3342 <affiliations/> | |
3343 </pubsub> | |
3344 </iq> | |
3345 """ | |
3346 | |
3347 def affiliationsGet(request): | |
3348 self.assertEqual('', request.nodeIdentifier) | |
3349 return defer.succeed({}) | |
3350 | |
3351 def cb(element): | |
3352 self.assertFalse(element.affiliations.hasAttribute(u'node')) | |
3353 | |
3354 self.resource.affiliationsGet = affiliationsGet | |
3355 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
3356 d = self.handleRequest(xml) | |
3357 d.addCallback(cb) | |
3358 return d | |
3359 | |
3360 | |
3361 def test_on_affiliationsSet(self): | |
3362 """ | |
3363 Setting node affiliations has the affiliations to be modified. | |
3364 """ | |
3365 | |
3366 xml = """ | |
3367 <iq type='set' to='pubsub.example.org' | |
3368 from='user@example.org'> | |
3369 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3370 <affiliations node='test'> | |
3371 <affiliation jid='other@example.org' affiliation='publisher'/> | |
3372 </affiliations> | |
3373 </pubsub> | |
3374 </iq> | |
3375 """ | |
3376 | |
3377 def affiliationsSet(request): | |
3378 self.assertEquals(u'test', request.nodeIdentifier) | |
3379 otherJID = JID(u'other@example.org') | |
3380 self.assertIn(otherJID, request.affiliations) | |
3381 self.assertEquals(u'publisher', request.affiliations[otherJID]) | |
3382 | |
3383 self.resource.affiliationsSet = affiliationsSet | |
3384 return self.handleRequest(xml) | |
3385 | |
3386 | |
3387 def test_on_affiliationsSetBareJID(self): | |
3388 """ | |
3389 Affiliations are always on the bare JID. | |
3390 """ | |
3391 | |
3392 xml = """ | |
3393 <iq type='set' to='pubsub.example.org' | |
3394 from='user@example.org'> | |
3395 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3396 <affiliations node='test'> | |
3397 <affiliation jid='other@example.org/Home' | |
3398 affiliation='publisher'/> | |
3399 </affiliations> | |
3400 </pubsub> | |
3401 </iq> | |
3402 """ | |
3403 | |
3404 def affiliationsSet(request): | |
3405 otherJID = JID(u'other@example.org') | |
3406 self.assertIn(otherJID, request.affiliations) | |
3407 | |
3408 self.resource.affiliationsSet = affiliationsSet | |
3409 return self.handleRequest(xml) | |
3410 | |
3411 | |
3412 def test_on_affiliationsSetMultipleForSameEntity(self): | |
3413 """ | |
3414 Setting node affiliations can only have one item per entity. | |
3415 """ | |
3416 | |
3417 xml = """ | |
3418 <iq type='set' to='pubsub.example.org' | |
3419 from='user@example.org'> | |
3420 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3421 <affiliations node='test'> | |
3422 <affiliation jid='other@example.org' affiliation='publisher'/> | |
3423 <affiliation jid='other@example.org' affiliation='owner'/> | |
3424 </affiliations> | |
3425 </pubsub> | |
3426 </iq> | |
3427 """ | |
3428 | |
3429 def cb(result): | |
3430 self.assertEquals('bad-request', result.condition) | |
3431 | |
3432 d = self.handleRequest(xml) | |
3433 self.assertFailure(d, error.StanzaError) | |
3434 d.addCallback(cb) | |
3435 return d | |
3436 | |
3437 | |
3438 def test_on_affiliationsSetMissingJID(self): | |
3439 """ | |
3440 Setting node affiliations must include a JID per affiliation. | |
3441 """ | |
3442 | |
3443 xml = """ | |
3444 <iq type='set' to='pubsub.example.org' | |
3445 from='user@example.org'> | |
3446 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3447 <affiliations node='test'> | |
3448 <affiliation affiliation='publisher'/> | |
3449 </affiliations> | |
3450 </pubsub> | |
3451 </iq> | |
3452 """ | |
3453 | |
3454 def cb(result): | |
3455 self.assertEquals('bad-request', result.condition) | |
3456 | |
3457 d = self.handleRequest(xml) | |
3458 self.assertFailure(d, error.StanzaError) | |
3459 d.addCallback(cb) | |
3460 return d | |
3461 | |
3462 | |
3463 def test_on_affiliationsSetMissingAffiliation(self): | |
3464 """ | |
3465 Setting node affiliations must include an affiliation. | |
3466 """ | |
3467 | |
3468 xml = """ | |
3469 <iq type='set' to='pubsub.example.org' | |
3470 from='user@example.org'> | |
3471 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3472 <affiliations node='test'> | |
3473 <affiliation jid='other@example.org'/> | |
3474 </affiliations> | |
3475 </pubsub> | |
3476 </iq> | |
3477 """ | |
3478 | |
3479 def cb(result): | |
3480 self.assertEquals('bad-request', result.condition) | |
3481 | |
3482 d = self.handleRequest(xml) | |
3483 self.assertFailure(d, error.StanzaError) | |
3484 d.addCallback(cb) | |
3485 return d | |
3486 | |
3487 | |
3488 | |
3489 class PubSubServiceWithoutResourceTest(unittest.TestCase, TestableRequestHandlerMixin): | |
3490 | |
3491 def setUp(self): | |
3492 self.stub = XmlStreamStub() | |
3493 self.service = pubsub.PubSubService() | |
3494 self.service.send = self.stub.xmlstream.send | |
3495 | |
3496 | |
3497 def test_getDiscoInfo(self): | |
3498 """ | |
3499 Test getDiscoInfo calls getNodeInfo and returns some minimal info. | |
3500 """ | |
3501 def cb(info): | |
3502 discoInfo = disco.DiscoInfo() | |
3503 for item in info: | |
3504 discoInfo.append(item) | |
3505 self.assertIn(('pubsub', 'service'), discoInfo.identities) | |
3506 self.assertIn(disco.NS_DISCO_ITEMS, discoInfo.features) | |
3507 | |
3508 d = self.service.getDiscoInfo(JID('user@example.org/home'), | |
3509 JID('pubsub.example.org'), '') | |
3510 d.addCallback(cb) | |
3511 return d | |
3512 | |
3513 | |
3514 def test_publish(self): | |
3515 """ | |
3516 Non-overridden L{PubSubService.publish} yields unsupported error. | |
3517 """ | |
3518 | |
3519 xml = """ | |
3520 <iq type='set' to='pubsub.example.org' | |
3521 from='user@example.org'> | |
3522 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3523 <publish node='mynode'/> | |
3524 </pubsub> | |
3525 </iq> | |
3526 """ | |
3527 | |
3528 def cb(result): | |
3529 self.assertEquals('feature-not-implemented', result.condition) | |
3530 self.assertEquals('unsupported', result.appCondition.name) | |
3531 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3532 self.assertEquals('publish', result.appCondition['feature']) | |
3533 | |
3534 d = self.handleRequest(xml) | |
3535 self.assertFailure(d, error.StanzaError) | |
3536 d.addCallback(cb) | |
3537 return d | |
3538 | |
3539 | |
3540 def test_subscribe(self): | |
3541 """ | |
3542 Non-overridden L{PubSubService.subscribe} yields unsupported error. | |
3543 """ | |
3544 | |
3545 xml = """ | |
3546 <iq type='set' to='pubsub.example.org' | |
3547 from='user@example.org'> | |
3548 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3549 <subscribe node='test' jid='user@example.org/Home'/> | |
3550 </pubsub> | |
3551 </iq> | |
3552 """ | |
3553 | |
3554 def cb(result): | |
3555 self.assertEquals('feature-not-implemented', result.condition) | |
3556 self.assertEquals('unsupported', result.appCondition.name) | |
3557 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3558 self.assertEquals('subscribe', result.appCondition['feature']) | |
3559 | |
3560 d = self.handleRequest(xml) | |
3561 self.assertFailure(d, error.StanzaError) | |
3562 d.addCallback(cb) | |
3563 return d | |
3564 | |
3565 | |
3566 def test_unsubscribe(self): | |
3567 """ | |
3568 Non-overridden L{PubSubService.unsubscribe} yields unsupported error. | |
3569 """ | |
3570 | |
3571 xml = """ | |
3572 <iq type='set' to='pubsub.example.org' | |
3573 from='user@example.org'> | |
3574 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3575 <unsubscribe node='test' jid='user@example.org/Home'/> | |
3576 </pubsub> | |
3577 </iq> | |
3578 """ | |
3579 | |
3580 def cb(result): | |
3581 self.assertEquals('feature-not-implemented', result.condition) | |
3582 self.assertEquals('unsupported', result.appCondition.name) | |
3583 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3584 self.assertEquals('subscribe', result.appCondition['feature']) | |
3585 | |
3586 d = self.handleRequest(xml) | |
3587 self.assertFailure(d, error.StanzaError) | |
3588 d.addCallback(cb) | |
3589 return d | |
3590 | |
3591 | |
3592 def test_subscriptions(self): | |
3593 """ | |
3594 Non-overridden L{PubSubService.subscriptions} yields unsupported error. | |
3595 """ | |
3596 | |
3597 xml = """ | |
3598 <iq type='get' to='pubsub.example.org' | |
3599 from='user@example.org'> | |
3600 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3601 <subscriptions/> | |
3602 </pubsub> | |
3603 </iq> | |
3604 """ | |
3605 | |
3606 def cb(result): | |
3607 self.assertEquals('feature-not-implemented', result.condition) | |
3608 self.assertEquals('unsupported', result.appCondition.name) | |
3609 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3610 self.assertEquals('retrieve-subscriptions', | |
3611 result.appCondition['feature']) | |
3612 | |
3613 d = self.handleRequest(xml) | |
3614 self.assertFailure(d, error.StanzaError) | |
3615 d.addCallback(cb) | |
3616 return d | |
3617 | |
3618 | |
3619 def test_affiliations(self): | |
3620 """ | |
3621 Non-overridden L{PubSubService.affiliations} yields unsupported error. | |
3622 """ | |
3623 | |
3624 xml = """ | |
3625 <iq type='get' to='pubsub.example.org' | |
3626 from='user@example.org'> | |
3627 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3628 <affiliations/> | |
3629 </pubsub> | |
3630 </iq> | |
3631 """ | |
3632 | |
3633 def cb(result): | |
3634 self.assertEquals('feature-not-implemented', result.condition) | |
3635 self.assertEquals('unsupported', result.appCondition.name) | |
3636 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3637 self.assertEquals('retrieve-affiliations', | |
3638 result.appCondition['feature']) | |
3639 | |
3640 d = self.handleRequest(xml) | |
3641 self.assertFailure(d, error.StanzaError) | |
3642 d.addCallback(cb) | |
3643 return d | |
3644 | |
3645 | |
3646 def test_create(self): | |
3647 """ | |
3648 Non-overridden L{PubSubService.create} yields unsupported error. | |
3649 """ | |
3650 | |
3651 xml = """ | |
3652 <iq type='set' to='pubsub.example.org' | |
3653 from='user@example.org'> | |
3654 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3655 <create node='mynode'/> | |
3656 </pubsub> | |
3657 </iq> | |
3658 """ | |
3659 | |
3660 def cb(result): | |
3661 self.assertEquals('feature-not-implemented', result.condition) | |
3662 self.assertEquals('unsupported', result.appCondition.name) | |
3663 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3664 self.assertEquals('create-nodes', result.appCondition['feature']) | |
3665 | |
3666 d = self.handleRequest(xml) | |
3667 self.assertFailure(d, error.StanzaError) | |
3668 d.addCallback(cb) | |
3669 return d | |
3670 | |
3671 | |
3672 def test_getDefaultConfiguration(self): | |
3673 """ | |
3674 Non-overridden L{PubSubService.getDefaultConfiguration} yields | |
3675 unsupported error. | |
3676 """ | |
3677 | |
3678 xml = """ | |
3679 <iq type='get' to='pubsub.example.org' | |
3680 from='user@example.org'> | |
3681 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3682 <default/> | |
3683 </pubsub> | |
3684 </iq> | |
3685 """ | |
3686 | |
3687 def cb(result): | |
3688 self.assertEquals('feature-not-implemented', result.condition) | |
3689 self.assertEquals('unsupported', result.appCondition.name) | |
3690 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3691 self.assertEquals('retrieve-default', result.appCondition['feature']) | |
3692 | |
3693 d = self.handleRequest(xml) | |
3694 self.assertFailure(d, error.StanzaError) | |
3695 d.addCallback(cb) | |
3696 return d | |
3697 | |
3698 | |
3699 def test_getConfiguration(self): | |
3700 """ | |
3701 Non-overridden L{PubSubService.getConfiguration} yields unsupported | |
3702 error. | |
3703 """ | |
3704 | |
3705 xml = """ | |
3706 <iq type='get' to='pubsub.example.org' | |
3707 from='user@example.org'> | |
3708 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3709 <configure/> | |
3710 </pubsub> | |
3711 </iq> | |
3712 """ | |
3713 | |
3714 def cb(result): | |
3715 self.assertEquals('feature-not-implemented', result.condition) | |
3716 self.assertEquals('unsupported', result.appCondition.name) | |
3717 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3718 self.assertEquals('config-node', result.appCondition['feature']) | |
3719 | |
3720 d = self.handleRequest(xml) | |
3721 self.assertFailure(d, error.StanzaError) | |
3722 d.addCallback(cb) | |
3723 return d | |
3724 | |
3725 | |
3726 def test_setConfiguration(self): | |
3727 """ | |
3728 Non-overridden L{PubSubService.setConfiguration} yields unsupported | |
3729 error. | |
3730 """ | |
3731 | |
3732 xml = """ | |
3733 <iq type='set' to='pubsub.example.org' | |
3734 from='user@example.org'> | |
3735 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3736 <configure node='test'> | |
3737 <x xmlns='jabber:x:data' type='submit'> | |
3738 <field var='FORM_TYPE' type='hidden'> | |
3739 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
3740 </field> | |
3741 <field var='pubsub#deliver_payloads'><value>0</value></field> | |
3742 <field var='pubsub#persist_items'><value>1</value></field> | |
3743 </x> | |
3744 </configure> | |
3745 </pubsub> | |
3746 </iq> | |
3747 """ | |
3748 | |
3749 def cb(result): | |
3750 self.assertEquals('feature-not-implemented', result.condition) | |
3751 self.assertEquals('unsupported', result.appCondition.name) | |
3752 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3753 self.assertEquals('config-node', result.appCondition['feature']) | |
3754 | |
3755 d = self.handleRequest(xml) | |
3756 self.assertFailure(d, error.StanzaError) | |
3757 d.addCallback(cb) | |
3758 return d | |
3759 | |
3760 | |
3761 def test_setConfigurationOptionsDict(self): | |
3762 """ | |
3763 Options should be passed as a dictionary, not a form. | |
3764 """ | |
3765 | |
3766 xml = """ | |
3767 <iq type='set' to='pubsub.example.org' | |
3768 from='user@example.org'> | |
3769 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3770 <configure node='test'> | |
3771 <x xmlns='jabber:x:data' type='submit'> | |
3772 <field var='FORM_TYPE' type='hidden'> | |
3773 <value>http://jabber.org/protocol/pubsub#node_config</value> | |
3774 </field> | |
3775 <field var='pubsub#deliver_payloads'><value>0</value></field> | |
3776 <field var='pubsub#persist_items'><value>1</value></field> | |
3777 </x> | |
3778 </configure> | |
3779 </pubsub> | |
3780 </iq> | |
3781 """ | |
3782 | |
3783 def getConfigurationOptions(): | |
3784 return { | |
3785 "pubsub#persist_items": | |
3786 {"type": "boolean", | |
3787 "label": "Persist items to storage"}, | |
3788 "pubsub#deliver_payloads": | |
3789 {"type": "boolean", | |
3790 "label": "Deliver payloads with event notifications"} | |
3791 } | |
3792 | |
3793 def setConfiguration(requestor, service, nodeIdentifier, options): | |
3794 self.assertIn('pubsub#deliver_payloads', options) | |
3795 self.assertFalse(options['pubsub#deliver_payloads']) | |
3796 self.assertIn('pubsub#persist_items', options) | |
3797 self.assertTrue(options['pubsub#persist_items']) | |
3798 | |
3799 self.service.getConfigurationOptions = getConfigurationOptions | |
3800 self.service.setConfiguration = setConfiguration | |
3801 return self.handleRequest(xml) | |
3802 | |
3803 | |
3804 def test_items(self): | |
3805 """ | |
3806 Non-overridden L{PubSubService.items} yields unsupported error. | |
3807 """ | |
3808 xml = """ | |
3809 <iq type='get' to='pubsub.example.org' | |
3810 from='user@example.org'> | |
3811 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3812 <items node='test'/> | |
3813 </pubsub> | |
3814 </iq> | |
3815 """ | |
3816 | |
3817 def cb(result): | |
3818 self.assertEquals('feature-not-implemented', result.condition) | |
3819 self.assertEquals('unsupported', result.appCondition.name) | |
3820 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3821 self.assertEquals('retrieve-items', result.appCondition['feature']) | |
3822 | |
3823 d = self.handleRequest(xml) | |
3824 self.assertFailure(d, error.StanzaError) | |
3825 d.addCallback(cb) | |
3826 return d | |
3827 | |
3828 | |
3829 def test_retract(self): | |
3830 """ | |
3831 Non-overridden L{PubSubService.retract} yields unsupported error. | |
3832 """ | |
3833 xml = """ | |
3834 <iq type='set' to='pubsub.example.org' | |
3835 from='user@example.org'> | |
3836 <pubsub xmlns='http://jabber.org/protocol/pubsub'> | |
3837 <retract node='test'> | |
3838 <item id='item1'/> | |
3839 <item id='item2'/> | |
3840 </retract> | |
3841 </pubsub> | |
3842 </iq> | |
3843 """ | |
3844 | |
3845 def cb(result): | |
3846 self.assertEquals('feature-not-implemented', result.condition) | |
3847 self.assertEquals('unsupported', result.appCondition.name) | |
3848 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3849 self.assertEquals('retract-items', result.appCondition['feature']) | |
3850 | |
3851 d = self.handleRequest(xml) | |
3852 self.assertFailure(d, error.StanzaError) | |
3853 d.addCallback(cb) | |
3854 return d | |
3855 | |
3856 | |
3857 def test_purge(self): | |
3858 """ | |
3859 Non-overridden L{PubSubService.purge} yields unsupported error. | |
3860 """ | |
3861 xml = """ | |
3862 <iq type='set' to='pubsub.example.org' | |
3863 from='user@example.org'> | |
3864 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3865 <purge node='test'/> | |
3866 </pubsub> | |
3867 </iq> | |
3868 """ | |
3869 | |
3870 def cb(result): | |
3871 self.assertEquals('feature-not-implemented', result.condition) | |
3872 self.assertEquals('unsupported', result.appCondition.name) | |
3873 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3874 self.assertEquals('purge-nodes', result.appCondition['feature']) | |
3875 | |
3876 d = self.handleRequest(xml) | |
3877 self.assertFailure(d, error.StanzaError) | |
3878 d.addCallback(cb) | |
3879 return d | |
3880 | |
3881 | |
3882 def test_delete(self): | |
3883 """ | |
3884 Non-overridden L{PubSubService.delete} yields unsupported error. | |
3885 """ | |
3886 xml = """ | |
3887 <iq type='set' to='pubsub.example.org' | |
3888 from='user@example.org'> | |
3889 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3890 <delete node='test'/> | |
3891 </pubsub> | |
3892 </iq> | |
3893 """ | |
3894 | |
3895 def cb(result): | |
3896 self.assertEquals('feature-not-implemented', result.condition) | |
3897 self.assertEquals('unsupported', result.appCondition.name) | |
3898 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3899 self.assertEquals('delete-nodes', result.appCondition['feature']) | |
3900 | |
3901 d = self.handleRequest(xml) | |
3902 self.assertFailure(d, error.StanzaError) | |
3903 d.addCallback(cb) | |
3904 return d | |
3905 | |
3906 | |
3907 def test_unknown(self): | |
3908 """ | |
3909 Unknown verb yields unsupported error. | |
3910 """ | |
3911 xml = """ | |
3912 <iq type='get' to='pubsub.example.org' | |
3913 from='user@example.org'> | |
3914 <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'> | |
3915 <affiliations node='test'/> | |
3916 </pubsub> | |
3917 </iq> | |
3918 """ | |
3919 | |
3920 def cb(result): | |
3921 self.assertEquals('feature-not-implemented', result.condition) | |
3922 self.assertEquals('unsupported', result.appCondition.name) | |
3923 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3924 | |
3925 d = self.handleRequest(xml) | |
3926 self.assertFailure(d, error.StanzaError) | |
3927 d.addCallback(cb) | |
3928 return d | |
3929 | |
3930 | |
3931 | |
3932 class PubSubResourceTest(unittest.TestCase): | |
3933 | |
3934 def setUp(self): | |
3935 self.resource = pubsub.PubSubResource() | |
3936 | |
3937 | |
3938 def test_interface(self): | |
3939 """ | |
3940 Do instances of L{pubsub.PubSubResource} provide L{iwokkel.IPubSubResource}? | |
3941 """ | |
3942 verify.verifyObject(iwokkel.IPubSubResource, self.resource) | |
3943 | |
3944 | |
3945 def test_getNodes(self): | |
3946 """ | |
3947 Default getNodes returns an empty list. | |
3948 """ | |
3949 def cb(nodes): | |
3950 self.assertEquals([], nodes) | |
3951 | |
3952 d = self.resource.getNodes(JID('user@example.org/home'), | |
3953 JID('pubsub.example.org'), | |
3954 '') | |
3955 d.addCallback(cb) | |
3956 return d | |
3957 | |
3958 | |
3959 def test_publish(self): | |
3960 """ | |
3961 Non-overridden L{PubSubResource.publish} yields unsupported | |
3962 error. | |
3963 """ | |
3964 | |
3965 def cb(result): | |
3966 self.assertEquals('feature-not-implemented', result.condition) | |
3967 self.assertEquals('unsupported', result.appCondition.name) | |
3968 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3969 self.assertEquals('publish', result.appCondition['feature']) | |
3970 | |
3971 d = self.resource.publish(pubsub.PubSubRequest()) | |
3972 self.assertFailure(d, error.StanzaError) | |
3973 d.addCallback(cb) | |
3974 return d | |
3975 | |
3976 | |
3977 def test_subscribe(self): | |
3978 """ | |
3979 Non-overridden subscriptions yields unsupported error. | |
3980 """ | |
3981 | |
3982 def cb(result): | |
3983 self.assertEquals('feature-not-implemented', result.condition) | |
3984 self.assertEquals('unsupported', result.appCondition.name) | |
3985 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
3986 self.assertEquals('subscribe', result.appCondition['feature']) | |
3987 | |
3988 d = self.resource.subscribe(pubsub.PubSubRequest()) | |
3989 self.assertFailure(d, error.StanzaError) | |
3990 d.addCallback(cb) | |
3991 return d | |
3992 | |
3993 | |
3994 def test_unsubscribe(self): | |
3995 """ | |
3996 Non-overridden unsubscribe yields unsupported error. | |
3997 """ | |
3998 | |
3999 def cb(result): | |
4000 self.assertEquals('feature-not-implemented', result.condition) | |
4001 self.assertEquals('unsupported', result.appCondition.name) | |
4002 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4003 self.assertEquals('subscribe', result.appCondition['feature']) | |
4004 | |
4005 d = self.resource.unsubscribe(pubsub.PubSubRequest()) | |
4006 self.assertFailure(d, error.StanzaError) | |
4007 d.addCallback(cb) | |
4008 return d | |
4009 | |
4010 | |
4011 def test_subscriptions(self): | |
4012 """ | |
4013 Non-overridden subscriptions yields unsupported error. | |
4014 """ | |
4015 | |
4016 def cb(result): | |
4017 self.assertEquals('feature-not-implemented', result.condition) | |
4018 self.assertEquals('unsupported', result.appCondition.name) | |
4019 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4020 self.assertEquals('retrieve-subscriptions', | |
4021 result.appCondition['feature']) | |
4022 | |
4023 d = self.resource.subscriptions(pubsub.PubSubRequest()) | |
4024 self.assertFailure(d, error.StanzaError) | |
4025 d.addCallback(cb) | |
4026 return d | |
4027 | |
4028 | |
4029 def test_affiliations(self): | |
4030 """ | |
4031 Non-overridden affiliations yields unsupported error. | |
4032 """ | |
4033 | |
4034 def cb(result): | |
4035 self.assertEquals('feature-not-implemented', result.condition) | |
4036 self.assertEquals('unsupported', result.appCondition.name) | |
4037 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4038 self.assertEquals('retrieve-affiliations', | |
4039 result.appCondition['feature']) | |
4040 | |
4041 d = self.resource.affiliations(pubsub.PubSubRequest()) | |
4042 self.assertFailure(d, error.StanzaError) | |
4043 d.addCallback(cb) | |
4044 return d | |
4045 | |
4046 | |
4047 def test_create(self): | |
4048 """ | |
4049 Non-overridden create yields unsupported error. | |
4050 """ | |
4051 | |
4052 def cb(result): | |
4053 self.assertEquals('feature-not-implemented', result.condition) | |
4054 self.assertEquals('unsupported', result.appCondition.name) | |
4055 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4056 self.assertEquals('create-nodes', result.appCondition['feature']) | |
4057 | |
4058 d = self.resource.create(pubsub.PubSubRequest()) | |
4059 self.assertFailure(d, error.StanzaError) | |
4060 d.addCallback(cb) | |
4061 return d | |
4062 | |
4063 | |
4064 def test_default(self): | |
4065 """ | |
4066 Non-overridden default yields unsupported error. | |
4067 """ | |
4068 | |
4069 def cb(result): | |
4070 self.assertEquals('feature-not-implemented', result.condition) | |
4071 self.assertEquals('unsupported', result.appCondition.name) | |
4072 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4073 self.assertEquals('retrieve-default', | |
4074 result.appCondition['feature']) | |
4075 | |
4076 d = self.resource.default(pubsub.PubSubRequest()) | |
4077 self.assertFailure(d, error.StanzaError) | |
4078 d.addCallback(cb) | |
4079 return d | |
4080 | |
4081 | |
4082 def test_configureGet(self): | |
4083 """ | |
4084 Non-overridden configureGet yields unsupported | |
4085 error. | |
4086 """ | |
4087 | |
4088 def cb(result): | |
4089 self.assertEquals('feature-not-implemented', result.condition) | |
4090 self.assertEquals('unsupported', result.appCondition.name) | |
4091 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4092 self.assertEquals('config-node', result.appCondition['feature']) | |
4093 | |
4094 d = self.resource.configureGet(pubsub.PubSubRequest()) | |
4095 self.assertFailure(d, error.StanzaError) | |
4096 d.addCallback(cb) | |
4097 return d | |
4098 | |
4099 | |
4100 def test_configureSet(self): | |
4101 """ | |
4102 Non-overridden configureSet yields unsupported error. | |
4103 """ | |
4104 | |
4105 def cb(result): | |
4106 self.assertEquals('feature-not-implemented', result.condition) | |
4107 self.assertEquals('unsupported', result.appCondition.name) | |
4108 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4109 self.assertEquals('config-node', result.appCondition['feature']) | |
4110 | |
4111 d = self.resource.configureSet(pubsub.PubSubRequest()) | |
4112 self.assertFailure(d, error.StanzaError) | |
4113 d.addCallback(cb) | |
4114 return d | |
4115 | |
4116 | |
4117 def test_items(self): | |
4118 """ | |
4119 Non-overridden items yields unsupported error. | |
4120 """ | |
4121 | |
4122 def cb(result): | |
4123 self.assertEquals('feature-not-implemented', result.condition) | |
4124 self.assertEquals('unsupported', result.appCondition.name) | |
4125 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4126 self.assertEquals('retrieve-items', result.appCondition['feature']) | |
4127 | |
4128 d = self.resource.items(pubsub.PubSubRequest()) | |
4129 self.assertFailure(d, error.StanzaError) | |
4130 d.addCallback(cb) | |
4131 return d | |
4132 | |
4133 | |
4134 def test_retract(self): | |
4135 """ | |
4136 Non-overridden retract yields unsupported error. | |
4137 """ | |
4138 | |
4139 def cb(result): | |
4140 self.assertEquals('feature-not-implemented', result.condition) | |
4141 self.assertEquals('unsupported', result.appCondition.name) | |
4142 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4143 self.assertEquals('retract-items', result.appCondition['feature']) | |
4144 | |
4145 d = self.resource.retract(pubsub.PubSubRequest()) | |
4146 self.assertFailure(d, error.StanzaError) | |
4147 d.addCallback(cb) | |
4148 return d | |
4149 | |
4150 | |
4151 def test_purge(self): | |
4152 """ | |
4153 Non-overridden purge yields unsupported error. | |
4154 """ | |
4155 | |
4156 def cb(result): | |
4157 self.assertEquals('feature-not-implemented', result.condition) | |
4158 self.assertEquals('unsupported', result.appCondition.name) | |
4159 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4160 self.assertEquals('purge-nodes', result.appCondition['feature']) | |
4161 | |
4162 d = self.resource.purge(pubsub.PubSubRequest()) | |
4163 self.assertFailure(d, error.StanzaError) | |
4164 d.addCallback(cb) | |
4165 return d | |
4166 | |
4167 | |
4168 def test_delete(self): | |
4169 """ | |
4170 Non-overridden delete yields unsupported error. | |
4171 """ | |
4172 | |
4173 def cb(result): | |
4174 self.assertEquals('feature-not-implemented', result.condition) | |
4175 self.assertEquals('unsupported', result.appCondition.name) | |
4176 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4177 self.assertEquals('delete-nodes', result.appCondition['feature']) | |
4178 | |
4179 d = self.resource.delete(pubsub.PubSubRequest()) | |
4180 self.assertFailure(d, error.StanzaError) | |
4181 d.addCallback(cb) | |
4182 return d | |
4183 | |
4184 | |
4185 def test_affiliationsGet(self): | |
4186 """ | |
4187 Non-overridden owner affiliations get yields unsupported error. | |
4188 """ | |
4189 | |
4190 def cb(result): | |
4191 self.assertEquals('feature-not-implemented', result.condition) | |
4192 self.assertEquals('unsupported', result.appCondition.name) | |
4193 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4194 self.assertEquals('modify-affiliations', | |
4195 result.appCondition['feature']) | |
4196 | |
4197 d = self.resource.affiliationsGet(pubsub.PubSubRequest()) | |
4198 self.assertFailure(d, error.StanzaError) | |
4199 d.addCallback(cb) | |
4200 return d | |
4201 | |
4202 | |
4203 def test_affiliationsSet(self): | |
4204 """ | |
4205 Non-overridden owner affiliations set yields unsupported error. | |
4206 """ | |
4207 | |
4208 def cb(result): | |
4209 self.assertEquals('feature-not-implemented', result.condition) | |
4210 self.assertEquals('unsupported', result.appCondition.name) | |
4211 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) | |
4212 self.assertEquals('modify-affiliations', | |
4213 result.appCondition['feature']) | |
4214 | |
4215 d = self.resource.affiliationsSet(pubsub.PubSubRequest()) | |
4216 self.assertFailure(d, error.StanzaError) | |
4217 d.addCallback(cb) | |
4218 return d |