Increase UT Coverage

UT Coverage for magnumclient/common/httpclient.py is increased
from 56% to 81%.

Overall coverage is now 79%

Change-Id: I28d0f3406ed9940cf0dee9d2fa5d238152017151
Partially-Implements: blueprint magnumclient-ut-coverage
This commit is contained in:
Hieu LE
2017-01-25 17:20:46 +07:00
parent d8d54392af
commit cdc1b5e433
3 changed files with 152 additions and 27 deletions

View File

@@ -51,7 +51,6 @@ def _extract_error_json(body):
'debuginfo': error_body['message']} 'debuginfo': error_body['message']}
else: else:
error_body = body_json['errors'][0] error_body = body_json['errors'][0]
raw_msg = error_body['title']
error_json = {'faultstring': error_body['title']} error_json = {'faultstring': error_body['title']}
if 'detail' in error_body: if 'detail' in error_body:
error_json['debuginfo'] = error_body['detail'] error_json['debuginfo'] = error_body['detail']
@@ -101,11 +100,8 @@ class HTTPClient(object):
def get_connection(self): def get_connection(self):
_class = self.connection_params[0] _class = self.connection_params[0]
try:
return _class(*self.connection_params[1][0:2], return _class(*self.connection_params[1][0:2],
**self.connection_params[2]) **self.connection_params[2])
except six.moves.http_client.InvalidURL:
raise exceptions.EndpointException()
def log_curl_request(self, method, url, kwargs): def log_curl_request(self, method, url, kwargs):
curl = ['curl -i -X %s' % method] curl = ['curl -i -X %s' % method]

View File

@@ -17,20 +17,36 @@ import json
import mock import mock
import six import six
import socket
from magnumclient.common.apiclient.exceptions import GatewayTimeout from magnumclient.common.apiclient.exceptions import GatewayTimeout
from magnumclient.common.apiclient.exceptions import MultipleChoices
from magnumclient.common import httpclient as http from magnumclient.common import httpclient as http
from magnumclient import exceptions as exc from magnumclient import exceptions as exc
from magnumclient.tests import utils from magnumclient.tests import utils
NORMAL_ERROR = 0
ERROR_DICT = 1
ERROR_LIST_WITH_DETAIL = 2
ERROR_LIST_WITH_DESC = 3
def _get_error_body(faultstring=None, debuginfo=None):
def _get_error_body(faultstring=None, debuginfo=None, err_type=NORMAL_ERROR):
if err_type == NORMAL_ERROR:
error_body = { error_body = {
'faultstring': faultstring, 'faultstring': faultstring,
'debuginfo': debuginfo 'debuginfo': debuginfo
} }
raw_error_body = json.dumps(error_body) raw_error_body = json.dumps(error_body)
body = {'error_message': raw_error_body} body = {'error_message': raw_error_body}
elif err_type == ERROR_DICT:
body = {'error': {'title': faultstring, 'message': debuginfo}}
elif err_type == ERROR_LIST_WITH_DETAIL:
main_body = {'title': faultstring, 'detail': debuginfo}
body = {'errors': [main_body]}
elif err_type == ERROR_LIST_WITH_DESC:
main_body = {'title': faultstring, 'description': debuginfo}
body = {'errors': [main_body]}
raw_body = json.dumps(body) raw_body = json.dumps(body)
return raw_body return raw_body
@@ -79,7 +95,7 @@ class HttpClientTest(utils.BaseTestCase):
def test_server_exception_msg_only(self): def test_server_exception_msg_only(self):
error_msg = 'test error msg' error_msg = 'test error msg'
error_body = _get_error_body(error_msg) error_body = _get_error_body(error_msg, err_type=ERROR_DICT)
fake_resp = utils.FakeResponse({'content-type': 'application/json'}, fake_resp = utils.FakeResponse({'content-type': 'application/json'},
six.StringIO(error_body), six.StringIO(error_body),
version=1, version=1,
@@ -97,7 +113,8 @@ class HttpClientTest(utils.BaseTestCase):
error_msg = 'another test error' error_msg = 'another test error'
error_trace = ("\"Traceback (most recent call last):\\n\\n " error_trace = ("\"Traceback (most recent call last):\\n\\n "
"File \\\"/usr/local/lib/python2.7/...") "File \\\"/usr/local/lib/python2.7/...")
error_body = _get_error_body(error_msg, error_trace) error_body = _get_error_body(error_msg, error_trace,
ERROR_LIST_WITH_DESC)
fake_resp = utils.FakeResponse({'content-type': 'application/json'}, fake_resp = utils.FakeResponse({'content-type': 'application/json'},
six.StringIO(error_body), six.StringIO(error_body),
version=1, version=1,
@@ -116,15 +133,41 @@ class HttpClientTest(utils.BaseTestCase):
"%(error)s\n%(details)s" % {'error': str(error), "%(error)s\n%(details)s" % {'error': str(error),
'details': str(error.details)}) 'details': str(error.details)})
def test_get_connection_params(self): def test_server_exception_address(self):
endpoint = 'http://magnum-host:6385' endpoint = 'https://magnum-host:6385'
expected = (HTTP_CLASS, client = http.HTTPClient(endpoint, token='foobar', insecure=True,
('magnum-host', 6385, ''), ca_file='/path/to/ca_file')
{'timeout': DEFAULT_TIMEOUT}) client.get_connection = (
params = http.HTTPClient.get_connection_params(endpoint) lambda *a, **kw: utils.FakeConnection(exc=socket.gaierror))
self.assertEqual(expected, params)
def test_get_connection_params_with_trailing_slash(self): self.assertRaises(exc.EndpointNotFound, client.json_request,
'GET', '/v1/resources', body='farboo')
def test_server_exception_socket(self):
client = http.HTTPClient('http://localhost/', token='foobar')
client.get_connection = (
lambda *a, **kw: utils.FakeConnection(exc=socket.error))
self.assertRaises(exc.ConnectionRefused, client.json_request,
'GET', '/v1/resources')
def test_server_exception_endpoint(self):
endpoint = 'https://magnum-host:6385'
client = http.HTTPClient(endpoint, token='foobar', insecure=True,
ca_file='/path/to/ca_file')
client.get_connection = (
lambda *a, **kw: utils.FakeConnection(exc=socket.gaierror))
self.assertRaises(exc.EndpointNotFound, client.json_request,
'GET', '/v1/resources', body='farboo')
def test_get_connection(self):
endpoint = 'https://magnum-host:6385'
client = http.HTTPClient(endpoint)
conn = client.get_connection()
self.assertTrue(conn, http.VerifiedHTTPSConnection)
def test_get_connection_exception(self):
endpoint = 'http://magnum-host:6385/' endpoint = 'http://magnum-host:6385/'
expected = (HTTP_CLASS, expected = (HTTP_CLASS,
('magnum-host', 6385, ''), ('magnum-host', 6385, ''),
@@ -219,8 +262,13 @@ class HttpClientTest(utils.BaseTestCase):
params = http.HTTPClient.get_connection_params(endpoint) params = http.HTTPClient.get_connection_params(endpoint)
self.assertEqual(expected, params) self.assertEqual(expected, params)
def test_get_connection_params_with_unsupported_scheme(self):
endpoint = 'foo://magnum-host:6385/magnum/v1/'
self.assertRaises(exc.EndpointException,
http.HTTPClient.get_connection_params, endpoint)
def test_401_unauthorized_exception(self): def test_401_unauthorized_exception(self):
error_body = _get_error_body() error_body = _get_error_body(err_type=ERROR_LIST_WITH_DETAIL)
fake_resp = utils.FakeResponse({'content-type': 'text/plain'}, fake_resp = utils.FakeResponse({'content-type': 'text/plain'},
six.StringIO(error_body), six.StringIO(error_body),
version=1, version=1,
@@ -232,6 +280,75 @@ class HttpClientTest(utils.BaseTestCase):
self.assertRaises(exc.Unauthorized, client.json_request, self.assertRaises(exc.Unauthorized, client.json_request,
'GET', '/v1/resources') 'GET', '/v1/resources')
def test_server_redirect_exception(self):
fake_redirect_resp = utils.FakeResponse(
{'content-type': 'application/octet-stream'},
'foo', version=1, status=301)
fake_resp = utils.FakeResponse(
{'content-type': 'application/octet-stream'},
'bar', version=1, status=300)
client = http.HTTPClient('http://localhost/')
conn = utils.FakeConnection(fake_redirect_resp,
redirect_resp=fake_resp)
client.get_connection = (lambda *a, **kw: conn)
self.assertRaises(MultipleChoices, client.json_request,
'GET', '/v1/resources')
def test_server_body_undecode_json(self):
err = "foo"
fake_resp = utils.FakeResponse(
{'content-type': 'application/json'},
six.StringIO(err), version=1, status=200)
client = http.HTTPClient('http://localhost/')
conn = utils.FakeConnection(fake_resp)
client.get_connection = (lambda *a, **kw: conn)
resp, body = client.json_request('GET', '/v1/resources')
self.assertEqual(resp, fake_resp)
self.assertEqual(err, body)
def test_server_success_body_app(self):
fake_resp = utils.FakeResponse(
{'content-type': 'application/octet-stream'},
'bar', version=1, status=200)
client = http.HTTPClient('http://localhost/')
conn = utils.FakeConnection(fake_resp)
client.get_connection = (lambda *a, **kw: conn)
resp, body = client.json_request('GET', '/v1/resources')
self.assertEqual(resp, fake_resp)
self.assertIsNone(body)
def test_server_success_body_none(self):
fake_resp = utils.FakeResponse(
{'content-type': None},
six.StringIO('bar'), version=1, status=200)
client = http.HTTPClient('http://localhost/')
conn = utils.FakeConnection(fake_resp)
client.get_connection = (lambda *a, **kw: conn)
resp, body = client.json_request('GET', '/v1/resources')
self.assertEqual(resp, fake_resp)
self.assertTrue(isinstance(body, list))
def test_server_success_body_json(self):
err = _get_error_body()
fake_resp = utils.FakeResponse(
{'content-type': 'application/json'},
six.StringIO(err), version=1, status=200)
client = http.HTTPClient('http://localhost/')
conn = utils.FakeConnection(fake_resp)
client.get_connection = (lambda *a, **kw: conn)
resp, body = client.json_request('GET', '/v1/resources')
self.assertEqual(resp, fake_resp)
self.assertEqual(json.dumps(body), err)
class SessionClientTest(utils.BaseTestCase): class SessionClientTest(utils.BaseTestCase):

View File

@@ -59,18 +59,24 @@ class FakeAPI(object):
class FakeConnection(object): class FakeConnection(object):
def __init__(self, response=None): def __init__(self, response=None, **kwargs):
self._response = response self._response = six.moves.queue.Queue()
self._response.put(response)
self._last_request = None self._last_request = None
self._exc = kwargs['exc'] if 'exc' in kwargs else None
if 'redirect_resp' in kwargs:
self._response.put(kwargs['redirect_resp'])
def request(self, method, conn_url, **kwargs): def request(self, method, conn_url, **kwargs):
self._last_request = (method, conn_url, kwargs) self._last_request = (method, conn_url, kwargs)
if self._exc:
raise self._exc
def setresponse(self, response): def setresponse(self, response):
self._response = response self._response = response
def getresponse(self): def getresponse(self):
return self._response return self._response.get()
class FakeResponse(object): class FakeResponse(object):
@@ -87,6 +93,12 @@ class FakeResponse(object):
self.status = status self.status = status
self.reason = reason self.reason = reason
def __getitem__(self, key):
if key is 'location':
return 'fake_url'
else:
return None
def getheaders(self): def getheaders(self):
return copy.deepcopy(self.headers).items() return copy.deepcopy(self.headers).items()