From f93048334cf9f93a823dd42387f76ecddf27d30d Mon Sep 17 00:00:00 2001 From: Endre Karlson Date: Mon, 18 May 2015 14:48:44 +0200 Subject: [PATCH] Pass response body down into RestClientExceptions This commit adds support to RestClientException objects to store the response body as a local attr. Additionally it modifies all the uses of the subclassed RestClientExceptions in the base rest client to store the response body on each error type. This is done in order to check the content in some occasion that additional error details are coming back from a service in the body. It will be useful to have the resp_body passed into the exception so that it can be used in additional checks. Change-Id: Ie1bb259e7e683081f0ad127617acc8deb98467c0 --- tempest_lib/common/rest_client.py | 13 ++++- tempest_lib/exceptions.py | 5 +- tempest_lib/tests/test_rest_client.py | 81 ++++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 6 deletions(-) diff --git a/tempest_lib/common/rest_client.py b/tempest_lib/common/rest_client.py index 7988061..1102a85 100644 --- a/tempest_lib/common/rest_client.py +++ b/tempest_lib/common/rest_client.py @@ -436,7 +436,10 @@ class RestClient(object): req_body, resp_body, caller_name, extra) def _parse_resp(self, body): - body = json.loads(body) + try: + body = json.loads(body) + except ValueError: + return body # We assume, that if the first value of the deserialized body's # item set is a dict or a list, that we just return the first value @@ -666,12 +669,18 @@ class RestClient(object): raise exceptions.InvalidContentType(str(resp.status)) if resp.status == 401: + if parse_resp: + resp_body = self._parse_resp(resp_body) raise exceptions.Unauthorized(resp_body) if resp.status == 403: + if parse_resp: + resp_body = self._parse_resp(resp_body) raise exceptions.Forbidden(resp_body) if resp.status == 404: + if parse_resp: + resp_body = self._parse_resp(resp_body) raise exceptions.NotFound(resp_body) if resp.status == 400: @@ -731,7 +740,7 @@ class RestClient(object): if resp.status == 501: raise exceptions.NotImplemented(message) else: - raise exceptions.ServerFault(message) + raise exceptions.ServerFault(resp_body, message=message) if resp.status >= 400: raise exceptions.UnexpectedResponseCode(str(resp.status)) diff --git a/tempest_lib/exceptions.py b/tempest_lib/exceptions.py index 90b0aca..d6f518c 100644 --- a/tempest_lib/exceptions.py +++ b/tempest_lib/exceptions.py @@ -47,7 +47,10 @@ class TempestException(Exception): class RestClientException(TempestException, testtools.TestCase.failureException): - pass + def __init__(self, resp_body, *args, **kwargs): + self.resp_body = resp_body + message = kwargs.get("message", resp_body) + super(RestClientException, self).__init__(message, *args, **kwargs) class InvalidHttpSuccessCode(RestClientException): diff --git a/tempest_lib/tests/test_rest_client.py b/tempest_lib/tests/test_rest_client.py index 373ef31..0aaf03f 100644 --- a/tempest_lib/tests/test_rest_client.py +++ b/tempest_lib/tests/test_rest_client.py @@ -361,11 +361,86 @@ class TestRestClientErrorCheckerJSON(base.TestCase): self.rest_client._error_checker, **self.set_data("501")) + def test_response_400_with_dict(self): + r_body = '{"resp_body": {"err": "fake_resp_body"}}' + e = self.assertRaises(exceptions.BadRequest, + self.rest_client._error_checker, + **self.set_data("400", r_body=r_body)) + + if self.c_type == 'application/json': + expected = {"err": "fake_resp_body"} + else: + expected = r_body + self.assertEqual(expected, e.resp_body) + + def test_response_401_with_dict(self): + r_body = '{"resp_body": {"err": "fake_resp_body"}}' + e = self.assertRaises(exceptions.Unauthorized, + self.rest_client._error_checker, + **self.set_data("401", r_body=r_body)) + + if self.c_type == 'application/json': + expected = {"err": "fake_resp_body"} + else: + expected = r_body + self.assertEqual(expected, e.resp_body) + + def test_response_403_with_dict(self): + r_body = '{"resp_body": {"err": "fake_resp_body"}}' + e = self.assertRaises(exceptions.Forbidden, + self.rest_client._error_checker, + **self.set_data("403", r_body=r_body)) + + if self.c_type == 'application/json': + expected = {"err": "fake_resp_body"} + else: + expected = r_body + self.assertEqual(expected, e.resp_body) + + def test_response_404_with_dict(self): + r_body = '{"resp_body": {"err": "fake_resp_body"}}' + e = self.assertRaises(exceptions.NotFound, + self.rest_client._error_checker, + **self.set_data("404", r_body=r_body)) + + if self.c_type == 'application/json': + expected = {"err": "fake_resp_body"} + else: + expected = r_body + self.assertEqual(expected, e.resp_body) + + def test_response_404_with_invalid_dict(self): + r_body = '{"foo": "bar"]' + e = self.assertRaises(exceptions.NotFound, + self.rest_client._error_checker, + **self.set_data("404", r_body=r_body)) + + expected = r_body + self.assertEqual(expected, e.resp_body) + + def test_response_409_with_dict(self): + r_body = '{"resp_body": {"err": "fake_resp_body"}}' + e = self.assertRaises(exceptions.Conflict, + self.rest_client._error_checker, + **self.set_data("409", r_body=r_body)) + + if self.c_type == 'application/json': + expected = {"err": "fake_resp_body"} + else: + expected = r_body + self.assertEqual(expected, e.resp_body) + def test_response_500_with_dict(self): r_body = '{"resp_body": {"err": "fake_resp_body"}}' - self.assertRaises(exceptions.ServerFault, - self.rest_client._error_checker, - **self.set_data("500", r_body=r_body)) + e = self.assertRaises(exceptions.ServerFault, + self.rest_client._error_checker, + **self.set_data("500", r_body=r_body)) + + if self.c_type == 'application/json': + expected = {"err": "fake_resp_body"} + else: + expected = r_body + self.assertEqual(expected, e.resp_body) def test_response_501_with_dict(self): r_body = '{"resp_body": {"err": "fake_resp_body"}}'