source: wokkel/test/test_pubsub.py @ 52:118fafcc5c5b

Last change on this file since 52:118fafcc5c5b was 52:118fafcc5c5b, checked in by Ralph Meijer <ralphm@…>, 11 years ago

Fix regression in returning node meta data.

Author: ralphm.
Fixes #42.

File size: 37.2 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
13from twisted.words.protocols.jabber import error
14from twisted.words.protocols.jabber.jid import JID
15
16from wokkel import data_form, disco, iwokkel, pubsub, shim
17from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
18
19try:
20    from twisted.words.protocols.jabber.xmlstream import toResponse
21except ImportError:
22    from wokkel.compat import toResponse
23
24NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
25NS_PUBSUB_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
26NS_PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors'
27NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event'
28NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner'
29NS_PUBSUB_META_DATA = 'http://jabber.org/protocol/pubsub#meta-data'
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, TestableRequestHandlerMixin):
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 test_interface(self):
505        """
506        Do instances of L{pubsub.PubSubService} provide L{iwokkel.IPubSubService}?
507        """
508        verify.verifyObject(iwokkel.IPubSubService, self.service)
509
510
511    def test_getDiscoInfo(self):
512        """
513        Test getDiscoInfo calls getNodeInfo and returns some minimal info.
514        """
515        def cb(info):
516            self.assertEqual(2, len(info))
517
518        def getNodeInfo(requestor, target, nodeIdentifier):
519            return defer.succeed(None)
520
521        self.service.getNodeInfo = getNodeInfo
522        d = self.service.getDiscoInfo(JID('user@example.org/home'),
523                                      JID('pubsub.example.org'), '')
524        d.addCallback(cb)
525        return d
526
527
528    def test_getDiscoInfoNodeType(self):
529        """
530        Test getDiscoInfo with node type.
531        """
532        def cb(info):
533            discoInfo = disco.DiscoInfo()
534            for item in info:
535                discoInfo.append(item)
536            self.assertIn(('pubsub', 'collection'), discoInfo.identities)
537
538        def getNodeInfo(requestor, target, nodeIdentifier):
539            return defer.succeed({'type': 'collection',
540                                  'meta-data': {}})
541
542        self.service.getNodeInfo = getNodeInfo
543        d = self.service.getDiscoInfo(JID('user@example.org/home'),
544                                      JID('pubsub.example.org'), '')
545        d.addCallback(cb)
546        return d
547
548
549    def test_getDiscoInfoMetaData(self):
550        """
551        Test getDiscoInfo with returned meta data.
552        """
553        def cb(info):
554            discoInfo = disco.DiscoInfo()
555            for item in info:
556                discoInfo.append(item)
557
558            self.assertIn(('pubsub', 'leaf'), discoInfo.identities)
559            self.assertIn(NS_PUBSUB_META_DATA, discoInfo.extensions)
560            form = discoInfo.extensions[NS_PUBSUB_META_DATA]
561            self.assertIn('pubsub#node_type', form.fields)
562
563        def getNodeInfo(requestor, target, nodeIdentifier):
564            metaData = [{'var': 'pubsub#persist_items',
565                         'label': 'Persist items to storage',
566                         'value': True}]
567            return defer.succeed({'type': 'leaf', 'meta-data': metaData})
568
569        self.service.getNodeInfo = getNodeInfo
570        d = self.service.getDiscoInfo(JID('user@example.org/home'),
571                                      JID('pubsub.example.org'), '')
572        d.addCallback(cb)
573        return d
574
575
576    def test_onPublishNoNode(self):
577        """
578        The root node is always a collection, publishing is a bad request.
579        """
580        xml = """
581        <iq type='set' to='pubsub.example.org'
582                       from='user@example.org'>
583          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
584            <publish/>
585          </pubsub>
586        </iq>
587        """
588
589        def cb(result):
590            self.assertEquals('bad-request', result.condition)
591
592        d = self.handleRequest(xml)
593        self.assertFailure(d, error.StanzaError)
594        d.addCallback(cb)
595        return d
596
597
598    def test_onPublish(self):
599        """
600        A publish request should result in L{PubSubService.publish} being
601        called.
602        """
603
604        xml = """
605        <iq type='set' to='pubsub.example.org'
606                       from='user@example.org'>
607          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
608            <publish node='test'/>
609          </pubsub>
610        </iq>
611        """
612
613        def publish(requestor, service, nodeIdentifier, items):
614            self.assertEqual(JID('user@example.org'), requestor)
615            self.assertEqual(JID('pubsub.example.org'), service)
616            self.assertEqual('test', nodeIdentifier)
617            self.assertEqual([], items)
618            return defer.succeed(None)
619
620        self.service.publish = publish
621        return self.handleRequest(xml)
622
623
624    def test_onOptionsGet(self):
625        """
626        Subscription options are not supported.
627        """
628
629        xml = """
630        <iq type='get' to='pubsub.example.org'
631                       from='user@example.org'>
632          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
633            <options/>
634          </pubsub>
635        </iq>
636        """
637
638        def cb(result):
639            self.assertEquals('feature-not-implemented', result.condition)
640            self.assertEquals('unsupported', result.appCondition.name)
641            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
642
643        d = self.handleRequest(xml)
644        self.assertFailure(d, error.StanzaError)
645        d.addCallback(cb)
646        return d
647
648
649    def test_onSubscriptions(self):
650        """
651        A subscriptions request should result in
652        L{PubSubService.subscriptions} being called and the result prepared
653        for the response.
654        """
655
656        xml = """
657        <iq type='get' to='pubsub.example.org'
658                       from='user@example.org'>
659          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
660            <subscriptions/>
661          </pubsub>
662        </iq>
663        """
664
665        def cb(element):
666            self.assertEqual('pubsub', element.name)
667            self.assertEqual(NS_PUBSUB, element.uri)
668            self.assertEqual(NS_PUBSUB, element.subscriptions.uri)
669            children = list(element.subscriptions.elements())
670            self.assertEqual(1, len(children))
671            subscription = children[0]
672            self.assertEqual('subscription', subscription.name)
673            self.assertEqual(NS_PUBSUB, subscription.uri)
674            self.assertEqual('user@example.org', subscription['jid'])
675            self.assertEqual('test', subscription['node'])
676            self.assertEqual('subscribed', subscription['subscription'])
677
678
679        def subscriptions(requestor, service):
680            self.assertEqual(JID('user@example.org'), requestor)
681            self.assertEqual(JID('pubsub.example.org'), service)
682            subscription = pubsub.Subscription('test', JID('user@example.org'),
683                                               'subscribed')
684            return defer.succeed([subscription])
685
686        self.service.subscriptions = subscriptions
687        d = self.handleRequest(xml)
688        d.addCallback(cb)
689        return d
690
691
692    def test_onDefault(self):
693        """
694        A default request should result in
695        L{PubSubService.getDefaultConfiguration} being called.
696        """
697
698        xml = """
699        <iq type='get' to='pubsub.example.org'
700                       from='user@example.org'>
701          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
702            <default/>
703          </pubsub>
704        </iq>
705        """
706
707        def getConfigurationOptions():
708            return {
709                "pubsub#persist_items":
710                    {"type": "boolean",
711                     "label": "Persist items to storage"},
712                "pubsub#deliver_payloads":
713                    {"type": "boolean",
714                     "label": "Deliver payloads with event notifications"}
715                }
716
717        def getDefaultConfiguration(requestor, service, nodeType):
718            self.assertEqual(JID('user@example.org'), requestor)
719            self.assertEqual(JID('pubsub.example.org'), service)
720            self.assertEqual('leaf', nodeType)
721            return defer.succeed({})
722
723        def cb(element):
724            self.assertEqual('pubsub', element.name)
725            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
726            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
727            form = data_form.Form.fromElement(element.default.x)
728            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
729
730        self.service.getConfigurationOptions = getConfigurationOptions
731        self.service.getDefaultConfiguration = getDefaultConfiguration
732        verify.verifyObject(iwokkel.IPubSubService, self.service)
733        d = self.handleRequest(xml)
734        d.addCallback(cb)
735        return d
736
737
738    def test_onConfigureGet(self):
739        """
740        On a node configuration get request L{PubSubService.getConfiguration}
741        is called and results in a data form with the configuration.
742        """
743
744        xml = """
745        <iq type='get' to='pubsub.example.org'
746                       from='user@example.org'>
747          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
748            <configure node='test'/>
749          </pubsub>
750        </iq>
751        """
752
753        def getConfigurationOptions():
754            return {
755                "pubsub#persist_items":
756                    {"type": "boolean",
757                     "label": "Persist items to storage"},
758                "pubsub#deliver_payloads":
759                    {"type": "boolean",
760                     "label": "Deliver payloads with event notifications"}
761                }
762
763        def getConfiguration(requestor, service, nodeIdentifier):
764            self.assertEqual(JID('user@example.org'), requestor)
765            self.assertEqual(JID('pubsub.example.org'), service)
766            self.assertEqual('test', nodeIdentifier)
767
768            return defer.succeed({'pubsub#deliver_payloads': '0',
769                                  'pubsub#persist_items': '1'})
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            self.assertEqual(False, field.value)
783
784            self.assertIn('pubsub#persist_items', fields)
785            field = fields['pubsub#persist_items']
786            self.assertEqual('boolean', field.fieldType)
787            self.assertEqual(True, field.value)
788
789        self.service.getConfigurationOptions = getConfigurationOptions
790        self.service.getConfiguration = getConfiguration
791        d = self.handleRequest(xml)
792        d.addCallback(cb)
793        return d
794
795
796    def test_onConfigureSet(self):
797        """
798        On a node configuration set request the Data Form is parsed and
799        L{PubSubService.setConfiguration} is called with the passed options.
800        """
801
802        xml = """
803        <iq type='set' to='pubsub.example.org'
804                       from='user@example.org'>
805          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
806            <configure node='test'>
807              <x xmlns='jabber:x:data' type='submit'>
808                <field var='FORM_TYPE' type='hidden'>
809                  <value>http://jabber.org/protocol/pubsub#node_config</value>
810                </field>
811                <field var='pubsub#deliver_payloads'><value>0</value></field>
812                <field var='pubsub#persist_items'><value>1</value></field>
813              </x>
814            </configure>
815          </pubsub>
816        </iq>
817        """
818
819        def getConfigurationOptions():
820            return {
821                "pubsub#persist_items":
822                    {"type": "boolean",
823                     "label": "Persist items to storage"},
824                "pubsub#deliver_payloads":
825                    {"type": "boolean",
826                     "label": "Deliver payloads with event notifications"}
827                }
828
829        def setConfiguration(requestor, service, nodeIdentifier, options):
830            self.assertEqual(JID('user@example.org'), requestor)
831            self.assertEqual(JID('pubsub.example.org'), service)
832            self.assertEqual('test', nodeIdentifier)
833            self.assertEqual({'pubsub#deliver_payloads': False,
834                              'pubsub#persist_items': True}, options)
835            return defer.succeed(None)
836
837        self.service.getConfigurationOptions = getConfigurationOptions
838        self.service.setConfiguration = setConfiguration
839        return self.handleRequest(xml)
840
841
842    def test_onConfigureSetCancel(self):
843        """
844        The node configuration is cancelled, L{PubSubService.setConfiguration}
845        not called.
846        """
847
848        xml = """
849        <iq type='set' to='pubsub.example.org'
850                       from='user@example.org'>
851          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
852            <configure node='test'>
853              <x xmlns='jabber:x:data' type='cancel'>
854                <field var='FORM_TYPE' type='hidden'>
855                  <value>http://jabber.org/protocol/pubsub#node_config</value>
856                </field>
857              </x>
858            </configure>
859          </pubsub>
860        </iq>
861        """
862
863        def setConfiguration(requestor, service, nodeIdentifier, options):
864            self.fail("Unexpected call to setConfiguration")
865
866        self.service.setConfiguration = setConfiguration
867        return self.handleRequest(xml)
868
869
870    def test_onConfigureSetIgnoreUnknown(self):
871        """
872        On a node configuration set request unknown fields should be ignored.
873        """
874
875        xml = """
876        <iq type='set' to='pubsub.example.org'
877                       from='user@example.org'>
878          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
879            <configure node='test'>
880              <x xmlns='jabber:x:data' type='submit'>
881                <field var='FORM_TYPE' type='hidden'>
882                  <value>http://jabber.org/protocol/pubsub#node_config</value>
883                </field>
884                <field var='pubsub#deliver_payloads'><value>0</value></field>
885                <field var='x-myfield'><value>1</value></field>
886              </x>
887            </configure>
888          </pubsub>
889        </iq>
890        """
891
892        def getConfigurationOptions():
893            return {
894                "pubsub#persist_items":
895                    {"type": "boolean",
896                     "label": "Persist items to storage"},
897                "pubsub#deliver_payloads":
898                    {"type": "boolean",
899                     "label": "Deliver payloads with event notifications"}
900                }
901
902        def setConfiguration(requestor, service, nodeIdentifier, options):
903            self.assertEquals(['pubsub#deliver_payloads'], options.keys())
904
905        self.service.getConfigurationOptions = getConfigurationOptions
906        self.service.setConfiguration = setConfiguration
907        return self.handleRequest(xml)
908
909
910    def test_onItems(self):
911        """
912        On a items request, return all items for the given node.
913        """
914        xml = """
915        <iq type='get' to='pubsub.example.org'
916                       from='user@example.org'>
917          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
918            <items node='test'/>
919          </pubsub>
920        </iq>
921        """
922
923        def items(requestor, service, nodeIdentifier, maxItems, items):
924            self.assertEqual(JID('user@example.org'), requestor)
925            self.assertEqual(JID('pubsub.example.org'), service)
926            self.assertEqual('test', nodeIdentifier)
927            self.assertIdentical(None, maxItems)
928            self.assertEqual([], items)
929            return defer.succeed([pubsub.Item('current')])
930
931        def cb(element):
932            self.assertEqual(NS_PUBSUB, element.uri)
933            self.assertEqual(NS_PUBSUB, element.items.uri)
934            self.assertEqual(1, len(element.items.children))
935            item = element.items.children[-1]
936            self.assertTrue(domish.IElement.providedBy(item))
937            self.assertEqual('item', item.name)
938            self.assertEqual(NS_PUBSUB, item.uri)
939            self.assertEqual('current', item['id'])
940
941        self.service.items = items
942        d = self.handleRequest(xml)
943        d.addCallback(cb)
944        return d
945
946
947    def test_onRetract(self):
948        """
949        A retract request should result in L{PubSubService.retract} being
950        called.
951        """
952
953        xml = """
954        <iq type='set' to='pubsub.example.org'
955                       from='user@example.org'>
956          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
957            <retract node='test'>
958              <item id='item1'/>
959              <item id='item2'/>
960            </retract>
961          </pubsub>
962        </iq>
963        """
964
965        def retract(requestor, service, nodeIdentifier, itemIdentifiers):
966            self.assertEqual(JID('user@example.org'), requestor)
967            self.assertEqual(JID('pubsub.example.org'), service)
968            self.assertEqual('test', nodeIdentifier)
969            self.assertEqual(['item1', 'item2'], itemIdentifiers)
970            return defer.succeed(None)
971
972        self.service.retract = retract
973        return self.handleRequest(xml)
974
975
976    def test_onPurge(self):
977        """
978        A purge request should result in L{PubSubService.purge} being
979        called.
980        """
981
982        xml = """
983        <iq type='set' to='pubsub.example.org'
984                       from='user@example.org'>
985          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
986            <purge node='test'/>
987          </pubsub>
988        </iq>
989        """
990
991        def purge(requestor, service, nodeIdentifier):
992            self.assertEqual(JID('user@example.org'), requestor)
993            self.assertEqual(JID('pubsub.example.org'), service)
994            self.assertEqual('test', nodeIdentifier)
995            return defer.succeed(None)
996
997        self.service.purge = purge
998        return self.handleRequest(xml)
999
1000
1001    def test_onDelete(self):
1002        """
1003        A delete request should result in L{PubSubService.delete} being
1004        called.
1005        """
1006
1007        xml = """
1008        <iq type='set' to='pubsub.example.org'
1009                       from='user@example.org'>
1010          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1011            <delete node='test'/>
1012          </pubsub>
1013        </iq>
1014        """
1015
1016        def delete(requestor, service, nodeIdentifier):
1017            self.assertEqual(JID('user@example.org'), requestor)
1018            self.assertEqual(JID('pubsub.example.org'), service)
1019            self.assertEqual('test', nodeIdentifier)
1020            return defer.succeed(None)
1021
1022        self.service.delete = delete
1023        return self.handleRequest(xml)
1024
1025
1026    def test_notifyDelete(self):
1027        """
1028        Subscribers should be sent a delete notification.
1029        """
1030        subscriptions = [JID('user@example.org')]
1031        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
1032                                  subscriptions)
1033        message = self.stub.output[-1]
1034
1035        self.assertEquals('message', message.name)
1036        self.assertIdentical(None, message.uri)
1037        self.assertEquals('user@example.org', message['to'])
1038        self.assertEquals('pubsub.example.org', message['from'])
1039        self.assertTrue(message.event)
1040        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
1041        self.assertTrue(message.event.delete)
1042        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
1043        self.assertTrue(message.event.delete.hasAttribute('node'))
1044        self.assertEqual('test', message.event.delete['node'])
1045
1046
1047    def test_notifyDeleteRedirect(self):
1048        """
1049        Subscribers should be sent a delete notification with redirect.
1050        """
1051        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
1052        subscriptions = [JID('user@example.org')]
1053        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
1054                                  subscriptions, redirectURI)
1055        message = self.stub.output[-1]
1056
1057        self.assertEquals('message', message.name)
1058        self.assertIdentical(None, message.uri)
1059        self.assertEquals('user@example.org', message['to'])
1060        self.assertEquals('pubsub.example.org', message['from'])
1061        self.assertTrue(message.event)
1062        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
1063        self.assertTrue(message.event.delete)
1064        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
1065        self.assertTrue(message.event.delete.hasAttribute('node'))
1066        self.assertEqual('test', message.event.delete['node'])
1067        self.assertTrue(message.event.delete.redirect)
1068        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
1069        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
1070        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
Note: See TracBrowser for help on using the repository browser.