Modify functional tests to use ostestr/testr
Defcore uses Tempest, which uses Test Repository. This change makes it easier for Defcore to pull functional tests from Swift and run them. Additionally, using testr allows tests to be run in parallel. Concurrency set to 1 for now, >1 causes failures for reasons that are still TBD. With switch to ostestr all the server logs are being sent to stdout which makes it completely unreadable. Suppressing the logs by default now with a flag to enable it if desired. Co-Authored-By: John Dickinson <me@not.mn> Co-Authored-By: Robert Collins <rbtcollins@hpe.com> Co-Authored-By: Matthew Oliver <matt@oliver.net.au> Co-Authored-By: Ganesh Maharaj Mahalingam <ganesh.mahalingam@intel.com> Change-Id: I53ef4a116996a772cf1f3abc2eb0ad60047322d5 Related-Bug: 1177924
This commit is contained in:
parent
b3d6fa1319
commit
9d7f71d575
@ -1,9 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
SRC_DIR=$(python -c "import os; print os.path.dirname(os.path.realpath('$0'))")
|
||||
set -e
|
||||
|
||||
cd ${SRC_DIR}/test/functional
|
||||
nosetests --exe $@
|
||||
cd ${SRC_DIR}
|
||||
export TESTS_DIR=${SRC_DIR}/test/functional
|
||||
ostestr --serial --pretty $@
|
||||
rvalue=$?
|
||||
cd -
|
||||
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,4 +15,6 @@ pycscope.*
|
||||
.idea
|
||||
MANIFEST
|
||||
|
||||
.testrepository/*
|
||||
subunit.log
|
||||
test/probe/.noseids
|
||||
|
6
.testr.conf
Normal file
6
.testr.conf
Normal file
@ -0,0 +1,6 @@
|
||||
[DEFAULT]
|
||||
test_command=SWIFT_TEST_DEBUG_LOGS=${SWIFT_TEST_DEBUG_LOGS} \
|
||||
${PYTHON:-python} -m subunit.run \
|
||||
discover -t ./ ${TESTS_DIR:-./test/functional/} $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
@ -10,6 +10,7 @@ nosexcover
|
||||
nosehtmloutput
|
||||
oslosphinx
|
||||
sphinx>=1.1.2,<1.2
|
||||
os-testr>=0.4.1
|
||||
mock>=1.0
|
||||
python-swiftclient
|
||||
python-keystoneclient>=1.3.0
|
||||
|
@ -109,7 +109,7 @@ orig_hash_path_suff_pref = ('', '')
|
||||
orig_swift_conf_name = None
|
||||
|
||||
in_process = False
|
||||
_testdir = _test_servers = _test_coros = None
|
||||
_testdir = _test_servers = _test_coros = _test_socks = None
|
||||
policy_specified = None
|
||||
|
||||
|
||||
@ -290,6 +290,7 @@ def in_process_setup(the_object_server=object_server):
|
||||
_info('IN-PROCESS SERVERS IN USE FOR FUNCTIONAL TESTS')
|
||||
_info('Using object_server class: %s' % the_object_server.__name__)
|
||||
conf_src_dir = os.environ.get('SWIFT_TEST_IN_PROCESS_CONF_DIR')
|
||||
show_debug_logs = os.environ.get('SWIFT_TEST_DEBUG_LOGS')
|
||||
|
||||
if conf_src_dir is not None:
|
||||
if not os.path.isdir(conf_src_dir):
|
||||
@ -339,10 +340,13 @@ def in_process_setup(the_object_server=object_server):
|
||||
orig_hash_path_suff_pref = utils.HASH_PATH_PREFIX, utils.HASH_PATH_SUFFIX
|
||||
utils.validate_hash_conf()
|
||||
|
||||
global _test_socks
|
||||
_test_socks = []
|
||||
# We create the proxy server listening socket to get its port number so
|
||||
# that we can add it as the "auth_port" value for the functional test
|
||||
# clients.
|
||||
prolis = eventlet.listen(('localhost', 0))
|
||||
_test_socks.append(prolis)
|
||||
|
||||
# The following set of configuration values is used both for the
|
||||
# functional test frame work and for the various proxy, account, container
|
||||
@ -388,6 +392,7 @@ def in_process_setup(the_object_server=object_server):
|
||||
acc2lis = eventlet.listen(('localhost', 0))
|
||||
con1lis = eventlet.listen(('localhost', 0))
|
||||
con2lis = eventlet.listen(('localhost', 0))
|
||||
_test_socks += [acc1lis, acc2lis, con1lis, con2lis] + obj_sockets
|
||||
|
||||
account_ring_path = os.path.join(_testdir, 'account.ring.gz')
|
||||
with closing(GzipFile(account_ring_path, 'wb')) as f:
|
||||
@ -416,23 +421,30 @@ def in_process_setup(the_object_server=object_server):
|
||||
# Default to only 4 seconds for in-process functional test runs
|
||||
eventlet.wsgi.WRITE_TIMEOUT = 4
|
||||
|
||||
def get_logger_name(name):
|
||||
if show_debug_logs:
|
||||
return debug_logger(name)
|
||||
else:
|
||||
return None
|
||||
|
||||
acc1srv = account_server.AccountController(
|
||||
config, logger=debug_logger('acct1'))
|
||||
config, logger=get_logger_name('acct1'))
|
||||
acc2srv = account_server.AccountController(
|
||||
config, logger=debug_logger('acct2'))
|
||||
config, logger=get_logger_name('acct2'))
|
||||
con1srv = container_server.ContainerController(
|
||||
config, logger=debug_logger('cont1'))
|
||||
config, logger=get_logger_name('cont1'))
|
||||
con2srv = container_server.ContainerController(
|
||||
config, logger=debug_logger('cont2'))
|
||||
config, logger=get_logger_name('cont2'))
|
||||
|
||||
objsrvs = [
|
||||
(obj_sockets[index],
|
||||
the_object_server.ObjectController(
|
||||
config, logger=debug_logger('obj%d' % (index + 1))))
|
||||
config, logger=get_logger_name('obj%d' % (index + 1))))
|
||||
for index in range(len(obj_sockets))
|
||||
]
|
||||
|
||||
logger = debug_logger('proxy')
|
||||
if show_debug_logs:
|
||||
logger = debug_logger('proxy')
|
||||
|
||||
def get_logger(name, *args, **kwargs):
|
||||
return logger
|
||||
@ -446,6 +458,8 @@ def in_process_setup(the_object_server=object_server):
|
||||
raise InProcessException(e)
|
||||
|
||||
nl = utils.NullLogger()
|
||||
global proxy_srv
|
||||
proxy_srv = prolis
|
||||
prospa = eventlet.spawn(eventlet.wsgi.server, prolis, app, nl)
|
||||
acc1spa = eventlet.spawn(eventlet.wsgi.server, acc1lis, acc1srv, nl)
|
||||
acc2spa = eventlet.spawn(eventlet.wsgi.server, acc2lis, acc2srv, nl)
|
||||
@ -487,6 +501,7 @@ def get_cluster_info():
|
||||
# We'll update those constraints based on what the /info API provides, if
|
||||
# anything.
|
||||
global cluster_info
|
||||
global config
|
||||
try:
|
||||
conn = Connection(config)
|
||||
conn.authenticate()
|
||||
@ -536,6 +551,7 @@ def setup_package():
|
||||
|
||||
global in_process
|
||||
|
||||
global config
|
||||
if use_in_process:
|
||||
# Explicitly set to True, so barrel on ahead with in-process
|
||||
# functional test setup.
|
||||
@ -722,7 +738,6 @@ def setup_package():
|
||||
% policy_specified)
|
||||
raise Exception('Failed to find specified policy %s'
|
||||
% policy_specified)
|
||||
|
||||
get_cluster_info()
|
||||
|
||||
|
||||
@ -731,16 +746,21 @@ def teardown_package():
|
||||
locale.setlocale(locale.LC_COLLATE, orig_collate)
|
||||
|
||||
# clean up containers and objects left behind after running tests
|
||||
global config
|
||||
conn = Connection(config)
|
||||
conn.authenticate()
|
||||
account = Account(conn, config.get('account', config['username']))
|
||||
account.delete_containers()
|
||||
|
||||
global in_process
|
||||
global _test_socks
|
||||
if in_process:
|
||||
try:
|
||||
for server in _test_coros:
|
||||
for i, server in enumerate(_test_coros):
|
||||
server.kill()
|
||||
if not server.dead:
|
||||
# kill it from the socket level
|
||||
_test_socks[i].close()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
@ -751,6 +771,7 @@ def teardown_package():
|
||||
orig_hash_path_suff_pref
|
||||
utils.SWIFT_CONF_FILE = orig_swift_conf_name
|
||||
constraints.reload_constraints()
|
||||
reset_globals()
|
||||
|
||||
|
||||
class AuthError(Exception):
|
||||
@ -768,6 +789,17 @@ parsed = [None, None, None, None, None]
|
||||
conn = [None, None, None, None, None]
|
||||
|
||||
|
||||
def reset_globals():
|
||||
global url, token, service_token, parsed, conn, config
|
||||
url = [None, None, None, None, None]
|
||||
token = [None, None, None, None, None]
|
||||
service_token = [None, None, None, None, None]
|
||||
parsed = [None, None, None, None, None]
|
||||
conn = [None, None, None, None, None]
|
||||
if config:
|
||||
config = {}
|
||||
|
||||
|
||||
def connection(url):
|
||||
if has_insecure:
|
||||
parsed_url, http_conn = http_connection(url, insecure=insecure)
|
||||
|
@ -29,6 +29,14 @@ from test.functional import check_response, retry, requires_acls, \
|
||||
import test.functional as tf
|
||||
|
||||
|
||||
def setUpModule():
|
||||
tf.setup_package()
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
tf.teardown_package()
|
||||
|
||||
|
||||
class TestAccount(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -27,6 +27,14 @@ import test.functional as tf
|
||||
from six.moves import range
|
||||
|
||||
|
||||
def setUpModule():
|
||||
tf.setup_package()
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
tf.teardown_package()
|
||||
|
||||
|
||||
class TestContainer(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -27,6 +27,14 @@ from test.functional import check_response, retry, requires_acls, \
|
||||
import test.functional as tf
|
||||
|
||||
|
||||
def setUpModule():
|
||||
tf.setup_package()
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
tf.teardown_package()
|
||||
|
||||
|
||||
class TestObject(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -39,6 +39,14 @@ from test.functional.swift_test_client import Account, Connection, File, \
|
||||
ResponseError
|
||||
|
||||
|
||||
def setUpModule():
|
||||
tf.setup_package()
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
tf.teardown_package()
|
||||
|
||||
|
||||
class Utils(object):
|
||||
@classmethod
|
||||
def create_ascii_name(cls, length=None):
|
||||
|
@ -37,7 +37,7 @@ from test.unit import patch_policies, with_tempdir, make_timestamp_iter
|
||||
from swift.common.db import DatabaseConnectionError
|
||||
from swift.common.storage_policy import StoragePolicy, POLICIES
|
||||
|
||||
from test.unit.common.test_db import TestExampleBroker
|
||||
from test.unit.common import test_db
|
||||
|
||||
|
||||
@patch_policies
|
||||
@ -979,7 +979,7 @@ def premetadata_create_account_stat_table(self, conn, put_timestamp):
|
||||
put_timestamp))
|
||||
|
||||
|
||||
class TestCommonAccountBroker(TestExampleBroker):
|
||||
class TestCommonAccountBroker(test_db.TestExampleBroker):
|
||||
|
||||
broker_class = AccountBroker
|
||||
|
||||
|
@ -36,7 +36,7 @@ import mock
|
||||
|
||||
from test.unit import (patch_policies, with_tempdir, make_timestamp_iter,
|
||||
EMPTY_ETAG)
|
||||
from test.unit.common.test_db import TestExampleBroker
|
||||
from test.unit.common import test_db
|
||||
|
||||
|
||||
class TestContainerBroker(unittest.TestCase):
|
||||
@ -1680,7 +1680,7 @@ class TestContainerBroker(unittest.TestCase):
|
||||
self.assertEqual(broker.get_policy_stats(), expected)
|
||||
|
||||
|
||||
class TestCommonContainerBroker(TestExampleBroker):
|
||||
class TestCommonContainerBroker(test_db.TestExampleBroker):
|
||||
|
||||
broker_class = ContainerBroker
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user