Commits

Olemis Lang committed de717d8

TracRpc: API v2: Most test for XML-RPC pass. Base TestCase added.

  • Participants
  • Parent commits 511dd8c

Comments (0)

Files changed (1)

t5437/t5437-protocol_api_v2-r7194.diff

 RPC Protocol API version 2
 
-diff -r a475cf08e780 trunk/tracrpc/api.py
---- a/trunk/tracrpc/api.py	Sat Mar 13 19:59:29 2010 -0500
-+++ b/trunk/tracrpc/api.py	Sun Mar 14 02:27:58 2010 -0500
+diff -r 203e791a70bf trunk/setup.py
+--- a/trunk/setup.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/setup.py	Wed Mar 17 15:41:29 2010 -0500
+@@ -28,7 +28,7 @@
+     url='http://trac-hacks.org/wiki/XmlRpcPlugin',
+     description='RPC interface to Trac',
+     zip_safe=True,
+-    test_suite = 'tracrpc.tests.suite',
++    test_suite = 'tracrpc.tests.test_suite',
+     tests_require = test_deps,
+     packages=find_packages(exclude=['*.tests']),
+     package_data={
+diff -r 203e791a70bf trunk/tracrpc/api.py
+--- a/trunk/tracrpc/api.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/api.py	Wed Mar 17 15:41:29 2010 -0500
 @@ -21,13 +21,34 @@
      """ RPC Binary type. Currently == xmlrpclib.Binary. """
      pass
  
  class IXMLRPCHandler(Interface):
  
-diff -r a475cf08e780 trunk/tracrpc/json_rpc.py
---- a/trunk/tracrpc/json_rpc.py	Sat Mar 13 19:59:29 2010 -0500
-+++ b/trunk/tracrpc/json_rpc.py	Sun Mar 14 02:27:58 2010 -0500
+diff -r 203e791a70bf trunk/tracrpc/json_rpc.py
+--- a/trunk/tracrpc/json_rpc.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/json_rpc.py	Wed Mar 17 15:41:29 2010 -0500
 @@ -5,8 +5,9 @@
  (c) 2009      ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)
  """
              return self._json_error(e, r_id=r_id)
  
      def _json_error(self, e, c=None, r_id=None):
-diff -r a475cf08e780 trunk/tracrpc/web_ui.py
---- a/trunk/tracrpc/web_ui.py	Sat Mar 13 19:59:29 2010 -0500
-+++ b/trunk/tracrpc/web_ui.py	Sun Mar 14 02:27:58 2010 -0500
+diff -r 203e791a70bf trunk/tracrpc/tests/__init__.py
+--- a/trunk/tracrpc/tests/__init__.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/tests/__init__.py	Wed Mar 17 15:41:29 2010 -0500
+@@ -35,6 +35,7 @@
+             print "Enabling RPC plugin and permissions..."
+             env.config.set('components', 'tracrpc.*', 'enabled')
+             env.config.save()
++            self.getLogger = lambda : env.log
+             self._tracadmin('permission', 'add', 'anonymous', 'XML_RPC')
+             print "Created test environment: %s" % self.dirname
+             parts = urllib2.urlparse.urlsplit(self.url)
+@@ -66,22 +67,55 @@
+                 os.path.realpath(__file__), '..', '..', '..', 'rpctestenv')),
+                 '8765', 'http://127.0.0.1')
+ 
+-    def suite():
++    def test_suite():
+         suite = unittest.TestSuite()
+         import tracrpc.tests.api
+-        suite.addTest(tracrpc.tests.api.suite())
++        suite.addTest(tracrpc.tests.api.test_suite())
+         import tracrpc.tests.xml_rpc
+-        suite.addTest(tracrpc.tests.xml_rpc.suite())
++        suite.addTest(tracrpc.tests.xml_rpc.test_suite())
+         import tracrpc.tests.json_rpc
+-        suite.addTest(tracrpc.tests.json_rpc.suite())
++        suite.addTest(tracrpc.tests.json_rpc.test_suite())
+         import tracrpc.tests.ticket
+-        suite.addTest(tracrpc.tests.ticket.suite())
++        suite.addTest(tracrpc.tests.ticket.test_suite())
+         import tracrpc.tests.wiki
+-        suite.addTest(tracrpc.tests.wiki.suite())
++        suite.addTest(tracrpc.tests.wiki.test_suite())
+         return suite
+ 
+ except Exception, e:
+     print e
+     print "Trac test infrastructure not available."
+     print "Install Trac as 'python setup.py develop' (run Trac from source).\n"
+-    suite = unittest.TestSuite() # return empty suite
++    test_suite = unittest.TestSuite() # return empty suite
++    
++    TracRpcTestCase = unittest.TestCase
++else :
++    class TracRpcTestCase(unittest.TestCase):
++        def setUp(self):
++            log = rpc_testenv.getLogger()
++            log.info('=' * 70)
++            log.info('(TEST) Starting %s', self._testMethodName)
++            log.info('=' * 70)
++
++        def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
++            """Enhanced assertions to detect exceptions."""
++            try:
++                callableObj(*args, **kwargs)
++            except excClass, e:
++                return e
++            except self.failureException :
++                raise
++            except Exception, e :
++                if hasattr(excClass, '__name__'): excName = excClass.__name__
++                else: excName = str(excClass)
++
++                if hasattr(e, '__name__'): excMsg = e.__name__
++                else: excMsg = str(e)
++
++                raise self.failureException("\n\nExpected %s\n\nGot %s : %s" % (
++                                        excName, e.__class__.__name__, excMsg))
++            else:
++                if hasattr(excClass,'__name__'): excName = excClass.__name__
++                else: excName = str(excClass)
++                raise self.failureException, "Expected %s\n\nNothing raised" % excName
++
++        assertRaises = failUnlessRaises
+diff -r 203e791a70bf trunk/tracrpc/tests/api.py
+--- a/trunk/tracrpc/tests/api.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/tests/api.py	Wed Mar 17 15:41:29 2010 -0500
+@@ -9,14 +9,14 @@
+ import unittest
+ import urllib2
+ 
+-from tracrpc.tests import rpc_testenv
++from tracrpc.tests import rpc_testenv, TracRpcTestCase
+ 
+ from tracrpc.api import IRPCProtocol
+ 
+ from trac.core import *
+ from trac.test import Mock
+ 
+-class ProtocolProviderTestCase(unittest.TestCase):
++class ProtocolProviderTestCase(TracRpcTestCase):
+ 
+     def test_invalid_content_type(self):
+         req = urllib2.Request(rpc_testenv.url_anon,
+@@ -47,13 +47,18 @@
+             "class DummyProvider(Component):\n"
+             "    implements(IRPCProtocol)\n"
+             "    def rpc_info(self):\n"
+-            "        yield ('TEST-RPC', 'No Docs!')\n"
++            "        return ('TEST-RPC', 'No Docs!')\n"
+             "    def rpc_match(self):\n"
+             "        yield ('rpc', 'application/x-tracrpc-test')\n"
+-            "    def rpc_process(self, req, content_type):\n"
++            "    def parse_rpc_request(self, req, content_type):\n"
++            "        return {'method' : 'system.getAPIVersion'}\n"
++            "    def send_rpc_error(self, req, rpcreq, e):\n"
++            "        req.send_error(None, template='', content_type=rpcreq['mimetype'],\n"
++            "                       status=500, env=None, data='Test failure ')\n"
++            "    def send_rpc_result(self, req, rpcreq, result):\n"
+             "        response = 'Got a result!'\n"
+             "        req.send_response(200)\n"
+-            "        req.send_header('Content-Type', content_type)\n"
++            "        req.send_header('Content-Type', rpcreq['mimetype'])\n"
+             "        req.send_header('Content-Length', len(response))\n"
+             "        req.end_headers()\n"
+             "        req.write(response)\n")
+@@ -80,10 +85,21 @@
+             "class DummyProvider(Component):\n"
+             "    implements(IRPCProtocol)\n"
+             "    def rpc_info(self):\n"
+-            "        yield ('TEST-RPC', 'No Docs!')\n"
++            "        return ('TEST-RPC', 'No Docs!')\n"
+             "    def rpc_match(self):\n"
+             "        yield ('rpc', 'application/x-tracrpc-test')\n"
+-            "    def rpc_process(self, req, content_type):\n"
++            "    def parse_rpc_request(self, req, content_type):\n"
++            "        return {'method' : 'system.getAPIVersion'}\n"
++            "    def send_rpc_error(self, req, rpcreq, e):\n"
++            "        if isinstance(e, RPCError) :\n"
++            "            req.send_error(None, template='', \n"
++            "                       content_type='text/plain',\n"
++            "                       status=500, env=None, data=e.message)\n"
++            "        else :\n"
++            "            req.send_error(None, template='', \n"
++            "                       content_type='text/plain',\n"
++            "                       status=500, env=None, data='Test failure')\n"
++            "    def send_rpc_result(self, req, rpcreq, result):\n"
+             "        raise RPCError('No good.')")
+         rpc_testenv.restart()
+         # Make the request
+@@ -100,8 +116,8 @@
+             os.unlink(provider)
+             rpc_testenv.restart()
+ 
+-def suite():
++def test_suite():
+     return unittest.makeSuite(ProtocolProviderTestCase)
+ 
+ if __name__ == '__main__':
+-    unittest.main(defaultTest='suite')
++    unittest.main(defaultTest='test_suite')
+diff -r 203e791a70bf trunk/tracrpc/tests/json_rpc.py
+--- a/trunk/tracrpc/tests/json_rpc.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/tests/json_rpc.py	Wed Mar 17 15:41:29 2010 -0500
+@@ -14,9 +14,9 @@
+ from tracrpc.util import StringIO
+ 
+ if json:
+-    from tracrpc.tests import rpc_testenv
++    from tracrpc.tests import rpc_testenv, TracRpcTestCase
+ 
+-    class JsonTestCase(unittest.TestCase):
++    class JsonTestCase(TracRpcTestCase):
+         
+         def _anon_req(self, data):
+             req = urllib2.Request(rpc_testenv.url_anon,
+@@ -38,12 +38,6 @@
+             resp = urllib2.build_opener(handler).open(req)
+             return json.loads(resp.read())
+ 
+-        def setUp(self):
+-            pass
+-
+-        def tearDown(self):
+-            pass
+-
+         def test_call(self):
+             result = self._anon_req(
+                     {'method': 'system.listMethods', 'params': [], 'id': 244})
+@@ -167,11 +161,11 @@
+             self.assertEquals(result['error']['message'],
+                      'Wiki page "Test" does not exist at version 10')
+ 
+-    def suite():
++    def test_suite():
+         return unittest.makeSuite(JsonTestCase)
+ else:
+     print "SKIP: json not available. Cannot run tests."
+-    suite = unittest.TestSuite()
++    test_suite = unittest.TestSuite()
+ 
+ if __name__ == '__main__':
+-    unittest.main(defaultTest='suite')
++    unittest.main(defaultTest='test_suite')
+diff -r 203e791a70bf trunk/tracrpc/tests/ticket.py
+--- a/trunk/tracrpc/tests/ticket.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/tests/ticket.py	Wed Mar 17 15:41:29 2010 -0500
+@@ -12,11 +12,12 @@
+ import shutil
+ import time
+ 
+-from tracrpc.tests import rpc_testenv
++from tracrpc.tests import rpc_testenv, TracRpcTestCase
+ 
+-class RpcTicketTestCase(unittest.TestCase):
++class RpcTicketTestCase(TracRpcTestCase):
+     
+     def setUp(self):
++        TracRpcTestCase.setUp(self)
+         self.anon = xmlrpclib.ServerProxy(rpc_testenv.url_anon)
+         self.user = xmlrpclib.ServerProxy(rpc_testenv.url_user)
+         self.admin = xmlrpclib.ServerProxy(rpc_testenv.url_admin)
+@@ -124,8 +125,8 @@
+             self.admin.ticket.delete(tid1)
+             self.admin.ticket.delete(tid2)
+ 
+-def suite():
++def test_suite():
+     return unittest.makeSuite(RpcTicketTestCase)
+ 
+ if __name__ == '__main__':
+-    unittest.main(defaultTest='suite')
++    unittest.main(defaultTest='test_suite')
+diff -r 203e791a70bf trunk/tracrpc/tests/wiki.py
+--- a/trunk/tracrpc/tests/wiki.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/tests/wiki.py	Wed Mar 17 15:41:29 2010 -0500
+@@ -13,12 +13,13 @@
+ 
+ from trac.util.compat import sorted
+ 
+-from tracrpc.tests import rpc_testenv
++from tracrpc.tests import rpc_testenv, TracRpcTestCase
+ from tracrpc.util import StringIO
+ 
+-class RpcWikiTestCase(unittest.TestCase):
++class RpcWikiTestCase(TracRpcTestCase):
+     
+     def setUp(self):
++        TracRpcTestCase.setUp(self)
+         self.anon = xmlrpclib.ServerProxy(rpc_testenv.url_anon)
+         self.user = xmlrpclib.ServerProxy(rpc_testenv.url_user)
+         self.admin = xmlrpclib.ServerProxy(rpc_testenv.url_admin)
+@@ -60,8 +61,8 @@
+         self.admin.wiki.deletePage('WikiOne')
+         self.admin.wiki.deletePage('WikiTwo')
+ 
+-def suite():
++def test_suite():
+     return unittest.makeSuite(RpcWikiTestCase)
+ 
+ if __name__ == '__main__':
+-    unittest.main(defaultTest='suite')
++    unittest.main(defaultTest='test_suite')
+diff -r 203e791a70bf trunk/tracrpc/tests/xml_rpc.py
+Binary file trunk/tracrpc/tests/xml_rpc.py has changed
+diff -r 203e791a70bf trunk/tracrpc/web_ui.py
+--- a/trunk/tracrpc/web_ui.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/web_ui.py	Wed Mar 17 15:41:29 2010 -0500
 @@ -6,6 +6,10 @@
  (c) 2009      ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)
  """
  
 +    def _rpc_process(self, req, protocol, content_type):
 +        """Process incoming RPC request and finalize response."""
-+        req.perm.require('XML_RPC') # Need at least XML_RPC
-+        proto_id = protocol.rpc_info()[0]
++        proto_id = tuple(protocol.rpc_info())[0]
 +        rpcreq = {'mimetype': content_type}
 +        try :
 +            self.log.debug("RPC(%s) call by '%s'", proto_id, req.authname)
++            req.perm.require('XML_RPC') # Need at least XML_RPC
 +            rpcreq = protocol.parse_rpc_request(req, content_type)
 +            rpcreq['mimetype'] = content_type
 +            method_name = rpcreq.get('method')
 +                result = (XMLRPCSystem(self.env).get_method(method_name)(req, args))[0]
 +                if isinstance(result, GeneratorType):
 +                    result = list(result)
-+            except (RPCError, PermissionError, ResourceNotFound), e:
++            except (RPCError, PermissionError, ResourceNotFound):
 +                raise
 +            except Exception:
 +                e, tb = sys.exc_info()[-2:]
      # ITemplateProvider methods
  
      def get_htdocs_dirs(self):
-diff -r a475cf08e780 trunk/tracrpc/xml_rpc.py
---- a/trunk/tracrpc/xml_rpc.py	Sat Mar 13 19:59:29 2010 -0500
-+++ b/trunk/tracrpc/xml_rpc.py	Sun Mar 14 02:27:58 2010 -0500
-@@ -19,7 +19,7 @@
+diff -r 203e791a70bf trunk/tracrpc/xml_rpc.py
+--- a/trunk/tracrpc/xml_rpc.py	Tue Mar 16 11:04:09 2010 -0500
++++ b/trunk/tracrpc/xml_rpc.py	Wed Mar 17 15:41:29 2010 -0500
+@@ -17,9 +17,10 @@
+ from trac.resource import ResourceNotFound
+ from trac.util.datefmt import utc
  from trac.util.text import to_unicode
++from trac.web.api import RequestDone
  
  from tracrpc.api import XMLRPCSystem, IRPCProtocol, Binary, \
 -        RPCError, MethodNotFound
  from tracrpc.util import empty, prepare_docs
  
  __all__ = ['XmlRpcProtocol']
-@@ -81,41 +81,46 @@
+@@ -81,41 +82,46 @@
          yield ('xmlrpc', 'application/xml')
          yield ('xmlrpc', 'text/xml')
  
              self.log.error(e)
              import traceback
              from tracrpc.util import StringIO
+@@ -123,6 +129,7 @@
+             traceback.print_exc(file = out)
+             self.log.error(out.getvalue())
+             err_code = hasattr(e, 'code') and e.code or 1
++            method = rpcreq.get('method')
+             self._send_response(req,
+                     xmlrpclib.dumps(
+                         xmlrpclib.Fault(err_code,
+@@ -137,6 +144,7 @@
+         req.send_header('Content-Length', len(response))
+         req.end_headers()
+         req.write(response)
++        raise RequestDone()
+ 
+     def _normalize_xml_input(self, args):
+         """ Normalizes arguments (at any level - traversing dicts and lists):