source: wokkel/test/test_pubsub.py @ 43:0a525d09169d

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

Add support for sending and receiving node delete notifications with redirect.

File size: 35.4 KB
Line 
1# Copyright (c) 2003-2008 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, xpath
13from twisted.words.protocols.jabber import error
14from twisted.words.protocols.jabber.jid import JID
15
16from wokkel import data_form, iwokkel, pubsub, shim
17from wokkel.generic import parseXml
18from wokkel.test.helpers import XmlStreamStub
19
20try:
21    from twisted.words.protocols.jabber.xmlstream import toResponse
22except ImportError:
23    from wokkel.compat import toResponse
24
25NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
26NS_PUBSUB_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
27NS_PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors'
28NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event'
29NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner'
30
31def calledAsync(fn):
32    """
33    Function wrapper that fires a deferred upon calling the given function.
34    """
35    d = defer.Deferred()
36
37    def func(*args, **kwargs):
38        try:
39            result = fn(*args, **kwargs)
40        except:
41            d.errback()
42        else:
43            d.callback(result)
44
45    return d, func
46
47
48class PubSubClientTest(unittest.TestCase):
49    timeout = 2
50
51    def setUp(self):
52        self.stub = XmlStreamStub()
53        self.protocol = pubsub.PubSubClient()
54        self.protocol.xmlstream = self.stub.xmlstream
55        self.protocol.connectionInitialized()
56
57
58    def test_interface(self):
59        """
60        Do instances of L{pubsub.PubSubClient} provide L{iwokkel.IPubSubClient}?
61        """
62        verify.verifyObject(iwokkel.IPubSubClient, self.protocol)
63
64
65    def test_eventItems(self):
66        """
67        Test receiving an items event resulting in a call to itemsReceived.
68        """
69        message = domish.Element((None, 'message'))
70        message['from'] = 'pubsub.example.org'
71        message['to'] = 'user@example.org/home'
72        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
73        items = event.addElement('items')
74        items['node'] = 'test'
75        item1 = items.addElement('item')
76        item1['id'] = 'item1'
77        item2 = items.addElement('retract')
78        item2['id'] = 'item2'
79        item3 = items.addElement('item')
80        item3['id'] = 'item3'
81
82        def itemsReceived(event):
83            self.assertEquals(JID('user@example.org/home'), event.recipient)
84            self.assertEquals(JID('pubsub.example.org'), event.sender)
85            self.assertEquals('test', event.nodeIdentifier)
86            self.assertEquals([item1, item2, item3], event.items)
87
88        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
89        self.stub.send(message)
90        return d
91
92
93    def test_eventItemsCollection(self):
94        """
95        Test receiving an items event resulting in a call to itemsReceived.
96        """
97        message = domish.Element((None, 'message'))
98        message['from'] = 'pubsub.example.org'
99        message['to'] = 'user@example.org/home'
100        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
101        items = event.addElement('items')
102        items['node'] = 'test'
103
104        headers = shim.Headers([('Collection', 'collection')])
105        message.addChild(headers)
106
107        def itemsReceived(event):
108            self.assertEquals(JID('user@example.org/home'), event.recipient)
109            self.assertEquals(JID('pubsub.example.org'), event.sender)
110            self.assertEquals('test', event.nodeIdentifier)
111            self.assertEquals({'Collection': ['collection']}, event.headers)
112
113        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
114        self.stub.send(message)
115        return d
116
117
118    def test_eventDelete(self):
119        """
120        Test receiving a delete event resulting in a call to deleteReceived.
121        """
122        message = domish.Element((None, 'message'))
123        message['from'] = 'pubsub.example.org'
124        message['to'] = 'user@example.org/home'
125        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
126        delete = event.addElement('delete')
127        delete['node'] = 'test'
128
129        def deleteReceived(event):
130            self.assertEquals(JID('user@example.org/home'), event.recipient)
131            self.assertEquals(JID('pubsub.example.org'), event.sender)
132            self.assertEquals('test', event.nodeIdentifier)
133
134        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
135        self.stub.send(message)
136        return d
137
138
139    def test_eventDeleteRedirect(self):
140        """
141        Test receiving a delete event with a redirect URI.
142        """
143        message = domish.Element((None, 'message'))
144        message['from'] = 'pubsub.example.org'
145        message['to'] = 'user@example.org/home'
146        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
147        delete = event.addElement('delete')
148        delete['node'] = 'test'
149        uri = 'xmpp:pubsub.example.org?;node=test2'
150        delete.addElement('redirect')['uri'] = uri
151
152        def deleteReceived(event):
153            self.assertEquals(JID('user@example.org/home'), event.recipient)
154            self.assertEquals(JID('pubsub.example.org'), event.sender)
155            self.assertEquals('test', event.nodeIdentifier)
156            self.assertEquals(uri, event.redirectURI)
157
158        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
159        self.stub.send(message)
160        return d
161
162
163    def test_event_purge(self):
164        """
165        Test receiving a purge event resulting in a call to purgeReceived.
166        """
167        message = domish.Element((None, 'message'))
168        message['from'] = 'pubsub.example.org'
169        message['to'] = 'user@example.org/home'
170        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
171        items = event.addElement('purge')
172        items['node'] = 'test'
173
174        def purgeReceived(event):
175            self.assertEquals(JID('user@example.org/home'), event.recipient)
176            self.assertEquals(JID('pubsub.example.org'), event.sender)
177            self.assertEquals('test', event.nodeIdentifier)
178
179        d, self.protocol.purgeReceived = calledAsync(purgeReceived)
180        self.stub.send(message)
181        return d
182
183
184    def test_createNode(self):
185        """
186        Test sending create request.
187        """
188
189        def cb(nodeIdentifier):
190            self.assertEquals('test', nodeIdentifier)
191
192        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
193        d.addCallback(cb)
194
195        iq = self.stub.output[-1]
196        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
197        self.assertEquals('set', iq.getAttribute('type'))
198        self.assertEquals('pubsub', iq.pubsub.name)
199        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
200        children = list(domish.generateElementsQNamed(iq.pubsub.children,
201                                                      'create', NS_PUBSUB))
202        self.assertEquals(1, len(children))
203        child = children[0]
204        self.assertEquals('test', child['node'])
205
206        response = toResponse(iq, 'result')
207        self.stub.send(response)
208        return d
209
210
211    def test_createNodeInstant(self):
212        """
213        Test sending create request resulting in an instant node.
214        """
215
216        def cb(nodeIdentifier):
217            self.assertEquals('test', nodeIdentifier)
218
219        d = self.protocol.createNode(JID('pubsub.example.org'))
220        d.addCallback(cb)
221
222        iq = self.stub.output[-1]
223        children = list(domish.generateElementsQNamed(iq.pubsub.children,
224                                                      'create', NS_PUBSUB))
225        child = children[0]
226        self.assertFalse(child.hasAttribute('node'))
227
228        response = toResponse(iq, 'result')
229        command = response.addElement((NS_PUBSUB, 'pubsub'))
230        create = command.addElement('create')
231        create['node'] = 'test'
232        self.stub.send(response)
233        return d
234
235
236    def test_createNodeRenamed(self):
237        """
238        Test sending create request resulting in renamed node.
239        """
240
241        def cb(nodeIdentifier):
242            self.assertEquals('test2', nodeIdentifier)
243
244        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
245        d.addCallback(cb)
246
247        iq = self.stub.output[-1]
248        children = list(domish.generateElementsQNamed(iq.pubsub.children,
249                                                      'create', NS_PUBSUB))
250        child = children[0]
251        self.assertEquals('test', child['node'])
252
253        response = toResponse(iq, 'result')
254        command = response.addElement((NS_PUBSUB, 'pubsub'))
255        create = command.addElement('create')
256        create['node'] = 'test2'
257        self.stub.send(response)
258        return d
259
260
261    def test_deleteNode(self):
262        """
263        Test sending delete request.
264        """
265
266        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test')
267
268        iq = self.stub.output[-1]
269        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
270        self.assertEquals('set', iq.getAttribute('type'))
271        self.assertEquals('pubsub', iq.pubsub.name)
272        self.assertEquals(NS_PUBSUB_OWNER, iq.pubsub.uri)
273        children = list(domish.generateElementsQNamed(iq.pubsub.children,
274                                                      'delete', NS_PUBSUB_OWNER))
275        self.assertEquals(1, len(children))
276        child = children[0]
277        self.assertEquals('test', child['node'])
278
279        response = toResponse(iq, 'result')
280        self.stub.send(response)
281        return d
282
283
284    def test_publish(self):
285        """
286        Test sending publish request.
287        """
288
289        item = pubsub.Item()
290        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item])
291
292        iq = self.stub.output[-1]
293        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
294        self.assertEquals('set', iq.getAttribute('type'))
295        self.assertEquals('pubsub', iq.pubsub.name)
296        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
297        children = list(domish.generateElementsQNamed(iq.pubsub.children,
298                                                      'publish', NS_PUBSUB))
299        self.assertEquals(1, len(children))
300        child = children[0]
301        self.assertEquals('test', child['node'])
302        items = list(domish.generateElementsQNamed(child.children,
303                                                   'item', NS_PUBSUB))
304        self.assertEquals(1, len(items))
305        self.assertIdentical(item, items[0])
306
307        response = toResponse(iq, 'result')
308        self.stub.send(response)
309        return d
310
311
312    def test_publishNoItems(self):
313        """
314        Test sending publish request without items.
315        """
316
317        d = self.protocol.publish(JID('pubsub.example.org'), 'test')
318
319        iq = self.stub.output[-1]
320        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
321        self.assertEquals('set', iq.getAttribute('type'))
322        self.assertEquals('pubsub', iq.pubsub.name)
323        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
324        children = list(domish.generateElementsQNamed(iq.pubsub.children,
325                                                      'publish', NS_PUBSUB))
326        self.assertEquals(1, len(children))
327        child = children[0]
328        self.assertEquals('test', child['node'])
329
330        response = toResponse(iq, 'result')
331        self.stub.send(response)
332        return d
333
334
335    def test_subscribe(self):
336        """
337        Test sending subscription request.
338        """
339        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
340                                      JID('user@example.org'))
341
342        iq = self.stub.output[-1]
343        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
344        self.assertEquals('set', iq.getAttribute('type'))
345        self.assertEquals('pubsub', iq.pubsub.name)
346        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
347        children = list(domish.generateElementsQNamed(iq.pubsub.children,
348                                                      'subscribe', NS_PUBSUB))
349        self.assertEquals(1, len(children))
350        child = children[0]
351        self.assertEquals('test', child['node'])
352        self.assertEquals('user@example.org', child['jid'])
353
354        response = toResponse(iq, 'result')
355        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
356        subscription = pubsub.addElement('subscription')
357        subscription['node'] = 'test'
358        subscription['jid'] = 'user@example.org'
359        subscription['subscription'] = 'subscribed'
360        self.stub.send(response)
361        return d
362
363
364    def test_subscribePending(self):
365        """
366        Test sending subscription request that results in a pending
367        subscription.
368        """
369        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
370                                      JID('user@example.org'))
371
372        iq = self.stub.output[-1]
373        response = toResponse(iq, 'result')
374        command = response.addElement((NS_PUBSUB, 'pubsub'))
375        subscription = command.addElement('subscription')
376        subscription['node'] = 'test'
377        subscription['jid'] = 'user@example.org'
378        subscription['subscription'] = 'pending'
379        self.stub.send(response)
380        self.assertFailure(d, pubsub.SubscriptionPending)
381        return d
382
383
384    def test_subscribeUnconfigured(self):
385        """
386        Test sending subscription request that results in an unconfigured
387        subscription.
388        """
389        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
390                                      JID('user@example.org'))
391
392        iq = self.stub.output[-1]
393        response = toResponse(iq, 'result')
394        command = response.addElement((NS_PUBSUB, 'pubsub'))
395        subscription = command.addElement('subscription')
396        subscription['node'] = 'test'
397        subscription['jid'] = 'user@example.org'
398        subscription['subscription'] = 'unconfigured'
399        self.stub.send(response)
400        self.assertFailure(d, pubsub.SubscriptionUnconfigured)
401        return d
402
403
404    def test_unsubscribe(self):
405        """
406        Test sending unsubscription request.
407        """
408        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
409                                      JID('user@example.org'))
410
411        iq = self.stub.output[-1]
412        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
413        self.assertEquals('set', iq.getAttribute('type'))
414        self.assertEquals('pubsub', iq.pubsub.name)
415        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
416        children = list(domish.generateElementsQNamed(iq.pubsub.children,
417                                                      'unsubscribe', NS_PUBSUB))
418        self.assertEquals(1, len(children))
419        child = children[0]
420        self.assertEquals('test', child['node'])
421        self.assertEquals('user@example.org', child['jid'])
422
423        self.stub.send(toResponse(iq, 'result'))
424        return d
425
426
427    def test_items(self):
428        """
429        Test sending items request.
430        """
431        def cb(items):
432            self.assertEquals([], items)
433
434        d = self.protocol.items(JID('pubsub.example.org'), 'test')
435        d.addCallback(cb)
436
437        iq = self.stub.output[-1]
438        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
439        self.assertEquals('get', iq.getAttribute('type'))
440        self.assertEquals('pubsub', iq.pubsub.name)
441        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
442        children = list(domish.generateElementsQNamed(iq.pubsub.children,
443                                                      'items', NS_PUBSUB))
444        self.assertEquals(1, len(children))
445        child = children[0]
446        self.assertEquals('test', child['node'])
447
448        response = toResponse(iq, 'result')
449        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
450        items['node'] = 'test'
451
452        self.stub.send(response)
453
454        return d
455
456
457    def test_itemsMaxItems(self):
458        """
459        Test sending items request, with limit on the number of items.
460        """
461        def cb(items):
462            self.assertEquals(2, len(items))
463            self.assertEquals([item1, item2], items)
464
465        d = self.protocol.items(JID('pubsub.example.org'), 'test', maxItems=2)
466        d.addCallback(cb)
467
468        iq = self.stub.output[-1]
469        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
470        self.assertEquals('get', iq.getAttribute('type'))
471        self.assertEquals('pubsub', iq.pubsub.name)
472        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
473        children = list(domish.generateElementsQNamed(iq.pubsub.children,
474                                                      'items', NS_PUBSUB))
475        self.assertEquals(1, len(children))
476        child = children[0]
477        self.assertEquals('test', child['node'])
478        self.assertEquals('2', child['max_items'])
479
480        response = toResponse(iq, 'result')
481        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
482        items['node'] = 'test'
483        item1 = items.addElement('item')
484        item1['id'] = 'item1'
485        item2 = items.addElement('item')
486        item2['id'] = 'item2'
487
488        self.stub.send(response)
489
490        return d
491
492
493
494class PubSubServiceTest(unittest.TestCase):
495    """
496    Tests for L{pubsub.PubSubService}.
497    """
498
499    def setUp(self):
500        self.stub = XmlStreamStub()
501        self.service = pubsub.PubSubService()
502        self.service.send = self.stub.xmlstream.send
503
504    def handleRequest(self, xml):
505        """
506        Find a handler and call it directly
507        """
508        handler = None
509        iq = parseXml(xml)
510        for queryString, method in self.service.iqHandlers.iteritems():
511            if xpath.internQuery(queryString).matches(iq):
512                handler = getattr(self.service, method)
513
514        if handler:
515            d = defer.maybeDeferred(handler, iq)
516        else:
517            d = defer.fail(NotImplementedError())
518
519        return d
520
521
522    def test_interface(self):
523        """
524        Do instances of L{pubsub.PubSubService} provide L{iwokkel.IPubSubService}?
525        """
526        verify.verifyObject(iwokkel.IPubSubService, self.service)
527
528
529    def test_onPublishNoNode(self):
530        """
531        The root node is always a collection, publishing is a bad request.
532        """
533        xml = """
534        <iq type='set' to='pubsub.example.org'
535                       from='user@example.org'>
536          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
537            <publish/>
538          </pubsub>
539        </iq>
540        """
541
542        def cb(result):
543            self.assertEquals('bad-request', result.condition)
544
545        d = self.handleRequest(xml)
546        self.assertFailure(d, error.StanzaError)
547        d.addCallback(cb)
548        return d
549
550
551    def test_onPublish(self):
552        """
553        A publish request should result in L{PubSubService.publish} being
554        called.
555        """
556
557        xml = """
558        <iq type='set' to='pubsub.example.org'
559                       from='user@example.org'>
560          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
561            <publish node='test'/>
562          </pubsub>
563        </iq>
564        """
565
566        def publish(requestor, service, nodeIdentifier, items):
567            self.assertEqual(JID('user@example.org'), requestor)
568            self.assertEqual(JID('pubsub.example.org'), service)
569            self.assertEqual('test', nodeIdentifier)
570            self.assertEqual([], items)
571            return defer.succeed(None)
572
573        self.service.publish = publish
574        return self.handleRequest(xml)
575
576
577    def test_onOptionsGet(self):
578        """
579        Subscription options are not supported.
580        """
581
582        xml = """
583        <iq type='get' to='pubsub.example.org'
584                       from='user@example.org'>
585          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
586            <options/>
587          </pubsub>
588        </iq>
589        """
590
591        def cb(result):
592            self.assertEquals('feature-not-implemented', result.condition)
593            self.assertEquals('unsupported', result.appCondition.name)
594            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
595
596        d = self.handleRequest(xml)
597        self.assertFailure(d, error.StanzaError)
598        d.addCallback(cb)
599        return d
600
601
602    def test_onSubscriptions(self):
603        """
604        A subscriptions request should result in
605        L{PubSubService.subscriptions} being called and the result prepared
606        for the response.
607        """
608
609        xml = """
610        <iq type='get' to='pubsub.example.org'
611                       from='user@example.org'>
612          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
613            <subscriptions/>
614          </pubsub>
615        </iq>
616        """
617
618        def cb(element):
619            self.assertEqual('pubsub', element.name)
620            self.assertEqual(NS_PUBSUB, element.uri)
621            self.assertEqual(NS_PUBSUB, element.subscriptions.uri)
622            children = list(element.subscriptions.elements())
623            self.assertEqual(1, len(children))
624            subscription = children[0]
625            self.assertEqual('subscription', subscription.name)
626            self.assertEqual(NS_PUBSUB, subscription.uri)
627            self.assertEqual('user@example.org', subscription['jid'])
628            self.assertEqual('test', subscription['node'])
629            self.assertEqual('subscribed', subscription['subscription'])
630
631
632        def subscriptions(requestor, service):
633            self.assertEqual(JID('user@example.org'), requestor)
634            self.assertEqual(JID('pubsub.example.org'), service)
635            subscription = pubsub.Subscription('test', JID('user@example.org'),
636                                               'subscribed')
637            return defer.succeed([subscription])
638
639        self.service.subscriptions = subscriptions
640        d = self.handleRequest(xml)
641        d.addCallback(cb)
642        return d
643
644
645    def test_onDefault(self):
646        """
647        A default request should result in
648        L{PubSubService.getDefaultConfiguration} being called.
649        """
650
651        xml = """
652        <iq type='get' to='pubsub.example.org'
653                       from='user@example.org'>
654          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
655            <default/>
656          </pubsub>
657        </iq>
658        """
659
660        def getConfigurationOptions():
661            return {
662                "pubsub#persist_items":
663                    {"type": "boolean",
664                     "label": "Persist items to storage"},
665                "pubsub#deliver_payloads":
666                    {"type": "boolean",
667                     "label": "Deliver payloads with event notifications"}
668                }
669
670        def getDefaultConfiguration(requestor, service, nodeType):
671            self.assertEqual(JID('user@example.org'), requestor)
672            self.assertEqual(JID('pubsub.example.org'), service)
673            self.assertEqual('leaf', nodeType)
674            return defer.succeed({})
675
676        def cb(element):
677            self.assertEqual('pubsub', element.name)
678            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
679            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
680            form = data_form.Form.fromElement(element.default.x)
681            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
682
683        self.service.getConfigurationOptions = getConfigurationOptions
684        self.service.getDefaultConfiguration = getDefaultConfiguration
685        verify.verifyObject(iwokkel.IPubSubService, self.service)
686        d = self.handleRequest(xml)
687        d.addCallback(cb)
688        return d
689
690
691    def test_onConfigureGet(self):
692        """
693        On a node configuration get request L{PubSubService.getConfiguration}
694        is called and results in a data form with the configuration.
695        """
696
697        xml = """
698        <iq type='get' to='pubsub.example.org'
699                       from='user@example.org'>
700          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
701            <configure node='test'/>
702          </pubsub>
703        </iq>
704        """
705
706        def getConfigurationOptions():
707            return {
708                "pubsub#persist_items":
709                    {"type": "boolean",
710                     "label": "Persist items to storage"},
711                "pubsub#deliver_payloads":
712                    {"type": "boolean",
713                     "label": "Deliver payloads with event notifications"}
714                }
715
716        def getConfiguration(requestor, service, nodeIdentifier):
717            self.assertEqual(JID('user@example.org'), requestor)
718            self.assertEqual(JID('pubsub.example.org'), service)
719            self.assertEqual('test', nodeIdentifier)
720
721            return defer.succeed({'pubsub#deliver_payloads': '0',
722                                  'pubsub#persist_items': '1'})
723
724        def cb(element):
725            self.assertEqual('pubsub', element.name)
726            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
727            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
728            form = data_form.Form.fromElement(element.configure.x)
729            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
730            fields = form.fields
731
732            self.assertIn('pubsub#deliver_payloads', fields)
733            field = fields['pubsub#deliver_payloads']
734            self.assertEqual('boolean', field.fieldType)
735            self.assertEqual(False, field.value)
736
737            self.assertIn('pubsub#persist_items', fields)
738            field = fields['pubsub#persist_items']
739            self.assertEqual('boolean', field.fieldType)
740            self.assertEqual(True, field.value)
741
742        self.service.getConfigurationOptions = getConfigurationOptions
743        self.service.getConfiguration = getConfiguration
744        d = self.handleRequest(xml)
745        d.addCallback(cb)
746        return d
747
748
749    def test_onConfigureSet(self):
750        """
751        On a node configuration set request the Data Form is parsed and
752        L{PubSubService.setConfiguration} is called with the passed options.
753        """
754
755        xml = """
756        <iq type='set' to='pubsub.example.org'
757                       from='user@example.org'>
758          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
759            <configure node='test'>
760              <x xmlns='jabber:x:data' type='submit'>
761                <field var='FORM_TYPE' type='hidden'>
762                  <value>http://jabber.org/protocol/pubsub#node_config</value>
763                </field>
764                <field var='pubsub#deliver_payloads'><value>0</value></field>
765                <field var='pubsub#persist_items'><value>1</value></field>
766              </x>
767            </configure>
768          </pubsub>
769        </iq>
770        """
771
772        def getConfigurationOptions():
773            return {
774                "pubsub#persist_items":
775                    {"type": "boolean",
776                     "label": "Persist items to storage"},
777                "pubsub#deliver_payloads":
778                    {"type": "boolean",
779                     "label": "Deliver payloads with event notifications"}
780                }
781
782        def setConfiguration(requestor, service, nodeIdentifier, options):
783            self.assertEqual(JID('user@example.org'), requestor)
784            self.assertEqual(JID('pubsub.example.org'), service)
785            self.assertEqual('test', nodeIdentifier)
786            self.assertEqual({'pubsub#deliver_payloads': False,
787                              'pubsub#persist_items': True}, options)
788            return defer.succeed(None)
789
790        self.service.getConfigurationOptions = getConfigurationOptions
791        self.service.setConfiguration = setConfiguration
792        return self.handleRequest(xml)
793
794
795    def test_onConfigureSetCancel(self):
796        """
797        The node configuration is cancelled, L{PubSubService.setConfiguration}
798        not called.
799        """
800
801        xml = """
802        <iq type='set' to='pubsub.example.org'
803                       from='user@example.org'>
804          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
805            <configure node='test'>
806              <x xmlns='jabber:x:data' type='cancel'>
807                <field var='FORM_TYPE' type='hidden'>
808                  <value>http://jabber.org/protocol/pubsub#node_config</value>
809                </field>
810              </x>
811            </configure>
812          </pubsub>
813        </iq>
814        """
815
816        def setConfiguration(requestor, service, nodeIdentifier, options):
817            self.fail("Unexpected call to setConfiguration")
818
819        self.service.setConfiguration = setConfiguration
820        return self.handleRequest(xml)
821
822
823    def test_onConfigureSetIgnoreUnknown(self):
824        """
825        On a node configuration set request unknown fields should be ignored.
826        """
827
828        xml = """
829        <iq type='set' to='pubsub.example.org'
830                       from='user@example.org'>
831          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
832            <configure node='test'>
833              <x xmlns='jabber:x:data' type='submit'>
834                <field var='FORM_TYPE' type='hidden'>
835                  <value>http://jabber.org/protocol/pubsub#node_config</value>
836                </field>
837                <field var='pubsub#deliver_payloads'><value>0</value></field>
838                <field var='x-myfield'><value>1</value></field>
839              </x>
840            </configure>
841          </pubsub>
842        </iq>
843        """
844
845        def getConfigurationOptions():
846            return {
847                "pubsub#persist_items":
848                    {"type": "boolean",
849                     "label": "Persist items to storage"},
850                "pubsub#deliver_payloads":
851                    {"type": "boolean",
852                     "label": "Deliver payloads with event notifications"}
853                }
854
855        def setConfiguration(requestor, service, nodeIdentifier, options):
856            self.assertEquals(['pubsub#deliver_payloads'], options.keys())
857
858        self.service.getConfigurationOptions = getConfigurationOptions
859        self.service.setConfiguration = setConfiguration
860        return self.handleRequest(xml)
861
862
863    def test_onItems(self):
864        """
865        On a items request, return all items for the given node.
866        """
867        xml = """
868        <iq type='get' to='pubsub.example.org'
869                       from='user@example.org'>
870          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
871            <items node='test'/>
872          </pubsub>
873        </iq>
874        """
875
876        def items(requestor, service, nodeIdentifier, maxItems, items):
877            self.assertEqual(JID('user@example.org'), requestor)
878            self.assertEqual(JID('pubsub.example.org'), service)
879            self.assertEqual('test', nodeIdentifier)
880            self.assertIdentical(None, maxItems)
881            self.assertEqual([], items)
882            return defer.succeed([pubsub.Item('current')])
883
884        def cb(element):
885            self.assertEqual(NS_PUBSUB, element.uri)
886            self.assertEqual(NS_PUBSUB, element.items.uri)
887            self.assertEqual(1, len(element.items.children))
888            item = element.items.children[-1]
889            self.assertTrue(domish.IElement.providedBy(item))
890            self.assertEqual('item', item.name)
891            self.assertEqual(NS_PUBSUB, item.uri)
892            self.assertEqual('current', item['id'])
893
894        self.service.items = items
895        d = self.handleRequest(xml)
896        d.addCallback(cb)
897        return d
898
899
900    def test_onRetract(self):
901        """
902        A retract request should result in L{PubSubService.retract} being
903        called.
904        """
905
906        xml = """
907        <iq type='set' to='pubsub.example.org'
908                       from='user@example.org'>
909          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
910            <retract node='test'>
911              <item id='item1'/>
912              <item id='item2'/>
913            </retract>
914          </pubsub>
915        </iq>
916        """
917
918        def retract(requestor, service, nodeIdentifier, itemIdentifiers):
919            self.assertEqual(JID('user@example.org'), requestor)
920            self.assertEqual(JID('pubsub.example.org'), service)
921            self.assertEqual('test', nodeIdentifier)
922            self.assertEqual(['item1', 'item2'], itemIdentifiers)
923            return defer.succeed(None)
924
925        self.service.retract = retract
926        return self.handleRequest(xml)
927
928
929    def test_onPurge(self):
930        """
931        A purge request should result in L{PubSubService.purge} being
932        called.
933        """
934
935        xml = """
936        <iq type='set' to='pubsub.example.org'
937                       from='user@example.org'>
938          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
939            <purge node='test'/>
940          </pubsub>
941        </iq>
942        """
943
944        def purge(requestor, service, nodeIdentifier):
945            self.assertEqual(JID('user@example.org'), requestor)
946            self.assertEqual(JID('pubsub.example.org'), service)
947            self.assertEqual('test', nodeIdentifier)
948            return defer.succeed(None)
949
950        self.service.purge = purge
951        return self.handleRequest(xml)
952
953
954    def test_onDelete(self):
955        """
956        A delete request should result in L{PubSubService.delete} being
957        called.
958        """
959
960        xml = """
961        <iq type='set' to='pubsub.example.org'
962                       from='user@example.org'>
963          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
964            <delete node='test'/>
965          </pubsub>
966        </iq>
967        """
968
969        def delete(requestor, service, nodeIdentifier):
970            self.assertEqual(JID('user@example.org'), requestor)
971            self.assertEqual(JID('pubsub.example.org'), service)
972            self.assertEqual('test', nodeIdentifier)
973            return defer.succeed(None)
974
975        self.service.delete = delete
976        return self.handleRequest(xml)
977
978
979    def test_notifyDelete(self):
980        """
981        Subscribers should be sent a delete notification.
982        """
983        subscriptions = [JID('user@example.org')]
984        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
985                                  subscriptions)
986        message = self.stub.output[-1]
987
988        self.assertEquals('message', message.name)
989        self.assertIdentical(None, message.uri)
990        self.assertEquals('user@example.org', message['to'])
991        self.assertEquals('pubsub.example.org', message['from'])
992        self.assertTrue(message.event)
993        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
994        self.assertTrue(message.event.delete)
995        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
996        self.assertTrue(message.event.delete.hasAttribute('node'))
997        self.assertEqual('test', message.event.delete['node'])
998
999
1000    def test_notifyDeleteRedirect(self):
1001        """
1002        Subscribers should be sent a delete notification with redirect.
1003        """
1004        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
1005        subscriptions = [JID('user@example.org')]
1006        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
1007                                  subscriptions, redirectURI)
1008        message = self.stub.output[-1]
1009
1010        self.assertEquals('message', message.name)
1011        self.assertIdentical(None, message.uri)
1012        self.assertEquals('user@example.org', message['to'])
1013        self.assertEquals('pubsub.example.org', message['from'])
1014        self.assertTrue(message.event)
1015        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
1016        self.assertTrue(message.event.delete)
1017        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
1018        self.assertTrue(message.event.delete.hasAttribute('node'))
1019        self.assertEqual('test', message.event.delete['node'])
1020        self.assertTrue(message.event.delete.redirect)
1021        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
1022        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
1023        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
Note: See TracBrowser for help on using the repository browser.