From c3ae6559cd36a4cb4b5e7b34b46076a45cf715d1 Mon Sep 17 00:00:00 2001 From: Cleber Rosa Date: Wed, 19 Oct 2016 14:28:14 -0300 Subject: [PATCH] Result: make sure every job has a result directory This change makes the initialization of the job results happen a lot earlier than usual, at job instantiation time. It matches the use cases of the "Job API", that is, when users want to manipulate job instances. With this, change it's possible to execute snippets of code such as: >>> from avocado.core.job import Job >>> job = avocado.core.Job() >>> job.log.info("Checking if system is ready") And have that persisted at `job.logdir`, with the "Checking if system is ready" message logged at `job.logfile`. This also addresses the issue that, once a job is created, its result dir is never removed, even if it's empty. The Avocado test runner still behaves mostly the same, that is, if the existing job has no tests (such as when none of the test names given were resolved), it will proceed to the job execution. I'd argue that, since it's not possible (or I'd say desirable) that test resolution happens outside the context of a job, this is the logical way to go. This reinforces the change that a job without a test suite is still a valid job. That's is the reason for the removal of the test that checked if job results directory were removed if Avocado was executed without test names as parameters. Reference: https://trello.com/c/hu4vxQOL Signed-off-by: Cleber Rosa --- avocado/core/job.py | 22 +++++++++---------- selftests/functional/test_argument_parsing.py | 4 ---- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/avocado/core/job.py b/avocado/core/job.py index b1a83d98..9eb407f2 100644 --- a/avocado/core/job.py +++ b/avocado/core/job.py @@ -89,7 +89,11 @@ class Job(object): if unique_id is None: unique_id = job_id.create_unique_job_id() self.unique_id = unique_id + #: The log directory for this job, also known as the job results + #: directory. If it's set to None, it means that the job results + #: directory has not yet been created. self.logdir = None + self._setup_job_results() raw_log_level = settings.get_value('job.output', 'loglevel', default='debug') mapping = {'info': logging.INFO, @@ -109,6 +113,7 @@ class Job(object): self.sysinfo = None self.timeout = getattr(self.args, 'job_timeout', 0) self.__logging_handlers = {} + self.__start_job_logging() self.funcatexit = data_structures.CallbackRegister("JobExit %s" % self.unique_id, _TEST_LOGGER) @@ -125,6 +130,9 @@ class Job(object): self._job_pre_post_dispatcher = None def _setup_job_results(self): + """ + Prepares a job result directory, also known as logdir, for this job + """ logdir = getattr(self.args, 'logdir', None) if self.standalone: if logdir is not None: @@ -140,6 +148,8 @@ class Job(object): logdir = os.path.abspath(logdir) self.logdir = data_dir.create_job_logs_dir(logdir=logdir, unique_id=self.unique_id) + if not (self.standalone or getattr(self.args, "dry_run", False)): + self._update_latest_link() self.logfile = os.path.join(self.logdir, "job.log") self.idfile = os.path.join(self.logdir, "id") with open(self.idfile, 'w') as id_file_obj: @@ -240,9 +250,6 @@ class Job(object): sysinfo_dir = path.init_dir(self.logdir, 'sysinfo') self.sysinfo = sysinfo.SysInfo(basedir=sysinfo_dir) - def _remove_job_results(self): - shutil.rmtree(self.logdir, ignore_errors=True) - def _make_test_runner(self): if hasattr(self.args, 'test_runner'): test_runner_class = self.args.test_runner @@ -291,10 +298,8 @@ class Job(object): try: suite = loader.loader.discover(urls) except loader.LoaderUnhandledUrlError as details: - self._remove_job_results() raise exceptions.OptionValidationError(details) except KeyboardInterrupt: - self._remove_job_results() raise exceptions.JobError('Command interrupted by user...') if not getattr(self.args, "dry_run", False): @@ -421,14 +426,10 @@ class Job(object): :class:`avocado.core.exceptions.JobBaseException` errors, that configure a job failure. """ - self._setup_job_results() - self.__start_job_logging() - self.create_test_suite() self.pre_tests() if not self.test_suite: - self._remove_job_results() if self.urls: e_msg = ("No tests found for given urls, try 'avocado list -V " "%s' for details" % " ".join(self.urls)) @@ -450,8 +451,6 @@ class Job(object): self.args.test_result_total = mux.get_number_of_tests(self.test_suite) self._make_old_style_test_result() - if not (self.standalone or getattr(self.args, "dry_run", False)): - self._update_latest_link() self._make_test_runner() self._start_sysinfo() @@ -495,7 +494,6 @@ class Job(object): self.test_suite = self._make_test_suite(self.urls) except loader.LoaderError as details: stacktrace.log_exc_info(sys.exc_info(), 'avocado.app.debug') - self._remove_job_results() raise exceptions.OptionValidationError(details) def pre_tests(self): diff --git a/selftests/functional/test_argument_parsing.py b/selftests/functional/test_argument_parsing.py index 4c855401..0def9970 100644 --- a/selftests/functional/test_argument_parsing.py +++ b/selftests/functional/test_argument_parsing.py @@ -72,9 +72,5 @@ class ArgumentParsingErrorEarlyTest(unittest.TestCase): self.run_but_fail_before_create_job_dir('--whacky-option passtest', exit_codes.AVOCADO_FAIL) - def test_empty_option(self): - self.run_but_fail_before_create_job_dir('', - exit_codes.AVOCADO_JOB_FAIL) - if __name__ == '__main__': unittest.main() -- GitLab