source: wokkel/test/test_pubsub.py @ 59:e984452207e0

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

Provide PubSubResource?, modeled after Twisted Web resources.

Author: ralphm.
Fixes #47.

This should make it rather easy to make publish-subscribe enabled services.

File size: 97.5 KB
Line 
1# Copyright (c) 2003-2009 Ralph Meijer
2# See LICENSE for details.
3
4"""
5Tests for L{wokkel.pubsub}
6"""
7
8from zope.interface import verify
9
10from twisted.trial import unittest
11from twisted.internet import defer
12from twisted.words.xish import domish
13from twisted.words.protocols.jabber import error
14from twisted.words.protocols.jabber.jid import JID
15from twisted.words.protocols.jabber.xmlstream import toResponse
16
17from wokkel import data_form, disco, iwokkel, pubsub, shim
18from wokkel.generic import parseXml
19from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
20
21NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
22NS_PUBSUB_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'
27
28def calledAsync(fn):
29    """
30    Function wrapper that fires a deferred upon calling the given function.
31    """
32    d = defer.Deferred()
33
34    def func(*args, **kwargs):
35        try:
36            result = fn(*args, **kwargs)
37        except:
38            d.errback()
39        else:
40            d.callback(result)
41
42    return d, func
43
44
45class PubSubClientTest(unittest.TestCase):
46    timeout = 2
47
48    def setUp(self):
49        self.stub = XmlStreamStub()
50        self.protocol = pubsub.PubSubClient()
51        self.protocol.xmlstream = self.stub.xmlstream
52        self.protocol.connectionInitialized()
53
54
55    def test_interface(self):
56        """
57        Do instances of L{pubsub.PubSubClient} provide L{iwokkel.IPubSubClient}?
58        """
59        verify.verifyObject(iwokkel.IPubSubClient, self.protocol)
60
61
62    def test_eventItems(self):
63        """
64        Test receiving an items event resulting in a call to itemsReceived.
65        """
66        message = domish.Element((None, 'message'))
67        message['from'] = 'pubsub.example.org'
68        message['to'] = 'user@example.org/home'
69        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
70        items = event.addElement('items')
71        items['node'] = 'test'
72        item1 = items.addElement('item')
73        item1['id'] = 'item1'
74        item2 = items.addElement('retract')
75        item2['id'] = 'item2'
76        item3 = items.addElement('item')
77        item3['id'] = 'item3'
78
79        def itemsReceived(event):
80            self.assertEquals(JID('user@example.org/home'), event.recipient)
81            self.assertEquals(JID('pubsub.example.org'), event.sender)
82            self.assertEquals('test', event.nodeIdentifier)
83            self.assertEquals([item1, item2, item3], event.items)
84
85        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
86        self.stub.send(message)
87        return d
88
89
90    def test_eventItemsCollection(self):
91        """
92        Test receiving an items event resulting in a call to itemsReceived.
93        """
94        message = domish.Element((None, 'message'))
95        message['from'] = 'pubsub.example.org'
96        message['to'] = 'user@example.org/home'
97        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
98        items = event.addElement('items')
99        items['node'] = 'test'
100
101        headers = shim.Headers([('Collection', 'collection')])
102        message.addChild(headers)
103
104        def itemsReceived(event):
105            self.assertEquals(JID('user@example.org/home'), event.recipient)
106            self.assertEquals(JID('pubsub.example.org'), event.sender)
107            self.assertEquals('test', event.nodeIdentifier)
108            self.assertEquals({'Collection': ['collection']}, event.headers)
109
110        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
111        self.stub.send(message)
112        return d
113
114
115    def test_eventDelete(self):
116        """
117        Test receiving a delete event resulting in a call to deleteReceived.
118        """
119        message = domish.Element((None, 'message'))
120        message['from'] = 'pubsub.example.org'
121        message['to'] = 'user@example.org/home'
122        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
123        delete = event.addElement('delete')
124        delete['node'] = 'test'
125
126        def deleteReceived(event):
127            self.assertEquals(JID('user@example.org/home'), event.recipient)
128            self.assertEquals(JID('pubsub.example.org'), event.sender)
129            self.assertEquals('test', event.nodeIdentifier)
130
131        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
132        self.stub.send(message)
133        return d
134
135
136    def test_eventDeleteRedirect(self):
137        """
138        Test receiving a delete event with a redirect URI.
139        """
140        message = domish.Element((None, 'message'))
141        message['from'] = 'pubsub.example.org'
142        message['to'] = 'user@example.org/home'
143        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
144        delete = event.addElement('delete')
145        delete['node'] = 'test'
146        uri = 'xmpp:pubsub.example.org?;node=test2'
147        delete.addElement('redirect')['uri'] = uri
148
149        def deleteReceived(event):
150            self.assertEquals(JID('user@example.org/home'), event.recipient)
151            self.assertEquals(JID('pubsub.example.org'), event.sender)
152            self.assertEquals('test', event.nodeIdentifier)
153            self.assertEquals(uri, event.redirectURI)
154
155        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
156        self.stub.send(message)
157        return d
158
159
160    def test_event_purge(self):
161        """
162        Test receiving a purge event resulting in a call to purgeReceived.
163        """
164        message = domish.Element((None, 'message'))
165        message['from'] = 'pubsub.example.org'
166        message['to'] = 'user@example.org/home'
167        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
168        items = event.addElement('purge')
169        items['node'] = 'test'
170
171        def purgeReceived(event):
172            self.assertEquals(JID('user@example.org/home'), event.recipient)
173            self.assertEquals(JID('pubsub.example.org'), event.sender)
174            self.assertEquals('test', event.nodeIdentifier)
175
176        d, self.protocol.purgeReceived = calledAsync(purgeReceived)
177        self.stub.send(message)
178        return d
179
180
181    def test_createNode(self):
182        """
183        Test sending create request.
184        """
185
186        def cb(nodeIdentifier):
187            self.assertEquals('test', nodeIdentifier)
188
189        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
190        d.addCallback(cb)
191
192        iq = self.stub.output[-1]
193        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
194        self.assertEquals('set', iq.getAttribute('type'))
195        self.assertEquals('pubsub', iq.pubsub.name)
196        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
197        children = list(domish.generateElementsQNamed(iq.pubsub.children,
198                                                      'create', NS_PUBSUB))
199        self.assertEquals(1, len(children))
200        child = children[0]
201        self.assertEquals('test', child['node'])
202
203        response = toResponse(iq, 'result')
204        self.stub.send(response)
205        return d
206
207
208    def test_createNodeInstant(self):
209        """
210        Test sending create request resulting in an instant node.
211        """
212
213        def cb(nodeIdentifier):
214            self.assertEquals('test', nodeIdentifier)
215
216        d = self.protocol.createNode(JID('pubsub.example.org'))
217        d.addCallback(cb)
218
219        iq = self.stub.output[-1]
220        children = list(domish.generateElementsQNamed(iq.pubsub.children,
221                                                      'create', NS_PUBSUB))
222        child = children[0]
223        self.assertFalse(child.hasAttribute('node'))
224
225        response = toResponse(iq, 'result')
226        command = response.addElement((NS_PUBSUB, 'pubsub'))
227        create = command.addElement('create')
228        create['node'] = 'test'
229        self.stub.send(response)
230        return d
231
232
233    def test_createNodeRenamed(self):
234        """
235        Test sending create request resulting in renamed node.
236        """
237
238        def cb(nodeIdentifier):
239            self.assertEquals('test2', nodeIdentifier)
240
241        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
242        d.addCallback(cb)
243
244        iq = self.stub.output[-1]
245        children = list(domish.generateElementsQNamed(iq.pubsub.children,
246                                                      'create', NS_PUBSUB))
247        child = children[0]
248        self.assertEquals('test', child['node'])
249
250        response = toResponse(iq, 'result')
251        command = response.addElement((NS_PUBSUB, 'pubsub'))
252        create = command.addElement('create')
253        create['node'] = 'test2'
254        self.stub.send(response)
255        return d
256
257
258    def test_createNodeWithSender(self):
259        """
260        Test sending create request from a specific JID.
261        """
262
263        d = self.protocol.createNode(JID('pubsub.example.org'), 'test',
264                                     sender=JID('user@example.org'))
265
266        iq = self.stub.output[-1]
267        self.assertEquals('user@example.org', iq['from'])
268
269        response = toResponse(iq, 'result')
270        self.stub.send(response)
271        return d
272
273
274    def test_deleteNode(self):
275        """
276        Test sending delete request.
277        """
278
279        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test')
280
281        iq = self.stub.output[-1]
282        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
283        self.assertEquals('set', iq.getAttribute('type'))
284        self.assertEquals('pubsub', iq.pubsub.name)
285        self.assertEquals(NS_PUBSUB_OWNER, iq.pubsub.uri)
286        children = list(domish.generateElementsQNamed(iq.pubsub.children,
287                                                      'delete', NS_PUBSUB_OWNER))
288        self.assertEquals(1, len(children))
289        child = children[0]
290        self.assertEquals('test', child['node'])
291
292        response = toResponse(iq, 'result')
293        self.stub.send(response)
294        return d
295
296
297    def test_deleteNodeWithSender(self):
298        """
299        Test sending delete request.
300        """
301
302        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test',
303                                     sender=JID('user@example.org'))
304
305        iq = self.stub.output[-1]
306        self.assertEquals('user@example.org', iq['from'])
307
308        response = toResponse(iq, 'result')
309        self.stub.send(response)
310        return d
311
312
313    def test_publish(self):
314        """
315        Test sending publish request.
316        """
317
318        item = pubsub.Item()
319        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item])
320
321        iq = self.stub.output[-1]
322        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
323        self.assertEquals('set', iq.getAttribute('type'))
324        self.assertEquals('pubsub', iq.pubsub.name)
325        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
326        children = list(domish.generateElementsQNamed(iq.pubsub.children,
327                                                      'publish', NS_PUBSUB))
328        self.assertEquals(1, len(children))
329        child = children[0]
330        self.assertEquals('test', child['node'])
331        items = list(domish.generateElementsQNamed(child.children,
332                                                   'item', NS_PUBSUB))
333        self.assertEquals(1, len(items))
334        self.assertIdentical(item, items[0])
335
336        response = toResponse(iq, 'result')
337        self.stub.send(response)
338        return d
339
340
341    def test_publishNoItems(self):
342        """
343        Test sending publish request without items.
344        """
345
346        d = self.protocol.publish(JID('pubsub.example.org'), 'test')
347
348        iq = self.stub.output[-1]
349        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
350        self.assertEquals('set', iq.getAttribute('type'))
351        self.assertEquals('pubsub', iq.pubsub.name)
352        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
353        children = list(domish.generateElementsQNamed(iq.pubsub.children,
354                                                      'publish', NS_PUBSUB))
355        self.assertEquals(1, len(children))
356        child = children[0]
357        self.assertEquals('test', child['node'])
358
359        response = toResponse(iq, 'result')
360        self.stub.send(response)
361        return d
362
363
364    def test_publishWithSender(self):
365        """
366        Test sending publish request from a specific JID.
367        """
368
369        item = pubsub.Item()
370        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item],
371                                  JID('user@example.org'))
372
373        iq = self.stub.output[-1]
374        self.assertEquals('user@example.org', iq['from'])
375
376        response = toResponse(iq, 'result')
377        self.stub.send(response)
378        return d
379
380
381    def test_subscribe(self):
382        """
383        Test sending subscription request.
384        """
385        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
386                                      JID('user@example.org'))
387
388        iq = self.stub.output[-1]
389        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
390        self.assertEquals('set', iq.getAttribute('type'))
391        self.assertEquals('pubsub', iq.pubsub.name)
392        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
393        children = list(domish.generateElementsQNamed(iq.pubsub.children,
394                                                      'subscribe', NS_PUBSUB))
395        self.assertEquals(1, len(children))
396        child = children[0]
397        self.assertEquals('test', child['node'])
398        self.assertEquals('user@example.org', child['jid'])
399
400        response = toResponse(iq, 'result')
401        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
402        subscription = pubsub.addElement('subscription')
403        subscription['node'] = 'test'
404        subscription['jid'] = 'user@example.org'
405        subscription['subscription'] = 'subscribed'
406        self.stub.send(response)
407        return d
408
409
410    def test_subscribePending(self):
411        """
412        Test sending subscription request that results in a pending
413        subscription.
414        """
415        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
416                                      JID('user@example.org'))
417
418        iq = self.stub.output[-1]
419        response = toResponse(iq, 'result')
420        command = response.addElement((NS_PUBSUB, 'pubsub'))
421        subscription = command.addElement('subscription')
422        subscription['node'] = 'test'
423        subscription['jid'] = 'user@example.org'
424        subscription['subscription'] = 'pending'
425        self.stub.send(response)
426        self.assertFailure(d, pubsub.SubscriptionPending)
427        return d
428
429
430    def test_subscribeUnconfigured(self):
431        """
432        Test sending subscription request that results in an unconfigured
433        subscription.
434        """
435        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
436                                      JID('user@example.org'))
437
438        iq = self.stub.output[-1]
439        response = toResponse(iq, 'result')
440        command = response.addElement((NS_PUBSUB, 'pubsub'))
441        subscription = command.addElement('subscription')
442        subscription['node'] = 'test'
443        subscription['jid'] = 'user@example.org'
444        subscription['subscription'] = 'unconfigured'
445        self.stub.send(response)
446        self.assertFailure(d, pubsub.SubscriptionUnconfigured)
447        return d
448
449
450    def test_subscribeWithSender(self):
451        """
452        Test sending subscription request from a specific JID.
453        """
454        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
455                                      JID('user@example.org'),
456                                      sender=JID('user@example.org'))
457
458        iq = self.stub.output[-1]
459        self.assertEquals('user@example.org', iq['from'])
460
461        response = toResponse(iq, 'result')
462        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
463        subscription = pubsub.addElement('subscription')
464        subscription['node'] = 'test'
465        subscription['jid'] = 'user@example.org'
466        subscription['subscription'] = 'subscribed'
467        self.stub.send(response)
468        return d
469
470
471    def test_unsubscribe(self):
472        """
473        Test sending unsubscription request.
474        """
475        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
476                                      JID('user@example.org'))
477
478        iq = self.stub.output[-1]
479        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
480        self.assertEquals('set', iq.getAttribute('type'))
481        self.assertEquals('pubsub', iq.pubsub.name)
482        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
483        children = list(domish.generateElementsQNamed(iq.pubsub.children,
484                                                      'unsubscribe', NS_PUBSUB))
485        self.assertEquals(1, len(children))
486        child = children[0]
487        self.assertEquals('test', child['node'])
488        self.assertEquals('user@example.org', child['jid'])
489
490        self.stub.send(toResponse(iq, 'result'))
491        return d
492
493
494    def test_unsubscribeWithSender(self):
495        """
496        Test sending unsubscription request from a specific JID.
497        """
498        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
499                                      JID('user@example.org'),
500                                      sender=JID('user@example.org'))
501
502        iq = self.stub.output[-1]
503        self.assertEquals('user@example.org', iq['from'])
504        self.stub.send(toResponse(iq, 'result'))
505        return d
506
507
508    def test_items(self):
509        """
510        Test sending items request.
511        """
512        def cb(items):
513            self.assertEquals([], items)
514
515        d = self.protocol.items(JID('pubsub.example.org'), 'test')
516        d.addCallback(cb)
517
518        iq = self.stub.output[-1]
519        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
520        self.assertEquals('get', iq.getAttribute('type'))
521        self.assertEquals('pubsub', iq.pubsub.name)
522        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
523        children = list(domish.generateElementsQNamed(iq.pubsub.children,
524                                                      'items', NS_PUBSUB))
525        self.assertEquals(1, len(children))
526        child = children[0]
527        self.assertEquals('test', child['node'])
528
529        response = toResponse(iq, 'result')
530        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
531        items['node'] = 'test'
532
533        self.stub.send(response)
534
535        return d
536
537
538    def test_itemsMaxItems(self):
539        """
540        Test sending items request, with limit on the number of items.
541        """
542        def cb(items):
543            self.assertEquals(2, len(items))
544            self.assertEquals([item1, item2], items)
545
546        d = self.protocol.items(JID('pubsub.example.org'), 'test', maxItems=2)
547        d.addCallback(cb)
548
549        iq = self.stub.output[-1]
550        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
551        self.assertEquals('get', iq.getAttribute('type'))
552        self.assertEquals('pubsub', iq.pubsub.name)
553        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
554        children = list(domish.generateElementsQNamed(iq.pubsub.children,
555                                                      'items', NS_PUBSUB))
556        self.assertEquals(1, len(children))
557        child = children[0]
558        self.assertEquals('test', child['node'])
559        self.assertEquals('2', child['max_items'])
560
561        response = toResponse(iq, 'result')
562        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
563        items['node'] = 'test'
564        item1 = items.addElement('item')
565        item1['id'] = 'item1'
566        item2 = items.addElement('item')
567        item2['id'] = 'item2'
568
569        self.stub.send(response)
570
571        return d
572
573
574    def test_itemsWithSender(self):
575        """
576        Test sending items request from a specific JID.
577        """
578
579        d = self.protocol.items(JID('pubsub.example.org'), 'test',
580                               sender=JID('user@example.org'))
581
582        iq = self.stub.output[-1]
583        self.assertEquals('user@example.org', iq['from'])
584
585        response = toResponse(iq, 'result')
586        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
587        items['node'] = 'test'
588
589        self.stub.send(response)
590        return d
591
592
593
594class PubSubRequestTest(unittest.TestCase):
595
596    def test_fromElementPublish(self):
597        """
598        Test parsing a publish request.
599        """
600
601        xml = """
602        <iq type='set' to='pubsub.example.org'
603                       from='user@example.org'>
604          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
605            <publish node='test'/>
606          </pubsub>
607        </iq>
608        """
609
610        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
611        self.assertEqual('publish', request.verb)
612        self.assertEqual(JID('user@example.org'), request.sender)
613        self.assertEqual(JID('pubsub.example.org'), request.recipient)
614        self.assertEqual('test', request.nodeIdentifier)
615        self.assertEqual([], request.items)
616
617
618    def test_fromElementPublishItems(self):
619        """
620        Test parsing a publish request with items.
621        """
622
623        xml = """
624        <iq type='set' to='pubsub.example.org'
625                       from='user@example.org'>
626          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
627            <publish node='test'>
628              <item id="item1"/>
629              <item id="item2"/>
630            </publish>
631          </pubsub>
632        </iq>
633        """
634
635        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
636        self.assertEqual(2, len(request.items))
637        self.assertEqual(u'item1', request.items[0]["id"])
638        self.assertEqual(u'item2', request.items[1]["id"])
639
640
641    def test_fromElementPublishNoNode(self):
642        """
643        A publish request to the root node should raise an exception.
644        """
645        xml = """
646        <iq type='set' to='pubsub.example.org'
647                       from='user@example.org'>
648          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
649            <publish/>
650          </pubsub>
651        </iq>
652        """
653
654        err = self.assertRaises(error.StanzaError,
655                                pubsub.PubSubRequest.fromElement,
656                                parseXml(xml))
657        self.assertEqual('bad-request', err.condition)
658        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
659        self.assertEqual('nodeid-required', err.appCondition.name)
660
661
662    def test_fromElementSubscribe(self):
663        """
664        Test parsing a subscription request.
665        """
666
667        xml = """
668        <iq type='set' to='pubsub.example.org'
669                       from='user@example.org'>
670          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
671            <subscribe node='test' jid='user@example.org/Home'/>
672          </pubsub>
673        </iq>
674        """
675
676        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
677        self.assertEqual('subscribe', request.verb)
678        self.assertEqual(JID('user@example.org'), request.sender)
679        self.assertEqual(JID('pubsub.example.org'), request.recipient)
680        self.assertEqual('test', request.nodeIdentifier)
681        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
682
683
684    def test_fromElementSubscribeEmptyNode(self):
685        """
686        Test parsing a subscription request to the root node.
687        """
688
689        xml = """
690        <iq type='set' to='pubsub.example.org'
691                       from='user@example.org'>
692          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
693            <subscribe jid='user@example.org/Home'/>
694          </pubsub>
695        </iq>
696        """
697
698        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
699        self.assertEqual('', request.nodeIdentifier)
700
701
702    def test_fromElementSubscribeNoJID(self):
703        """
704        Subscribe requests without a JID should raise a bad-request exception.
705        """
706        xml = """
707        <iq type='set' to='pubsub.example.org'
708                       from='user@example.org'>
709          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
710            <subscribe node='test'/>
711          </pubsub>
712        </iq>
713        """
714        err = self.assertRaises(error.StanzaError,
715                                pubsub.PubSubRequest.fromElement,
716                                parseXml(xml))
717        self.assertEqual('bad-request', err.condition)
718        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
719        self.assertEqual('jid-required', err.appCondition.name)
720
721    def test_fromElementUnsubscribe(self):
722        """
723        Test parsing an unsubscription request.
724        """
725
726        xml = """
727        <iq type='set' to='pubsub.example.org'
728                       from='user@example.org'>
729          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
730            <unsubscribe node='test' jid='user@example.org/Home'/>
731          </pubsub>
732        </iq>
733        """
734
735        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
736        self.assertEqual('unsubscribe', request.verb)
737        self.assertEqual(JID('user@example.org'), request.sender)
738        self.assertEqual(JID('pubsub.example.org'), request.recipient)
739        self.assertEqual('test', request.nodeIdentifier)
740        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
741
742
743    def test_fromElementUnsubscribeNoJID(self):
744        """
745        Unsubscribe requests without a JID should raise a bad-request exception.
746        """
747        xml = """
748        <iq type='set' to='pubsub.example.org'
749                       from='user@example.org'>
750          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
751            <unsubscribe node='test'/>
752          </pubsub>
753        </iq>
754        """
755        err = self.assertRaises(error.StanzaError,
756                                pubsub.PubSubRequest.fromElement,
757                                parseXml(xml))
758        self.assertEqual('bad-request', err.condition)
759        self.assertEqual(NS_PUBSUB_ERRORS, err.appCondition.uri)
760        self.assertEqual('jid-required', err.appCondition.name)
761
762
763    def test_fromElementOptionsGet(self):
764        """
765        Test parsing a request for getting subscription options.
766        """
767
768        xml = """
769        <iq type='get' to='pubsub.example.org'
770                       from='user@example.org'>
771          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
772            <options node='test' jid='user@example.org/Home'/>
773          </pubsub>
774        </iq>
775        """
776
777        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
778        self.assertEqual('optionsGet', request.verb)
779
780
781    def test_fromElementOptionsSet(self):
782        """
783        Test parsing a request for setting subscription options.
784        """
785
786        xml = """
787        <iq type='set' to='pubsub.example.org'
788                       from='user@example.org'>
789          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
790            <options node='test' jid='user@example.org/Home'>
791              <x xmlns='jabber:x:data' type='submit'>
792                <field var='FORM_TYPE' type='hidden'>
793                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
794                </field>
795                <field var='pubsub#deliver'><value>1</value></field>
796              </x>
797            </options>
798          </pubsub>
799        </iq>
800        """
801
802        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
803        self.assertEqual('optionsSet', request.verb)
804        self.assertEqual(JID('user@example.org'), request.sender)
805        self.assertEqual(JID('pubsub.example.org'), request.recipient)
806        self.assertEqual('test', request.nodeIdentifier)
807        self.assertEqual(JID('user@example.org/Home'), request.subscriber)
808        self.assertEqual({'pubsub#deliver': '1'}, request.options)
809
810
811    def test_fromElementOptionsSetCancel(self):
812        """
813        Test parsing a request for cancelling setting subscription options.
814        """
815
816        xml = """
817        <iq type='set' to='pubsub.example.org'
818                       from='user@example.org'>
819          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
820            <options node='test' jid='user@example.org/Home'>
821              <x xmlns='jabber:x:data' type='cancel'/>
822            </options>
823          </pubsub>
824        </iq>
825        """
826
827        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
828        self.assertEqual({}, request.options)
829
830
831    def test_fromElementOptionsSetBadFormType(self):
832        """
833        On a options set request unknown fields should be ignored.
834        """
835
836        xml = """
837        <iq type='set' to='pubsub.example.org'
838                       from='user@example.org'>
839          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
840            <options node='test' jid='user@example.org/Home'>
841              <x xmlns='jabber:x:data' type='result'>
842                <field var='FORM_TYPE' type='hidden'>
843                  <value>http://jabber.org/protocol/pubsub#node_config</value>
844                </field>
845                <field var='pubsub#deliver'><value>1</value></field>
846              </x>
847            </options>
848          </pubsub>
849        </iq>
850        """
851
852        err = self.assertRaises(error.StanzaError,
853                                pubsub.PubSubRequest.fromElement,
854                                parseXml(xml))
855        self.assertEqual('bad-request', err.condition)
856        self.assertEqual(None, err.appCondition)
857
858
859    def test_fromElementOptionsSetNoForm(self):
860        """
861        On a options set request a form is required.
862        """
863
864        xml = """
865        <iq type='set' to='pubsub.example.org'
866                       from='user@example.org'>
867          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
868            <options node='test' jid='user@example.org/Home'/>
869          </pubsub>
870        </iq>
871        """
872        err = self.assertRaises(error.StanzaError,
873                                pubsub.PubSubRequest.fromElement,
874                                parseXml(xml))
875        self.assertEqual('bad-request', err.condition)
876        self.assertEqual(None, err.appCondition)
877
878
879    def test_fromElementSubscriptions(self):
880        """
881        Test parsing a request for all subscriptions.
882        """
883
884        xml = """
885        <iq type='get' to='pubsub.example.org'
886                       from='user@example.org'>
887          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
888            <subscriptions/>
889          </pubsub>
890        </iq>
891        """
892
893        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
894        self.assertEqual('subscriptions', request.verb)
895        self.assertEqual(JID('user@example.org'), request.sender)
896        self.assertEqual(JID('pubsub.example.org'), request.recipient)
897
898
899    def test_fromElementAffiliations(self):
900        """
901        Test parsing a request for all affiliations.
902        """
903
904        xml = """
905        <iq type='get' to='pubsub.example.org'
906                       from='user@example.org'>
907          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
908            <affiliations/>
909          </pubsub>
910        </iq>
911        """
912
913        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
914        self.assertEqual('affiliations', request.verb)
915        self.assertEqual(JID('user@example.org'), request.sender)
916        self.assertEqual(JID('pubsub.example.org'), request.recipient)
917
918
919    def test_fromElementCreate(self):
920        """
921        Test parsing a request to create a node.
922        """
923
924        xml = """
925        <iq type='set' to='pubsub.example.org'
926                       from='user@example.org'>
927          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
928            <create node='mynode'/>
929          </pubsub>
930        </iq>
931        """
932
933        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
934        self.assertEqual('create', request.verb)
935        self.assertEqual(JID('user@example.org'), request.sender)
936        self.assertEqual(JID('pubsub.example.org'), request.recipient)
937        self.assertEqual('mynode', request.nodeIdentifier)
938
939
940    def test_fromElementCreateInstant(self):
941        """
942        Test parsing a request to create an instant node.
943        """
944
945        xml = """
946        <iq type='set' to='pubsub.example.org'
947                       from='user@example.org'>
948          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
949            <create/>
950          </pubsub>
951        </iq>
952        """
953
954        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
955        self.assertIdentical(None, request.nodeIdentifier)
956
957
958    def test_fromElementDefault(self):
959        """
960        Test parsing a request for the default node configuration.
961        """
962
963        xml = """
964        <iq type='get' to='pubsub.example.org'
965                       from='user@example.org'>
966          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
967            <default/>
968          </pubsub>
969        </iq>
970        """
971
972        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
973        self.assertEqual('default', request.verb)
974        self.assertEqual(JID('user@example.org'), request.sender)
975        self.assertEqual(JID('pubsub.example.org'), request.recipient)
976        self.assertEqual('leaf', request.nodeType)
977
978
979    def test_fromElementDefaultCollection(self):
980        """
981        Parsing a request for the default configuration extracts the node type.
982        """
983
984        xml = """
985        <iq type='get' to='pubsub.example.org'
986                       from='user@example.org'>
987          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
988            <default>
989              <x xmlns='jabber:x:data' type='submit'>
990                <field var='FORM_TYPE' type='hidden'>
991                  <value>http://jabber.org/protocol/pubsub#node_config</value>
992                </field>
993                <field var='pubsub#node_type'>
994                  <value>collection</value>
995                </field>
996              </x>
997            </default>
998
999          </pubsub>
1000        </iq>
1001        """
1002
1003        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1004        self.assertEqual('collection', request.nodeType)
1005
1006
1007    def test_fromElementConfigureGet(self):
1008        """
1009        Test parsing a node configuration get request.
1010        """
1011
1012        xml = """
1013        <iq type='get' to='pubsub.example.org'
1014                       from='user@example.org'>
1015          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1016            <configure node='test'/>
1017          </pubsub>
1018        </iq>
1019        """
1020
1021        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1022        self.assertEqual('configureGet', request.verb)
1023        self.assertEqual(JID('user@example.org'), request.sender)
1024        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1025        self.assertEqual('test', request.nodeIdentifier)
1026
1027
1028    def test_fromElementConfigureSet(self):
1029        """
1030        On a node configuration set request the Data Form is parsed.
1031        """
1032
1033        xml = """
1034        <iq type='set' to='pubsub.example.org'
1035                       from='user@example.org'>
1036          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1037            <configure node='test'>
1038              <x xmlns='jabber:x:data' type='submit'>
1039                <field var='FORM_TYPE' type='hidden'>
1040                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1041                </field>
1042                <field var='pubsub#deliver_payloads'><value>0</value></field>
1043                <field var='pubsub#persist_items'><value>1</value></field>
1044              </x>
1045            </configure>
1046          </pubsub>
1047        </iq>
1048        """
1049
1050        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1051        self.assertEqual('configureSet', request.verb)
1052        self.assertEqual(JID('user@example.org'), request.sender)
1053        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1054        self.assertEqual('test', request.nodeIdentifier)
1055        self.assertEqual({'pubsub#deliver_payloads': '0',
1056                          'pubsub#persist_items': '1'}, request.options)
1057
1058
1059    def test_fromElementConfigureSetCancel(self):
1060        """
1061        The node configuration is cancelled, so no options.
1062        """
1063
1064        xml = """
1065        <iq type='set' to='pubsub.example.org'
1066                       from='user@example.org'>
1067          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1068            <configure node='test'>
1069              <x xmlns='jabber:x:data' type='cancel'/>
1070            </configure>
1071          </pubsub>
1072        </iq>
1073        """
1074
1075        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1076        self.assertEqual({}, request.options)
1077
1078
1079    def test_fromElementConfigureSetBadFormType(self):
1080        """
1081        On a node configuration set request unknown fields should be ignored.
1082        """
1083
1084        xml = """
1085        <iq type='set' to='pubsub.example.org'
1086                       from='user@example.org'>
1087          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1088            <configure node='test'>
1089              <x xmlns='jabber:x:data' type='result'>
1090                <field var='FORM_TYPE' type='hidden'>
1091                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1092                </field>
1093                <field var='pubsub#deliver_payloads'><value>0</value></field>
1094                <field var='x-myfield'><value>1</value></field>
1095              </x>
1096            </configure>
1097          </pubsub>
1098        </iq>
1099        """
1100
1101        err = self.assertRaises(error.StanzaError,
1102                                pubsub.PubSubRequest.fromElement,
1103                                parseXml(xml))
1104        self.assertEqual('bad-request', err.condition)
1105        self.assertEqual(None, err.appCondition)
1106
1107
1108    def test_fromElementConfigureSetNoForm(self):
1109        """
1110        On a node configuration set request a form is required.
1111        """
1112
1113        xml = """
1114        <iq type='set' to='pubsub.example.org'
1115                       from='user@example.org'>
1116          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1117            <configure node='test'/>
1118          </pubsub>
1119        </iq>
1120        """
1121        err = self.assertRaises(error.StanzaError,
1122                                pubsub.PubSubRequest.fromElement,
1123                                parseXml(xml))
1124        self.assertEqual('bad-request', err.condition)
1125        self.assertEqual(None, err.appCondition)
1126
1127
1128    def test_fromElementItems(self):
1129        """
1130        Test parsing an items request.
1131        """
1132        xml = """
1133        <iq type='get' to='pubsub.example.org'
1134                       from='user@example.org'>
1135          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1136            <items node='test'/>
1137          </pubsub>
1138        </iq>
1139        """
1140
1141        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1142        self.assertEqual('items', request.verb)
1143        self.assertEqual(JID('user@example.org'), request.sender)
1144        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1145        self.assertEqual('test', request.nodeIdentifier)
1146        self.assertIdentical(None, request.maxItems)
1147        self.assertEqual([], request.itemIdentifiers)
1148
1149
1150    def test_fromElementRetract(self):
1151        """
1152        Test parsing a retract request.
1153        """
1154
1155        xml = """
1156        <iq type='set' to='pubsub.example.org'
1157                       from='user@example.org'>
1158          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1159            <retract node='test'>
1160              <item id='item1'/>
1161              <item id='item2'/>
1162            </retract>
1163          </pubsub>
1164        </iq>
1165        """
1166
1167        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1168        self.assertEqual('retract', request.verb)
1169        self.assertEqual(JID('user@example.org'), request.sender)
1170        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1171        self.assertEqual('test', request.nodeIdentifier)
1172        self.assertEqual(['item1', 'item2'], request.itemIdentifiers)
1173
1174
1175    def test_fromElementPurge(self):
1176        """
1177        Test parsing a purge request.
1178        """
1179
1180        xml = """
1181        <iq type='set' to='pubsub.example.org'
1182                       from='user@example.org'>
1183          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1184            <purge node='test'/>
1185          </pubsub>
1186        </iq>
1187        """
1188
1189        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1190        self.assertEqual('purge', request.verb)
1191        self.assertEqual(JID('user@example.org'), request.sender)
1192        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1193        self.assertEqual('test', request.nodeIdentifier)
1194
1195
1196    def test_fromElementDelete(self):
1197        """
1198        Test parsing a delete request.
1199        """
1200
1201        xml = """
1202        <iq type='set' to='pubsub.example.org'
1203                       from='user@example.org'>
1204          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1205            <delete node='test'/>
1206          </pubsub>
1207        </iq>
1208        """
1209
1210        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1211        self.assertEqual('delete', request.verb)
1212        self.assertEqual(JID('user@example.org'), request.sender)
1213        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1214        self.assertEqual('test', request.nodeIdentifier)
1215
1216
1217
1218class PubSubServiceTest(unittest.TestCase, TestableRequestHandlerMixin):
1219    """
1220    Tests for L{pubsub.PubSubService}.
1221    """
1222
1223    def setUp(self):
1224        self.stub = XmlStreamStub()
1225        self.resource = pubsub.PubSubResource()
1226        self.service = pubsub.PubSubService(self.resource)
1227        self.service.send = self.stub.xmlstream.send
1228
1229    def test_interface(self):
1230        """
1231        Do instances of L{pubsub.PubSubService} provide L{iwokkel.IPubSubService}?
1232        """
1233        verify.verifyObject(iwokkel.IPubSubService, self.service)
1234
1235
1236    def test_connectionMade(self):
1237        """
1238        Verify setup of observers in L{pubsub.connectionMade}.
1239        """
1240        requests = []
1241
1242        def handleRequest(iq):
1243            requests.append(iq)
1244
1245        self.service.xmlstream = self.stub.xmlstream
1246        self.service.handleRequest = handleRequest
1247        self.service.connectionMade()
1248
1249        for namespace in (NS_PUBSUB, NS_PUBSUB_OWNER):
1250            for stanzaType in ('get', 'set'):
1251                iq = domish.Element((None, 'iq'))
1252                iq['type'] = stanzaType
1253                iq.addElement((namespace, 'pubsub'))
1254                self.stub.xmlstream.dispatch(iq)
1255
1256        self.assertEqual(4, len(requests))
1257
1258
1259    def test_getDiscoInfo(self):
1260        """
1261        Test getDiscoInfo calls getNodeInfo and returns some minimal info.
1262        """
1263        def cb(info):
1264            discoInfo = disco.DiscoInfo()
1265            for item in info:
1266                discoInfo.append(item)
1267            self.assertIn(('pubsub', 'service'), discoInfo.identities)
1268            self.assertIn(disco.NS_DISCO_ITEMS, discoInfo.features)
1269
1270        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1271                                      JID('pubsub.example.org'), '')
1272        d.addCallback(cb)
1273        return d
1274
1275
1276    def test_getDiscoInfoNodeType(self):
1277        """
1278        Test getDiscoInfo with node type.
1279        """
1280        def cb(info):
1281            discoInfo = disco.DiscoInfo()
1282            for item in info:
1283                discoInfo.append(item)
1284            self.assertIn(('pubsub', 'collection'), discoInfo.identities)
1285
1286        def getInfo(requestor, target, nodeIdentifier):
1287            return defer.succeed({'type': 'collection',
1288                                  'meta-data': {}})
1289
1290        self.resource.getInfo = getInfo
1291        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1292                                      JID('pubsub.example.org'), '')
1293        d.addCallback(cb)
1294        return d
1295
1296
1297    def test_getDiscoInfoMetaData(self):
1298        """
1299        Test getDiscoInfo with returned meta data.
1300        """
1301        def cb(info):
1302            discoInfo = disco.DiscoInfo()
1303            for item in info:
1304                discoInfo.append(item)
1305
1306            self.assertIn(('pubsub', 'leaf'), discoInfo.identities)
1307            self.assertIn(NS_PUBSUB_META_DATA, discoInfo.extensions)
1308            form = discoInfo.extensions[NS_PUBSUB_META_DATA]
1309            self.assertIn('pubsub#node_type', form.fields)
1310
1311        def getInfo(requestor, target, nodeIdentifier):
1312            metaData = [{'var': 'pubsub#persist_items',
1313                         'label': 'Persist items to storage',
1314                         'value': True}]
1315            return defer.succeed({'type': 'leaf', 'meta-data': metaData})
1316
1317        self.resource.getInfo = getInfo
1318        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1319                                      JID('pubsub.example.org'), '')
1320        d.addCallback(cb)
1321        return d
1322
1323
1324    def test_getDiscoInfoResourceFeatures(self):
1325        """
1326        Test getDiscoInfo with the resource features.
1327        """
1328        def cb(info):
1329            discoInfo = disco.DiscoInfo()
1330            for item in info:
1331                discoInfo.append(item)
1332            self.assertIn('http://jabber.org/protocol/pubsub#publish',
1333                          discoInfo.features)
1334
1335        self.resource.features = ['publish']
1336        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1337                                      JID('pubsub.example.org'), '')
1338        d.addCallback(cb)
1339        return d
1340
1341
1342    def test_getDiscoItemsRoot(self):
1343        """
1344        Test getDiscoItems on the root node.
1345        """
1346        def getNodes(requestor, service, nodeIdentifier):
1347            return defer.succeed(['node1', 'node2'])
1348
1349        def cb(items):
1350            self.assertEqual(2, len(items))
1351            item1, item2 = items
1352
1353            self.assertEqual(JID('pubsub.example.org'), item1.entity)
1354            self.assertEqual('node1', item1.nodeIdentifier)
1355
1356            self.assertEqual(JID('pubsub.example.org'), item2.entity)
1357            self.assertEqual('node2', item2.nodeIdentifier)
1358
1359        self.resource.getNodes = getNodes
1360        d = self.service.getDiscoItems(JID('user@example.org/home'),
1361                                       JID('pubsub.example.org'),
1362                                       '')
1363        d.addCallback(cb)
1364        return d
1365
1366
1367    def test_getDiscoItemsRootHideNodes(self):
1368        """
1369        Test getDiscoItems on the root node.
1370        """
1371        def getNodes(requestor, service, nodeIdentifier):
1372            raise Exception("Unexpected call to getNodes")
1373
1374        def cb(items):
1375            self.assertEqual([], items)
1376
1377        self.service.hideNodes = True
1378        self.resource.getNodes = getNodes
1379        d = self.service.getDiscoItems(JID('user@example.org/home'),
1380                                       JID('pubsub.example.org'),
1381                                       '')
1382        d.addCallback(cb)
1383        return d
1384
1385
1386    def test_getDiscoItemsNonRoot(self):
1387        """
1388        Test getDiscoItems on a non-root node.
1389        """
1390        def getNodes(requestor, service, nodeIdentifier):
1391            return defer.succeed(['node1', 'node2'])
1392
1393        def cb(items):
1394            self.assertEqual(2, len(items))
1395
1396        self.resource.getNodes = getNodes
1397        d = self.service.getDiscoItems(JID('user@example.org/home'),
1398                                       JID('pubsub.example.org'),
1399                                       'test')
1400        d.addCallback(cb)
1401        return d
1402
1403
1404    def test_on_publish(self):
1405        """
1406        A publish request should result in L{PubSubService.publish} being
1407        called.
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            <publish node='test'/>
1415          </pubsub>
1416        </iq>
1417        """
1418
1419        def publish(request):
1420            return defer.succeed(None)
1421
1422        self.resource.publish = publish
1423        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1424        return self.handleRequest(xml)
1425
1426
1427    def test_on_subscribe(self):
1428        """
1429        A successful subscription should return the current subscription.
1430        """
1431
1432        xml = """
1433        <iq type='set' to='pubsub.example.org'
1434                       from='user@example.org'>
1435          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1436            <subscribe node='test' jid='user@example.org/Home'/>
1437          </pubsub>
1438        </iq>
1439        """
1440
1441        def subscribe(request):
1442            return defer.succeed(pubsub.Subscription(request.nodeIdentifier,
1443                                                     request.subscriber,
1444                                                     'subscribed'))
1445
1446        def cb(element):
1447            self.assertEqual('pubsub', element.name)
1448            self.assertEqual(NS_PUBSUB, element.uri)
1449            subscription = element.subscription
1450            self.assertEqual(NS_PUBSUB, subscription.uri)
1451            self.assertEqual('test', subscription['node'])
1452            self.assertEqual('user@example.org/Home', subscription['jid'])
1453            self.assertEqual('subscribed', subscription['subscription'])
1454
1455        self.resource.subscribe = subscribe
1456        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1457        d = self.handleRequest(xml)
1458        d.addCallback(cb)
1459        return d
1460
1461
1462    def test_on_subscribeEmptyNode(self):
1463        """
1464        A successful subscription on root node should return no node attribute.
1465        """
1466
1467        xml = """
1468        <iq type='set' to='pubsub.example.org'
1469                       from='user@example.org'>
1470          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1471            <subscribe jid='user@example.org/Home'/>
1472          </pubsub>
1473        </iq>
1474        """
1475
1476        def subscribe(request):
1477            return defer.succeed(pubsub.Subscription(request.nodeIdentifier,
1478                                                     request.subscriber,
1479                                                     'subscribed'))
1480
1481        def cb(element):
1482            self.assertFalse(element.subscription.hasAttribute('node'))
1483
1484        self.resource.subscribe = subscribe
1485        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1486        d = self.handleRequest(xml)
1487        d.addCallback(cb)
1488        return d
1489
1490
1491    def test_on_unsubscribe(self):
1492        """
1493        A successful unsubscription should return an empty response.
1494        """
1495
1496        xml = """
1497        <iq type='set' to='pubsub.example.org'
1498                       from='user@example.org'>
1499          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1500            <unsubscribe node='test' jid='user@example.org/Home'/>
1501          </pubsub>
1502        </iq>
1503        """
1504
1505        def unsubscribe(request):
1506            return defer.succeed(None)
1507
1508        def cb(element):
1509            self.assertIdentical(None, element)
1510
1511        self.resource.unsubscribe = unsubscribe
1512        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1513        d = self.handleRequest(xml)
1514        d.addCallback(cb)
1515        return d
1516
1517
1518    def test_on_optionsGet(self):
1519        """
1520        Getting subscription options is not supported.
1521        """
1522
1523        xml = """
1524        <iq type='get' to='pubsub.example.org'
1525                       from='user@example.org'>
1526          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1527            <options node='test' jid='user@example.org/Home'/>
1528          </pubsub>
1529        </iq>
1530        """
1531
1532        def cb(result):
1533            self.assertEquals('feature-not-implemented', result.condition)
1534            self.assertEquals('unsupported', result.appCondition.name)
1535            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
1536
1537        d = self.handleRequest(xml)
1538        self.assertFailure(d, error.StanzaError)
1539        d.addCallback(cb)
1540        return d
1541
1542
1543    def test_on_optionsSet(self):
1544        """
1545        Setting subscription options is not supported.
1546        """
1547
1548        xml = """
1549        <iq type='set' to='pubsub.example.org'
1550                       from='user@example.org'>
1551          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1552            <options node='test' jid='user@example.org/Home'>
1553              <x xmlns='jabber:x:data' type='submit'>
1554                <field var='FORM_TYPE' type='hidden'>
1555                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
1556                </field>
1557                <field var='pubsub#deliver'><value>1</value></field>
1558              </x>
1559            </options>
1560          </pubsub>
1561        </iq>
1562        """
1563
1564        def cb(result):
1565            self.assertEquals('feature-not-implemented', result.condition)
1566            self.assertEquals('unsupported', result.appCondition.name)
1567            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
1568
1569        d = self.handleRequest(xml)
1570        self.assertFailure(d, error.StanzaError)
1571        d.addCallback(cb)
1572        return d
1573
1574
1575    def test_on_subscriptions(self):
1576        """
1577        A subscriptions request should result in
1578        L{PubSubService.subscriptions} being called and the result prepared
1579        for the response.
1580        """
1581
1582        xml = """
1583        <iq type='get' to='pubsub.example.org'
1584                       from='user@example.org'>
1585          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1586            <subscriptions/>
1587          </pubsub>
1588        </iq>
1589        """
1590
1591        def subscriptions(request):
1592            subscription = pubsub.Subscription('test', JID('user@example.org'),
1593                                               'subscribed')
1594            return defer.succeed([subscription])
1595
1596        def cb(element):
1597            self.assertEqual('pubsub', element.name)
1598            self.assertEqual(NS_PUBSUB, element.uri)
1599            self.assertEqual(NS_PUBSUB, element.subscriptions.uri)
1600            children = list(element.subscriptions.elements())
1601            self.assertEqual(1, len(children))
1602            subscription = children[0]
1603            self.assertEqual('subscription', subscription.name)
1604            self.assertEqual(NS_PUBSUB, subscription.uri)
1605            self.assertEqual('user@example.org', subscription['jid'])
1606            self.assertEqual('test', subscription['node'])
1607            self.assertEqual('subscribed', subscription['subscription'])
1608
1609        self.resource.subscriptions = subscriptions
1610        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1611        d = self.handleRequest(xml)
1612        d.addCallback(cb)
1613        return d
1614
1615
1616    def test_on_affiliations(self):
1617        """
1618        A subscriptions request should result in
1619        L{PubSubService.affiliations} being called and the result prepared
1620        for the response.
1621        """
1622
1623        xml = """
1624        <iq type='get' to='pubsub.example.org'
1625                       from='user@example.org'>
1626          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1627            <affiliations/>
1628          </pubsub>
1629        </iq>
1630        """
1631
1632        def affiliations(request):
1633            affiliation = ('test', 'owner')
1634            return defer.succeed([affiliation])
1635
1636        def cb(element):
1637            self.assertEqual('pubsub', element.name)
1638            self.assertEqual(NS_PUBSUB, element.uri)
1639            self.assertEqual(NS_PUBSUB, element.affiliations.uri)
1640            children = list(element.affiliations.elements())
1641            self.assertEqual(1, len(children))
1642            affiliation = children[0]
1643            self.assertEqual('affiliation', affiliation.name)
1644            self.assertEqual(NS_PUBSUB, affiliation.uri)
1645            self.assertEqual('test', affiliation['node'])
1646            self.assertEqual('owner', affiliation['affiliation'])
1647
1648        self.resource.affiliations = affiliations
1649        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1650        d = self.handleRequest(xml)
1651        d.addCallback(cb)
1652        return d
1653
1654
1655    def test_on_create(self):
1656        """
1657        Replies to create node requests don't return the created node.
1658        """
1659
1660        xml = """
1661        <iq type='set' to='pubsub.example.org'
1662                       from='user@example.org'>
1663          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1664            <create node='mynode'/>
1665          </pubsub>
1666        </iq>
1667        """
1668
1669        def create(request):
1670            return defer.succeed(request.nodeIdentifier)
1671
1672        def cb(element):
1673            self.assertIdentical(None, element)
1674
1675        self.resource.create = create
1676        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1677        d = self.handleRequest(xml)
1678        d.addCallback(cb)
1679        return d
1680
1681
1682    def test_on_createChanged(self):
1683        """
1684        Replies to create node requests return the created node if changed.
1685        """
1686
1687        xml = """
1688        <iq type='set' to='pubsub.example.org'
1689                       from='user@example.org'>
1690          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1691            <create node='mynode'/>
1692          </pubsub>
1693        </iq>
1694        """
1695
1696        def create(request):
1697            return defer.succeed(u'myrenamednode')
1698
1699        def cb(element):
1700            self.assertEqual('pubsub', element.name)
1701            self.assertEqual(NS_PUBSUB, element.uri)
1702            self.assertEqual(NS_PUBSUB, element.create.uri)
1703            self.assertEqual(u'myrenamednode',
1704                             element.create.getAttribute('node'))
1705
1706        self.resource.create = create
1707        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1708        d = self.handleRequest(xml)
1709        d.addCallback(cb)
1710        return d
1711
1712
1713    def test_on_createInstant(self):
1714        """
1715        Replies to create instant node requests return the created node.
1716        """
1717
1718        xml = """
1719        <iq type='set' to='pubsub.example.org'
1720                       from='user@example.org'>
1721          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1722            <create/>
1723          </pubsub>
1724        </iq>
1725        """
1726
1727        def create(request):
1728            return defer.succeed(u'random')
1729
1730        def cb(element):
1731            self.assertEqual('pubsub', element.name)
1732            self.assertEqual(NS_PUBSUB, element.uri)
1733            self.assertEqual(NS_PUBSUB, element.create.uri)
1734            self.assertEqual(u'random', element.create.getAttribute('node'))
1735
1736        self.resource.create = create
1737        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1738        d = self.handleRequest(xml)
1739        d.addCallback(cb)
1740        return d
1741
1742
1743    def test_on_default(self):
1744        """
1745        A default request should result in
1746        L{PubSubService.getDefaultConfiguration} being called.
1747        """
1748
1749        xml = """
1750        <iq type='get' to='pubsub.example.org'
1751                       from='user@example.org'>
1752          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1753            <default/>
1754          </pubsub>
1755        </iq>
1756        """
1757
1758        def getConfigurationOptions():
1759            return {
1760                "pubsub#persist_items":
1761                    {"type": "boolean",
1762                     "label": "Persist items to storage"},
1763                "pubsub#deliver_payloads":
1764                    {"type": "boolean",
1765                     "label": "Deliver payloads with event notifications"}
1766                }
1767
1768        def default(request):
1769            return defer.succeed({})
1770
1771        def cb(element):
1772            self.assertEqual('pubsub', element.name)
1773            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
1774            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
1775            form = data_form.Form.fromElement(element.default.x)
1776            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
1777
1778        self.resource.getConfigurationOptions = getConfigurationOptions
1779        self.resource.default = default
1780        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1781        d = self.handleRequest(xml)
1782        d.addCallback(cb)
1783        return d
1784
1785
1786    def test_on_defaultCollection(self):
1787        """
1788        Responses to default requests should depend on passed node type.
1789        """
1790
1791        xml = """
1792        <iq type='get' to='pubsub.example.org'
1793                       from='user@example.org'>
1794          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1795            <default>
1796              <x xmlns='jabber:x:data' type='submit'>
1797                <field var='FORM_TYPE' type='hidden'>
1798                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1799                </field>
1800                <field var='pubsub#node_type'>
1801                  <value>collection</value>
1802                </field>
1803              </x>
1804            </default>
1805
1806          </pubsub>
1807        </iq>
1808        """
1809
1810        def getConfigurationOptions():
1811            return {
1812                "pubsub#deliver_payloads":
1813                    {"type": "boolean",
1814                     "label": "Deliver payloads with event notifications"}
1815                }
1816
1817        def default(request):
1818            return defer.succeed({})
1819
1820        self.resource.getConfigurationOptions = getConfigurationOptions
1821        self.resource.default = default
1822        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1823        return self.handleRequest(xml)
1824
1825
1826    def test_on_defaultUnknownNodeType(self):
1827        """
1828        A default request should result in
1829        L{PubSubResource.default} being called.
1830        """
1831
1832        xml = """
1833        <iq type='get' to='pubsub.example.org'
1834                       from='user@example.org'>
1835          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1836            <default>
1837              <x xmlns='jabber:x:data' type='submit'>
1838                <field var='FORM_TYPE' type='hidden'>
1839                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1840                </field>
1841                <field var='pubsub#node_type'>
1842                  <value>unknown</value>
1843                </field>
1844              </x>
1845            </default>
1846
1847          </pubsub>
1848        </iq>
1849        """
1850
1851        def default(request):
1852            self.fail("Unexpected call to getConfiguration")
1853
1854        def cb(result):
1855            self.assertEquals('not-acceptable', result.condition)
1856
1857        self.resource.default = default
1858        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1859        d = self.handleRequest(xml)
1860        self.assertFailure(d, error.StanzaError)
1861        d.addCallback(cb)
1862        return d
1863
1864
1865    def test_on_configureGet(self):
1866        """
1867        On a node configuration get
1868        requestL{PubSubResource.configureGet} is called and results in a
1869        data form with the configuration.
1870        """
1871
1872        xml = """
1873        <iq type='get' to='pubsub.example.org'
1874                       from='user@example.org'>
1875          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1876            <configure node='test'/>
1877          </pubsub>
1878        </iq>
1879        """
1880
1881        def getConfigurationOptions():
1882            return {
1883                "pubsub#persist_items":
1884                    {"type": "boolean",
1885                     "label": "Persist items to storage"},
1886                "pubsub#deliver_payloads":
1887                    {"type": "boolean",
1888                     "label": "Deliver payloads with event notifications"},
1889                "pubsub#owner":
1890                    {"type": "jid-single",
1891                     "label": "Owner of the node"}
1892                }
1893
1894        def configureGet(request):
1895            return defer.succeed({'pubsub#deliver_payloads': '0',
1896                                  'pubsub#persist_items': '1',
1897                                  'pubsub#owner': JID('user@example.org'),
1898                                  'x-myfield': ['a', 'b']})
1899
1900        def cb(element):
1901            self.assertEqual('pubsub', element.name)
1902            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
1903            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
1904            form = data_form.Form.fromElement(element.configure.x)
1905            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
1906            fields = form.fields
1907
1908            self.assertIn('pubsub#deliver_payloads', fields)
1909            field = fields['pubsub#deliver_payloads']
1910            self.assertEqual('boolean', field.fieldType)
1911            field.typeCheck()
1912            self.assertEqual(False, field.value)
1913
1914            self.assertIn('pubsub#persist_items', fields)
1915            field = fields['pubsub#persist_items']
1916            self.assertEqual('boolean', field.fieldType)
1917            field.typeCheck()
1918            self.assertEqual(True, field.value)
1919
1920            self.assertIn('pubsub#owner', fields)
1921            field = fields['pubsub#owner']
1922            self.assertEqual('jid-single', field.fieldType)
1923            field.typeCheck()
1924            self.assertEqual(JID('user@example.org'), field.value)
1925
1926            self.assertNotIn('x-myfield', fields)
1927
1928        self.resource.getConfigurationOptions = getConfigurationOptions
1929        self.resource.configureGet = configureGet
1930        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1931        d = self.handleRequest(xml)
1932        d.addCallback(cb)
1933        return d
1934
1935
1936    def test_on_configureSet(self):
1937        """
1938        On a node configuration set request the Data Form is parsed and
1939        L{PubSubResource.configureSet} is called with the passed options.
1940        """
1941
1942        xml = """
1943        <iq type='set' to='pubsub.example.org'
1944                       from='user@example.org'>
1945          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1946            <configure node='test'>
1947              <x xmlns='jabber:x:data' type='submit'>
1948                <field var='FORM_TYPE' type='hidden'>
1949                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1950                </field>
1951                <field var='pubsub#deliver_payloads'><value>0</value></field>
1952                <field var='pubsub#persist_items'><value>1</value></field>
1953              </x>
1954            </configure>
1955          </pubsub>
1956        </iq>
1957        """
1958
1959        def getConfigurationOptions():
1960            return {
1961                "pubsub#persist_items":
1962                    {"type": "boolean",
1963                     "label": "Persist items to storage"},
1964                "pubsub#deliver_payloads":
1965                    {"type": "boolean",
1966                     "label": "Deliver payloads with event notifications"}
1967                }
1968
1969        def configureSet(request):
1970            self.assertEqual({'pubsub#deliver_payloads': False,
1971                              'pubsub#persist_items': True}, request.options)
1972            return defer.succeed(None)
1973
1974        self.resource.getConfigurationOptions = getConfigurationOptions
1975        self.resource.configureSet = configureSet
1976        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1977        return self.handleRequest(xml)
1978
1979
1980    def test_on_configureSetCancel(self):
1981        """
1982        The node configuration is cancelled,
1983        L{PubSubResource.configureSet} not called.
1984        """
1985
1986        xml = """
1987        <iq type='set' to='pubsub.example.org'
1988                       from='user@example.org'>
1989          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1990            <configure node='test'>
1991              <x xmlns='jabber:x:data' type='cancel'>
1992                <field var='FORM_TYPE' type='hidden'>
1993                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1994                </field>
1995              </x>
1996            </configure>
1997          </pubsub>
1998        </iq>
1999        """
2000
2001        def configureSet(request):
2002            self.fail("Unexpected call to setConfiguration")
2003
2004        self.resource.configureSet = configureSet
2005        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2006        return self.handleRequest(xml)
2007
2008
2009    def test_on_configureSetIgnoreUnknown(self):
2010        """
2011        On a node configuration set request unknown fields should be ignored.
2012        """
2013
2014        xml = """
2015        <iq type='set' to='pubsub.example.org'
2016                       from='user@example.org'>
2017          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2018            <configure node='test'>
2019              <x xmlns='jabber:x:data' type='submit'>
2020                <field var='FORM_TYPE' type='hidden'>
2021                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2022                </field>
2023                <field var='pubsub#deliver_payloads'><value>0</value></field>
2024                <field var='x-myfield'><value>1</value></field>
2025              </x>
2026            </configure>
2027          </pubsub>
2028        </iq>
2029        """
2030
2031        def getConfigurationOptions():
2032            return {
2033                "pubsub#persist_items":
2034                    {"type": "boolean",
2035                     "label": "Persist items to storage"},
2036                "pubsub#deliver_payloads":
2037                    {"type": "boolean",
2038                     "label": "Deliver payloads with event notifications"}
2039                }
2040
2041        def configureSet(request):
2042            self.assertEquals(['pubsub#deliver_payloads'],
2043                              request.options.keys())
2044
2045        self.resource.getConfigurationOptions = getConfigurationOptions
2046        self.resource.configureSet = configureSet
2047        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2048        return self.handleRequest(xml)
2049
2050
2051    def test_on_configureSetBadFormType(self):
2052        """
2053        On a node configuration set request unknown fields should be ignored.
2054        """
2055
2056        xml = """
2057        <iq type='set' to='pubsub.example.org'
2058                       from='user@example.org'>
2059          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2060            <configure node='test'>
2061              <x xmlns='jabber:x:data' type='result'>
2062                <field var='FORM_TYPE' type='hidden'>
2063                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2064                </field>
2065                <field var='pubsub#deliver_payloads'><value>0</value></field>
2066                <field var='x-myfield'><value>1</value></field>
2067              </x>
2068            </configure>
2069          </pubsub>
2070        </iq>
2071        """
2072
2073        def cb(result):
2074            self.assertEquals('bad-request', result.condition)
2075
2076        d = self.handleRequest(xml)
2077        self.assertFailure(d, error.StanzaError)
2078        d.addCallback(cb)
2079        return d
2080
2081
2082    def test_on_items(self):
2083        """
2084        On a items request, return all items for the given node.
2085        """
2086        xml = """
2087        <iq type='get' to='pubsub.example.org'
2088                       from='user@example.org'>
2089          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2090            <items node='test'/>
2091          </pubsub>
2092        </iq>
2093        """
2094
2095        def items(request):
2096            return defer.succeed([pubsub.Item('current')])
2097
2098        def cb(element):
2099            self.assertEqual(NS_PUBSUB, element.uri)
2100            self.assertEqual(NS_PUBSUB, element.items.uri)
2101            self.assertEqual(1, len(element.items.children))
2102            item = element.items.children[-1]
2103            self.assertTrue(domish.IElement.providedBy(item))
2104            self.assertEqual('item', item.name)
2105            self.assertEqual(NS_PUBSUB, item.uri)
2106            self.assertEqual('current', item['id'])
2107
2108        self.resource.items = items
2109        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2110        d = self.handleRequest(xml)
2111        d.addCallback(cb)
2112        return d
2113
2114
2115    def test_on_retract(self):
2116        """
2117        A retract request should result in L{PubSubResource.retract}
2118        being called.
2119        """
2120
2121        xml = """
2122        <iq type='set' to='pubsub.example.org'
2123                       from='user@example.org'>
2124          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2125            <retract node='test'>
2126              <item id='item1'/>
2127              <item id='item2'/>
2128            </retract>
2129          </pubsub>
2130        </iq>
2131        """
2132
2133        def retract(request):
2134            return defer.succeed(None)
2135
2136        self.resource.retract = retract
2137        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2138        return self.handleRequest(xml)
2139
2140
2141    def test_on_purge(self):
2142        """
2143        A purge request should result in L{PubSubResource.purge} being
2144        called.
2145        """
2146
2147        xml = """
2148        <iq type='set' to='pubsub.example.org'
2149                       from='user@example.org'>
2150          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2151            <purge node='test'/>
2152          </pubsub>
2153        </iq>
2154        """
2155
2156        def purge(request):
2157            return defer.succeed(None)
2158
2159        self.resource.purge = purge
2160        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2161        return self.handleRequest(xml)
2162
2163
2164    def test_on_delete(self):
2165        """
2166        A delete request should result in L{PubSubResource.delete} being
2167        called.
2168        """
2169
2170        xml = """
2171        <iq type='set' to='pubsub.example.org'
2172                       from='user@example.org'>
2173          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2174            <delete node='test'/>
2175          </pubsub>
2176        </iq>
2177        """
2178
2179        def delete(request):
2180            return defer.succeed(None)
2181
2182        self.resource.delete = delete
2183        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2184        return self.handleRequest(xml)
2185
2186
2187    def test_notifyDelete(self):
2188        """
2189        Subscribers should be sent a delete notification.
2190        """
2191        subscriptions = [JID('user@example.org')]
2192        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
2193                                  subscriptions)
2194        message = self.stub.output[-1]
2195
2196        self.assertEquals('message', message.name)
2197        self.assertIdentical(None, message.uri)
2198        self.assertEquals('user@example.org', message['to'])
2199        self.assertEquals('pubsub.example.org', message['from'])
2200        self.assertTrue(message.event)
2201        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
2202        self.assertTrue(message.event.delete)
2203        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
2204        self.assertTrue(message.event.delete.hasAttribute('node'))
2205        self.assertEqual('test', message.event.delete['node'])
2206
2207
2208    def test_notifyDeleteRedirect(self):
2209        """
2210        Subscribers should be sent a delete notification with redirect.
2211        """
2212        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
2213        subscriptions = [JID('user@example.org')]
2214        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
2215                                  subscriptions, redirectURI)
2216        message = self.stub.output[-1]
2217
2218        self.assertEquals('message', message.name)
2219        self.assertIdentical(None, message.uri)
2220        self.assertEquals('user@example.org', message['to'])
2221        self.assertEquals('pubsub.example.org', message['from'])
2222        self.assertTrue(message.event)
2223        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
2224        self.assertTrue(message.event.delete)
2225        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
2226        self.assertTrue(message.event.delete.hasAttribute('node'))
2227        self.assertEqual('test', message.event.delete['node'])
2228        self.assertTrue(message.event.delete.redirect)
2229        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
2230        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
2231        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
2232
2233
2234    def test_on_subscriptionsGet(self):
2235        """
2236        Getting subscription options is not supported.
2237        """
2238
2239        xml = """
2240        <iq type='get' to='pubsub.example.org'
2241                       from='user@example.org'>
2242          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2243            <subscriptions/>
2244          </pubsub>
2245        </iq>
2246        """
2247
2248        def cb(result):
2249            self.assertEquals('feature-not-implemented', result.condition)
2250            self.assertEquals('unsupported', result.appCondition.name)
2251            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2252            self.assertEquals('manage-subscriptions',
2253                              result.appCondition['feature'])
2254
2255        d = self.handleRequest(xml)
2256        self.assertFailure(d, error.StanzaError)
2257        d.addCallback(cb)
2258        return d
2259
2260
2261    def test_on_subscriptionsSet(self):
2262        """
2263        Setting subscription options is not supported.
2264        """
2265
2266        xml = """
2267        <iq type='set' to='pubsub.example.org'
2268                       from='user@example.org'>
2269          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2270            <subscriptions/>
2271          </pubsub>
2272        </iq>
2273        """
2274
2275        def cb(result):
2276            self.assertEquals('feature-not-implemented', result.condition)
2277            self.assertEquals('unsupported', result.appCondition.name)
2278            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2279            self.assertEquals('manage-subscriptions',
2280                              result.appCondition['feature'])
2281
2282        d = self.handleRequest(xml)
2283        self.assertFailure(d, error.StanzaError)
2284        d.addCallback(cb)
2285        return d
2286
2287
2288    def test_on_affiliationsGet(self):
2289        """
2290        Getting subscription options is not supported.
2291        """
2292
2293        xml = """
2294        <iq type='get' to='pubsub.example.org'
2295                       from='user@example.org'>
2296          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2297            <affiliations/>
2298          </pubsub>
2299        </iq>
2300        """
2301
2302        def cb(result):
2303            self.assertEquals('feature-not-implemented', result.condition)
2304            self.assertEquals('unsupported', result.appCondition.name)
2305            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2306            self.assertEquals('modify-affiliations',
2307                              result.appCondition['feature'])
2308
2309        d = self.handleRequest(xml)
2310        self.assertFailure(d, error.StanzaError)
2311        d.addCallback(cb)
2312        return d
2313
2314
2315    def test_on_affiliationsSet(self):
2316        """
2317        Setting subscription options is not supported.
2318        """
2319
2320        xml = """
2321        <iq type='set' to='pubsub.example.org'
2322                       from='user@example.org'>
2323          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2324            <affiliations/>
2325          </pubsub>
2326        </iq>
2327        """
2328
2329        def cb(result):
2330            self.assertEquals('feature-not-implemented', result.condition)
2331            self.assertEquals('unsupported', result.appCondition.name)
2332            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2333            self.assertEquals('modify-affiliations',
2334                              result.appCondition['feature'])
2335
2336        d = self.handleRequest(xml)
2337        self.assertFailure(d, error.StanzaError)
2338        d.addCallback(cb)
2339        return d
2340
2341
2342
2343class PubSubServiceWithoutResourceTest(unittest.TestCase, TestableRequestHandlerMixin):
2344
2345    def setUp(self):
2346        self.stub = XmlStreamStub()
2347        self.service = pubsub.PubSubService()
2348        self.service.send = self.stub.xmlstream.send
2349
2350
2351    def test_publish(self):
2352        """
2353        Non-overridden L{PubSubService.publish} yields unsupported error.
2354        """
2355
2356        xml = """
2357        <iq type='set' to='pubsub.example.org'
2358                       from='user@example.org'>
2359          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2360            <publish node='mynode'/>
2361          </pubsub>
2362        </iq>
2363        """
2364
2365        def cb(result):
2366            self.assertEquals('feature-not-implemented', result.condition)
2367            self.assertEquals('unsupported', result.appCondition.name)
2368            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2369            self.assertEquals('publish', result.appCondition['feature'])
2370
2371        d = self.handleRequest(xml)
2372        self.assertFailure(d, error.StanzaError)
2373        d.addCallback(cb)
2374        return d
2375
2376
2377    def test_subscribe(self):
2378        """
2379        Non-overridden L{PubSubService.subscribe} yields unsupported error.
2380        """
2381
2382        xml = """
2383        <iq type='set' to='pubsub.example.org'
2384                       from='user@example.org'>
2385          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2386            <subscribe node='test' jid='user@example.org/Home'/>
2387          </pubsub>
2388        </iq>
2389        """
2390
2391        def cb(result):
2392            self.assertEquals('feature-not-implemented', result.condition)
2393            self.assertEquals('unsupported', result.appCondition.name)
2394            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2395            self.assertEquals('subscribe', result.appCondition['feature'])
2396
2397        d = self.handleRequest(xml)
2398        self.assertFailure(d, error.StanzaError)
2399        d.addCallback(cb)
2400        return d
2401
2402
2403    def test_unsubscribe(self):
2404        """
2405        Non-overridden L{PubSubService.unsubscribe} yields unsupported error.
2406        """
2407
2408        xml = """
2409        <iq type='set' to='pubsub.example.org'
2410                       from='user@example.org'>
2411          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2412            <unsubscribe node='test' jid='user@example.org/Home'/>
2413          </pubsub>
2414        </iq>
2415        """
2416
2417        def cb(result):
2418            self.assertEquals('feature-not-implemented', result.condition)
2419            self.assertEquals('unsupported', result.appCondition.name)
2420            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2421            self.assertEquals('subscribe', result.appCondition['feature'])
2422
2423        d = self.handleRequest(xml)
2424        self.assertFailure(d, error.StanzaError)
2425        d.addCallback(cb)
2426        return d
2427
2428
2429    def test_subscriptions(self):
2430        """
2431        Non-overridden L{PubSubService.subscriptions} yields unsupported error.
2432        """
2433
2434        xml = """
2435        <iq type='get' to='pubsub.example.org'
2436                       from='user@example.org'>
2437          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2438            <subscriptions/>
2439          </pubsub>
2440        </iq>
2441        """
2442
2443        def cb(result):
2444            self.assertEquals('feature-not-implemented', result.condition)
2445            self.assertEquals('unsupported', result.appCondition.name)
2446            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2447            self.assertEquals('retrieve-subscriptions',
2448                              result.appCondition['feature'])
2449
2450        d = self.handleRequest(xml)
2451        self.assertFailure(d, error.StanzaError)
2452        d.addCallback(cb)
2453        return d
2454
2455
2456    def test_affiliations(self):
2457        """
2458        Non-overridden L{PubSubService.affiliations} yields unsupported error.
2459        """
2460
2461        xml = """
2462        <iq type='get' to='pubsub.example.org'
2463                       from='user@example.org'>
2464          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2465            <affiliations/>
2466          </pubsub>
2467        </iq>
2468        """
2469
2470        def cb(result):
2471            self.assertEquals('feature-not-implemented', result.condition)
2472            self.assertEquals('unsupported', result.appCondition.name)
2473            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2474            self.assertEquals('retrieve-affiliations',
2475                              result.appCondition['feature'])
2476
2477        d = self.handleRequest(xml)
2478        self.assertFailure(d, error.StanzaError)
2479        d.addCallback(cb)
2480        return d
2481
2482
2483    def test_create(self):
2484        """
2485        Non-overridden L{PubSubService.create} yields unsupported error.
2486        """
2487
2488        xml = """
2489        <iq type='set' to='pubsub.example.org'
2490                       from='user@example.org'>
2491          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2492            <create node='mynode'/>
2493          </pubsub>
2494        </iq>
2495        """
2496
2497        def cb(result):
2498            self.assertEquals('feature-not-implemented', result.condition)
2499            self.assertEquals('unsupported', result.appCondition.name)
2500            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2501            self.assertEquals('create-nodes', result.appCondition['feature'])
2502
2503        d = self.handleRequest(xml)
2504        self.assertFailure(d, error.StanzaError)
2505        d.addCallback(cb)
2506        return d
2507
2508
2509    def test_getDefaultConfiguration(self):
2510        """
2511        Non-overridden L{PubSubService.getDefaultConfiguration} yields
2512        unsupported error.
2513        """
2514
2515        xml = """
2516        <iq type='get' to='pubsub.example.org'
2517                       from='user@example.org'>
2518          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2519            <default/>
2520          </pubsub>
2521        </iq>
2522        """
2523
2524        def cb(result):
2525            self.assertEquals('feature-not-implemented', result.condition)
2526            self.assertEquals('unsupported', result.appCondition.name)
2527            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2528            self.assertEquals('retrieve-default', result.appCondition['feature'])
2529
2530        d = self.handleRequest(xml)
2531        self.assertFailure(d, error.StanzaError)
2532        d.addCallback(cb)
2533        return d
2534
2535
2536    def test_getConfiguration(self):
2537        """
2538        Non-overridden L{PubSubService.getConfiguration} yields unsupported
2539        error.
2540        """
2541
2542        xml = """
2543        <iq type='get' to='pubsub.example.org'
2544                       from='user@example.org'>
2545          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2546            <configure/>
2547          </pubsub>
2548        </iq>
2549        """
2550
2551        def cb(result):
2552            self.assertEquals('feature-not-implemented', result.condition)
2553            self.assertEquals('unsupported', result.appCondition.name)
2554            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2555            self.assertEquals('config-node', result.appCondition['feature'])
2556
2557        d = self.handleRequest(xml)
2558        self.assertFailure(d, error.StanzaError)
2559        d.addCallback(cb)
2560        return d
2561
2562
2563    def test_setConfiguration(self):
2564        """
2565        Non-overridden L{PubSubService.setConfiguration} yields unsupported
2566        error.
2567        """
2568
2569        xml = """
2570        <iq type='set' to='pubsub.example.org'
2571                       from='user@example.org'>
2572          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2573            <configure node='test'>
2574              <x xmlns='jabber:x:data' type='submit'>
2575                <field var='FORM_TYPE' type='hidden'>
2576                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2577                </field>
2578                <field var='pubsub#deliver_payloads'><value>0</value></field>
2579                <field var='pubsub#persist_items'><value>1</value></field>
2580              </x>
2581            </configure>
2582          </pubsub>
2583        </iq>
2584        """
2585
2586        def cb(result):
2587            self.assertEquals('feature-not-implemented', result.condition)
2588            self.assertEquals('unsupported', result.appCondition.name)
2589            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2590            self.assertEquals('config-node', result.appCondition['feature'])
2591
2592        d = self.handleRequest(xml)
2593        self.assertFailure(d, error.StanzaError)
2594        d.addCallback(cb)
2595        return d
2596
2597
2598    def test_items(self):
2599        """
2600        Non-overridden L{PubSubService.items} yields unsupported error.
2601        """
2602        xml = """
2603        <iq type='get' to='pubsub.example.org'
2604                       from='user@example.org'>
2605          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2606            <items node='test'/>
2607          </pubsub>
2608        </iq>
2609        """
2610
2611        def cb(result):
2612            self.assertEquals('feature-not-implemented', result.condition)
2613            self.assertEquals('unsupported', result.appCondition.name)
2614            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2615            self.assertEquals('retrieve-items', result.appCondition['feature'])
2616
2617        d = self.handleRequest(xml)
2618        self.assertFailure(d, error.StanzaError)
2619        d.addCallback(cb)
2620        return d
2621
2622
2623    def test_retract(self):
2624        """
2625        Non-overridden L{PubSubService.retract} yields unsupported error.
2626        """
2627        xml = """
2628        <iq type='set' to='pubsub.example.org'
2629                       from='user@example.org'>
2630          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2631            <retract node='test'>
2632              <item id='item1'/>
2633              <item id='item2'/>
2634            </retract>
2635          </pubsub>
2636        </iq>
2637        """
2638
2639        def cb(result):
2640            self.assertEquals('feature-not-implemented', result.condition)
2641            self.assertEquals('unsupported', result.appCondition.name)
2642            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2643            self.assertEquals('retract-items', result.appCondition['feature'])
2644
2645        d = self.handleRequest(xml)
2646        self.assertFailure(d, error.StanzaError)
2647        d.addCallback(cb)
2648        return d
2649
2650
2651    def test_purge(self):
2652        """
2653        Non-overridden L{PubSubService.purge} yields unsupported error.
2654        """
2655        xml = """
2656        <iq type='set' to='pubsub.example.org'
2657                       from='user@example.org'>
2658          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2659            <purge node='test'/>
2660          </pubsub>
2661        </iq>
2662        """
2663
2664        def cb(result):
2665            self.assertEquals('feature-not-implemented', result.condition)
2666            self.assertEquals('unsupported', result.appCondition.name)
2667            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2668            self.assertEquals('purge-nodes', result.appCondition['feature'])
2669
2670        d = self.handleRequest(xml)
2671        self.assertFailure(d, error.StanzaError)
2672        d.addCallback(cb)
2673        return d
2674
2675
2676    def test_delete(self):
2677        """
2678        Non-overridden L{PubSubService.delete} yields unsupported error.
2679        """
2680        xml = """
2681        <iq type='set' to='pubsub.example.org'
2682                       from='user@example.org'>
2683          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2684            <delete node='test'/>
2685          </pubsub>
2686        </iq>
2687        """
2688
2689        def cb(result):
2690            self.assertEquals('feature-not-implemented', result.condition)
2691            self.assertEquals('unsupported', result.appCondition.name)
2692            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2693            self.assertEquals('delete-nodes', result.appCondition['feature'])
2694
2695        d = self.handleRequest(xml)
2696        self.assertFailure(d, error.StanzaError)
2697        d.addCallback(cb)
2698        return d
2699
2700
2701
2702class PubSubResourceTest(unittest.TestCase):
2703
2704    def setUp(self):
2705        self.resource = pubsub.PubSubResource()
2706
2707
2708    def test_interface(self):
2709        """
2710        Do instances of L{pubsub.PubSubResource} provide L{iwokkel.IPubSubResource}?
2711        """
2712        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2713
2714
2715    def test_getNodes(self):
2716        """
2717        Default getNodes returns an empty list.
2718        """
2719        def cb(nodes):
2720            self.assertEquals([], nodes)
2721
2722        d = self.resource.getNodes(JID('user@example.org/home'),
2723                                   JID('pubsub.example.org'),
2724                                   '')
2725        d.addCallback(cb)
2726        return d
2727
2728
2729    def test_publish(self):
2730        """
2731        Non-overridden L{PubSubResource.publish} yields unsupported
2732        error.
2733        """
2734
2735        def cb(result):
2736            self.assertEquals('feature-not-implemented', result.condition)
2737            self.assertEquals('unsupported', result.appCondition.name)
2738            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2739            self.assertEquals('publish', result.appCondition['feature'])
2740
2741        d = self.resource.publish(pubsub.PubSubRequest())
2742        self.assertFailure(d, error.StanzaError)
2743        d.addCallback(cb)
2744        return d
2745
2746
2747    def test_subscribe(self):
2748        """
2749        Non-overridden subscriptions yields unsupported error.
2750        """
2751
2752        def cb(result):
2753            self.assertEquals('feature-not-implemented', result.condition)
2754            self.assertEquals('unsupported', result.appCondition.name)
2755            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2756            self.assertEquals('subscribe', result.appCondition['feature'])
2757
2758        d = self.resource.subscribe(pubsub.PubSubRequest())
2759        self.assertFailure(d, error.StanzaError)
2760        d.addCallback(cb)
2761        return d
2762
2763
2764    def test_unsubscribe(self):
2765        """
2766        Non-overridden unsubscribe yields unsupported error.
2767        """
2768
2769        def cb(result):
2770            self.assertEquals('feature-not-implemented', result.condition)
2771            self.assertEquals('unsupported', result.appCondition.name)
2772            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2773            self.assertEquals('subscribe', result.appCondition['feature'])
2774
2775        d = self.resource.unsubscribe(pubsub.PubSubRequest())
2776        self.assertFailure(d, error.StanzaError)
2777        d.addCallback(cb)
2778        return d
2779
2780
2781    def test_subscriptions(self):
2782        """
2783        Non-overridden subscriptions yields unsupported error.
2784        """
2785
2786        def cb(result):
2787            self.assertEquals('feature-not-implemented', result.condition)
2788            self.assertEquals('unsupported', result.appCondition.name)
2789            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2790            self.assertEquals('retrieve-subscriptions',
2791                              result.appCondition['feature'])
2792
2793        d = self.resource.subscriptions(pubsub.PubSubRequest())
2794        self.assertFailure(d, error.StanzaError)
2795        d.addCallback(cb)
2796        return d
2797
2798
2799    def test_affiliations(self):
2800        """
2801        Non-overridden affiliations yields unsupported error.
2802        """
2803
2804        def cb(result):
2805            self.assertEquals('feature-not-implemented', result.condition)
2806            self.assertEquals('unsupported', result.appCondition.name)
2807            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2808            self.assertEquals('retrieve-affiliations',
2809                              result.appCondition['feature'])
2810
2811        d = self.resource.affiliations(pubsub.PubSubRequest())
2812        self.assertFailure(d, error.StanzaError)
2813        d.addCallback(cb)
2814        return d
2815
2816
2817    def test_create(self):
2818        """
2819        Non-overridden create yields unsupported error.
2820        """
2821
2822        def cb(result):
2823            self.assertEquals('feature-not-implemented', result.condition)
2824            self.assertEquals('unsupported', result.appCondition.name)
2825            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2826            self.assertEquals('create-nodes', result.appCondition['feature'])
2827
2828        d = self.resource.create(pubsub.PubSubRequest())
2829        self.assertFailure(d, error.StanzaError)
2830        d.addCallback(cb)
2831        return d
2832
2833
2834    def test_default(self):
2835        """
2836        Non-overridden default yields unsupported error.
2837        """
2838
2839        def cb(result):
2840            self.assertEquals('feature-not-implemented', result.condition)
2841            self.assertEquals('unsupported', result.appCondition.name)
2842            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2843            self.assertEquals('retrieve-default',
2844                              result.appCondition['feature'])
2845
2846        d = self.resource.default(pubsub.PubSubRequest())
2847        self.assertFailure(d, error.StanzaError)
2848        d.addCallback(cb)
2849        return d
2850
2851
2852    def test_configureGet(self):
2853        """
2854        Non-overridden configureGet yields unsupported
2855        error.
2856        """
2857
2858        def cb(result):
2859            self.assertEquals('feature-not-implemented', result.condition)
2860            self.assertEquals('unsupported', result.appCondition.name)
2861            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2862            self.assertEquals('config-node', result.appCondition['feature'])
2863
2864        d = self.resource.configureGet(pubsub.PubSubRequest())
2865        self.assertFailure(d, error.StanzaError)
2866        d.addCallback(cb)
2867        return d
2868
2869
2870    def test_configureSet(self):
2871        """
2872        Non-overridden configureSet yields unsupported error.
2873        """
2874
2875        def cb(result):
2876            self.assertEquals('feature-not-implemented', result.condition)
2877            self.assertEquals('unsupported', result.appCondition.name)
2878            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2879            self.assertEquals('config-node', result.appCondition['feature'])
2880
2881        d = self.resource.configureSet(pubsub.PubSubRequest())
2882        self.assertFailure(d, error.StanzaError)
2883        d.addCallback(cb)
2884        return d
2885
2886
2887    def test_items(self):
2888        """
2889        Non-overridden items yields unsupported error.
2890        """
2891
2892        def cb(result):
2893            self.assertEquals('feature-not-implemented', result.condition)
2894            self.assertEquals('unsupported', result.appCondition.name)
2895            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2896            self.assertEquals('retrieve-items', result.appCondition['feature'])
2897
2898        d = self.resource.items(pubsub.PubSubRequest())
2899        self.assertFailure(d, error.StanzaError)
2900        d.addCallback(cb)
2901        return d
2902
2903
2904    def test_retract(self):
2905        """
2906        Non-overridden retract yields unsupported error.
2907        """
2908
2909        def cb(result):
2910            self.assertEquals('feature-not-implemented', result.condition)
2911            self.assertEquals('unsupported', result.appCondition.name)
2912            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2913            self.assertEquals('retract-items', result.appCondition['feature'])
2914
2915        d = self.resource.retract(pubsub.PubSubRequest())
2916        self.assertFailure(d, error.StanzaError)
2917        d.addCallback(cb)
2918        return d
2919
2920
2921    def test_purge(self):
2922        """
2923        Non-overridden purge yields unsupported error.
2924        """
2925
2926        def cb(result):
2927            self.assertEquals('feature-not-implemented', result.condition)
2928            self.assertEquals('unsupported', result.appCondition.name)
2929            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2930            self.assertEquals('purge-nodes', result.appCondition['feature'])
2931
2932        d = self.resource.purge(pubsub.PubSubRequest())
2933        self.assertFailure(d, error.StanzaError)
2934        d.addCallback(cb)
2935        return d
2936
2937
2938    def test_delete(self):
2939        """
2940        Non-overridden delete yields unsupported error.
2941        """
2942
2943        def cb(result):
2944            self.assertEquals('feature-not-implemented', result.condition)
2945            self.assertEquals('unsupported', result.appCondition.name)
2946            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2947            self.assertEquals('delete-nodes', result.appCondition['feature'])
2948
2949        d = self.resource.delete(pubsub.PubSubRequest())
2950        self.assertFailure(d, error.StanzaError)
2951        d.addCallback(cb)
2952        return d
Note: See TracBrowser for help on using the repository browser.