source: wokkel/test/test_pubsub.py @ 57:bcc9bc7a0929

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

Add a PubSubRequest? class, to parse and render publish-subscribe requests.

Author: ralphm.
Fixes #45.

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