source: wokkel/test/test_pubsub.py @ 56:01740c205934

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

Don't do type interpretation on parsing Data Forms fields.

File size: 37.6 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                "pubsub#owner":
758                    {"type": "jid-single",
759                     "label": "Owner of the node"}
760                }
761
762        def getConfiguration(requestor, service, nodeIdentifier):
763            self.assertEqual(JID('user@example.org'), requestor)
764            self.assertEqual(JID('pubsub.example.org'), service)
765            self.assertEqual('test', nodeIdentifier)
766
767            return defer.succeed({'pubsub#deliver_payloads': '0',
768                                  'pubsub#persist_items': '1',
769                                  'pubsub#owner': JID('user@example.org')})
770
771        def cb(element):
772            self.assertEqual('pubsub', element.name)
773            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
774            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
775            form = data_form.Form.fromElement(element.configure.x)
776            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
777            fields = form.fields
778
779            self.assertIn('pubsub#deliver_payloads', fields)
780            field = fields['pubsub#deliver_payloads']
781            self.assertEqual('boolean', field.fieldType)
782            field.typeCheck()
783            self.assertEqual(False, field.value)
784
785            self.assertIn('pubsub#persist_items', fields)
786            field = fields['pubsub#persist_items']
787            self.assertEqual('boolean', field.fieldType)
788            field.typeCheck()
789            self.assertEqual(True, field.value)
790
791            self.assertIn('pubsub#owner', fields)
792            field = fields['pubsub#owner']
793            self.assertEqual('jid-single', field.fieldType)
794            field.typeCheck()
795            self.assertEqual(JID('user@example.org'), field.value)
796
797        self.service.getConfigurationOptions = getConfigurationOptions
798        self.service.getConfiguration = getConfiguration
799        d = self.handleRequest(xml)
800        d.addCallback(cb)
801        return d
802
803
804    def test_onConfigureSet(self):
805        """
806        On a node configuration set request the Data Form is parsed and
807        L{PubSubService.setConfiguration} is called with the passed options.
808        """
809
810        xml = """
811        <iq type='set' to='pubsub.example.org'
812                       from='user@example.org'>
813          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
814            <configure node='test'>
815              <x xmlns='jabber:x:data' type='submit'>
816                <field var='FORM_TYPE' type='hidden'>
817                  <value>http://jabber.org/protocol/pubsub#node_config</value>
818                </field>
819                <field var='pubsub#deliver_payloads'><value>0</value></field>
820                <field var='pubsub#persist_items'><value>1</value></field>
821              </x>
822            </configure>
823          </pubsub>
824        </iq>
825        """
826
827        def getConfigurationOptions():
828            return {
829                "pubsub#persist_items":
830                    {"type": "boolean",
831                     "label": "Persist items to storage"},
832                "pubsub#deliver_payloads":
833                    {"type": "boolean",
834                     "label": "Deliver payloads with event notifications"}
835                }
836
837        def setConfiguration(requestor, service, nodeIdentifier, options):
838            self.assertEqual(JID('user@example.org'), requestor)
839            self.assertEqual(JID('pubsub.example.org'), service)
840            self.assertEqual('test', nodeIdentifier)
841            self.assertEqual({'pubsub#deliver_payloads': False,
842                              'pubsub#persist_items': True}, options)
843            return defer.succeed(None)
844
845        self.service.getConfigurationOptions = getConfigurationOptions
846        self.service.setConfiguration = setConfiguration
847        return self.handleRequest(xml)
848
849
850    def test_onConfigureSetCancel(self):
851        """
852        The node configuration is cancelled, L{PubSubService.setConfiguration}
853        not called.
854        """
855
856        xml = """
857        <iq type='set' to='pubsub.example.org'
858                       from='user@example.org'>
859          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
860            <configure node='test'>
861              <x xmlns='jabber:x:data' type='cancel'>
862                <field var='FORM_TYPE' type='hidden'>
863                  <value>http://jabber.org/protocol/pubsub#node_config</value>
864                </field>
865              </x>
866            </configure>
867          </pubsub>
868        </iq>
869        """
870
871        def setConfiguration(requestor, service, nodeIdentifier, options):
872            self.fail("Unexpected call to setConfiguration")
873
874        self.service.setConfiguration = setConfiguration
875        return self.handleRequest(xml)
876
877
878    def test_onConfigureSetIgnoreUnknown(self):
879        """
880        On a node configuration set request unknown fields should be ignored.
881        """
882
883        xml = """
884        <iq type='set' to='pubsub.example.org'
885                       from='user@example.org'>
886          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
887            <configure node='test'>
888              <x xmlns='jabber:x:data' type='submit'>
889                <field var='FORM_TYPE' type='hidden'>
890                  <value>http://jabber.org/protocol/pubsub#node_config</value>
891                </field>
892                <field var='pubsub#deliver_payloads'><value>0</value></field>
893                <field var='x-myfield'><value>1</value></field>
894              </x>
895            </configure>
896          </pubsub>
897        </iq>
898        """
899
900        def getConfigurationOptions():
901            return {
902                "pubsub#persist_items":
903                    {"type": "boolean",
904                     "label": "Persist items to storage"},
905                "pubsub#deliver_payloads":
906                    {"type": "boolean",
907                     "label": "Deliver payloads with event notifications"}
908                }
909
910        def setConfiguration(requestor, service, nodeIdentifier, options):
911            self.assertEquals(['pubsub#deliver_payloads'], options.keys())
912
913        self.service.getConfigurationOptions = getConfigurationOptions
914        self.service.setConfiguration = setConfiguration
915        return self.handleRequest(xml)
916
917
918    def test_onItems(self):
919        """
920        On a items request, return all items for the given node.
921        """
922        xml = """
923        <iq type='get' to='pubsub.example.org'
924                       from='user@example.org'>
925          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
926            <items node='test'/>
927          </pubsub>
928        </iq>
929        """
930
931        def items(requestor, service, nodeIdentifier, maxItems, items):
932            self.assertEqual(JID('user@example.org'), requestor)
933            self.assertEqual(JID('pubsub.example.org'), service)
934            self.assertEqual('test', nodeIdentifier)
935            self.assertIdentical(None, maxItems)
936            self.assertEqual([], items)
937            return defer.succeed([pubsub.Item('current')])
938
939        def cb(element):
940            self.assertEqual(NS_PUBSUB, element.uri)
941            self.assertEqual(NS_PUBSUB, element.items.uri)
942            self.assertEqual(1, len(element.items.children))
943            item = element.items.children[-1]
944            self.assertTrue(domish.IElement.providedBy(item))
945            self.assertEqual('item', item.name)
946            self.assertEqual(NS_PUBSUB, item.uri)
947            self.assertEqual('current', item['id'])
948
949        self.service.items = items
950        d = self.handleRequest(xml)
951        d.addCallback(cb)
952        return d
953
954
955    def test_onRetract(self):
956        """
957        A retract request should result in L{PubSubService.retract} being
958        called.
959        """
960
961        xml = """
962        <iq type='set' to='pubsub.example.org'
963                       from='user@example.org'>
964          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
965            <retract node='test'>
966              <item id='item1'/>
967              <item id='item2'/>
968            </retract>
969          </pubsub>
970        </iq>
971        """
972
973        def retract(requestor, service, nodeIdentifier, itemIdentifiers):
974            self.assertEqual(JID('user@example.org'), requestor)
975            self.assertEqual(JID('pubsub.example.org'), service)
976            self.assertEqual('test', nodeIdentifier)
977            self.assertEqual(['item1', 'item2'], itemIdentifiers)
978            return defer.succeed(None)
979
980        self.service.retract = retract
981        return self.handleRequest(xml)
982
983
984    def test_onPurge(self):
985        """
986        A purge request should result in L{PubSubService.purge} being
987        called.
988        """
989
990        xml = """
991        <iq type='set' to='pubsub.example.org'
992                       from='user@example.org'>
993          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
994            <purge node='test'/>
995          </pubsub>
996        </iq>
997        """
998
999        def purge(requestor, service, nodeIdentifier):
1000            self.assertEqual(JID('user@example.org'), requestor)
1001            self.assertEqual(JID('pubsub.example.org'), service)
1002            self.assertEqual('test', nodeIdentifier)
1003            return defer.succeed(None)
1004
1005        self.service.purge = purge
1006        return self.handleRequest(xml)
1007
1008
1009    def test_onDelete(self):
1010        """
1011        A delete request should result in L{PubSubService.delete} being
1012        called.
1013        """
1014
1015        xml = """
1016        <iq type='set' to='pubsub.example.org'
1017                       from='user@example.org'>
1018          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1019            <delete node='test'/>
1020          </pubsub>
1021        </iq>
1022        """
1023
1024        def delete(requestor, service, nodeIdentifier):
1025            self.assertEqual(JID('user@example.org'), requestor)
1026            self.assertEqual(JID('pubsub.example.org'), service)
1027            self.assertEqual('test', nodeIdentifier)
1028            return defer.succeed(None)
1029
1030        self.service.delete = delete
1031        return self.handleRequest(xml)
1032
1033
1034    def test_notifyDelete(self):
1035        """
1036        Subscribers should be sent a delete notification.
1037        """
1038        subscriptions = [JID('user@example.org')]
1039        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
1040                                  subscriptions)
1041        message = self.stub.output[-1]
1042
1043        self.assertEquals('message', message.name)
1044        self.assertIdentical(None, message.uri)
1045        self.assertEquals('user@example.org', message['to'])
1046        self.assertEquals('pubsub.example.org', message['from'])
1047        self.assertTrue(message.event)
1048        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
1049        self.assertTrue(message.event.delete)
1050        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
1051        self.assertTrue(message.event.delete.hasAttribute('node'))
1052        self.assertEqual('test', message.event.delete['node'])
1053
1054
1055    def test_notifyDeleteRedirect(self):
1056        """
1057        Subscribers should be sent a delete notification with redirect.
1058        """
1059        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
1060        subscriptions = [JID('user@example.org')]
1061        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
1062                                  subscriptions, redirectURI)
1063        message = self.stub.output[-1]
1064
1065        self.assertEquals('message', message.name)
1066        self.assertIdentical(None, message.uri)
1067        self.assertEquals('user@example.org', message['to'])
1068        self.assertEquals('pubsub.example.org', message['from'])
1069        self.assertTrue(message.event)
1070        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
1071        self.assertTrue(message.event.delete)
1072        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
1073        self.assertTrue(message.event.delete.hasAttribute('node'))
1074        self.assertEqual('test', message.event.delete['node'])
1075        self.assertTrue(message.event.delete.redirect)
1076        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
1077        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
1078        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
Note: See TracBrowser for help on using the repository browser.