source: wokkel/test/test_pubsub.py @ 81:1334124db2fd

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

Make PubSubRequest?.options be a form and use new form type checking

File size: 99.4 KB
Line 
1# Copyright (c) 2003-2010 Ralph Meijer
2# See LICENSE for details.
3
4"""
5Tests for L{wokkel.pubsub}
6"""
7
8from zope.interface import verify
9
10from twisted.trial import unittest
11from twisted.internet import defer
12from twisted.words.xish import domish
13from twisted.words.protocols.jabber import error
14from twisted.words.protocols.jabber.jid import JID
15from twisted.words.protocols.jabber.xmlstream import toResponse
16
17from wokkel import data_form, disco, iwokkel, pubsub, shim
18from wokkel.generic import parseXml
19from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
20
21NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
22NS_PUBSUB_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.getValues())
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('cancel', request.options.formType)
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#subscribe_options</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("Unexpected form type 'result'", err.text)
857        self.assertEqual(None, err.appCondition)
858
859
860    def test_fromElementOptionsSetNoForm(self):
861        """
862        On a options set request a form is required.
863        """
864
865        xml = """
866        <iq type='set' to='pubsub.example.org'
867                       from='user@example.org'>
868          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
869            <options node='test' jid='user@example.org/Home'/>
870          </pubsub>
871        </iq>
872        """
873        err = self.assertRaises(error.StanzaError,
874                                pubsub.PubSubRequest.fromElement,
875                                parseXml(xml))
876        self.assertEqual('bad-request', err.condition)
877        self.assertEqual(None, err.appCondition)
878
879
880    def test_fromElementSubscriptions(self):
881        """
882        Test parsing a request for all subscriptions.
883        """
884
885        xml = """
886        <iq type='get' to='pubsub.example.org'
887                       from='user@example.org'>
888          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
889            <subscriptions/>
890          </pubsub>
891        </iq>
892        """
893
894        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
895        self.assertEqual('subscriptions', request.verb)
896        self.assertEqual(JID('user@example.org'), request.sender)
897        self.assertEqual(JID('pubsub.example.org'), request.recipient)
898
899
900    def test_fromElementAffiliations(self):
901        """
902        Test parsing a request for all affiliations.
903        """
904
905        xml = """
906        <iq type='get' to='pubsub.example.org'
907                       from='user@example.org'>
908          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
909            <affiliations/>
910          </pubsub>
911        </iq>
912        """
913
914        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
915        self.assertEqual('affiliations', request.verb)
916        self.assertEqual(JID('user@example.org'), request.sender)
917        self.assertEqual(JID('pubsub.example.org'), request.recipient)
918
919
920    def test_fromElementCreate(self):
921        """
922        Test parsing a request to create a node.
923        """
924
925        xml = """
926        <iq type='set' to='pubsub.example.org'
927                       from='user@example.org'>
928          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
929            <create node='mynode'/>
930          </pubsub>
931        </iq>
932        """
933
934        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
935        self.assertEqual('create', request.verb)
936        self.assertEqual(JID('user@example.org'), request.sender)
937        self.assertEqual(JID('pubsub.example.org'), request.recipient)
938        self.assertEqual('mynode', request.nodeIdentifier)
939
940
941    def test_fromElementCreateInstant(self):
942        """
943        Test parsing a request to create an instant node.
944        """
945
946        xml = """
947        <iq type='set' to='pubsub.example.org'
948                       from='user@example.org'>
949          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
950            <create/>
951          </pubsub>
952        </iq>
953        """
954
955        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
956        self.assertIdentical(None, request.nodeIdentifier)
957
958
959    def test_fromElementDefault(self):
960        """
961        Test parsing a request for the default node configuration.
962        """
963
964        xml = """
965        <iq type='get' to='pubsub.example.org'
966                       from='user@example.org'>
967          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
968            <default/>
969          </pubsub>
970        </iq>
971        """
972
973        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
974        self.assertEqual('default', request.verb)
975        self.assertEqual(JID('user@example.org'), request.sender)
976        self.assertEqual(JID('pubsub.example.org'), request.recipient)
977        self.assertEqual('leaf', request.nodeType)
978
979
980    def test_fromElementDefaultCollection(self):
981        """
982        Parsing a request for the default configuration extracts the node type.
983        """
984
985        xml = """
986        <iq type='get' to='pubsub.example.org'
987                       from='user@example.org'>
988          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
989            <default>
990              <x xmlns='jabber:x:data' type='submit'>
991                <field var='FORM_TYPE' type='hidden'>
992                  <value>http://jabber.org/protocol/pubsub#node_config</value>
993                </field>
994                <field var='pubsub#node_type'>
995                  <value>collection</value>
996                </field>
997              </x>
998            </default>
999
1000          </pubsub>
1001        </iq>
1002        """
1003
1004        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1005        self.assertEqual('collection', request.nodeType)
1006
1007
1008    def test_fromElementConfigureGet(self):
1009        """
1010        Test parsing a node configuration get request.
1011        """
1012
1013        xml = """
1014        <iq type='get' to='pubsub.example.org'
1015                       from='user@example.org'>
1016          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1017            <configure node='test'/>
1018          </pubsub>
1019        </iq>
1020        """
1021
1022        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1023        self.assertEqual('configureGet', request.verb)
1024        self.assertEqual(JID('user@example.org'), request.sender)
1025        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1026        self.assertEqual('test', request.nodeIdentifier)
1027
1028
1029    def test_fromElementConfigureSet(self):
1030        """
1031        On a node configuration set request the Data Form is parsed.
1032        """
1033
1034        xml = """
1035        <iq type='set' to='pubsub.example.org'
1036                       from='user@example.org'>
1037          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1038            <configure node='test'>
1039              <x xmlns='jabber:x:data' type='submit'>
1040                <field var='FORM_TYPE' type='hidden'>
1041                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1042                </field>
1043                <field var='pubsub#deliver_payloads'><value>0</value></field>
1044                <field var='pubsub#persist_items'><value>1</value></field>
1045              </x>
1046            </configure>
1047          </pubsub>
1048        </iq>
1049        """
1050
1051        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1052        self.assertEqual('configureSet', request.verb)
1053        self.assertEqual(JID('user@example.org'), request.sender)
1054        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1055        self.assertEqual('test', request.nodeIdentifier)
1056        self.assertEqual({'pubsub#deliver_payloads': '0',
1057                          'pubsub#persist_items': '1'},
1058                         request.options.getValues())
1059
1060
1061    def test_fromElementConfigureSetCancel(self):
1062        """
1063        The node configuration is cancelled, so no options.
1064        """
1065
1066        xml = """
1067        <iq type='set' to='pubsub.example.org'
1068                       from='user@example.org'>
1069          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1070            <configure node='test'>
1071              <x xmlns='jabber:x:data' type='cancel'/>
1072            </configure>
1073          </pubsub>
1074        </iq>
1075        """
1076
1077        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1078        self.assertEqual('cancel', request.options.formType)
1079
1080
1081    def test_fromElementConfigureSetBadFormType(self):
1082        """
1083        On a node configuration set request unknown fields should be ignored.
1084        """
1085
1086        xml = """
1087        <iq type='set' to='pubsub.example.org'
1088                       from='user@example.org'>
1089          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1090            <configure node='test'>
1091              <x xmlns='jabber:x:data' type='result'>
1092                <field var='FORM_TYPE' type='hidden'>
1093                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1094                </field>
1095                <field var='pubsub#deliver_payloads'><value>0</value></field>
1096                <field var='x-myfield'><value>1</value></field>
1097              </x>
1098            </configure>
1099          </pubsub>
1100        </iq>
1101        """
1102
1103        err = self.assertRaises(error.StanzaError,
1104                                pubsub.PubSubRequest.fromElement,
1105                                parseXml(xml))
1106        self.assertEqual('bad-request', err.condition)
1107        self.assertEqual("Unexpected form type 'result'", err.text)
1108        self.assertEqual(None, err.appCondition)
1109
1110
1111    def test_fromElementConfigureSetNoForm(self):
1112        """
1113        On a node configuration set request a form is required.
1114        """
1115
1116        xml = """
1117        <iq type='set' to='pubsub.example.org'
1118                       from='user@example.org'>
1119          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1120            <configure node='test'/>
1121          </pubsub>
1122        </iq>
1123        """
1124        err = self.assertRaises(error.StanzaError,
1125                                pubsub.PubSubRequest.fromElement,
1126                                parseXml(xml))
1127        self.assertEqual('bad-request', err.condition)
1128        self.assertEqual(None, err.appCondition)
1129
1130
1131    def test_fromElementItems(self):
1132        """
1133        Test parsing an items request.
1134        """
1135        xml = """
1136        <iq type='get' to='pubsub.example.org'
1137                       from='user@example.org'>
1138          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1139            <items node='test'/>
1140          </pubsub>
1141        </iq>
1142        """
1143
1144        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1145        self.assertEqual('items', request.verb)
1146        self.assertEqual(JID('user@example.org'), request.sender)
1147        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1148        self.assertEqual('test', request.nodeIdentifier)
1149        self.assertIdentical(None, request.maxItems)
1150        self.assertEqual([], request.itemIdentifiers)
1151
1152
1153    def test_fromElementRetract(self):
1154        """
1155        Test parsing a retract request.
1156        """
1157
1158        xml = """
1159        <iq type='set' to='pubsub.example.org'
1160                       from='user@example.org'>
1161          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1162            <retract node='test'>
1163              <item id='item1'/>
1164              <item id='item2'/>
1165            </retract>
1166          </pubsub>
1167        </iq>
1168        """
1169
1170        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1171        self.assertEqual('retract', request.verb)
1172        self.assertEqual(JID('user@example.org'), request.sender)
1173        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1174        self.assertEqual('test', request.nodeIdentifier)
1175        self.assertEqual(['item1', 'item2'], request.itemIdentifiers)
1176
1177
1178    def test_fromElementPurge(self):
1179        """
1180        Test parsing a purge request.
1181        """
1182
1183        xml = """
1184        <iq type='set' to='pubsub.example.org'
1185                       from='user@example.org'>
1186          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1187            <purge node='test'/>
1188          </pubsub>
1189        </iq>
1190        """
1191
1192        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1193        self.assertEqual('purge', request.verb)
1194        self.assertEqual(JID('user@example.org'), request.sender)
1195        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1196        self.assertEqual('test', request.nodeIdentifier)
1197
1198
1199    def test_fromElementDelete(self):
1200        """
1201        Test parsing a delete request.
1202        """
1203
1204        xml = """
1205        <iq type='set' to='pubsub.example.org'
1206                       from='user@example.org'>
1207          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1208            <delete node='test'/>
1209          </pubsub>
1210        </iq>
1211        """
1212
1213        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
1214        self.assertEqual('delete', request.verb)
1215        self.assertEqual(JID('user@example.org'), request.sender)
1216        self.assertEqual(JID('pubsub.example.org'), request.recipient)
1217        self.assertEqual('test', request.nodeIdentifier)
1218
1219
1220
1221class PubSubServiceTest(unittest.TestCase, TestableRequestHandlerMixin):
1222    """
1223    Tests for L{pubsub.PubSubService}.
1224    """
1225
1226    def setUp(self):
1227        self.stub = XmlStreamStub()
1228        self.resource = pubsub.PubSubResource()
1229        self.service = pubsub.PubSubService(self.resource)
1230        self.service.send = self.stub.xmlstream.send
1231
1232    def test_interface(self):
1233        """
1234        Do instances of L{pubsub.PubSubService} provide L{iwokkel.IPubSubService}?
1235        """
1236        verify.verifyObject(iwokkel.IPubSubService, self.service)
1237
1238
1239    def test_connectionMade(self):
1240        """
1241        Verify setup of observers in L{pubsub.connectionMade}.
1242        """
1243        requests = []
1244
1245        def handleRequest(iq):
1246            requests.append(iq)
1247
1248        self.service.xmlstream = self.stub.xmlstream
1249        self.service.handleRequest = handleRequest
1250        self.service.connectionMade()
1251
1252        for namespace in (NS_PUBSUB, NS_PUBSUB_OWNER):
1253            for stanzaType in ('get', 'set'):
1254                iq = domish.Element((None, 'iq'))
1255                iq['type'] = stanzaType
1256                iq.addElement((namespace, 'pubsub'))
1257                self.stub.xmlstream.dispatch(iq)
1258
1259        self.assertEqual(4, len(requests))
1260
1261
1262    def test_getDiscoInfo(self):
1263        """
1264        Test getDiscoInfo calls getNodeInfo and returns some minimal info.
1265        """
1266        def cb(info):
1267            discoInfo = disco.DiscoInfo()
1268            for item in info:
1269                discoInfo.append(item)
1270            self.assertIn(('pubsub', 'service'), discoInfo.identities)
1271            self.assertIn(disco.NS_DISCO_ITEMS, discoInfo.features)
1272
1273        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1274                                      JID('pubsub.example.org'), '')
1275        d.addCallback(cb)
1276        return d
1277
1278
1279    def test_getDiscoInfoNodeType(self):
1280        """
1281        Test getDiscoInfo with node type.
1282        """
1283        def cb(info):
1284            discoInfo = disco.DiscoInfo()
1285            for item in info:
1286                discoInfo.append(item)
1287            self.assertIn(('pubsub', 'collection'), discoInfo.identities)
1288
1289        def getInfo(requestor, target, nodeIdentifier):
1290            return defer.succeed({'type': 'collection',
1291                                  'meta-data': {}})
1292
1293        self.resource.getInfo = getInfo
1294        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1295                                      JID('pubsub.example.org'), '')
1296        d.addCallback(cb)
1297        return d
1298
1299
1300    def test_getDiscoInfoMetaData(self):
1301        """
1302        Test getDiscoInfo with returned meta data.
1303        """
1304        def cb(info):
1305            discoInfo = disco.DiscoInfo()
1306            for item in info:
1307                discoInfo.append(item)
1308
1309            self.assertIn(('pubsub', 'leaf'), discoInfo.identities)
1310            self.assertIn(NS_PUBSUB_META_DATA, discoInfo.extensions)
1311            form = discoInfo.extensions[NS_PUBSUB_META_DATA]
1312            self.assertIn('pubsub#node_type', form.fields)
1313
1314        def getInfo(requestor, target, nodeIdentifier):
1315            metaData = [{'var': 'pubsub#persist_items',
1316                         'label': 'Persist items to storage',
1317                         'value': True}]
1318            return defer.succeed({'type': 'leaf', 'meta-data': metaData})
1319
1320        self.resource.getInfo = getInfo
1321        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1322                                      JID('pubsub.example.org'), '')
1323        d.addCallback(cb)
1324        return d
1325
1326
1327    def test_getDiscoInfoResourceFeatures(self):
1328        """
1329        Test getDiscoInfo with the resource features.
1330        """
1331        def cb(info):
1332            discoInfo = disco.DiscoInfo()
1333            for item in info:
1334                discoInfo.append(item)
1335            self.assertIn('http://jabber.org/protocol/pubsub#publish',
1336                          discoInfo.features)
1337
1338        self.resource.features = ['publish']
1339        d = self.service.getDiscoInfo(JID('user@example.org/home'),
1340                                      JID('pubsub.example.org'), '')
1341        d.addCallback(cb)
1342        return d
1343
1344
1345    def test_getDiscoItemsRoot(self):
1346        """
1347        Test getDiscoItems on the root node.
1348        """
1349        def getNodes(requestor, service, nodeIdentifier):
1350            return defer.succeed(['node1', 'node2'])
1351
1352        def cb(items):
1353            self.assertEqual(2, len(items))
1354            item1, item2 = items
1355
1356            self.assertEqual(JID('pubsub.example.org'), item1.entity)
1357            self.assertEqual('node1', item1.nodeIdentifier)
1358
1359            self.assertEqual(JID('pubsub.example.org'), item2.entity)
1360            self.assertEqual('node2', item2.nodeIdentifier)
1361
1362        self.resource.getNodes = getNodes
1363        d = self.service.getDiscoItems(JID('user@example.org/home'),
1364                                       JID('pubsub.example.org'),
1365                                       '')
1366        d.addCallback(cb)
1367        return d
1368
1369
1370    def test_getDiscoItemsRootHideNodes(self):
1371        """
1372        Test getDiscoItems on the root node.
1373        """
1374        def getNodes(requestor, service, nodeIdentifier):
1375            raise Exception("Unexpected call to getNodes")
1376
1377        def cb(items):
1378            self.assertEqual([], items)
1379
1380        self.service.hideNodes = True
1381        self.resource.getNodes = getNodes
1382        d = self.service.getDiscoItems(JID('user@example.org/home'),
1383                                       JID('pubsub.example.org'),
1384                                       '')
1385        d.addCallback(cb)
1386        return d
1387
1388
1389    def test_getDiscoItemsNonRoot(self):
1390        """
1391        Test getDiscoItems on a non-root node.
1392        """
1393        def getNodes(requestor, service, nodeIdentifier):
1394            return defer.succeed(['node1', 'node2'])
1395
1396        def cb(items):
1397            self.assertEqual(2, len(items))
1398
1399        self.resource.getNodes = getNodes
1400        d = self.service.getDiscoItems(JID('user@example.org/home'),
1401                                       JID('pubsub.example.org'),
1402                                       'test')
1403        d.addCallback(cb)
1404        return d
1405
1406
1407    def test_on_publish(self):
1408        """
1409        A publish request should result in L{PubSubService.publish} being
1410        called.
1411        """
1412
1413        xml = """
1414        <iq type='set' to='pubsub.example.org'
1415                       from='user@example.org'>
1416          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1417            <publish node='test'/>
1418          </pubsub>
1419        </iq>
1420        """
1421
1422        def publish(request):
1423            return defer.succeed(None)
1424
1425        self.resource.publish = publish
1426        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1427        return self.handleRequest(xml)
1428
1429
1430    def test_on_subscribe(self):
1431        """
1432        A successful subscription should return the current subscription.
1433        """
1434
1435        xml = """
1436        <iq type='set' to='pubsub.example.org'
1437                       from='user@example.org'>
1438          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1439            <subscribe node='test' jid='user@example.org/Home'/>
1440          </pubsub>
1441        </iq>
1442        """
1443
1444        def subscribe(request):
1445            return defer.succeed(pubsub.Subscription(request.nodeIdentifier,
1446                                                     request.subscriber,
1447                                                     'subscribed'))
1448
1449        def cb(element):
1450            self.assertEqual('pubsub', element.name)
1451            self.assertEqual(NS_PUBSUB, element.uri)
1452            subscription = element.subscription
1453            self.assertEqual(NS_PUBSUB, subscription.uri)
1454            self.assertEqual('test', subscription['node'])
1455            self.assertEqual('user@example.org/Home', subscription['jid'])
1456            self.assertEqual('subscribed', subscription['subscription'])
1457
1458        self.resource.subscribe = subscribe
1459        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1460        d = self.handleRequest(xml)
1461        d.addCallback(cb)
1462        return d
1463
1464
1465    def test_on_subscribeEmptyNode(self):
1466        """
1467        A successful subscription on root node should return no node attribute.
1468        """
1469
1470        xml = """
1471        <iq type='set' to='pubsub.example.org'
1472                       from='user@example.org'>
1473          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1474            <subscribe jid='user@example.org/Home'/>
1475          </pubsub>
1476        </iq>
1477        """
1478
1479        def subscribe(request):
1480            return defer.succeed(pubsub.Subscription(request.nodeIdentifier,
1481                                                     request.subscriber,
1482                                                     'subscribed'))
1483
1484        def cb(element):
1485            self.assertFalse(element.subscription.hasAttribute('node'))
1486
1487        self.resource.subscribe = subscribe
1488        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1489        d = self.handleRequest(xml)
1490        d.addCallback(cb)
1491        return d
1492
1493
1494    def test_on_unsubscribe(self):
1495        """
1496        A successful unsubscription should return an empty response.
1497        """
1498
1499        xml = """
1500        <iq type='set' to='pubsub.example.org'
1501                       from='user@example.org'>
1502          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1503            <unsubscribe node='test' jid='user@example.org/Home'/>
1504          </pubsub>
1505        </iq>
1506        """
1507
1508        def unsubscribe(request):
1509            return defer.succeed(None)
1510
1511        def cb(element):
1512            self.assertIdentical(None, element)
1513
1514        self.resource.unsubscribe = unsubscribe
1515        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1516        d = self.handleRequest(xml)
1517        d.addCallback(cb)
1518        return d
1519
1520
1521    def test_on_optionsGet(self):
1522        """
1523        Getting subscription options is not supported.
1524        """
1525
1526        xml = """
1527        <iq type='get' to='pubsub.example.org'
1528                       from='user@example.org'>
1529          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1530            <options node='test' jid='user@example.org/Home'/>
1531          </pubsub>
1532        </iq>
1533        """
1534
1535        def cb(result):
1536            self.assertEquals('feature-not-implemented', result.condition)
1537            self.assertEquals('unsupported', result.appCondition.name)
1538            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
1539
1540        d = self.handleRequest(xml)
1541        self.assertFailure(d, error.StanzaError)
1542        d.addCallback(cb)
1543        return d
1544
1545
1546    def test_on_optionsSet(self):
1547        """
1548        Setting subscription options is not supported.
1549        """
1550
1551        xml = """
1552        <iq type='set' to='pubsub.example.org'
1553                       from='user@example.org'>
1554          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1555            <options node='test' jid='user@example.org/Home'>
1556              <x xmlns='jabber:x:data' type='submit'>
1557                <field var='FORM_TYPE' type='hidden'>
1558                  <value>http://jabber.org/protocol/pubsub#subscribe_options</value>
1559                </field>
1560                <field var='pubsub#deliver'><value>1</value></field>
1561              </x>
1562            </options>
1563          </pubsub>
1564        </iq>
1565        """
1566
1567        def cb(result):
1568            self.assertEquals('feature-not-implemented', result.condition)
1569            self.assertEquals('unsupported', result.appCondition.name)
1570            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
1571
1572        d = self.handleRequest(xml)
1573        self.assertFailure(d, error.StanzaError)
1574        d.addCallback(cb)
1575        return d
1576
1577
1578    def test_on_subscriptions(self):
1579        """
1580        A subscriptions request should result in
1581        L{PubSubService.subscriptions} being called and the result prepared
1582        for the response.
1583        """
1584
1585        xml = """
1586        <iq type='get' to='pubsub.example.org'
1587                       from='user@example.org'>
1588          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1589            <subscriptions/>
1590          </pubsub>
1591        </iq>
1592        """
1593
1594        def subscriptions(request):
1595            subscription = pubsub.Subscription('test', JID('user@example.org'),
1596                                               'subscribed')
1597            return defer.succeed([subscription])
1598
1599        def cb(element):
1600            self.assertEqual('pubsub', element.name)
1601            self.assertEqual(NS_PUBSUB, element.uri)
1602            self.assertEqual(NS_PUBSUB, element.subscriptions.uri)
1603            children = list(element.subscriptions.elements())
1604            self.assertEqual(1, len(children))
1605            subscription = children[0]
1606            self.assertEqual('subscription', subscription.name)
1607            self.assertEqual(NS_PUBSUB, subscription.uri)
1608            self.assertEqual('user@example.org', subscription['jid'])
1609            self.assertEqual('test', subscription['node'])
1610            self.assertEqual('subscribed', subscription['subscription'])
1611
1612        self.resource.subscriptions = subscriptions
1613        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1614        d = self.handleRequest(xml)
1615        d.addCallback(cb)
1616        return d
1617
1618
1619    def test_on_affiliations(self):
1620        """
1621        A subscriptions request should result in
1622        L{PubSubService.affiliations} being called and the result prepared
1623        for the response.
1624        """
1625
1626        xml = """
1627        <iq type='get' to='pubsub.example.org'
1628                       from='user@example.org'>
1629          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1630            <affiliations/>
1631          </pubsub>
1632        </iq>
1633        """
1634
1635        def affiliations(request):
1636            affiliation = ('test', 'owner')
1637            return defer.succeed([affiliation])
1638
1639        def cb(element):
1640            self.assertEqual('pubsub', element.name)
1641            self.assertEqual(NS_PUBSUB, element.uri)
1642            self.assertEqual(NS_PUBSUB, element.affiliations.uri)
1643            children = list(element.affiliations.elements())
1644            self.assertEqual(1, len(children))
1645            affiliation = children[0]
1646            self.assertEqual('affiliation', affiliation.name)
1647            self.assertEqual(NS_PUBSUB, affiliation.uri)
1648            self.assertEqual('test', affiliation['node'])
1649            self.assertEqual('owner', affiliation['affiliation'])
1650
1651        self.resource.affiliations = affiliations
1652        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1653        d = self.handleRequest(xml)
1654        d.addCallback(cb)
1655        return d
1656
1657
1658    def test_on_create(self):
1659        """
1660        Replies to create node requests don't return the created node.
1661        """
1662
1663        xml = """
1664        <iq type='set' to='pubsub.example.org'
1665                       from='user@example.org'>
1666          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1667            <create node='mynode'/>
1668          </pubsub>
1669        </iq>
1670        """
1671
1672        def create(request):
1673            return defer.succeed(request.nodeIdentifier)
1674
1675        def cb(element):
1676            self.assertIdentical(None, element)
1677
1678        self.resource.create = create
1679        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1680        d = self.handleRequest(xml)
1681        d.addCallback(cb)
1682        return d
1683
1684
1685    def test_on_createChanged(self):
1686        """
1687        Replies to create node requests return the created node if changed.
1688        """
1689
1690        xml = """
1691        <iq type='set' to='pubsub.example.org'
1692                       from='user@example.org'>
1693          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1694            <create node='mynode'/>
1695          </pubsub>
1696        </iq>
1697        """
1698
1699        def create(request):
1700            return defer.succeed(u'myrenamednode')
1701
1702        def cb(element):
1703            self.assertEqual('pubsub', element.name)
1704            self.assertEqual(NS_PUBSUB, element.uri)
1705            self.assertEqual(NS_PUBSUB, element.create.uri)
1706            self.assertEqual(u'myrenamednode',
1707                             element.create.getAttribute('node'))
1708
1709        self.resource.create = create
1710        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1711        d = self.handleRequest(xml)
1712        d.addCallback(cb)
1713        return d
1714
1715
1716    def test_on_createInstant(self):
1717        """
1718        Replies to create instant node requests return the created node.
1719        """
1720
1721        xml = """
1722        <iq type='set' to='pubsub.example.org'
1723                       from='user@example.org'>
1724          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
1725            <create/>
1726          </pubsub>
1727        </iq>
1728        """
1729
1730        def create(request):
1731            return defer.succeed(u'random')
1732
1733        def cb(element):
1734            self.assertEqual('pubsub', element.name)
1735            self.assertEqual(NS_PUBSUB, element.uri)
1736            self.assertEqual(NS_PUBSUB, element.create.uri)
1737            self.assertEqual(u'random', element.create.getAttribute('node'))
1738
1739        self.resource.create = create
1740        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1741        d = self.handleRequest(xml)
1742        d.addCallback(cb)
1743        return d
1744
1745
1746    def test_on_default(self):
1747        """
1748        A default request should result in
1749        L{PubSubService.getDefaultConfiguration} being called.
1750        """
1751
1752        xml = """
1753        <iq type='get' to='pubsub.example.org'
1754                       from='user@example.org'>
1755          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1756            <default/>
1757          </pubsub>
1758        </iq>
1759        """
1760
1761        def getConfigurationOptions():
1762            return {
1763                "pubsub#persist_items":
1764                    {"type": "boolean",
1765                     "label": "Persist items to storage"},
1766                "pubsub#deliver_payloads":
1767                    {"type": "boolean",
1768                     "label": "Deliver payloads with event notifications"}
1769                }
1770
1771        def default(request):
1772            return defer.succeed({})
1773
1774        def cb(element):
1775            self.assertEqual('pubsub', element.name)
1776            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
1777            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
1778            form = data_form.Form.fromElement(element.default.x)
1779            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
1780
1781        self.resource.getConfigurationOptions = getConfigurationOptions
1782        self.resource.default = default
1783        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1784        d = self.handleRequest(xml)
1785        d.addCallback(cb)
1786        return d
1787
1788
1789    def test_on_defaultCollection(self):
1790        """
1791        Responses to default requests should depend on passed node type.
1792        """
1793
1794        xml = """
1795        <iq type='get' to='pubsub.example.org'
1796                       from='user@example.org'>
1797          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1798            <default>
1799              <x xmlns='jabber:x:data' type='submit'>
1800                <field var='FORM_TYPE' type='hidden'>
1801                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1802                </field>
1803                <field var='pubsub#node_type'>
1804                  <value>collection</value>
1805                </field>
1806              </x>
1807            </default>
1808
1809          </pubsub>
1810        </iq>
1811        """
1812
1813        def getConfigurationOptions():
1814            return {
1815                "pubsub#deliver_payloads":
1816                    {"type": "boolean",
1817                     "label": "Deliver payloads with event notifications"}
1818                }
1819
1820        def default(request):
1821            return defer.succeed({})
1822
1823        self.resource.getConfigurationOptions = getConfigurationOptions
1824        self.resource.default = default
1825        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1826        return self.handleRequest(xml)
1827
1828
1829    def test_on_defaultUnknownNodeType(self):
1830        """
1831        A default request should result in
1832        L{PubSubResource.default} being called.
1833        """
1834
1835        xml = """
1836        <iq type='get' to='pubsub.example.org'
1837                       from='user@example.org'>
1838          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1839            <default>
1840              <x xmlns='jabber:x:data' type='submit'>
1841                <field var='FORM_TYPE' type='hidden'>
1842                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1843                </field>
1844                <field var='pubsub#node_type'>
1845                  <value>unknown</value>
1846                </field>
1847              </x>
1848            </default>
1849
1850          </pubsub>
1851        </iq>
1852        """
1853
1854        def default(request):
1855            self.fail("Unexpected call to getConfiguration")
1856
1857        def cb(result):
1858            self.assertEquals('not-acceptable', result.condition)
1859
1860        self.resource.default = default
1861        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1862        d = self.handleRequest(xml)
1863        self.assertFailure(d, error.StanzaError)
1864        d.addCallback(cb)
1865        return d
1866
1867
1868    def test_on_configureGet(self):
1869        """
1870        On a node configuration get
1871        requestL{PubSubResource.configureGet} is called and results in a
1872        data form with the configuration.
1873        """
1874
1875        xml = """
1876        <iq type='get' to='pubsub.example.org'
1877                       from='user@example.org'>
1878          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1879            <configure node='test'/>
1880          </pubsub>
1881        </iq>
1882        """
1883
1884        def getConfigurationOptions():
1885            return {
1886                "pubsub#persist_items":
1887                    {"type": "boolean",
1888                     "label": "Persist items to storage"},
1889                "pubsub#deliver_payloads":
1890                    {"type": "boolean",
1891                     "label": "Deliver payloads with event notifications"},
1892                "pubsub#owner":
1893                    {"type": "jid-single",
1894                     "label": "Owner of the node"}
1895                }
1896
1897        def configureGet(request):
1898            return defer.succeed({'pubsub#deliver_payloads': '0',
1899                                  'pubsub#persist_items': '1',
1900                                  'pubsub#owner': JID('user@example.org'),
1901                                  'x-myfield': 'a'})
1902
1903        def cb(element):
1904            self.assertEqual('pubsub', element.name)
1905            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
1906            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
1907            form = data_form.Form.fromElement(element.configure.x)
1908            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
1909            fields = form.fields
1910
1911            self.assertIn('pubsub#deliver_payloads', fields)
1912            field = fields['pubsub#deliver_payloads']
1913            self.assertEqual('boolean', field.fieldType)
1914            field.typeCheck()
1915            self.assertEqual(False, field.value)
1916
1917            self.assertIn('pubsub#persist_items', fields)
1918            field = fields['pubsub#persist_items']
1919            self.assertEqual('boolean', field.fieldType)
1920            field.typeCheck()
1921            self.assertEqual(True, field.value)
1922
1923            self.assertIn('pubsub#owner', fields)
1924            field = fields['pubsub#owner']
1925            self.assertEqual('jid-single', field.fieldType)
1926            field.typeCheck()
1927            self.assertEqual(JID('user@example.org'), field.value)
1928
1929            self.assertNotIn('x-myfield', fields)
1930
1931        self.resource.getConfigurationOptions = getConfigurationOptions
1932        self.resource.configureGet = configureGet
1933        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1934        d = self.handleRequest(xml)
1935        d.addCallback(cb)
1936        return d
1937
1938
1939    def test_on_configureSet(self):
1940        """
1941        On a node configuration set request the Data Form is parsed and
1942        L{PubSubResource.configureSet} is called with the passed options.
1943        """
1944
1945        xml = """
1946        <iq type='set' to='pubsub.example.org'
1947                       from='user@example.org'>
1948          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1949            <configure node='test'>
1950              <x xmlns='jabber:x:data' type='submit'>
1951                <field var='FORM_TYPE' type='hidden'>
1952                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1953                </field>
1954                <field var='pubsub#deliver_payloads'><value>0</value></field>
1955                <field var='pubsub#persist_items'><value>1</value></field>
1956              </x>
1957            </configure>
1958          </pubsub>
1959        </iq>
1960        """
1961
1962        def getConfigurationOptions():
1963            return {
1964                "pubsub#persist_items":
1965                    {"type": "boolean",
1966                     "label": "Persist items to storage"},
1967                "pubsub#deliver_payloads":
1968                    {"type": "boolean",
1969                     "label": "Deliver payloads with event notifications"}
1970                }
1971
1972        def configureSet(request):
1973            self.assertEqual({'pubsub#deliver_payloads': False,
1974                              'pubsub#persist_items': True},
1975                             request.options.getValues())
1976            return defer.succeed(None)
1977
1978        self.resource.getConfigurationOptions = getConfigurationOptions
1979        self.resource.configureSet = configureSet
1980        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
1981        return self.handleRequest(xml)
1982
1983
1984    def test_on_configureSetCancel(self):
1985        """
1986        The node configuration is cancelled,
1987        L{PubSubResource.configureSet} not called.
1988        """
1989
1990        xml = """
1991        <iq type='set' to='pubsub.example.org'
1992                       from='user@example.org'>
1993          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
1994            <configure node='test'>
1995              <x xmlns='jabber:x:data' type='cancel'>
1996                <field var='FORM_TYPE' type='hidden'>
1997                  <value>http://jabber.org/protocol/pubsub#node_config</value>
1998                </field>
1999              </x>
2000            </configure>
2001          </pubsub>
2002        </iq>
2003        """
2004
2005        def configureSet(request):
2006            self.fail("Unexpected call to setConfiguration")
2007
2008        self.resource.configureSet = configureSet
2009        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2010        return self.handleRequest(xml)
2011
2012
2013    def test_on_configureSetIgnoreUnknown(self):
2014        """
2015        On a node configuration set request unknown fields should be ignored.
2016        """
2017
2018        xml = """
2019        <iq type='set' to='pubsub.example.org'
2020                       from='user@example.org'>
2021          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2022            <configure node='test'>
2023              <x xmlns='jabber:x:data' type='submit'>
2024                <field var='FORM_TYPE' type='hidden'>
2025                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2026                </field>
2027                <field var='pubsub#deliver_payloads'><value>0</value></field>
2028                <field var='x-myfield'><value>1</value></field>
2029              </x>
2030            </configure>
2031          </pubsub>
2032        </iq>
2033        """
2034
2035        def getConfigurationOptions():
2036            return {
2037                "pubsub#persist_items":
2038                    {"type": "boolean",
2039                     "label": "Persist items to storage"},
2040                "pubsub#deliver_payloads":
2041                    {"type": "boolean",
2042                     "label": "Deliver payloads with event notifications"}
2043                }
2044
2045        def configureSet(request):
2046            self.assertEquals(['pubsub#deliver_payloads'],
2047                              request.options.fields.keys())
2048
2049        self.resource.getConfigurationOptions = getConfigurationOptions
2050        self.resource.configureSet = configureSet
2051        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2052        return self.handleRequest(xml)
2053
2054
2055    def test_on_configureSetBadFormType(self):
2056        """
2057        On a node configuration set request unknown fields should be ignored.
2058        """
2059
2060        xml = """
2061        <iq type='set' to='pubsub.example.org'
2062                       from='user@example.org'>
2063          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2064            <configure node='test'>
2065              <x xmlns='jabber:x:data' type='result'>
2066                <field var='FORM_TYPE' type='hidden'>
2067                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2068                </field>
2069                <field var='pubsub#deliver_payloads'><value>0</value></field>
2070                <field var='x-myfield'><value>1</value></field>
2071              </x>
2072            </configure>
2073          </pubsub>
2074        </iq>
2075        """
2076
2077        def cb(result):
2078            self.assertEquals('bad-request', result.condition)
2079            self.assertEqual("Unexpected form type 'result'", result.text)
2080
2081        d = self.handleRequest(xml)
2082        self.assertFailure(d, error.StanzaError)
2083        d.addCallback(cb)
2084        return d
2085
2086
2087    def test_on_items(self):
2088        """
2089        On a items request, return all items for the given node.
2090        """
2091        xml = """
2092        <iq type='get' to='pubsub.example.org'
2093                       from='user@example.org'>
2094          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2095            <items node='test'/>
2096          </pubsub>
2097        </iq>
2098        """
2099
2100        def items(request):
2101            return defer.succeed([pubsub.Item('current')])
2102
2103        def cb(element):
2104            self.assertEqual(NS_PUBSUB, element.uri)
2105            self.assertEqual(NS_PUBSUB, element.items.uri)
2106            self.assertEqual(1, len(element.items.children))
2107            item = element.items.children[-1]
2108            self.assertTrue(domish.IElement.providedBy(item))
2109            self.assertEqual('item', item.name)
2110            self.assertEqual(NS_PUBSUB, item.uri)
2111            self.assertEqual('current', item['id'])
2112
2113        self.resource.items = items
2114        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2115        d = self.handleRequest(xml)
2116        d.addCallback(cb)
2117        return d
2118
2119
2120    def test_on_retract(self):
2121        """
2122        A retract request should result in L{PubSubResource.retract}
2123        being called.
2124        """
2125
2126        xml = """
2127        <iq type='set' to='pubsub.example.org'
2128                       from='user@example.org'>
2129          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2130            <retract node='test'>
2131              <item id='item1'/>
2132              <item id='item2'/>
2133            </retract>
2134          </pubsub>
2135        </iq>
2136        """
2137
2138        def retract(request):
2139            return defer.succeed(None)
2140
2141        self.resource.retract = retract
2142        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2143        return self.handleRequest(xml)
2144
2145
2146    def test_on_purge(self):
2147        """
2148        A purge request should result in L{PubSubResource.purge} being
2149        called.
2150        """
2151
2152        xml = """
2153        <iq type='set' to='pubsub.example.org'
2154                       from='user@example.org'>
2155          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2156            <purge node='test'/>
2157          </pubsub>
2158        </iq>
2159        """
2160
2161        def purge(request):
2162            return defer.succeed(None)
2163
2164        self.resource.purge = purge
2165        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2166        return self.handleRequest(xml)
2167
2168
2169    def test_on_delete(self):
2170        """
2171        A delete request should result in L{PubSubResource.delete} being
2172        called.
2173        """
2174
2175        xml = """
2176        <iq type='set' to='pubsub.example.org'
2177                       from='user@example.org'>
2178          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2179            <delete node='test'/>
2180          </pubsub>
2181        </iq>
2182        """
2183
2184        def delete(request):
2185            return defer.succeed(None)
2186
2187        self.resource.delete = delete
2188        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2189        return self.handleRequest(xml)
2190
2191
2192    def test_notifyDelete(self):
2193        """
2194        Subscribers should be sent a delete notification.
2195        """
2196        subscriptions = [JID('user@example.org')]
2197        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
2198                                  subscriptions)
2199        message = self.stub.output[-1]
2200
2201        self.assertEquals('message', message.name)
2202        self.assertIdentical(None, message.uri)
2203        self.assertEquals('user@example.org', message['to'])
2204        self.assertEquals('pubsub.example.org', message['from'])
2205        self.assertTrue(message.event)
2206        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
2207        self.assertTrue(message.event.delete)
2208        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
2209        self.assertTrue(message.event.delete.hasAttribute('node'))
2210        self.assertEqual('test', message.event.delete['node'])
2211
2212
2213    def test_notifyDeleteRedirect(self):
2214        """
2215        Subscribers should be sent a delete notification with redirect.
2216        """
2217        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
2218        subscriptions = [JID('user@example.org')]
2219        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
2220                                  subscriptions, redirectURI)
2221        message = self.stub.output[-1]
2222
2223        self.assertEquals('message', message.name)
2224        self.assertIdentical(None, message.uri)
2225        self.assertEquals('user@example.org', message['to'])
2226        self.assertEquals('pubsub.example.org', message['from'])
2227        self.assertTrue(message.event)
2228        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
2229        self.assertTrue(message.event.delete)
2230        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
2231        self.assertTrue(message.event.delete.hasAttribute('node'))
2232        self.assertEqual('test', message.event.delete['node'])
2233        self.assertTrue(message.event.delete.redirect)
2234        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
2235        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
2236        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
2237
2238
2239    def test_on_subscriptionsGet(self):
2240        """
2241        Getting subscription options is not supported.
2242        """
2243
2244        xml = """
2245        <iq type='get' to='pubsub.example.org'
2246                       from='user@example.org'>
2247          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2248            <subscriptions/>
2249          </pubsub>
2250        </iq>
2251        """
2252
2253        def cb(result):
2254            self.assertEquals('feature-not-implemented', result.condition)
2255            self.assertEquals('unsupported', result.appCondition.name)
2256            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2257            self.assertEquals('manage-subscriptions',
2258                              result.appCondition['feature'])
2259
2260        d = self.handleRequest(xml)
2261        self.assertFailure(d, error.StanzaError)
2262        d.addCallback(cb)
2263        return d
2264
2265
2266    def test_on_subscriptionsSet(self):
2267        """
2268        Setting subscription options is not supported.
2269        """
2270
2271        xml = """
2272        <iq type='set' to='pubsub.example.org'
2273                       from='user@example.org'>
2274          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2275            <subscriptions/>
2276          </pubsub>
2277        </iq>
2278        """
2279
2280        def cb(result):
2281            self.assertEquals('feature-not-implemented', result.condition)
2282            self.assertEquals('unsupported', result.appCondition.name)
2283            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2284            self.assertEquals('manage-subscriptions',
2285                              result.appCondition['feature'])
2286
2287        d = self.handleRequest(xml)
2288        self.assertFailure(d, error.StanzaError)
2289        d.addCallback(cb)
2290        return d
2291
2292
2293    def test_on_affiliationsGet(self):
2294        """
2295        Getting subscription options is not supported.
2296        """
2297
2298        xml = """
2299        <iq type='get' to='pubsub.example.org'
2300                       from='user@example.org'>
2301          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2302            <affiliations/>
2303          </pubsub>
2304        </iq>
2305        """
2306
2307        def cb(result):
2308            self.assertEquals('feature-not-implemented', result.condition)
2309            self.assertEquals('unsupported', result.appCondition.name)
2310            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2311            self.assertEquals('modify-affiliations',
2312                              result.appCondition['feature'])
2313
2314        d = self.handleRequest(xml)
2315        self.assertFailure(d, error.StanzaError)
2316        d.addCallback(cb)
2317        return d
2318
2319
2320    def test_on_affiliationsSet(self):
2321        """
2322        Setting subscription options is not supported.
2323        """
2324
2325        xml = """
2326        <iq type='set' to='pubsub.example.org'
2327                       from='user@example.org'>
2328          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2329            <affiliations/>
2330          </pubsub>
2331        </iq>
2332        """
2333
2334        def cb(result):
2335            self.assertEquals('feature-not-implemented', result.condition)
2336            self.assertEquals('unsupported', result.appCondition.name)
2337            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2338            self.assertEquals('modify-affiliations',
2339                              result.appCondition['feature'])
2340
2341        d = self.handleRequest(xml)
2342        self.assertFailure(d, error.StanzaError)
2343        d.addCallback(cb)
2344        return d
2345
2346
2347
2348class PubSubServiceWithoutResourceTest(unittest.TestCase, TestableRequestHandlerMixin):
2349
2350    def setUp(self):
2351        self.stub = XmlStreamStub()
2352        self.service = pubsub.PubSubService()
2353        self.service.send = self.stub.xmlstream.send
2354
2355
2356    def test_publish(self):
2357        """
2358        Non-overridden L{PubSubService.publish} yields unsupported error.
2359        """
2360
2361        xml = """
2362        <iq type='set' to='pubsub.example.org'
2363                       from='user@example.org'>
2364          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2365            <publish node='mynode'/>
2366          </pubsub>
2367        </iq>
2368        """
2369
2370        def cb(result):
2371            self.assertEquals('feature-not-implemented', result.condition)
2372            self.assertEquals('unsupported', result.appCondition.name)
2373            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2374            self.assertEquals('publish', result.appCondition['feature'])
2375
2376        d = self.handleRequest(xml)
2377        self.assertFailure(d, error.StanzaError)
2378        d.addCallback(cb)
2379        return d
2380
2381
2382    def test_subscribe(self):
2383        """
2384        Non-overridden L{PubSubService.subscribe} yields unsupported error.
2385        """
2386
2387        xml = """
2388        <iq type='set' to='pubsub.example.org'
2389                       from='user@example.org'>
2390          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2391            <subscribe node='test' jid='user@example.org/Home'/>
2392          </pubsub>
2393        </iq>
2394        """
2395
2396        def cb(result):
2397            self.assertEquals('feature-not-implemented', result.condition)
2398            self.assertEquals('unsupported', result.appCondition.name)
2399            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2400            self.assertEquals('subscribe', result.appCondition['feature'])
2401
2402        d = self.handleRequest(xml)
2403        self.assertFailure(d, error.StanzaError)
2404        d.addCallback(cb)
2405        return d
2406
2407
2408    def test_unsubscribe(self):
2409        """
2410        Non-overridden L{PubSubService.unsubscribe} yields unsupported error.
2411        """
2412
2413        xml = """
2414        <iq type='set' to='pubsub.example.org'
2415                       from='user@example.org'>
2416          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2417            <unsubscribe node='test' jid='user@example.org/Home'/>
2418          </pubsub>
2419        </iq>
2420        """
2421
2422        def cb(result):
2423            self.assertEquals('feature-not-implemented', result.condition)
2424            self.assertEquals('unsupported', result.appCondition.name)
2425            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2426            self.assertEquals('subscribe', result.appCondition['feature'])
2427
2428        d = self.handleRequest(xml)
2429        self.assertFailure(d, error.StanzaError)
2430        d.addCallback(cb)
2431        return d
2432
2433
2434    def test_subscriptions(self):
2435        """
2436        Non-overridden L{PubSubService.subscriptions} yields unsupported error.
2437        """
2438
2439        xml = """
2440        <iq type='get' to='pubsub.example.org'
2441                       from='user@example.org'>
2442          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2443            <subscriptions/>
2444          </pubsub>
2445        </iq>
2446        """
2447
2448        def cb(result):
2449            self.assertEquals('feature-not-implemented', result.condition)
2450            self.assertEquals('unsupported', result.appCondition.name)
2451            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2452            self.assertEquals('retrieve-subscriptions',
2453                              result.appCondition['feature'])
2454
2455        d = self.handleRequest(xml)
2456        self.assertFailure(d, error.StanzaError)
2457        d.addCallback(cb)
2458        return d
2459
2460
2461    def test_affiliations(self):
2462        """
2463        Non-overridden L{PubSubService.affiliations} yields unsupported error.
2464        """
2465
2466        xml = """
2467        <iq type='get' to='pubsub.example.org'
2468                       from='user@example.org'>
2469          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2470            <affiliations/>
2471          </pubsub>
2472        </iq>
2473        """
2474
2475        def cb(result):
2476            self.assertEquals('feature-not-implemented', result.condition)
2477            self.assertEquals('unsupported', result.appCondition.name)
2478            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2479            self.assertEquals('retrieve-affiliations',
2480                              result.appCondition['feature'])
2481
2482        d = self.handleRequest(xml)
2483        self.assertFailure(d, error.StanzaError)
2484        d.addCallback(cb)
2485        return d
2486
2487
2488    def test_create(self):
2489        """
2490        Non-overridden L{PubSubService.create} yields unsupported error.
2491        """
2492
2493        xml = """
2494        <iq type='set' to='pubsub.example.org'
2495                       from='user@example.org'>
2496          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2497            <create node='mynode'/>
2498          </pubsub>
2499        </iq>
2500        """
2501
2502        def cb(result):
2503            self.assertEquals('feature-not-implemented', result.condition)
2504            self.assertEquals('unsupported', result.appCondition.name)
2505            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2506            self.assertEquals('create-nodes', result.appCondition['feature'])
2507
2508        d = self.handleRequest(xml)
2509        self.assertFailure(d, error.StanzaError)
2510        d.addCallback(cb)
2511        return d
2512
2513
2514    def test_getDefaultConfiguration(self):
2515        """
2516        Non-overridden L{PubSubService.getDefaultConfiguration} yields
2517        unsupported error.
2518        """
2519
2520        xml = """
2521        <iq type='get' to='pubsub.example.org'
2522                       from='user@example.org'>
2523          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2524            <default/>
2525          </pubsub>
2526        </iq>
2527        """
2528
2529        def cb(result):
2530            self.assertEquals('feature-not-implemented', result.condition)
2531            self.assertEquals('unsupported', result.appCondition.name)
2532            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2533            self.assertEquals('retrieve-default', result.appCondition['feature'])
2534
2535        d = self.handleRequest(xml)
2536        self.assertFailure(d, error.StanzaError)
2537        d.addCallback(cb)
2538        return d
2539
2540
2541    def test_getConfiguration(self):
2542        """
2543        Non-overridden L{PubSubService.getConfiguration} yields unsupported
2544        error.
2545        """
2546
2547        xml = """
2548        <iq type='get' to='pubsub.example.org'
2549                       from='user@example.org'>
2550          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2551            <configure/>
2552          </pubsub>
2553        </iq>
2554        """
2555
2556        def cb(result):
2557            self.assertEquals('feature-not-implemented', result.condition)
2558            self.assertEquals('unsupported', result.appCondition.name)
2559            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2560            self.assertEquals('config-node', result.appCondition['feature'])
2561
2562        d = self.handleRequest(xml)
2563        self.assertFailure(d, error.StanzaError)
2564        d.addCallback(cb)
2565        return d
2566
2567
2568    def test_setConfiguration(self):
2569        """
2570        Non-overridden L{PubSubService.setConfiguration} yields unsupported
2571        error.
2572        """
2573
2574        xml = """
2575        <iq type='set' to='pubsub.example.org'
2576                       from='user@example.org'>
2577          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2578            <configure node='test'>
2579              <x xmlns='jabber:x:data' type='submit'>
2580                <field var='FORM_TYPE' type='hidden'>
2581                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2582                </field>
2583                <field var='pubsub#deliver_payloads'><value>0</value></field>
2584                <field var='pubsub#persist_items'><value>1</value></field>
2585              </x>
2586            </configure>
2587          </pubsub>
2588        </iq>
2589        """
2590
2591        def cb(result):
2592            self.assertEquals('feature-not-implemented', result.condition)
2593            self.assertEquals('unsupported', result.appCondition.name)
2594            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2595            self.assertEquals('config-node', result.appCondition['feature'])
2596
2597        d = self.handleRequest(xml)
2598        self.assertFailure(d, error.StanzaError)
2599        d.addCallback(cb)
2600        return d
2601
2602
2603    def test_setConfigurationOptionsDict(self):
2604        """
2605        Options should be passed as a dictionary, not a form.
2606        """
2607
2608        xml = """
2609        <iq type='set' to='pubsub.example.org'
2610                       from='user@example.org'>
2611          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2612            <configure node='test'>
2613              <x xmlns='jabber:x:data' type='submit'>
2614                <field var='FORM_TYPE' type='hidden'>
2615                  <value>http://jabber.org/protocol/pubsub#node_config</value>
2616                </field>
2617                <field var='pubsub#deliver_payloads'><value>0</value></field>
2618                <field var='pubsub#persist_items'><value>1</value></field>
2619              </x>
2620            </configure>
2621          </pubsub>
2622        </iq>
2623        """
2624
2625        def getConfigurationOptions():
2626            return {
2627                "pubsub#persist_items":
2628                    {"type": "boolean",
2629                     "label": "Persist items to storage"},
2630                "pubsub#deliver_payloads":
2631                    {"type": "boolean",
2632                     "label": "Deliver payloads with event notifications"}
2633                }
2634
2635        def setConfiguration(requestor, service, nodeIdentifier, options):
2636            self.assertEquals({'pubsub#deliver_payloads': False,
2637                               'pubsub#persist_items': True}, options)
2638
2639
2640        self.service.getConfigurationOptions = getConfigurationOptions
2641        self.service.setConfiguration = setConfiguration
2642        return self.handleRequest(xml)
2643
2644
2645    def test_items(self):
2646        """
2647        Non-overridden L{PubSubService.items} yields unsupported error.
2648        """
2649        xml = """
2650        <iq type='get' to='pubsub.example.org'
2651                       from='user@example.org'>
2652          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2653            <items node='test'/>
2654          </pubsub>
2655        </iq>
2656        """
2657
2658        def cb(result):
2659            self.assertEquals('feature-not-implemented', result.condition)
2660            self.assertEquals('unsupported', result.appCondition.name)
2661            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2662            self.assertEquals('retrieve-items', result.appCondition['feature'])
2663
2664        d = self.handleRequest(xml)
2665        self.assertFailure(d, error.StanzaError)
2666        d.addCallback(cb)
2667        return d
2668
2669
2670    def test_retract(self):
2671        """
2672        Non-overridden L{PubSubService.retract} yields unsupported error.
2673        """
2674        xml = """
2675        <iq type='set' to='pubsub.example.org'
2676                       from='user@example.org'>
2677          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
2678            <retract node='test'>
2679              <item id='item1'/>
2680              <item id='item2'/>
2681            </retract>
2682          </pubsub>
2683        </iq>
2684        """
2685
2686        def cb(result):
2687            self.assertEquals('feature-not-implemented', result.condition)
2688            self.assertEquals('unsupported', result.appCondition.name)
2689            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2690            self.assertEquals('retract-items', result.appCondition['feature'])
2691
2692        d = self.handleRequest(xml)
2693        self.assertFailure(d, error.StanzaError)
2694        d.addCallback(cb)
2695        return d
2696
2697
2698    def test_purge(self):
2699        """
2700        Non-overridden L{PubSubService.purge} yields unsupported error.
2701        """
2702        xml = """
2703        <iq type='set' to='pubsub.example.org'
2704                       from='user@example.org'>
2705          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2706            <purge node='test'/>
2707          </pubsub>
2708        </iq>
2709        """
2710
2711        def cb(result):
2712            self.assertEquals('feature-not-implemented', result.condition)
2713            self.assertEquals('unsupported', result.appCondition.name)
2714            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2715            self.assertEquals('purge-nodes', result.appCondition['feature'])
2716
2717        d = self.handleRequest(xml)
2718        self.assertFailure(d, error.StanzaError)
2719        d.addCallback(cb)
2720        return d
2721
2722
2723    def test_delete(self):
2724        """
2725        Non-overridden L{PubSubService.delete} yields unsupported error.
2726        """
2727        xml = """
2728        <iq type='set' to='pubsub.example.org'
2729                       from='user@example.org'>
2730          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
2731            <delete node='test'/>
2732          </pubsub>
2733        </iq>
2734        """
2735
2736        def cb(result):
2737            self.assertEquals('feature-not-implemented', result.condition)
2738            self.assertEquals('unsupported', result.appCondition.name)
2739            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2740            self.assertEquals('delete-nodes', result.appCondition['feature'])
2741
2742        d = self.handleRequest(xml)
2743        self.assertFailure(d, error.StanzaError)
2744        d.addCallback(cb)
2745        return d
2746
2747
2748
2749class PubSubResourceTest(unittest.TestCase):
2750
2751    def setUp(self):
2752        self.resource = pubsub.PubSubResource()
2753
2754
2755    def test_interface(self):
2756        """
2757        Do instances of L{pubsub.PubSubResource} provide L{iwokkel.IPubSubResource}?
2758        """
2759        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
2760
2761
2762    def test_getNodes(self):
2763        """
2764        Default getNodes returns an empty list.
2765        """
2766        def cb(nodes):
2767            self.assertEquals([], nodes)
2768
2769        d = self.resource.getNodes(JID('user@example.org/home'),
2770                                   JID('pubsub.example.org'),
2771                                   '')
2772        d.addCallback(cb)
2773        return d
2774
2775
2776    def test_publish(self):
2777        """
2778        Non-overridden L{PubSubResource.publish} yields unsupported
2779        error.
2780        """
2781
2782        def cb(result):
2783            self.assertEquals('feature-not-implemented', result.condition)
2784            self.assertEquals('unsupported', result.appCondition.name)
2785            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2786            self.assertEquals('publish', result.appCondition['feature'])
2787
2788        d = self.resource.publish(pubsub.PubSubRequest())
2789        self.assertFailure(d, error.StanzaError)
2790        d.addCallback(cb)
2791        return d
2792
2793
2794    def test_subscribe(self):
2795        """
2796        Non-overridden subscriptions yields unsupported error.
2797        """
2798
2799        def cb(result):
2800            self.assertEquals('feature-not-implemented', result.condition)
2801            self.assertEquals('unsupported', result.appCondition.name)
2802            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2803            self.assertEquals('subscribe', result.appCondition['feature'])
2804
2805        d = self.resource.subscribe(pubsub.PubSubRequest())
2806        self.assertFailure(d, error.StanzaError)
2807        d.addCallback(cb)
2808        return d
2809
2810
2811    def test_unsubscribe(self):
2812        """
2813        Non-overridden unsubscribe yields unsupported error.
2814        """
2815
2816        def cb(result):
2817            self.assertEquals('feature-not-implemented', result.condition)
2818            self.assertEquals('unsupported', result.appCondition.name)
2819            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2820            self.assertEquals('subscribe', result.appCondition['feature'])
2821
2822        d = self.resource.unsubscribe(pubsub.PubSubRequest())
2823        self.assertFailure(d, error.StanzaError)
2824        d.addCallback(cb)
2825        return d
2826
2827
2828    def test_subscriptions(self):
2829        """
2830        Non-overridden subscriptions yields unsupported error.
2831        """
2832
2833        def cb(result):
2834            self.assertEquals('feature-not-implemented', result.condition)
2835            self.assertEquals('unsupported', result.appCondition.name)
2836            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2837            self.assertEquals('retrieve-subscriptions',
2838                              result.appCondition['feature'])
2839
2840        d = self.resource.subscriptions(pubsub.PubSubRequest())
2841        self.assertFailure(d, error.StanzaError)
2842        d.addCallback(cb)
2843        return d
2844
2845
2846    def test_affiliations(self):
2847        """
2848        Non-overridden affiliations yields unsupported error.
2849        """
2850
2851        def cb(result):
2852            self.assertEquals('feature-not-implemented', result.condition)
2853            self.assertEquals('unsupported', result.appCondition.name)
2854            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2855            self.assertEquals('retrieve-affiliations',
2856                              result.appCondition['feature'])
2857
2858        d = self.resource.affiliations(pubsub.PubSubRequest())
2859        self.assertFailure(d, error.StanzaError)
2860        d.addCallback(cb)
2861        return d
2862
2863
2864    def test_create(self):
2865        """
2866        Non-overridden create yields unsupported error.
2867        """
2868
2869        def cb(result):
2870            self.assertEquals('feature-not-implemented', result.condition)
2871            self.assertEquals('unsupported', result.appCondition.name)
2872            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2873            self.assertEquals('create-nodes', result.appCondition['feature'])
2874
2875        d = self.resource.create(pubsub.PubSubRequest())
2876        self.assertFailure(d, error.StanzaError)
2877        d.addCallback(cb)
2878        return d
2879
2880
2881    def test_default(self):
2882        """
2883        Non-overridden default yields unsupported error.
2884        """
2885
2886        def cb(result):
2887            self.assertEquals('feature-not-implemented', result.condition)
2888            self.assertEquals('unsupported', result.appCondition.name)
2889            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2890            self.assertEquals('retrieve-default',
2891                              result.appCondition['feature'])
2892
2893        d = self.resource.default(pubsub.PubSubRequest())
2894        self.assertFailure(d, error.StanzaError)
2895        d.addCallback(cb)
2896        return d
2897
2898
2899    def test_configureGet(self):
2900        """
2901        Non-overridden configureGet yields unsupported
2902        error.
2903        """
2904
2905        def cb(result):
2906            self.assertEquals('feature-not-implemented', result.condition)
2907            self.assertEquals('unsupported', result.appCondition.name)
2908            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2909            self.assertEquals('config-node', result.appCondition['feature'])
2910
2911        d = self.resource.configureGet(pubsub.PubSubRequest())
2912        self.assertFailure(d, error.StanzaError)
2913        d.addCallback(cb)
2914        return d
2915
2916
2917    def test_configureSet(self):
2918        """
2919        Non-overridden configureSet yields unsupported error.
2920        """
2921
2922        def cb(result):
2923            self.assertEquals('feature-not-implemented', result.condition)
2924            self.assertEquals('unsupported', result.appCondition.name)
2925            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2926            self.assertEquals('config-node', result.appCondition['feature'])
2927
2928        d = self.resource.configureSet(pubsub.PubSubRequest())
2929        self.assertFailure(d, error.StanzaError)
2930        d.addCallback(cb)
2931        return d
2932
2933
2934    def test_items(self):
2935        """
2936        Non-overridden items yields unsupported error.
2937        """
2938
2939        def cb(result):
2940            self.assertEquals('feature-not-implemented', result.condition)
2941            self.assertEquals('unsupported', result.appCondition.name)
2942            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2943            self.assertEquals('retrieve-items', result.appCondition['feature'])
2944
2945        d = self.resource.items(pubsub.PubSubRequest())
2946        self.assertFailure(d, error.StanzaError)
2947        d.addCallback(cb)
2948        return d
2949
2950
2951    def test_retract(self):
2952        """
2953        Non-overridden retract yields unsupported error.
2954        """
2955
2956        def cb(result):
2957            self.assertEquals('feature-not-implemented', result.condition)
2958            self.assertEquals('unsupported', result.appCondition.name)
2959            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2960            self.assertEquals('retract-items', result.appCondition['feature'])
2961
2962        d = self.resource.retract(pubsub.PubSubRequest())
2963        self.assertFailure(d, error.StanzaError)
2964        d.addCallback(cb)
2965        return d
2966
2967
2968    def test_purge(self):
2969        """
2970        Non-overridden purge yields unsupported error.
2971        """
2972
2973        def cb(result):
2974            self.assertEquals('feature-not-implemented', result.condition)
2975            self.assertEquals('unsupported', result.appCondition.name)
2976            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2977            self.assertEquals('purge-nodes', result.appCondition['feature'])
2978
2979        d = self.resource.purge(pubsub.PubSubRequest())
2980        self.assertFailure(d, error.StanzaError)
2981        d.addCallback(cb)
2982        return d
2983
2984
2985    def test_delete(self):
2986        """
2987        Non-overridden delete yields unsupported error.
2988        """
2989
2990        def cb(result):
2991            self.assertEquals('feature-not-implemented', result.condition)
2992            self.assertEquals('unsupported', result.appCondition.name)
2993            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
2994            self.assertEquals('delete-nodes', result.appCondition['feature'])
2995
2996        d = self.resource.delete(pubsub.PubSubRequest())
2997        self.assertFailure(d, error.StanzaError)
2998        d.addCallback(cb)
2999        return d
Note: See TracBrowser for help on using the repository browser.