diff --git a/TESTING b/TESTING index 2b433d7eb..7c16f374f 100644 --- a/TESTING +++ b/TESTING @@ -27,6 +27,15 @@ Running tests After running all of the tests, run_test.sh will report any pep8 errors found in the tree. +Running individual tests + + Individual tests can be run using run_tests.py, you just need to pass + the dot-separated path to the module you want as an argument to it. + For example, the following would run only the APITestV11 tests from + quantum/tests/unit/test_api.py: + + $ ./run_tests.sh quantum.tests.unit.test_api:APITestV11 + Adding more tests Quantum is a pretty new code base at this point and there is plenty of diff --git a/quantum/api/faults.py b/quantum/api/faults.py index 3ad04e5f4..a9e373fcb 100644 --- a/quantum/api/faults.py +++ b/quantum/api/faults.py @@ -55,7 +55,7 @@ def fault_body_function_v10(wrapped_exc): def fault_body_function_v11(wrapped_exc): """ This function creates the contents of the body for a fault - response for Quantum API v1.0. + response for Quantum API v1.1. :param wrapped_exc: Exception thrown by the Quantum service :type wrapped_exc: quantum.common.exceptions.QuantumException diff --git a/quantum/tests/unit/_test_api.py b/quantum/tests/unit/_test_api.py index 0ef5fa3da..5d27fb866 100644 --- a/quantum/tests/unit/_test_api.py +++ b/quantum/tests/unit/_test_api.py @@ -18,8 +18,12 @@ # @author: Salvatore Orlando, Citrix Systems import logging -import unittest +import unittest2 as unittest +import mock + +from quantum.api.api_common import APIFaultWrapper +from quantum.api.networks import Controller from quantum.common.test_lib import test_config from quantum.common import utils from quantum.db import api as db @@ -1187,3 +1191,21 @@ class BaseAPIOperationsTest(AbstractAPITest): def test_multitenancy_json(self): self._test_multitenancy('json') + + def test_internal_error(self): + """Check that internal errors do not leak. + + Any internal, unexpected error should be turned into a 500 response + without any traces of the original exception. + """ + orig_exception_msg = "An exception with a traceback" + + @APIFaultWrapper() + def raise_exception(self, *args, **kwargs): + raise Exception(orig_exception_msg) + + list_network_req = testlib.network_list_request(self.tenant_id, "json") + with mock.patch.object(Controller, 'index', new=raise_exception): + list_network_res = list_network_req.get_response(self.api) + self.assertEqual(list_network_res.status_int, 500) + self.assertNotIn(orig_exception_msg, list_network_res.body) diff --git a/quantum/wsgi.py b/quantum/wsgi.py index 402825004..6dd508614 100644 --- a/quantum/wsgi.py +++ b/quantum/wsgi.py @@ -752,6 +752,12 @@ class Resource(Application): action_result = Fault(ex, self._xmlns, self._fault_body_function) + except Exception: + LOG.exception("Internal error") + # Do not include the traceback to avoid returning it to clients. + action_result = Fault(webob.exc.HTTPServerError(), + self._xmlns, + self._fault_body_function) if isinstance(action_result, dict) or action_result is None: response = self.serializer.serialize(action_result, diff --git a/run_tests.py b/run_tests.py old mode 100644 new mode 100755 diff --git a/tools/pip-requires b/tools/pip-requires index 43be661c2..cbb9f1831 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -3,7 +3,6 @@ PasteDeploy==1.5.0 Routes>=1.12.3 eventlet>=0.9.12 lxml -mox==0.5.3 python-gflags==1.3 sqlalchemy webob==1.0.8 diff --git a/tools/test-requires b/tools/test-requires index e0f0058b3..8426f998d 100644 --- a/tools/test-requires +++ b/tools/test-requires @@ -2,9 +2,11 @@ distribute>=0.6.24 coverage mock>=0.7.1 +mox==0.5.3 nose nosexcover openstack.nose_plugin pep8==0.6.1 sphinx>=1.1.2 +unittest2 webtest