提交 6b506e6c 编写于 作者: L Lucas Meneghel Rodrigues 提交者: Lucas Meneghel Rodrigues

Merge pull request #120 from lmr/flat-tests-2

Flat tests
...@@ -36,6 +36,14 @@ class JobError(Exception): ...@@ -36,6 +36,14 @@ class JobError(Exception):
status = "ERROR" status = "ERROR"
class OptionValidationError(Exception):
"""
An invalid option was passed to the test runner
"""
status = "ERROR"
class TestBaseException(Exception): class TestBaseException(Exception):
""" """
......
...@@ -69,28 +69,44 @@ class TestRunner(object): ...@@ -69,28 +69,44 @@ class TestRunner(object):
:type params: dict :type params: dict
:return: an instance of :class:`avocado.test.Test`. :return: an instance of :class:`avocado.test.Test`.
""" """
shortname = params.get('shortname') t_id = params.get('id')
url = shortname.split('.')[0] test_path = os.path.abspath(t_id)
path_attempt = os.path.abspath(shortname) path_analyzer = path.PathInspector(test_path)
if os.path.exists(path_attempt): module_name = os.path.basename(test_path).split('.')[0]
test_class = test.DropinTest if not os.path.exists(test_path):
test_instance = test_class(path=path_attempt, # Try to resolve test ID (keep compatibility)
base_logdir=self.job.logdir, test_path = os.path.join(data_dir.get_test_dir(), '%s.py' % t_id)
job=self.job) if os.path.exists(test_path):
else: path_analyzer = path.PathInspector(test_path)
else:
test_class = test.MissingTest
test_instance = test_class(name=t_id,
base_logdir=self.job.logdir,
params=params,
job=self.job)
return test_instance
if path_analyzer.is_python():
try: try:
test_module_dir = os.path.join(self.job.test_dir, url) test_module_dir = os.path.dirname(test_path)
f, p, d = imp.find_module(url, [test_module_dir]) f, p, d = imp.find_module(module_name, [test_module_dir])
test_module = imp.load_module(url, f, p, d) test_module = imp.load_module(module_name, f, p, d)
f.close() f.close()
test_class = getattr(test_module, url) test_class = getattr(test_module, module_name)
except ImportError: except ImportError:
test_class = test.MissingTest test_class = test.MissingTest
finally: finally:
test_instance = test_class(name=url, test_instance = test_class(name=t_id,
base_logdir=self.job.logdir, base_logdir=self.job.logdir,
params=params, params=params,
job=self.job) job=self.job)
else:
test_class = test.DropinTest
test_instance = test_class(path=test_path,
base_logdir=self.job.logdir,
job=self.job)
return test_instance return test_instance
def run_test(self, instance, queue): def run_test(self, instance, queue):
...@@ -287,7 +303,7 @@ class Job(object): ...@@ -287,7 +303,7 @@ class Job(object):
if urls is not None: if urls is not None:
for url in urls: for url in urls:
params_list.append({'shortname': url}) params_list.append({'id': url})
if multiplex_file is None: if multiplex_file is None:
if self.args and self.args.multiplex_file is not None: if self.args and self.args.multiplex_file is not None:
...@@ -299,18 +315,19 @@ class Job(object): ...@@ -299,18 +315,19 @@ class Job(object):
params_list = [] params_list = []
if urls is not None: if urls is not None:
for url in urls: for url in urls:
test_module = os.path.basename(url).split('.')[0]
parser = multiplex_config.Parser(multiplex_file) parser = multiplex_config.Parser(multiplex_file)
parser.only_filter(url) parser.only_filter(test_module)
dcts = [d for d in parser.get_dicts()] dcts = [d for d in parser.get_dicts()]
if dcts: if dcts:
for dct in dcts: for dct in dcts:
dct['id'] = url
params_list.append(dct) params_list.append(dct)
else: else:
params_list.append({'shortname': url}) params_list.append({'id': url})
else: else:
parser = multiplex_config.Parser(multiplex_file) e_msg = "Empty test ID. A test path or alias must be provided"
for dct in parser.get_dicts(): raise exceptions.OptionValidationError(e_msg)
params_list.append(dct)
if self.args is not None: if self.args is not None:
self.args.test_result_total = len(params_list) self.args.test_result_total = len(params_list)
...@@ -371,6 +388,10 @@ class Job(object): ...@@ -371,6 +388,10 @@ class Job(object):
self.output_manager.log_fail_header('Avocado job failed: %s: %s' % self.output_manager.log_fail_header('Avocado job failed: %s: %s' %
(fail_class, details)) (fail_class, details))
return error_codes.numeric_status['AVOCADO_JOB_FAIL'] return error_codes.numeric_status['AVOCADO_JOB_FAIL']
except exceptions.OptionValidationError, details:
self.output_manager.log_fail_header(str(details))
return error_codes.numeric_status['AVOCADO_JOB_FAIL']
except Exception, details: except Exception, details:
self.status = "ERROR" self.status = "ERROR"
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
......
...@@ -21,6 +21,7 @@ import os ...@@ -21,6 +21,7 @@ import os
from avocado.plugins import plugin from avocado.plugins import plugin
from avocado.core import data_dir from avocado.core import data_dir
from avocado.core import output from avocado.core import output
from avocado.utils import path
from avocado import sysinfo from avocado import sysinfo
from avocado import job from avocado import job
...@@ -53,7 +54,12 @@ class TestLister(plugin.Plugin): ...@@ -53,7 +54,12 @@ class TestLister(plugin.Plugin):
""" """
bcolors = output.colors bcolors = output.colors
pipe = output.get_paginator() pipe = output.get_paginator()
test_dirs = os.listdir(data_dir.get_test_dir()) test_files = os.listdir(data_dir.get_test_dir())
test_dirs = []
for t in test_files:
inspector = path.PathInspector(path=t)
if inspector.is_python():
test_dirs.append(t.split('.')[0])
pipe.write(bcolors.header_str('Tests available:')) pipe.write(bcolors.header_str('Tests available:'))
pipe.write("\n") pipe.write("\n")
for test_dir in test_dirs: for test_dir in test_dirs:
......
...@@ -17,6 +17,7 @@ Contains the base test implementation, used as a base for the actual ...@@ -17,6 +17,7 @@ Contains the base test implementation, used as a base for the actual
framework tests. framework tests.
""" """
import inspect
import logging import logging
import os import os
import sys import sys
...@@ -115,14 +116,22 @@ class Test(unittest.TestCase): ...@@ -115,14 +116,22 @@ class Test(unittest.TestCase):
s_tag = ".".join(split_shortname[1:]) s_tag = ".".join(split_shortname[1:])
self.tag = tag or s_tag self.tag = tag or s_tag
self.job = job self.job = job
self.basedir = os.path.join(data_dir.get_test_dir(), self.name)
self.datadir = os.path.join(self.basedir, 'data') basename = os.path.basename(self.name)
self.workdir = path.init_dir(data_dir.get_tmp_dir(), self.name)
self.basedir = os.path.dirname(inspect.getfile(self.__class__))
self.datadir = os.path.join(self.basedir, '%s.data' % basename)
self.workdir = path.init_dir(data_dir.get_tmp_dir(), basename)
self.srcdir = path.init_dir(self.workdir, 'src') self.srcdir = path.init_dir(self.workdir, 'src')
if base_logdir is None: if base_logdir is None:
base_logdir = data_dir.get_job_logs_dir() base_logdir = data_dir.get_job_logs_dir()
self.tagged_name = self.get_tagged_name(base_logdir) self.tagged_name = self.get_tagged_name(base_logdir)
self.logdir = path.init_dir(base_logdir, self.tagged_name) # We need log directory names to be unique
tagged_name = self.tagged_name.replace('/', '.')
if tagged_name.startswith('.'):
tagged_name = tagged_name[1:]
self.logdir = path.init_dir(base_logdir, tagged_name)
self.logfile = os.path.join(self.logdir, 'debug.log') self.logfile = os.path.join(self.logdir, 'debug.log')
self.outputdir = path.init_dir(self.logdir, 'data') self.outputdir = path.init_dir(self.logdir, 'data')
self.sysinfodir = path.init_dir(self.logdir, 'sysinfo') self.sysinfodir = path.init_dir(self.logdir, 'sysinfo')
...@@ -386,10 +395,8 @@ class DropinTest(Test): ...@@ -386,10 +395,8 @@ class DropinTest(Test):
""" """
def __init__(self, path, params=None, base_logdir=None, tag=None, job=None): def __init__(self, path, params=None, base_logdir=None, tag=None, job=None):
basename = os.path.basename(path)
name = basename.split(".")[0]
self.path = os.path.abspath(path) self.path = os.path.abspath(path)
super(DropinTest, self).__init__(name=name, base_logdir=base_logdir, super(DropinTest, self).__init__(name=path, base_logdir=base_logdir,
params=params, tag=tag, job=job) params=params, tag=tag, job=job)
def _log_detailed_cmd_info(self, result): def _log_detailed_cmd_info(self, result):
......
...@@ -17,6 +17,10 @@ Avocado path related functions. ...@@ -17,6 +17,10 @@ Avocado path related functions.
""" """
import os import os
import stat
PY_EXTENSIONS = ['.py']
SHEBANG = '#!'
def init_dir(*args): def init_dir(*args):
...@@ -32,3 +36,42 @@ def init_dir(*args): ...@@ -32,3 +36,42 @@ def init_dir(*args):
if not os.path.isdir(directory): if not os.path.isdir(directory):
os.makedirs(directory) os.makedirs(directory)
return directory return directory
class PathInspector(object):
def __init__(self, path):
self.path = path
def get_first_line(self):
first_line = ""
if os.path.isfile(self.path):
checked_file = open(self.path, "r")
first_line = checked_file.readline()
checked_file.close()
return first_line
def has_exec_permission(self):
mode = os.stat(self.path)[stat.ST_MODE]
return mode & stat.S_IXUSR
def is_empty(self):
size = os.stat(self.path)[stat.ST_SIZE]
return size == 0
def is_script(self, language=None):
first_line = self.get_first_line()
if first_line:
if first_line.startswith(SHEBANG):
if language is None:
return True
elif language in first_line:
return True
return False
def is_python(self):
for extension in PY_EXTENSIONS:
if self.path.endswith(extension):
return True
return self.is_script(language='python')
...@@ -46,6 +46,11 @@ class RunnerOperationTest(unittest.TestCase): ...@@ -46,6 +46,11 @@ class RunnerOperationTest(unittest.TestCase):
cmd_line = './scripts/avocado run "sleeptest sleeptest"' cmd_line = './scripts/avocado run "sleeptest sleeptest"'
process.run(cmd_line) process.run(cmd_line)
def test_runner_noalias(self):
os.chdir(basedir)
cmd_line = "./scripts/avocado run 'tests/sleeptest.py tests/sleeptest.py'"
process.run(cmd_line)
def test_runner_tests_fail(self): def test_runner_tests_fail(self):
os.chdir(basedir) os.chdir(basedir)
cmd_line = './scripts/avocado run "sleeptest failtest sleeptest"' cmd_line = './scripts/avocado run "sleeptest failtest sleeptest"'
......
...@@ -60,7 +60,7 @@ class MultiplexTests(unittest.TestCase): ...@@ -60,7 +60,7 @@ class MultiplexTests(unittest.TestCase):
"%d:\n%s" % (cmd_line, expected_rc, result)) "%d:\n%s" % (cmd_line, expected_rc, result))
def test_mplex_plugin(self): def test_mplex_plugin(self):
cmd_line = './scripts/avocado multiplex tests/sleeptest/sleeptest.mplx' cmd_line = './scripts/avocado multiplex tests/sleeptest.py.data/sleeptest.mplx'
expected_rc = 0 expected_rc = 0
self.run_and_check(cmd_line, expected_rc) self.run_and_check(cmd_line, expected_rc)
...@@ -69,8 +69,22 @@ class MultiplexTests(unittest.TestCase): ...@@ -69,8 +69,22 @@ class MultiplexTests(unittest.TestCase):
expected_rc = 2 expected_rc = 2
self.run_and_check(cmd_line, expected_rc) self.run_and_check(cmd_line, expected_rc)
def test_run_mplex_noid(self):
cmd_line = './scripts/avocado run --multiplex tests/sleeptest.py.data/sleeptest.mplx'
expected_rc = 0
self.run_and_check(cmd_line, 2)
def test_run_mplex_sleeptest(self): def test_run_mplex_sleeptest(self):
cmd_line = './scripts/avocado run sleeptest --multiplex tests/sleeptest/sleeptest.mplx' cmd_line = './scripts/avocado run sleeptest --multiplex tests/sleeptest.py.data/sleeptest.mplx'
expected_rc = 0
# A typical sleeptest has about 14 lines of output,
# so we expect the full job log has at least 3 times
# this value. If that is not the case, something is wrong with
# the output.
self.run_and_check(cmd_line, expected_rc, 14*3)
def test_run_mplex_noalias_sleeptest(self):
cmd_line = './scripts/avocado run tests/sleeptest.py --multiplex tests/sleeptest.py.data/sleeptest.mplx'
expected_rc = 0 expected_rc = 0
# A typical sleeptest has about 14 lines of output, # A typical sleeptest has about 14 lines of output,
# so we expect the full job log has at least 3 times # so we expect the full job log has at least 3 times
...@@ -79,12 +93,12 @@ class MultiplexTests(unittest.TestCase): ...@@ -79,12 +93,12 @@ class MultiplexTests(unittest.TestCase):
self.run_and_check(cmd_line, expected_rc, 14*3) self.run_and_check(cmd_line, expected_rc, 14*3)
def test_run_mplex_doublesleep(self): def test_run_mplex_doublesleep(self):
cmd_line = './scripts/avocado run "sleeptest sleeptest" --multiplex tests/sleeptest/sleeptest.mplx' cmd_line = './scripts/avocado run "sleeptest sleeptest" --multiplex tests/sleeptest.py.data/sleeptest.mplx'
expected_rc = 0 expected_rc = 0
self.run_and_check(cmd_line, expected_rc) self.run_and_check(cmd_line, expected_rc)
def test_run_mplex_failtest(self): def test_run_mplex_failtest(self):
cmd_line = './scripts/avocado run "sleeptest failtest" --multiplex tests/sleeptest/sleeptest.mplx' cmd_line = './scripts/avocado run "sleeptest failtest" --multiplex tests/sleeptest.py.data/sleeptest.mplx'
expected_rc = 1 expected_rc = 1
self.run_and_check(cmd_line, expected_rc) self.run_and_check(cmd_line, expected_rc)
......
...@@ -44,27 +44,27 @@ class StandaloneTests(unittest.TestCase): ...@@ -44,27 +44,27 @@ class StandaloneTests(unittest.TestCase):
"%d:\n%s" % (tstname, expected_rc, result)) "%d:\n%s" % (tstname, expected_rc, result))
def test_sleeptest(self): def test_sleeptest(self):
cmd_line = './tests/sleeptest/sleeptest.py' cmd_line = './tests/sleeptest.py'
expected_rc = 0 expected_rc = 0
self.run_and_check(cmd_line, expected_rc, 'sleeptest') self.run_and_check(cmd_line, expected_rc, 'sleeptest')
def test_skiptest(self): def test_skiptest(self):
cmd_line = './tests/skiptest/skiptest.py' cmd_line = './tests/skiptest.py'
expected_rc = 0 expected_rc = 0
self.run_and_check(cmd_line, expected_rc, 'skiptest') self.run_and_check(cmd_line, expected_rc, 'skiptest')
def test_failtest(self): def test_failtest(self):
cmd_line = './tests/failtest/failtest.py' cmd_line = './tests/failtest.py'
expected_rc = 1 expected_rc = 1
self.run_and_check(cmd_line, expected_rc, 'failtest') self.run_and_check(cmd_line, expected_rc, 'failtest')
def test_errortest(self): def test_errortest(self):
cmd_line = './tests/errortest/errortest.py' cmd_line = './tests/errortest.py'
expected_rc = 1 expected_rc = 1
self.run_and_check(cmd_line, expected_rc, 'errortest') self.run_and_check(cmd_line, expected_rc, 'errortest')
def test_warntest(self): def test_warntest(self):
cmd_line = './tests/warntest/warntest.py' cmd_line = './tests/warntest.py'
expected_rc = 1 expected_rc = 1
self.run_and_check(cmd_line, expected_rc, 'warntest') self.run_and_check(cmd_line, expected_rc, 'warntest')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册