Use testr instead of nose.
Part of blueprint grizzly-testtools Change-Id: I76dee19781eaac21901b5c0258e83a42180c1702
This commit is contained in:
		
				
					committed by
					
						
						Clark Boylan
					
				
			
			
				
	
			
			
			
						parent
						
							548b52336f
						
					
				
				
					commit
					11263ac318
				
			
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,6 @@
 | 
			
		||||
.coverage
 | 
			
		||||
.testrepository
 | 
			
		||||
subunit.log
 | 
			
		||||
.venv
 | 
			
		||||
*,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
 | 
			
		||||
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, --no-pep8            Don't run pep8"
 | 
			
		||||
  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 "  --hide-elapsed           Don't print the elapsed time for each test along with slow test list"
 | 
			
		||||
  echo ""
 | 
			
		||||
@@ -33,8 +34,9 @@ function process_option {
 | 
			
		||||
    -p|--pep8) just_pep8=1;;
 | 
			
		||||
    -P|--no-pep8) no_pep8=1;;
 | 
			
		||||
    -c|--coverage) coverage=1;;
 | 
			
		||||
    -*) noseopts="$noseopts $1";;
 | 
			
		||||
    *) noseargs="$noseargs $1"
 | 
			
		||||
    -d|--debug) debug=1;;
 | 
			
		||||
    -*) testropts="$testropts $1";;
 | 
			
		||||
    *) testrargs="$testrargs $1"
 | 
			
		||||
  esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -45,34 +47,86 @@ never_venv=0
 | 
			
		||||
force=0
 | 
			
		||||
no_site_packages=0
 | 
			
		||||
installvenvopts=
 | 
			
		||||
noseargs=
 | 
			
		||||
noseopts=
 | 
			
		||||
testrargs=
 | 
			
		||||
testropts=
 | 
			
		||||
wrapper=""
 | 
			
		||||
just_pep8=0
 | 
			
		||||
no_pep8=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
 | 
			
		||||
  process_option $arg
 | 
			
		||||
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
 | 
			
		||||
  installvenvopts="--no-site-packages"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
function init_testr {
 | 
			
		||||
  if [ ! -d .testrepository ]; then
 | 
			
		||||
    ${wrapper} testr init
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
  ${wrapper} $NOSETESTS
 | 
			
		||||
  # If we get some short import error right away, print the error log directly
 | 
			
		||||
  set +e
 | 
			
		||||
  testrargs=`echo "$testrargs" | sed -e's/^\s*\(.*\)\s*$/\1/'`
 | 
			
		||||
  TESTRTESTS="$TESTRTESTS --testr-args='$testropts $testrargs'"
 | 
			
		||||
  echo "Running \`${wrapper} $TESTRTESTS\`"
 | 
			
		||||
  bash -c "${wrapper} $TESTRTESTS"
 | 
			
		||||
  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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function copy_subunit_log {
 | 
			
		||||
  LOGNAME=`cat .testrepository/next-stream`
 | 
			
		||||
  LOGNAME=$(($LOGNAME - 1))
 | 
			
		||||
  LOGNAME=".testrepository/${LOGNAME}"
 | 
			
		||||
  cp $LOGNAME subunit.log
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function run_pep8 {
 | 
			
		||||
  echo "Running pep8 ..."
 | 
			
		||||
  srcfiles="keystoneclient tests"
 | 
			
		||||
@@ -85,7 +139,7 @@ function run_pep8 {
 | 
			
		||||
    ${srcfiles}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NOSETESTS="nosetests $noseopts $noseargs"
 | 
			
		||||
TESTRTESTS="python setup.py testr"
 | 
			
		||||
 | 
			
		||||
if [ $never_venv -eq 0 ]
 | 
			
		||||
then
 | 
			
		||||
@@ -123,19 +177,15 @@ if [ $just_pep8 -eq 1 ]; then
 | 
			
		||||
    exit
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
init_testr
 | 
			
		||||
run_tests
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
# distinguish between options (noseopts), which begin with a '-', and
 | 
			
		||||
# arguments (noseargs).
 | 
			
		||||
if [ -z "$noseargs" ]; then
 | 
			
		||||
# distinguish between options (testropts), which begin with a '-', and
 | 
			
		||||
# arguments (testrargs).
 | 
			
		||||
if [ -z "$testrargs" ]; then
 | 
			
		||||
  if [ $no_pep8 -eq 0 ]; then
 | 
			
		||||
    run_pep8
 | 
			
		||||
  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]
 | 
			
		||||
source-dir = doc/source
 | 
			
		||||
build-dir = doc/build
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								setup.py
									
									
									
									
									
								
							@@ -37,7 +37,6 @@ setuptools.setup(
 | 
			
		||||
    cmdclass=setup.get_cmdclass(),
 | 
			
		||||
 | 
			
		||||
    tests_require=tests_require,
 | 
			
		||||
    test_suite="nose.collector",
 | 
			
		||||
 | 
			
		||||
    entry_points={
 | 
			
		||||
        'console_scripts': ['keystone = keystoneclient.shell:main']
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ import sys
 | 
			
		||||
import tempfile
 | 
			
		||||
import testtools
 | 
			
		||||
 | 
			
		||||
import fixtures
 | 
			
		||||
import webob
 | 
			
		||||
 | 
			
		||||
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 jsonutils
 | 
			
		||||
from keystoneclient.openstack.common import timeutils
 | 
			
		||||
from keystoneclient.middleware import test
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CERTDIR = test.rootdir('examples', 'pki', 'certs')
 | 
			
		||||
KEYDIR = test.rootdir('examples', 'pki', 'private')
 | 
			
		||||
CMSDIR = test.rootdir('examples', 'pki', 'cms')
 | 
			
		||||
ROOTDIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
 | 
			
		||||
 | 
			
		||||
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_KEY = os.path.join(KEYDIR, 'signing_key.pem')
 | 
			
		||||
CA = os.path.join(CERTDIR, 'ca.pem')
 | 
			
		||||
@@ -239,95 +241,96 @@ EXPECTED_V2_DEFAULT_ENV_RESPONSE = {
 | 
			
		||||
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
 | 
			
		||||
# 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.
 | 
			
		||||
def setUpModule(self):
 | 
			
		||||
    signing_path = CMSDIR
 | 
			
		||||
    with open(os.path.join(signing_path, 'auth_token_scoped.pem')) as f:
 | 
			
		||||
        self.SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read())
 | 
			
		||||
    with open(os.path.join(signing_path, 'auth_token_unscoped.pem')) as f:
 | 
			
		||||
        self.SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read())
 | 
			
		||||
    with open(os.path.join(signing_path, 'auth_v3_token_scoped.pem')) as f:
 | 
			
		||||
        self.SIGNED_v3_TOKEN_SCOPED = cms.cms_to_token(f.read())
 | 
			
		||||
    with open(os.path.join(signing_path, 'auth_token_revoked.pem')) as f:
 | 
			
		||||
        self.REVOKED_TOKEN = cms.cms_to_token(f.read())
 | 
			
		||||
    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:
 | 
			
		||||
        self.REVOKED_v3_TOKEN = cms.cms_to_token(f.read())
 | 
			
		||||
    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:
 | 
			
		||||
        self.REVOCATION_LIST = jsonutils.loads(f.read())
 | 
			
		||||
    with open(os.path.join(signing_path, 'revocation_list.pem')) as f:
 | 
			
		||||
        self.VALID_SIGNED_REVOCATION_LIST = jsonutils.dumps(
 | 
			
		||||
            {'signed': f.read()})
 | 
			
		||||
    self.SIGNED_TOKEN_SCOPED_KEY = (
 | 
			
		||||
        cms.cms_hash_token(self.SIGNED_TOKEN_SCOPED))
 | 
			
		||||
    self.SIGNED_TOKEN_UNSCOPED_KEY = (
 | 
			
		||||
        cms.cms_hash_token(self.SIGNED_TOKEN_UNSCOPED))
 | 
			
		||||
    self.SIGNED_v3_TOKEN_SCOPED_KEY = (
 | 
			
		||||
        cms.cms_hash_token(self.SIGNED_v3_TOKEN_SCOPED))
 | 
			
		||||
signing_path = CMSDIR
 | 
			
		||||
with open(os.path.join(signing_path, 'auth_token_scoped.pem')) as f:
 | 
			
		||||
    SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read())
 | 
			
		||||
with open(os.path.join(signing_path, 'auth_token_unscoped.pem')) as f:
 | 
			
		||||
    SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read())
 | 
			
		||||
with open(os.path.join(signing_path, 'auth_v3_token_scoped.pem')) as f:
 | 
			
		||||
    SIGNED_v3_TOKEN_SCOPED = cms.cms_to_token(f.read())
 | 
			
		||||
with open(os.path.join(signing_path, 'auth_token_revoked.pem')) as f:
 | 
			
		||||
    REVOKED_TOKEN = cms.cms_to_token(f.read())
 | 
			
		||||
REVOKED_TOKEN_HASH = utils.hash_signed_token(REVOKED_TOKEN)
 | 
			
		||||
with open(os.path.join(signing_path, 'auth_v3_token_revoked.pem')) as f:
 | 
			
		||||
    REVOKED_v3_TOKEN = cms.cms_to_token(f.read())
 | 
			
		||||
REVOKED_v3_TOKEN_HASH = utils.hash_signed_token(REVOKED_v3_TOKEN)
 | 
			
		||||
with open(os.path.join(signing_path, 'revocation_list.json')) as f:
 | 
			
		||||
    REVOCATION_LIST = jsonutils.loads(f.read())
 | 
			
		||||
with open(os.path.join(signing_path, 'revocation_list.pem')) as f:
 | 
			
		||||
    VALID_SIGNED_REVOCATION_LIST = jsonutils.dumps(
 | 
			
		||||
        {'signed': f.read()})
 | 
			
		||||
SIGNED_TOKEN_SCOPED_KEY =\
 | 
			
		||||
    cms.cms_hash_token(SIGNED_TOKEN_SCOPED)
 | 
			
		||||
SIGNED_TOKEN_UNSCOPED_KEY =\
 | 
			
		||||
    cms.cms_hash_token(SIGNED_TOKEN_UNSCOPED)
 | 
			
		||||
SIGNED_v3_TOKEN_SCOPED_KEY = (
 | 
			
		||||
    cms.cms_hash_token(SIGNED_v3_TOKEN_SCOPED))
 | 
			
		||||
 | 
			
		||||
    self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_KEY] = {
 | 
			
		||||
        'access': {
 | 
			
		||||
            'token': {
 | 
			
		||||
                'id': self.SIGNED_TOKEN_SCOPED_KEY,
 | 
			
		||||
            },
 | 
			
		||||
            'user': {
 | 
			
		||||
                'id': 'user_id1',
 | 
			
		||||
                'name': 'user_name1',
 | 
			
		||||
                'tenantId': 'tenant_id1',
 | 
			
		||||
                'tenantName': 'tenant_name1',
 | 
			
		||||
                'roles': [
 | 
			
		||||
                    {'name': 'role1'},
 | 
			
		||||
                    {'name': 'role2'},
 | 
			
		||||
                ],
 | 
			
		||||
            },
 | 
			
		||||
TOKEN_RESPONSES[SIGNED_TOKEN_SCOPED_KEY] = {
 | 
			
		||||
    'access': {
 | 
			
		||||
        'token': {
 | 
			
		||||
            'id': SIGNED_TOKEN_SCOPED_KEY,
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    self.TOKEN_RESPONSES[SIGNED_TOKEN_UNSCOPED_KEY] = {
 | 
			
		||||
        'access': {
 | 
			
		||||
            'token': {
 | 
			
		||||
                'id': SIGNED_TOKEN_UNSCOPED_KEY,
 | 
			
		||||
            },
 | 
			
		||||
            'user': {
 | 
			
		||||
                'id': 'user_id1',
 | 
			
		||||
                'name': 'user_name1',
 | 
			
		||||
                'roles': [
 | 
			
		||||
                    {'name': 'role1'},
 | 
			
		||||
                    {'name': 'role2'},
 | 
			
		||||
                ],
 | 
			
		||||
            },
 | 
			
		||||
        'user': {
 | 
			
		||||
            'id': 'user_id1',
 | 
			
		||||
            'name': 'user_name1',
 | 
			
		||||
            'tenantId': 'tenant_id1',
 | 
			
		||||
            'tenantName': 'tenant_name1',
 | 
			
		||||
            'roles': [
 | 
			
		||||
                {'name': 'role1'},
 | 
			
		||||
                {'name': 'role2'},
 | 
			
		||||
            ],
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_KEY] = {
 | 
			
		||||
TOKEN_RESPONSES[SIGNED_TOKEN_UNSCOPED_KEY] = {
 | 
			
		||||
    'access': {
 | 
			
		||||
        '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'
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            'id': SIGNED_TOKEN_UNSCOPED_KEY,
 | 
			
		||||
        },
 | 
			
		||||
        'user': {
 | 
			
		||||
            'id': 'user_id1',
 | 
			
		||||
            'name': 'user_name1',
 | 
			
		||||
            'roles': [
 | 
			
		||||
                    {'name': 'role1'},
 | 
			
		||||
                    {'name': 'role2'}
 | 
			
		||||
                {'name': 'role1'},
 | 
			
		||||
                {'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 = {
 | 
			
		||||
    "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):
 | 
			
		||||
    # NOTE(vish): swift memcache uses param timeout instead of time
 | 
			
		||||
    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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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):
 | 
			
		||||
        conf = {
 | 
			
		||||
@@ -975,17 +1054,6 @@ class AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
 | 
			
		||||
        self.middleware._cache_initialized = True
 | 
			
		||||
        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):
 | 
			
		||||
        env = {'swift.cache': 'CACHE_TEST'}
 | 
			
		||||
        conf = {
 | 
			
		||||
@@ -999,18 +1067,6 @@ class AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
 | 
			
		||||
        self.middleware._init_cache(env)
 | 
			
		||||
        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):
 | 
			
		||||
        tenseconds = datetime.datetime.utcnow() + datetime.timedelta(
 | 
			
		||||
            seconds=10)
 | 
			
		||||
@@ -1176,7 +1232,7 @@ class AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
 | 
			
		||||
                          datetime.timedelta(seconds=24))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class v2AuthTokenMiddlewareTest(test.NoModule, BaseAuthTokenMiddlewareTest):
 | 
			
		||||
class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
 | 
			
		||||
    """ v2 token specific tests.
 | 
			
		||||
 | 
			
		||||
    There are some differences between how the auth-token middleware handles
 | 
			
		||||
 
 | 
			
		||||
@@ -5,13 +5,10 @@ fixtures
 | 
			
		||||
keyring
 | 
			
		||||
mock
 | 
			
		||||
mox
 | 
			
		||||
nose
 | 
			
		||||
nose-exclude
 | 
			
		||||
openstack.nose_plugin
 | 
			
		||||
nosehtmloutput
 | 
			
		||||
pep8==1.3.3
 | 
			
		||||
pycrypto
 | 
			
		||||
sphinx>=1.1.2
 | 
			
		||||
testrepository>=0.0.13
 | 
			
		||||
testtools>=0.9.22
 | 
			
		||||
WebOb>=1.0.8
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								tox.ini
									
									
									
									
									
								
							@@ -3,24 +3,24 @@ envlist = py26,py27,pep8
 | 
			
		||||
 | 
			
		||||
[testenv]
 | 
			
		||||
setenv = VIRTUAL_ENV={envdir}
 | 
			
		||||
         NOSE_WITH_OPENSTACK=1
 | 
			
		||||
         NOSE_OPENSTACK_COLOR=1
 | 
			
		||||
         NOSE_OPENSTACK_RED=0.05
 | 
			
		||||
         NOSE_OPENSTACK_YELLOW=0.025
 | 
			
		||||
         NOSE_OPENSTACK_SHOW_ELAPSED=1
 | 
			
		||||
         NOSE_OPENSTACK_STDOUT=1
 | 
			
		||||
         LANG=en_US.UTF-8
 | 
			
		||||
         LANGUAGE=en_US:en
 | 
			
		||||
         LC_ALL=C
 | 
			
		||||
         OS_STDOUT_NOCAPTURE=False
 | 
			
		||||
         OS_STDERR_NOCAPTURE=False
 | 
			
		||||
 | 
			
		||||
deps = -r{toxinidir}/tools/pip-requires
 | 
			
		||||
       -r{toxinidir}/tools/test-requires
 | 
			
		||||
commands = nosetests {posargs}
 | 
			
		||||
 | 
			
		||||
[tox:jenkins]
 | 
			
		||||
downloadcache = ~/cache/pip
 | 
			
		||||
commands = python setup.py testr --testr-args='{posargs}'
 | 
			
		||||
 | 
			
		||||
[testenv:pep8]
 | 
			
		||||
commands = pep8 --repeat --show-source --ignore=E711,E712,E125,E126 --exclude=.venv,.tox,dist,doc .
 | 
			
		||||
 | 
			
		||||
[testenv:cover]
 | 
			
		||||
setenv = NOSE_WITH_COVERAGE=1
 | 
			
		||||
 | 
			
		||||
[testenv:venv]
 | 
			
		||||
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