source: wokkel/test/test_pubsub.py @ 58:a8c2aadabebd

Last change on this file since 58:a8c2aadabebd was 58:a8c2aadabebd, checked in by Ralph Meijer <ralphm@…>, 13 years ago

Allow publish-subscribe client requests to come from a specific JID.

Author: ralphm.
Fixes #46.

File size: 86.7 KB
Line 
1# Copyright (c) 2003-2009 Ralph Meijer
2# See LICENSE for details.
3
4"""
5Tests for L{wokkel.pubsub}
6"""
7
8from zope.interface import verify
9
10from twisted.trial import unittest
11from twisted.internet import defer
12from twisted.words.xish import domish
13from twisted.words.protocols.jabber import error
14from twisted.words.protocols.jabber.jid import JID
15from twisted.words.protocols.jabber.xmlstream import toResponse
16
17from wokkel import data_form, disco, iwokkel, pubsub, shim
18from wokkel.generic import parseXml
19from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
20
21NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
22NS_PUBSUB_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
23NS_PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors'
24NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event'
25NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner'
26NS_PUBSUB_META_DATA = 'http://jabber.org/protocol/pubsub#meta-data'
27
28def calledAsync(fn):
29    """
30    Function wrapper that fires a deferred upon calling the given function.
31    """
32    d = defer.Deferred()
33
34    def func(*args, **kwargs):
35        try:
36            result = fn(*args, **kwargs)
37        except:
38            d.errback()
39        else:
40            d.callback(result)
41
42    return d, func
43
44
45class PubSubClientTest(unittest.TestCase):
46    timeout = 2
47
48    def setUp(self):
49        self.stub = XmlStreamStub()
50        self.protocol = pubsub.PubSubClient()
51        self.protocol.xmlstream = self.stub.xmlstream
52        self.protocol.connectionInitialized()
53
54
55    def test_interface(self):
56        """
57        Do instances of L{pubsub.PubSubClient} provide L{iwokkel.IPubSubClient}?
58        """
59        verify.verifyObject(iwokkel.IPubSubClient, self.protocol)
60
61
62    def test_eventItems(self):
63        """
64        Test receiving an items event resulting in a call to itemsReceived.
65        """
66        message = domish.Element((None, 'message'))
67        message['from'] = 'pubsub.example.org'
68        message['to'] = 'user@example.org/home'
69        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
70        items = event.addElement('items')
71        items['node'] = 'test'
72        item1 = items.addElement('item')
73        item1['id'] = 'item1'
74        item2 = items.addElement('retract')
75        item2['id'] = 'item2'
76        item3 = items.addElement('item')
77        item3['id'] = 'item3'
78
79        def itemsReceived(event):
80            self.assertEquals(JID('user@example.org/home'), event.recipient)
81            self.assertEquals(JID('pubsub.example.org'), event.sender)
82            self.assertEquals('test', event.nodeIdentifier)
83            self.assertEquals([item1, item2, item3], event.items)
84
85        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
86        self.stub.send(message)
87        return d
88
89
90    def test_eventItemsCollection(self):
91        """
92        Test receiving an items event resulting in a call to itemsReceived.
93        """
94        message = domish.Element((None, 'message'))
95        message['from'] = 'pubsub.example.org'
96        message['to'] = 'user@example.org/home'
97        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
98        items = event.addElement('items')
99        items['node'] = 'test'
100
101        headers = shim.Headers([('Collection', 'collection')])
102        message.addChild(headers)
103
104        def itemsReceived(event):
105            self.assertEquals(JID('user@example.org/home'), event.recipient)
106            self.assertEquals(JID('pubsub.example.org'), event.sender)
107            self.assertEquals('test', event.nodeIdentifier)
108            self.assertEquals({'Collection': ['collection']}, event.headers)
109
110        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
111        self.stub.send(message)
112        return d
113
114
115    def test_eventDelete(self):
116        """
117        Test receiving a delete event resulting in a call to deleteReceived.
118        """
119        message = domish.Element((None, 'message'))
120        message['from'] = 'pubsub.example.org'
121        message['to'] = 'user@example.org/home'
122        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
123        delete = event.addElement('delete')
124        delete['node'] = 'test'
125
126        def deleteReceived(event):
127            self.assertEquals(JID('user@example.org/home'), event.recipient)
128            self.assertEquals(JID('pubsub.example.org'), event.sender)
129            self.assertEquals('test', event.nodeIdentifier)
130
131        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
132        self.stub.send(message)
133        return d
134
135
136    def test_eventDeleteRedirect(self):
137        """
138        Test receiving a delete event with a redirect URI.
139        """
140        message = domish.Element((None, 'message'))
141        message['from'] = 'pubsub.example.org'
142        message['to'] = 'user@example.org/home'
143        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
144        delete = event.addElement('delete')
145        delete['node'] = 'test'
146        uri = 'xmpp:pubsub.example.org?;node=test2'
147        delete.addElement('redirect')['uri'] = uri
148
149        def deleteReceived(event):
150            self.assertEquals(JID('user@example.org/home'), event.recipient)
151            self.assertEquals(JID('pubsub.example.org'), event.sender)
152            self.assertEquals('test', event.nodeIdentifier)
153            self.assertEquals(uri, event.redirectURI)
154
155        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
156        self.stub.send(message)
157        return d
158
159
160    def test_event_purge(self):
161        """
162        Test receiving a purge event resulting in a call to purgeReceived.
163        """
164        message = domish.Element((None, 'message'))
165        message['from'] = 'pubsub.example.org'
166        message['to'] = 'user@example.org/home'
167        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
168        items = event.addElement('purge')
169        items['node'] = 'test'
170
171        def purgeReceived(event):
172            self.assertEquals(JID('user@example.org/home'), event.recipient)
173            self.assertEquals(JID('pubsub.example.org'), event.sender)
174            self.assertEquals('test', event.nodeIdentifier)
175
176        d, self.protocol.purgeReceived = calledAsync(purgeReceived)
177        self.stub.send(message)
178        return d
179
180
181    def test_createNode(self):
182        """
183        Test sending create request.
184        """
185
186        def cb(nodeIdentifier):
187            self.assertEquals('test', nodeIdentifier)
188
189        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
190        d.addCallback(cb)
191
192        iq = self.stub.output[-1]
193        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
194        self.assertEquals('set', iq.getAttribute('type'))
195        self.assertEquals('pubsub', iq.pubsub.name)
196        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
197        children = list(domish.generateElementsQNamed(iq.pubsub.children,
198                                                      'create', NS_PUBSUB))
199        self.assertEquals(1, len(children))
200        child = children[0]
201        self.assertEquals('test', child['node'])
202
203        response = toResponse(iq, 'result')
204        self.stub.send(response)
205        return d
206
207
208    def test_createNodeInstant(self):
209        """
210        Test sending create request resulting in an instant node.
211        """
212
213        def cb(nodeIdentifier):
214            self.assertEquals('test', nodeIdentifier)
215
216        d = self.protocol.createNode(JID('pubsub.example.org'))
217        d.addCallback(cb)
218
219        iq = self.stub.output[-1]
220        children = list(domish.generateElementsQNamed(iq.pubsub.children,
221                                                      'create', NS_PUBSUB))
222        child = children[0]
223        self.assertFalse(child.hasAttribute('node'))
224
225        response = toResponse(iq, 'result')
226        command = response.addElement((NS_PUBSUB, 'pubsub'))
227        create = command.addElement('create')
228        create['node'] = 'test'
229        self.stub.send(response)
230        return d
231
232
233    def test_createNodeRenamed(self):
234        """
235        Test sending create request resulting in renamed node.
236        """
237
238        def cb(nodeIdentifier):
239            self.assertEquals('test2', nodeIdentifier)
240
241        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
242        d.addCallback(cb)
243
244        iq = self.stub.output[-1]
245        children = list(domish.generateElementsQNamed(iq.pubsub.children,
246                                                      'create', NS_PUBSUB))
247        child = children[0]
248        self.assertEquals('test', child['node'])
249
250        response = toResponse(iq, 'result')
251        command = response.addElement((NS_PUBSUB, 'pubsub'))
252        create = command.addElement('create')
253        create['node'] = 'test2'
254        self.stub.send(response)
255        return d
256
257
258    def test_createNodeWithSender(self):
259        """
260        Test sending create request from a specific JID.
261        """
262
263        d = self.protocol.createNode(JID('pubsub.example.org'), 'test',
264                                     sender=JID('user@example.org'))
265
266        iq = self.stub.output[-1]
267        self.assertEquals('user@example.org', iq['from'])
268
269        response = toResponse(iq, 'result')
270        self.stub.send(response)
271        return d
272
273
274    def test_deleteNode(self):
275        """
276        Test sending delete request.
277        """
278
279        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test')
280
281        iq = self.stub.output[-1]
282        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
283        self.assertEquals('set', iq.getAttribute('type'))
284        self.assertEquals('pubsub', iq.pubsub.name)
285        self.assertEquals(NS_PUBSUB_OWNER, iq.pubsub.uri)
286        children = list(domish.generateElementsQNamed(iq.pubsub.children,
287                                                      'delete', NS_PUBSUB_OWNER))
288        self.assertEquals(1, len(children))
289        child = children[0]
290        self.assertEquals('test', child['node'])
291
292        response = toResponse(iq, 'result')
293        self.stub.send(response)
294        return d
295
296
297    def test_deleteNodeWithSender(self):
298        """
299        Test sending delete request.
300        """
301
302        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test',
303                                     sender=JID('user@example.org'))
304
305        iq = self.stub.output[-1]
306        self.assertEquals('user@example.org', iq['from'])
307
308        response = toResponse(iq, 'result')
309        self.stub.send(response)
310        return d
311
312
313    def test_publish(self):
314        """
315        Test sending publish request.
316        """
317
318        item = pubsub.Item()
319        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item])
320
321        iq = self.stub.output[-1]
322        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
323        self.assertEquals('set', iq.getAttribute('type'))
324        self.assertEquals('pubsub', iq.pubsub.name)
325        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
326        children = list(domish.generateElementsQNamed(iq.pubsub.children,
327                                                      'publish', NS_PUBSUB))
328        self.assertEquals(1, len(children))
329        child = children[0]
330        self.assertEquals('test', child['node'])
331        items = list(domish.generateElementsQNamed(child.children,
332                                                   'item', NS_PUBSUB))
333        self.assertEquals(1, len(items))
334        self.assertIdentical(item, items[0])
335
336        response = toResponse(iq, 'result')
337        self.stub.send(response)
338        return d
339
340
341    def test_publishNoItems(self):
342        """
343        Test sending publish request without items.
344        """
345
346        d = self.protocol.publish(JID('pubsub.example.org'), 'test')
347
348        iq = self.stub.output[-1]
349        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
350        self.assertEquals('set', iq.getAttribute('type'))
351        self.assertEquals('pubsub', iq.pubsub.name)
352        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
353        children = list(domish.generateElementsQNamed(iq.pubsub.children,
354                                                      'publish', NS_PUBSUB))
355        self.assertEquals(1, len(children))
356        child = children[0]
357        self.assertEquals('test', child['node'])
358
359        response = toResponse(iq, 'result')
360        self.stub.send(response)
361        return d
362
363
364    def test_publishWithSender(self):
365        """
366        Test sending publish request from a specific JID.
367        """
368
369        item = pubsub.Item()
370        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item],
371                                  JID('user@example.org'))
372
373        iq = self.stub.output[-1]
374        self.assertEquals('user@example.org', iq['from'])
375
376        response = toResponse(iq, 'result')
377        self.stub.send(response)
378        return d
379
380
381    def test_subscribe(self):
382        """
383        Test sending subscription request.
384        """
385        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
386                                      JID('user@example.org'))
387
388        iq = self.stub.output[-1]
389        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
390        self.assertEquals('set', iq.getAttribute('type'))
391        self.assertEquals('pubsub', iq.pubsub.name)
392        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
393        children = list(domish.generateElementsQNamed(iq.pubsub.children,
394                                                      'subscribe', NS_PUBSUB))
395        self.assertEquals(1, len(children))
396        child = children[0]
397        self.assertEquals('test', child['node'])
398        self.assertEquals('user@example.org', child['jid'])
399
400        response = toResponse(iq, 'result')
401        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
402        subscription = pubsub.addElement('subscription')
403        subscription['node'] = 'test'
404        subscription['jid'] = 'user@example.org'
405        subscription['subscription'] = 'subscribed'
406        self.stub.send(response)
407        return d
408
409
410    def test_subscribePending(self):
411        """
412        Test sending subscription request that results in a pending
413        subscription.
414        """
415        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
416                                      JID('user@example.org'))
417
418        iq = self.stub.output[-1]
419        response = toResponse(iq, 'result')
420        command = response.addElement((NS_PUBSUB, 'pubsub'))
421        subscription = command.addElement('subscription')
422        subscription['node'] = 'test'
423        subscription['jid'] = 'user@example.org'
424        subscription['subscription'] = 'pending'
425        self.stub.send(response)
426        self.assertFailure(d, pubsub.SubscriptionPending)
427        return d
428
429
430    def test_subscribeUnconfigured(self):
431        """
432        Test sending subscription request that results in an unconfigured
433        subscription.
434        """
435        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
436                                      JID('user@example.org'))
437
438        iq = self.stub.output[-1]
439        response = toResponse(iq, 'result')
440        command = response.addElement((NS_PUBSUB, 'pubsub'))
441        subscription = command.addElement('subscription')
442        subscription['node'] = 'test'
443        subscription['jid'] = 'user@example.org'
444        subscription['subscription'] = 'unconfigured'
445        self.stub.send(response)
446        self.assertFailure(d, pubsub.SubscriptionUnconfigured)
447        return d
448
449
450    def test_subscribeWithSender(self):
451        """
452        Test sending subscription request from a specific JID.
453        """
454        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
455                                      JID('user@example.org'),
456                                      sender=JID('user@example.org'))
457
458        iq = self.stub.output[-1]
459        self.assertEquals('user@example.org', iq['from'])
460
461        response = toResponse(iq, 'result')
462        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
463        subscription = pubsub.addElement('subscription')
464        subscription['node'] = 'test'
465        subscription['jid'] = 'user@example.org'
466        subscription['subscription'] = 'subscribed'
467        self.stub.send(response)
468        return d
469
470
471    def test_unsubscribe(self):
472        """
473        Test sending unsubscription request.
474        """
475        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
476                                      JID('user@example.org'))
477
478        iq = self.stub.output[-1]
479        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
480        self.assertEquals('set', iq.getAttribute('type'))
481        self.assertEquals('pubsub', iq.pubsub.name)
482        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
483        children = list(domish.generateElementsQNamed(iq.pubsub.children,
484                                                      'unsubscribe', NS_PUBSUB))
485        self.assertEquals(1, len(children))
486        child = children[0]
487        self.assertEquals('test', child['node'])
488        self.assertEquals('user@example.org', child['jid'])
489
490        self.stub.send(toResponse(iq, 'result'))
491        return d
492
493
494    def test_unsubscribeWithSender(self):
495        """
496        Test sending unsubscription request from a specific JID.
497        """
498        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
499                                      JID('user@example.org'),
500                                      sender=JID('user@example.org'))
501
502        iq = self.stub.output[-1]
503        self.assertEquals('user@example.org', iq['from'])
504        self.stub.send(toResponse(iq, 'result'))
505        return d
506
507
508    def test_items(self):
509        """
510        Test sending items request.
511        """
512        def cb(items):
513            self.assertEquals([], items)
514
515        d = self.protocol.items(JID('pubsub.example.org'), 'test')
516        d.addCallback(cb)
517
518        iq = self.stub.output[-1]
519        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
520        self.assertEquals('get', iq.getAttribute('type'))
521        self.assertEquals('pubsub', iq.pubsub.name)
522        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
523        children = list(domish.generateElementsQNamed(iq.pubsub.children,
524                                                      'items', NS_PUBSUB))
525        self.assertEquals(1, len(children))
526        child = children[0]
527        self.assertEquals('test', child['node'])
528
529        response = toResponse(iq, 'result')
530        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
531        items['node'] = 'test'
532
533        self.stub.send(response)
534
535        return d
536
537
538    def test_itemsMaxItems(self):
539        """
540        Test sending items request, with limit on the number of items.
541        """
542        def cb(items):
543            self.assertEquals(2, len(items))
544            self.assertEquals([item1, item2], items)
545
546        d = self.protocol.items(JID('pubsub.example.org'), 'test', maxItems=2)
547        d.addCallback(cb)
548
549        iq = self.stub.output[-1]
550        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
551        self.assertEquals('get', iq.getAttribute('type'))
552        self.assertEquals('pubsub', iq.pubsub.name)
553        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
554        children = list(domish.generateElementsQNamed(iq.pubsub.children,
555                                                      'items', NS_PUBSUB))
556        self.assertEquals(1, len(children))
557        child = children[0]
558        self.assertEquals('test', child['node'])
559        self.assertEquals('2', child['max_items'])
560
561        response = toResponse(iq, 'result')
562        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
563        items['node'] = 'test'
564        item1 = items.addElement('item')
565        item1['id'] = 'item1'
566        item2 = items.addElement('item')
567        item2['id'] = 'item2'
568
569        self.stub.send(response)
570
571        return d
572
573
574    def test_itemsWithSender(self):
575        """
576        Test sending items request from a specific JID.
577        """
578
579        d = self.protocol.items(JID('pubsub.example.org'), 'test',
580                               sender=JID('user@example.org'))
581
582        iq = self.stub.output[-1]
583        self.assertEquals('user@example.org', iq['from'])
584
585        response = toResponse(iq, 'result')
586        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
587        items['node'] = 'test'
588
589        self.stub.send(response)
590        return d
591
592
593
594class PubSubRequestTest(unittest.TestCase):
595
596    def test_fromElementPublish(self):
597        """
598        Test parsing a publish request.
599        """
600
601        xml = """
602        <iq type='set' to='pubsub.example.org'
603                       from='user@example.org'>
604          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
605            <publish node='test'/>
606          </pubsub>
607        </iq>
608        """
609
610        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
611        self.assertEqual('publish', request.verb)
612        self.assertEqual(JID('user@example.org'), request.sender)
613        self.assertEqual(JID('pubsub.example.org'), request.recipient)
614        self.assertEqual('test', request.nodeIdentifier)
615        self.assertEqual([], request.items)
616
617
618    def test_fromElementPublishItems(self):
619        """
620        Test parsing a publish request with items.
621        """
622
623        xml = """
624        <iq type='set' to='pubsub.example.org'
625                       from='user@example.org'>
626          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
627            <publish node='test'>
628              <item id="item1"/>
629              <item id="item2"/>
630            </publish>
631          </pubsub>
632        </iq>
633        """
634
635        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
636        self.assertEqual(2, len(request.items))
637        self.assertEqual(u'item1', request.items[0]["id"])
638        self.assertEqual(u'item2', request.items[1]["id"])
639
640
641    def test_fromElementPublishNoNode(self):
642        """
643        A publish request to the root node should raise an exception.
644        """
645        xml = """
646        <iq type='set' to='pubsub.example.org'
647                       from='user@example.org'>
648          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
649            <publish/>
650          </pubsub>
651        </iq>
652        """
653
654        err = self.assertRaises(error.StanzaError,
655                                pubsub.PubSubRequest.fromElement,
656                                parseXml(xml))
657        self.assertEqual('bad-request', err.condition)
658        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
659        self.assertEqual('nodeid-required', err.appCondition.name)
660
661
662    def test_fromElementSubscribe(self):
663        """
664        Test parsing a subscription request.
665        """
666
667        xml = """
668        <iq type='set' to='pubsub.example.org'
669                       from='user@example.org'>
670          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
671            <subscribe node='test' jid='user@example.org/Home'/>
672          </pubsub>
673        </iq>
674        """
675
676        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
677        self.assertEqual('subscribe', request.verb)
678        self.assertEqual(JID('user@example.org'), request.sender)
679        self.assertEqual(JID('pubsub.example.org'), request.recipient)
680        self.assertEqual('test', request.nodeIdentifier)
681        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
682
683
684    def test_fromElementSubscribeEmptyNode(self):
685        """
686        Test parsing a subscription request to the root node.
687        """
688
689        xml = """
690        <iq type='set' to='pubsub.example.org'
691                       from='user@example.org'>
692          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
693            <subscribe jid='user@example.org/Home'/>
694          </pubsub>
695        </iq>
696        """
697
698        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
699        self.assertEqual('', request.nodeIdentifier)
700
701
702    def test_fromElementSubscribeNoJID(self):
703        """
704        Subscribe requests without a JID should raise a bad-request exception.
705        """
706        xml = """
707        <iq type='set' to='pubsub.example.org'
708                       from='user@example.org'>
709          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
710            <subscribe node='test'/>
711          </pubsub>
712        </iq>
713        """
714        err = self.assertRaises(error.StanzaError,
715                                pubsub.PubSubRequest.fromElement,
716                                parseXml(xml))
717        self.assertEqual('bad-request', err.condition)
718        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
719        self.assertEqual('jid-required', err.appCondition.name)
720
721    def test_fromElementUnsubscribe(self):
722        """
723        Test parsing an unsubscription request.
724        """
725
726        xml = """
727        <iq type='set' to='pubsub.example.org'
728                       from='user@example.org'>
729          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
730            <unsubscribe node='test' jid='user@example.org/Home'/>
731          </pubsub>
732        </iq>
733        """
734
735        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
736        self.assertEqual('unsubscribe', request.verb)
737        self.assertEqual(JID('user@example.org'), request.sender)
738        self.assertEqual(JID('pubsub.example.org'), request.recipient)
739        self.assertEqual('test', request.nodeIdentifier)
740        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
741
742
743    def test_fromElementUnsubscribeNoJID(self):
744        """
745        Unsubscribe requests without a JID should raise a bad-request exception.
746        """
747        xml = """
748        <iq type='set' to='pubsub.example.org'
749                       from='user@example.org'>
750          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
751            <unsubscribe node='test'/>
752          </pubsub>
753        </iq>
754        """
755        err = self.assertRaises(error.StanzaError,
756                                pubsub.PubSubRequest.fromElement,
757                                parseXml(xml))
758        self.assertEqual('bad-request', err.condition)
759        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
760        self.assertEqual('jid-required', err.appCondition.name)
761
762
763    def test_fromElementOptionsGet(self):
764        """
765        Test parsing a request for getting subscription options.
766        """
767
768        xml = """
769        <iq type='get' to='pubsub.example.org'
770                       from='user@example.org'>
771          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
772            <options node='test' jid='user@example.org/Home'/>
773          </pubsub>
774        </iq>
775        """
776
777        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
778        self.assertEqual('optionsGet', request.verb)
779
780
781    def test_fromElementOptionsSet(self):
782        """
783        Test parsing a request for setting subscription options.
784        """
785
786        xml = """
787        <iq type='set' to='pubsub.example.org'
788                       from='user@example.org'>
789          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
790            <options node='test' jid='user@example.org/Home'>
791              <x xmlns='jabber:x:data' type='submit'>
792                <field var='FORM_TYPE' type='hidden'>
793                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
794                </field>
795                <field var='pubsub#deliver'><value>1</value></field>
796              </x>
797            </options>
798          </pubsub>
799        </iq>
800        """
801
802        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
803        self.assertEqual('optionsSet', request.verb)
804        self.assertEqual(JID('user@example.org'), request.sender)
805        self.assertEqual(JID('pubsub.example.org'), request.recipient)
806        self.assertEqual('test', request.nodeIdentifier)
807        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
808        self.assertEqual({'pubsub#deliver': '1'}, request.options)
809
810
811    def test_fromElementOptionsSetCancel(self):
812        """
813        Test parsing a request for cancelling setting subscription options.
814        """
815
816        xml = """
817        <iq type='set' to='pubsub.example.org'
818                       from='user@example.org'>
819          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
820            <options node='test' jid='user@example.org/Home'>
821              <x xmlns='jabber:x:data' type='cancel'/>
822            </options>
823          </pubsub>
824        </iq>
825        """
826
827        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
828        self.assertEqual({}, request.options)
829
830
831    def test_fromElementOptionsSetBadFormType(self):
832        """
833        On a options set request unknown fields should be ignored.
834        """
835
836        xml = """
837        <iq type='set' to='pubsub.example.org'
838                       from='user@example.org'>
839          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
840            <options node='test' jid='user@example.org/Home'>
841              <x xmlns='jabber:x:data' type='result'>
842                <field var='FORM_TYPE' type='hidden'>
843                  <value>http://jabber.org/protocol/pubsub#node_config</value>
844                </field>
845                <field var='pubsub#deliver'><value>1</value></field>
846              </x>
847            </options>
848          </pubsub>
849        </iq>
850        """
851
852        err = self.assertRaises(error.StanzaError,
853                                pubsub.PubSubRequest.fromElement,
854                                parseXml(xml))
855        self.assertEqual('bad-request', err.condition)
856        self.assertEqual(None, err.appCondition)
857
858
859    def test_fromElementOptionsSetNoForm(self):
860        """
861        On a options set request a form is required.
862        """
863
864        xml = """
865        <iq type='set' to='pubsub.example.org'
866                       from='user@example.org'>
867          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
868            <options node='test' jid='user@example.org/Home'/>
869          </pubsub>
870        </iq>
871        """
872        err = self.assertRaises(error.StanzaError,
873                                pubsub.PubSubRequest.fromElement,
874                                parseXml(xml))
875        self.assertEqual('bad-request', err.condition)
876        self.assertEqual(None, err.appCondition)
877
878
879    def test_fromElementSubscriptions(self):
880        """
881        Test parsing a request for all subscriptions.
882        """
883
884        xml = """
885        <iq type='get' to='pubsub.example.org'
886                       from='user@example.org'>
887          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
888            <subscriptions/>
889          </pubsub>
890        </iq>
891        """
892
893        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
894        self.assertEqual('subscriptions', request.verb)
895        self.assertEqual(JID('user@example.org'), request.sender)
896        self.assertEqual(JID('pubsub.example.org'), request.recipient)
897
898
899    def test_fromElementAffiliations(self):
900        """
901        Test parsing a request for all affiliations.
902        """
903
904        xml = """
905        <iq type='get' to='pubsub.example.org'
906                       from='user@example.org'>
907          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
908            <affiliations/>
909          </pubsub>
910        </iq>
911        """
912
913        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
914        self.assertEqual('affiliations', request.verb)
915        self.assertEqual(JID('user@example.org'), request.sender)
916        self.assertEqual(JID('pubsub.example.org'), request.recipient)
917
918
919    def test_fromElementCreate(self):
920        """
921        Test parsing a request to create a node.
922        """
923
924        xml = """
925        <iq type='set' to='pubsub.example.org'
926                       from='user@example.org'>
927          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
928            <create node='mynode'/>
929          </pubsub>
930        </iq>
931        """
932
933        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
934        self.assertEqual('create', request.verb)
935        self.assertEqual(JID('user@example.org'), request.sender)
936        self.assertEqual(JID('pubsub.example.org'), request.recipient)
937        self.assertEqual('mynode', request.nodeIdentifier)
938
939
940    def test_fromElementCreateInstant(self):
941        """
942        Test parsing a request to create an instant node.
943        """
944
945        xml = """
946        <iq type='set' to='pubsub.example.org'
947                       from='user@example.org'>
948          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
949            <create/>
950          </pubsub>
951        </iq>
952        """
953
954        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
955        self.assertIdentical(None, request.nodeIdentifier)
956
957
958    def test_fromElementDefault(self):
959        """
960        Test parsing a request for the default node configuration.
961        """
962
963        xml = """
964        <iq type='get' to='pubsub.example.org'
965                       from='user@example.org'>
966          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
967            <default/>
968          </pubsub>
969        </iq>
970        """
971
972        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
973        self.assertEqual('default', request.verb)
974        self.assertEqual(JID('user@example.org'), request.sender)
975        self.assertEqual(JID('pubsub.example.org'), request.recipient)
976        self.assertEqual('leaf', request.nodeType)
977
978
979    def test_fromElementDefaultCollection(self):
980        """
981        Parsing a request for the default configuration extracts the node type.
982        """
983
984        xml = """
985        <iq type='get' to='pubsub.example.org'
986                       from='user@example.org'>
987          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
988            <default>
989              <x xmlns='jabber:x:data' type='submit'>
990                <field var='FORM_TYPE' type='hidden'>
991                  <value>http://jabber.org/protocol/pubsub#node_config</value>
992                </field>
993                <field var='pubsub#node_type'>
994                  <value>collection</value>
995                </field>
996              </x>
997            </default>
998
999          </pubsub>
1000        </iq>
1001        """
1002
1003        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1004        self.assertEqual('collection', request.nodeType)
1005
1006
1007    def test_fromElementConfigureGet(self):
1008        """
1009        Test parsing a node configuration get request.
1010        """
1011
1012        xml = """
1013        <iq type='get' to='pubsub.example.org'
1014                       from='user@example.org'>
1015          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1016            <configure node='test'/>
1017          </pubsub>
1018        </iq>
1019        """
1020
1021        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1022        self.assertEqual('configureGet', request.verb)
1023        self.assertEqual(JID('user@example.org'), request.sender)
1024        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1025        self.assertEqual('test', request.nodeIdentifier)
1026
1027
1028    def test_fromElementConfigureSet(self):
1029        """
1030        On a node configuration set request the Data Form is parsed.
1031        """
1032
1033        xml = """
1034        <iq type='set' to='pubsub.example.org'
1035                       from='user@example.org'>
1036          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1037            <configure node='test'>
1038              <x xmlns='jabber:x:data' type='submit'>
1039                <field var='FORM_TYPE' type='hidden'>
1040                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1041                </field>
1042                <field var='pubsub#deliver_payloads'><value>0</value></field>
1043                <field var='pubsub#persist_items'><value>1</value></field>
1044              </x>
1045            </configure>
1046          </pubsub>
1047        </iq>
1048        """
1049
1050        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1051        self.assertEqual('configureSet', request.verb)
1052        self.assertEqual(JID('user@example.org'), request.sender)
1053        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1054        self.assertEqual('test', request.nodeIdentifier)
1055        self.assertEqual({'pubsub#deliver_payloads': '0',
1056                          'pubsub#persist_items': '1'}, request.options)
1057
1058
1059    def test_fromElementConfigureSetCancel(self):
1060        """
1061        The node configuration is cancelled, so no options.
1062        """
1063
1064        xml = """
1065        <iq type='set' to='pubsub.example.org'
1066                       from='user@example.org'>
1067          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1068            <configure node='test'>
1069              <x xmlns='jabber:x:data' type='cancel'/>
1070            </configure>
1071          </pubsub>
1072        </iq>
1073        """
1074
1075        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1076        self.assertEqual({}, request.options)
1077
1078
1079    def test_fromElementConfigureSetBadFormType(self):
1080        """
1081        On a node configuration set request unknown fields should be ignored.
1082        """
1083
1084        xml = """
1085        <iq type='set' to='pubsub.example.org'
1086                       from='user@example.org'>
1087          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1088            <configure node='test'>
1089              <x xmlns='jabber:x:data' type='result'>
1090                <field var='FORM_TYPE' type='hidden'>
1091                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1092                </field>
1093                <field var='pubsub#deliver_payloads'><value>0</value></field>
1094                <field var='x-myfield'><value>1</value></field>
1095              </x>
1096            </configure>
1097          </pubsub>
1098        </iq>
1099        """
1100
1101        err = self.assertRaises(error.StanzaError,
1102                                pubsub.PubSubRequest.fromElement,
1103                                parseXml(xml))
1104        self.assertEqual('bad-request', err.condition)
1105        self.assertEqual(None, err.appCondition)
1106
1107
1108    def test_fromElementConfigureSetNoForm(self):
1109        """
1110        On a node configuration set request a form is required.
1111        """
1112
1113        xml = """
1114        <iq type='set' to='pubsub.example.org'
1115                       from='user@example.org'>
1116          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1117            <configure node='test'/>
1118          </pubsub>
1119        </iq>
1120        """
1121        err = self.assertRaises(error.StanzaError,
1122                                pubsub.PubSubRequest.fromElement,
1123                                parseXml(xml))
1124        self.assertEqual('bad-request', err.condition)
1125        self.assertEqual(None, err.appCondition)
1126
1127
1128    def test_fromElementItems(self):
1129        """
1130        Test parsing an items request.
1131        """
1132        xml = """
1133        <iq type='get' to='pubsub.example.org'
1134                       from='user@example.org'>
1135          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1136            <items node='test'/>
1137          </pubsub>
1138        </iq>
1139        """
1140
1141        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1142        self.assertEqual('items', request.verb)
1143        self.assertEqual(JID('user@example.org'), request.sender)
1144        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1145        self.assertEqual('test', request.nodeIdentifier)
1146        self.assertIdentical(None, request.maxItems)
1147        self.assertEqual([], request.itemIdentifiers)
1148
1149
1150    def test_fromElementRetract(self):
1151        """
1152        Test parsing a retract request.
1153        """
1154
1155        xml = """
1156        <iq type='set' to='pubsub.example.org'
1157                       from='user@example.org'>
1158          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1159            <retract node='test'>
1160              <item id='item1'/>
1161              <item id='item2'/>
1162            </retract>
1163          </pubsub>
1164        </iq>
1165        """
1166
1167        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1168        self.assertEqual('retract', request.verb)
1169        self.assertEqual(JID('user@example.org'), request.sender)
1170        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1171        self.assertEqual('test', request.nodeIdentifier)
1172        self.assertEqual(['item1', 'item2'], request.itemIdentifiers)
1173
1174
1175    def test_fromElementPurge(self):
1176        """
1177        Test parsing a purge request.
1178        """
1179
1180        xml = """
1181        <iq type='set' to='pubsub.example.org'
1182                       from='user@example.org'>
1183          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1184            <purge node='test'/>
1185          </pubsub>
1186        </iq>
1187        """
1188
1189        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1190        self.assertEqual('purge', request.verb)
1191        self.assertEqual(JID('user@example.org'), request.sender)
1192        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1193        self.assertEqual('test', request.nodeIdentifier)
1194
1195
1196    def test_fromElementDelete(self):
1197        """
1198        Test parsing a delete request.
1199        """
1200
1201        xml = """
1202        <iq type='set' to='pubsub.example.org'
1203                       from='user@example.org'>
1204          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1205            <delete node='test'/>
1206          </pubsub>
1207        </iq>
1208        """
1209
1210        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1211        self.assertEqual('delete', request.verb)
1212        self.assertEqual(JID('user@example.org'), request.sender)
1213        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1214        self.assertEqual('test', request.nodeIdentifier)
1215
1216
1217
1218class PubSubServiceTest(unittest.TestCase, TestableRequestHandlerMixin):
1219    """
1220    Tests for L{pubsub.PubSubService}.
1221    """
1222
1223    def setUp(self):
1224        self.stub = XmlStreamStub()
1225        self.service = pubsub.PubSubService()
1226        self.service.send = self.stub.xmlstream.send
1227
1228    def test_interface(self):
1229        """
1230        Do instances of L{pubsub.PubSubService} provide L{iwokkel.IPubSubService}?
1231        """
1232        verify.verifyObject(iwokkel.IPubSubService, self.service)
1233
1234
1235    def test_connectionMade(self):
1236        """
1237        Verify setup of observers in L{pubsub.connectionMade}.
1238        """
1239        requests = []
1240
1241        def handleRequest(iq):
1242            requests.append(iq)
1243
1244        self.service.xmlstream = self.stub.xmlstream
1245        self.service.handleRequest = handleRequest
1246        self.service.connectionMade()
1247
1248        for namespace in (NS_PUBSUB, NS_PUBSUB_OWNER):
1249            for stanzaType in ('get', 'set'):
1250                iq = domish.Element((None, 'iq'))
1251                iq['type'] = stanzaType
1252                iq.addElement((namespace, 'pubsub'))
1253                self.stub.xmlstream.dispatch(iq)
1254
1255        self.assertEqual(4, len(requests))
1256
1257
1258    def test_getDiscoInfo(self):
1259        """
1260        Test getDiscoInfo calls getNodeInfo and returns some minimal info.
1261        """
1262        def cb(info):
1263            self.assertEqual(2, len(info))
1264
1265        def getNodeInfo(requestor, target, nodeIdentifier):
1266            return defer.succeed(None)
1267
1268        self.service.getNodeInfo = getNodeInfo
1269        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1270                                      JID('pubsub.example.org'), '')
1271        d.addCallback(cb)
1272        return d
1273
1274
1275    def test_getDiscoInfoNodeType(self):
1276        """
1277        Test getDiscoInfo with node type.
1278        """
1279        def cb(info):
1280            discoInfo = disco.DiscoInfo()
1281            for item in info:
1282                discoInfo.append(item)
1283            self.assertIn(('pubsub', 'collection'), discoInfo.identities)
1284
1285        def getNodeInfo(requestor, target, nodeIdentifier):
1286            return defer.succeed({'type': 'collection',
1287                                  'meta-data': {}})
1288
1289        self.service.getNodeInfo = getNodeInfo
1290        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1291                                      JID('pubsub.example.org'), '')
1292        d.addCallback(cb)
1293        return d
1294
1295
1296    def test_getDiscoInfoMetaData(self):
1297        """
1298        Test getDiscoInfo with returned meta data.
1299        """
1300        def cb(info):
1301            discoInfo = disco.DiscoInfo()
1302            for item in info:
1303                discoInfo.append(item)
1304
1305            self.assertIn(('pubsub', 'leaf'), discoInfo.identities)
1306            self.assertIn(NS_PUBSUB_META_DATA, discoInfo.extensions)
1307            form = discoInfo.extensions[NS_PUBSUB_META_DATA]
1308            self.assertIn('pubsub#node_type', form.fields)
1309
1310        def getNodeInfo(requestor, target, nodeIdentifier):
1311            metaData = [{'var': 'pubsub#persist_items',
1312                         'label': 'Persist items to storage',
1313                         'value': True}]
1314            return defer.succeed({'type': 'leaf', 'meta-data': metaData})
1315
1316        self.service.getNodeInfo = getNodeInfo
1317        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1318                                      JID('pubsub.example.org'), '')
1319        d.addCallback(cb)
1320        return d
1321
1322
1323    def test_onPublish(self):
1324        """
1325        A publish request should result in L{PubSubService.publish} being
1326        called.
1327        """
1328
1329        xml = """
1330        <iq type='set' to='pubsub.example.org'
1331                       from='user@example.org'>
1332          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1333            <publish node='test'/>
1334          </pubsub>
1335        </iq>
1336        """
1337
1338        def publish(requestor, service, nodeIdentifier, items):
1339            return defer.succeed(None)
1340
1341        self.service.publish = publish
1342        verify.verifyObject(iwokkel.IPubSubService, self.service)
1343        return self.handleRequest(xml)
1344
1345
1346    def test_onSubscribe(self):
1347        """
1348        A successful subscription should return the current subscription.
1349        """
1350
1351        xml = """
1352        <iq type='set' to='pubsub.example.org'
1353                       from='user@example.org'>
1354          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1355            <subscribe node='test' jid='user@example.org/Home'/>
1356          </pubsub>
1357        </iq>
1358        """
1359
1360        def subscribe(requestor, service, nodeIdentifier, subscriber):
1361            return defer.succeed(pubsub.Subscription(nodeIdentifier,
1362                                                     subscriber,
1363                                                     'subscribed'))
1364
1365        def cb(element):
1366            self.assertEqual('pubsub', element.name)
1367            self.assertEqual(NS_PUBSUB, element.uri)
1368            subscription = element.subscription
1369            self.assertEqual(NS_PUBSUB, subscription.uri)
1370            self.assertEqual('test', subscription['node'])
1371            self.assertEqual('user@example.org/Home', subscription['jid'])
1372            self.assertEqual('subscribed', subscription['subscription'])
1373
1374        self.service.subscribe = subscribe
1375        verify.verifyObject(iwokkel.IPubSubService, self.service)
1376        d = self.handleRequest(xml)
1377        d.addCallback(cb)
1378        return d
1379
1380
1381    def test_onSubscribeEmptyNode(self):
1382        """
1383        A successful subscription on root node should return no node attribute.
1384        """
1385
1386        xml = """
1387        <iq type='set' to='pubsub.example.org'
1388                       from='user@example.org'>
1389          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1390            <subscribe jid='user@example.org/Home'/>
1391          </pubsub>
1392        </iq>
1393        """
1394
1395        def subscribe(requestor, service, nodeIdentifier, subscriber):
1396            return defer.succeed(pubsub.Subscription(nodeIdentifier,
1397                                                     subscriber,
1398                                                     'subscribed'))
1399
1400        def cb(element):
1401            self.assertFalse(element.subscription.hasAttribute('node'))
1402
1403        self.service.subscribe = subscribe
1404        verify.verifyObject(iwokkel.IPubSubService, self.service)
1405        d = self.handleRequest(xml)
1406        d.addCallback(cb)
1407        return d
1408
1409
1410    def test_onUnsubscribe(self):
1411        """
1412        A successful unsubscription should return an empty response.
1413        """
1414
1415        xml = """
1416        <iq type='set' to='pubsub.example.org'
1417                       from='user@example.org'>
1418          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1419            <unsubscribe node='test' jid='user@example.org/Home'/>
1420          </pubsub>
1421        </iq>
1422        """
1423
1424        def unsubscribe(requestor, service, nodeIdentifier, subscriber):
1425            return defer.succeed(None)
1426
1427        def cb(element):
1428            self.assertIdentical(None, element)
1429
1430        self.service.unsubscribe = unsubscribe
1431        verify.verifyObject(iwokkel.IPubSubService, self.service)
1432        d = self.handleRequest(xml)
1433        d.addCallback(cb)
1434        return d
1435
1436
1437    def test_onOptionsGet(self):
1438        """
1439        Getting subscription options is not supported.
1440        """
1441
1442        xml = """
1443        <iq type='get' to='pubsub.example.org'
1444                       from='user@example.org'>
1445          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1446            <options node='test' jid='user@example.org/Home'/>
1447          </pubsub>
1448        </iq>
1449        """
1450
1451        def cb(result):
1452            self.assertEquals('feature-not-implemented', result.condition)
1453            self.assertEquals('unsupported', result.appCondition.name)
1454            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
1455
1456        d = self.handleRequest(xml)
1457        self.assertFailure(d, error.StanzaError)
1458        d.addCallback(cb)
1459        return d
1460
1461
1462    def test_onOptionsSet(self):
1463        """
1464        Setting subscription options is not supported.
1465        """
1466
1467        xml = """
1468        <iq type='set' to='pubsub.example.org'
1469                       from='user@example.org'>
1470          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1471            <options node='test' jid='user@example.org/Home'>
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        def cb(result):
1484            self.assertEquals('feature-not-implemented', result.condition)
1485            self.assertEquals('unsupported', result.appCondition.name)
1486            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
1487
1488        d = self.handleRequest(xml)
1489        self.assertFailure(d, error.StanzaError)
1490        d.addCallback(cb)
1491        return d
1492
1493
1494    def test_onSubscriptions(self):
1495        """
1496        A subscriptions request should result in
1497        L{PubSubService.subscriptions} being called and the result prepared
1498        for the response.
1499        """
1500
1501        xml = """
1502        <iq type='get' to='pubsub.example.org'
1503                       from='user@example.org'>
1504          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1505            <subscriptions/>
1506          </pubsub>
1507        </iq>
1508        """
1509
1510        def cb(element):
1511            self.assertEqual('pubsub', element.name)
1512            self.assertEqual(NS_PUBSUB, element.uri)
1513            self.assertEqual(NS_PUBSUB, element.subscriptions.uri)
1514            children = list(element.subscriptions.elements())
1515            self.assertEqual(1, len(children))
1516            subscription = children[0]
1517            self.assertEqual('subscription', subscription.name)
1518            self.assertEqual(NS_PUBSUB, subscription.uri)
1519            self.assertEqual('user@example.org', subscription['jid'])
1520            self.assertEqual('test', subscription['node'])
1521            self.assertEqual('subscribed', subscription['subscription'])
1522
1523
1524        def subscriptions(requestor, service):
1525            subscription = pubsub.Subscription('test', JID('user@example.org'),
1526                                               'subscribed')
1527            return defer.succeed([subscription])
1528
1529        self.service.subscriptions = subscriptions
1530        verify.verifyObject(iwokkel.IPubSubService, self.service)
1531        d = self.handleRequest(xml)
1532        d.addCallback(cb)
1533        return d
1534
1535
1536    def test_onAffiliations(self):
1537        """
1538        A subscriptions request should result in
1539        L{PubSubService.affiliations} being called and the result prepared
1540        for the response.
1541        """
1542
1543        xml = """
1544        <iq type='get' to='pubsub.example.org'
1545                       from='user@example.org'>
1546          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1547            <affiliations/>
1548          </pubsub>
1549        </iq>
1550        """
1551
1552        def cb(element):
1553            self.assertEqual('pubsub', element.name)
1554            self.assertEqual(NS_PUBSUB, element.uri)
1555            self.assertEqual(NS_PUBSUB, element.affiliations.uri)
1556            children = list(element.affiliations.elements())
1557            self.assertEqual(1, len(children))
1558            affiliation = children[0]
1559            self.assertEqual('affiliation', affiliation.name)
1560            self.assertEqual(NS_PUBSUB, affiliation.uri)
1561            self.assertEqual('test', affiliation['node'])
1562            self.assertEqual('owner', affiliation['affiliation'])
1563
1564
1565        def affiliations(requestor, service):
1566            affiliation = ('test', 'owner')
1567            return defer.succeed([affiliation])
1568
1569        self.service.affiliations = affiliations
1570        verify.verifyObject(iwokkel.IPubSubService, self.service)
1571        d = self.handleRequest(xml)
1572        d.addCallback(cb)
1573        return d
1574
1575
1576    def test_onCreate(self):
1577        """
1578        Replies to create node requests don't return the created node.
1579        """
1580
1581        xml = """
1582        <iq type='set' to='pubsub.example.org'
1583                       from='user@example.org'>
1584          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1585            <create node='mynode'/>
1586          </pubsub>
1587        </iq>
1588        """
1589
1590        def create(requestor, service, nodeIdentifier):
1591            return defer.succeed(nodeIdentifier)
1592
1593        def cb(element):
1594            self.assertIdentical(None, element)
1595
1596        self.service.create = create
1597        verify.verifyObject(iwokkel.IPubSubService, self.service)
1598        d = self.handleRequest(xml)
1599        d.addCallback(cb)
1600        return d
1601
1602
1603    def test_onCreateChanged(self):
1604        """
1605        Replies to create node requests return the created node if changed.
1606        """
1607
1608        xml = """
1609        <iq type='set' to='pubsub.example.org'
1610                       from='user@example.org'>
1611          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1612            <create node='mynode'/>
1613          </pubsub>
1614        </iq>
1615        """
1616
1617        def create(requestor, service, nodeIdentifier):
1618            return defer.succeed(u'myrenamednode')
1619
1620        def cb(element):
1621            self.assertEqual('pubsub', element.name)
1622            self.assertEqual(NS_PUBSUB, element.uri)
1623            self.assertEqual(NS_PUBSUB, element.create.uri)
1624            self.assertEqual(u'myrenamednode',
1625                             element.create.getAttribute('node'))
1626
1627        self.service.create = create
1628        verify.verifyObject(iwokkel.IPubSubService, self.service)
1629        d = self.handleRequest(xml)
1630        d.addCallback(cb)
1631        return d
1632
1633
1634    def test_onCreateInstant(self):
1635        """
1636        Replies to create instant node requests return the created node.
1637        """
1638
1639        xml = """
1640        <iq type='set' to='pubsub.example.org'
1641                       from='user@example.org'>
1642          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1643            <create/>
1644          </pubsub>
1645        </iq>
1646        """
1647
1648        def create(requestor, service, nodeIdentifier):
1649            return defer.succeed(u'random')
1650
1651        def cb(element):
1652            self.assertEqual('pubsub', element.name)
1653            self.assertEqual(NS_PUBSUB, element.uri)
1654            self.assertEqual(NS_PUBSUB, element.create.uri)
1655            self.assertEqual(u'random', element.create.getAttribute('node'))
1656
1657        self.service.create = create
1658        verify.verifyObject(iwokkel.IPubSubService, self.service)
1659        d = self.handleRequest(xml)
1660        d.addCallback(cb)
1661        return d
1662
1663
1664    def test_onDefault(self):
1665        """
1666        A default request should result in
1667        L{PubSubService.getDefaultConfiguration} being called.
1668        """
1669
1670        xml = """
1671        <iq type='get' to='pubsub.example.org'
1672                       from='user@example.org'>
1673          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1674            <default/>
1675          </pubsub>
1676        </iq>
1677        """
1678
1679        def getConfigurationOptions():
1680            return {
1681                "pubsub#persist_items":
1682                    {"type": "boolean",
1683                     "label": "Persist items to storage"},
1684                "pubsub#deliver_payloads":
1685                    {"type": "boolean",
1686                     "label": "Deliver payloads with event notifications"}
1687                }
1688
1689        def getDefaultConfiguration(requestor, service, nodeType):
1690            return defer.succeed({})
1691
1692        def cb(element):
1693            self.assertEqual('pubsub', element.name)
1694            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
1695            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
1696            form = data_form.Form.fromElement(element.default.x)
1697            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
1698
1699        self.service.getConfigurationOptions = getConfigurationOptions
1700        self.service.getDefaultConfiguration = getDefaultConfiguration
1701        verify.verifyObject(iwokkel.IPubSubService, self.service)
1702        d = self.handleRequest(xml)
1703        d.addCallback(cb)
1704        return d
1705
1706
1707    def test_onDefaultCollection(self):
1708        """
1709        Responses to default requests should depend on passed node type.
1710        """
1711
1712        xml = """
1713        <iq type='get' to='pubsub.example.org'
1714                       from='user@example.org'>
1715          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1716            <default>
1717              <x xmlns='jabber:x:data' type='submit'>
1718                <field var='FORM_TYPE' type='hidden'>
1719                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1720                </field>
1721                <field var='pubsub#node_type'>
1722                  <value>collection</value>
1723                </field>
1724              </x>
1725            </default>
1726
1727          </pubsub>
1728        </iq>
1729        """
1730
1731        def getConfigurationOptions():
1732            return {
1733                "pubsub#deliver_payloads":
1734                    {"type": "boolean",
1735                     "label": "Deliver payloads with event notifications"}
1736                }
1737
1738        def getDefaultConfiguration(requestor, service, nodeType):
1739            return defer.succeed({})
1740
1741        self.service.getConfigurationOptions = getConfigurationOptions
1742        self.service.getDefaultConfiguration = getDefaultConfiguration
1743        verify.verifyObject(iwokkel.IPubSubService, self.service)
1744        return self.handleRequest(xml)
1745
1746
1747    def test_onDefaultUnknownNodeType(self):
1748        """
1749        A default request should result in
1750        L{PubSubService.getDefaultConfiguration} being called.
1751        """
1752
1753        xml = """
1754        <iq type='get' to='pubsub.example.org'
1755                       from='user@example.org'>
1756          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1757            <default>
1758              <x xmlns='jabber:x:data' type='submit'>
1759                <field var='FORM_TYPE' type='hidden'>
1760                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1761                </field>
1762                <field var='pubsub#node_type'>
1763                  <value>unknown</value>
1764                </field>
1765              </x>
1766            </default>
1767
1768          </pubsub>
1769        </iq>
1770        """
1771
1772        def getDefaultConfiguration(requestor, service, nodeType):
1773            self.fail("Unexpected call to getConfiguration")
1774
1775        def cb(result):
1776            self.assertEquals('not-acceptable', result.condition)
1777
1778        self.service.getDefaultConfiguration = getDefaultConfiguration
1779        verify.verifyObject(iwokkel.IPubSubService, self.service)
1780        d = self.handleRequest(xml)
1781        self.assertFailure(d, error.StanzaError)
1782        d.addCallback(cb)
1783        return d
1784
1785
1786    def test_onConfigureGet(self):
1787        """
1788        On a node configuration get request L{PubSubService.getConfiguration}
1789        is called and results in a data form with the configuration.
1790        """
1791
1792        xml = """
1793        <iq type='get' to='pubsub.example.org'
1794                       from='user@example.org'>
1795          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1796            <configure node='test'/>
1797          </pubsub>
1798        </iq>
1799        """
1800
1801        def getConfigurationOptions():
1802            return {
1803                "pubsub#persist_items":
1804                    {"type": "boolean",
1805                     "label": "Persist items to storage"},
1806                "pubsub#deliver_payloads":
1807                    {"type": "boolean",
1808                     "label": "Deliver payloads with event notifications"},
1809                "pubsub#owner":
1810                    {"type": "jid-single",
1811                     "label": "Owner of the node"}
1812                }
1813
1814        def getConfiguration(requestor, service, nodeIdentifier):
1815            return defer.succeed({'pubsub#deliver_payloads': '0',
1816                                  'pubsub#persist_items': '1',
1817                                  'pubsub#owner': JID('user@example.org'),
1818                                  'x-myfield': ['a', 'b']})
1819
1820        def cb(element):
1821            self.assertEqual('pubsub', element.name)
1822            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
1823            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
1824            form = data_form.Form.fromElement(element.configure.x)
1825            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
1826            fields = form.fields
1827
1828            self.assertIn('pubsub#deliver_payloads', fields)
1829            field = fields['pubsub#deliver_payloads']
1830            self.assertEqual('boolean', field.fieldType)
1831            field.typeCheck()
1832            self.assertEqual(False, field.value)
1833
1834            self.assertIn('pubsub#persist_items', fields)
1835            field = fields['pubsub#persist_items']
1836            self.assertEqual('boolean', field.fieldType)
1837            field.typeCheck()
1838            self.assertEqual(True, field.value)
1839
1840            self.assertIn('pubsub#owner', fields)
1841            field = fields['pubsub#owner']
1842            self.assertEqual('jid-single', field.fieldType)
1843            field.typeCheck()
1844            self.assertEqual(JID('user@example.org'), field.value)
1845
1846            self.assertNotIn('x-myfield', fields)
1847
1848
1849        self.service.getConfigurationOptions = getConfigurationOptions
1850        self.service.getConfiguration = getConfiguration
1851        verify.verifyObject(iwokkel.IPubSubService, self.service)
1852        d = self.handleRequest(xml)
1853        d.addCallback(cb)
1854        return d
1855
1856
1857    def test_onConfigureSet(self):
1858        """
1859        On a node configuration set request the Data Form is parsed and
1860        L{PubSubService.setConfiguration} is called with the passed options.
1861        """
1862
1863        xml = """
1864        <iq type='set' to='pubsub.example.org'
1865                       from='user@example.org'>
1866          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1867            <configure node='test'>
1868              <x xmlns='jabber:x:data' type='submit'>
1869                <field var='FORM_TYPE' type='hidden'>
1870                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1871                </field>
1872                <field var='pubsub#deliver_payloads'><value>0</value></field>
1873                <field var='pubsub#persist_items'><value>1</value></field>
1874              </x>
1875            </configure>
1876          </pubsub>
1877        </iq>
1878        """
1879
1880        def getConfigurationOptions():
1881            return {
1882                "pubsub#persist_items":
1883                    {"type": "boolean",
1884                     "label": "Persist items to storage"},
1885                "pubsub#deliver_payloads":
1886                    {"type": "boolean",
1887                     "label": "Deliver payloads with event notifications"}
1888                }
1889
1890        def setConfiguration(requestor, service, nodeIdentifier, options):
1891            self.assertEqual({'pubsub#deliver_payloads': False,
1892                              'pubsub#persist_items': True}, options)
1893            return defer.succeed(None)
1894
1895        self.service.getConfigurationOptions = getConfigurationOptions
1896        self.service.setConfiguration = setConfiguration
1897        verify.verifyObject(iwokkel.IPubSubService, self.service)
1898        return self.handleRequest(xml)
1899
1900
1901    def test_onConfigureSetCancel(self):
1902        """
1903        The node configuration is cancelled, L{PubSubService.setConfiguration}
1904        not called.
1905        """
1906
1907        xml = """
1908        <iq type='set' to='pubsub.example.org'
1909                       from='user@example.org'>
1910          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1911            <configure node='test'>
1912              <x xmlns='jabber:x:data' type='cancel'>
1913                <field var='FORM_TYPE' type='hidden'>
1914                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1915                </field>
1916              </x>
1917            </configure>
1918          </pubsub>
1919        </iq>
1920        """
1921
1922        def setConfiguration(requestor, service, nodeIdentifier, options):
1923            self.fail("Unexpected call to setConfiguration")
1924
1925        self.service.setConfiguration = setConfiguration
1926        verify.verifyObject(iwokkel.IPubSubService, self.service)
1927        return self.handleRequest(xml)
1928
1929
1930    def test_onConfigureSetIgnoreUnknown(self):
1931        """
1932        On a node configuration set request unknown fields should be ignored.
1933        """
1934
1935        xml = """
1936        <iq type='set' to='pubsub.example.org'
1937                       from='user@example.org'>
1938          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1939            <configure node='test'>
1940              <x xmlns='jabber:x:data' type='submit'>
1941                <field var='FORM_TYPE' type='hidden'>
1942                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1943                </field>
1944                <field var='pubsub#deliver_payloads'><value>0</value></field>
1945                <field var='x-myfield'><value>1</value></field>
1946              </x>
1947            </configure>
1948          </pubsub>
1949        </iq>
1950        """
1951
1952        def getConfigurationOptions():
1953            return {
1954                "pubsub#persist_items":
1955                    {"type": "boolean",
1956                     "label": "Persist items to storage"},
1957                "pubsub#deliver_payloads":
1958                    {"type": "boolean",
1959                     "label": "Deliver payloads with event notifications"}
1960                }
1961
1962        def setConfiguration(requestor, service, nodeIdentifier, options):
1963            self.assertEquals(['pubsub#deliver_payloads'], options.keys())
1964
1965        self.service.getConfigurationOptions = getConfigurationOptions
1966        self.service.setConfiguration = setConfiguration
1967        verify.verifyObject(iwokkel.IPubSubService, self.service)
1968        return self.handleRequest(xml)
1969
1970
1971    def test_onConfigureSetBadFormType(self):
1972        """
1973        On a node configuration set request unknown fields should be ignored.
1974        """
1975
1976        xml = """
1977        <iq type='set' to='pubsub.example.org'
1978                       from='user@example.org'>
1979          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1980            <configure node='test'>
1981              <x xmlns='jabber:x:data' type='result'>
1982                <field var='FORM_TYPE' type='hidden'>
1983                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1984                </field>
1985                <field var='pubsub#deliver_payloads'><value>0</value></field>
1986                <field var='x-myfield'><value>1</value></field>
1987              </x>
1988            </configure>
1989          </pubsub>
1990        </iq>
1991        """
1992
1993        def cb(result):
1994            self.assertEquals('bad-request', result.condition)
1995
1996        d = self.handleRequest(xml)
1997        self.assertFailure(d, error.StanzaError)
1998        d.addCallback(cb)
1999        return d
2000
2001
2002    def test_onItems(self):
2003        """
2004        On a items request, return all items for the given node.
2005        """
2006        xml = """
2007        <iq type='get' to='pubsub.example.org'
2008                       from='user@example.org'>
2009          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2010            <items node='test'/>
2011          </pubsub>
2012        </iq>
2013        """
2014
2015        def items(requestor, service, nodeIdentifier, maxItems,
2016                  itemIdentifiers):
2017            return defer.succeed([pubsub.Item('current')])
2018
2019        def cb(element):
2020            self.assertEqual(NS_PUBSUB, element.uri)
2021            self.assertEqual(NS_PUBSUB, element.items.uri)
2022            self.assertEqual(1, len(element.items.children))
2023            item = element.items.children[-1]
2024            self.assertTrue(domish.IElement.providedBy(item))
2025            self.assertEqual('item', item.name)
2026            self.assertEqual(NS_PUBSUB, item.uri)
2027            self.assertEqual('current', item['id'])
2028
2029        self.service.items = items
2030        d = self.handleRequest(xml)
2031        d.addCallback(cb)
2032        return d
2033
2034
2035    def test_onRetract(self):
2036        """
2037        A retract request should result in L{PubSubService.retract} being
2038        called.
2039        """
2040
2041        xml = """
2042        <iq type='set' to='pubsub.example.org'
2043                       from='user@example.org'>
2044          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2045            <retract node='test'>
2046              <item id='item1'/>
2047              <item id='item2'/>
2048            </retract>
2049          </pubsub>
2050        </iq>
2051        """
2052
2053        def retract(requestor, service, nodeIdentifier, itemIdentifiers):
2054            return defer.succeed(None)
2055
2056        self.service.retract = retract
2057        return self.handleRequest(xml)
2058
2059
2060    def test_onPurge(self):
2061        """
2062        A purge request should result in L{PubSubService.purge} being
2063        called.
2064        """
2065
2066        xml = """
2067        <iq type='set' to='pubsub.example.org'
2068                       from='user@example.org'>
2069          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2070            <purge node='test'/>
2071          </pubsub>
2072        </iq>
2073        """
2074
2075        def purge(requestor, service, nodeIdentifier):
2076            return defer.succeed(None)
2077
2078        self.service.purge = purge
2079        return self.handleRequest(xml)
2080
2081
2082    def test_onDelete(self):
2083        """
2084        A delete request should result in L{PubSubService.delete} being
2085        called.
2086        """
2087
2088        xml = """
2089        <iq type='set' to='pubsub.example.org'
2090                       from='user@example.org'>
2091          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2092            <delete node='test'/>
2093          </pubsub>
2094        </iq>
2095        """
2096
2097        def delete(requestor, service, nodeIdentifier):
2098            return defer.succeed(None)
2099
2100        self.service.delete = delete
2101        return self.handleRequest(xml)
2102
2103
2104    def test_notifyDelete(self):
2105        """
2106        Subscribers should be sent a delete notification.
2107        """
2108        subscriptions = [JID('user@example.org')]
2109        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
2110                                  subscriptions)
2111        message = self.stub.output[-1]
2112
2113        self.assertEquals('message', message.name)
2114        self.assertIdentical(None, message.uri)
2115        self.assertEquals('user@example.org', message['to'])
2116        self.assertEquals('pubsub.example.org', message['from'])
2117        self.assertTrue(message.event)
2118        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
2119        self.assertTrue(message.event.delete)
2120        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
2121        self.assertTrue(message.event.delete.hasAttribute('node'))
2122        self.assertEqual('test', message.event.delete['node'])
2123
2124
2125    def test_notifyDeleteRedirect(self):
2126        """
2127        Subscribers should be sent a delete notification with redirect.
2128        """
2129        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
2130        subscriptions = [JID('user@example.org')]
2131        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
2132                                  subscriptions, redirectURI)
2133        message = self.stub.output[-1]
2134
2135        self.assertEquals('message', message.name)
2136        self.assertIdentical(None, message.uri)
2137        self.assertEquals('user@example.org', message['to'])
2138        self.assertEquals('pubsub.example.org', message['from'])
2139        self.assertTrue(message.event)
2140        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
2141        self.assertTrue(message.event.delete)
2142        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
2143        self.assertTrue(message.event.delete.hasAttribute('node'))
2144        self.assertEqual('test', message.event.delete['node'])
2145        self.assertTrue(message.event.delete.redirect)
2146        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
2147        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
2148        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
2149
2150
2151    def test_onSubscriptionsGet(self):
2152        """
2153        Getting subscription options is not supported.
2154        """
2155
2156        xml = """
2157        <iq type='get' to='pubsub.example.org'
2158                       from='user@example.org'>
2159          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2160            <subscriptions/>
2161          </pubsub>
2162        </iq>
2163        """
2164
2165        def cb(result):
2166            self.assertEquals('feature-not-implemented', result.condition)
2167            self.assertEquals('unsupported', result.appCondition.name)
2168            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2169            self.assertEquals('manage-subscriptions',
2170                              result.appCondition['feature'])
2171
2172        d = self.handleRequest(xml)
2173        self.assertFailure(d, error.StanzaError)
2174        d.addCallback(cb)
2175        return d
2176
2177
2178    def test_onSubscriptionsSet(self):
2179        """
2180        Setting subscription options is not supported.
2181        """
2182
2183        xml = """
2184        <iq type='set' to='pubsub.example.org'
2185                       from='user@example.org'>
2186          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2187            <subscriptions/>
2188          </pubsub>
2189        </iq>
2190        """
2191
2192        def cb(result):
2193            self.assertEquals('feature-not-implemented', result.condition)
2194            self.assertEquals('unsupported', result.appCondition.name)
2195            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2196            self.assertEquals('manage-subscriptions',
2197                              result.appCondition['feature'])
2198
2199        d = self.handleRequest(xml)
2200        self.assertFailure(d, error.StanzaError)
2201        d.addCallback(cb)
2202        return d
2203
2204
2205    def test_onAffiliationsGet(self):
2206        """
2207        Getting subscription options is not supported.
2208        """
2209
2210        xml = """
2211        <iq type='get' to='pubsub.example.org'
2212                       from='user@example.org'>
2213          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2214            <affiliations/>
2215          </pubsub>
2216        </iq>
2217        """
2218
2219        def cb(result):
2220            self.assertEquals('feature-not-implemented', result.condition)
2221            self.assertEquals('unsupported', result.appCondition.name)
2222            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2223            self.assertEquals('modify-affiliations',
2224                              result.appCondition['feature'])
2225
2226        d = self.handleRequest(xml)
2227        self.assertFailure(d, error.StanzaError)
2228        d.addCallback(cb)
2229        return d
2230
2231
2232    def test_onAffiliationsSet(self):
2233        """
2234        Setting subscription options is not supported.
2235        """
2236
2237        xml = """
2238        <iq type='set' to='pubsub.example.org'
2239                       from='user@example.org'>
2240          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2241            <affiliations/>
2242          </pubsub>
2243        </iq>
2244        """
2245
2246        def cb(result):
2247            self.assertEquals('feature-not-implemented', result.condition)
2248            self.assertEquals('unsupported', result.appCondition.name)
2249            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2250            self.assertEquals('modify-affiliations',
2251                              result.appCondition['feature'])
2252
2253        d = self.handleRequest(xml)
2254        self.assertFailure(d, error.StanzaError)
2255        d.addCallback(cb)
2256        return d
2257
2258
2259    def test_publish(self):
2260        """
2261        Non-overridden L{PubSubService.publish} yields unsupported error.
2262        """
2263
2264        xml = """
2265        <iq type='set' to='pubsub.example.org'
2266                       from='user@example.org'>
2267          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2268            <publish node='mynode'/>
2269          </pubsub>
2270        </iq>
2271        """
2272
2273        def cb(result):
2274            self.assertEquals('feature-not-implemented', result.condition)
2275            self.assertEquals('unsupported', result.appCondition.name)
2276            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2277            self.assertEquals('publish', result.appCondition['feature'])
2278
2279        d = self.handleRequest(xml)
2280        self.assertFailure(d, error.StanzaError)
2281        d.addCallback(cb)
2282        return d
2283
2284
2285    def test_subscribe(self):
2286        """
2287        Non-overridden L{PubSubService.subscribe} yields unsupported error.
2288        """
2289
2290        xml = """
2291        <iq type='set' to='pubsub.example.org'
2292                       from='user@example.org'>
2293          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2294            <subscribe node='test' jid='user@example.org/Home'/>
2295          </pubsub>
2296        </iq>
2297        """
2298
2299        def cb(result):
2300            self.assertEquals('feature-not-implemented', result.condition)
2301            self.assertEquals('unsupported', result.appCondition.name)
2302            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2303            self.assertEquals('subscribe', result.appCondition['feature'])
2304
2305        d = self.handleRequest(xml)
2306        self.assertFailure(d, error.StanzaError)
2307        d.addCallback(cb)
2308        return d
2309
2310
2311    def test_unsubscribe(self):
2312        """
2313        Non-overridden L{PubSubService.unsubscribe} yields unsupported error.
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            <unsubscribe node='test' jid='user@example.org/Home'/>
2321          </pubsub>
2322        </iq>
2323        """
2324
2325        def cb(result):
2326            self.assertEquals('feature-not-implemented', result.condition)
2327            self.assertEquals('unsupported', result.appCondition.name)
2328            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2329            self.assertEquals('subscribe', result.appCondition['feature'])
2330
2331        d = self.handleRequest(xml)
2332        self.assertFailure(d, error.StanzaError)
2333        d.addCallback(cb)
2334        return d
2335
2336
2337    def test_subscriptions(self):
2338        """
2339        Non-overridden L{PubSubService.subscriptions} yields unsupported error.
2340        """
2341
2342        xml = """
2343        <iq type='get' to='pubsub.example.org'
2344                       from='user@example.org'>
2345          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2346            <subscriptions/>
2347          </pubsub>
2348        </iq>
2349        """
2350
2351        def cb(result):
2352            self.assertEquals('feature-not-implemented', result.condition)
2353            self.assertEquals('unsupported', result.appCondition.name)
2354            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2355            self.assertEquals('retrieve-subscriptions',
2356                              result.appCondition['feature'])
2357
2358        d = self.handleRequest(xml)
2359        self.assertFailure(d, error.StanzaError)
2360        d.addCallback(cb)
2361        return d
2362
2363
2364    def test_affiliations(self):
2365        """
2366        Non-overridden L{PubSubService.affiliations} yields unsupported error.
2367        """
2368
2369        xml = """
2370        <iq type='get' to='pubsub.example.org'
2371                       from='user@example.org'>
2372          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2373            <affiliations/>
2374          </pubsub>
2375        </iq>
2376        """
2377
2378        def cb(result):
2379            self.assertEquals('feature-not-implemented', result.condition)
2380            self.assertEquals('unsupported', result.appCondition.name)
2381            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2382            self.assertEquals('retrieve-affiliations',
2383                              result.appCondition['feature'])
2384
2385        d = self.handleRequest(xml)
2386        self.assertFailure(d, error.StanzaError)
2387        d.addCallback(cb)
2388        return d
2389
2390
2391    def test_create(self):
2392        """
2393        Non-overridden L{PubSubService.create} yields unsupported error.
2394        """
2395
2396        xml = """
2397        <iq type='set' to='pubsub.example.org'
2398                       from='user@example.org'>
2399          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2400            <create node='mynode'/>
2401          </pubsub>
2402        </iq>
2403        """
2404
2405        def cb(result):
2406            self.assertEquals('feature-not-implemented', result.condition)
2407            self.assertEquals('unsupported', result.appCondition.name)
2408            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2409            self.assertEquals('create-nodes', result.appCondition['feature'])
2410
2411        d = self.handleRequest(xml)
2412        self.assertFailure(d, error.StanzaError)
2413        d.addCallback(cb)
2414        return d
2415
2416
2417    def test_getDefaultConfiguration(self):
2418        """
2419        Non-overridden L{PubSubService.getDefaultConfiguration} yields
2420        unsupported error.
2421        """
2422
2423        xml = """
2424        <iq type='get' to='pubsub.example.org'
2425                       from='user@example.org'>
2426          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2427            <default/>
2428          </pubsub>
2429        </iq>
2430        """
2431
2432        def cb(result):
2433            self.assertEquals('feature-not-implemented', result.condition)
2434            self.assertEquals('unsupported', result.appCondition.name)
2435            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2436            self.assertEquals('retrieve-default', result.appCondition['feature'])
2437
2438        d = self.handleRequest(xml)
2439        self.assertFailure(d, error.StanzaError)
2440        d.addCallback(cb)
2441        return d
2442
2443
2444    def test_getConfiguration(self):
2445        """
2446        Non-overridden L{PubSubService.getConfiguration} yields unsupported
2447        error.
2448        """
2449
2450        xml = """
2451        <iq type='get' to='pubsub.example.org'
2452                       from='user@example.org'>
2453          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2454            <configure/>
2455          </pubsub>
2456        </iq>
2457        """
2458
2459        def cb(result):
2460            self.assertEquals('feature-not-implemented', result.condition)
2461            self.assertEquals('unsupported', result.appCondition.name)
2462            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2463            self.assertEquals('config-node', result.appCondition['feature'])
2464
2465        d = self.handleRequest(xml)
2466        self.assertFailure(d, error.StanzaError)
2467        d.addCallback(cb)
2468        return d
2469
2470
2471    def test_setConfiguration(self):
2472        """
2473        Non-overridden L{PubSubService.setConfiguration} yields unsupported
2474        error.
2475        """
2476
2477        xml = """
2478        <iq type='set' to='pubsub.example.org'
2479                       from='user@example.org'>
2480          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2481            <configure node='test'>
2482              <x xmlns='jabber:x:data' type='submit'>
2483                <field var='FORM_TYPE' type='hidden'>
2484                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2485                </field>
2486                <field var='pubsub#deliver_payloads'><value>0</value></field>
2487                <field var='pubsub#persist_items'><value>1</value></field>
2488              </x>
2489            </configure>
2490          </pubsub>
2491        </iq>
2492        """
2493
2494        def cb(result):
2495            self.assertEquals('feature-not-implemented', result.condition)
2496            self.assertEquals('unsupported', result.appCondition.name)
2497            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2498            self.assertEquals('config-node', result.appCondition['feature'])
2499
2500        d = self.handleRequest(xml)
2501        self.assertFailure(d, error.StanzaError)
2502        d.addCallback(cb)
2503        return d
2504
2505
2506    def test_items(self):
2507        """
2508        Non-overridden L{PubSubService.items} yields unsupported error.
2509        """
2510        xml = """
2511        <iq type='get' to='pubsub.example.org'
2512                       from='user@example.org'>
2513          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2514            <items node='test'/>
2515          </pubsub>
2516        </iq>
2517        """
2518
2519        def cb(result):
2520            self.assertEquals('feature-not-implemented', result.condition)
2521            self.assertEquals('unsupported', result.appCondition.name)
2522            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2523            self.assertEquals('retrieve-items', result.appCondition['feature'])
2524
2525        d = self.handleRequest(xml)
2526        self.assertFailure(d, error.StanzaError)
2527        d.addCallback(cb)
2528        return d
2529
2530
2531    def test_retract(self):
2532        """
2533        Non-overridden L{PubSubService.retract} yields unsupported error.
2534        """
2535        xml = """
2536        <iq type='set' to='pubsub.example.org'
2537                       from='user@example.org'>
2538          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2539            <retract node='test'>
2540              <item id='item1'/>
2541              <item id='item2'/>
2542            </retract>
2543          </pubsub>
2544        </iq>
2545        """
2546
2547        def cb(result):
2548            self.assertEquals('feature-not-implemented', result.condition)
2549            self.assertEquals('unsupported', result.appCondition.name)
2550            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2551            self.assertEquals('retract-items', result.appCondition['feature'])
2552
2553        d = self.handleRequest(xml)
2554        self.assertFailure(d, error.StanzaError)
2555        d.addCallback(cb)
2556        return d
2557
2558
2559    def test_purge(self):
2560        """
2561        Non-overridden L{PubSubService.purge} yields unsupported error.
2562        """
2563        xml = """
2564        <iq type='set' to='pubsub.example.org'
2565                       from='user@example.org'>
2566          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2567            <purge node='test'/>
2568          </pubsub>
2569        </iq>
2570        """
2571
2572        def cb(result):
2573            self.assertEquals('feature-not-implemented', result.condition)
2574            self.assertEquals('unsupported', result.appCondition.name)
2575            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2576            self.assertEquals('purge-nodes', result.appCondition['feature'])
2577
2578        d = self.handleRequest(xml)
2579        self.assertFailure(d, error.StanzaError)
2580        d.addCallback(cb)
2581        return d
2582
2583
2584    def test_delete(self):
2585        """
2586        Non-overridden L{PubSubService.delete} yields unsupported error.
2587        """
2588        xml = """
2589        <iq type='set' to='pubsub.example.org'
2590                       from='user@example.org'>
2591          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2592            <delete node='test'/>
2593          </pubsub>
2594        </iq>
2595        """
2596
2597        def cb(result):
2598            self.assertEquals('feature-not-implemented', result.condition)
2599            self.assertEquals('unsupported', result.appCondition.name)
2600            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2601            self.assertEquals('delete-nodes', result.appCondition['feature'])
2602
2603        d = self.handleRequest(xml)
2604        self.assertFailure(d, error.StanzaError)
2605        d.addCallback(cb)
2606        return d
Note: See TracBrowser for help on using the repository browser.