aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test-runner
diff options
context:
space:
mode:
authorRyan Moeller <[email protected]>2019-10-09 13:39:26 -0400
committerBrian Behlendorf <[email protected]>2019-10-09 10:39:26 -0700
commit5e74ac51c70ee978e338e828f05377092d0637d4 (patch)
tree7182de383e8467e4a07481dbdc59cd0739cd4990 /tests/test-runner
parentca5777793ee10b9f7bb57aef00a6c8d57969625e (diff)
Move platform independent tests to a shared runfile
Tests that aren't limited to running on Linux can be moved to a common runfile to be shared with other platforms. The test runner and wrapper script are enhanced to allow specifying multiple runfiles as a comma-separated list. The default runfiles are now "common.run,PLATFORM.run" where PLATFORM is determined at run time. Sections in runfiles that share a path with another runfile can append a colon separator and an identifier to the path in the section name, ie `[tests/functional/atime:Linux]`, to avoid overriding the tests specified by other runfiles. Reviewed-by: Jorgen Lundman <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: John Kennedy <[email protected]> Signed-off-by: Ryan Moeller <[email protected]> Closes #9391
Diffstat (limited to 'tests/test-runner')
-rwxr-xr-xtests/test-runner/bin/test-runner.py111
1 files changed, 63 insertions, 48 deletions
diff --git a/tests/test-runner/bin/test-runner.py b/tests/test-runner/bin/test-runner.py
index ca08b3754..be05409f8 100755
--- a/tests/test-runner/bin/test-runner.py
+++ b/tests/test-runner/bin/test-runner.py
@@ -155,9 +155,10 @@ class Output(object):
class Cmd(object):
verified_users = []
- def __init__(self, pathname, outputdir=None, timeout=None, user=None,
- tags=None):
+ def __init__(self, pathname, identifier=None, outputdir=None,
+ timeout=None, user=None, tags=None):
self.pathname = pathname
+ self.identifier = identifier
self.outputdir = outputdir or 'BASEDIR'
"""
The timeout for tests is measured in wall-clock time
@@ -172,8 +173,10 @@ class Cmd(object):
self.timeout = 60
def __str__(self):
- return "Pathname: %s\nOutputdir: %s\nTimeout: %d\nUser: %s\n" % \
- (self.pathname, self.outputdir, self.timeout, self.user)
+ return "Pathname: %s\nIdentifier: %s\nOutputdir: %s\nTimeout: %d\n" \
+ "User: %s\n" % \
+ (self.pathname, self.identifier, self.outputdir, self.timeout,
+ self.user)
def kill_cmd(self, proc, keyboard_interrupt=False):
"""
@@ -315,7 +318,10 @@ class Cmd(object):
if self.reran is True:
rer = ' (RERAN)'
user = ' (run as %s)' % (self.user if len(self.user) else logname)
- msga = 'Test: %s%s ' % (self.pathname, user)
+ if self.identifier:
+ msga = 'Test (%s): %s%s ' % (self.identifier, self.pathname, user)
+ else:
+ msga = 'Test: %s%s ' % (self.pathname, user)
msgb = '[%s] [%s]%s\n' % (self.result.runtime, self.result.result, rer)
pad = ' ' * (80 - (len(msga) + len(msgb)))
result_line = msga + pad + msgb
@@ -357,10 +363,10 @@ class Test(Cmd):
props = ['outputdir', 'timeout', 'user', 'pre', 'pre_user', 'post',
'post_user', 'tags']
- def __init__(self, pathname, outputdir=None, timeout=None, user=None,
- pre=None, pre_user=None, post=None, post_user=None,
- tags=None):
- super(Test, self).__init__(pathname, outputdir, timeout, user)
+ def __init__(self, pathname,
+ pre=None, pre_user=None, post=None, post_user=None, tags=None,
+ **kwargs):
+ super(Test, self).__init__(pathname, **kwargs)
self.pre = pre or ''
self.pre_user = pre_user or ''
self.post = post or ''
@@ -373,10 +379,10 @@ class Test(Cmd):
pre_user = ' (as %s)' % (self.pre_user)
if len(self.post_user):
post_user = ' (as %s)' % (self.post_user)
- return "Pathname: %s\nOutputdir: %s\nTimeout: %d\nPre: %s%s\nPost: " \
- "%s%s\nUser: %s\nTags: %s\n" % \
- (self.pathname, self.outputdir, self.timeout, self.pre,
- pre_user, self.post, post_user, self.user, self.tags)
+ return "Pathname: %s\nIdentifier: %s\nOutputdir: %s\nTimeout: %d\n" \
+ "Pre: %s%s\nPost: %s%s\nUser: %s\nTags: %s\n" % \
+ (self.pathname, self.identifier, self.outputdir, self.timeout,
+ self.pre, pre_user, self.post, post_user, self.user, self.tags)
def verify(self):
"""
@@ -406,13 +412,14 @@ class Test(Cmd):
doesn't pass, skip this Test. Run the post script regardless.
"""
odir = os.path.join(self.outputdir, os.path.basename(self.pre))
- pretest = Cmd(self.pre, outputdir=odir, timeout=self.timeout,
- user=self.pre_user)
- test = Cmd(self.pathname, outputdir=self.outputdir,
- timeout=self.timeout, user=self.user)
+ pretest = Cmd(self.pre, identifier=self.identifier, outputdir=odir,
+ timeout=self.timeout, user=self.pre_user)
+ test = Cmd(self.pathname, identifier=self.identifier,
+ outputdir=self.outputdir, timeout=self.timeout,
+ user=self.user)
odir = os.path.join(self.outputdir, os.path.basename(self.post))
- posttest = Cmd(self.post, outputdir=odir, timeout=self.timeout,
- user=self.post_user)
+ posttest = Cmd(self.post, identifier=self.identifier, outputdir=odir,
+ timeout=self.timeout, user=self.post_user)
cont = True
if len(pretest.pathname):
@@ -435,11 +442,8 @@ class Test(Cmd):
class TestGroup(Test):
props = Test.props + ['tests']
- def __init__(self, pathname, outputdir=None, timeout=None, user=None,
- pre=None, pre_user=None, post=None, post_user=None,
- tests=None, tags=None):
- super(TestGroup, self).__init__(pathname, outputdir, timeout, user,
- pre, pre_user, post, post_user, tags)
+ def __init__(self, pathname, tests=None, **kwargs):
+ super(TestGroup, self).__init__(pathname, **kwargs)
self.tests = tests or []
def __str__(self):
@@ -448,10 +452,11 @@ class TestGroup(Test):
pre_user = ' (as %s)' % (self.pre_user)
if len(self.post_user):
post_user = ' (as %s)' % (self.post_user)
- return "Pathname: %s\nOutputdir: %s\nTests: %s\nTimeout: %s\n" \
- "Pre: %s%s\nPost: %s%s\nUser: %s\nTags: %s\n" % \
- (self.pathname, self.outputdir, self.tests, self.timeout,
- self.pre, pre_user, self.post, post_user, self.user, self.tags)
+ return "Pathname: %s\nIdentifier: %s\nOutputdir: %s\nTests: %s\n" \
+ "Timeout: %s\nPre: %s%s\nPost: %s%s\nUser: %s\nTags: %s\n" % \
+ (self.pathname, self.identifier, self.outputdir, self.tests,
+ self.timeout, self.pre, pre_user, self.post, post_user,
+ self.user, self.tags)
def verify(self):
"""
@@ -510,10 +515,10 @@ class TestGroup(Test):
odir = os.path.join(self.outputdir, os.path.basename(self.pre))
pretest = Cmd(self.pre, outputdir=odir, timeout=self.timeout,
- user=self.pre_user)
+ user=self.pre_user, identifier=self.identifier)
odir = os.path.join(self.outputdir, os.path.basename(self.post))
posttest = Cmd(self.post, outputdir=odir, timeout=self.timeout,
- user=self.post_user)
+ user=self.post_user, identifier=self.identifier)
cont = True
if len(pretest.pathname):
@@ -524,7 +529,8 @@ class TestGroup(Test):
for fname in self.tests:
test = Cmd(os.path.join(self.pathname, fname),
outputdir=os.path.join(self.outputdir, fname),
- timeout=self.timeout, user=self.user)
+ timeout=self.timeout, user=self.user,
+ identifier=self.identifier)
if cont:
test.run(options.dryrun)
else:
@@ -605,7 +611,7 @@ class TestRun(object):
def read(self, options):
"""
- Read in the specified runfile, and apply the TestRun properties
+ Read in the specified runfiles, and apply the TestRun properties
listed in the 'DEFAULT' section to our TestRun. Then read each
section, and apply the appropriate properties to the Test or
TestGroup. Properties from individual sections override those set
@@ -613,8 +619,11 @@ class TestRun(object):
verification, add it to the TestRun.
"""
config = configparser.RawConfigParser()
- if not len(config.read(options.runfile)):
- fail("Coulnd't read config file %s" % options.runfile)
+ parsed = config.read(options.runfiles)
+ failed = options.runfiles - set(parsed)
+ if len(failed):
+ files = ' '.join(sorted(failed))
+ fail("Couldn't read config files: %s" % files)
for opt in TestRun.props:
if config.has_option('DEFAULT', opt):
@@ -623,14 +632,18 @@ class TestRun(object):
for section in config.sections():
if 'tests' in config.options(section):
- if os.path.isdir(section):
- pathname = section
- elif os.path.isdir(os.path.join(options.testdir, section)):
- pathname = os.path.join(options.testdir, section)
+ parts = section.split(':', 1)
+ sectiondir = parts[0]
+ identifier = parts[1] if len(parts) == 2 else None
+ if os.path.isdir(sectiondir):
+ pathname = sectiondir
+ elif os.path.isdir(os.path.join(options.testdir, sectiondir)):
+ pathname = os.path.join(options.testdir, sectiondir)
else:
- pathname = section
+ pathname = sectiondir
- testgroup = TestGroup(os.path.abspath(pathname))
+ testgroup = TestGroup(os.path.abspath(pathname),
+ identifier=identifier)
for prop in TestGroup.props:
for sect in ['DEFAULT', section]:
if config.has_option(sect, prop):
@@ -873,32 +886,34 @@ def fail(retstr, ret=1):
def options_cb(option, opt_str, value, parser):
- path_options = ['runfile', 'outputdir', 'template', 'testdir']
+ path_options = ['outputdir', 'template', 'testdir']
- if option.dest == 'runfile' and '-w' in parser.rargs or \
+ if option.dest == 'runfiles' and '-w' in parser.rargs or \
option.dest == 'template' and '-c' in parser.rargs:
fail('-c and -w are mutually exclusive.')
if opt_str in parser.rargs:
fail('%s may only be specified once.' % opt_str)
- if option.dest == 'runfile':
+ if option.dest == 'runfiles':
parser.values.cmd = 'rdconfig'
+ value = set(os.path.abspath(p) for p in value.split(','))
if option.dest == 'template':
parser.values.cmd = 'wrconfig'
if option.dest == 'tags':
value = [x.strip() for x in value.split(',')]
- setattr(parser.values, option.dest, value)
if option.dest in path_options:
setattr(parser.values, option.dest, os.path.abspath(value))
+ else:
+ setattr(parser.values, option.dest, value)
def parse_args():
parser = OptionParser()
parser.add_option('-c', action='callback', callback=options_cb,
- type='string', dest='runfile', metavar='runfile',
- help='Specify tests to run via config file.')
+ type='string', dest='runfiles', metavar='runfiles',
+ help='Specify tests to run via config files.')
parser.add_option('-d', action='store_true', default=False, dest='dryrun',
help='Dry run. Print tests, but take no other action.')
parser.add_option('-g', action='store_true', default=False,
@@ -940,10 +955,10 @@ def parse_args():
help='Number of times to run the test run.')
(options, pathnames) = parser.parse_args()
- if not options.runfile and not options.template:
+ if not options.runfiles and not options.template:
options.cmd = 'runtests'
- if options.runfile and len(pathnames):
+ if options.runfiles and len(pathnames):
fail('Extraneous arguments.')
options.pathnames = [os.path.abspath(path) for path in pathnames]