Get rid of httplib2, use urllib3 instead

httplib2 has been abandonned by its author [1] and is less going
to be updated and maintained than urllib3. So, let's replace httplib2
with urllib3.

Note that this patch mostly rework the unit tests.

I removed the files `tempest.tests.fake_identity` and
`tempest.tests.fake_http` to use their `tempest.tests.lib` counterpart.

Also, I tried to "encapsulated" HTTP calls and use
`tempest/lib/common/http.py` everywhere so that we only import
urllib3 once. This makes us not so dependent on a specific HTTP
library.

[1] http://bitworking.org/news/2016/03/an_update_on_httplib2
Change-Id: Id469e78afdb69a404144568a454d98d20a924231
This commit is contained in:
Jordan Pittier 2016-03-18 17:10:07 +01:00
parent 0afc659299
commit 00f259670c
21 changed files with 264 additions and 428 deletions

View File

@ -4,7 +4,6 @@
pbr>=1.6 # Apache-2.0
cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0
anyjson>=0.3.3 # BSD
httplib2>=0.7.5 # MIT
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
testtools>=1.4.0 # MIT
paramiko>=1.16.0 # LGPL
@ -25,3 +24,4 @@ PyYAML>=3.1.0 # MIT
stevedore>=1.5.0 # Apache-2.0
PrettyTable<0.8,>=0.7 # BSD
os-testr>=0.4.1 # Apache-2.0
urllib3>=1.8.3 # MIT

View File

@ -15,7 +15,6 @@
# under the License.
import argparse
import httplib2
import os
import sys
import traceback
@ -29,6 +28,7 @@ from six.moves.urllib import parse as urlparse
from tempest import clients
from tempest.common import credentials_factory as credentials
from tempest import config
import tempest.lib.common.http
CONF = config.CONF
@ -91,11 +91,12 @@ def _get_api_versions(os, service):
}
client_dict[service].skip_path()
endpoint = _get_unversioned_endpoint(client_dict[service].base_url)
dscv = CONF.identity.disable_ssl_certificate_validation
ca_certs = CONF.identity.ca_certificates_file
raw_http = httplib2.Http(disable_ssl_certificate_validation=dscv,
ca_certs=ca_certs)
__, body = raw_http.request(endpoint, 'GET')
http = tempest.lib.common.http.ClosingHttp(
CONF.identity.disable_ssl_certificate_validation,
CONF.identity.ca_certificates_file)
__, body = http.request(endpoint, 'GET')
client_dict[service].reset_path()
try:
body = json.loads(body)

View File

@ -1,5 +1,4 @@
# Copyright 2013 OpenStack Foundation
# Copyright 2013 Citrix Systems, Inc.
# Copyright 2016 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -14,12 +13,43 @@
# License for the specific language governing permissions and limitations
# under the License.
import httplib2
import urllib3
class ClosingHttp(httplib2.Http):
def request(self, *args, **kwargs):
class ClosingHttp(urllib3.poolmanager.PoolManager):
def __init__(self, disable_ssl_certificate_validation=False,
ca_certs=None):
kwargs = {}
if disable_ssl_certificate_validation:
urllib3.disable_warnings()
kwargs['cert_reqs'] = 'CERT_NONE'
if ca_certs:
kwargs['cert_reqs'] = 'CERT_REQUIRED'
kwargs['ca_certs'] = ca_certs
super(ClosingHttp, self).__init__(**kwargs)
def request(self, url, method, *args, **kwargs):
class Response(dict):
def __init__(self, info):
for key, value in info.getheaders().items():
self[key.lower()] = value
self.status = info.status
self['status'] = str(self.status)
self.reason = info.reason
self.version = info.version
self['content-location'] = url
original_headers = kwargs.get('headers', {})
new_headers = dict(original_headers, connection='close')
new_kwargs = dict(kwargs, headers=new_headers)
return super(ClosingHttp, self).request(*args, **new_kwargs)
# Follow up to 5 redirections. Don't raise an exception if
# it's exceeded but return the HTTP 3XX response instead.
retry = urllib3.util.Retry(raise_on_redirect=False, redirect=5)
r = super(ClosingHttp, self).request(method, url, retries=retry,
*args, **new_kwargs)
return Response(r), r.data

View File

@ -49,8 +49,9 @@ class TestDiscovery(base.TestCase):
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': {'values': [{'id': 'v2.0'}, {'id': 'v3.0'}]}}
fake_resp = json.dumps(fake_resp)
self.useFixture(mockpatch.Patch('httplib2.Http.request',
return_value=(None, fake_resp)))
self.useFixture(mockpatch.Patch(
'tempest.lib.common.http.ClosingHttp.request',
return_value=(None, fake_resp)))
fake_os = mock.MagicMock()
versions = verify_tempest_config._get_api_versions(fake_os, 'keystone')
self.assertIn('v2.0', versions)
@ -62,8 +63,9 @@ class TestDiscovery(base.TestCase):
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': [{'id': 'v1.0'}, {'id': 'v2.0'}]}
fake_resp = json.dumps(fake_resp)
self.useFixture(mockpatch.Patch('httplib2.Http.request',
return_value=(None, fake_resp)))
self.useFixture(mockpatch.Patch(
'tempest.lib.common.http.ClosingHttp.request',
return_value=(None, fake_resp)))
fake_os = mock.MagicMock()
versions = verify_tempest_config._get_api_versions(fake_os, 'cinder')
self.assertIn('v1.0', versions)
@ -75,8 +77,9 @@ class TestDiscovery(base.TestCase):
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': [{'id': 'v2.0'}, {'id': 'v3.0'}]}
fake_resp = json.dumps(fake_resp)
self.useFixture(mockpatch.Patch('httplib2.Http.request',
return_value=(None, fake_resp)))
self.useFixture(mockpatch.Patch(
'tempest.lib.common.http.ClosingHttp.request',
return_value=(None, fake_resp)))
fake_os = mock.MagicMock()
versions = verify_tempest_config._get_api_versions(fake_os, 'nova')
self.assertIn('v2.0', versions)
@ -95,8 +98,9 @@ class TestDiscovery(base.TestCase):
sample_body = (
'<html><head>Sample Response</head><body>This is the sample page '
'for the web server. Why are you requesting it?</body></html>')
self.useFixture(mockpatch.Patch('httplib2.Http.request',
return_value=(None, sample_body)))
self.useFixture(mockpatch.Patch(
'tempest.lib.common.http.ClosingHttp.request',
return_value=(None, sample_body)))
# service value doesn't matter, just needs to match what
# _get_api_versions puts in its client_dict.
@ -122,14 +126,14 @@ class TestDiscovery(base.TestCase):
verify_tempest_config.verify_api_versions(fake_os, 'foo', True)
self.assertFalse(verify_mock.called)
def test_verify_keystone_api_versions_no_v3(self):
@mock.patch('tempest.lib.common.http.ClosingHttp.request')
def test_verify_keystone_api_versions_no_v3(self, mock_request):
self.useFixture(mockpatch.PatchObject(
verify_tempest_config, '_get_unversioned_endpoint',
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': {'values': [{'id': 'v2.0'}]}}
fake_resp = json.dumps(fake_resp)
self.useFixture(mockpatch.Patch('httplib2.Http.request',
return_value=(None, fake_resp)))
mock_request.return_value = (None, fake_resp)
fake_os = mock.MagicMock()
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
@ -138,14 +142,14 @@ class TestDiscovery(base.TestCase):
'identity-feature-enabled',
False, True)
def test_verify_keystone_api_versions_no_v2(self):
@mock.patch('tempest.lib.common.http.ClosingHttp.request')
def test_verify_keystone_api_versions_no_v2(self, mock_request):
self.useFixture(mockpatch.PatchObject(
verify_tempest_config, '_get_unversioned_endpoint',
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': {'values': [{'id': 'v3.0'}]}}
fake_resp = json.dumps(fake_resp)
self.useFixture(mockpatch.Patch('httplib2.Http.request',
return_value=(None, fake_resp)))
mock_request.return_value = (None, fake_resp)
fake_os = mock.MagicMock()
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
@ -154,14 +158,14 @@ class TestDiscovery(base.TestCase):
'identity-feature-enabled',
False, True)
def test_verify_cinder_api_versions_no_v2(self):
@mock.patch('tempest.lib.common.http.ClosingHttp.request')
def test_verify_cinder_api_versions_no_v2(self, mock_request):
self.useFixture(mockpatch.PatchObject(
verify_tempest_config, '_get_unversioned_endpoint',
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': [{'id': 'v1.0'}]}
fake_resp = json.dumps(fake_resp)
self.useFixture(mockpatch.Patch('httplib2.Http.request',
return_value=(None, fake_resp)))
mock_request.return_value = (None, fake_resp)
fake_os = mock.MagicMock()
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:
@ -169,14 +173,14 @@ class TestDiscovery(base.TestCase):
print_mock.assert_called_once_with('api_v2', 'volume-feature-enabled',
False, True)
def test_verify_cinder_api_versions_no_v1(self):
@mock.patch('tempest.lib.common.http.ClosingHttp.request')
def test_verify_cinder_api_versions_no_v1(self, mock_request):
self.useFixture(mockpatch.PatchObject(
verify_tempest_config, '_get_unversioned_endpoint',
return_value='http://fake_endpoint:5000'))
fake_resp = {'versions': [{'id': 'v2.0'}]}
fake_resp = json.dumps(fake_resp)
self.useFixture(mockpatch.Patch('httplib2.Http.request',
return_value=(None, fake_resp)))
mock_request.return_value = (None, fake_resp)
fake_os = mock.MagicMock()
with mock.patch.object(verify_tempest_config,
'print_and_or_update') as print_mock:

View File

@ -22,8 +22,8 @@ from tempest.lib import exceptions as lib_exc
from tempest.lib.services.identity.v2 import token_client as v2_client
from tempest.lib.services.identity.v3 import token_client as v3_client
from tempest.tests import fake_config
from tempest.tests import fake_identity
from tempest.tests.lib import base
from tempest.tests.lib import fake_identity
class ConfiguredV2CredentialsTests(base.TestCase):

View File

@ -32,9 +32,9 @@ from tempest.services.identity.v2.json import users_client as \
json_users_client
from tempest.services.network.json import routers_client
from tempest.tests import fake_config
from tempest.tests import fake_http
from tempest.tests import fake_identity
from tempest.tests.lib import base
from tempest.tests.lib import fake_http
from tempest.tests.lib import fake_identity
class TestDynamicCredentialProvider(base.TestCase):
@ -47,7 +47,6 @@ class TestDynamicCredentialProvider(base.TestCase):
super(TestDynamicCredentialProvider, self).setUp()
self.useFixture(fake_config.ConfigFixture())
self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
self.fake_http = fake_http.fake_httplib2(return_type=200)
self.stubs.Set(json_token_client.TokenClient, 'raw_request',
fake_identity._fake_v2_response)
cfg.CONF.set_default('operator_role', 'FakeRole',
@ -402,7 +401,7 @@ class TestDynamicCredentialProvider(base.TestCase):
side_effect=side_effect)
secgroup_list_mock.start()
return_values = (fake_http.fake_httplib({}, status=204), {})
return_values = fake_http.fake_http_response({}, status=204), ''
remove_secgroup_mock = self.patch(
'tempest.lib.services.network.security_groups_client.'
'SecurityGroupsClient.delete', return_value=return_values)

View File

@ -29,9 +29,8 @@ from tempest.lib import auth
from tempest.lib import exceptions as lib_exc
from tempest.lib.services.identity.v2 import token_client
from tempest.tests import fake_config
from tempest.tests import fake_http
from tempest.tests import fake_identity
from tempest.tests.lib import base
from tempest.tests.lib import fake_identity
class TestPreProvisionedCredentials(base.TestCase):
@ -48,7 +47,6 @@ class TestPreProvisionedCredentials(base.TestCase):
super(TestPreProvisionedCredentials, self).setUp()
self.useFixture(fake_config.ConfigFixture())
self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
self.fake_http = fake_http.fake_httplib2(return_type=200)
self.stubs.Set(token_client.TokenClient, 'raw_request',
fake_identity._fake_v2_response)
self.useFixture(lockutils_fixtures.ExternalLockFixture())

View File

@ -1,74 +0,0 @@
# Copyright 2013 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import httplib2
class fake_httplib2(object):
def __init__(self, return_type=None, *args, **kwargs):
self.return_type = return_type
def request(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
if not self.return_type:
fake_headers = httplib2.Response(headers)
return_obj = {
'uri': uri,
'method': method,
'body': body,
'headers': headers
}
return (fake_headers, return_obj)
elif isinstance(self.return_type, int):
body = "fake_body"
header_info = {
'content-type': 'text/plain',
'status': str(self.return_type),
'content-length': len(body)
}
resp_header = httplib2.Response(header_info)
return (resp_header, body)
else:
msg = "unsupported return type %s" % self.return_type
raise TypeError(msg)
class fake_httplib(object):
def __init__(self, headers, body=None,
version=1.0, status=200, reason="Ok"):
"""Initialization of fake httplib
:param headers: dict representing HTTP response headers
:param body: file-like object
:param version: HTTP Version
:param status: Response status code
:param reason: Status code related message.
"""
self.body = body
self.status = status
self.reason = reason
self.version = version
self.headers = headers
def getheaders(self):
return copy.deepcopy(self.headers).items()
def getheader(self, key, default):
return self.headers.get(key, default)
def read(self, amt):
return self.body.read(amt)

View File

@ -1,163 +0,0 @@
# Copyright 2014 IBM Corp.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import httplib2
from oslo_serialization import jsonutils as json
FAKE_AUTH_URL = 'http://fake_uri.com/auth'
TOKEN = "fake_token"
ALT_TOKEN = "alt_fake_token"
# Fake Identity v2 constants
COMPUTE_ENDPOINTS_V2 = {
"endpoints": [
{
"adminURL": "http://fake_url/v2/first_endpoint/admin",
"region": "NoMatchRegion",
"internalURL": "http://fake_url/v2/first_endpoint/internal",
"publicURL": "http://fake_url/v2/first_endpoint/public"
},
{
"adminURL": "http://fake_url/v2/second_endpoint/admin",
"region": "FakeRegion",
"internalURL": "http://fake_url/v2/second_endpoint/internal",
"publicURL": "http://fake_url/v2/second_endpoint/public"
},
],
"type": "compute",
"name": "nova"
}
CATALOG_V2 = [COMPUTE_ENDPOINTS_V2, ]
ALT_IDENTITY_V2_RESPONSE = {
"access": {
"token": {
"expires": "2020-01-01T00:00:10Z",
"id": ALT_TOKEN,
"tenant": {
"id": "fake_tenant_id"
},
},
"user": {
"id": "fake_user_id",
},
"serviceCatalog": CATALOG_V2,
},
}
IDENTITY_V2_RESPONSE = {
"access": {
"token": {
"expires": "2020-01-01T00:00:10Z",
"id": TOKEN,
"tenant": {
"id": "fake_tenant_id"
},
},
"user": {
"id": "fake_user_id",
},
"serviceCatalog": CATALOG_V2,
},
}
# Fake Identity V3 constants
COMPUTE_ENDPOINTS_V3 = {
"endpoints": [
{
"id": "first_compute_fake_service",
"interface": "public",
"region": "NoMatchRegion",
"url": "http://fake_url/v3/first_endpoint/api"
},
{
"id": "second_fake_service",
"interface": "public",
"region": "FakeRegion",
"url": "http://fake_url/v3/second_endpoint/api"
},
{
"id": "third_fake_service",
"interface": "admin",
"region": "MiddleEarthRegion",
"url": "http://fake_url/v3/third_endpoint/api"
}
],
"type": "compute",
"id": "fake_compute_endpoint"
}
CATALOG_V3 = [COMPUTE_ENDPOINTS_V3, ]
IDENTITY_V3_RESPONSE = {
"token": {
"methods": [
"token",
"password"
],
"expires_at": "2020-01-01T00:00:10.000123Z",
"project": {
"domain": {
"id": "fake_domain_id",
"name": "fake"
},
"id": "project_id",
"name": "project_name"
},
"user": {
"domain": {
"id": "fake_domain_id",
"name": "domain_name"
},
"id": "fake_user_id",
"name": "username"
},
"issued_at": "2013-05-29T16:55:21.468960Z",
"catalog": CATALOG_V3
}
}
ALT_IDENTITY_V3 = IDENTITY_V3_RESPONSE
def _fake_v3_response(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
fake_headers = {
"status": "201",
"x-subject-token": TOKEN
}
return (httplib2.Response(fake_headers),
json.dumps(IDENTITY_V3_RESPONSE))
def _fake_v2_response(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
return (httplib2.Response({"status": "200"}),
json.dumps(IDENTITY_V2_RESPONSE))
def _fake_auth_failure_response():
# the response body isn't really used in this case, but lets send it anyway
# to have a safe check in some future change on the rest client.
body = {
"unauthorized": {
"message": "Unauthorized",
"code": "401"
}
}
return httplib2.Response({"status": "401"}), json.dumps(body)

View File

@ -14,8 +14,6 @@
import copy
import httplib2
class fake_httplib2(object):
@ -25,7 +23,7 @@ class fake_httplib2(object):
def request(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
if not self.return_type:
fake_headers = httplib2.Response(headers)
fake_headers = fake_http_response(headers)
return_obj = {
'uri': uri,
'method': method,
@ -37,20 +35,20 @@ class fake_httplib2(object):
body = body or "fake_body"
header_info = {
'content-type': 'text/plain',
'status': str(self.return_type),
'content-length': len(body)
}
resp_header = httplib2.Response(header_info)
resp_header = fake_http_response(header_info,
status=self.return_type)
return (resp_header, body)
else:
msg = "unsupported return type %s" % self.return_type
raise TypeError(msg)
class fake_httplib(object):
class fake_http_response(dict):
def __init__(self, headers, body=None,
version=1.0, status=200, reason="Ok"):
"""Fake httplib implementation
"""Initialization of fake HTTP Response
:param headers: dict representing HTTP response headers
:param body: file-like object
@ -60,10 +58,15 @@ class fake_httplib(object):
"""
self.body = body
self.status = status
self['status'] = str(self.status)
self.reason = reason
self.version = version
self.headers = headers
if headers:
for key, value in headers.items():
self[key.lower()] = value
def getheaders(self):
return copy.deepcopy(self.headers).items()

View File

@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import json
from oslo_serialization import jsonutils as json
import httplib2
from tempest.tests.lib import fake_http
FAKE_AUTH_URL = 'http://fake_uri.com/auth'
@ -139,16 +139,15 @@ ALT_IDENTITY_V3 = IDENTITY_V3_RESPONSE
def _fake_v3_response(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
fake_headers = {
"status": "201",
"x-subject-token": TOKEN
}
return (httplib2.Response(fake_headers),
return (fake_http.fake_http_response(fake_headers, status=201),
json.dumps(IDENTITY_V3_RESPONSE))
def _fake_v2_response(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
return (httplib2.Response({"status": "200"}),
return (fake_http.fake_http_response({}, status=200),
json.dumps(IDENTITY_V2_RESPONSE))
@ -161,4 +160,4 @@ def _fake_auth_failure_response():
"code": "401"
}
}
return httplib2.Response({"status": "401"}), json.dumps(body)
return fake_http.fake_http_response({}, status=401), json.dumps(body)

View File

@ -12,11 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import httplib2
from oslo_serialization import jsonutils as json
from oslotest import mockpatch
from tempest.tests.lib import base
from tempest.tests.lib import fake_http
class BaseComputeServiceTest(base.TestCase):
@ -26,11 +26,8 @@ class BaseComputeServiceTest(base.TestCase):
json_body = json.dumps(body)
if to_utf:
json_body = json_body.encode('utf-8')
resp_dict = {'status': status}
if headers:
resp_dict.update(headers)
response = (httplib2.Response(resp_dict), json_body)
return response
resp = fake_http.fake_http_response(headers, status=status), json_body
return resp
def check_service_client_function(self, function, function2mock,
body, to_utf=False, status=200,

View File

@ -12,14 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
import httplib2
import mock
from oslotest import mockpatch
from tempest.lib.common import rest_client
from tempest.lib import exceptions
from tempest.lib.services.compute import base_compute_client
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib import fake_http
from tempest.tests.lib.services.compute import base
@ -36,28 +35,29 @@ class TestMicroversionHeaderCheck(base.BaseComputeServiceTest):
super(TestMicroversionHeaderCheck, self).tearDown()
base_compute_client.COMPUTE_MICROVERSION = None
def _check_microverion_header_in_response(self, fake_response):
def request(*args, **kwargs):
return (httplib2.Response(fake_response), {})
self.useFixture(mockpatch.PatchObject(
rest_client.RestClient,
'request',
side_effect=request))
def test_correct_microverion_in_response(self):
fake_response = {self.client.api_microversion_header_name: '2.2'}
self._check_microverion_header_in_response(fake_response)
@mock.patch('tempest.lib.common.http.ClosingHttp.request')
def test_correct_microverion_in_response(self, mock_request):
response = fake_http.fake_http_response(
headers={self.client.api_microversion_header_name: '2.2'},
)
mock_request.return_value = response, ''
self.client.get('fake_url')
def test_incorrect_microverion_in_response(self):
fake_response = {self.client.api_microversion_header_name: '2.3'}
self._check_microverion_header_in_response(fake_response)
@mock.patch('tempest.lib.common.http.ClosingHttp.request')
def test_incorrect_microverion_in_response(self, mock_request):
response = fake_http.fake_http_response(
headers={self.client.api_microversion_header_name: '2.3'},
)
mock_request.return_value = response, ''
self.assertRaises(exceptions.InvalidHTTPResponseHeader,
self.client.get, 'fake_url')
def test_no_microverion_header_in_response(self):
self._check_microverion_header_in_response({})
@mock.patch('tempest.lib.common.http.ClosingHttp.request')
def test_no_microverion_header_in_response(self, mock_request):
response = fake_http.fake_http_response(
headers={},
)
mock_request.return_value = response, ''
self.assertRaises(exceptions.InvalidHTTPResponseHeader,
self.client.get, 'fake_url')
@ -164,7 +164,7 @@ class TestClientWithoutMicroversionHeader(base.BaseComputeServiceTest):
def test_no_microverion_header_in_raw_request(self):
def raw_request(*args, **kwargs):
self.assertNotIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
return (httplib2.Response({'status': 200}), {})
return (fake_http.fake_http_response({}, status=200), '')
with mock.patch.object(rest_client.RestClient,
'raw_request') as mock_get:
@ -196,9 +196,9 @@ class TestClientWithMicroversionHeader(base.BaseComputeServiceTest):
self.assertIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
self.assertEqual('2.2',
kwargs['headers']['X-OpenStack-Nova-API-Version'])
return (httplib2.Response(
{'status': 200,
self.client.api_microversion_header_name: '2.2'}), {})
return (fake_http.fake_http_response(
headers={self.client.api_microversion_header_name: '2.2'},
status=200), '')
with mock.patch.object(rest_client.RestClient,
'raw_request') as mock_get:

View File

@ -13,13 +13,13 @@
# under the License.
import copy
import httplib2
from oslo_serialization import jsonutils as json
from oslotest import mockpatch
from tempest.lib.services.compute import flavors_client
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib import fake_http
from tempest.tests.lib.services.compute import base
@ -117,7 +117,7 @@ class TestFlavorsClient(base.BaseComputeServiceTest):
body = json.dumps({'flavors': [TestFlavorsClient.FAKE_FLAVOR]})
if bytes_body:
body = body.encode('utf-8')
response = (httplib2.Response({'status': 200}), body)
response = fake_http.fake_http_response({}, status=200), body
self.useFixture(mockpatch.Patch(
'tempest.lib.common.rest_client.RestClient.get',
return_value=response))

View File

@ -12,12 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import httplib2
from oslotest import mockpatch
from tempest.tests.lib import fake_auth_provider
from tempest.lib.services.compute import server_groups_client
from tempest.tests.lib import fake_http
from tempest.tests.lib.services.compute import base
@ -50,7 +49,7 @@ class TestServerGroupsClient(base.BaseComputeServiceTest):
self._test_create_server_group(bytes_body=True)
def test_delete_server_group(self):
response = (httplib2.Response({'status': 204}), None)
response = fake_http.fake_http_response({}, status=204), ''
self.useFixture(mockpatch.Patch(
'tempest.lib.common.rest_client.RestClient.delete',
return_value=response))

View File

@ -14,8 +14,7 @@
import json
import httplib2
from oslotest import mockpatch
import mock
from tempest.lib.common import rest_client
from tempest.lib import exceptions
@ -28,7 +27,6 @@ class TestTokenClientV2(base.TestCase):
def setUp(self):
super(TestTokenClientV2, self).setUp()
self.fake_200_http = fake_http.fake_httplib2(return_type=200)
def test_init_without_authurl(self):
self.assertRaises(exceptions.IdentityError,
@ -36,10 +34,15 @@ class TestTokenClientV2(base.TestCase):
def test_auth(self):
token_client_v2 = token_client.TokenClient('fake_url')
post_mock = self.useFixture(mockpatch.PatchObject(
token_client_v2, 'post', return_value=self.fake_200_http.request(
'fake_url', body={'access': {'token': 'fake_token'}})))
resp = token_client_v2.auth('fake_user', 'fake_pass')
response = fake_http.fake_http_response(
None, status=200,
)
body = {'access': {'token': 'fake_token'}}
with mock.patch.object(token_client_v2, 'post') as post_mock:
post_mock.return_value = response, body
resp = token_client_v2.auth('fake_user', 'fake_pass')
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@ -49,15 +52,21 @@ class TestTokenClientV2(base.TestCase):
},
}
}, sort_keys=True)
post_mock.mock.assert_called_once_with('fake_url/tokens',
body=req_dict)
post_mock.assert_called_once_with('fake_url/tokens',
body=req_dict)
def test_auth_with_tenant(self):
token_client_v2 = token_client.TokenClient('fake_url')
post_mock = self.useFixture(mockpatch.PatchObject(
token_client_v2, 'post', return_value=self.fake_200_http.request(
'fake_url', body={'access': {'token': 'fake_token'}})))
resp = token_client_v2.auth('fake_user', 'fake_pass', 'fake_tenant')
response = fake_http.fake_http_response(
None, status=200,
)
body = {'access': {'token': 'fake_token'}}
with mock.patch.object(token_client_v2, 'post') as post_mock:
post_mock.return_value = response, body
resp = token_client_v2.auth('fake_user', 'fake_pass',
'fake_tenant')
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@ -68,25 +77,31 @@ class TestTokenClientV2(base.TestCase):
},
}
}, sort_keys=True)
post_mock.mock.assert_called_once_with('fake_url/tokens',
body=req_dict)
post_mock.assert_called_once_with('fake_url/tokens',
body=req_dict)
def test_request_with_str_body(self):
token_client_v2 = token_client.TokenClient('fake_url')
self.useFixture(mockpatch.PatchObject(
token_client_v2, 'raw_request', return_value=(
httplib2.Response({'status': '200'}),
str('{"access": {"token": "fake_token"}}'))))
resp, body = token_client_v2.request('GET', 'fake_uri')
self.assertIsInstance(resp, httplib2.Response)
response = fake_http.fake_http_response(
None, status=200,
)
body = str('{"access": {"token": "fake_token"}}')
with mock.patch.object(token_client_v2, 'raw_request') as mock_raw_r:
mock_raw_r.return_value = response, body
resp, body = token_client_v2.request('GET', 'fake_uri')
self.assertIsInstance(body, dict)
def test_request_with_bytes_body(self):
token_client_v2 = token_client.TokenClient('fake_url')
self.useFixture(mockpatch.PatchObject(
token_client_v2, 'raw_request', return_value=(
httplib2.Response({'status': '200'}),
bytes(b'{"access": {"token": "fake_token"}}'))))
resp, body = token_client_v2.request('GET', 'fake_uri')
self.assertIsInstance(resp, httplib2.Response)
response = fake_http.fake_http_response(
None, status=200,
)
body = b'{"access": {"token": "fake_token"}}'
with mock.patch.object(token_client_v2, 'raw_request') as mock_raw_r:
mock_raw_r.return_value = response, body
resp, body = token_client_v2.request('GET', 'fake_uri')
self.assertIsInstance(body, dict)

View File

@ -14,8 +14,7 @@
import json
import httplib2
from oslotest import mockpatch
import mock
from tempest.lib.common import rest_client
from tempest.lib import exceptions
@ -24,11 +23,10 @@ from tempest.tests.lib import base
from tempest.tests.lib import fake_http
class TestTokenClientV2(base.TestCase):
class TestTokenClientV3(base.TestCase):
def setUp(self):
super(TestTokenClientV2, self).setUp()
self.fake_201_http = fake_http.fake_httplib2(return_type=201)
super(TestTokenClientV3, self).setUp()
def test_init_without_authurl(self):
self.assertRaises(exceptions.IdentityError,
@ -36,10 +34,16 @@ class TestTokenClientV2(base.TestCase):
def test_auth(self):
token_client_v3 = token_client.V3TokenClient('fake_url')
post_mock = self.useFixture(mockpatch.PatchObject(
token_client_v3, 'post', return_value=self.fake_201_http.request(
'fake_url', body={'access': {'token': 'fake_token'}})))
resp = token_client_v3.auth(username='fake_user', password='fake_pass')
response = fake_http.fake_http_response(
None, status=201,
)
body = {'access': {'token': 'fake_token'}}
with mock.patch.object(token_client_v3, 'post') as post_mock:
post_mock.return_value = response, body
resp = token_client_v3.auth(username='fake_user',
password='fake_pass')
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@ -54,19 +58,24 @@ class TestTokenClientV2(base.TestCase):
},
}
}, sort_keys=True)
post_mock.mock.assert_called_once_with('fake_url/auth/tokens',
body=req_dict)
post_mock.assert_called_once_with('fake_url/auth/tokens',
body=req_dict)
def test_auth_with_project_id_and_domain_id(self):
token_client_v3 = token_client.V3TokenClient('fake_url')
post_mock = self.useFixture(mockpatch.PatchObject(
token_client_v3, 'post', return_value=self.fake_201_http.request(
'fake_url', body={'access': {'token': 'fake_token'}})))
resp = token_client_v3.auth(
username='fake_user', password='fake_pass',
project_id='fcac2a055a294e4c82d0a9c21c620eb4',
user_domain_id='14f4a9a99973404d8c20ba1d2af163ff',
project_domain_id='291f63ae9ac54ee292ca09e5f72d9676')
response = fake_http.fake_http_response(
None, status=201,
)
body = {'access': {'token': 'fake_token'}}
with mock.patch.object(token_client_v3, 'post') as post_mock:
post_mock.return_value = response, body
resp = token_client_v3.auth(
username='fake_user', password='fake_pass',
project_id='fcac2a055a294e4c82d0a9c21c620eb4',
user_domain_id='14f4a9a99973404d8c20ba1d2af163ff',
project_domain_id='291f63ae9ac54ee292ca09e5f72d9676')
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@ -92,16 +101,22 @@ class TestTokenClientV2(base.TestCase):
}
}
}, sort_keys=True)
post_mock.mock.assert_called_once_with('fake_url/auth/tokens',
body=req_dict)
post_mock.assert_called_once_with('fake_url/auth/tokens',
body=req_dict)
def test_auth_with_tenant(self):
token_client_v2 = token_client.V3TokenClient('fake_url')
post_mock = self.useFixture(mockpatch.PatchObject(
token_client_v2, 'post', return_value=self.fake_201_http.request(
'fake_url', body={'access': {'token': 'fake_token'}})))
resp = token_client_v2.auth(username='fake_user', password='fake_pass',
project_name='fake_tenant')
token_client_v3 = token_client.V3TokenClient('fake_url')
response = fake_http.fake_http_response(
None, status=201,
)
body = {'access': {'token': 'fake_token'}}
with mock.patch.object(token_client_v3, 'post') as post_mock:
post_mock.return_value = response, body
resp = token_client_v3.auth(username='fake_user',
password='fake_pass',
project_name='fake_tenant')
self.assertIsInstance(resp, rest_client.ResponseBody)
req_dict = json.dumps({
'auth': {
@ -121,25 +136,32 @@ class TestTokenClientV2(base.TestCase):
}
}, sort_keys=True)
post_mock.mock.assert_called_once_with('fake_url/auth/tokens',
body=req_dict)
post_mock.assert_called_once_with('fake_url/auth/tokens',
body=req_dict)
def test_request_with_str_body(self):
token_client_v3 = token_client.V3TokenClient('fake_url')
self.useFixture(mockpatch.PatchObject(
token_client_v3, 'raw_request', return_value=(
httplib2.Response({"status": "200"}),
str('{"access": {"token": "fake_token"}}'))))
resp, body = token_client_v3.request('GET', 'fake_uri')
self.assertIsInstance(resp, httplib2.Response)
response = fake_http.fake_http_response(
None, status=200,
)
body = str('{"access": {"token": "fake_token"}}')
with mock.patch.object(token_client_v3, 'raw_request') as mock_raw_r:
mock_raw_r.return_value = response, body
resp, body = token_client_v3.request('GET', 'fake_uri')
self.assertIsInstance(body, dict)
def test_request_with_bytes_body(self):
token_client_v3 = token_client.V3TokenClient('fake_url')
self.useFixture(mockpatch.PatchObject(
token_client_v3, 'raw_request', return_value=(
httplib2.Response({"status": "200"}),
bytes(b'{"access": {"token": "fake_token"}}'))))
resp, body = token_client_v3.request('GET', 'fake_uri')
self.assertIsInstance(resp, httplib2.Response)
response = fake_http.fake_http_response(
None, status=200,
)
body = b'{"access": {"token": "fake_token"}}'
with mock.patch.object(token_client_v3, 'raw_request') as mock_raw_r:
mock_raw_r.return_value = response, body
resp, body = token_client_v3.request('GET', 'fake_uri')
self.assertIsInstance(body, dict)

View File

@ -24,7 +24,6 @@ from tempest.lib.services.identity.v2 import token_client as v2_client
from tempest.lib.services.identity.v3 import token_client as v3_client
from tempest.tests.lib import base
from tempest.tests.lib import fake_credentials
from tempest.tests.lib import fake_http
from tempest.tests.lib import fake_identity
@ -42,7 +41,6 @@ class BaseAuthTestsSetUp(base.TestCase):
def setUp(self):
super(BaseAuthTestsSetUp, self).setUp()
self.fake_http = fake_http.fake_httplib2(return_type=200)
self.stubs.Set(auth, 'get_credentials', fake_get_credentials)
self.auth_provider = self._auth(self.credentials,
fake_identity.FAKE_AUTH_URL)

View File

@ -15,11 +15,11 @@
import copy
import json
import httplib2
import jsonschema
from oslotest import mockpatch
import six
from tempest.lib.common import http
from tempest.lib.common import rest_client
from tempest.lib import exceptions
from tempest.tests.lib import base
@ -37,7 +37,9 @@ class BaseRestClientTestClass(base.TestCase):
self.fake_auth_provider = fake_auth_provider.FakeAuthProvider()
self.rest_client = rest_client.RestClient(
self.fake_auth_provider, None, None)
self.stubs.Set(httplib2.Http, 'request', self.fake_http.request)
self.stubs.Set(http.ClosingHttp, 'request',
self.fake_http.request)
self.useFixture(mockpatch.PatchObject(self.rest_client,
'_log_request'))
@ -292,7 +294,9 @@ class TestRestClientErrorCheckerJSON(base.TestCase):
if absolute_limit is False:
resp_dict.update({'retry-after': 120})
resp_body.update({'overLimit': {'message': 'fake_message'}})
resp = httplib2.Response(resp_dict)
resp = fake_http.fake_http_response(headers=resp_dict,
status=int(r_code),
body=json.dumps(resp_body))
data = {
"method": "fake_method",
"url": "fake_url",

View File

@ -23,19 +23,14 @@ from six.moves import http_client as httplib
from tempest.common import glance_http
from tempest import exceptions
from tempest.tests import fake_auth_provider
from tempest.tests import fake_http
from tempest.tests.lib import base
from tempest.tests.lib import fake_http
class TestGlanceHTTPClient(base.TestCase):
def setUp(self):
super(TestGlanceHTTPClient, self).setUp()
self.fake_http = fake_http.fake_httplib2(return_type=200)
# NOTE(maurosr): using http here implies that we will be using httplib
# directly. With https glance_client would use an httpS version, but
# the real backend would still be httplib anyway and since we mock it
# that there is no reason to care.
self.endpoint = 'http://fake_url.com'
self.fake_auth = fake_auth_provider.FakeAuthProvider()
@ -44,12 +39,12 @@ class TestGlanceHTTPClient(base.TestCase):
self.useFixture(mockpatch.PatchObject(
httplib.HTTPConnection,
'request',
side_effect=self.fake_http.request(self.endpoint)[1]))
side_effect=b'fake_body'))
self.client = glance_http.HTTPClient(self.fake_auth, {})
def _set_response_fixture(self, header, status, resp_body):
resp = fake_http.fake_httplib(header, status=status,
body=six.StringIO(resp_body))
resp = fake_http.fake_http_response(header, status=status,
body=six.StringIO(resp_body))
self.useFixture(mockpatch.PatchObject(httplib.HTTPConnection,
'getresponse', return_value=resp))
return resp
@ -223,7 +218,7 @@ class TestVerifiedHTTPSConnection(base.TestCase):
class TestResponseBodyIterator(base.TestCase):
def test_iter_default_chunk_size_64k(self):
resp = fake_http.fake_httplib({}, six.StringIO(
resp = fake_http.fake_http_response({}, six.StringIO(
'X' * (glance_http.CHUNKSIZE + 1)))
iterator = glance_http.ResponseBodyIterator(resp)
chunks = list(iterator)

View File

@ -15,14 +15,13 @@
# License for the specific language governing permissions and limitations
# under the License.
import httplib2
import mock
from oslotest import mockpatch
from tempest.common import negative_rest_client
from tempest import config
from tempest.tests import fake_auth_provider
from tempest.tests import fake_config
from tempest.tests import fake_http
from tempest.tests.lib import base
@ -31,59 +30,69 @@ class TestNegativeRestClient(base.TestCase):
url = 'fake_endpoint'
def setUp(self):
self.fake_http = fake_http.fake_httplib2()
super(TestNegativeRestClient, self).setUp()
self.useFixture(fake_config.ConfigFixture())
self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
self.stubs.Set(httplib2.Http, 'request', self.fake_http.request)
self.negative_rest_client = negative_rest_client.NegativeRestClient(
fake_auth_provider.FakeAuthProvider(), None)
self.useFixture(mockpatch.PatchObject(self.negative_rest_client,
'_log_request'))
def test_post(self):
@mock.patch('tempest.lib.common.rest_client.RestClient.post',
return_value=(mock.Mock(), mock.Mock()))
def test_post(self, mock_post):
__, return_dict = self.negative_rest_client.send_request('POST',
self.url,
[], {})
self.assertEqual('POST', return_dict['method'])
mock_post.assert_called_once_with(self.url, {})
def test_get(self):
@mock.patch('tempest.lib.common.rest_client.RestClient.get',
return_value=(mock.Mock(), mock.Mock()))
def test_get(self, mock_get):
__, return_dict = self.negative_rest_client.send_request('GET',
self.url,
[])
self.assertEqual('GET', return_dict['method'])
mock_get.assert_called_once_with(self.url)
def test_delete(self):
@mock.patch('tempest.lib.common.rest_client.RestClient.delete',
return_value=(mock.Mock(), mock.Mock()))
def test_delete(self, mock_delete):
__, return_dict = self.negative_rest_client.send_request('DELETE',
self.url,
[])
self.assertEqual('DELETE', return_dict['method'])
mock_delete.assert_called_once_with(self.url)
def test_patch(self):
@mock.patch('tempest.lib.common.rest_client.RestClient.patch',
return_value=(mock.Mock(), mock.Mock()))
def test_patch(self, mock_patch):
__, return_dict = self.negative_rest_client.send_request('PATCH',
self.url,
[], {})
self.assertEqual('PATCH', return_dict['method'])
mock_patch.assert_called_once_with(self.url, {})
def test_put(self):
@mock.patch('tempest.lib.common.rest_client.RestClient.put',
return_value=(mock.Mock(), mock.Mock()))
def test_put(self, mock_put):
__, return_dict = self.negative_rest_client.send_request('PUT',
self.url,
[], {})
self.assertEqual('PUT', return_dict['method'])
mock_put.assert_called_once_with(self.url, {})
def test_head(self):
self.useFixture(mockpatch.PatchObject(self.negative_rest_client,
'response_checker'))
@mock.patch('tempest.lib.common.rest_client.RestClient.head',
return_value=(mock.Mock(), mock.Mock()))
def test_head(self, mock_head):
__, return_dict = self.negative_rest_client.send_request('HEAD',
self.url,
[])
self.assertEqual('HEAD', return_dict['method'])
mock_head.assert_called_once_with(self.url)
def test_copy(self):
@mock.patch('tempest.lib.common.rest_client.RestClient.copy',
return_value=(mock.Mock(), mock.Mock()))
def test_copy(self, mock_copy):
__, return_dict = self.negative_rest_client.send_request('COPY',
self.url,
[])
self.assertEqual('COPY', return_dict['method'])
mock_copy.assert_called_once_with(self.url)
def test_other(self):
self.assertRaises(AssertionError,