Commits

Olemis Lang committed 9435b3d

BH RPC : Functional testers for JSON-RPC over HTTP (auth)

Comments (0)

Files changed (3)

 
 from setuptools import setup, find_packages
 
+test_deps = ['jsonrpclib', 'twill',]
 try :
   import crypt
 except ImportError :
-  test_deps = ['twill', 'fcrypt']
-else :
-  test_deps = ['twill']
+  test_deps.append('fcrypt')
 
 if sys.version_info[:2] < (2, 7):
     test_deps.append('unittest2')

trunk/tracrpc/tests/__init__.py

 Contains modifications for Apache(TM) Bloodhound compatibility
 """
 
-import abc
 import os
 import sys
 import time
 import urllib2
 import xmlrpclib
 
+import jsonrpclib.jsonrpc
+
 if sys.version_info[:2] < (2, 7):
     import unittest2 as unittest
 else:
     class RpcTesterMixin(functional.OpenerDirectorMixin):
         """RPC extensions for functional testers.
         """
-        __metaclass__ = abc.ABCMeta
 
-        @abc.abstractmethod
         def server_proxy(self, rpc_url, user=None):
             """Return an object of a type compatible with xmlrpclib.ServerProxy
             """
+            raise NotImplemented('Must override RPC server_proxy method')
 
 
     def basic_auth_url(url, user, pwd=None):
                                    parts.path, parts.query, parts.fragment)
         return newparts.geturl()
 
+    #--------------
+    # XML-RPC functional testers
+    #--------------
 
     class XmlRpcTester(RpcTesterMixin):
         """XML-RPC over HTTP. Supports custom transport.
 
-        If transport is mnissing fall back to basic auth, default behavior
+        If transport is missing fall back to basic auth, default behavior
         for Trac RPC test suite.
         """
 
+        xmlrpclib_compat = True
         transport = None
+        ServerProxy = xmlrpclib.ServerProxy
 
         def server_proxy(self, rpc_url, user=None):
             transport = self.transport(rpc_url, user) \
                         if self.transport is not None else None
             if transport is None and user is not None:
                 rpc_url = basic_auth_url(rpc_url, user)
-            return xmlrpclib.ServerProxy(rpc_url, transport=transport)
+            return self.ServerProxy(rpc_url, transport=transport)
 
-    #--------------
-    # RPC functional testers for HTTP basic auth
-    #--------------
 
     class XmlRpcBasicTester(functional.HttpAuthTester, XmlRpcTester):
         """XML-RPC over HTTP Basic authentication.
         url_auth_handlers = urllib2.HTTPBasicAuthHandler
 
 
-    #--------------
-    # RPC functional testers for HTTP digest auth
-    #--------------
-
     class AdvancedXmlRpcTester(functional.HttpAuthTester, XmlRpcTester):
         """Abstract XML-RPC tester supporting custom urllib2 handlers.
 
         http://bytes.com/topic/python/answers/509382-solution-xml-rpc-over-proxy
         """
         class _TransportMixin(object):
+            content_type = 'text/xml'
+
             def __init__(self, username, pw, build_opener, verbose = None,
                          use_datetime=0):
                 self._username = username
                 # FIXME: Tester ?
                 self.build_opener = build_opener
 
-            # scheme_prefix overridden in subclasses
-            scheme_prefix = None
+            def scheme_prefix(self):
+                """URL scheme, overridden in subclasses
+                """
+                raise NotImplementedError("Must override 'scheme_prefix' "
+                                          "property")
 
             def request(self, host, handler, request_body, verbose):
 
                 url= self.scheme_prefix + host + handler
                 if verbose or self.verbose:
-                    print "ProxyTransport URL: [%s]"%url
+                    print "Transport URL: [%s]"%url
 
                 request = urllib2.Request(url)
                 request.add_data(request_body)
                 # Note: 'Host' and 'Content-Length' are added automatically
                 request.add_header("User-Agent", self.user_agent)
-                request.add_header("Content-Type", "text/xml") # Important
+                request.add_header("Content-Type", self.content_type) #Important
 
                 # implicit handlers setup e.g. digest authentication
                 opener = self.build_opener(url, self._username, self._pw)
 
     class XmlRpcDigestTester(AdvancedXmlRpcTester):
         """XML-RPC over HTTP Digest authentication.
-
-        Based on
-        http://trac-hacks.org/wiki/XmlRpcPlugin#UsingDigestAuthenticationinpython
-        http://bytes.com/topic/python/answers/509382-solution-xml-rpc-over-proxy
         """
         url_auth_handlers = urllib2.HTTPDigestAuthHandler
 
 
-    class DefaultRpcTester(XmlRpcDigestTester,
+    class DefaultXmlRpcTester(XmlRpcDigestTester,
                            functional.BloodhoundGlobalEnvFunctionalTester):
         pass
 
 
+    #--------------
+    # JSON-RPC functional testers
+    #--------------
+
+    class JsonRpcLibTester(AdvancedXmlRpcTester):
+        """JSON-RPC over HTTP.
+        """
+        ServerProxy = jsonrpclib.Server
+
+        class _TransportMixin(AdvancedXmlRpcTester._TransportMixin):
+            content_type = 'application/json'
+
+            # FIXME: Really need this ?
+            def getparser(self):
+                target = jsonrpclib.jsonrpc.JSONTarget()
+                return jsonrpclib.jsonrpc.JSONParser(target), target
+
+        class SafeTransport(_TransportMixin, xmlrpclib.SafeTransport):
+            scheme_prefix = 'https://'
+
+        class Transport(_TransportMixin, xmlrpclib.Transport):
+            scheme_prefix = 'http://'
+
+
+    class JsonRpcLibBasicTester(JsonRpcLibTester):
+        """JSON-RPC over HTTP Basic authentication.
+        """
+        url_auth_handlers = urllib2.HTTPBasicAuthHandler
+
+
+    class JsonRpcLibDigestTester(JsonRpcLibTester):
+        """JSON-RPC over HTTP Digest authentication.
+        """
+        url_auth_handlers = urllib2.HTTPDigestAuthHandler
+
+
+    class DefaultJsonRpcTester(JsonRpcLibDigestTester,
+                               functional.BloodhoundGlobalEnvFunctionalTester):
+        pass
+
+
+    #--------------
+    # unittest
+    #--------------
+
     class RpcFunctionalTestSuite(functional.MultiproductFunctionalTestSuite):
         class env_class(functional.DigestAuthTestEnvironment,
                         RpcTestEnvironment):
         # FIXME: Solve TracStandalone /login issue
         @staticmethod
         def tester_class(baseurl):
-            return DefaultRpcTester(baseurl, skiplogin=True)
+            # FIXME: Parameterize test runs to activate JSON-RPC
+            return DefaultJsonRpcTester(baseurl, skiplogin=True)
+            #return DefaultXmlRpcTester(baseurl, skiplogin=True)
 
         def testenv_path(self, port=None):
             if port is None:
     def tracrpc_functionalSuite(suite):
         import tracrpc.tests.api
         tracrpc.tests.api.test_suite(suite)
+        import tracrpc.tests.web_ui
+        tracrpc.tests.web_ui.test_suite(suite)
         import tracrpc.tests.xml_rpc
         tracrpc.tests.xml_rpc.test_suite(suite)
         import tracrpc.tests.json_rpc
         tracrpc.tests.ticket.test_suite(suite)
         import tracrpc.tests.wiki
         tracrpc.tests.wiki.test_suite(suite)
-        import tracrpc.tests.web_ui
-        tracrpc.tests.web_ui.test_suite(suite)
         return suite
 
     def test_suite(suite=None):

trunk/tracrpc/tests/xml_rpc.py

 (c) 2009      ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)
 """
 
-import unittest
+from tracrpc.tests import unittest
 
 import xmlrpclib
 
 class RpcXmlTestCase(TracRpcTestCase):
     
     def setUp(self):
+        if not getattr(self._tester, 'xmlrpclib_compat', False):
+            raise unittest.SkipTest('Protocol not compatible with xmlrpclib')
         TracRpcTestCase.setUp(self)
         self.anon = self._tester.server_proxy(self.url_anon)
         self.user = self._tester.server_proxy(self.url_auth, user='user')