From e29359029c98842bec3b41be17b148cf57d07970 Mon Sep 17 00:00:00 2001 From: Jan Richter Date: Tue, 2 Mar 2021 17:04:09 +0100 Subject: [PATCH] Test independent on Job class This commit removes the Job instance from the Test class. This is preparation for legacy runner removal. For the nrunner doesn't make sense to have Test dependent on Job instance, because Test is run inside runner separated from Job. Reference: #4425 Signed-off-by: Jan Richter --- avocado/core/nrunner_avocado_instrumented.py | 4 +- avocado/core/test.py | 146 +++++++++---------- avocado/plugins/runner.py | 6 +- selftests/unit/test_jsonresult.py | 2 +- selftests/unit/test_xunit.py | 2 +- 5 files changed, 81 insertions(+), 79 deletions(-) diff --git a/avocado/core/nrunner_avocado_instrumented.py b/avocado/core/nrunner_avocado_instrumented.py index d9c2f0e3e2..2f02f04883 100644 --- a/avocado/core/nrunner_avocado_instrumented.py +++ b/avocado/core/nrunner_avocado_instrumented.py @@ -2,7 +2,7 @@ import tempfile import time -from . import job, loader, nrunner, teststatus +from . import loader, nrunner, teststatus from .test import TestID from .tree import TreeNode @@ -38,7 +38,7 @@ def _run_avocado(runnable, queue): test_factory = [klass, {'name': TestID(1, klass_method), 'methodName': method, - 'job': job.Job(), + 'config': runnable.config, 'modulePath': module_path, 'params': (TreeNode(), []), 'tags': runnable.tags, diff --git a/avocado/core/test.py b/avocado/core/test.py index 806bebeaf3..7047934db6 100644 --- a/avocado/core/test.py +++ b/avocado/core/test.py @@ -228,7 +228,7 @@ class Test(unittest.TestCase, TestData): timeout = None def __init__(self, methodName='test', name=None, params=None, - base_logdir=None, job=None, runner_queue=None, tags=None): + base_logdir=None, config=None, runner_queue=None, tags=None): """ Initializes the test. @@ -242,7 +242,9 @@ def __init__(self, methodName='test', name=None, params=None, :type name: :class:`avocado.core.test.TestID` :param base_logdir: Directory where test logs should go. If None provided a temporary directory will be created. - :param job: The job that this test is part of. + :param config: the job configuration, usually set by command + line options and argument parsing + :type config: dict """ self.__phase = 'INIT' @@ -257,9 +259,10 @@ def record_and_warn(*args, **kwargs): else: self.__name = TestID(0, self.__class__.__name__) - self.__job = job self.__tags = tags + self.__config = config or settings.as_dict() + self.__base_logdir_tmp = None if base_logdir is None: prefix = 'avocado_test_' @@ -282,10 +285,10 @@ def record_and_warn(*args, **kwargs): self.__outputdir = utils_path.init_dir(self.logdir, 'data') - # For some reason, sometimes, job.config if None here. + # For some reason, sometimes, config if None here. # This is the only place that we create a "default" in code. try: - self.__sysinfo_enabled = job.config.get('sysinfo.collect.per_test') + self.__sysinfo_enabled = config.get('sysinfo.collect.per_test') except AttributeError: self.__sysinfo_enabled = False @@ -325,11 +328,9 @@ def record_and_warn(*args, **kwargs): self.__runner_queue = runner_queue - base_tmpdir = getattr(job, "tmpdir", None) - # When tmpdir not specified by job, use logdir to preserve all data - if base_tmpdir is None: - base_tmpdir = tempfile.mkdtemp(prefix="tmp_dir", dir=self.logdir) - self.__workdir = os.path.join(base_tmpdir, + self.__base_tmpdir = tempfile.mkdtemp(prefix="tmp_dir", + dir=base_logdir) + self.__workdir = os.path.join(self.__base_tmpdir, self.name.str_filesystem) utils_path.init_dir(self.__workdir) @@ -356,13 +357,6 @@ def name(self): """ return self.__name - @property - def job(self): - """ - The job this test is associated with - """ - return self.__job - @property def tags(self): """ @@ -560,8 +554,6 @@ def get_state(self): self._update_time_elapsed() state = {key: getattr(self, key, None) for (key) in TEST_STATE_ATTRIBUTES} state['class_name'] = self.__class__.__name__ - state['job_logdir'] = self.job.logdir - state['job_unique_id'] = self.job.unique_id state['params'] = [(path, key, value) for path, key, value in self.__params.iteritems()] # pylint: disable=W1620 @@ -798,59 +790,58 @@ def _run_avocado(self): whiteboard_file = os.path.join(self.logdir, 'whiteboard') genio.write_file(whiteboard_file, self.whiteboard) - if self.job is not None: - output_check_record = self.job.config.get('run.output_check_record') - output_check = self.job.config.get('run.output_check') + output_check_record = self.__config.get('run.output_check_record') + output_check = self.__config.get('run.output_check') - # record the output if the modes are valid - if output_check_record == 'combined': - self._record_reference(self._output_file, - "output.expected") - else: - if output_check_record in ['all', 'both', 'stdout']: - self._record_reference(self._stdout_file, - "stdout.expected") - if output_check_record in ['all', 'both', 'stderr']: - self._record_reference(self._stderr_file, - "stderr.expected") - - # check the output and produce test failures - if output_check_record != 'none' and output_check: - output_checked = False + # record the output if the modes are valid + if output_check_record == 'combined': + self._record_reference(self._output_file, + "output.expected") + else: + if output_check_record in ['all', 'both', 'stdout']: + self._record_reference(self._stdout_file, + "stdout.expected") + if output_check_record in ['all', 'both', 'stderr']: + self._record_reference(self._stderr_file, + "stderr.expected") + + # check the output and produce test failures + if output_check_record != 'none' and output_check: + output_checked = False + try: + output_checked = self._check_reference( + self._output_file, + 'output.expected', + 'output.diff', + 'output_diff', + 'Output') + except exceptions.TestFail as details: + stacktrace.log_exc_info(sys.exc_info(), + logger=LOG_JOB) + output_check_exception = details + if not output_checked: + try: + self._check_reference(self._stdout_file, + 'stdout.expected', + 'stdout.diff', + 'stdout_diff', + 'Stdout') + except exceptions.TestFail as details: + # output check was performed (and failed) + output_checked = True + stacktrace.log_exc_info(sys.exc_info(), + logger=LOG_JOB) + stdout_check_exception = details try: - output_checked = self._check_reference( - self._output_file, - 'output.expected', - 'output.diff', - 'output_diff', - 'Output') + self._check_reference(self._stderr_file, + 'stderr.expected', + 'stderr.diff', + 'stderr_diff', + 'Stderr') except exceptions.TestFail as details: stacktrace.log_exc_info(sys.exc_info(), logger=LOG_JOB) - output_check_exception = details - if not output_checked: - try: - self._check_reference(self._stdout_file, - 'stdout.expected', - 'stdout.diff', - 'stdout_diff', - 'Stdout') - except exceptions.TestFail as details: - # output check was performed (and failed) - output_checked = True - stacktrace.log_exc_info(sys.exc_info(), - logger=LOG_JOB) - stdout_check_exception = details - try: - self._check_reference(self._stderr_file, - 'stderr.expected', - 'stderr.diff', - 'stderr_diff', - 'Stderr') - except exceptions.TestFail as details: - stacktrace.log_exc_info(sys.exc_info(), - logger=LOG_JOB) - stderr_check_exception = details + stderr_check_exception = details # pylint: disable=E0702 if test_exception is not None: @@ -1051,11 +1042,17 @@ def tearDown(self): if self.__base_logdir_tmp is not None: self.__base_logdir_tmp.cleanup() self.__base_logdir_tmp = None + if not self.__config.get('run.keep_tmp') and os.path.exists( + self.__base_tmpdir): + shutil.rmtree(self.__base_tmpdir) def __del__(self): if self.__base_logdir_tmp is not None: self.__base_logdir_tmp.cleanup() self.__base_logdir_tmp = None + if not self.__config.get('run.keep_tmp') and os.path.exists( + self.__base_tmpdir): + shutil.rmtree(self.__base_tmpdir) class SimpleTest(Test): @@ -1066,13 +1063,14 @@ class SimpleTest(Test): DATA_SOURCES = ["variant", "file"] - def __init__(self, name, params=None, base_logdir=None, job=None, + def __init__(self, name, params=None, base_logdir=None, config=None, executable=None): if executable is None: executable = name.name self._filename = executable super(SimpleTest, self).__init__(name=name, params=params, - base_logdir=base_logdir, job=job) + base_logdir=base_logdir, + config=config) # Maximal allowed file name length is 255 file_datadir = None if (self.filename is not None and @@ -1180,7 +1178,7 @@ def __init__(self, runner, chdir=None, test_dir=None): class ExternalRunnerTest(SimpleTest): - def __init__(self, name, params=None, base_logdir=None, job=None, + def __init__(self, name, params=None, base_logdir=None, config=None, external_runner=None, external_runner_argument=None): if external_runner_argument is None: external_runner_argument = name.name @@ -1189,7 +1187,7 @@ def __init__(self, name, params=None, base_logdir=None, job=None, "external_runner parameter, got None instead.") self.external_runner = external_runner super(ExternalRunnerTest, self).__init__(name, params, base_logdir, - job) + config) self._command = "%s %s" % (external_runner.runner, external_runner_argument) @@ -1229,12 +1227,12 @@ class PythonUnittest(ExternalRunnerTest): Python unittest test """ - def __init__(self, name, params=None, base_logdir=None, job=None, + def __init__(self, name, params=None, base_logdir=None, config=None, test_dir=None, python_unittest_module=None, tags=None): # pylint: disable=W0613 runner = "%s -m unittest -q -c" % sys.executable external_runner = ExternalRunnerSpec(runner, "test", test_dir) - super(PythonUnittest, self).__init__(name, params, base_logdir, job, + super(PythonUnittest, self).__init__(name, params, base_logdir, config, external_runner=external_runner, external_runner_argument=python_unittest_module) @@ -1338,7 +1336,7 @@ def __init__(self, *args, **kwargs): """ super_kwargs = dict() args = list(reversed(args)) - for arg in ["methodName", "name", "params", "base_logdir", "job", + for arg in ["methodName", "name", "params", "base_logdir", "config", "runner_queue"]: if arg in kwargs: super_kwargs[arg] = kwargs[arg] diff --git a/avocado/plugins/runner.py b/avocado/plugins/runner.py index f4f84036e8..c87d52c441 100644 --- a/avocado/plugins/runner.py +++ b/avocado/plugins/runner.py @@ -92,6 +92,8 @@ def sigterm_handler(signum, frame): # pylint: disable=W0613 instance.set_runner_queue(queue) early_state = instance.get_state() early_state['early_status'] = True + early_state['job_logdir'] = job.logdir + early_state['job_unique_id'] = job.unique_id try: queue.put(early_state) except queueFullException: @@ -118,6 +120,8 @@ def sigterm_handler(signum, frame): # pylint: disable=W0613 finally: try: state = instance.get_state() + state['job_logdir'] = job.logdir + state['job_unique_id'] = job.unique_id queue.put(state) except queueFullException: instance.error(stacktrace.str_unpickable_object(state)) @@ -359,7 +363,7 @@ def run_suite(self, job, test_suite): try: for test_factory in test_suite.tests: test_factory[1]["base_logdir"] = job.logdir - test_factory[1]["job"] = job + test_factory[1]["config"] = job.config for test_factory, variant in self._iter_suite(test_suite, execution_order): test_parameters = test_factory[1] diff --git a/selftests/unit/test_jsonresult.py b/selftests/unit/test_jsonresult.py index 37bf682b63..5bc1fe63c1 100644 --- a/selftests/unit/test_jsonresult.py +++ b/selftests/unit/test_jsonresult.py @@ -35,7 +35,7 @@ def test(self): self.test_result = Result(UNIQUE_ID, LOGFILE) self.test_result.filename = json_output_path self.test_result.tests_total = 1 - self.test1 = SimpleTest(job=self.job, base_logdir=self.tmpdir.name) + self.test1 = SimpleTest(config=self.job.config, base_logdir=self.tmpdir.name) self.test1._Test__status = 'PASS' self.test1.time_elapsed = 1.23 diff --git a/selftests/unit/test_xunit.py b/selftests/unit/test_xunit.py index 887135a625..d4e9584d9c 100644 --- a/selftests/unit/test_xunit.py +++ b/selftests/unit/test_xunit.py @@ -49,7 +49,7 @@ def test(self): self.test_result.tests_total = 1 self.test_result.logfile = ("/.../avocado/job-results/" "job-2018-11-28T16.27-8fef221/job.log") - self.test1 = SimpleTest(job=self.job, base_logdir=self.tmpdir.name) + self.test1 = SimpleTest(config=self.job.config, base_logdir=self.tmpdir.name) self.test1._Test__status = 'PASS' self.test1._Test__logfile = '' self.test1.time_elapsed = 678.23689