source: wokkel/test/test_pubsub.py @ 84:3fe44cf07366

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

Add support for pubsub subscription identifiers

File size: 127.5 KB
Line 
1# Copyright (c) 2003-2010 Ralph Meijer
2# See LICENSE for details.
3
4"""
5Tests for L{wokkel.pubsub}
6"""
7
8from zope.interface import verify
9
10from twisted.trial import unittest
11from twisted.internet import defer
12from twisted.words.xish import domish
13from twisted.words.protocols.jabber import error
14from twisted.words.protocols.jabber.jid import JID
15from twisted.words.protocols.jabber.xmlstream import toResponse
16
17from wokkel import data_form, disco, iwokkel, pubsub, shim
18from wokkel.generic import parseXml
19from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
20
21NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
22NS_PUBSUB_NODE_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
23NS_PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors'
24NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event'
25NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner'
26NS_PUBSUB_META_DATA = 'http://jabber.org/protocol/pubsub#meta-data'
27NS_PUBSUB_SUBSCRIBE_OPTIONS = 'http://jabber.org/protocol/pubsub#subscribe_options'
28
29def calledAsync(fn):
30    """
31    Function wrapper that fires a deferred upon calling the given function.
32    """
33    d = defer.Deferred()
34
35    def func(*args, **kwargs):
36        try:
37            result = fn(*args, **kwargs)
38        except:
39            d.errback()
40        else:
41            d.callback(result)
42
43    return d, func
44
45
46class SubscriptionTest(unittest.TestCase):
47    """
48    Tests for L{pubsub.Subscription}.
49    """
50
51    def test_fromElement(self):
52        """
53        fromElement parses a subscription from XML DOM.
54        """
55        xml = """
56        <subscription node='test' jid='user@example.org/Home'
57                      subscription='pending'/>
58        """
59        subscription = pubsub.Subscription.fromElement(parseXml(xml))
60        self.assertEqual('test', subscription.nodeIdentifier)
61        self.assertEqual(JID('user@example.org/Home'), subscription.subscriber)
62        self.assertEqual('pending', subscription.state)
63        self.assertIdentical(None, subscription.subscriptionIdentifier)
64
65
66    def test_fromElementWithSubscriptionIdentifier(self):
67        """
68        A subscription identifier in the subscription should be parsed, too.
69        """
70        xml = """
71        <subscription node='test' jid='user@example.org/Home' subid='1234'
72                      subscription='pending'/>
73        """
74        subscription = pubsub.Subscription.fromElement(parseXml(xml))
75        self.assertEqual('1234', subscription.subscriptionIdentifier)
76
77
78    def test_toElement(self):
79        """
80        Rendering a Subscription should yield the proper attributes.
81        """
82        subscription = pubsub.Subscription('test',
83                                           JID('user@example.org/Home'),
84                                           'pending')
85        element = subscription.toElement()
86        self.assertEqual('subscription', element.name)
87        self.assertEqual(None, element.uri)
88        self.assertEqual('test', element.getAttribute('node'))
89        self.assertEqual('user@example.org/Home', element.getAttribute('jid'))
90        self.assertEqual('pending', element.getAttribute('subscription'))
91        self.assertFalse(element.hasAttribute('subid'))
92
93
94    def test_toElementEmptyNodeIdentifier(self):
95        """
96        The empty node identifier should not yield a node attribute.
97        """
98        subscription = pubsub.Subscription('',
99                                           JID('user@example.org/Home'),
100                                           'pending')
101        element = subscription.toElement()
102        self.assertFalse(element.hasAttribute('node'))
103
104
105    def test_toElementWithSubscriptionIdentifier(self):
106        """
107        The subscription identifier, if set, is in the subid attribute.
108        """
109        subscription = pubsub.Subscription('test',
110                                           JID('user@example.org/Home'),
111                                           'pending',
112                                           subscriptionIdentifier='1234')
113        element = subscription.toElement()
114        self.assertEqual('1234', element.getAttribute('subid'))
115
116
117
118class PubSubClientTest(unittest.TestCase):
119    timeout = 2
120
121    def setUp(self):
122        self.stub = XmlStreamStub()
123        self.protocol = pubsub.PubSubClient()
124        self.protocol.xmlstream = self.stub.xmlstream
125        self.protocol.connectionInitialized()
126
127
128    def test_interface(self):
129        """
130        Do instances of L{pubsub.PubSubClient} provide L{iwokkel.IPubSubClient}?
131        """
132        verify.verifyObject(iwokkel.IPubSubClient, self.protocol)
133
134
135    def test_eventItems(self):
136        """
137        Test receiving an items event resulting in a call to itemsReceived.
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        items = event.addElement('items')
144        items['node'] = 'test'
145        item1 = items.addElement('item')
146        item1['id'] = 'item1'
147        item2 = items.addElement('retract')
148        item2['id'] = 'item2'
149        item3 = items.addElement('item')
150        item3['id'] = 'item3'
151
152        def itemsReceived(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([item1, item2, item3], event.items)
157
158        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
159        self.stub.send(message)
160        return d
161
162
163    def test_eventItemsCollection(self):
164        """
165        Test receiving an items event resulting in a call to itemsReceived.
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('items')
172        items['node'] = 'test'
173
174        headers = shim.Headers([('Collection', 'collection')])
175        message.addChild(headers)
176
177        def itemsReceived(event):
178            self.assertEquals(JID('user@example.org/home'), event.recipient)
179            self.assertEquals(JID('pubsub.example.org'), event.sender)
180            self.assertEquals('test', event.nodeIdentifier)
181            self.assertEquals({'Collection': ['collection']}, event.headers)
182
183        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
184        self.stub.send(message)
185        return d
186
187
188    def test_eventDelete(self):
189        """
190        Test receiving a delete event resulting in a call to deleteReceived.
191        """
192        message = domish.Element((None, 'message'))
193        message['from'] = 'pubsub.example.org'
194        message['to'] = 'user@example.org/home'
195        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
196        delete = event.addElement('delete')
197        delete['node'] = 'test'
198
199        def deleteReceived(event):
200            self.assertEquals(JID('user@example.org/home'), event.recipient)
201            self.assertEquals(JID('pubsub.example.org'), event.sender)
202            self.assertEquals('test', event.nodeIdentifier)
203
204        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
205        self.stub.send(message)
206        return d
207
208
209    def test_eventDeleteRedirect(self):
210        """
211        Test receiving a delete event with a redirect URI.
212        """
213        message = domish.Element((None, 'message'))
214        message['from'] = 'pubsub.example.org'
215        message['to'] = 'user@example.org/home'
216        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
217        delete = event.addElement('delete')
218        delete['node'] = 'test'
219        uri = 'xmpp:pubsub.example.org?;node=test2'
220        delete.addElement('redirect')['uri'] = uri
221
222        def deleteReceived(event):
223            self.assertEquals(JID('user@example.org/home'), event.recipient)
224            self.assertEquals(JID('pubsub.example.org'), event.sender)
225            self.assertEquals('test', event.nodeIdentifier)
226            self.assertEquals(uri, event.redirectURI)
227
228        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
229        self.stub.send(message)
230        return d
231
232
233    def test_event_purge(self):
234        """
235        Test receiving a purge event resulting in a call to purgeReceived.
236        """
237        message = domish.Element((None, 'message'))
238        message['from'] = 'pubsub.example.org'
239        message['to'] = 'user@example.org/home'
240        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
241        items = event.addElement('purge')
242        items['node'] = 'test'
243
244        def purgeReceived(event):
245            self.assertEquals(JID('user@example.org/home'), event.recipient)
246            self.assertEquals(JID('pubsub.example.org'), event.sender)
247            self.assertEquals('test', event.nodeIdentifier)
248
249        d, self.protocol.purgeReceived = calledAsync(purgeReceived)
250        self.stub.send(message)
251        return d
252
253
254    def test_createNode(self):
255        """
256        Test sending create request.
257        """
258
259        def cb(nodeIdentifier):
260            self.assertEquals('test', nodeIdentifier)
261
262        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
263        d.addCallback(cb)
264
265        iq = self.stub.output[-1]
266        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
267        self.assertEquals('set', iq.getAttribute('type'))
268        self.assertEquals('pubsub', iq.pubsub.name)
269        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
270        children = list(domish.generateElementsQNamed(iq.pubsub.children,
271                                                      'create', NS_PUBSUB))
272        self.assertEquals(1, len(children))
273        child = children[0]
274        self.assertEquals('test', child['node'])
275
276        response = toResponse(iq, 'result')
277        self.stub.send(response)
278        return d
279
280
281    def test_createNodeInstant(self):
282        """
283        Test sending create request resulting in an instant node.
284        """
285
286        def cb(nodeIdentifier):
287            self.assertEquals('test', nodeIdentifier)
288
289        d = self.protocol.createNode(JID('pubsub.example.org'))
290        d.addCallback(cb)
291
292        iq = self.stub.output[-1]
293        children = list(domish.generateElementsQNamed(iq.pubsub.children,
294                                                      'create', NS_PUBSUB))
295        child = children[0]
296        self.assertFalse(child.hasAttribute('node'))
297
298        response = toResponse(iq, 'result')
299        command = response.addElement((NS_PUBSUB, 'pubsub'))
300        create = command.addElement('create')
301        create['node'] = 'test'
302        self.stub.send(response)
303        return d
304
305
306    def test_createNodeRenamed(self):
307        """
308        Test sending create request resulting in renamed node.
309        """
310
311        def cb(nodeIdentifier):
312            self.assertEquals('test2', nodeIdentifier)
313
314        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
315        d.addCallback(cb)
316
317        iq = self.stub.output[-1]
318        children = list(domish.generateElementsQNamed(iq.pubsub.children,
319                                                      'create', NS_PUBSUB))
320        child = children[0]
321        self.assertEquals('test', child['node'])
322
323        response = toResponse(iq, 'result')
324        command = response.addElement((NS_PUBSUB, 'pubsub'))
325        create = command.addElement('create')
326        create['node'] = 'test2'
327        self.stub.send(response)
328        return d
329
330
331    def test_createNodeWithSender(self):
332        """
333        Test sending create request from a specific JID.
334        """
335
336        d = self.protocol.createNode(JID('pubsub.example.org'), 'test',
337                                     sender=JID('user@example.org'))
338
339        iq = self.stub.output[-1]
340        self.assertEquals('user@example.org', iq['from'])
341
342        response = toResponse(iq, 'result')
343        self.stub.send(response)
344        return d
345
346
347    def test_createNodeWithConfig(self):
348        """
349        Test sending create request with configuration options
350        """
351
352        options = {
353            'pubsub#title': 'Princely Musings (Atom)',
354            'pubsub#deliver_payloads': True,
355            'pubsub#persist_items': '1',
356            'pubsub#max_items': '10',
357            'pubsub#access_model': 'open',
358            'pubsub#type': 'http://www.w3.org/2005/Atom',
359        }
360
361        d = self.protocol.createNode(JID('pubsub.example.org'), 'test',
362                                     sender=JID('user@example.org'),
363                                     options=options)
364
365        iq = self.stub.output[-1]
366
367        # check if there is exactly one configure element
368        children = list(domish.generateElementsQNamed(iq.pubsub.children,
369                                                      'configure', NS_PUBSUB))
370        self.assertEqual(1, len(children))
371
372        # check that it has a configuration form
373        form = data_form.findForm(children[0], NS_PUBSUB_NODE_CONFIG)
374        self.assertEqual('submit', form.formType)
375
376
377        response = toResponse(iq, 'result')
378        self.stub.send(response)
379        return d
380
381
382    def test_deleteNode(self):
383        """
384        Test sending delete request.
385        """
386
387        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test')
388
389        iq = self.stub.output[-1]
390        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
391        self.assertEquals('set', iq.getAttribute('type'))
392        self.assertEquals('pubsub', iq.pubsub.name)
393        self.assertEquals(NS_PUBSUB_OWNER, iq.pubsub.uri)
394        children = list(domish.generateElementsQNamed(iq.pubsub.children,
395                                                      'delete', NS_PUBSUB_OWNER))
396        self.assertEquals(1, len(children))
397        child = children[0]
398        self.assertEquals('test', child['node'])
399
400        response = toResponse(iq, 'result')
401        self.stub.send(response)
402        return d
403
404
405    def test_deleteNodeWithSender(self):
406        """
407        Test sending delete request.
408        """
409
410        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test',
411                                     sender=JID('user@example.org'))
412
413        iq = self.stub.output[-1]
414        self.assertEquals('user@example.org', iq['from'])
415
416        response = toResponse(iq, 'result')
417        self.stub.send(response)
418        return d
419
420
421    def test_publish(self):
422        """
423        Test sending publish request.
424        """
425
426        item = pubsub.Item()
427        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item])
428
429        iq = self.stub.output[-1]
430        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
431        self.assertEquals('set', iq.getAttribute('type'))
432        self.assertEquals('pubsub', iq.pubsub.name)
433        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
434        children = list(domish.generateElementsQNamed(iq.pubsub.children,
435                                                      'publish', NS_PUBSUB))
436        self.assertEquals(1, len(children))
437        child = children[0]
438        self.assertEquals('test', child['node'])
439        items = list(domish.generateElementsQNamed(child.children,
440                                                   'item', NS_PUBSUB))
441        self.assertEquals(1, len(items))
442        self.assertIdentical(item, items[0])
443
444        response = toResponse(iq, 'result')
445        self.stub.send(response)
446        return d
447
448
449    def test_publishNoItems(self):
450        """
451        Test sending publish request without items.
452        """
453
454        d = self.protocol.publish(JID('pubsub.example.org'), 'test')
455
456        iq = self.stub.output[-1]
457        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
458        self.assertEquals('set', iq.getAttribute('type'))
459        self.assertEquals('pubsub', iq.pubsub.name)
460        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
461        children = list(domish.generateElementsQNamed(iq.pubsub.children,
462                                                      'publish', NS_PUBSUB))
463        self.assertEquals(1, len(children))
464        child = children[0]
465        self.assertEquals('test', child['node'])
466
467        response = toResponse(iq, 'result')
468        self.stub.send(response)
469        return d
470
471
472    def test_publishWithSender(self):
473        """
474        Test sending publish request from a specific JID.
475        """
476
477        item = pubsub.Item()
478        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item],
479                                  JID('user@example.org'))
480
481        iq = self.stub.output[-1]
482        self.assertEquals('user@example.org', iq['from'])
483
484        response = toResponse(iq, 'result')
485        self.stub.send(response)
486        return d
487
488
489    def test_subscribe(self):
490        """
491        Test sending subscription request.
492        """
493        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
494                                      JID('user@example.org'))
495
496        iq = self.stub.output[-1]
497        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
498        self.assertEquals('set', iq.getAttribute('type'))
499        self.assertEquals('pubsub', iq.pubsub.name)
500        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
501        children = list(domish.generateElementsQNamed(iq.pubsub.children,
502                                                      'subscribe', NS_PUBSUB))
503        self.assertEquals(1, len(children))
504        child = children[0]
505        self.assertEquals('test', child['node'])
506        self.assertEquals('user@example.org', child['jid'])
507
508        response = toResponse(iq, 'result')
509        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
510        subscription = pubsub.addElement('subscription')
511        subscription['node'] = 'test'
512        subscription['jid'] = 'user@example.org'
513        subscription['subscription'] = 'subscribed'
514        self.stub.send(response)
515        return d
516
517
518    def test_subscribeReturnsSubscription(self):
519        """
520        A successful subscription should return a Subscription instance.
521        """
522        def cb(subscription):
523            self.assertEqual(JID('user@example.org'), subscription.subscriber)
524
525        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
526                                      JID('user@example.org'))
527        d.addCallback(cb)
528
529        iq = self.stub.output[-1]
530
531        response = toResponse(iq, 'result')
532        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
533        subscription = pubsub.addElement('subscription')
534        subscription['node'] = 'test'
535        subscription['jid'] = 'user@example.org'
536        subscription['subscription'] = 'subscribed'
537        self.stub.send(response)
538        return d
539
540
541    def test_subscribePending(self):
542        """
543        Test sending subscription request that results in a pending
544        subscription.
545        """
546        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
547                                      JID('user@example.org'))
548
549        iq = self.stub.output[-1]
550        response = toResponse(iq, 'result')
551        command = response.addElement((NS_PUBSUB, 'pubsub'))
552        subscription = command.addElement('subscription')
553        subscription['node'] = 'test'
554        subscription['jid'] = 'user@example.org'
555        subscription['subscription'] = 'pending'
556        self.stub.send(response)
557        self.assertFailure(d, pubsub.SubscriptionPending)
558        return d
559
560
561    def test_subscribeUnconfigured(self):
562        """
563        Test sending subscription request that results in an unconfigured
564        subscription.
565        """
566        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
567                                      JID('user@example.org'))
568
569        iq = self.stub.output[-1]
570        response = toResponse(iq, 'result')
571        command = response.addElement((NS_PUBSUB, 'pubsub'))
572        subscription = command.addElement('subscription')
573        subscription['node'] = 'test'
574        subscription['jid'] = 'user@example.org'
575        subscription['subscription'] = 'unconfigured'
576        self.stub.send(response)
577        self.assertFailure(d, pubsub.SubscriptionUnconfigured)
578        return d
579
580
581    def test_subscribeWithOptions(self):
582        options = {'pubsub#deliver': False}
583
584        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
585                                    JID('user@example.org'),
586                                    options=options)
587        iq = self.stub.output[-1]
588
589        # Check options present
590        childNames = []
591        for element in iq.pubsub.elements():
592            if element.uri == NS_PUBSUB:
593                childNames.append(element.name)
594
595        self.assertEqual(['subscribe', 'options'], childNames)
596        form = data_form.findForm(iq.pubsub.options,
597                                  NS_PUBSUB_SUBSCRIBE_OPTIONS)
598        self.assertEqual('submit', form.formType)
599        form.typeCheck({'pubsub#deliver': {'type': 'boolean'}})
600        self.assertEqual(options, form.getValues())
601
602        # Send response
603        response = toResponse(iq, 'result')
604        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
605        subscription = pubsub.addElement('subscription')
606        subscription['node'] = 'test'
607        subscription['jid'] = 'user@example.org'
608        subscription['subscription'] = 'subscribed'
609        self.stub.send(response)
610
611        return d
612
613
614    def test_subscribeWithSender(self):
615        """
616        Test sending subscription request from a specific JID.
617        """
618        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
619                                      JID('user@example.org'),
620                                      sender=JID('user@example.org'))
621
622        iq = self.stub.output[-1]
623        self.assertEquals('user@example.org', iq['from'])
624
625        response = toResponse(iq, 'result')
626        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
627        subscription = pubsub.addElement('subscription')
628        subscription['node'] = 'test'
629        subscription['jid'] = 'user@example.org'
630        subscription['subscription'] = 'subscribed'
631        self.stub.send(response)
632        return d
633
634
635    def test_subscribeReturningSubscriptionIdentifier(self):
636        """
637        Test sending subscription request with subscription identifier.
638        """
639        def cb(subscription):
640            self.assertEqual('1234', subscription.subscriptionIdentifier)
641
642        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
643                                      JID('user@example.org'))
644        d.addCallback(cb)
645
646        iq = self.stub.output[-1]
647
648        response = toResponse(iq, 'result')
649        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
650        subscription = pubsub.addElement('subscription')
651        subscription['node'] = 'test'
652        subscription['jid'] = 'user@example.org'
653        subscription['subscription'] = 'subscribed'
654        subscription['subid'] = '1234'
655        self.stub.send(response)
656        return d
657
658
659    def test_unsubscribe(self):
660        """
661        Test sending unsubscription request.
662        """
663        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
664                                      JID('user@example.org'))
665
666        iq = self.stub.output[-1]
667        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
668        self.assertEquals('set', iq.getAttribute('type'))
669        self.assertEquals('pubsub', iq.pubsub.name)
670        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
671        children = list(domish.generateElementsQNamed(iq.pubsub.children,
672                                                      'unsubscribe', NS_PUBSUB))
673        self.assertEquals(1, len(children))
674        child = children[0]
675        self.assertEquals('test', child['node'])
676        self.assertEquals('user@example.org', child['jid'])
677
678        self.stub.send(toResponse(iq, 'result'))
679        return d
680
681
682    def test_unsubscribeWithSender(self):
683        """
684        Test sending unsubscription request from a specific JID.
685        """
686        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
687                                      JID('user@example.org'),
688                                      sender=JID('user@example.org'))
689
690        iq = self.stub.output[-1]
691        self.assertEquals('user@example.org', iq['from'])
692        self.stub.send(toResponse(iq, 'result'))
693        return d
694
695
696    def test_unsubscribeWithSubscriptionIdentifier(self):
697        """
698        Test sending unsubscription request with subscription identifier.
699        """
700        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
701                                      JID('user@example.org'),
702                                      subscriptionIdentifier='1234')
703
704        iq = self.stub.output[-1]
705        child = iq.pubsub.unsubscribe
706        self.assertEquals('1234', child['subid'])
707
708        self.stub.send(toResponse(iq, 'result'))
709        return d
710
711
712    def test_items(self):
713        """
714        Test sending items request.
715        """
716        def cb(items):
717            self.assertEquals([], items)
718
719        d = self.protocol.items(JID('pubsub.example.org'), 'test')
720        d.addCallback(cb)
721
722        iq = self.stub.output[-1]
723        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
724        self.assertEquals('get', iq.getAttribute('type'))
725        self.assertEquals('pubsub', iq.pubsub.name)
726        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
727        children = list(domish.generateElementsQNamed(iq.pubsub.children,
728                                                      'items', NS_PUBSUB))
729        self.assertEquals(1, len(children))
730        child = children[0]
731        self.assertEquals('test', child['node'])
732
733        response = toResponse(iq, 'result')
734        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
735        items['node'] = 'test'
736
737        self.stub.send(response)
738
739        return d
740
741
742    def test_itemsMaxItems(self):
743        """
744        Test sending items request, with limit on the number of items.
745        """
746        def cb(items):
747            self.assertEquals(2, len(items))
748            self.assertEquals([item1, item2], items)
749
750        d = self.protocol.items(JID('pubsub.example.org'), 'test', maxItems=2)
751        d.addCallback(cb)
752
753        iq = self.stub.output[-1]
754        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
755        self.assertEquals('get', iq.getAttribute('type'))
756        self.assertEquals('pubsub', iq.pubsub.name)
757        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
758        children = list(domish.generateElementsQNamed(iq.pubsub.children,
759                                                      'items', NS_PUBSUB))
760        self.assertEquals(1, len(children))
761        child = children[0]
762        self.assertEquals('test', child['node'])
763        self.assertEquals('2', child['max_items'])
764
765        response = toResponse(iq, 'result')
766        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
767        items['node'] = 'test'
768        item1 = items.addElement('item')
769        item1['id'] = 'item1'
770        item2 = items.addElement('item')
771        item2['id'] = 'item2'
772
773        self.stub.send(response)
774
775        return d
776
777
778    def test_itemsWithSubscriptionIdentifier(self):
779        """
780        Test sending items request with a subscription identifier.
781        """
782
783        d = self.protocol.items(JID('pubsub.example.org'), 'test',
784                               subscriptionIdentifier='1234')
785
786        iq = self.stub.output[-1]
787        child = iq.pubsub.items
788        self.assertEquals('1234', child['subid'])
789
790        response = toResponse(iq, 'result')
791        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
792        items['node'] = 'test'
793
794        self.stub.send(response)
795        return d
796
797
798    def test_itemsWithSender(self):
799        """
800        Test sending items request from a specific JID.
801        """
802
803        d = self.protocol.items(JID('pubsub.example.org'), 'test',
804                               sender=JID('user@example.org'))
805
806        iq = self.stub.output[-1]
807        self.assertEquals('user@example.org', iq['from'])
808
809        response = toResponse(iq, 'result')
810        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
811        items['node'] = 'test'
812
813        self.stub.send(response)
814        return d
815
816
817    def test_getOptions(self):
818        def cb(form):
819            self.assertEqual('form', form.formType)
820            self.assertEqual(NS_PUBSUB_SUBSCRIBE_OPTIONS, form.formNamespace)
821            field = form.fields['pubsub#deliver']
822            self.assertEqual('boolean', field.fieldType)
823            self.assertIdentical(True, field.value)
824            self.assertEqual('Enable delivery?', field.label)
825
826        d = self.protocol.getOptions(JID('pubsub.example.org'), 'test',
827                                     JID('user@example.org'),
828                                     sender=JID('user@example.org'))
829        d.addCallback(cb)
830
831        iq = self.stub.output[-1]
832        self.assertEqual('pubsub.example.org', iq.getAttribute('to'))
833        self.assertEqual('get', iq.getAttribute('type'))
834        self.assertEqual('pubsub', iq.pubsub.name)
835        self.assertEqual(NS_PUBSUB, iq.pubsub.uri)
836        children = list(domish.generateElementsQNamed(iq.pubsub.children,
837                                                      'options', NS_PUBSUB))
838        self.assertEqual(1, len(children))
839        child = children[0]
840        self.assertEqual('test', child['node'])
841
842        self.assertEqual(0, len(child.children))
843
844        # Send response
845        form = data_form.Form('form', formNamespace=NS_PUBSUB_SUBSCRIBE_OPTIONS)
846        form.addField(data_form.Field('boolean', var='pubsub#deliver',
847                                                 label='Enable delivery?',
848                                                 value=True))
849        response = toResponse(iq, 'result')
850        response.addElement((NS_PUBSUB, 'pubsub'))
851        response.pubsub.addElement('options')
852        response.pubsub.options.addChild(form.toElement())
853        self.stub.send(response)
854
855        return d
856
857
858    def test_getOptionsWithSubscriptionIdentifier(self):
859        """
860        Getting options with a subid should have the subid in the request.
861        """
862
863        d = self.protocol.getOptions(JID('pubsub.example.org'), 'test',
864                                     JID('user@example.org'),
865                                     sender=JID('user@example.org'),
866                                     subscriptionIdentifier='1234')
867
868        iq = self.stub.output[-1]
869        child = iq.pubsub.options
870        self.assertEqual('1234', child['subid'])
871
872        # Send response
873        form = data_form.Form('form', formNamespace=NS_PUBSUB_SUBSCRIBE_OPTIONS)
874        form.addField(data_form.Field('boolean', var='pubsub#deliver',
875                                                 label='Enable delivery?',
876                                                 value=True))
877        response = toResponse(iq, 'result')
878        response.addElement((NS_PUBSUB, 'pubsub'))
879        response.pubsub.addElement('options')
880        response.pubsub.options.addChild(form.toElement())
881        self.stub.send(response)
882
883        return d
884
885
886    def test_setOptions(self):
887        """
888        setOptions should send out a options-set request.
889        """
890        options = {'pubsub#deliver': False}
891
892        d = self.protocol.setOptions(JID('pubsub.example.org'), 'test',
893                                     JID('user@example.org'),
894                                     options,
895                                     sender=JID('user@example.org'))
896
897        iq = self.stub.output[-1]
898        self.assertEqual('pubsub.example.org', iq.getAttribute('to'))
899        self.assertEqual('set', iq.getAttribute('type'))
900        self.assertEqual('pubsub', iq.pubsub.name)
901        self.assertEqual(NS_PUBSUB, iq.pubsub.uri)
902        children = list(domish.generateElementsQNamed(iq.pubsub.children,
903                                                      'options', NS_PUBSUB))
904        self.assertEqual(1, len(children))
905        child = children[0]
906        self.assertEqual('test', child['node'])
907
908        form = data_form.findForm(child, NS_PUBSUB_SUBSCRIBE_OPTIONS)
909        self.assertEqual('submit', form.formType)
910        form.typeCheck({'pubsub#deliver': {'type': 'boolean'}})
911        self.assertEqual(options, form.getValues())
912
913        response = toResponse(iq, 'result')
914        self.stub.send(response)
915
916        return d
917
918
919    def test_setOptionsWithSubscriptionIdentifier(self):
920        """
921        setOptions should send out a options-set request with subid.
922        """
923        options = {'pubsub#deliver': False}
924
925        d = self.protocol.setOptions(JID('pubsub.example.org'), 'test',
926                                     JID('user@example.org'),
927                                     options,
928                                     subscriptionIdentifier='1234',
929                                     sender=JID('user@example.org'))
930
931        iq = self.stub.output[-1]
932        child = iq.pubsub.options
933        self.assertEqual('1234', child['subid'])
934
935        form = data_form.findForm(child, NS_PUBSUB_SUBSCRIBE_OPTIONS)
936        self.assertEqual('submit', form.formType)
937        form.typeCheck({'pubsub#deliver': {'type': 'boolean'}})
938        self.assertEqual(options, form.getValues())
939
940        response = toResponse(iq, 'result')
941        self.stub.send(response)
942
943        return d
944
945
946class PubSubRequestTest(unittest.TestCase):
947
948    def test_fromElementUnknown(self):
949        """
950        An unknown verb raises NotImplementedError.
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            <non-existing-verb/>
958          </pubsub>
959        </iq>
960        """
961
962        self.assertRaises(NotImplementedError,
963                          pubsub.PubSubRequest.fromElement, parseXml(xml))
964
965
966    def test_fromElementKnownBadCombination(self):
967        """
968        Multiple verbs in an unknown configuration raises NotImplementedError.
969        """
970
971        xml = """
972        <iq type='set' to='pubsub.example.org'
973                       from='user@example.org'>
974          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
975             <publish/>
976             <create/>
977          </pubsub>
978        </iq>
979        """
980
981        self.assertRaises(NotImplementedError,
982                          pubsub.PubSubRequest.fromElement, parseXml(xml))
983
984    def test_fromElementPublish(self):
985        """
986        Test parsing a publish request.
987        """
988
989        xml = """
990        <iq type='set' to='pubsub.example.org'
991                       from='user@example.org'>
992          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
993            <publish node='test'/>
994          </pubsub>
995        </iq>
996        """
997
998        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
999        self.assertEqual('publish', request.verb)
1000        self.assertEqual(JID('user@example.org'), request.sender)
1001        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1002        self.assertEqual('test', request.nodeIdentifier)
1003        self.assertEqual([], request.items)
1004
1005
1006    def test_fromElementPublishItems(self):
1007        """
1008        Test parsing a publish request with items.
1009        """
1010
1011        xml = """
1012        <iq type='set' to='pubsub.example.org'
1013                       from='user@example.org'>
1014          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1015            <publish node='test'>
1016              <item id="item1"/>
1017              <item id="item2"/>
1018            </publish>
1019          </pubsub>
1020        </iq>
1021        """
1022
1023        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1024        self.assertEqual(2, len(request.items))
1025        self.assertEqual(u'item1', request.items[0]["id"])
1026        self.assertEqual(u'item2', request.items[1]["id"])
1027
1028
1029    def test_fromElementPublishNoNode(self):
1030        """
1031        A publish request to the root node should raise an exception.
1032        """
1033        xml = """
1034        <iq type='set' to='pubsub.example.org'
1035                       from='user@example.org'>
1036          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1037            <publish/>
1038          </pubsub>
1039        </iq>
1040        """
1041
1042        err = self.assertRaises(error.StanzaError,
1043                                pubsub.PubSubRequest.fromElement,
1044                                parseXml(xml))
1045        self.assertEqual('bad-request', err.condition)
1046        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
1047        self.assertEqual('nodeid-required', err.appCondition.name)
1048
1049
1050    def test_fromElementSubscribe(self):
1051        """
1052        Test parsing a subscription request.
1053        """
1054
1055        xml = """
1056        <iq type='set' to='pubsub.example.org'
1057                       from='user@example.org'>
1058          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1059            <subscribe node='test' jid='user@example.org/Home'/>
1060          </pubsub>
1061        </iq>
1062        """
1063
1064        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1065        self.assertEqual('subscribe', request.verb)
1066        self.assertEqual(JID('user@example.org'), request.sender)
1067        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1068        self.assertEqual('test', request.nodeIdentifier)
1069        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
1070
1071
1072    def test_fromElementSubscribeEmptyNode(self):
1073        """
1074        Test parsing a subscription request to the root node.
1075        """
1076
1077        xml = """
1078        <iq type='set' to='pubsub.example.org'
1079                       from='user@example.org'>
1080          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1081            <subscribe jid='user@example.org/Home'/>
1082          </pubsub>
1083        </iq>
1084        """
1085
1086        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1087        self.assertEqual('', request.nodeIdentifier)
1088
1089
1090    def test_fromElementSubscribeNoJID(self):
1091        """
1092        Subscribe requests without a JID should raise a bad-request exception.
1093        """
1094        xml = """
1095        <iq type='set' to='pubsub.example.org'
1096                       from='user@example.org'>
1097          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1098            <subscribe node='test'/>
1099          </pubsub>
1100        </iq>
1101        """
1102        err = self.assertRaises(error.StanzaError,
1103                                pubsub.PubSubRequest.fromElement,
1104                                parseXml(xml))
1105        self.assertEqual('bad-request', err.condition)
1106        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
1107        self.assertEqual('jid-required', err.appCondition.name)
1108
1109
1110    def test_fromElementSubscribeWithOptions(self):
1111        """
1112        Test parsing a subscription request.
1113        """
1114
1115        xml = """
1116        <iq type='set' to='pubsub.example.org'
1117                       from='user@example.org'>
1118          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1119            <subscribe node='test' jid='user@example.org/Home'/>
1120            <options>
1121              <x xmlns="jabber:x:data" type='submit'>
1122                <field var='FORM_TYPE' type='hidden'>
1123                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
1124                </field>
1125                <field var='pubsub#deliver' type='boolean'
1126                       label='Enable delivery?'>
1127                  <value>1</value>
1128                </field>
1129              </x>
1130            </options>
1131          </pubsub>
1132        </iq>
1133        """
1134
1135        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1136        self.assertEqual('subscribe', request.verb)
1137        request.options.typeCheck({'pubsub#deliver': {'type': 'boolean'}})
1138        self.assertEqual({'pubsub#deliver': True}, request.options.getValues())
1139
1140
1141    def test_fromElementSubscribeWithOptionsBadFormType(self):
1142        """
1143        The options form should have the right type.
1144        """
1145
1146        xml = """
1147        <iq type='set' to='pubsub.example.org'
1148                       from='user@example.org'>
1149          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1150            <subscribe node='test' jid='user@example.org/Home'/>
1151            <options>
1152              <x xmlns="jabber:x:data" type='result'>
1153                <field var='FORM_TYPE' type='hidden'>
1154                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
1155                </field>
1156                <field var='pubsub#deliver' type='boolean'
1157                       label='Enable delivery?'>
1158                  <value>1</value>
1159                </field>
1160              </x>
1161            </options>
1162          </pubsub>
1163        </iq>
1164        """
1165
1166        err = self.assertRaises(error.StanzaError,
1167                                pubsub.PubSubRequest.fromElement,
1168                                parseXml(xml))
1169        self.assertEqual('bad-request', err.condition)
1170        self.assertEqual("Unexpected form type 'result'", err.text)
1171        self.assertEqual(None, err.appCondition)
1172
1173
1174    def test_fromElementSubscribeWithOptionsEmpty(self):
1175        """
1176        When no (suitable) form is found, the options are empty.
1177        """
1178
1179        xml = """
1180        <iq type='set' to='pubsub.example.org'
1181                       from='user@example.org'>
1182          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1183            <subscribe node='test' jid='user@example.org/Home'/>
1184            <options/>
1185          </pubsub>
1186        </iq>
1187        """
1188
1189        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1190        self.assertEqual('subscribe', request.verb)
1191        self.assertEqual({}, request.options.getValues())
1192
1193
1194    def test_fromElementUnsubscribe(self):
1195        """
1196        Test parsing an unsubscription request.
1197        """
1198
1199        xml = """
1200        <iq type='set' to='pubsub.example.org'
1201                       from='user@example.org'>
1202          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1203            <unsubscribe node='test' jid='user@example.org/Home'/>
1204          </pubsub>
1205        </iq>
1206        """
1207
1208        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1209        self.assertEqual('unsubscribe', request.verb)
1210        self.assertEqual(JID('user@example.org'), request.sender)
1211        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1212        self.assertEqual('test', request.nodeIdentifier)
1213        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
1214
1215
1216    def test_fromElementUnsubscribeWithSubscriptionIdentifier(self):
1217        """
1218        Test parsing an unsubscription request with subscription identifier.
1219        """
1220
1221        xml = """
1222        <iq type='set' to='pubsub.example.org'
1223                       from='user@example.org'>
1224          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1225            <unsubscribe node='test' jid='user@example.org/Home'
1226                         subid='1234'/>
1227          </pubsub>
1228        </iq>
1229        """
1230
1231        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1232        self.assertEqual('1234', request.subscriptionIdentifier)
1233
1234
1235    def test_fromElementUnsubscribeNoJID(self):
1236        """
1237        Unsubscribe requests without a JID should raise a bad-request exception.
1238        """
1239        xml = """
1240        <iq type='set' to='pubsub.example.org'
1241                       from='user@example.org'>
1242          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1243            <unsubscribe node='test'/>
1244          </pubsub>
1245        </iq>
1246        """
1247        err = self.assertRaises(error.StanzaError,
1248                                pubsub.PubSubRequest.fromElement,
1249                                parseXml(xml))
1250        self.assertEqual('bad-request', err.condition)
1251        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
1252        self.assertEqual('jid-required', err.appCondition.name)
1253
1254
1255    def test_fromElementOptionsGet(self):
1256        """
1257        Test parsing a request for getting subscription options.
1258        """
1259
1260        xml = """
1261        <iq type='get' to='pubsub.example.org'
1262                       from='user@example.org'>
1263          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1264            <options node='test' jid='user@example.org/Home'/>
1265          </pubsub>
1266        </iq>
1267        """
1268
1269        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1270        self.assertEqual('optionsGet', request.verb)
1271        self.assertEqual(JID('user@example.org'), request.sender)
1272        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1273        self.assertEqual('test', request.nodeIdentifier)
1274        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
1275
1276
1277    def test_fromElementOptionsGetWithSubscriptionIdentifier(self):
1278        """
1279        Test parsing a request for getting subscription options with subid.
1280        """
1281
1282        xml = """
1283        <iq type='get' to='pubsub.example.org'
1284                       from='user@example.org'>
1285          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1286            <options node='test' jid='user@example.org/Home'
1287                     subid='1234'/>
1288          </pubsub>
1289        </iq>
1290        """
1291
1292        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1293        self.assertEqual('1234', request.subscriptionIdentifier)
1294
1295
1296    def test_fromElementOptionsSet(self):
1297        """
1298        Test parsing a request for setting subscription options.
1299        """
1300
1301        xml = """
1302        <iq type='set' to='pubsub.example.org'
1303                       from='user@example.org'>
1304          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1305            <options node='test' jid='user@example.org/Home'>
1306              <x xmlns='jabber:x:data' type='submit'>
1307                <field var='FORM_TYPE' type='hidden'>
1308                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
1309                </field>
1310                <field var='pubsub#deliver'><value>1</value></field>
1311              </x>
1312            </options>
1313          </pubsub>
1314        </iq>
1315        """
1316
1317        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1318        self.assertEqual('optionsSet', request.verb)
1319        self.assertEqual(JID('user@example.org'), request.sender)
1320        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1321        self.assertEqual('test', request.nodeIdentifier)
1322        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
1323        self.assertEqual({'pubsub#deliver': '1'}, request.options.getValues())
1324
1325
1326    def test_fromElementOptionsSetWithSubscriptionIdentifier(self):
1327        """
1328        Test parsing a request for setting subscription options with subid.
1329        """
1330
1331        xml = """
1332        <iq type='set' to='pubsub.example.org'
1333                       from='user@example.org'>
1334          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1335            <options node='test' jid='user@example.org/Home'
1336                     subid='1234'>
1337              <x xmlns='jabber:x:data' type='submit'>
1338                <field var='FORM_TYPE' type='hidden'>
1339                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
1340                </field>
1341                <field var='pubsub#deliver'><value>1</value></field>
1342              </x>
1343            </options>
1344          </pubsub>
1345        </iq>
1346        """
1347
1348        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1349        self.assertEqual('1234', request.subscriptionIdentifier)
1350
1351
1352    def test_fromElementOptionsSetCancel(self):
1353        """
1354        Test parsing a request for cancelling setting subscription options.
1355        """
1356
1357        xml = """
1358        <iq type='set' to='pubsub.example.org'
1359                       from='user@example.org'>
1360          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1361            <options node='test' jid='user@example.org/Home'>
1362              <x xmlns='jabber:x:data' type='cancel'/>
1363            </options>
1364          </pubsub>
1365        </iq>
1366        """
1367
1368        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1369        self.assertEqual('cancel', request.options.formType)
1370
1371
1372    def test_fromElementOptionsSetBadFormType(self):
1373        """
1374        On a options set request unknown fields should be ignored.
1375        """
1376
1377        xml = """
1378        <iq type='set' to='pubsub.example.org'
1379                       from='user@example.org'>
1380          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1381            <options node='test' jid='user@example.org/Home'>
1382              <x xmlns='jabber:x:data' type='result'>
1383                <field var='FORM_TYPE' type='hidden'>
1384                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
1385                </field>
1386                <field var='pubsub#deliver'><value>1</value></field>
1387              </x>
1388            </options>
1389          </pubsub>
1390        </iq>
1391        """
1392
1393        err = self.assertRaises(error.StanzaError,
1394                                pubsub.PubSubRequest.fromElement,
1395                                parseXml(xml))
1396        self.assertEqual('bad-request', err.condition)
1397        self.assertEqual("Unexpected form type 'result'", err.text)
1398        self.assertEqual(None, err.appCondition)
1399
1400
1401    def test_fromElementOptionsSetNoForm(self):
1402        """
1403        On a options set request a form is required.
1404        """
1405
1406        xml = """
1407        <iq type='set' to='pubsub.example.org'
1408                       from='user@example.org'>
1409          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1410            <options node='test' jid='user@example.org/Home'/>
1411          </pubsub>
1412        </iq>
1413        """
1414        err = self.assertRaises(error.StanzaError,
1415                                pubsub.PubSubRequest.fromElement,
1416                                parseXml(xml))
1417        self.assertEqual('bad-request', err.condition)
1418        self.assertEqual(None, err.appCondition)
1419
1420
1421    def test_fromElementSubscriptions(self):
1422        """
1423        Test parsing a request for all subscriptions.
1424        """
1425
1426        xml = """
1427        <iq type='get' to='pubsub.example.org'
1428                       from='user@example.org'>
1429          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1430            <subscriptions/>
1431          </pubsub>
1432        </iq>
1433        """
1434
1435        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1436        self.assertEqual('subscriptions', request.verb)
1437        self.assertEqual(JID('user@example.org'), request.sender)
1438        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1439
1440
1441    def test_fromElementAffiliations(self):
1442        """
1443        Test parsing a request for all affiliations.
1444        """
1445
1446        xml = """
1447        <iq type='get' to='pubsub.example.org'
1448                       from='user@example.org'>
1449          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1450            <affiliations/>
1451          </pubsub>
1452        </iq>
1453        """
1454
1455        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1456        self.assertEqual('affiliations', request.verb)
1457        self.assertEqual(JID('user@example.org'), request.sender)
1458        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1459
1460
1461    def test_fromElementCreate(self):
1462        """
1463        Test parsing a request to create a node.
1464        """
1465
1466        xml = """
1467        <iq type='set' to='pubsub.example.org'
1468                       from='user@example.org'>
1469          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1470            <create node='mynode'/>
1471          </pubsub>
1472        </iq>
1473        """
1474
1475        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1476        self.assertEqual('create', request.verb)
1477        self.assertEqual(JID('user@example.org'), request.sender)
1478        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1479        self.assertEqual('mynode', request.nodeIdentifier)
1480        self.assertIdentical(None, request.options)
1481
1482
1483    def test_fromElementCreateInstant(self):
1484        """
1485        Test parsing a request to create an instant node.
1486        """
1487
1488        xml = """
1489        <iq type='set' to='pubsub.example.org'
1490                       from='user@example.org'>
1491          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1492            <create/>
1493          </pubsub>
1494        </iq>
1495        """
1496
1497        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1498        self.assertIdentical(None, request.nodeIdentifier)
1499
1500
1501    def test_fromElementCreateConfigureEmpty(self):
1502        """
1503        Test parsing a request to create a node with an empty configuration.
1504        """
1505
1506        xml = """
1507        <iq type='set' to='pubsub.example.org'
1508                       from='user@example.org'>
1509          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1510            <create node='mynode'/>
1511            <configure/>
1512          </pubsub>
1513        </iq>
1514        """
1515
1516        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1517        self.assertEqual({}, request.options.getValues())
1518
1519
1520    def test_fromElementCreateConfigureEmptyWrongOrder(self):
1521        """
1522        Test parsing a request to create a node and configure, wrong order.
1523
1524        The C{configure} element should come after the C{create} request,
1525        but we should accept both orders.
1526        """
1527
1528        xml = """
1529        <iq type='set' to='pubsub.example.org'
1530                       from='user@example.org'>
1531          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1532            <configure/>
1533            <create node='mynode'/>
1534          </pubsub>
1535        </iq>
1536        """
1537
1538        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1539        self.assertEqual({}, request.options.getValues())
1540
1541
1542    def test_fromElementCreateConfigure(self):
1543        """
1544        Test parsing a request to create a node.
1545        """
1546
1547        xml = """
1548        <iq type='set' to='pubsub.example.org'
1549                       from='user@example.org'>
1550          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1551            <create node='mynode'/>
1552            <configure>
1553              <x xmlns='jabber:x:data' type='submit'>
1554                <field var='FORM_TYPE' type='hidden'>
1555                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1556                </field>
1557                <field var='pubsub#access_model'><value>open</value></field>
1558                <field var='pubsub#persist_items'><value>0</value></field>
1559              </x>
1560            </configure>
1561          </pubsub>
1562        </iq>
1563        """
1564
1565        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1566        values = request.options.getValues()
1567        self.assertIn('pubsub#access_model', values)
1568        self.assertEqual(u'open', values['pubsub#access_model'])
1569        self.assertIn('pubsub#persist_items', values)
1570        self.assertEqual(u'0', values['pubsub#persist_items'])
1571
1572
1573    def test_fromElementCreateConfigureBadFormType(self):
1574        """
1575        The form of a node creation request should have the right type.
1576        """
1577
1578        xml = """
1579        <iq type='set' to='pubsub.example.org'
1580                       from='user@example.org'>
1581          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1582            <create node='mynode'/>
1583            <configure>
1584              <x xmlns='jabber:x:data' type='result'>
1585                <field var='FORM_TYPE' type='hidden'>
1586                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1587                </field>
1588                <field var='pubsub#access_model'><value>open</value></field>
1589                <field var='pubsub#persist_items'><value>0</value></field>
1590              </x>
1591            </configure>
1592          </pubsub>
1593        </iq>
1594        """
1595
1596        err = self.assertRaises(error.StanzaError,
1597                                pubsub.PubSubRequest.fromElement,
1598                                parseXml(xml))
1599        self.assertEqual('bad-request', err.condition)
1600        self.assertEqual("Unexpected form type 'result'", err.text)
1601        self.assertEqual(None, err.appCondition)
1602
1603
1604    def test_fromElementDefault(self):
1605        """
1606        Test parsing a request for the default node configuration.
1607        """
1608
1609        xml = """
1610        <iq type='get' to='pubsub.example.org'
1611                       from='user@example.org'>
1612          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1613            <default/>
1614          </pubsub>
1615        </iq>
1616        """
1617
1618        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1619        self.assertEqual('default', request.verb)
1620        self.assertEqual(JID('user@example.org'), request.sender)
1621        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1622        self.assertEqual('leaf', request.nodeType)
1623
1624
1625    def test_fromElementDefaultCollection(self):
1626        """
1627        Parsing a request for the default configuration extracts the node type.
1628        """
1629
1630        xml = """
1631        <iq type='get' to='pubsub.example.org'
1632                       from='user@example.org'>
1633          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1634            <default>
1635              <x xmlns='jabber:x:data' type='submit'>
1636                <field var='FORM_TYPE' type='hidden'>
1637                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1638                </field>
1639                <field var='pubsub#node_type'>
1640                  <value>collection</value>
1641                </field>
1642              </x>
1643            </default>
1644
1645          </pubsub>
1646        </iq>
1647        """
1648
1649        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1650        self.assertEqual('collection', request.nodeType)
1651
1652
1653    def test_fromElementConfigureGet(self):
1654        """
1655        Test parsing a node configuration get request.
1656        """
1657
1658        xml = """
1659        <iq type='get' to='pubsub.example.org'
1660                       from='user@example.org'>
1661          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1662            <configure node='test'/>
1663          </pubsub>
1664        </iq>
1665        """
1666
1667        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1668        self.assertEqual('configureGet', request.verb)
1669        self.assertEqual(JID('user@example.org'), request.sender)
1670        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1671        self.assertEqual('test', request.nodeIdentifier)
1672
1673
1674    def test_fromElementConfigureSet(self):
1675        """
1676        On a node configuration set request the Data Form is parsed.
1677        """
1678
1679        xml = """
1680        <iq type='set' to='pubsub.example.org'
1681                       from='user@example.org'>
1682          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1683            <configure node='test'>
1684              <x xmlns='jabber:x:data' type='submit'>
1685                <field var='FORM_TYPE' type='hidden'>
1686                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1687                </field>
1688                <field var='pubsub#deliver_payloads'><value>0</value></field>
1689                <field var='pubsub#persist_items'><value>1</value></field>
1690              </x>
1691            </configure>
1692          </pubsub>
1693        </iq>
1694        """
1695
1696        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1697        self.assertEqual('configureSet', request.verb)
1698        self.assertEqual(JID('user@example.org'), request.sender)
1699        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1700        self.assertEqual('test', request.nodeIdentifier)
1701        self.assertEqual({'pubsub#deliver_payloads': '0',
1702                          'pubsub#persist_items': '1'},
1703                         request.options.getValues())
1704
1705
1706    def test_fromElementConfigureSetCancel(self):
1707        """
1708        The node configuration is cancelled, so no options.
1709        """
1710
1711        xml = """
1712        <iq type='set' to='pubsub.example.org'
1713                       from='user@example.org'>
1714          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1715            <configure node='test'>
1716              <x xmlns='jabber:x:data' type='cancel'/>
1717            </configure>
1718          </pubsub>
1719        </iq>
1720        """
1721
1722        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1723        self.assertEqual('cancel', request.options.formType)
1724
1725
1726    def test_fromElementConfigureSetBadFormType(self):
1727        """
1728        The form of a node configuraton set request should have the right type.
1729        """
1730
1731        xml = """
1732        <iq type='set' to='pubsub.example.org'
1733                       from='user@example.org'>
1734          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1735            <configure node='test'>
1736              <x xmlns='jabber:x:data' type='result'>
1737                <field var='FORM_TYPE' type='hidden'>
1738                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1739                </field>
1740                <field var='pubsub#deliver_payloads'><value>0</value></field>
1741                <field var='x-myfield'><value>1</value></field>
1742              </x>
1743            </configure>
1744          </pubsub>
1745        </iq>
1746        """
1747
1748        err = self.assertRaises(error.StanzaError,
1749                                pubsub.PubSubRequest.fromElement,
1750                                parseXml(xml))
1751        self.assertEqual('bad-request', err.condition)
1752        self.assertEqual("Unexpected form type 'result'", err.text)
1753        self.assertEqual(None, err.appCondition)
1754
1755
1756    def test_fromElementConfigureSetNoForm(self):
1757        """
1758        On a node configuration set request a form is required.
1759        """
1760
1761        xml = """
1762        <iq type='set' to='pubsub.example.org'
1763                       from='user@example.org'>
1764          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1765            <configure node='test'/>
1766          </pubsub>
1767        </iq>
1768        """
1769        err = self.assertRaises(error.StanzaError,
1770                                pubsub.PubSubRequest.fromElement,
1771                                parseXml(xml))
1772        self.assertEqual('bad-request', err.condition)
1773        self.assertEqual(None, err.appCondition)
1774
1775
1776    def test_fromElementItems(self):
1777        """
1778        Test parsing an items request.
1779        """
1780        xml = """
1781        <iq type='get' to='pubsub.example.org'
1782                       from='user@example.org'>
1783          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1784            <items node='test'/>
1785          </pubsub>
1786        </iq>
1787        """
1788
1789        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1790        self.assertEqual('items', request.verb)
1791        self.assertEqual(JID('user@example.org'), request.sender)
1792        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1793        self.assertEqual('test', request.nodeIdentifier)
1794        self.assertIdentical(None, request.maxItems)
1795        self.assertIdentical(None, request.subscriptionIdentifier)
1796        self.assertEqual([], request.itemIdentifiers)
1797
1798
1799    def test_fromElementItemsSubscriptionIdentifier(self):
1800        """
1801        Test parsing an items request with subscription identifier.
1802        """
1803        xml = """
1804        <iq type='get' to='pubsub.example.org'
1805                       from='user@example.org'>
1806          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1807            <items node='test' subid='1234'/>
1808          </pubsub>
1809        </iq>
1810        """
1811
1812        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1813        self.assertEqual('1234', request.subscriptionIdentifier)
1814
1815
1816    def test_fromElementRetract(self):
1817        """
1818        Test parsing a retract request.
1819        """
1820
1821        xml = """
1822        <iq type='set' to='pubsub.example.org'
1823                       from='user@example.org'>
1824          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1825            <retract node='test'>
1826              <item id='item1'/>
1827              <item id='item2'/>
1828            </retract>
1829          </pubsub>
1830        </iq>
1831        """
1832
1833        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1834        self.assertEqual('retract', request.verb)
1835        self.assertEqual(JID('user@example.org'), request.sender)
1836        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1837        self.assertEqual('test', request.nodeIdentifier)
1838        self.assertEqual(['item1', 'item2'], request.itemIdentifiers)
1839
1840
1841    def test_fromElementPurge(self):
1842        """
1843        Test parsing a purge request.
1844        """
1845
1846        xml = """
1847        <iq type='set' to='pubsub.example.org'
1848                       from='user@example.org'>
1849          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1850            <purge node='test'/>
1851          </pubsub>
1852        </iq>
1853        """
1854
1855        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1856        self.assertEqual('purge', request.verb)
1857        self.assertEqual(JID('user@example.org'), request.sender)
1858        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1859        self.assertEqual('test', request.nodeIdentifier)
1860
1861
1862    def test_fromElementDelete(self):
1863        """
1864        Test parsing a delete request.
1865        """
1866
1867        xml = """
1868        <iq type='set' to='pubsub.example.org'
1869                       from='user@example.org'>
1870          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1871            <delete node='test'/>
1872          </pubsub>
1873        </iq>
1874        """
1875
1876        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1877        self.assertEqual('delete', request.verb)
1878        self.assertEqual(JID('user@example.org'), request.sender)
1879        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1880        self.assertEqual('test', request.nodeIdentifier)
1881
1882
1883
1884class PubSubServiceTest(unittest.TestCase, TestableRequestHandlerMixin):
1885    """
1886    Tests for L{pubsub.PubSubService}.
1887    """
1888
1889    def setUp(self):
1890        self.stub = XmlStreamStub()
1891        self.resource = pubsub.PubSubResource()
1892        self.service = pubsub.PubSubService(self.resource)
1893        self.service.send = self.stub.xmlstream.send
1894
1895    def test_interface(self):
1896        """
1897        Do instances of L{pubsub.PubSubService} provide L{iwokkel.IPubSubService}?
1898        """
1899        verify.verifyObject(iwokkel.IPubSubService, self.service)
1900
1901
1902    def test_connectionMade(self):
1903        """
1904        Verify setup of observers in L{pubsub.connectionMade}.
1905        """
1906        requests = []
1907
1908        def handleRequest(iq):
1909            requests.append(iq)
1910
1911        self.service.xmlstream = self.stub.xmlstream
1912        self.service.handleRequest = handleRequest
1913        self.service.connectionMade()
1914
1915        for namespace in (NS_PUBSUB, NS_PUBSUB_OWNER):
1916            for stanzaType in ('get', 'set'):
1917                iq = domish.Element((None, 'iq'))
1918                iq['type'] = stanzaType
1919                iq.addElement((namespace, 'pubsub'))
1920                self.stub.xmlstream.dispatch(iq)
1921
1922        self.assertEqual(4, len(requests))
1923
1924
1925    def test_getDiscoInfo(self):
1926        """
1927        Test getDiscoInfo calls getNodeInfo and returns some minimal info.
1928        """
1929        def cb(info):
1930            discoInfo = disco.DiscoInfo()
1931            for item in info:
1932                discoInfo.append(item)
1933            self.assertIn(('pubsub', 'service'), discoInfo.identities)
1934            self.assertIn(disco.NS_DISCO_ITEMS, discoInfo.features)
1935
1936        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1937                                      JID('pubsub.example.org'), '')
1938        d.addCallback(cb)
1939        return d
1940
1941
1942    def test_getDiscoInfoNodeType(self):
1943        """
1944        Test getDiscoInfo with node type.
1945        """
1946        def cb(info):
1947            discoInfo = disco.DiscoInfo()
1948            for item in info:
1949                discoInfo.append(item)
1950            self.assertIn(('pubsub', 'collection'), discoInfo.identities)
1951
1952        def getInfo(requestor, target, nodeIdentifier):
1953            return defer.succeed({'type': 'collection',
1954                                  'meta-data': {}})
1955
1956        self.resource.getInfo = getInfo
1957        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1958                                      JID('pubsub.example.org'), '')
1959        d.addCallback(cb)
1960        return d
1961
1962
1963    def test_getDiscoInfoMetaData(self):
1964        """
1965        Test getDiscoInfo with returned meta data.
1966        """
1967        def cb(info):
1968            discoInfo = disco.DiscoInfo()
1969            for item in info:
1970                discoInfo.append(item)
1971
1972            self.assertIn(('pubsub', 'leaf'), discoInfo.identities)
1973            self.assertIn(NS_PUBSUB_META_DATA, discoInfo.extensions)
1974            form = discoInfo.extensions[NS_PUBSUB_META_DATA]
1975            self.assertIn('pubsub#node_type', form.fields)
1976
1977        def getInfo(requestor, target, nodeIdentifier):
1978            metaData = [{'var': 'pubsub#persist_items',
1979                         'label': 'Persist items to storage',
1980                         'value': True}]
1981            return defer.succeed({'type': 'leaf', 'meta-data': metaData})
1982
1983        self.resource.getInfo = getInfo
1984        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1985                                      JID('pubsub.example.org'), '')
1986        d.addCallback(cb)
1987        return d
1988
1989
1990    def test_getDiscoInfoResourceFeatures(self):
1991        """
1992        Test getDiscoInfo with the resource features.
1993        """
1994        def cb(info):
1995            discoInfo = disco.DiscoInfo()
1996            for item in info:
1997                discoInfo.append(item)
1998            self.assertIn('http://jabber.org/protocol/pubsub#publish',
1999                          discoInfo.features)
2000
2001        self.resource.features = ['publish']
2002        d = self.service.getDiscoInfo(JID('user@example.org/home'),
2003                                      JID('pubsub.example.org'), '')
2004        d.addCallback(cb)
2005        return d
2006
2007
2008    def test_getDiscoItemsRoot(self):
2009        """
2010        Test getDiscoItems on the root node.
2011        """
2012        def getNodes(requestor, service, nodeIdentifier):
2013            return defer.succeed(['node1', 'node2'])
2014
2015        def cb(items):
2016            self.assertEqual(2, len(items))
2017            item1, item2 = items
2018
2019            self.assertEqual(JID('pubsub.example.org'), item1.entity)
2020            self.assertEqual('node1', item1.nodeIdentifier)
2021
2022            self.assertEqual(JID('pubsub.example.org'), item2.entity)
2023            self.assertEqual('node2', item2.nodeIdentifier)
2024
2025        self.resource.getNodes = getNodes
2026        d = self.service.getDiscoItems(JID('user@example.org/home'),
2027                                       JID('pubsub.example.org'),
2028                                       '')
2029        d.addCallback(cb)
2030        return d
2031
2032
2033    def test_getDiscoItemsRootHideNodes(self):
2034        """
2035        Test getDiscoItems on the root node.
2036        """
2037        def getNodes(requestor, service, nodeIdentifier):
2038            raise Exception("Unexpected call to getNodes")
2039
2040        def cb(items):
2041            self.assertEqual([], items)
2042
2043        self.service.hideNodes = True
2044        self.resource.getNodes = getNodes
2045        d = self.service.getDiscoItems(JID('user@example.org/home'),
2046                                       JID('pubsub.example.org'),
2047                                       '')
2048        d.addCallback(cb)
2049        return d
2050
2051
2052    def test_getDiscoItemsNonRoot(self):
2053        """
2054        Test getDiscoItems on a non-root node.
2055        """
2056        def getNodes(requestor, service, nodeIdentifier):
2057            return defer.succeed(['node1', 'node2'])
2058
2059        def cb(items):
2060            self.assertEqual(2, len(items))
2061
2062        self.resource.getNodes = getNodes
2063        d = self.service.getDiscoItems(JID('user@example.org/home'),
2064                                       JID('pubsub.example.org'),
2065                                       'test')
2066        d.addCallback(cb)
2067        return d
2068
2069
2070    def test_on_publish(self):
2071        """
2072        A publish request should result in L{PubSubService.publish} being
2073        called.
2074        """
2075
2076        xml = """
2077        <iq type='set' to='pubsub.example.org'
2078                       from='user@example.org'>
2079          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2080            <publish node='test'/>
2081          </pubsub>
2082        </iq>
2083        """
2084
2085        def publish(request):
2086            return defer.succeed(None)
2087
2088        self.resource.publish = publish
2089        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2090        return self.handleRequest(xml)
2091
2092
2093    def test_on_subscribe(self):
2094        """
2095        A successful subscription should return the current subscription.
2096        """
2097
2098        xml = """
2099        <iq type='set' to='pubsub.example.org'
2100                       from='user@example.org'>
2101          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2102            <subscribe node='test' jid='user@example.org/Home'/>
2103          </pubsub>
2104        </iq>
2105        """
2106
2107        def subscribe(request):
2108            return defer.succeed(pubsub.Subscription(request.nodeIdentifier,
2109                                                     request.subscriber,
2110                                                     'subscribed'))
2111
2112        def cb(element):
2113            self.assertEqual('pubsub', element.name)
2114            self.assertEqual(NS_PUBSUB, element.uri)
2115            subscription = element.subscription
2116            self.assertIn(subscription.uri, (None, NS_PUBSUB))
2117            self.assertEqual('test', subscription['node'])
2118            self.assertEqual('user@example.org/Home', subscription['jid'])
2119            self.assertEqual('subscribed', subscription['subscription'])
2120
2121        self.resource.subscribe = subscribe
2122        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2123        d = self.handleRequest(xml)
2124        d.addCallback(cb)
2125        return d
2126
2127
2128    def test_on_subscribeEmptyNode(self):
2129        """
2130        A successful subscription on root node should return no node attribute.
2131        """
2132
2133        xml = """
2134        <iq type='set' to='pubsub.example.org'
2135                       from='user@example.org'>
2136          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2137            <subscribe jid='user@example.org/Home'/>
2138          </pubsub>
2139        </iq>
2140        """
2141
2142        def subscribe(request):
2143            return defer.succeed(pubsub.Subscription(request.nodeIdentifier,
2144                                                     request.subscriber,
2145                                                     'subscribed'))
2146
2147        def cb(element):
2148            self.assertFalse(element.subscription.hasAttribute('node'))
2149
2150        self.resource.subscribe = subscribe
2151        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2152        d = self.handleRequest(xml)
2153        d.addCallback(cb)
2154        return d
2155
2156
2157    def test_on_subscribeSubscriptionIdentifier(self):
2158        """
2159        If a subscription returns a subid, this should be available.
2160        """
2161
2162        xml = """
2163        <iq type='set' to='pubsub.example.org'
2164                       from='user@example.org'>
2165          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2166            <subscribe node='test' jid='user@example.org/Home'/>
2167          </pubsub>
2168        </iq>
2169        """
2170
2171        def subscribe(request):
2172            subscription = pubsub.Subscription(request.nodeIdentifier,
2173                                               request.subscriber,
2174                                               'subscribed',
2175                                               subscriptionIdentifier='1234')
2176            return defer.succeed(subscription)
2177
2178        def cb(element):
2179            self.assertEqual('1234', element.subscription.getAttribute('subid'))
2180
2181        self.resource.subscribe = subscribe
2182        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2183        d = self.handleRequest(xml)
2184        d.addCallback(cb)
2185        return d
2186
2187
2188    def test_on_unsubscribe(self):
2189        """
2190        A successful unsubscription should return an empty response.
2191        """
2192
2193        xml = """
2194        <iq type='set' to='pubsub.example.org'
2195                       from='user@example.org'>
2196          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2197            <unsubscribe node='test' jid='user@example.org/Home'/>
2198          </pubsub>
2199        </iq>
2200        """
2201
2202        def unsubscribe(request):
2203            return defer.succeed(None)
2204
2205        def cb(element):
2206            self.assertIdentical(None, element)
2207
2208        self.resource.unsubscribe = unsubscribe
2209        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2210        d = self.handleRequest(xml)
2211        d.addCallback(cb)
2212        return d
2213
2214
2215    def test_on_unsubscribe(self):
2216        """
2217        A successful unsubscription with subid should return an empty response.
2218        """
2219
2220        xml = """
2221        <iq type='set' to='pubsub.example.org'
2222                       from='user@example.org'>
2223          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2224            <unsubscribe node='test' jid='user@example.org/Home' subid='1234'/>
2225          </pubsub>
2226        </iq>
2227        """
2228
2229        def unsubscribe(request):
2230            self.assertEqual('1234', request.subscriptionIdentifier)
2231            return defer.succeed(None)
2232
2233        def cb(element):
2234            self.assertIdentical(None, element)
2235
2236        self.resource.unsubscribe = unsubscribe
2237        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2238        d = self.handleRequest(xml)
2239        d.addCallback(cb)
2240        return d
2241
2242
2243    def test_on_optionsGet(self):
2244        """
2245        Getting subscription options is not supported.
2246        """
2247
2248        xml = """
2249        <iq type='get' to='pubsub.example.org'
2250                       from='user@example.org'>
2251          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2252            <options node='test' jid='user@example.org/Home'/>
2253          </pubsub>
2254        </iq>
2255        """
2256
2257        def cb(result):
2258            self.assertEquals('feature-not-implemented', result.condition)
2259            self.assertEquals('unsupported', result.appCondition.name)
2260            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2261
2262        d = self.handleRequest(xml)
2263        self.assertFailure(d, error.StanzaError)
2264        d.addCallback(cb)
2265        return d
2266
2267
2268    def test_on_optionsSet(self):
2269        """
2270        Setting subscription options is not supported.
2271        """
2272
2273        xml = """
2274        <iq type='set' to='pubsub.example.org'
2275                       from='user@example.org'>
2276          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2277            <options node='test' jid='user@example.org/Home'>
2278              <x xmlns='jabber:x:data' type='submit'>
2279                <field var='FORM_TYPE' type='hidden'>
2280                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
2281                </field>
2282                <field var='pubsub#deliver'><value>1</value></field>
2283              </x>
2284            </options>
2285          </pubsub>
2286        </iq>
2287        """
2288
2289        def cb(result):
2290            self.assertEquals('feature-not-implemented', result.condition)
2291            self.assertEquals('unsupported', result.appCondition.name)
2292            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2293
2294        d = self.handleRequest(xml)
2295        self.assertFailure(d, error.StanzaError)
2296        d.addCallback(cb)
2297        return d
2298
2299
2300    def test_on_subscriptions(self):
2301        """
2302        A subscriptions request should result in
2303        L{PubSubService.subscriptions} being called and the result prepared
2304        for the response.
2305        """
2306
2307        xml = """
2308        <iq type='get' to='pubsub.example.org'
2309                       from='user@example.org'>
2310          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2311            <subscriptions/>
2312          </pubsub>
2313        </iq>
2314        """
2315
2316        def subscriptions(request):
2317            subscription = pubsub.Subscription('test', JID('user@example.org'),
2318                                               'subscribed')
2319            return defer.succeed([subscription])
2320
2321        def cb(element):
2322            self.assertEqual('pubsub', element.name)
2323            self.assertEqual(NS_PUBSUB, element.uri)
2324            self.assertEqual(NS_PUBSUB, element.subscriptions.uri)
2325            children = list(element.subscriptions.elements())
2326            self.assertEqual(1, len(children))
2327            subscription = children[0]
2328            self.assertEqual('subscription', subscription.name)
2329            self.assertIn(subscription.uri, (None, NS_PUBSUB))
2330            self.assertEqual('user@example.org', subscription['jid'])
2331            self.assertEqual('test', subscription['node'])
2332            self.assertEqual('subscribed', subscription['subscription'])
2333
2334        self.resource.subscriptions = subscriptions
2335        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2336        d = self.handleRequest(xml)
2337        d.addCallback(cb)
2338        return d
2339
2340
2341    def test_on_subscriptionsWithSubscriptionIdentifier(self):
2342        """
2343        A subscriptions request response should include subids, if set.
2344        """
2345
2346        xml = """
2347        <iq type='get' to='pubsub.example.org'
2348                       from='user@example.org'>
2349          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2350            <subscriptions/>
2351          </pubsub>
2352        </iq>
2353        """
2354
2355        def subscriptions(request):
2356            subscription = pubsub.Subscription('test', JID('user@example.org'),
2357                                               'subscribed',
2358                                               subscriptionIdentifier='1234')
2359            return defer.succeed([subscription])
2360
2361        def cb(element):
2362            subscription = element.subscriptions.subscription
2363            self.assertEqual('1234', subscription['subid'])
2364
2365        self.resource.subscriptions = subscriptions
2366        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2367        d = self.handleRequest(xml)
2368        d.addCallback(cb)
2369        return d
2370
2371
2372    def test_on_affiliations(self):
2373        """
2374        A subscriptions request should result in
2375        L{PubSubService.affiliations} being called and the result prepared
2376        for the response.
2377        """
2378
2379        xml = """
2380        <iq type='get' to='pubsub.example.org'
2381                       from='user@example.org'>
2382          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2383            <affiliations/>
2384          </pubsub>
2385        </iq>
2386        """
2387
2388        def affiliations(request):
2389            affiliation = ('test', 'owner')
2390            return defer.succeed([affiliation])
2391
2392        def cb(element):
2393            self.assertEqual('pubsub', element.name)
2394            self.assertEqual(NS_PUBSUB, element.uri)
2395            self.assertEqual(NS_PUBSUB, element.affiliations.uri)
2396            children = list(element.affiliations.elements())
2397            self.assertEqual(1, len(children))
2398            affiliation = children[0]
2399            self.assertEqual('affiliation', affiliation.name)
2400            self.assertEqual(NS_PUBSUB, affiliation.uri)
2401            self.assertEqual('test', affiliation['node'])
2402            self.assertEqual('owner', affiliation['affiliation'])
2403
2404        self.resource.affiliations = affiliations
2405        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2406        d = self.handleRequest(xml)
2407        d.addCallback(cb)
2408        return d
2409
2410
2411    def test_on_create(self):
2412        """
2413        Replies to create node requests don't return the created node.
2414        """
2415
2416        xml = """
2417        <iq type='set' to='pubsub.example.org'
2418                       from='user@example.org'>
2419          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2420            <create node='mynode'/>
2421          </pubsub>
2422        </iq>
2423        """
2424
2425        def create(request):
2426            return defer.succeed(request.nodeIdentifier)
2427
2428        def cb(element):
2429            self.assertIdentical(None, element)
2430
2431        self.resource.create = create
2432        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2433        d = self.handleRequest(xml)
2434        d.addCallback(cb)
2435        return d
2436
2437
2438    def test_on_createChanged(self):
2439        """
2440        Replies to create node requests return the created node if changed.
2441        """
2442
2443        xml = """
2444        <iq type='set' to='pubsub.example.org'
2445                       from='user@example.org'>
2446          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2447            <create node='mynode'/>
2448          </pubsub>
2449        </iq>
2450        """
2451
2452        def create(request):
2453            return defer.succeed(u'myrenamednode')
2454
2455        def cb(element):
2456            self.assertEqual('pubsub', element.name)
2457            self.assertEqual(NS_PUBSUB, element.uri)
2458            self.assertEqual(NS_PUBSUB, element.create.uri)
2459            self.assertEqual(u'myrenamednode',
2460                             element.create.getAttribute('node'))
2461
2462        self.resource.create = create
2463        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2464        d = self.handleRequest(xml)
2465        d.addCallback(cb)
2466        return d
2467
2468
2469    def test_on_createInstant(self):
2470        """
2471        Replies to create instant node requests return the created node.
2472        """
2473
2474        xml = """
2475        <iq type='set' to='pubsub.example.org'
2476                       from='user@example.org'>
2477          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2478            <create/>
2479          </pubsub>
2480        </iq>
2481        """
2482
2483        def create(request):
2484            return defer.succeed(u'random')
2485
2486        def cb(element):
2487            self.assertEqual('pubsub', element.name)
2488            self.assertEqual(NS_PUBSUB, element.uri)
2489            self.assertEqual(NS_PUBSUB, element.create.uri)
2490            self.assertEqual(u'random', element.create.getAttribute('node'))
2491
2492        self.resource.create = create
2493        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2494        d = self.handleRequest(xml)
2495        d.addCallback(cb)
2496        return d
2497
2498
2499    def test_on_createWithConfig(self):
2500        """
2501        On a node create with configuration request the Data Form is parsed and
2502        L{PubSubResource.create} is called with the passed options.
2503        """
2504
2505        xml = """
2506        <iq type='set' to='pubsub.example.org'
2507                       from='user@example.org'>
2508          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2509            <create node='mynode'/>
2510            <configure>
2511              <x xmlns='jabber:x:data' type='submit'>
2512                <field var='FORM_TYPE' type='hidden'>
2513                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2514                </field>
2515                <field var='pubsub#deliver_payloads'><value>0</value></field>
2516                <field var='pubsub#persist_items'><value>1</value></field>
2517              </x>
2518            </configure>
2519          </pubsub>
2520        </iq>
2521        """
2522
2523        def getConfigurationOptions():
2524            return {
2525                "pubsub#persist_items":
2526                    {"type": "boolean",
2527                     "label": "Persist items to storage"},
2528                "pubsub#deliver_payloads":
2529                    {"type": "boolean",
2530                     "label": "Deliver payloads with event notifications"}
2531                }
2532
2533        def create(request):
2534            self.assertEqual({'pubsub#deliver_payloads': False,
2535                              'pubsub#persist_items': True},
2536                             request.options.getValues())
2537            return defer.succeed(None)
2538
2539        self.resource.getConfigurationOptions = getConfigurationOptions
2540        self.resource.create = create
2541        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2542        return self.handleRequest(xml)
2543
2544
2545    def test_on_default(self):
2546        """
2547        A default request should result in
2548        L{PubSubService.getDefaultConfiguration} being called.
2549        """
2550
2551        xml = """
2552        <iq type='get' to='pubsub.example.org'
2553                       from='user@example.org'>
2554          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2555            <default/>
2556          </pubsub>
2557        </iq>
2558        """
2559
2560        def getConfigurationOptions():
2561            return {
2562                "pubsub#persist_items":
2563                    {"type": "boolean",
2564                     "label": "Persist items to storage"},
2565                "pubsub#deliver_payloads":
2566                    {"type": "boolean",
2567                     "label": "Deliver payloads with event notifications"}
2568                }
2569
2570        def default(request):
2571            return defer.succeed({})
2572
2573        def cb(element):
2574            self.assertEqual('pubsub', element.name)
2575            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
2576            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
2577            form = data_form.Form.fromElement(element.default.x)
2578            self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace)
2579
2580        self.resource.getConfigurationOptions = getConfigurationOptions
2581        self.resource.default = default
2582        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2583        d = self.handleRequest(xml)
2584        d.addCallback(cb)
2585        return d
2586
2587
2588    def test_on_defaultCollection(self):
2589        """
2590        Responses to default requests should depend on passed node type.
2591        """
2592
2593        xml = """
2594        <iq type='get' to='pubsub.example.org'
2595                       from='user@example.org'>
2596          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2597            <default>
2598              <x xmlns='jabber:x:data' type='submit'>
2599                <field var='FORM_TYPE' type='hidden'>
2600                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2601                </field>
2602                <field var='pubsub#node_type'>
2603                  <value>collection</value>
2604                </field>
2605              </x>
2606            </default>
2607
2608          </pubsub>
2609        </iq>
2610        """
2611
2612        def getConfigurationOptions():
2613            return {
2614                "pubsub#deliver_payloads":
2615                    {"type": "boolean",
2616                     "label": "Deliver payloads with event notifications"}
2617                }
2618
2619        def default(request):
2620            return defer.succeed({})
2621
2622        self.resource.getConfigurationOptions = getConfigurationOptions
2623        self.resource.default = default
2624        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2625        return self.handleRequest(xml)
2626
2627
2628    def test_on_defaultUnknownNodeType(self):
2629        """
2630        A default request should result in
2631        L{PubSubResource.default} being called.
2632        """
2633
2634        xml = """
2635        <iq type='get' to='pubsub.example.org'
2636                       from='user@example.org'>
2637          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2638            <default>
2639              <x xmlns='jabber:x:data' type='submit'>
2640                <field var='FORM_TYPE' type='hidden'>
2641                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2642                </field>
2643                <field var='pubsub#node_type'>
2644                  <value>unknown</value>
2645                </field>
2646              </x>
2647            </default>
2648
2649          </pubsub>
2650        </iq>
2651        """
2652
2653        def default(request):
2654            self.fail("Unexpected call to getConfiguration")
2655
2656        def cb(result):
2657            self.assertEquals('not-acceptable', result.condition)
2658
2659        self.resource.default = default
2660        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2661        d = self.handleRequest(xml)
2662        self.assertFailure(d, error.StanzaError)
2663        d.addCallback(cb)
2664        return d
2665
2666
2667    def test_on_configureGet(self):
2668        """
2669        On a node configuration get
2670        requestL{PubSubResource.configureGet} is called and results in a
2671        data form with the configuration.
2672        """
2673
2674        xml = """
2675        <iq type='get' to='pubsub.example.org'
2676                       from='user@example.org'>
2677          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2678            <configure node='test'/>
2679          </pubsub>
2680        </iq>
2681        """
2682
2683        def getConfigurationOptions():
2684            return {
2685                "pubsub#persist_items":
2686                    {"type": "boolean",
2687                     "label": "Persist items to storage"},
2688                "pubsub#deliver_payloads":
2689                    {"type": "boolean",
2690                     "label": "Deliver payloads with event notifications"},
2691                "pubsub#owner":
2692                    {"type": "jid-single",
2693                     "label": "Owner of the node"}
2694                }
2695
2696        def configureGet(request):
2697            return defer.succeed({'pubsub#deliver_payloads': '0',
2698                                  'pubsub#persist_items': '1',
2699                                  'pubsub#owner': JID('user@example.org'),
2700                                  'x-myfield': 'a'})
2701
2702        def cb(element):
2703            self.assertEqual('pubsub', element.name)
2704            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
2705            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
2706            form = data_form.Form.fromElement(element.configure.x)
2707            self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace)
2708            fields = form.fields
2709
2710            self.assertIn('pubsub#deliver_payloads', fields)
2711            field = fields['pubsub#deliver_payloads']
2712            self.assertEqual('boolean', field.fieldType)
2713            field.typeCheck()
2714            self.assertEqual(False, field.value)
2715
2716            self.assertIn('pubsub#persist_items', fields)
2717            field = fields['pubsub#persist_items']
2718            self.assertEqual('boolean', field.fieldType)
2719            field.typeCheck()
2720            self.assertEqual(True, field.value)
2721
2722            self.assertIn('pubsub#owner', fields)
2723            field = fields['pubsub#owner']
2724            self.assertEqual('jid-single', field.fieldType)
2725            field.typeCheck()
2726            self.assertEqual(JID('user@example.org'), field.value)
2727
2728            self.assertNotIn('x-myfield', fields)
2729
2730        self.resource.getConfigurationOptions = getConfigurationOptions
2731        self.resource.configureGet = configureGet
2732        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2733        d = self.handleRequest(xml)
2734        d.addCallback(cb)
2735        return d
2736
2737
2738    def test_on_configureSet(self):
2739        """
2740        On a node configuration set request the Data Form is parsed and
2741        L{PubSubResource.configureSet} is called with the passed options.
2742        """
2743
2744        xml = """
2745        <iq type='set' to='pubsub.example.org'
2746                       from='user@example.org'>
2747          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2748            <configure node='test'>
2749              <x xmlns='jabber:x:data' type='submit'>
2750                <field var='FORM_TYPE' type='hidden'>
2751                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2752                </field>
2753                <field var='pubsub#deliver_payloads'><value>0</value></field>
2754                <field var='pubsub#persist_items'><value>1</value></field>
2755              </x>
2756            </configure>
2757          </pubsub>
2758        </iq>
2759        """
2760
2761        def getConfigurationOptions():
2762            return {
2763                "pubsub#persist_items":
2764                    {"type": "boolean",
2765                     "label": "Persist items to storage"},
2766                "pubsub#deliver_payloads":
2767                    {"type": "boolean",
2768                     "label": "Deliver payloads with event notifications"}
2769                }
2770
2771        def configureSet(request):
2772            self.assertEqual({'pubsub#deliver_payloads': False,
2773                              'pubsub#persist_items': True},
2774                             request.options.getValues())
2775            return defer.succeed(None)
2776
2777        self.resource.getConfigurationOptions = getConfigurationOptions
2778        self.resource.configureSet = configureSet
2779        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2780        return self.handleRequest(xml)
2781
2782
2783    def test_on_configureSetCancel(self):
2784        """
2785        The node configuration is cancelled,
2786        L{PubSubResource.configureSet} not called.
2787        """
2788
2789        xml = """
2790        <iq type='set' to='pubsub.example.org'
2791                       from='user@example.org'>
2792          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2793            <configure node='test'>
2794              <x xmlns='jabber:x:data' type='cancel'>
2795                <field var='FORM_TYPE' type='hidden'>
2796                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2797                </field>
2798              </x>
2799            </configure>
2800          </pubsub>
2801        </iq>
2802        """
2803
2804        def configureSet(request):
2805            self.fail("Unexpected call to setConfiguration")
2806
2807        self.resource.configureSet = configureSet
2808        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2809        return self.handleRequest(xml)
2810
2811
2812    def test_on_configureSetIgnoreUnknown(self):
2813        """
2814        On a node configuration set request unknown fields should be ignored.
2815        """
2816
2817        xml = """
2818        <iq type='set' to='pubsub.example.org'
2819                       from='user@example.org'>
2820          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2821            <configure node='test'>
2822              <x xmlns='jabber:x:data' type='submit'>
2823                <field var='FORM_TYPE' type='hidden'>
2824                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2825                </field>
2826                <field var='pubsub#deliver_payloads'><value>0</value></field>
2827                <field var='x-myfield'><value>1</value></field>
2828              </x>
2829            </configure>
2830          </pubsub>
2831        </iq>
2832        """
2833
2834        def getConfigurationOptions():
2835            return {
2836                "pubsub#persist_items":
2837                    {"type": "boolean",
2838                     "label": "Persist items to storage"},
2839                "pubsub#deliver_payloads":
2840                    {"type": "boolean",
2841                     "label": "Deliver payloads with event notifications"}
2842                }
2843
2844        def configureSet(request):
2845            self.assertEquals(['pubsub#deliver_payloads'],
2846                              request.options.fields.keys())
2847
2848        self.resource.getConfigurationOptions = getConfigurationOptions
2849        self.resource.configureSet = configureSet
2850        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2851        return self.handleRequest(xml)
2852
2853
2854    def test_on_configureSetBadFormType(self):
2855        """
2856        On a node configuration set request unknown fields should be ignored.
2857        """
2858
2859        xml = """
2860        <iq type='set' to='pubsub.example.org'
2861                       from='user@example.org'>
2862          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2863            <configure node='test'>
2864              <x xmlns='jabber:x:data' type='result'>
2865                <field var='FORM_TYPE' type='hidden'>
2866                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2867                </field>
2868                <field var='pubsub#deliver_payloads'><value>0</value></field>
2869                <field var='x-myfield'><value>1</value></field>
2870              </x>
2871            </configure>
2872          </pubsub>
2873        </iq>
2874        """
2875
2876        def cb(result):
2877            self.assertEquals('bad-request', result.condition)
2878            self.assertEqual("Unexpected form type 'result'", result.text)
2879
2880        d = self.handleRequest(xml)
2881        self.assertFailure(d, error.StanzaError)
2882        d.addCallback(cb)
2883        return d
2884
2885
2886    def test_on_items(self):
2887        """
2888        On a items request, return all items for the given node.
2889        """
2890        xml = """
2891        <iq type='get' to='pubsub.example.org'
2892                       from='user@example.org'>
2893          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2894            <items node='test'/>
2895          </pubsub>
2896        </iq>
2897        """
2898
2899        def items(request):
2900            return defer.succeed([pubsub.Item('current')])
2901
2902        def cb(element):
2903            self.assertEqual(NS_PUBSUB, element.uri)
2904            self.assertEqual(NS_PUBSUB, element.items.uri)
2905            self.assertEqual(1, len(element.items.children))
2906            item = element.items.children[-1]
2907            self.assertTrue(domish.IElement.providedBy(item))
2908            self.assertEqual('item', item.name)
2909            self.assertEqual(NS_PUBSUB, item.uri)
2910            self.assertEqual('current', item['id'])
2911
2912        self.resource.items = items
2913        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2914        d = self.handleRequest(xml)
2915        d.addCallback(cb)
2916        return d
2917
2918
2919    def test_on_retract(self):
2920        """
2921        A retract request should result in L{PubSubResource.retract}
2922        being called.
2923        """
2924
2925        xml = """
2926        <iq type='set' to='pubsub.example.org'
2927                       from='user@example.org'>
2928          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2929            <retract node='test'>
2930              <item id='item1'/>
2931              <item id='item2'/>
2932            </retract>
2933          </pubsub>
2934        </iq>
2935        """
2936
2937        def retract(request):
2938            return defer.succeed(None)
2939
2940        self.resource.retract = retract
2941        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2942        return self.handleRequest(xml)
2943
2944
2945    def test_on_purge(self):
2946        """
2947        A purge request should result in L{PubSubResource.purge} being
2948        called.
2949        """
2950
2951        xml = """
2952        <iq type='set' to='pubsub.example.org'
2953                       from='user@example.org'>
2954          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2955            <purge node='test'/>
2956          </pubsub>
2957        </iq>
2958        """
2959
2960        def purge(request):
2961            return defer.succeed(None)
2962
2963        self.resource.purge = purge
2964        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2965        return self.handleRequest(xml)
2966
2967
2968    def test_on_delete(self):
2969        """
2970        A delete request should result in L{PubSubResource.delete} being
2971        called.
2972        """
2973
2974        xml = """
2975        <iq type='set' to='pubsub.example.org'
2976                       from='user@example.org'>
2977          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2978            <delete node='test'/>
2979          </pubsub>
2980        </iq>
2981        """
2982
2983        def delete(request):
2984            return defer.succeed(None)
2985
2986        self.resource.delete = delete
2987        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2988        return self.handleRequest(xml)
2989
2990
2991    def test_notifyDelete(self):
2992        """
2993        Subscribers should be sent a delete notification.
2994        """
2995        subscriptions = [JID('user@example.org')]
2996        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
2997                                  subscriptions)
2998        message = self.stub.output[-1]
2999
3000        self.assertEquals('message', message.name)
3001        self.assertIdentical(None, message.uri)
3002        self.assertEquals('user@example.org', message['to'])
3003        self.assertEquals('pubsub.example.org', message['from'])
3004        self.assertTrue(message.event)
3005        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
3006        self.assertTrue(message.event.delete)
3007        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
3008        self.assertTrue(message.event.delete.hasAttribute('node'))
3009        self.assertEqual('test', message.event.delete['node'])
3010
3011
3012    def test_notifyDeleteRedirect(self):
3013        """
3014        Subscribers should be sent a delete notification with redirect.
3015        """
3016        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
3017        subscriptions = [JID('user@example.org')]
3018        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
3019                                  subscriptions, redirectURI)
3020        message = self.stub.output[-1]
3021
3022        self.assertEquals('message', message.name)
3023        self.assertIdentical(None, message.uri)
3024        self.assertEquals('user@example.org', message['to'])
3025        self.assertEquals('pubsub.example.org', message['from'])
3026        self.assertTrue(message.event)
3027        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
3028        self.assertTrue(message.event.delete)
3029        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
3030        self.assertTrue(message.event.delete.hasAttribute('node'))
3031        self.assertEqual('test', message.event.delete['node'])
3032        self.assertTrue(message.event.delete.redirect)
3033        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
3034        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
3035        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
3036
3037
3038    def test_on_subscriptionsGet(self):
3039        """
3040        Getting subscription options is not supported.
3041        """
3042
3043        xml = """
3044        <iq type='get' to='pubsub.example.org'
3045                       from='user@example.org'>
3046          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3047            <subscriptions/>
3048          </pubsub>
3049        </iq>
3050        """
3051
3052        def cb(result):
3053            self.assertEquals('feature-not-implemented', result.condition)
3054            self.assertEquals('unsupported', result.appCondition.name)
3055            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3056            self.assertEquals('manage-subscriptions',
3057                              result.appCondition['feature'])
3058
3059        d = self.handleRequest(xml)
3060        self.assertFailure(d, error.StanzaError)
3061        d.addCallback(cb)
3062        return d
3063
3064
3065    def test_on_subscriptionsSet(self):
3066        """
3067        Setting subscription options is not supported.
3068        """
3069
3070        xml = """
3071        <iq type='set' to='pubsub.example.org'
3072                       from='user@example.org'>
3073          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3074            <subscriptions/>
3075          </pubsub>
3076        </iq>
3077        """
3078
3079        def cb(result):
3080            self.assertEquals('feature-not-implemented', result.condition)
3081            self.assertEquals('unsupported', result.appCondition.name)
3082            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3083            self.assertEquals('manage-subscriptions',
3084                              result.appCondition['feature'])
3085
3086        d = self.handleRequest(xml)
3087        self.assertFailure(d, error.StanzaError)
3088        d.addCallback(cb)
3089        return d
3090
3091
3092    def test_on_affiliationsGet(self):
3093        """
3094        Getting subscription options is not supported.
3095        """
3096
3097        xml = """
3098        <iq type='get' to='pubsub.example.org'
3099                       from='user@example.org'>
3100          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3101            <affiliations/>
3102          </pubsub>
3103        </iq>
3104        """
3105
3106        def cb(result):
3107            self.assertEquals('feature-not-implemented', result.condition)
3108            self.assertEquals('unsupported', result.appCondition.name)
3109            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3110            self.assertEquals('modify-affiliations',
3111                              result.appCondition['feature'])
3112
3113        d = self.handleRequest(xml)
3114        self.assertFailure(d, error.StanzaError)
3115        d.addCallback(cb)
3116        return d
3117
3118
3119    def test_on_affiliationsSet(self):
3120        """
3121        Setting subscription options is not supported.
3122        """
3123
3124        xml = """
3125        <iq type='set' to='pubsub.example.org'
3126                       from='user@example.org'>
3127          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3128            <affiliations/>
3129          </pubsub>
3130        </iq>
3131        """
3132
3133        def cb(result):
3134            self.assertEquals('feature-not-implemented', result.condition)
3135            self.assertEquals('unsupported', result.appCondition.name)
3136            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3137            self.assertEquals('modify-affiliations',
3138                              result.appCondition['feature'])
3139
3140        d = self.handleRequest(xml)
3141        self.assertFailure(d, error.StanzaError)
3142        d.addCallback(cb)
3143        return d
3144
3145
3146
3147class PubSubServiceWithoutResourceTest(unittest.TestCase, TestableRequestHandlerMixin):
3148
3149    def setUp(self):
3150        self.stub = XmlStreamStub()
3151        self.service = pubsub.PubSubService()
3152        self.service.send = self.stub.xmlstream.send
3153
3154
3155    def test_publish(self):
3156        """
3157        Non-overridden L{PubSubService.publish} yields unsupported error.
3158        """
3159
3160        xml = """
3161        <iq type='set' to='pubsub.example.org'
3162                       from='user@example.org'>
3163          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
3164            <publish node='mynode'/>
3165          </pubsub>
3166        </iq>
3167        """
3168
3169        def cb(result):
3170            self.assertEquals('feature-not-implemented', result.condition)
3171            self.assertEquals('unsupported', result.appCondition.name)
3172            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3173            self.assertEquals('publish', result.appCondition['feature'])
3174
3175        d = self.handleRequest(xml)
3176        self.assertFailure(d, error.StanzaError)
3177        d.addCallback(cb)
3178        return d
3179
3180
3181    def test_subscribe(self):
3182        """
3183        Non-overridden L{PubSubService.subscribe} yields unsupported error.
3184        """
3185
3186        xml = """
3187        <iq type='set' to='pubsub.example.org'
3188                       from='user@example.org'>
3189          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
3190            <subscribe node='test' jid='user@example.org/Home'/>
3191          </pubsub>
3192        </iq>
3193        """
3194
3195        def cb(result):
3196            self.assertEquals('feature-not-implemented', result.condition)
3197            self.assertEquals('unsupported', result.appCondition.name)
3198            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3199            self.assertEquals('subscribe', result.appCondition['feature'])
3200
3201        d = self.handleRequest(xml)
3202        self.assertFailure(d, error.StanzaError)
3203        d.addCallback(cb)
3204        return d
3205
3206
3207    def test_unsubscribe(self):
3208        """
3209        Non-overridden L{PubSubService.unsubscribe} yields unsupported error.
3210        """
3211
3212        xml = """
3213        <iq type='set' to='pubsub.example.org'
3214                       from='user@example.org'>
3215          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
3216            <unsubscribe node='test' jid='user@example.org/Home'/>
3217          </pubsub>
3218        </iq>
3219        """
3220
3221        def cb(result):
3222            self.assertEquals('feature-not-implemented', result.condition)
3223            self.assertEquals('unsupported', result.appCondition.name)
3224            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3225            self.assertEquals('subscribe', result.appCondition['feature'])
3226
3227        d = self.handleRequest(xml)
3228        self.assertFailure(d, error.StanzaError)
3229        d.addCallback(cb)
3230        return d
3231
3232
3233    def test_subscriptions(self):
3234        """
3235        Non-overridden L{PubSubService.subscriptions} yields unsupported error.
3236        """
3237
3238        xml = """
3239        <iq type='get' to='pubsub.example.org'
3240                       from='user@example.org'>
3241          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
3242            <subscriptions/>
3243          </pubsub>
3244        </iq>
3245        """
3246
3247        def cb(result):
3248            self.assertEquals('feature-not-implemented', result.condition)
3249            self.assertEquals('unsupported', result.appCondition.name)
3250            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3251            self.assertEquals('retrieve-subscriptions',
3252                              result.appCondition['feature'])
3253
3254        d = self.handleRequest(xml)
3255        self.assertFailure(d, error.StanzaError)
3256        d.addCallback(cb)
3257        return d
3258
3259
3260    def test_affiliations(self):
3261        """
3262        Non-overridden L{PubSubService.affiliations} yields unsupported error.
3263        """
3264
3265        xml = """
3266        <iq type='get' to='pubsub.example.org'
3267                       from='user@example.org'>
3268          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
3269            <affiliations/>
3270          </pubsub>
3271        </iq>
3272        """
3273
3274        def cb(result):
3275            self.assertEquals('feature-not-implemented', result.condition)
3276            self.assertEquals('unsupported', result.appCondition.name)
3277            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3278            self.assertEquals('retrieve-affiliations',
3279                              result.appCondition['feature'])
3280
3281        d = self.handleRequest(xml)
3282        self.assertFailure(d, error.StanzaError)
3283        d.addCallback(cb)
3284        return d
3285
3286
3287    def test_create(self):
3288        """
3289        Non-overridden L{PubSubService.create} yields unsupported error.
3290        """
3291
3292        xml = """
3293        <iq type='set' to='pubsub.example.org'
3294                       from='user@example.org'>
3295          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
3296            <create node='mynode'/>
3297          </pubsub>
3298        </iq>
3299        """
3300
3301        def cb(result):
3302            self.assertEquals('feature-not-implemented', result.condition)
3303            self.assertEquals('unsupported', result.appCondition.name)
3304            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3305            self.assertEquals('create-nodes', result.appCondition['feature'])
3306
3307        d = self.handleRequest(xml)
3308        self.assertFailure(d, error.StanzaError)
3309        d.addCallback(cb)
3310        return d
3311
3312
3313    def test_getDefaultConfiguration(self):
3314        """
3315        Non-overridden L{PubSubService.getDefaultConfiguration} yields
3316        unsupported error.
3317        """
3318
3319        xml = """
3320        <iq type='get' to='pubsub.example.org'
3321                       from='user@example.org'>
3322          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3323            <default/>
3324          </pubsub>
3325        </iq>
3326        """
3327
3328        def cb(result):
3329            self.assertEquals('feature-not-implemented', result.condition)
3330            self.assertEquals('unsupported', result.appCondition.name)
3331            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3332            self.assertEquals('retrieve-default', result.appCondition['feature'])
3333
3334        d = self.handleRequest(xml)
3335        self.assertFailure(d, error.StanzaError)
3336        d.addCallback(cb)
3337        return d
3338
3339
3340    def test_getConfiguration(self):
3341        """
3342        Non-overridden L{PubSubService.getConfiguration} yields unsupported
3343        error.
3344        """
3345
3346        xml = """
3347        <iq type='get' to='pubsub.example.org'
3348                       from='user@example.org'>
3349          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3350            <configure/>
3351          </pubsub>
3352        </iq>
3353        """
3354
3355        def cb(result):
3356            self.assertEquals('feature-not-implemented', result.condition)
3357            self.assertEquals('unsupported', result.appCondition.name)
3358            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3359            self.assertEquals('config-node', result.appCondition['feature'])
3360
3361        d = self.handleRequest(xml)
3362        self.assertFailure(d, error.StanzaError)
3363        d.addCallback(cb)
3364        return d
3365
3366
3367    def test_setConfiguration(self):
3368        """
3369        Non-overridden L{PubSubService.setConfiguration} yields unsupported
3370        error.
3371        """
3372
3373        xml = """
3374        <iq type='set' to='pubsub.example.org'
3375                       from='user@example.org'>
3376          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3377            <configure node='test'>
3378              <x xmlns='jabber:x:data' type='submit'>
3379                <field var='FORM_TYPE' type='hidden'>
3380                  <value>http://jabber.org/protocol/pubsub#node_config</value>
3381                </field>
3382                <field var='pubsub#deliver_payloads'><value>0</value></field>
3383                <field var='pubsub#persist_items'><value>1</value></field>
3384              </x>
3385            </configure>
3386          </pubsub>
3387        </iq>
3388        """
3389
3390        def cb(result):
3391            self.assertEquals('feature-not-implemented', result.condition)
3392            self.assertEquals('unsupported', result.appCondition.name)
3393            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3394            self.assertEquals('config-node', result.appCondition['feature'])
3395
3396        d = self.handleRequest(xml)
3397        self.assertFailure(d, error.StanzaError)
3398        d.addCallback(cb)
3399        return d
3400
3401
3402    def test_setConfigurationOptionsDict(self):
3403        """
3404        Options should be passed as a dictionary, not a form.
3405        """
3406
3407        xml = """
3408        <iq type='set' to='pubsub.example.org'
3409                       from='user@example.org'>
3410          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3411            <configure node='test'>
3412              <x xmlns='jabber:x:data' type='submit'>
3413                <field var='FORM_TYPE' type='hidden'>
3414                  <value>http://jabber.org/protocol/pubsub#node_config</value>
3415                </field>
3416                <field var='pubsub#deliver_payloads'><value>0</value></field>
3417                <field var='pubsub#persist_items'><value>1</value></field>
3418              </x>
3419            </configure>
3420          </pubsub>
3421        </iq>
3422        """
3423
3424        def getConfigurationOptions():
3425            return {
3426                "pubsub#persist_items":
3427                    {"type": "boolean",
3428                     "label": "Persist items to storage"},
3429                "pubsub#deliver_payloads":
3430                    {"type": "boolean",
3431                     "label": "Deliver payloads with event notifications"}
3432                }
3433
3434        def setConfiguration(requestor, service, nodeIdentifier, options):
3435            self.assertEquals({'pubsub#deliver_payloads': False,
3436                               'pubsub#persist_items': True}, options)
3437
3438
3439        self.service.getConfigurationOptions = getConfigurationOptions
3440        self.service.setConfiguration = setConfiguration
3441        return self.handleRequest(xml)
3442
3443
3444    def test_items(self):
3445        """
3446        Non-overridden L{PubSubService.items} yields unsupported error.
3447        """
3448        xml = """
3449        <iq type='get' to='pubsub.example.org'
3450                       from='user@example.org'>
3451          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
3452            <items node='test'/>
3453          </pubsub>
3454        </iq>
3455        """
3456
3457        def cb(result):
3458            self.assertEquals('feature-not-implemented', result.condition)
3459            self.assertEquals('unsupported', result.appCondition.name)
3460            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3461            self.assertEquals('retrieve-items', result.appCondition['feature'])
3462
3463        d = self.handleRequest(xml)
3464        self.assertFailure(d, error.StanzaError)
3465        d.addCallback(cb)
3466        return d
3467
3468
3469    def test_retract(self):
3470        """
3471        Non-overridden L{PubSubService.retract} yields unsupported error.
3472        """
3473        xml = """
3474        <iq type='set' to='pubsub.example.org'
3475                       from='user@example.org'>
3476          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
3477            <retract node='test'>
3478              <item id='item1'/>
3479              <item id='item2'/>
3480            </retract>
3481          </pubsub>
3482        </iq>
3483        """
3484
3485        def cb(result):
3486            self.assertEquals('feature-not-implemented', result.condition)
3487            self.assertEquals('unsupported', result.appCondition.name)
3488            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3489            self.assertEquals('retract-items', result.appCondition['feature'])
3490
3491        d = self.handleRequest(xml)
3492        self.assertFailure(d, error.StanzaError)
3493        d.addCallback(cb)
3494        return d
3495
3496
3497    def test_purge(self):
3498        """
3499        Non-overridden L{PubSubService.purge} yields unsupported error.
3500        """
3501        xml = """
3502        <iq type='set' to='pubsub.example.org'
3503                       from='user@example.org'>
3504          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3505            <purge node='test'/>
3506          </pubsub>
3507        </iq>
3508        """
3509
3510        def cb(result):
3511            self.assertEquals('feature-not-implemented', result.condition)
3512            self.assertEquals('unsupported', result.appCondition.name)
3513            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3514            self.assertEquals('purge-nodes', result.appCondition['feature'])
3515
3516        d = self.handleRequest(xml)
3517        self.assertFailure(d, error.StanzaError)
3518        d.addCallback(cb)
3519        return d
3520
3521
3522    def test_delete(self):
3523        """
3524        Non-overridden L{PubSubService.delete} yields unsupported error.
3525        """
3526        xml = """
3527        <iq type='set' to='pubsub.example.org'
3528                       from='user@example.org'>
3529          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
3530            <delete node='test'/>
3531          </pubsub>
3532        </iq>
3533        """
3534
3535        def cb(result):
3536            self.assertEquals('feature-not-implemented', result.condition)
3537            self.assertEquals('unsupported', result.appCondition.name)
3538            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3539            self.assertEquals('delete-nodes', result.appCondition['feature'])
3540
3541        d = self.handleRequest(xml)
3542        self.assertFailure(d, error.StanzaError)
3543        d.addCallback(cb)
3544        return d
3545
3546
3547
3548class PubSubResourceTest(unittest.TestCase):
3549
3550    def setUp(self):
3551        self.resource = pubsub.PubSubResource()
3552
3553
3554    def test_interface(self):
3555        """
3556        Do instances of L{pubsub.PubSubResource} provide L{iwokkel.IPubSubResource}?
3557        """
3558        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
3559
3560
3561    def test_getNodes(self):
3562        """
3563        Default getNodes returns an empty list.
3564        """
3565        def cb(nodes):
3566            self.assertEquals([], nodes)
3567
3568        d = self.resource.getNodes(JID('user@example.org/home'),
3569                                   JID('pubsub.example.org'),
3570                                   '')
3571        d.addCallback(cb)
3572        return d
3573
3574
3575    def test_publish(self):
3576        """
3577        Non-overridden L{PubSubResource.publish} yields unsupported
3578        error.
3579        """
3580
3581        def cb(result):
3582            self.assertEquals('feature-not-implemented', result.condition)
3583            self.assertEquals('unsupported', result.appCondition.name)
3584            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3585            self.assertEquals('publish', result.appCondition['feature'])
3586
3587        d = self.resource.publish(pubsub.PubSubRequest())
3588        self.assertFailure(d, error.StanzaError)
3589        d.addCallback(cb)
3590        return d
3591
3592
3593    def test_subscribe(self):
3594        """
3595        Non-overridden subscriptions yields unsupported error.
3596        """
3597
3598        def cb(result):
3599            self.assertEquals('feature-not-implemented', result.condition)
3600            self.assertEquals('unsupported', result.appCondition.name)
3601            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3602            self.assertEquals('subscribe', result.appCondition['feature'])
3603
3604        d = self.resource.subscribe(pubsub.PubSubRequest())
3605        self.assertFailure(d, error.StanzaError)
3606        d.addCallback(cb)
3607        return d
3608
3609
3610    def test_unsubscribe(self):
3611        """
3612        Non-overridden unsubscribe yields unsupported error.
3613        """
3614
3615        def cb(result):
3616            self.assertEquals('feature-not-implemented', result.condition)
3617            self.assertEquals('unsupported', result.appCondition.name)
3618            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3619            self.assertEquals('subscribe', result.appCondition['feature'])
3620
3621        d = self.resource.unsubscribe(pubsub.PubSubRequest())
3622        self.assertFailure(d, error.StanzaError)
3623        d.addCallback(cb)
3624        return d
3625
3626
3627    def test_subscriptions(self):
3628        """
3629        Non-overridden subscriptions yields unsupported error.
3630        """
3631
3632        def cb(result):
3633            self.assertEquals('feature-not-implemented', result.condition)
3634            self.assertEquals('unsupported', result.appCondition.name)
3635            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3636            self.assertEquals('retrieve-subscriptions',
3637                              result.appCondition['feature'])
3638
3639        d = self.resource.subscriptions(pubsub.PubSubRequest())
3640        self.assertFailure(d, error.StanzaError)
3641        d.addCallback(cb)
3642        return d
3643
3644
3645    def test_affiliations(self):
3646        """
3647        Non-overridden affiliations yields unsupported error.
3648        """
3649
3650        def cb(result):
3651            self.assertEquals('feature-not-implemented', result.condition)
3652            self.assertEquals('unsupported', result.appCondition.name)
3653            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3654            self.assertEquals('retrieve-affiliations',
3655                              result.appCondition['feature'])
3656
3657        d = self.resource.affiliations(pubsub.PubSubRequest())
3658        self.assertFailure(d, error.StanzaError)
3659        d.addCallback(cb)
3660        return d
3661
3662
3663    def test_create(self):
3664        """
3665        Non-overridden create yields unsupported error.
3666        """
3667
3668        def cb(result):
3669            self.assertEquals('feature-not-implemented', result.condition)
3670            self.assertEquals('unsupported', result.appCondition.name)
3671            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3672            self.assertEquals('create-nodes', result.appCondition['feature'])
3673
3674        d = self.resource.create(pubsub.PubSubRequest())
3675        self.assertFailure(d, error.StanzaError)
3676        d.addCallback(cb)
3677        return d
3678
3679
3680    def test_default(self):
3681        """
3682        Non-overridden default yields unsupported error.
3683        """
3684
3685        def cb(result):
3686            self.assertEquals('feature-not-implemented', result.condition)
3687            self.assertEquals('unsupported', result.appCondition.name)
3688            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3689            self.assertEquals('retrieve-default',
3690                              result.appCondition['feature'])
3691
3692        d = self.resource.default(pubsub.PubSubRequest())
3693        self.assertFailure(d, error.StanzaError)
3694        d.addCallback(cb)
3695        return d
3696
3697
3698    def test_configureGet(self):
3699        """
3700        Non-overridden configureGet yields unsupported
3701        error.
3702        """
3703
3704        def cb(result):
3705            self.assertEquals('feature-not-implemented', result.condition)
3706            self.assertEquals('unsupported', result.appCondition.name)
3707            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3708            self.assertEquals('config-node', result.appCondition['feature'])
3709
3710        d = self.resource.configureGet(pubsub.PubSubRequest())
3711        self.assertFailure(d, error.StanzaError)
3712        d.addCallback(cb)
3713        return d
3714
3715
3716    def test_configureSet(self):
3717        """
3718        Non-overridden configureSet yields unsupported error.
3719        """
3720
3721        def cb(result):
3722            self.assertEquals('feature-not-implemented', result.condition)
3723            self.assertEquals('unsupported', result.appCondition.name)
3724            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3725            self.assertEquals('config-node', result.appCondition['feature'])
3726
3727        d = self.resource.configureSet(pubsub.PubSubRequest())
3728        self.assertFailure(d, error.StanzaError)
3729        d.addCallback(cb)
3730        return d
3731
3732
3733    def test_items(self):
3734        """
3735        Non-overridden items yields unsupported error.
3736        """
3737
3738        def cb(result):
3739            self.assertEquals('feature-not-implemented', result.condition)
3740            self.assertEquals('unsupported', result.appCondition.name)
3741            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3742            self.assertEquals('retrieve-items', result.appCondition['feature'])
3743
3744        d = self.resource.items(pubsub.PubSubRequest())
3745        self.assertFailure(d, error.StanzaError)
3746        d.addCallback(cb)
3747        return d
3748
3749
3750    def test_retract(self):
3751        """
3752        Non-overridden retract yields unsupported error.
3753        """
3754
3755        def cb(result):
3756            self.assertEquals('feature-not-implemented', result.condition)
3757            self.assertEquals('unsupported', result.appCondition.name)
3758            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3759            self.assertEquals('retract-items', result.appCondition['feature'])
3760
3761        d = self.resource.retract(pubsub.PubSubRequest())
3762        self.assertFailure(d, error.StanzaError)
3763        d.addCallback(cb)
3764        return d
3765
3766
3767    def test_purge(self):
3768        """
3769        Non-overridden purge yields unsupported error.
3770        """
3771
3772        def cb(result):
3773            self.assertEquals('feature-not-implemented', result.condition)
3774            self.assertEquals('unsupported', result.appCondition.name)
3775            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3776            self.assertEquals('purge-nodes', result.appCondition['feature'])
3777
3778        d = self.resource.purge(pubsub.PubSubRequest())
3779        self.assertFailure(d, error.StanzaError)
3780        d.addCallback(cb)
3781        return d
3782
3783
3784    def test_delete(self):
3785        """
3786        Non-overridden delete yields unsupported error.
3787        """
3788
3789        def cb(result):
3790            self.assertEquals('feature-not-implemented', result.condition)
3791            self.assertEquals('unsupported', result.appCondition.name)
3792            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
3793            self.assertEquals('delete-nodes', result.appCondition['feature'])
3794
3795        d = self.resource.delete(pubsub.PubSubRequest())
3796        self.assertFailure(d, error.StanzaError)
3797        d.addCallback(cb)
3798        return d
Note: See TracBrowser for help on using the repository browser.