source: wokkel/test/test_pubsub.py @ 53:4aec395fda5b

Last change on this file since 53:4aec395fda5b was 53:4aec395fda5b, checked in by Ralph Meijer <ralphm@…>, 11 years ago

Release Wokkel 0.5.0.

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