Merge "Adds a base class for functional tests"
This commit is contained in:
commit
200e7f3dff
0
keystone/tests/common/__init__.py
Normal file
0
keystone/tests/common/__init__.py
Normal file
91
keystone/tests/common/auth.py
Normal file
91
keystone/tests/common/auth.py
Normal file
@ -0,0 +1,91 @@
|
||||
# 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.
|
||||
|
||||
|
||||
class AuthTestMixin(object):
|
||||
"""To hold auth building helper functions."""
|
||||
|
||||
def _build_auth_scope(self, project_id=None, project_name=None,
|
||||
project_domain_id=None, project_domain_name=None,
|
||||
domain_id=None, domain_name=None, trust_id=None,
|
||||
unscoped=None):
|
||||
scope_data = {}
|
||||
if unscoped:
|
||||
scope_data['unscoped'] = {}
|
||||
if project_id or project_name:
|
||||
scope_data['project'] = {}
|
||||
if project_id:
|
||||
scope_data['project']['id'] = project_id
|
||||
else:
|
||||
scope_data['project']['name'] = project_name
|
||||
if project_domain_id or project_domain_name:
|
||||
project_domain_json = {}
|
||||
if project_domain_id:
|
||||
project_domain_json['id'] = project_domain_id
|
||||
else:
|
||||
project_domain_json['name'] = project_domain_name
|
||||
scope_data['project']['domain'] = project_domain_json
|
||||
if domain_id or domain_name:
|
||||
scope_data['domain'] = {}
|
||||
if domain_id:
|
||||
scope_data['domain']['id'] = domain_id
|
||||
else:
|
||||
scope_data['domain']['name'] = domain_name
|
||||
if trust_id:
|
||||
scope_data['OS-TRUST:trust'] = {}
|
||||
scope_data['OS-TRUST:trust']['id'] = trust_id
|
||||
return scope_data
|
||||
|
||||
def _build_password_auth(self, user_id=None, username=None,
|
||||
user_domain_id=None, user_domain_name=None,
|
||||
password=None):
|
||||
password_data = {'user': {}}
|
||||
if user_id:
|
||||
password_data['user']['id'] = user_id
|
||||
else:
|
||||
password_data['user']['name'] = username
|
||||
if user_domain_id or user_domain_name:
|
||||
password_data['user']['domain'] = {}
|
||||
if user_domain_id:
|
||||
password_data['user']['domain']['id'] = user_domain_id
|
||||
else:
|
||||
password_data['user']['domain']['name'] = user_domain_name
|
||||
password_data['user']['password'] = password
|
||||
return password_data
|
||||
|
||||
def _build_token_auth(self, token):
|
||||
return {'id': token}
|
||||
|
||||
def build_authentication_request(self, token=None, user_id=None,
|
||||
username=None, user_domain_id=None,
|
||||
user_domain_name=None, password=None,
|
||||
kerberos=False, **kwargs):
|
||||
"""Build auth dictionary.
|
||||
|
||||
It will create an auth dictionary based on all the arguments
|
||||
that it receives.
|
||||
"""
|
||||
auth_data = {}
|
||||
auth_data['identity'] = {'methods': []}
|
||||
if kerberos:
|
||||
auth_data['identity']['methods'].append('kerberos')
|
||||
auth_data['identity']['kerberos'] = {}
|
||||
if token:
|
||||
auth_data['identity']['methods'].append('token')
|
||||
auth_data['identity']['token'] = self._build_token_auth(token)
|
||||
if user_id or username:
|
||||
auth_data['identity']['methods'].append('password')
|
||||
auth_data['identity']['password'] = self._build_password_auth(
|
||||
user_id, username, user_domain_id, user_domain_name, password)
|
||||
if kwargs:
|
||||
auth_data['scope'] = self._build_auth_scope(**kwargs)
|
||||
return {'auth': auth_data}
|
85
keystone/tests/functional/core.py
Normal file
85
keystone/tests/functional/core.py
Normal file
@ -0,0 +1,85 @@
|
||||
# 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 os
|
||||
|
||||
import requests
|
||||
import testtools
|
||||
|
||||
from keystone.tests.common import auth as common_auth
|
||||
|
||||
|
||||
class BaseTestCase(testtools.TestCase, common_auth.AuthTestMixin):
|
||||
|
||||
request_headers = {'content-type': 'application/json'}
|
||||
|
||||
def setUp(self):
|
||||
self.ADMIN_URL = os.environ.get('KSTEST_ADMIN_URL',
|
||||
'http://localhost:35357')
|
||||
self.PUBLIC_URL = os.environ.get('KSTEST_PUBLIC_URL',
|
||||
'http://localhost:5000')
|
||||
self.admin = {
|
||||
'name': os.environ.get('KSTEST_ADMIN_USERNAME', 'admin'),
|
||||
'password': os.environ.get('KSTEST_ADMIN_PASSWORD', ''),
|
||||
'domain_id': os.environ.get('KSTEST_ADMIN_DOMAIN_ID', 'default')
|
||||
}
|
||||
|
||||
self.user = {
|
||||
'name': os.environ.get('KSTEST_USER_USERNAME', 'demo'),
|
||||
'password': os.environ.get('KSTEST_USER_PASSWORD', ''),
|
||||
'domain_id': os.environ.get('KSTEST_USER_DOMAIN_ID', 'default')
|
||||
}
|
||||
|
||||
self.project_id = os.environ.get('KSTEST_PROJECT_ID')
|
||||
|
||||
super(BaseTestCase, self).setUp()
|
||||
|
||||
def _http_headers(self, token=None):
|
||||
headers = {'content-type': 'application/json'}
|
||||
if token:
|
||||
headers['X-Auth-Token'] = token
|
||||
return headers
|
||||
|
||||
def get_scoped_token_response(self, user):
|
||||
"""Convenience method so that we can test authenticated requests
|
||||
|
||||
:param user: A dictionary with user information like 'username',
|
||||
'password', 'domain_id'
|
||||
:returns: urllib3.Response object
|
||||
|
||||
"""
|
||||
body = self.build_authentication_request(
|
||||
username=user['name'], user_domain_name=user['domain_id'],
|
||||
password=user['password'], project_id=self.project_id)
|
||||
return requests.post(self.PUBLIC_URL + '/v3/auth/tokens',
|
||||
headers=self.request_headers,
|
||||
json=body)
|
||||
|
||||
def get_scoped_token(self, user):
|
||||
"""Convenience method for getting scoped token
|
||||
|
||||
This method doesn't do any token validaton.
|
||||
|
||||
:param user: A dictionary with user information like 'username',
|
||||
'password', 'domain_id'
|
||||
:returns: An OpenStack token for further use
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
r = self.get_scoped_token_response(user)
|
||||
return r.headers.get('X-Subject-Token')
|
||||
|
||||
def get_scoped_admin_token(self):
|
||||
return self.get_scoped_token(self.admin)
|
||||
|
||||
def get_scoped_user_token(self):
|
||||
return self.get_scoped_token(self.user)
|
@ -13,42 +13,46 @@
|
||||
import requests
|
||||
import testtools.matchers
|
||||
|
||||
from keystone.tests.functional import core as functests
|
||||
|
||||
|
||||
is_multiple_choices = testtools.matchers.Equals(
|
||||
requests.status_codes.codes.multiple_choices)
|
||||
is_ok = testtools.matchers.Equals(requests.status_codes.codes.ok)
|
||||
|
||||
versions = ('v2.0', 'v3')
|
||||
|
||||
class TestServerRunning(testtools.TestCase):
|
||||
versions = ('v2.0', 'v3')
|
||||
admin_url = 'http://localhost:35357'
|
||||
public_url = 'http://localhost:5000'
|
||||
|
||||
class TestServerRunning(functests.BaseTestCase):
|
||||
|
||||
def test_admin_responds_with_multiple_choices(self):
|
||||
resp = requests.get(self.admin_url)
|
||||
resp = requests.get(self.ADMIN_URL)
|
||||
self.assertThat(resp.status_code, is_multiple_choices)
|
||||
|
||||
def test_admin_versions(self):
|
||||
for version in self.versions:
|
||||
resp = requests.get(self.admin_url + '/' + version)
|
||||
for version in versions:
|
||||
resp = requests.get(self.ADMIN_URL + '/' + version)
|
||||
self.assertThat(
|
||||
resp.status_code,
|
||||
testtools.matchers.Annotate(
|
||||
'failed for version %s' % version, is_ok))
|
||||
|
||||
def test_public_responds_with_multiple_choices(self):
|
||||
resp = requests.get(self.public_url)
|
||||
resp = requests.get(self.PUBLIC_URL)
|
||||
self.assertThat(resp.status_code, is_multiple_choices)
|
||||
|
||||
def test_public_versions(self):
|
||||
for version in self.versions:
|
||||
resp = requests.get(self.public_url + '/' + version)
|
||||
for version in versions:
|
||||
resp = requests.get(self.PUBLIC_URL + '/' + version)
|
||||
self.assertThat(
|
||||
resp.status_code,
|
||||
testtools.matchers.Annotate(
|
||||
'failed for version %s' % version, is_ok))
|
||||
|
||||
def test_get_user_token(self):
|
||||
token = self.get_scoped_user_token()
|
||||
self.assertIsNotNone(token)
|
||||
|
||||
class TestServerRunningOnPath(TestServerRunning):
|
||||
admin_url = 'http://localhost/identity_admin'
|
||||
public_url = 'http://localhost/identity'
|
||||
def test_get_admin_token(self):
|
||||
token = self.get_scoped_admin_token()
|
||||
self.assertIsNotNone(token)
|
||||
|
@ -29,6 +29,7 @@ from keystone.common.validation import validators
|
||||
from keystone import exception
|
||||
from keystone import middleware
|
||||
from keystone.policy.backends import rules
|
||||
from keystone.tests.common import auth as common_auth
|
||||
from keystone.tests import unit
|
||||
from keystone.tests.unit import rest
|
||||
|
||||
@ -120,7 +121,7 @@ class AuthTestMixin(object):
|
||||
|
||||
|
||||
class RestfulTestCase(unit.SQLDriverOverrides, rest.RestfulTestCase,
|
||||
AuthTestMixin):
|
||||
common_auth.AuthTestMixin):
|
||||
def config_files(self):
|
||||
config_files = super(RestfulTestCase, self).config_files()
|
||||
config_files.append(unit.dirs.tests_conf('backend_sql.conf'))
|
||||
|
@ -33,6 +33,7 @@ from keystone.common import utils
|
||||
from keystone.contrib.revoke import routers
|
||||
from keystone import exception
|
||||
from keystone.policy.backends import rules
|
||||
from keystone.tests.common import auth as common_auth
|
||||
from keystone.tests import unit
|
||||
from keystone.tests.unit import ksfixtures
|
||||
from keystone.tests.unit import test_v3
|
||||
@ -40,7 +41,7 @@ from keystone.tests.unit import test_v3
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class TestAuthInfo(test_v3.AuthTestMixin, testcase.TestCase):
|
||||
class TestAuthInfo(common_auth.AuthTestMixin, testcase.TestCase):
|
||||
def setUp(self):
|
||||
super(TestAuthInfo, self).setUp()
|
||||
auth.controllers.load_auth_methods()
|
||||
|
20
tox.ini
20
tox.ini
@ -116,12 +116,32 @@ commands = {posargs}
|
||||
|
||||
[testenv:debug]
|
||||
commands = oslo_debug_helper {posargs}
|
||||
passenv =
|
||||
KSTEST_ADMIN_URL
|
||||
KSTEST_ADMIN_USERNAME
|
||||
KSTEST_ADMIN_PASSWORD
|
||||
KSTEST_ADMIN_DOMAIN_ID
|
||||
KSTEST_PUBLIC_URL
|
||||
KSTEST_USER_USERNAME
|
||||
KSTEST_USER_PASSWORD
|
||||
KSTEST_USER_DOMAIN_ID
|
||||
KSTEST_PROJECT_ID
|
||||
|
||||
[testenv:functional]
|
||||
basepython = python3.4
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
setenv = OS_TEST_PATH=./keystone/tests/functional
|
||||
commands = python setup.py testr --slowest --testr-args='{posargs}'
|
||||
passenv =
|
||||
KSTEST_ADMIN_URL
|
||||
KSTEST_ADMIN_USERNAME
|
||||
KSTEST_ADMIN_PASSWORD
|
||||
KSTEST_ADMIN_DOMAIN_ID
|
||||
KSTEST_PUBLIC_URL
|
||||
KSTEST_USER_USERNAME
|
||||
KSTEST_USER_PASSWORD
|
||||
KSTEST_USER_DOMAIN_ID
|
||||
KSTEST_PROJECT_ID
|
||||
|
||||
[flake8]
|
||||
filename= *.py,keystone-all,keystone-manage
|
||||
|
Loading…
Reference in New Issue
Block a user