Changeset 5:231bc3e8b810 in ralphm-patches for pubsub_resource.patch


Ignore:
Timestamp:
Apr 1, 2009, 2:17:03 PM (13 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
default
Message:

A gazillion changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pubsub_resource.patch

    r4 r5  
    1 diff -r dc8ed1ff55d7 wokkel/iwokkel.py
    2 --- a/wokkel/iwokkel.py Wed Mar 18 09:26:24 2009 +0100
    3 +++ b/wokkel/iwokkel.py Wed Mar 18 20:51:58 2009 +0100
    4 @@ -297,76 +297,14 @@
     1diff -r 2ea6196efcdc wokkel/iwokkel.py
     2--- a/wokkel/iwokkel.py Wed Mar 25 18:14:07 2009 +0100
     3+++ b/wokkel/iwokkel.py Mon Mar 30 08:35:05 2009 +0200
     4@@ -297,75 +297,46 @@
    55         """
    66 
     
    1717         @type request: L{wokkel.pubsub.PubSubRequest}
    1818-        @return: deferred that fires on success.
    19 -        @rtype: L{defer.Deferred}
    20 -        """
    21 -
    22 -
     19+        """
     20+
     21+
     22+    def getInfo(requestor, service, nodeIdentifier):
     23+        """
     24+        Get node type and meta data.
     25+
     26+        @param requestor: The entity the request originated from.
     27+        @type requestor: L{jid.JID}
     28+        @param service: The publish-subscribe service entity.
     29+        @type service: L{jid.JID}
     30+        @param nodeIdentifier: Identifier of the node to request the info for.
     31+        @type nodeIdentifier: L{unicode}
     32+        @return: A deferred that fires with a dictionary. If not empty,
     33+                 it must have the keys C{'type'} and C{'meta-data'} to keep
     34+                 respectively the node type and a dictionary with the meta
     35+                 data for that node.
     36         @rtype: L{defer.Deferred}
     37         """
     38 
     39 
    2340-    def subscribe(request):
    24 -        """
     41+    def getNodes(requestor, service, nodeIdentifier):
     42         """
    2543-        Called when a subscribe request has been received.
    26 -
     44+        Get all nodes contained by this node.
     45 
    2746-        @param request: The publish-subscribe request.
    2847-        @type request: L{wokkel.pubsub.PubSubRequest}
     
    7998-        @return: A deferred that fires with a C{unicode} that represents
    8099-                 the identifier of the new node.
    81 -        @rtype: L{defer.Deferred}
    82          """
    83  
    84  
    85 @@ -406,7 +344,80 @@
     100+        @param requestor: The entity the request originated from.
     101+        @type requestor: L{jid.JID}
     102+        @param service: The publish-subscribe service entity.
     103+        @type service: L{jid.JID}
     104+        @param nodeIdentifier: Identifier of the node to request the childs for.
     105+        @type nodeIdentifier: L{unicode}
     106+        @return: A deferred that fires with a list of child node identifiers.
     107         @rtype: L{defer.Deferred}
     108         """
     109 
     110@@ -406,7 +377,80 @@
    86111         """
    87112 
    88113 
    89114-    def getDefaultConfiguration(request):
    90 +    def pubsub_publish(request):
     115+    def publish(request):
    91116+        """
    92117+        Called when a publish request has been received.
     
    99124+
    100125+
    101 +    def pubsub_subscribe(request):
     126+    def subscribe(request):
    102127+        """
    103128+        Called when a subscribe request has been received.
     
    111136+
    112137+
    113 +    def pubsub_unsubscribe(request):
     138+    def unsubscribe(request):
    114139+        """
    115140+        Called when a subscribe request has been received.
     
    123148+
    124149+
    125 +    def pubsub_subscriptions(request):
     150+    def subscriptions(request):
    126151+        """
    127152+        Called when a subscriptions retrieval request has been received.
     
    135160+
    136161+
    137 +    def pubsub_affiliations(request):
     162+    def affiliations(request):
    138163+        """
    139164+        Called when a affiliations retrieval request has been received.
     
    149174+
    150175+
    151 +    def pubsub_create(request):
     176+    def create(request):
    152177+        """
    153178+        Called when a node creation request has been received.
     
    161186+
    162187+
    163 +    def pubsub_default(request):
     188+    def default(request):
    164189         """
    165190         Called when a default node configuration request has been received.
    166191 
    167 @@ -420,7 +431,7 @@
     192@@ -420,7 +464,7 @@
    168193         """
    169194 
    170195 
    171196-    def getConfiguration(request):
    172 +    def pubsub_configureGet(request):
     197+    def configureGet(request):
    173198         """
    174199         Called when a node configuration retrieval request has been received.
    175200 
    176 @@ -433,7 +444,7 @@
     201@@ -433,7 +477,7 @@
    177202         """
    178203 
    179204 
    180205-    def setConfiguration(request):
    181 +    def pubsub_configureSet(request):
     206+    def configureSet(request):
    182207         """
    183208         Called when a node configuration change request has been received.
    184209 
    185 @@ -445,7 +456,7 @@
    186          """
    187  
    188  
    189 -    def items(request):
    190 +    def pubsub_items(request):
    191          """
    192          Called when a items retrieval request has been received.
    193  
    194 @@ -456,7 +467,7 @@
    195          """
    196  
    197  
    198 -    def retract(request):
    199 +    def pubsub_retract(request):
    200          """
    201          Called when a item retraction request has been received.
    202  
    203 @@ -468,7 +479,7 @@
    204          """
    205  
    206  
    207 -    def purge(request):
    208 +    def pubsub_purge(request):
    209          """
    210          Called when a node purge request has been received.
    211  
    212 @@ -480,7 +491,7 @@
    213          """
    214  
    215  
    216 -    def delete(request):
    217 +    def pubsub_delete(request):
    218          """
    219          Called when a node deletion request has been received.
    220  
    221 diff -r dc8ed1ff55d7 wokkel/pubsub.py
    222 --- a/wokkel/pubsub.py  Wed Mar 18 09:26:24 2009 +0100
    223 +++ b/wokkel/pubsub.py  Wed Mar 18 20:51:58 2009 +0100
    224 @@ -18,7 +18,7 @@
     210diff -r 2ea6196efcdc wokkel/pubsub.py
     211--- a/wokkel/pubsub.py  Wed Mar 25 18:14:07 2009 +0100
     212+++ b/wokkel/pubsub.py  Mon Mar 30 08:35:05 2009 +0200
     213@@ -13,12 +13,13 @@
     214 from zope.interface import implements
     215 
     216 from twisted.internet import defer
     217+from twisted.python import log
     218 from twisted.words.protocols.jabber import jid, error, xmlstream
     219 from twisted.words.xish import domish
    225220 
    226221 from wokkel import disco, data_form, generic, shim
     
    231226 # Iq get and set XPath queries
    232227 IQ_GET = '/iq[@type="get"]'
    233 @@ -77,11 +77,16 @@
     228@@ -84,11 +85,16 @@
    234229 
    235230 class Unsupported(PubSubError):
     
    248243 
    249244 class Subscription(object):
    250 @@ -228,9 +233,9 @@
     245@@ -235,9 +241,9 @@
    251246         'retract': ['node', 'itemIdentifiers'],
    252247         'purge': ['node'],
     
    260255     }
    261256 
    262 @@ -359,6 +364,9 @@
    263          else:
    264              self.nodeType = 'leaf'
    265  
    266 +        if self.nodeType not in ('leaf', 'collection'):
    267 +            raise error.StanzaError('not-acceptable')
    268 +
    269  
    270      def _parse_configure(self, verbElement):
    271          """
    272 @@ -787,8 +795,8 @@
     257@@ -806,13 +812,10 @@
    273258             '/*': '_onPubSubRequest',
    274259             }
    275260 
    276 -
     261+    hideNodes = False
     262 
    277263-    def __init__(self):
     264-        self.discoIdentity = {'category': 'pubsub',
     265-                              'type': 'generic',
     266-                              'name': 'Generic Publish-Subscribe Service'}
     267-
     268-        self.pubSubFeatures = []
    278269+    def __init__(self, resource):
    279270+        self.resource = resource
    280          self.discoIdentity = {'category': 'pubsub',
    281                                'type': 'generic',
    282                                'name': 'Generic Publish-Subscribe Service'}
    283 @@ -851,91 +859,80 @@
     271 
     272 
     273     def connectionMade(self):
     274@@ -820,19 +823,9 @@
     275 
     276 
     277     def getDiscoInfo(self, requestor, target, nodeIdentifier):
     278-        info = []
     279-
     280-        if not nodeIdentifier:
     281-            category, idType, name = self.discoIdentity
     282-            info.append(disco.DiscoIdentity(category, idType, name))
     283-
     284-            info.append(disco.DiscoFeature(disco.NS_DISCO_ITEMS))
     285-            info.extend([disco.DiscoFeature("%s#%s" % (NS_PUBSUB, feature))
     286-                         for feature in self.pubSubFeatures])
     287-
     288-        def toInfo(nodeInfo):
     289+        def toInfo(nodeInfo, info):
     290             if not nodeInfo:
     291-                return
     292+                return info
     293 
     294             (nodeType, metaData) = nodeInfo['type'], nodeInfo['meta-data']
     295             info.append(disco.DiscoIdentity('pubsub', nodeType))
     296@@ -852,17 +845,33 @@
     297 
     298                 info.append(form.toElement())
     299 
     300-        d = self.getNodeInfo(requestor, target, nodeIdentifier or '')
     301-        d.addCallback(toInfo)
     302-        d.addBoth(lambda result: info)
     303+            return info
     304+
     305+        info = []
     306+
     307+        request = PubSubRequest('discoInfo')
     308+        resource = self.resource.locateResource(request)
     309+
     310+        if not nodeIdentifier:
     311+            info.append(resource.discoIdentity)
     312+            info.append(disco.DiscoFeature(disco.NS_DISCO_ITEMS))
     313+            info.extend([disco.DiscoFeature("%s#%s" % (NS_PUBSUB, feature))
     314+                         for feature in resource.features])
     315+
     316+        d = resource.getInfo(requestor, target, nodeIdentifier or '')
     317+        d.addCallback(toInfo, info)
     318+        d.addErrback(log.err)
     319         return d
     320 
     321 
     322     def getDiscoItems(self, requestor, target, nodeIdentifier):
     323-        if nodeIdentifier or self.hideNodes:
     324+        request = PubSubRequest('discoInfo')
     325+        resource = self.resource.locateResource(request)
     326+
     327+        if self.hideNodes:
     328             return defer.succeed([])
     329 
     330-        d = self.getNodes(requestor, target)
     331+        d = resource.getNodes(requestor, target, nodeIdentifier)
     332         d.addCallback(lambda nodes: [disco.DiscoItem(target, node)
     333                                      for node in nodes])
     334         return d
     335@@ -870,91 +879,80 @@
    284336 
    285337     def _onPubSubRequest(self, iq):
     
    303355+        # Process the request itself,
    304356+        try:
    305 +            handler = getattr(resource, 'pubsub_%s' % request.verb)
     357+            handler = getattr(resource, request.verb)
    306358+        except AttributeError:
    307359+            # fix lookup feature
     
    430482 
    431483     def _makeFields(self, options, values):
    432 @@ -954,8 +951,8 @@
     484@@ -973,8 +971,8 @@
    433485         return fields
    434486 
     
    441493         form = data_form.Form(formType="form",
    442494                               formNamespace=NS_PUBSUB_NODE_CONFIG,
    443 @@ -964,8 +961,8 @@
     495@@ -983,8 +981,8 @@
    444496         return form
    445497 
     
    452504 
    453505         for key, value in values.iteritems():
    454 @@ -989,93 +986,45 @@
     506@@ -1008,93 +1006,52 @@
    455507         return processedValues
    456508 
    457509 
    458510-    def _on_default(self, request):
     511+    def _preProcess_default(self, resource, request):
     512+        if request.nodeType not in ('leaf', 'collection'):
     513+            raise error.StanzaError('not-acceptable')
     514+        else:
     515+            return request
     516 
     517-        def toResponse(options):
     518-            response = domish.Element((NS_PUBSUB_OWNER, "pubsub"))
     519-            default = response.addElement("default")
     520-            default.addChild(self._formFromConfiguration(options).toElement())
     521-            return response
     522 
     523-        if request.nodeType not in ('leaf', 'collection'):
     524-            return defer.fail(error.StanzaError('not-acceptable'))
    459525+    def _toResponse_default(self, options, resource, request):
    460526+        response = domish.Element((NS_PUBSUB_OWNER, "pubsub"))
     
    464530+        return response
    465531 
    466 -        def toResponse(options):
    467 -            response = domish.Element((NS_PUBSUB_OWNER, "pubsub"))
    468 -            default = response.addElement("default")
    469 -            default.addChild(self._formFromConfiguration(options).toElement())
    470 -            return response
    471  
    472 -        if request.nodeType not in ('leaf', 'collection'):
    473 -            return defer.fail(error.StanzaError('not-acceptable'))
     532-        d = self.getDefaultConfiguration(request)
     533-        d.addCallback(toResponse)
     534-        return d
     535 
    474536+    def _toResponse_configureGet(self, options, resource, request):
    475537+        response = domish.Element((NS_PUBSUB_OWNER, "pubsub"))
     
    477539+        form = self._formFromConfiguration(resource, options)
    478540+        configure.addChild(form.toElement())
    479  
    480 -        d = self.getDefaultConfiguration(request)
    481 -        d.addCallback(toResponse)
    482 -        return d
    483 +        if request.nodeIdentifier:
    484 +            configure["node"] = request.nodeIdentifier
    485  
    486 +        return response
    487541 
    488542-    def _on_configureGet(self, request):
     
    492546-            form = self._formFromConfiguration(options)
    493547-            configure.addChild(form.toElement())
     548+        if request.nodeIdentifier:
     549+            configure["node"] = request.nodeIdentifier
    494550 
    495551-            if request.nodeIdentifier:
    496552-                configure["node"] = request.nodeIdentifier
    497 -
     553+        return response
     554 
    498555-            return response
    499 -
     556 
    500557-        d = self.getConfiguration(request)
    501558-        d.addCallback(toResponse)
     
    571628     def _createNotification(self, eventType, service, nodeIdentifier,
    572629                                   subscriber, subscriptions=None):
    573 @@ -1099,6 +1048,8 @@
     630@@ -1118,6 +1075,8 @@
    574631 
    575632         return message
     
    580637         for subscriber, subscriptions, items in notifications:
    581638             message = self._createNotification('items', service,
    582 @@ -1120,65 +1071,90 @@
     639@@ -1139,65 +1098,96 @@
    583640             self.send(message)
    584641 
     
    586643-    def getNodeInfo(self, requestor, service, nodeIdentifier):
    587644-        return None
    588 +
     645 
    589646+class PubSubResource(object):
    590 +
     647 
     648-    def getNodes(self, requestor, service):
     649-        return []
    591650+    implements(IPubSubResource)
    592 +
     651 
     652+    features = []
     653+    discoIdentity = disco.DiscoIdentity('pubsub',
     654+                                        'service',
     655+                                        'Publish-Subscribe Service')
     656 
     657-    def publish(self, request):
     658-        raise Unsupported('publish')
     659 
    593660+    def locateResource(self, request):
    594661+        return self
    595 +
    596 +
     662 
     663-    def subscribe(self, request):
     664-        raise Unsupported('subscribe')
     665 
    597666+    def getInfo(self, requestor, service, nodeIdentifier):
    598667+        return defer.succeed(None)
    599668 
    600  
    601      def getNodes(self, requestor, service):
    602          return []
    603  
    604  
    605 -    def publish(self, request):
    606 -        raise Unsupported('publish')
    607 -
    608 -
    609 -    def subscribe(self, request):
    610 -        raise Unsupported('subscribe')
    611 -
    612 -
    613669-    def unsubscribe(self, request):
    614670-        raise Unsupported('subscribe')
    615 -
     671 
    616672-
    617673-    def subscriptions(self, request):
     
    625681-    def create(self, request):
    626682-        raise Unsupported('create-nodes')
    627 -
    628 -
     683+    def getNodes(self, requestor, service, nodeIdentifier):
     684+        return defer.succeed([])
     685 
     686 
    629687     def getConfigurationOptions(self):
    630688         return {}
     
    633691-    def getDefaultConfiguration(self, request):
    634692-        raise Unsupported('retrieve-default')
    635 +    def pubsub_publish(self, request):
     693+    def publish(self, request):
    636694+        return defer.fail(Unsupported('publish'))
    637695 
     
    639697-    def getConfiguration(self, request):
    640698-        raise Unsupported('config-node')
    641 +    def pubsub_subscribe(self, request):
     699+    def subscribe(self, request):
    642700+        return defer.fail(Unsupported('subscribe'))
    643701 
     
    645703-    def setConfiguration(self, request):
    646704-        raise Unsupported('config-node')
    647 +    def pubsub_unsubscribe(self, request):
     705+    def unsubscribe(self, request):
    648706+        return defer.fail(Unsupported('subscribe'))
    649  
    650  
    651 -    def items(self, request):
     707+
     708+
     709+    def subscriptions(self, request):
     710+        return defer.fail(Unsupported('retrieve-subscriptions'))
     711+
     712+
     713+    def affiliations(self, request):
     714+        return defer.fail(Unsupported('retrieve-affiliations'))
     715+
     716+
     717+    def create(self, request):
     718+        return defer.fail(Unsupported('create-nodes'))
     719+
     720+
     721+    def default(self, request):
     722+        return defer.fail(Unsupported('retrieve-default'))
     723+
     724+
     725+    def configureGet(self, request):
     726+        return defer.fail(Unsupported('config-node'))
     727+
     728+
     729+    def configureSet(self, request):
     730+        return defer.fail(Unsupported('config-node'))
     731 
     732 
     733     def items(self, request):
    652734-        raise Unsupported('retrieve-items')
    653 +    def pubsub_subscriptions(self, request):
    654 +        return defer.fail(Unsupported('retrieve-subscriptions'))
    655  
    656  
    657 -    def retract(self, request):
     735+        return defer.fail(Unsupported('retrieve-items'))
     736 
     737 
     738     def retract(self, request):
    658739-        raise Unsupported('retract-items')
    659 +    def pubsub_affiliations(self, request):
    660 +        return defer.fail(Unsupported('retrieve-affiliations'))
    661  
    662  
    663 -    def purge(self, request):
     740+        return defer.fail(Unsupported('retract-items'))
     741 
     742 
     743     def purge(self, request):
    664744-        raise Unsupported('purge-nodes')
    665 +    def pubsub_create(self, request):
    666 +        return defer.fail(Unsupported('create-nodes'))
    667  
    668  
    669 -    def delete(self, request):
     745+        return defer.fail(Unsupported('purge-nodes'))
     746 
     747 
     748     def delete(self, request):
    670749-        raise Unsupported('delete-nodes')
    671 +    def pubsub_default(self, request):
    672 +        return defer.fail(Unsupported('retrieve-default'))
    673 +
    674 +
    675 +    def pubsub_configureGet(self, request):
    676 +        return defer.fail(Unsupported('config-node'))
    677 +
    678 +
    679 +    def pubsub_configureSet(self, request):
    680 +        return defer.fail(Unsupported('config-node'))
    681 +
    682 +
    683 +    def pubsub_items(self, request):
    684 +        return defer.fail(Unsupported('retrieve-items'))
    685 +
    686 +
    687 +    def pubsub_retract(self, request):
    688 +        return defer.fail(Unsupported('retract-items'))
    689 +
    690 +
    691 +    def pubsub_purge(self, request):
    692 +        return defer.fail(Unsupported('purge-nodes'))
    693 +
    694 +
    695 +    def pubsub_delete(self, request):
    696750+        return defer.fail(Unsupported('delete-nodes'))
    697751+
    698752+
    699 +    def pubsub_affiliationsGet(self, request):
     753+    def affiliationsGet(self, request):
    700754+        return defer.fail(Unsupported('modify-affiliations'))
    701755+
    702756+
    703 +    def pubsub_affiliationsSet(self, request):
     757+    def affiliationsSet(self, request):
    704758+        return defer.fail(Unsupported('modify-affiliations'))
    705759+
    706760+
    707 +    def pubsub_subscriptionsGet(self, request):
     761+    def subscriptionsGet(self, request):
    708762+        return defer.fail(Unsupported('manage-subscriptions'))
    709763+
    710764+
    711 +    def pubsub_subscriptionsSet(self, request):
     765+    def subscriptionsSet(self, request):
    712766+        return defer.fail(Unsupported('manage-subscriptions'))
    713 diff -r dc8ed1ff55d7 wokkel/test/test_pubsub.py
    714 --- a/wokkel/test/test_pubsub.py        Wed Mar 18 09:26:24 2009 +0100
    715 +++ b/wokkel/test/test_pubsub.py        Wed Mar 18 20:51:58 2009 +0100
    716 @@ -600,7 +600,8 @@
     767diff -r 2ea6196efcdc wokkel/test/test_pubsub.py
     768--- a/wokkel/test/test_pubsub.py        Wed Mar 25 18:14:07 2009 +0100
     769+++ b/wokkel/test/test_pubsub.py        Mon Mar 30 08:35:05 2009 +0200
     770@@ -13,7 +13,7 @@
     771 from twisted.words.protocols.jabber import error
     772 from twisted.words.protocols.jabber.jid import JID
     773 
     774-from wokkel import data_form, iwokkel, pubsub, shim
     775+from wokkel import data_form, disco, iwokkel, pubsub, shim
     776 from wokkel.generic import parseXml
     777 from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
     778 
     779@@ -1225,7 +1225,8 @@
    717780 
    718781     def setUp(self):
     
    724787 
    725788     def test_interface(self):
    726 @@ -694,8 +695,8 @@
    727              self.assertEqual([], request.items)
     789@@ -1263,19 +1264,120 @@
     790         Test getDiscoInfo calls getNodeInfo and returns some minimal info.
     791         """
     792         def cb(info):
     793-            self.assertEqual(2, len(info))
     794+            discoInfo = disco.DiscoInfo()
     795+            for item in info:
     796+                discoInfo.append(item)
     797+            self.assertIn(('pubsub', 'service'), discoInfo.identities)
     798+            self.assertIn(disco.NS_DISCO_ITEMS, discoInfo.features)
     799 
     800-        def getNodeInfo(requestor, target, nodeIdentifier):
     801-            return defer.succeed(None)
     802-
     803-        self.service.getNodeInfo = getNodeInfo
     804         d = self.service.getDiscoInfo(JID('user@example.org/home'),
     805                                       JID('pubsub.example.org'), '')
     806         d.addCallback(cb)
     807         return d
     808 
     809 
     810-    def test_onPublish(self):
     811+    def test_getDiscoInfoNodeType(self):
     812+        """
     813+        Test getDiscoInfo calls getNodeInfo and returns some minimal info.
     814+        """
     815+        def cb(info):
     816+            discoInfo = disco.DiscoInfo()
     817+            for item in info:
     818+                discoInfo.append(item)
     819+            self.assertIn(('pubsub', 'collection'), discoInfo.identities)
     820+
     821+        def getInfo(requestor, target, nodeIdentifier):
     822+            return defer.succeed({'type': 'collection',
     823+                                  'meta-data': {}})
     824+
     825+        self.resource.getInfo = getInfo
     826+        d = self.service.getDiscoInfo(JID('user@example.org/home'),
     827+                                      JID('pubsub.example.org'), '')
     828+        d.addCallback(cb)
     829+        return d
     830+
     831+
     832+    def test_getDiscoInfoResourceFeatures(self):
     833+        """
     834+        Test getDiscoInfo calls getNodeInfo and returns some minimal info.
     835+        """
     836+        def cb(info):
     837+            discoInfo = disco.DiscoInfo()
     838+            for item in info:
     839+                discoInfo.append(item)
     840+            self.assertIn('http://jabber.org/protocol/pubsub#publish',
     841+                          discoInfo.features)
     842+
     843+        self.resource.features = ['publish']
     844+        d = self.service.getDiscoInfo(JID('user@example.org/home'),
     845+                                      JID('pubsub.example.org'), '')
     846+        d.addCallback(cb)
     847+        return d
     848+
     849+
     850+    def test_getDiscoItemsRoot(self):
     851+        """
     852+        Test getDiscoItems on the root node.
     853+        """
     854+        def getNodes(requestor, service, nodeIdentifier):
     855+            return defer.succeed(['node1', 'node2'])
     856+
     857+        def cb(items):
     858+            self.assertEqual(2, len(items))
     859+            item1, item2 = items
     860+
     861+            self.assertEqual(JID('pubsub.example.org'), item1.entity)
     862+            self.assertEqual('node1', item1.nodeIdentifier)
     863+
     864+            self.assertEqual(JID('pubsub.example.org'), item2.entity)
     865+            self.assertEqual('node2', item2.nodeIdentifier)
     866+
     867+        self.resource.getNodes = getNodes
     868+        d = self.service.getDiscoItems(JID('user@example.org/home'),
     869+                                       JID('pubsub.example.org'),
     870+                                       '')
     871+        d.addCallback(cb)
     872+        return d
     873+
     874+
     875+    def test_getDiscoItemsRootHideNodes(self):
     876+        """
     877+        Test getDiscoItems on the root node.
     878+        """
     879+        def getNodes(requestor, service, nodeIdentifier):
     880+            raise Exception("Unexpected call to getNodes")
     881+
     882+        def cb(items):
     883+            self.assertEqual([], items)
     884+
     885+        self.service.hideNodes = True
     886+        self.resource.getNodes = getNodes
     887+        d = self.service.getDiscoItems(JID('user@example.org/home'),
     888+                                       JID('pubsub.example.org'),
     889+                                       '')
     890+        d.addCallback(cb)
     891+        return d
     892+
     893+
     894+    def test_getDiscoItemsNonRoot(self):
     895+        """
     896+        Test getDiscoItems on a non-root node.
     897+        """
     898+        def getNodes(requestor, service, nodeIdentifier):
     899+            return defer.succeed(['node1', 'node2'])
     900+
     901+        def cb(items):
     902+            self.assertEqual(2, len(items))
     903+
     904+        self.resource.getNodes = getNodes
     905+        d = self.service.getDiscoItems(JID('user@example.org/home'),
     906+                                       JID('pubsub.example.org'),
     907+                                       'test')
     908+        d.addCallback(cb)
     909+        return d
     910+
     911+
     912+    def test_on_publish(self):
     913         """
     914         A publish request should result in L{PubSubService.publish} being
     915         called.
     916@@ -1293,12 +1395,12 @@
     917         def publish(request):
    728918             return defer.succeed(None)
    729919 
    730920-        self.service.publish = publish
    731921-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    732 +        self.resource.pubsub_publish = publish
     922+        self.resource.publish = publish
    733923+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    734924         return self.handleRequest(xml)
    735925 
    736926 
    737 @@ -722,8 +723,8 @@
    738              self.assertEqual(u'item2', request.items[1]["id"])
    739              return defer.succeed(None)
    740  
    741 -        self.service.publish = publish
    742 -        verify.verifyObject(iwokkel.IPubSubService, self.service)
    743 +        self.resource.pubsub_publish = publish
    744 +        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    745          return self.handleRequest(xml)
    746  
    747  
    748 @@ -759,8 +760,8 @@
     927-    def test_onSubscribe(self):
     928+    def test_on_subscribe(self):
     929         """
     930         A successful subscription should return the current subscription.
     931         """
     932@@ -1326,14 +1428,14 @@
    749933             self.assertEqual('user@example.org/Home', subscription['jid'])
    750934             self.assertEqual('subscribed', subscription['subscription'])
     
    752936-        self.service.subscribe = subscribe
    753937-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    754 +        self.resource.pubsub_subscribe = subscribe
     938+        self.resource.subscribe = subscribe
    755939+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    756940         d = self.handleRequest(xml)
    757941         d.addCallback(cb)
    758942         return d
    759 @@ -789,8 +790,8 @@
     943 
     944 
     945-    def test_onSubscribeEmptyNode(self):
     946+    def test_on_subscribeEmptyNode(self):
     947         """
     948         A successful subscription on root node should return no node attribute.
     949         """
     950@@ -1355,14 +1457,14 @@
    760951         def cb(element):
    761952             self.assertFalse(element.subscription.hasAttribute('node'))
     
    763954-        self.service.subscribe = subscribe
    764955-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    765 +        self.resource.pubsub_subscribe = subscribe
     956+        self.resource.subscribe = subscribe
    766957+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    767958         d = self.handleRequest(xml)
    768959         d.addCallback(cb)
    769960         return d
    770 @@ -820,8 +821,8 @@
     961 
     962 
     963-    def test_onUnsubscribe(self):
     964+    def test_on_unsubscribe(self):
     965         """
     966         A successful unsubscription should return an empty response.
     967         """
     968@@ -1382,14 +1484,14 @@
    771969         def cb(element):
    772970             self.assertIdentical(None, element)
     
    774972-        self.service.unsubscribe = unsubscribe
    775973-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    776 +        self.resource.pubsub_unsubscribe = unsubscribe
     974+        self.resource.unsubscribe = unsubscribe
    777975+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    778976         d = self.handleRequest(xml)
    779977         d.addCallback(cb)
    780978         return d
    781 @@ -914,8 +915,8 @@
    782                                                 'subscribed')
    783              return defer.succeed([subscription])
    784  
     979 
     980 
     981-    def test_onOptionsGet(self):
     982+    def test_on_optionsGet(self):
     983         """
     984         Getting subscription options is not supported.
     985         """
     986@@ -1414,7 +1516,7 @@
     987         return d
     988 
     989 
     990-    def test_onOptionsSet(self):
     991+    def test_on_optionsSet(self):
     992         """
     993         Setting subscription options is not supported.
     994         """
     995@@ -1446,7 +1548,7 @@
     996         return d
     997 
     998 
     999-    def test_onSubscriptions(self):
     1000+    def test_on_subscriptions(self):
     1001         """
     1002         A subscriptions request should result in
     1003         L{PubSubService.subscriptions} being called and the result prepared
     1004@@ -1462,6 +1564,11 @@
     1005         </iq>
     1006         """
     1007 
     1008+        def subscriptions(request):
     1009+            subscription = pubsub.Subscription('test', JID('user@example.org'),
     1010+                                               'subscribed')
     1011+            return defer.succeed([subscription])
     1012+
     1013         def cb(element):
     1014             self.assertEqual('pubsub', element.name)
     1015             self.assertEqual(NS_PUBSUB, element.uri)
     1016@@ -1475,20 +1582,14 @@
     1017             self.assertEqual('test', subscription['node'])
     1018             self.assertEqual('subscribed', subscription['subscription'])
     1019 
     1020-
     1021-        def subscriptions(request):
     1022-            subscription = pubsub.Subscription('test', JID('user@example.org'),
     1023-                                               'subscribed')
     1024-            return defer.succeed([subscription])
     1025-
    7851026-        self.service.subscriptions = subscriptions
    7861027-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    787 +        self.resource.pubsub_subscriptions = subscriptions
     1028+        self.resource.subscriptions = subscriptions
    7881029+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    7891030         d = self.handleRequest(xml)
    7901031         d.addCallback(cb)
    7911032         return d
    792 @@ -956,8 +957,8 @@
    793              affiliation = ('test', 'owner')
    794              return defer.succeed([affiliation])
    795  
     1033 
     1034 
     1035-    def test_onAffiliations(self):
     1036+    def test_on_affiliations(self):
     1037         """
     1038         A subscriptions request should result in
     1039         L{PubSubService.affiliations} being called and the result prepared
     1040@@ -1504,6 +1605,10 @@
     1041         </iq>
     1042         """
     1043 
     1044+        def affiliations(request):
     1045+            affiliation = ('test', 'owner')
     1046+            return defer.succeed([affiliation])
     1047+
     1048         def cb(element):
     1049             self.assertEqual('pubsub', element.name)
     1050             self.assertEqual(NS_PUBSUB, element.uri)
     1051@@ -1516,19 +1621,14 @@
     1052             self.assertEqual('test', affiliation['node'])
     1053             self.assertEqual('owner', affiliation['affiliation'])
     1054 
     1055-
     1056-        def affiliations(request):
     1057-            affiliation = ('test', 'owner')
     1058-            return defer.succeed([affiliation])
     1059-
    7961060-        self.service.affiliations = affiliations
    7971061-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    798 +        self.resource.pubsub_affiliations = affiliations
     1062+        self.resource.affiliations = affiliations
    7991063+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    8001064         d = self.handleRequest(xml)
    8011065         d.addCallback(cb)
    8021066         return d
    803 @@ -986,8 +987,8 @@
     1067 
     1068 
     1069-    def test_onCreate(self):
     1070+    def test_on_create(self):
     1071         """
     1072         Replies to create node requests don't return the created node.
     1073         """
     1074@@ -1548,14 +1648,14 @@
    8041075         def cb(element):
    8051076             self.assertIdentical(None, element)
     
    8071078-        self.service.create = create
    8081079-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    809 +        self.resource.pubsub_create = create
     1080+        self.resource.create = create
    8101081+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    8111082         d = self.handleRequest(xml)
    8121083         d.addCallback(cb)
    8131084         return d
    814 @@ -1017,8 +1018,8 @@
     1085 
     1086 
     1087-    def test_onCreateChanged(self):
     1088+    def test_on_createChanged(self):
     1089         """
     1090         Replies to create node requests return the created node if changed.
     1091         """
     1092@@ -1579,14 +1679,14 @@
    8151093             self.assertEqual(u'myrenamednode',
    8161094                              element.create.getAttribute('node'))
     
    8181096-        self.service.create = create
    8191097-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    820 +        self.resource.pubsub_create = create
     1098+        self.resource.create = create
    8211099+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    8221100         d = self.handleRequest(xml)
    8231101         d.addCallback(cb)
    8241102         return d
    825 @@ -1048,8 +1049,8 @@
     1103 
     1104 
     1105-    def test_onCreateInstant(self):
     1106+    def test_on_createInstant(self):
     1107         """
     1108         Replies to create instant node requests return the created node.
     1109         """
     1110@@ -1609,14 +1709,14 @@
    8261111             self.assertEqual(NS_PUBSUB, element.create.uri)
    8271112             self.assertEqual(u'random', element.create.getAttribute('node'))
     
    8291114-        self.service.create = create
    8301115-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    831 +        self.resource.pubsub_create = create
     1116+        self.resource.create = create
    8321117+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    8331118         d = self.handleRequest(xml)
    8341119         d.addCallback(cb)
    8351120         return d
    836 @@ -1093,9 +1094,9 @@
     1121 
     1122 
     1123-    def test_onDefault(self):
     1124+    def test_on_default(self):
     1125         """
     1126         A default request should result in
     1127         L{PubSubService.getDefaultConfiguration} being called.
     1128@@ -1641,7 +1741,7 @@
     1129                      "label": "Deliver payloads with event notifications"}
     1130                 }
     1131 
     1132-        def getDefaultConfiguration(request):
     1133+        def default(request):
     1134             return defer.succeed({})
     1135 
     1136         def cb(element):
     1137@@ -1651,15 +1751,15 @@
    8371138             form = data_form.Form.fromElement(element.default.x)
    8381139             self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
     
    8421143-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    8431144+        self.resource.getConfigurationOptions = getConfigurationOptions
    844 +        self.resource.pubsub_default = getDefaultConfiguration
     1145+        self.resource.default = default
    8451146+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    8461147         d = self.handleRequest(xml)
    8471148         d.addCallback(cb)
    8481149         return d
    849 @@ -1143,9 +1144,9 @@
    850              form = data_form.Form.fromElement(element.default.x)
    851              self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
     1150 
     1151 
     1152-    def test_onDefaultCollection(self):
     1153+    def test_on_defaultCollection(self):
     1154         """
     1155         Responses to default requests should depend on passed node type.
     1156         """
     1157@@ -1690,19 +1790,19 @@
     1158                      "label": "Deliver payloads with event notifications"}
     1159                 }
     1160 
     1161-        def getDefaultConfiguration(request):
     1162+        def default(request):
     1163             return defer.succeed({})
    8521164 
    8531165-        self.service.getConfigurationOptions = getConfigurationOptions
     
    8551167-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    8561168+        self.resource.getConfigurationOptions = getConfigurationOptions
    857 +        self.resource.pubsub_default = getDefaultConfiguration
    858 +        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    859          d = self.handleRequest(xml)
    860          d.addCallback(cb)
    861          return d
    862 @@ -1182,8 +1183,8 @@
     1169+        self.resource.default = default
     1170+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
     1171         return self.handleRequest(xml)
     1172 
     1173 
     1174-    def test_onDefaultUnknownNodeType(self):
     1175+    def test_on_defaultUnknownNodeType(self):
     1176         """
     1177         A default request should result in
     1178-        L{PubSubService.getDefaultConfiguration} being called.
     1179+        L{PubSubResource.default} being called.
     1180         """
     1181 
     1182         xml = """
     1183@@ -1724,24 +1824,25 @@
     1184         </iq>
     1185         """
     1186 
     1187-        def getDefaultConfiguration(request):
     1188+        def default(request):
     1189             self.fail("Unexpected call to getConfiguration")
     1190 
    8631191         def cb(result):
    8641192             self.assertEquals('not-acceptable', result.condition)
     
    8661194-        self.service.getDefaultConfiguration = getDefaultConfiguration
    8671195-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    868 +        self.resource.pubsub_default = getDefaultConfiguration
     1196+        self.resource.default = default
    8691197+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    8701198         d = self.handleRequest(xml)
    8711199         self.assertFailure(d, error.StanzaError)
    8721200         d.addCallback(cb)
    873 @@ -1257,9 +1258,9 @@
     1201         return d
     1202 
     1203 
     1204-    def test_onConfigureGet(self):
     1205+    def test_on_configureGet(self):
     1206         """
     1207-        On a node configuration get request L{PubSubService.getConfiguration}
     1208-        is called and results in a data form with the configuration.
     1209+        On a node configuration get
     1210+        requestL{PubSubResource.configureGet} is called and results in a
     1211+        data form with the configuration.
     1212         """
     1213 
     1214         xml = """
     1215@@ -1766,7 +1867,7 @@
     1216                      "label": "Owner of the node"}
     1217                 }
     1218 
     1219-        def getConfiguration(request):
     1220+        def configureGet(request):
     1221             return defer.succeed({'pubsub#deliver_payloads': '0',
     1222                                   'pubsub#persist_items': '1',
     1223                                   'pubsub#owner': JID('user@example.org'),
     1224@@ -1800,19 +1901,18 @@
     1225 
    8741226             self.assertNotIn('x-myfield', fields)
    8751227 
    876  
     1228-
    8771229-        self.service.getConfigurationOptions = getConfigurationOptions
    8781230-        self.service.getConfiguration = getConfiguration
    8791231-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    8801232+        self.resource.getConfigurationOptions = getConfigurationOptions
    881 +        self.resource.pubsub_configureGet = getConfiguration
     1233+        self.resource.configureGet = configureGet
    8821234+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    8831235         d = self.handleRequest(xml)
    8841236         d.addCallback(cb)
    8851237         return d
    886 @@ -1306,9 +1307,9 @@
     1238 
     1239 
     1240-    def test_onConfigureSet(self):
     1241+    def test_on_configureSet(self):
     1242         """
     1243         On a node configuration set request the Data Form is parsed and
     1244-        L{PubSubService.setConfiguration} is called with the passed options.
     1245+        L{PubSubResource.configureSet} is called with the passed options.
     1246         """
     1247 
     1248         xml = """
     1249@@ -1842,21 +1942,21 @@
     1250                      "label": "Deliver payloads with event notifications"}
     1251                 }
     1252 
     1253-        def setConfiguration(request):
     1254+        def configureSet(request):
     1255             self.assertEqual({'pubsub#deliver_payloads': False,
    8871256                               'pubsub#persist_items': True}, request.options)
    8881257             return defer.succeed(None)
     
    8921261-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    8931262+        self.resource.getConfigurationOptions = getConfigurationOptions
    894 +        self.resource.pubsub_configureSet = setConfiguration
     1263+        self.resource.configureSet = configureSet
    8951264+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    8961265         return self.handleRequest(xml)
    8971266 
    8981267 
    899 @@ -1336,8 +1337,8 @@
    900          def setConfiguration(request):
     1268-    def test_onConfigureSetCancel(self):
     1269+    def test_on_configureSetCancel(self):
     1270         """
     1271-        The node configuration is cancelled, L{PubSubService.setConfiguration}
     1272-        not called.
     1273+        The node configuration is cancelled,
     1274+        L{PubSubResource.configureSet} not called.
     1275         """
     1276 
     1277         xml = """
     1278@@ -1874,15 +1974,15 @@
     1279         </iq>
     1280         """
     1281 
     1282-        def setConfiguration(request):
     1283+        def configureSet(request):
    9011284             self.fail("Unexpected call to setConfiguration")
    9021285 
    9031286-        self.service.setConfiguration = setConfiguration
    9041287-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    905 +        self.resource.pubsub_configureSet = setConfiguration
     1288+        self.resource.configureSet = configureSet
    9061289+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    9071290         return self.handleRequest(xml)
    9081291 
    9091292 
    910 @@ -1377,9 +1378,9 @@
     1293-    def test_onConfigureSetIgnoreUnknown(self):
     1294+    def test_on_configureSetIgnoreUnknown(self):
     1295         """
     1296         On a node configuration set request unknown fields should be ignored.
     1297         """
     1298@@ -1914,17 +2014,17 @@
     1299                      "label": "Deliver payloads with event notifications"}
     1300                 }
     1301 
     1302-        def setConfiguration(request):
     1303+        def configureSet(request):
    9111304             self.assertEquals(['pubsub#deliver_payloads'],
    9121305                               request.options.keys())
     
    9161309-        verify.verifyObject(iwokkel.IPubSubService, self.service)
    9171310+        self.resource.getConfigurationOptions = getConfigurationOptions
    918 +        self.resource.pubsub_configureSet = setConfiguration
     1311+        self.resource.configureSet = configureSet
    9191312+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    9201313         return self.handleRequest(xml)
    9211314 
    9221315 
    923 @@ -1445,7 +1446,8 @@
     1316-    def test_onConfigureSetBadFormType(self):
     1317+    def test_on_configureSetBadFormType(self):
     1318         """
     1319         On a node configuration set request unknown fields should be ignored.
     1320         """
     1321@@ -1955,7 +2055,7 @@
     1322         return d
     1323 
     1324 
     1325-    def test_onItems(self):
     1326+    def test_on_items(self):
     1327         """
     1328         On a items request, return all items for the given node.
     1329         """
     1330@@ -1981,16 +2081,17 @@
    9241331             self.assertEqual(NS_PUBSUB, item.uri)
    9251332             self.assertEqual('current', item['id'])
    9261333 
    9271334-        self.service.items = items
    928 +        self.resource.pubsub_items = items
     1335+        self.resource.items = items
    9291336+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    9301337         d = self.handleRequest(xml)
    9311338         d.addCallback(cb)
    9321339         return d
    933 @@ -1476,7 +1478,8 @@
    934              self.assertEqual(['item1', 'item2'], request.itemIdentifiers)
     1340 
     1341 
     1342-    def test_onRetract(self):
     1343+    def test_on_retract(self):
     1344         """
     1345-        A retract request should result in L{PubSubService.retract} being
     1346-        called.
     1347+        A retract request should result in L{PubSubResource.retract}
     1348+        being called.
     1349         """
     1350 
     1351         xml = """
     1352@@ -2008,13 +2109,14 @@
     1353         def retract(request):
    9351354             return defer.succeed(None)
    9361355 
    9371356-        self.service.retract = retract
    938 +        self.resource.pubsub_retract = retract
     1357+        self.resource.retract = retract
    9391358+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    9401359         return self.handleRequest(xml)
    9411360 
    9421361 
    943 @@ -1501,7 +1504,8 @@
    944              self.assertEqual('test', request.nodeIdentifier)
     1362-    def test_onPurge(self):
     1363+    def test_on_purge(self):
     1364         """
     1365-        A purge request should result in L{PubSubService.purge} being
     1366+        A purge request should result in L{PubSubResource.purge} being
     1367         called.
     1368         """
     1369 
     1370@@ -2030,13 +2132,14 @@
     1371         def purge(request):
    9451372             return defer.succeed(None)
    9461373 
    9471374-        self.service.purge = purge
    948 +        self.resource.pubsub_purge = purge
     1375+        self.resource.purge = purge
    9491376+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    9501377         return self.handleRequest(xml)
    9511378 
    9521379 
    953 @@ -1526,7 +1530,8 @@
    954              self.assertEqual('test', request.nodeIdentifier)
     1380-    def test_onDelete(self):
     1381+    def test_on_delete(self):
     1382         """
     1383-        A delete request should result in L{PubSubService.delete} being
     1384+        A delete request should result in L{PubSubResource.delete} being
     1385         called.
     1386         """
     1387 
     1388@@ -2052,7 +2155,8 @@
     1389         def delete(request):
    9551390             return defer.succeed(None)
    9561391 
    9571392-        self.service.delete = delete
    958 +        self.resource.pubsub_delete = delete
     1393+        self.resource.delete = delete
    9591394+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
    9601395         return self.handleRequest(xml)
    9611396 
    9621397 
    963 @@ -1687,7 +1692,7 @@
    964  
     1398@@ -2103,7 +2207,7 @@
     1399         self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
     1400 
     1401 
     1402-    def test_onSubscriptionsGet(self):
     1403+    def test_on_subscriptionsGet(self):
     1404         """
     1405         Getting subscription options is not supported.
     1406         """
     1407@@ -2130,7 +2234,7 @@
     1408         return d
     1409 
     1410 
     1411-    def test_onSubscriptionsSet(self):
     1412+    def test_on_subscriptionsSet(self):
     1413         """
     1414         Setting subscription options is not supported.
     1415         """
     1416@@ -2157,7 +2261,7 @@
     1417         return d
     1418 
     1419 
     1420-    def test_onAffiliationsGet(self):
     1421+    def test_on_affiliationsGet(self):
     1422         """
     1423         Getting subscription options is not supported.
     1424         """
     1425@@ -2184,7 +2288,7 @@
     1426         return d
     1427 
     1428 
     1429-    def test_onAffiliationsSet(self):
     1430+    def test_on_affiliationsSet(self):
     1431         """
     1432         Setting subscription options is not supported.
     1433         """
     1434@@ -2211,18 +2315,38 @@
     1435         return d
     1436 
     1437 
     1438+
     1439+class PubSubResourceTest(unittest.TestCase):
     1440+
     1441+    def setUp(self):
     1442+        self.resource = pubsub.PubSubResource()
     1443+
     1444+
     1445+    def test_interface(self):
     1446+        """
     1447+        Do instances of L{pubsub.PubSubResource} provide L{iwokkel.IPubSubResource}?
     1448+        """
     1449+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
     1450+
     1451+
     1452+    def test_getNodes(self):
     1453+        """
     1454+        Default getNodes returns an empty list.
     1455+        """
     1456+        def cb(nodes):
     1457+            self.assertEquals([], nodes)
     1458+
     1459+        d = self.resource.getNodes(JID('user@example.org/home'),
     1460+                                   JID('pubsub.example.org'),
     1461+                                   '')
     1462+        d.addCallback(cb)
     1463+        return d
     1464+
     1465+
    9651466     def test_publish(self):
    9661467         """
    9671468-        Non-overridden L{PubSubService.publish} yields unsupported error.
    968 +        Non-overridden L{PubSubResource.publish} yields unsupported error.
    969          """
    970  
    971          xml = """
     1469-        """
     1470-
     1471-        xml = """
     1472-        <iq type='set' to='pubsub.example.org'
     1473-                       from='user@example.org'>
     1474-          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1475-            <publish node='mynode'/>
     1476-          </pubsub>
     1477-        </iq>
     1478+        Non-overridden L{PubSubResource.publish} yields unsupported
     1479+        error.
     1480         """
     1481 
     1482         def cb(result):
     1483@@ -2231,7 +2355,7 @@
     1484             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1485             self.assertEquals('publish', result.appCondition['feature'])
     1486 
     1487-        d = self.handleRequest(xml)
     1488+        d = self.resource.publish(pubsub.PubSubRequest())
     1489         self.assertFailure(d, error.StanzaError)
     1490         d.addCallback(cb)
     1491         return d
     1492@@ -2239,16 +2363,7 @@
     1493 
     1494     def test_subscribe(self):
     1495         """
     1496-        Non-overridden L{PubSubService.subscribe} yields unsupported error.
     1497-        """
     1498-
     1499-        xml = """
     1500-        <iq type='set' to='pubsub.example.org'
     1501-                       from='user@example.org'>
     1502-          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1503-            <subscribe node='test' jid='user@example.org/Home'/>
     1504-          </pubsub>
     1505-        </iq>
     1506+        Non-overridden subscriptions yields unsupported error.
     1507         """
     1508 
     1509         def cb(result):
     1510@@ -2257,7 +2372,7 @@
     1511             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1512             self.assertEquals('subscribe', result.appCondition['feature'])
     1513 
     1514-        d = self.handleRequest(xml)
     1515+        d = self.resource.subscribe(pubsub.PubSubRequest())
     1516         self.assertFailure(d, error.StanzaError)
     1517         d.addCallback(cb)
     1518         return d
     1519@@ -2265,16 +2380,7 @@
     1520 
     1521     def test_unsubscribe(self):
     1522         """
     1523-        Non-overridden L{PubSubService.unsubscribe} yields unsupported error.
     1524-        """
     1525-
     1526-        xml = """
     1527-        <iq type='set' to='pubsub.example.org'
     1528-                       from='user@example.org'>
     1529-          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1530-            <unsubscribe node='test' jid='user@example.org/Home'/>
     1531-          </pubsub>
     1532-        </iq>
     1533+        Non-overridden unsubscribe yields unsupported error.
     1534         """
     1535 
     1536         def cb(result):
     1537@@ -2283,7 +2389,7 @@
     1538             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1539             self.assertEquals('subscribe', result.appCondition['feature'])
     1540 
     1541-        d = self.handleRequest(xml)
     1542+        d = self.resource.unsubscribe(pubsub.PubSubRequest())
     1543         self.assertFailure(d, error.StanzaError)
     1544         d.addCallback(cb)
     1545         return d
     1546@@ -2291,16 +2397,7 @@
     1547 
     1548     def test_subscriptions(self):
     1549         """
     1550-        Non-overridden L{PubSubService.subscriptions} yields unsupported error.
     1551-        """
     1552-
     1553-        xml = """
     1554-        <iq type='get' to='pubsub.example.org'
     1555-                       from='user@example.org'>
     1556-          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1557-            <subscriptions/>
     1558-          </pubsub>
     1559-        </iq>
     1560+        Non-overridden subscriptions yields unsupported error.
     1561         """
     1562 
     1563         def cb(result):
     1564@@ -2310,7 +2407,7 @@
     1565             self.assertEquals('retrieve-subscriptions',
     1566                               result.appCondition['feature'])
     1567 
     1568-        d = self.handleRequest(xml)
     1569+        d = self.resource.subscriptions(pubsub.PubSubRequest())
     1570         self.assertFailure(d, error.StanzaError)
     1571         d.addCallback(cb)
     1572         return d
     1573@@ -2318,16 +2415,7 @@
     1574 
     1575     def test_affiliations(self):
     1576         """
     1577-        Non-overridden L{PubSubService.affiliations} yields unsupported error.
     1578-        """
     1579-
     1580-        xml = """
     1581-        <iq type='get' to='pubsub.example.org'
     1582-                       from='user@example.org'>
     1583-          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1584-            <affiliations/>
     1585-          </pubsub>
     1586-        </iq>
     1587+        Non-overridden affiliations yields unsupported error.
     1588         """
     1589 
     1590         def cb(result):
     1591@@ -2337,7 +2425,7 @@
     1592             self.assertEquals('retrieve-affiliations',
     1593                               result.appCondition['feature'])
     1594 
     1595-        d = self.handleRequest(xml)
     1596+        d = self.resource.affiliations(pubsub.PubSubRequest())
     1597         self.assertFailure(d, error.StanzaError)
     1598         d.addCallback(cb)
     1599         return d
     1600@@ -2345,16 +2433,7 @@
     1601 
     1602     def test_create(self):
     1603         """
     1604-        Non-overridden L{PubSubService.create} yields unsupported error.
     1605-        """
     1606-
     1607-        xml = """
     1608-        <iq type='set' to='pubsub.example.org'
     1609-                       from='user@example.org'>
     1610-          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1611-            <create node='mynode'/>
     1612-          </pubsub>
     1613-        </iq>
     1614+        Non-overridden create yields unsupported error.
     1615         """
     1616 
     1617         def cb(result):
     1618@@ -2363,87 +2442,51 @@
     1619             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1620             self.assertEquals('create-nodes', result.appCondition['feature'])
     1621 
     1622-        d = self.handleRequest(xml)
     1623+        d = self.resource.create(pubsub.PubSubRequest())
     1624         self.assertFailure(d, error.StanzaError)
     1625         d.addCallback(cb)
     1626         return d
     1627 
     1628 
     1629-    def test_getDefaultConfiguration(self):
     1630+    def test_default(self):
     1631         """
     1632-        Non-overridden L{PubSubService.getDefaultConfiguration} yields
     1633-        unsupported error.
     1634-        """
     1635-
     1636-        xml = """
     1637-        <iq type='get' to='pubsub.example.org'
     1638-                       from='user@example.org'>
     1639-          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
     1640-            <default/>
     1641-          </pubsub>
     1642-        </iq>
     1643+        Non-overridden default yields unsupported error.
     1644         """
     1645 
     1646         def cb(result):
     1647             self.assertEquals('feature-not-implemented', result.condition)
     1648             self.assertEquals('unsupported', result.appCondition.name)
     1649             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1650-            self.assertEquals('retrieve-default', result.appCondition['feature'])
     1651+            self.assertEquals('retrieve-default',
     1652+                              result.appCondition['feature'])
     1653 
     1654-        d = self.handleRequest(xml)
     1655+        d = self.resource.default(pubsub.PubSubRequest())
     1656         self.assertFailure(d, error.StanzaError)
     1657         d.addCallback(cb)
     1658         return d
     1659 
     1660 
     1661-    def test_getConfiguration(self):
     1662+    def test_configureGet(self):
     1663         """
     1664-        Non-overridden L{PubSubService.getConfiguration} yields unsupported
     1665+        Non-overridden configureGet yields unsupported
     1666         error.
     1667         """
     1668 
     1669-        xml = """
     1670-        <iq type='get' to='pubsub.example.org'
     1671-                       from='user@example.org'>
     1672-          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
     1673-            <configure/>
     1674-          </pubsub>
     1675-        </iq>
     1676-        """
     1677-
     1678         def cb(result):
     1679             self.assertEquals('feature-not-implemented', result.condition)
     1680             self.assertEquals('unsupported', result.appCondition.name)
     1681             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1682             self.assertEquals('config-node', result.appCondition['feature'])
     1683 
     1684-        d = self.handleRequest(xml)
     1685+        d = self.resource.configureGet(pubsub.PubSubRequest())
     1686         self.assertFailure(d, error.StanzaError)
     1687         d.addCallback(cb)
     1688         return d
     1689 
     1690 
     1691-    def test_setConfiguration(self):
     1692+    def test_configureSet(self):
     1693         """
     1694-        Non-overridden L{PubSubService.setConfiguration} yields unsupported
     1695-        error.
     1696-        """
     1697-
     1698-        xml = """
     1699-        <iq type='set' to='pubsub.example.org'
     1700-                       from='user@example.org'>
     1701-          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
     1702-            <configure node='test'>
     1703-              <x xmlns='jabber:x:data' type='submit'>
     1704-                <field var='FORM_TYPE' type='hidden'>
     1705-                  <value>http://jabber.org/protocol/pubsub#node_config</value>
     1706-                </field>
     1707-                <field var='pubsub#deliver_payloads'><value>0</value></field>
     1708-                <field var='pubsub#persist_items'><value>1</value></field>
     1709-              </x>
     1710-            </configure>
     1711-          </pubsub>
     1712-        </iq>
     1713+        Non-overridden configureSet yields unsupported error.
     1714         """
     1715 
     1716         def cb(result):
     1717@@ -2452,7 +2495,7 @@
     1718             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1719             self.assertEquals('config-node', result.appCondition['feature'])
     1720 
     1721-        d = self.handleRequest(xml)
     1722+        d = self.resource.configureSet(pubsub.PubSubRequest())
     1723         self.assertFailure(d, error.StanzaError)
     1724         d.addCallback(cb)
     1725         return d
     1726@@ -2460,15 +2503,7 @@
     1727 
     1728     def test_items(self):
     1729         """
     1730-        Non-overridden L{PubSubService.items} yields unsupported error.
     1731-        """
     1732-        xml = """
     1733-        <iq type='get' to='pubsub.example.org'
     1734-                       from='user@example.org'>
     1735-          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1736-            <items node='test'/>
     1737-          </pubsub>
     1738-        </iq>
     1739+        Non-overridden items yields unsupported error.
     1740         """
     1741 
     1742         def cb(result):
     1743@@ -2477,7 +2512,7 @@
     1744             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1745             self.assertEquals('retrieve-items', result.appCondition['feature'])
     1746 
     1747-        d = self.handleRequest(xml)
     1748+        d = self.resource.items(pubsub.PubSubRequest())
     1749         self.assertFailure(d, error.StanzaError)
     1750         d.addCallback(cb)
     1751         return d
     1752@@ -2485,18 +2520,7 @@
     1753 
     1754     def test_retract(self):
     1755         """
     1756-        Non-overridden L{PubSubService.retract} yields unsupported error.
     1757-        """
     1758-        xml = """
     1759-        <iq type='set' to='pubsub.example.org'
     1760-                       from='user@example.org'>
     1761-          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1762-            <retract node='test'>
     1763-              <item id='item1'/>
     1764-              <item id='item2'/>
     1765-            </retract>
     1766-          </pubsub>
     1767-        </iq>
     1768+        Non-overridden retract yields unsupported error.
     1769         """
     1770 
     1771         def cb(result):
     1772@@ -2505,7 +2529,7 @@
     1773             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1774             self.assertEquals('retract-items', result.appCondition['feature'])
     1775 
     1776-        d = self.handleRequest(xml)
     1777+        d = self.resource.retract(pubsub.PubSubRequest())
     1778         self.assertFailure(d, error.StanzaError)
     1779         d.addCallback(cb)
     1780         return d
     1781@@ -2513,15 +2537,7 @@
     1782 
     1783     def test_purge(self):
     1784         """
     1785-        Non-overridden L{PubSubService.purge} yields unsupported error.
     1786-        """
     1787-        xml = """
     1788-        <iq type='set' to='pubsub.example.org'
     1789-                       from='user@example.org'>
     1790-          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
     1791-            <purge node='test'/>
     1792-          </pubsub>
     1793-        </iq>
     1794+        Non-overridden purge yields unsupported error.
     1795         """
     1796 
     1797         def cb(result):
     1798@@ -2530,7 +2546,7 @@
     1799             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1800             self.assertEquals('purge-nodes', result.appCondition['feature'])
     1801 
     1802-        d = self.handleRequest(xml)
     1803+        d = self.resource.purge(pubsub.PubSubRequest())
     1804         self.assertFailure(d, error.StanzaError)
     1805         d.addCallback(cb)
     1806         return d
     1807@@ -2538,15 +2554,7 @@
     1808 
     1809     def test_delete(self):
     1810         """
     1811-        Non-overridden L{PubSubService.delete} yields unsupported error.
     1812-        """
     1813-        xml = """
     1814-        <iq type='set' to='pubsub.example.org'
     1815-                       from='user@example.org'>
     1816-          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
     1817-            <delete node='test'/>
     1818-          </pubsub>
     1819-        </iq>
     1820+        Non-overridden delete yields unsupported error.
     1821         """
     1822 
     1823         def cb(result):
     1824@@ -2555,7 +2563,7 @@
     1825             self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
     1826             self.assertEquals('delete-nodes', result.appCondition['feature'])
     1827 
     1828-        d = self.handleRequest(xml)
     1829+        d = self.resource.delete(pubsub.PubSubRequest())
     1830         self.assertFailure(d, error.StanzaError)
     1831         d.addCallback(cb)
     1832         return d
Note: See TracChangeset for help on using the changeset viewer.