source: wokkel/test/test_pubsub.py @ 82:f965c6c5da15

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

Add support for configuration options in node creation requests

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