Merge "Use testr instead of nose."
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,6 @@
|
|||||||
.coverage
|
.coverage
|
||||||
|
.testrepository
|
||||||
|
subunit.log
|
||||||
.venv
|
.venv
|
||||||
*,cover
|
*,cover
|
||||||
cover
|
cover
|
||||||
|
4
.testr.conf
Normal file
4
.testr.conf
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
test_command=${PYTHON:-python} -m subunit.run discover -t ./ ./tests $LISTOPT $IDOPTION
|
||||||
|
test_id_option=--load-list $IDFILE
|
||||||
|
test_list_option=--list
|
14
HACKING
14
HACKING
@@ -81,3 +81,17 @@ Exceptions
|
|||||||
|
|
||||||
When dealing with exceptions from underlying libraries, translate those
|
When dealing with exceptions from underlying libraries, translate those
|
||||||
exceptions to an instance or subclass of ClientException.
|
exceptions to an instance or subclass of ClientException.
|
||||||
|
|
||||||
|
=======
|
||||||
|
Testing
|
||||||
|
=======
|
||||||
|
|
||||||
|
python-keystoneclient uses testtools and testr for its unittest suite
|
||||||
|
and its test runner. Basic workflow around our use of tox and testr can
|
||||||
|
be found at http://wiki.openstack.org/testr. If you'd like to learn more
|
||||||
|
in depth:
|
||||||
|
|
||||||
|
https://testtools.readthedocs.org/
|
||||||
|
https://testrepository.readthedocs.org/
|
||||||
|
|
||||||
|
Happy hacking!
|
||||||
|
@@ -1,67 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright 2012 OpenStack LLC
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
#
|
|
||||||
# Test support for middleware authentication
|
|
||||||
#
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
ROOTDIR = os.path.abspath(os.curdir)
|
|
||||||
|
|
||||||
|
|
||||||
def rootdir(*p):
|
|
||||||
return os.path.join(ROOTDIR, *p)
|
|
||||||
|
|
||||||
|
|
||||||
class NoModule(object):
|
|
||||||
"""A mixin class to provide support for unloading/disabling modules."""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kw):
|
|
||||||
super(NoModule, self).__init__(*args, **kw)
|
|
||||||
self._finders = []
|
|
||||||
self._cleared_modules = {}
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super(NoModule, self).tearDown()
|
|
||||||
for finder in self._finders:
|
|
||||||
sys.meta_path.remove(finder)
|
|
||||||
sys.modules.update(self._cleared_modules)
|
|
||||||
|
|
||||||
def clear_module(self, module):
|
|
||||||
cleared_modules = {}
|
|
||||||
for fullname in sys.modules.keys():
|
|
||||||
if fullname == module or fullname.startswith(module + '.'):
|
|
||||||
cleared_modules[fullname] = sys.modules.pop(fullname)
|
|
||||||
return cleared_modules
|
|
||||||
|
|
||||||
def disable_module(self, module):
|
|
||||||
"""Ensure ImportError for the specified module."""
|
|
||||||
|
|
||||||
# Clear 'module' references in sys.modules
|
|
||||||
self._cleared_modules.update(self.clear_module(module))
|
|
||||||
|
|
||||||
# Disallow further imports of 'module'
|
|
||||||
class NoModule(object):
|
|
||||||
def find_module(self, fullname, path):
|
|
||||||
if fullname == module or fullname.startswith(module + '.'):
|
|
||||||
raise ImportError
|
|
||||||
|
|
||||||
finder = NoModule()
|
|
||||||
self._finders.append(finder)
|
|
||||||
sys.meta_path.insert(0, finder)
|
|
90
run_tests.sh
90
run_tests.sh
@@ -14,6 +14,7 @@ function usage {
|
|||||||
echo " -p, --pep8 Just run pep8"
|
echo " -p, --pep8 Just run pep8"
|
||||||
echo " -P, --no-pep8 Don't run pep8"
|
echo " -P, --no-pep8 Don't run pep8"
|
||||||
echo " -c, --coverage Generate coverage report"
|
echo " -c, --coverage Generate coverage report"
|
||||||
|
echo " -d, --debug Run tests with testtools instead of testr. This allows you to use the debugger."
|
||||||
echo " -h, --help Print this usage message"
|
echo " -h, --help Print this usage message"
|
||||||
echo " --hide-elapsed Don't print the elapsed time for each test along with slow test list"
|
echo " --hide-elapsed Don't print the elapsed time for each test along with slow test list"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -33,8 +34,9 @@ function process_option {
|
|||||||
-p|--pep8) just_pep8=1;;
|
-p|--pep8) just_pep8=1;;
|
||||||
-P|--no-pep8) no_pep8=1;;
|
-P|--no-pep8) no_pep8=1;;
|
||||||
-c|--coverage) coverage=1;;
|
-c|--coverage) coverage=1;;
|
||||||
-*) noseopts="$noseopts $1";;
|
-d|--debug) debug=1;;
|
||||||
*) noseargs="$noseargs $1"
|
-*) testropts="$testropts $1";;
|
||||||
|
*) testrargs="$testrargs $1"
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,34 +47,86 @@ never_venv=0
|
|||||||
force=0
|
force=0
|
||||||
no_site_packages=0
|
no_site_packages=0
|
||||||
installvenvopts=
|
installvenvopts=
|
||||||
noseargs=
|
testrargs=
|
||||||
noseopts=
|
testropts=
|
||||||
wrapper=""
|
wrapper=""
|
||||||
just_pep8=0
|
just_pep8=0
|
||||||
no_pep8=0
|
no_pep8=0
|
||||||
coverage=0
|
coverage=0
|
||||||
|
debug=0
|
||||||
|
|
||||||
|
LANG=en_US.UTF-8
|
||||||
|
LANGUAGE=en_US:en
|
||||||
|
LC_ALL=C
|
||||||
|
OS_STDOUT_NOCAPTURE=False
|
||||||
|
OS_STDERR_NOCAPTURE=False
|
||||||
|
|
||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
process_option $arg
|
process_option $arg
|
||||||
done
|
done
|
||||||
|
|
||||||
# If enabled, tell nose to collect coverage data
|
|
||||||
if [ $coverage -eq 1 ]; then
|
|
||||||
noseopts="$noseopts --with-coverage --cover-package=keystoneclient"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $no_site_packages -eq 1 ]; then
|
if [ $no_site_packages -eq 1 ]; then
|
||||||
installvenvopts="--no-site-packages"
|
installvenvopts="--no-site-packages"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
function init_testr {
|
||||||
|
if [ ! -d .testrepository ]; then
|
||||||
|
${wrapper} testr init
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
function run_tests {
|
function run_tests {
|
||||||
|
# Cleanup *.pyc
|
||||||
|
${wrapper} find . -type f -name "*.pyc" -delete
|
||||||
|
|
||||||
|
if [ $debug -eq 1 ]; then
|
||||||
|
if [ "$testropts" = "" ] && [ "$testrargs" = "" ]; then
|
||||||
|
# Default to running all tests if specific test is not
|
||||||
|
# provided.
|
||||||
|
testrargs="discover ./tests"
|
||||||
|
fi
|
||||||
|
${wrapper} python -m testtools.run $testropts $testrargs
|
||||||
|
|
||||||
|
# Short circuit because all of the testr and coverage stuff
|
||||||
|
# below does not make sense when running testtools.run for
|
||||||
|
# debugging purposes.
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $coverage -eq 1 ]; then
|
||||||
|
TESTRTESTS="$TESTRTESTS --coverage"
|
||||||
|
else
|
||||||
|
TESTRTESTS="$TESTRTESTS"
|
||||||
|
fi
|
||||||
|
|
||||||
# Just run the test suites in current environment
|
# Just run the test suites in current environment
|
||||||
${wrapper} $NOSETESTS
|
set +e
|
||||||
# If we get some short import error right away, print the error log directly
|
testrargs=`echo "$testrargs" | sed -e's/^\s*\(.*\)\s*$/\1/'`
|
||||||
|
TESTRTESTS="$TESTRTESTS --testr-args='$testropts $testrargs'"
|
||||||
|
echo "Running \`${wrapper} $TESTRTESTS\`"
|
||||||
|
bash -c "${wrapper} $TESTRTESTS"
|
||||||
RESULT=$?
|
RESULT=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
copy_subunit_log
|
||||||
|
|
||||||
|
if [ $coverage -eq 1 ]; then
|
||||||
|
echo "Generating coverage report in covhtml/"
|
||||||
|
# Don't compute coverage for common code, which is tested elsewhere
|
||||||
|
${wrapper} coverage combine
|
||||||
|
${wrapper} coverage html --include='keystoneclient/*' --omit='keystoneclient/openstack/common/*' -d covhtml -i
|
||||||
|
fi
|
||||||
|
|
||||||
return $RESULT
|
return $RESULT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copy_subunit_log {
|
||||||
|
LOGNAME=`cat .testrepository/next-stream`
|
||||||
|
LOGNAME=$(($LOGNAME - 1))
|
||||||
|
LOGNAME=".testrepository/${LOGNAME}"
|
||||||
|
cp $LOGNAME subunit.log
|
||||||
|
}
|
||||||
|
|
||||||
function run_pep8 {
|
function run_pep8 {
|
||||||
echo "Running pep8 ..."
|
echo "Running pep8 ..."
|
||||||
srcfiles="keystoneclient tests"
|
srcfiles="keystoneclient tests"
|
||||||
@@ -85,7 +139,7 @@ function run_pep8 {
|
|||||||
${srcfiles}
|
${srcfiles}
|
||||||
}
|
}
|
||||||
|
|
||||||
NOSETESTS="nosetests $noseopts $noseargs"
|
TESTRTESTS="python setup.py testr"
|
||||||
|
|
||||||
if [ $never_venv -eq 0 ]
|
if [ $never_venv -eq 0 ]
|
||||||
then
|
then
|
||||||
@@ -123,19 +177,15 @@ if [ $just_pep8 -eq 1 ]; then
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
init_testr
|
||||||
run_tests
|
run_tests
|
||||||
|
|
||||||
# NOTE(sirp): we only want to run pep8 when we're running the full-test suite,
|
# NOTE(sirp): we only want to run pep8 when we're running the full-test suite,
|
||||||
# not when we're running tests individually. To handle this, we need to
|
# not when we're running tests individually. To handle this, we need to
|
||||||
# distinguish between options (noseopts), which begin with a '-', and
|
# distinguish between options (testropts), which begin with a '-', and
|
||||||
# arguments (noseargs).
|
# arguments (testrargs).
|
||||||
if [ -z "$noseargs" ]; then
|
if [ -z "$testrargs" ]; then
|
||||||
if [ $no_pep8 -eq 0 ]; then
|
if [ $no_pep8 -eq 0 ]; then
|
||||||
run_pep8
|
run_pep8
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $coverage -eq 1 ]; then
|
|
||||||
echo "Generating coverage report in covhtml/"
|
|
||||||
${wrapper} coverage html -d covhtml -i
|
|
||||||
fi
|
|
||||||
|
@@ -1,10 +1,3 @@
|
|||||||
[nosetests]
|
|
||||||
verbosity=2
|
|
||||||
detailed-errors=1
|
|
||||||
cover-package = keystoneclient
|
|
||||||
cover-erase = true
|
|
||||||
cover-inclusive = true
|
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
build-dir = doc/build
|
build-dir = doc/build
|
||||||
|
1
setup.py
1
setup.py
@@ -37,7 +37,6 @@ setuptools.setup(
|
|||||||
cmdclass=setup.get_cmdclass(),
|
cmdclass=setup.get_cmdclass(),
|
||||||
|
|
||||||
tests_require=tests_require,
|
tests_require=tests_require,
|
||||||
test_suite="nose.collector",
|
|
||||||
|
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': ['keystone = keystoneclient.shell:main']
|
'console_scripts': ['keystone = keystoneclient.shell:main']
|
||||||
|
@@ -22,6 +22,7 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
import fixtures
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
from keystoneclient.common import cms
|
from keystoneclient.common import cms
|
||||||
@@ -31,12 +32,13 @@ from keystoneclient.middleware import memcache_crypt
|
|||||||
from keystoneclient.openstack.common import memorycache
|
from keystoneclient.openstack.common import memorycache
|
||||||
from keystoneclient.openstack.common import jsonutils
|
from keystoneclient.openstack.common import jsonutils
|
||||||
from keystoneclient.openstack.common import timeutils
|
from keystoneclient.openstack.common import timeutils
|
||||||
from keystoneclient.middleware import test
|
|
||||||
|
|
||||||
|
|
||||||
CERTDIR = test.rootdir('examples', 'pki', 'certs')
|
ROOTDIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||||
KEYDIR = test.rootdir('examples', 'pki', 'private')
|
|
||||||
CMSDIR = test.rootdir('examples', 'pki', 'cms')
|
CERTDIR = os.path.join(ROOTDIR, "examples/pki/certs")
|
||||||
|
KEYDIR = os.path.join(ROOTDIR, "examples/pki/private")
|
||||||
|
CMSDIR = os.path.join(ROOTDIR, "examples/pki/cms")
|
||||||
SIGNING_CERT = os.path.join(CERTDIR, 'signing_cert.pem')
|
SIGNING_CERT = os.path.join(CERTDIR, 'signing_cert.pem')
|
||||||
SIGNING_KEY = os.path.join(KEYDIR, 'signing_key.pem')
|
SIGNING_KEY = os.path.join(KEYDIR, 'signing_key.pem')
|
||||||
CA = os.path.join(CERTDIR, 'ca.pem')
|
CA = os.path.join(CERTDIR, 'ca.pem')
|
||||||
@@ -239,95 +241,96 @@ EXPECTED_V2_DEFAULT_ENV_RESPONSE = {
|
|||||||
FAKE_RESPONSE_STACK = []
|
FAKE_RESPONSE_STACK = []
|
||||||
|
|
||||||
|
|
||||||
|
# @TODO(mordred) This should become a testresources resource attached to the
|
||||||
|
# class
|
||||||
# The data for these tests are signed using openssl and are stored in files
|
# The data for these tests are signed using openssl and are stored in files
|
||||||
# in the signing subdirectory. In order to keep the values consistent between
|
# in the signing subdirectory. In order to keep the values consistent between
|
||||||
# the tests and the signed documents, we read them in for use in the tests.
|
# the tests and the signed documents, we read them in for use in the tests.
|
||||||
def setUpModule(self):
|
signing_path = CMSDIR
|
||||||
signing_path = CMSDIR
|
with open(os.path.join(signing_path, 'auth_token_scoped.pem')) as f:
|
||||||
with open(os.path.join(signing_path, 'auth_token_scoped.pem')) as f:
|
SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read())
|
||||||
self.SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read())
|
with open(os.path.join(signing_path, 'auth_token_unscoped.pem')) as f:
|
||||||
with open(os.path.join(signing_path, 'auth_token_unscoped.pem')) as f:
|
SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read())
|
||||||
self.SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read())
|
with open(os.path.join(signing_path, 'auth_v3_token_scoped.pem')) as f:
|
||||||
with open(os.path.join(signing_path, 'auth_v3_token_scoped.pem')) as f:
|
SIGNED_v3_TOKEN_SCOPED = cms.cms_to_token(f.read())
|
||||||
self.SIGNED_v3_TOKEN_SCOPED = cms.cms_to_token(f.read())
|
with open(os.path.join(signing_path, 'auth_token_revoked.pem')) as f:
|
||||||
with open(os.path.join(signing_path, 'auth_token_revoked.pem')) as f:
|
REVOKED_TOKEN = cms.cms_to_token(f.read())
|
||||||
self.REVOKED_TOKEN = cms.cms_to_token(f.read())
|
REVOKED_TOKEN_HASH = utils.hash_signed_token(REVOKED_TOKEN)
|
||||||
self.REVOKED_TOKEN_HASH = utils.hash_signed_token(self.REVOKED_TOKEN)
|
with open(os.path.join(signing_path, 'auth_v3_token_revoked.pem')) as f:
|
||||||
with open(os.path.join(signing_path, 'auth_v3_token_revoked.pem')) as f:
|
REVOKED_v3_TOKEN = cms.cms_to_token(f.read())
|
||||||
self.REVOKED_v3_TOKEN = cms.cms_to_token(f.read())
|
REVOKED_v3_TOKEN_HASH = utils.hash_signed_token(REVOKED_v3_TOKEN)
|
||||||
self.REVOKED_v3_TOKEN_HASH = utils.hash_signed_token(self.REVOKED_v3_TOKEN)
|
with open(os.path.join(signing_path, 'revocation_list.json')) as f:
|
||||||
with open(os.path.join(signing_path, 'revocation_list.json')) as f:
|
REVOCATION_LIST = jsonutils.loads(f.read())
|
||||||
self.REVOCATION_LIST = jsonutils.loads(f.read())
|
with open(os.path.join(signing_path, 'revocation_list.pem')) as f:
|
||||||
with open(os.path.join(signing_path, 'revocation_list.pem')) as f:
|
VALID_SIGNED_REVOCATION_LIST = jsonutils.dumps(
|
||||||
self.VALID_SIGNED_REVOCATION_LIST = jsonutils.dumps(
|
{'signed': f.read()})
|
||||||
{'signed': f.read()})
|
SIGNED_TOKEN_SCOPED_KEY =\
|
||||||
self.SIGNED_TOKEN_SCOPED_KEY = (
|
cms.cms_hash_token(SIGNED_TOKEN_SCOPED)
|
||||||
cms.cms_hash_token(self.SIGNED_TOKEN_SCOPED))
|
SIGNED_TOKEN_UNSCOPED_KEY =\
|
||||||
self.SIGNED_TOKEN_UNSCOPED_KEY = (
|
cms.cms_hash_token(SIGNED_TOKEN_UNSCOPED)
|
||||||
cms.cms_hash_token(self.SIGNED_TOKEN_UNSCOPED))
|
SIGNED_v3_TOKEN_SCOPED_KEY = (
|
||||||
self.SIGNED_v3_TOKEN_SCOPED_KEY = (
|
cms.cms_hash_token(SIGNED_v3_TOKEN_SCOPED))
|
||||||
cms.cms_hash_token(self.SIGNED_v3_TOKEN_SCOPED))
|
|
||||||
|
|
||||||
self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_KEY] = {
|
TOKEN_RESPONSES[SIGNED_TOKEN_SCOPED_KEY] = {
|
||||||
'access': {
|
'access': {
|
||||||
'token': {
|
'token': {
|
||||||
'id': self.SIGNED_TOKEN_SCOPED_KEY,
|
'id': SIGNED_TOKEN_SCOPED_KEY,
|
||||||
},
|
|
||||||
'user': {
|
|
||||||
'id': 'user_id1',
|
|
||||||
'name': 'user_name1',
|
|
||||||
'tenantId': 'tenant_id1',
|
|
||||||
'tenantName': 'tenant_name1',
|
|
||||||
'roles': [
|
|
||||||
{'name': 'role1'},
|
|
||||||
{'name': 'role2'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
'user': {
|
||||||
|
'id': 'user_id1',
|
||||||
self.TOKEN_RESPONSES[SIGNED_TOKEN_UNSCOPED_KEY] = {
|
'name': 'user_name1',
|
||||||
'access': {
|
'tenantId': 'tenant_id1',
|
||||||
'token': {
|
'tenantName': 'tenant_name1',
|
||||||
'id': SIGNED_TOKEN_UNSCOPED_KEY,
|
'roles': [
|
||||||
},
|
{'name': 'role1'},
|
||||||
'user': {
|
{'name': 'role2'},
|
||||||
'id': 'user_id1',
|
],
|
||||||
'name': 'user_name1',
|
|
||||||
'roles': [
|
|
||||||
{'name': 'role1'},
|
|
||||||
{'name': 'role2'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_KEY] = {
|
TOKEN_RESPONSES[SIGNED_TOKEN_UNSCOPED_KEY] = {
|
||||||
|
'access': {
|
||||||
'token': {
|
'token': {
|
||||||
'expires': '2020-01-01T00:00:10.000123Z',
|
'id': SIGNED_TOKEN_UNSCOPED_KEY,
|
||||||
'user': {
|
},
|
||||||
'id': 'user_id1',
|
'user': {
|
||||||
'name': 'user_name1',
|
'id': 'user_id1',
|
||||||
'domain': {
|
'name': 'user_name1',
|
||||||
'id': 'domain_id1',
|
|
||||||
'name': 'domain_name1'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'project': {
|
|
||||||
'id': 'tenant_id1',
|
|
||||||
'name': 'tenant_name1',
|
|
||||||
'domain': {
|
|
||||||
'id': 'domain_id1',
|
|
||||||
'name': 'domain_name1'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'roles': [
|
'roles': [
|
||||||
{'name': 'role1'},
|
{'name': 'role1'},
|
||||||
{'name': 'role2'}
|
{'name': 'role2'},
|
||||||
],
|
],
|
||||||
'catalog': {}
|
},
|
||||||
}
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
TOKEN_RESPONSES[SIGNED_v3_TOKEN_SCOPED_KEY] = {
|
||||||
|
'token': {
|
||||||
|
'expires': '2020-01-01T00:00:10.000123Z',
|
||||||
|
'user': {
|
||||||
|
'id': 'user_id1',
|
||||||
|
'name': 'user_name1',
|
||||||
|
'domain': {
|
||||||
|
'id': 'domain_id1',
|
||||||
|
'name': 'domain_name1'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'project': {
|
||||||
|
'id': 'tenant_id1',
|
||||||
|
'name': 'tenant_name1',
|
||||||
|
'domain': {
|
||||||
|
'id': 'domain_id1',
|
||||||
|
'name': 'domain_name1'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'roles': [
|
||||||
|
{'name': 'role1'},
|
||||||
|
{'name': 'role2'}
|
||||||
|
],
|
||||||
|
'catalog': {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VERSION_LIST_v3 = {
|
VERSION_LIST_v3 = {
|
||||||
"versions": {
|
"versions": {
|
||||||
@@ -362,6 +365,53 @@ VERSION_LIST_v2 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class NoModuleFinder(object):
|
||||||
|
""" Disallow further imports of 'module' """
|
||||||
|
|
||||||
|
def __init__(self, module):
|
||||||
|
self.module = module
|
||||||
|
|
||||||
|
def find_module(self, fullname, path):
|
||||||
|
if fullname == self.module or fullname.startswith(self.module + '.'):
|
||||||
|
raise ImportError
|
||||||
|
|
||||||
|
|
||||||
|
class DisableModuleFixture(fixtures.Fixture):
|
||||||
|
"""A fixture to provide support for unloading/disabling modules."""
|
||||||
|
|
||||||
|
def __init__(self, module, *args, **kw):
|
||||||
|
super(DisableModuleFixture, self).__init__(*args, **kw)
|
||||||
|
self.module = module
|
||||||
|
self._finders = []
|
||||||
|
self._cleared_modules = {}
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(DisableModuleFixture, self).tearDown()
|
||||||
|
for finder in self._finders:
|
||||||
|
sys.meta_path.remove(finder)
|
||||||
|
sys.modules.update(self._cleared_modules)
|
||||||
|
|
||||||
|
def clear_module(self):
|
||||||
|
cleared_modules = {}
|
||||||
|
for fullname in sys.modules.keys():
|
||||||
|
if (fullname == self.module or
|
||||||
|
fullname.startswith(self.module + '.')):
|
||||||
|
cleared_modules[fullname] = sys.modules.pop(fullname)
|
||||||
|
return cleared_modules
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Ensure ImportError for the specified module."""
|
||||||
|
|
||||||
|
super(DisableModuleFixture, self).setUp()
|
||||||
|
|
||||||
|
# Clear 'module' references in sys.modules
|
||||||
|
self._cleared_modules.update(self.clear_module())
|
||||||
|
|
||||||
|
finder = NoModuleFinder(self.module)
|
||||||
|
self._finders.append(finder)
|
||||||
|
sys.meta_path.insert(0, finder)
|
||||||
|
|
||||||
|
|
||||||
class FakeSwiftMemcacheRing(memorycache.Client):
|
class FakeSwiftMemcacheRing(memorycache.Client):
|
||||||
# NOTE(vish): swift memcache uses param timeout instead of time
|
# NOTE(vish): swift memcache uses param timeout instead of time
|
||||||
def set(self, key, value, timeout=0, min_compress_len=0):
|
def set(self, key, value, timeout=0, min_compress_len=0):
|
||||||
@@ -741,7 +791,36 @@ class DiabloAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
|
|||||||
self.assertTrue('keystone.token_info' in req.environ)
|
self.assertTrue('keystone.token_info' in req.environ)
|
||||||
|
|
||||||
|
|
||||||
class AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
|
class NoMemcacheAuthToken(BaseAuthTokenMiddlewareTest):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(NoMemcacheAuthToken, self).setUp()
|
||||||
|
self.useFixture(DisableModuleFixture('memcache'))
|
||||||
|
|
||||||
|
def test_nomemcache(self):
|
||||||
|
conf = {
|
||||||
|
'admin_token': 'admin_token1',
|
||||||
|
'auth_host': 'keystone.example.com',
|
||||||
|
'auth_port': 1234,
|
||||||
|
'memcache_servers': 'localhost:11211',
|
||||||
|
}
|
||||||
|
|
||||||
|
auth_token.AuthProtocol(FakeApp(), conf)
|
||||||
|
|
||||||
|
def test_not_use_cache_from_env(self):
|
||||||
|
env = {'swift.cache': 'CACHE_TEST'}
|
||||||
|
conf = {
|
||||||
|
'auth_host': 'keystone.example.com',
|
||||||
|
'auth_port': 1234,
|
||||||
|
'auth_admin_prefix': '/testadmin',
|
||||||
|
'memcache_servers': 'localhost:11211'
|
||||||
|
}
|
||||||
|
self.set_middleware(conf=conf)
|
||||||
|
self.middleware._init_cache(env)
|
||||||
|
self.assertNotEqual(self.middleware._cache, 'CACHE_TEST')
|
||||||
|
|
||||||
|
|
||||||
|
class AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
|
||||||
|
|
||||||
def test_init_does_not_call_http(self):
|
def test_init_does_not_call_http(self):
|
||||||
conf = {
|
conf = {
|
||||||
@@ -975,17 +1054,6 @@ class AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
|
|||||||
self.middleware._cache_initialized = True
|
self.middleware._cache_initialized = True
|
||||||
self.test_memcache_set_expired()
|
self.test_memcache_set_expired()
|
||||||
|
|
||||||
def test_nomemcache(self):
|
|
||||||
self.disable_module('memcache')
|
|
||||||
|
|
||||||
conf = {
|
|
||||||
'auth_host': 'keystone.example.com',
|
|
||||||
'auth_port': 1234,
|
|
||||||
'auth_admin_prefix': '/testadmin',
|
|
||||||
'memcache_servers': 'localhost:11211'
|
|
||||||
}
|
|
||||||
self.set_middleware(conf=conf)
|
|
||||||
|
|
||||||
def test_use_cache_from_env(self):
|
def test_use_cache_from_env(self):
|
||||||
env = {'swift.cache': 'CACHE_TEST'}
|
env = {'swift.cache': 'CACHE_TEST'}
|
||||||
conf = {
|
conf = {
|
||||||
@@ -999,18 +1067,6 @@ class AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
|
|||||||
self.middleware._init_cache(env)
|
self.middleware._init_cache(env)
|
||||||
self.assertEqual(self.middleware._cache, 'CACHE_TEST')
|
self.assertEqual(self.middleware._cache, 'CACHE_TEST')
|
||||||
|
|
||||||
def test_not_use_cache_from_env(self):
|
|
||||||
env = {'swift.cache': 'CACHE_TEST'}
|
|
||||||
conf = {
|
|
||||||
'auth_host': 'keystone.example.com',
|
|
||||||
'auth_port': 1234,
|
|
||||||
'auth_admin_prefix': '/testadmin',
|
|
||||||
'memcache_servers': 'localhost:11211'
|
|
||||||
}
|
|
||||||
self.set_middleware(conf=conf)
|
|
||||||
self.middleware._init_cache(env)
|
|
||||||
self.assertNotEqual(self.middleware._cache, 'CACHE_TEST')
|
|
||||||
|
|
||||||
def test_will_expire_soon(self):
|
def test_will_expire_soon(self):
|
||||||
tenseconds = datetime.datetime.utcnow() + datetime.timedelta(
|
tenseconds = datetime.datetime.utcnow() + datetime.timedelta(
|
||||||
seconds=10)
|
seconds=10)
|
||||||
@@ -1176,7 +1232,7 @@ class AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
|
|||||||
datetime.timedelta(seconds=24))
|
datetime.timedelta(seconds=24))
|
||||||
|
|
||||||
|
|
||||||
class v2AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
|
class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
|
||||||
""" v2 token specific tests.
|
""" v2 token specific tests.
|
||||||
|
|
||||||
There are some differences between how the auth-token middleware handles
|
There are some differences between how the auth-token middleware handles
|
||||||
|
@@ -5,13 +5,10 @@ fixtures
|
|||||||
keyring
|
keyring
|
||||||
mock
|
mock
|
||||||
mox
|
mox
|
||||||
nose
|
|
||||||
nose-exclude
|
|
||||||
openstack.nose_plugin
|
|
||||||
nosehtmloutput
|
|
||||||
pep8==1.3.3
|
pep8==1.3.3
|
||||||
pycrypto
|
pycrypto
|
||||||
sphinx>=1.1.2
|
sphinx>=1.1.2
|
||||||
|
testrepository>=0.0.13
|
||||||
testtools>=0.9.22
|
testtools>=0.9.22
|
||||||
WebOb>=1.0.8
|
WebOb>=1.0.8
|
||||||
|
|
||||||
|
26
tox.ini
26
tox.ini
@@ -3,24 +3,24 @@ envlist = py26,py27,pep8
|
|||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
setenv = VIRTUAL_ENV={envdir}
|
setenv = VIRTUAL_ENV={envdir}
|
||||||
NOSE_WITH_OPENSTACK=1
|
LANG=en_US.UTF-8
|
||||||
NOSE_OPENSTACK_COLOR=1
|
LANGUAGE=en_US:en
|
||||||
NOSE_OPENSTACK_RED=0.05
|
LC_ALL=C
|
||||||
NOSE_OPENSTACK_YELLOW=0.025
|
OS_STDOUT_NOCAPTURE=False
|
||||||
NOSE_OPENSTACK_SHOW_ELAPSED=1
|
OS_STDERR_NOCAPTURE=False
|
||||||
NOSE_OPENSTACK_STDOUT=1
|
|
||||||
deps = -r{toxinidir}/tools/pip-requires
|
deps = -r{toxinidir}/tools/pip-requires
|
||||||
-r{toxinidir}/tools/test-requires
|
-r{toxinidir}/tools/test-requires
|
||||||
commands = nosetests {posargs}
|
commands = python setup.py testr --testr-args='{posargs}'
|
||||||
|
|
||||||
[tox:jenkins]
|
|
||||||
downloadcache = ~/cache/pip
|
|
||||||
|
|
||||||
[testenv:pep8]
|
[testenv:pep8]
|
||||||
commands = pep8 --repeat --show-source --ignore=E711,E712,E125,E126 --exclude=.venv,.tox,dist,doc .
|
commands = pep8 --repeat --show-source --ignore=E711,E712,E125,E126 --exclude=.venv,.tox,dist,doc .
|
||||||
|
|
||||||
[testenv:cover]
|
|
||||||
setenv = NOSE_WITH_COVERAGE=1
|
|
||||||
|
|
||||||
[testenv:venv]
|
[testenv:venv]
|
||||||
commands = {posargs}
|
commands = {posargs}
|
||||||
|
|
||||||
|
[testenv:cover]
|
||||||
|
commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||||
|
|
||||||
|
[tox:jenkins]
|
||||||
|
downloadcache = ~/cache/pip
|
||||||
|
Reference in New Issue
Block a user