source: wokkel/test/test_pubsub.py @ 86:f4aa0d507bc8

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

Don't set an explicit namespace on wokkel.pubsub.Item.

Before this change, wokkel.pubsub.Item could not be used for constructing
notifications, as those are in another namespace. This makes sure that items
will always have the correct namespace, inherited from their ancestors.

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