From c6aa6ca89f66204eea682995a2c05a57e13d406a Mon Sep 17 00:00:00 2001 From: bignamic Date: Tue, 27 Aug 2019 18:06:40 +0200 Subject: [PATCH 01/16] WIP Dependency unit testing development --- reframe/frontend/executors/__init__.py | 28 ++++++++++-- reframe/frontend/executors/policies.py | 15 +++++-- unittests/resources/checks/frontend_checks.py | 45 +++++++++++++++++++ unittests/test_cli.py | 9 ++++ 4 files changed, 90 insertions(+), 7 deletions(-) diff --git a/reframe/frontend/executors/__init__.py b/reframe/frontend/executors/__init__.py index 0a1f31d551..20ac3d15e7 100644 --- a/reframe/frontend/executors/__init__.py +++ b/reframe/frontend/executors/__init__.py @@ -9,6 +9,7 @@ from reframe.core.environments import EnvironmentSnapshot from reframe.core.exceptions import (AbortTaskError, JobNotStartedError, ReframeFatalError, TaskExit) +import reframe.frontend.dependency as dependency from reframe.frontend.printer import PrettyPrinter from reframe.frontend.statistics import TestStats @@ -261,7 +262,25 @@ def runall(self, testcases): self._printer.timestamp('Started on', 'short double line') self._printer.info('') try: - self._runall(testcases) + # TODO: dependenct-specific exception handling needed here + dependency_graph = dependency.build_deps(testcases) + dependency.validate_deps(dependency_graph) + dependency.print_deps(dependency_graph) + ordered_tests = dependency.toposort(dependency_graph) + keep_stage_flag = [] + for t in ordered_tests: + is_dependency = False + for c, deps in dependency_graph.items(): + if is_dependency is True: + break + if t in deps: + is_dependency = True + break + keep_stage_flag.append(is_dependency) + + print(keep_stage_flag) + print('CHRI') + self._runall(ordered_tests, keep_stage_flag) if self._max_retries: self._retry_failed(testcases) @@ -291,7 +310,7 @@ def _retry_failed(self, cases): self._runall(t.testcase.clone() for t in failures) failures = self._stats.failures() - def _runall(self, testcases): + def _runall(self, testcases, keep_stage_flag): def print_separator(check, prefix): self._printer.separator( 'short single line', @@ -300,7 +319,8 @@ def print_separator(check, prefix): self._policy.enter() last_check = None - for t in testcases: +# for t in testcases: + for index, t in enumerate(testcases): if last_check is None or last_check.name != t.check.name: if last_check is not None: print_separator(last_check, 'finished processing') @@ -310,7 +330,7 @@ def print_separator(check, prefix): last_check = t.check self._environ_snapshot.load() - self._policy.runcase(t) + self._policy.runcase(t, keep_stage_flag[index]) # Close the last visual box if last_check is not None: diff --git a/reframe/frontend/executors/policies.py b/reframe/frontend/executors/policies.py index 40b2dd5965..bb57ef0ca5 100644 --- a/reframe/frontend/executors/policies.py +++ b/reframe/frontend/executors/policies.py @@ -14,7 +14,7 @@ def __init__(self): super().__init__() self._tasks = [] - def runcase(self, case): + def runcase(self, case, keep_stage): super().runcase(case) check, partition, environ = case @@ -22,6 +22,10 @@ def runcase(self, case): 'RUN', '%s on %s using %s' % (check.name, partition.fullname, environ.name) ) + + print('Keep stage?') + print(keep_stage) + task = RegressionTask(case) self._tasks.append(task) self.stats.add_task(task) @@ -45,7 +49,12 @@ def runcase(self, case): if not self.skip_performance_check: task.performance() - task.cleanup(not self.keep_stage_files, False) + print('In policy') + print(case) + print(keep_stage) + +# if not keep_stage: +# task.cleanup(not self.keep_stage_files, False) except TaskExit: return @@ -144,7 +153,7 @@ def on_task_exit(self, task): self._remove_from_running(task) self._retired_tasks.append(task) - def runcase(self, case): + def runcase(self, case, keep_stage): super().runcase(case) check, partition, environ = case diff --git a/unittests/resources/checks/frontend_checks.py b/unittests/resources/checks/frontend_checks.py index b144f97668..c98382632c 100644 --- a/unittests/resources/checks/frontend_checks.py +++ b/unittests/resources/checks/frontend_checks.py @@ -180,3 +180,48 @@ def __init__(self, run_to_pass, filename): self.post_run = ['((current_run++))', 'echo $current_run > %s' % filename] self.sanity_patterns = sn.assert_found('%d' % run_to_pass, self.stdout) + + +@rfm.simple_test +class DependencyT0(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo DependencyT0' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('DependencyT1') + +@rfm.simple_test +class DependencyT1(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo DependencyT1' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('DependencyT2') + +@rfm.simple_test +class DependencyT2(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo DependencyT2' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('DependencyT3') + +@rfm.simple_test +class DependencyT3(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo DependencyT3' + print('STDOUT') +# if self.stdout: + print('STDOUT DEFINED') +# else: + print('STDOUT NOT DEFINED') + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] diff --git a/unittests/test_cli.py b/unittests/test_cli.py index 69ffb3c3f1..5e0a798887 100644 --- a/unittests/test_cli.py +++ b/unittests/test_cli.py @@ -408,3 +408,12 @@ def test_verbosity(self): self.assertNotIn('Traceback', stdout) self.assertNotIn('Traceback', stderr) self.assertEqual(0, returncode) + + def test_dependency_cli(self): + self.checkpath = ['unittests/resources/checks/frontend_checks.py'] + self.action = 'run' + self.more_options = ['-n', 'Dependency'] + returncode, stdout, _ = self._run_reframe() + print(stdout) + self.assertIn('Running 4 check(s)', stdout) + self.assertEqual(1, returncode) From 9fbfb49df02e969593907ba8f0733f8100cc8022 Mon Sep 17 00:00:00 2001 From: bignamic Date: Wed, 18 Sep 2019 16:14:25 +0200 Subject: [PATCH 02/16] test cleanup procedure implemented with dependencies --- reframe/frontend/cli.py | 11 +++ reframe/frontend/executors/__init__.py | 33 +++----- reframe/frontend/executors/policies.py | 32 +++++--- unittests/resources/checks/frontend_checks.py | 76 +++++++++++++++++-- unittests/test_cli.py | 11 ++- 5 files changed, 122 insertions(+), 41 deletions(-) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index e145218fe1..57fb3c5b61 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -11,6 +11,7 @@ import reframe.core.runtime as runtime import reframe.frontend.argparse as argparse import reframe.frontend.check_filters as filters +import reframe.frontend.dependency as dependency import reframe.utility.os_ext as os_ext from reframe.core.exceptions import (EnvironError, ConfigError, ReframeError, ReframeFatalError, format_exception, @@ -487,6 +488,12 @@ def main(): # Act on checks + # Build dependency graph and reorder test case accordingly + dependency_graph = dependency.build_deps(testcases) + dependency.validate_deps(dependency_graph) + dependency.print_deps(dependency_graph) + testcases = dependency.toposort(dependency_graph) + # Unload regression's module and load user-specified modules if settings.reframe_module: rt.modules_system.unload_module(settings.reframe_module) @@ -557,6 +564,10 @@ def main(): exec_policy.sched_nodelist = options.nodelist exec_policy.sched_exclude_nodelist = options.exclude_nodes exec_policy.sched_options = options.job_options + exec_policy.dependency_tree = dependency_graph + exec_policy.dependency_count = dependency.create_deps_count( + dependency_graph) + try: max_retries = int(options.max_retries) except ValueError: diff --git a/reframe/frontend/executors/__init__.py b/reframe/frontend/executors/__init__.py index 20ac3d15e7..9d26b453ce 100644 --- a/reframe/frontend/executors/__init__.py +++ b/reframe/frontend/executors/__init__.py @@ -27,6 +27,8 @@ def __init__(self, check, partition, environ): self.__partition = copy.deepcopy(partition) self.__environ = copy.deepcopy(environ) self.__check._case = weakref.ref(self) + + # TODO: this member is not used self.__deps = [] def __iter__(self): @@ -262,25 +264,7 @@ def runall(self, testcases): self._printer.timestamp('Started on', 'short double line') self._printer.info('') try: - # TODO: dependenct-specific exception handling needed here - dependency_graph = dependency.build_deps(testcases) - dependency.validate_deps(dependency_graph) - dependency.print_deps(dependency_graph) - ordered_tests = dependency.toposort(dependency_graph) - keep_stage_flag = [] - for t in ordered_tests: - is_dependency = False - for c, deps in dependency_graph.items(): - if is_dependency is True: - break - if t in deps: - is_dependency = True - break - keep_stage_flag.append(is_dependency) - - print(keep_stage_flag) - print('CHRI') - self._runall(ordered_tests, keep_stage_flag) + self._runall(testcases) if self._max_retries: self._retry_failed(testcases) @@ -310,7 +294,7 @@ def _retry_failed(self, cases): self._runall(t.testcase.clone() for t in failures) failures = self._stats.failures() - def _runall(self, testcases, keep_stage_flag): + def _runall(self, testcases): def print_separator(check, prefix): self._printer.separator( 'short single line', @@ -319,8 +303,7 @@ def print_separator(check, prefix): self._policy.enter() last_check = None -# for t in testcases: - for index, t in enumerate(testcases): + for t in testcases: if last_check is None or last_check.name != t.check.name: if last_check is not None: print_separator(last_check, 'finished processing') @@ -330,7 +313,7 @@ def print_separator(check, prefix): last_check = t.check self._environ_snapshot.load() - self._policy.runcase(t, keep_stage_flag[index]) + self._policy.runcase(t) # Close the last visual box if last_check is not None: @@ -371,6 +354,10 @@ def __init__(self): self.stats = None + # Check dependencies data + self.dependency_tree = [] + self.dependency_count = [] + def __repr__(self): return debug.repr(self) diff --git a/reframe/frontend/executors/policies.py b/reframe/frontend/executors/policies.py index bb57ef0ca5..cc8cc476f0 100644 --- a/reframe/frontend/executors/policies.py +++ b/reframe/frontend/executors/policies.py @@ -14,7 +14,7 @@ def __init__(self): super().__init__() self._tasks = [] - def runcase(self, case, keep_stage): + def runcase(self, case): super().runcase(case) check, partition, environ = case @@ -23,9 +23,6 @@ def runcase(self, case, keep_stage): (check.name, partition.fullname, environ.name) ) - print('Keep stage?') - print(keep_stage) - task = RegressionTask(case) self._tasks.append(task) self.stats.add_task(task) @@ -49,12 +46,10 @@ def runcase(self, case, keep_stage): if not self.skip_performance_check: task.performance() - print('In policy') - print(case) - print(keep_stage) - -# if not keep_stage: -# task.cleanup(not self.keep_stage_files, False) + # Execute cleanup of current case if all dependent cases have been + # executed + if self.dependency_count[case] == 0: + task.cleanup(not self.keep_stage_files, False) except TaskExit: return @@ -64,6 +59,21 @@ def runcase(self, case, keep_stage): except BaseException: task.fail(sys.exc_info()) finally: + + # Execute cleanup of dependencies if all dependent cases have been + # executed + for dep in self.dependency_tree[case]: + self.dependency_count[dep] = -1 + if self.dependency_count[dep] == 0: + # Check if dep has failed before cleaning + for t in self.stats.tasks(): + if t.testcase == dep and t.failed is False: + dependency_clean_up_task = RegressionTask(dep) + dependency_clean_up_task.cleanup( + not self.keep_stage_files, + False) + break + self.printer.status('FAIL' if task.failed else 'OK', task.check.info(), just='right') @@ -153,7 +163,7 @@ def on_task_exit(self, task): self._remove_from_running(task) self._retired_tasks.append(task) - def runcase(self, case, keep_stage): + def runcase(self, case): super().runcase(case) check, partition, environ = case diff --git a/unittests/resources/checks/frontend_checks.py b/unittests/resources/checks/frontend_checks.py index c98382632c..143d31d796 100644 --- a/unittests/resources/checks/frontend_checks.py +++ b/unittests/resources/checks/frontend_checks.py @@ -217,11 +217,77 @@ class DependencyT3(rfm.RunOnlyRegressionTest): def __init__(self): self.local = True self.executable = 'echo DependencyT3' - print('STDOUT') -# if self.stdout: - print('STDOUT DEFINED') -# else: - print('STDOUT NOT DEFINED') + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + +@rfm.simple_test +class MultiDependencyT0(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT0' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT1') + self.depends_on('MultiDependencyT2') + +@rfm.simple_test +class MultiDependencyT1(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT1' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT6') + +@rfm.simple_test +class MultiDependencyT2(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT2' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT3') + self.depends_on('MultiDependencyT4') + +@rfm.simple_test +class MultiDependencyT3(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT3' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT6') + self.depends_on('MultiDependencyT5') + +@rfm.simple_test +class MultiDependencyT4(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT4' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT5') + +@rfm.simple_test +class MultiDependencyT5(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT5' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + +@rfm.simple_test +class MultiDependencyT6(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT6' self.sanity_patterns = sn.assert_found('Dependency', self.stdout) self.valid_systems = ['*'] self.valid_prog_environs = ['*'] diff --git a/unittests/test_cli.py b/unittests/test_cli.py index 5e0a798887..9fff0dfed7 100644 --- a/unittests/test_cli.py +++ b/unittests/test_cli.py @@ -414,6 +414,13 @@ def test_dependency_cli(self): self.action = 'run' self.more_options = ['-n', 'Dependency'] returncode, stdout, _ = self._run_reframe() - print(stdout) self.assertIn('Running 4 check(s)', stdout) - self.assertEqual(1, returncode) + self.assertEqual(0, returncode) + + def test_multi_dependency_cli(self): + self.checkpath = ['unittests/resources/checks/frontend_checks.py'] + self.action = 'run' + self.more_options = ['-n', 'MultiDependency'] + returncode, stdout, _ = self._run_reframe() + self.assertIn('Running 7 check(s)', stdout) + self.assertEqual(0, returncode) From 60d2156df56485ef056afad41268ce324f0642dc Mon Sep 17 00:00:00 2001 From: bignamic Date: Wed, 18 Sep 2019 16:30:49 +0200 Subject: [PATCH 03/16] Merge with master --- reframe/frontend/dependency.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/reframe/frontend/dependency.py b/reframe/frontend/dependency.py index 192ccb7424..68a5e36abf 100644 --- a/reframe/frontend/dependency.py +++ b/reframe/frontend/dependency.py @@ -167,3 +167,21 @@ def visit(node, path): cases_by_name[c.check.name] = [c] return list(itertools.chain(*(cases_by_name[n] for n in visited))) + + +def create_deps_count(graph): + + # TODO: create unit test + deps_count = {} + for test, deps in graph.items(): + try: + deps_count[test] += 1 + except KeyError: + deps_count[test] = 0 + for dep in deps: + try: + deps_count[dep] += 1 + except KeyError: + deps_count[dep] = 0 + + return deps_count From bca4959143f4e6a16eee3d8565be3592dc22366b Mon Sep 17 00:00:00 2001 From: bignamic Date: Wed, 18 Sep 2019 17:03:46 +0200 Subject: [PATCH 04/16] Bug fixed --- reframe/frontend/executors/policies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reframe/frontend/executors/policies.py b/reframe/frontend/executors/policies.py index cc8cc476f0..f59fc8d027 100644 --- a/reframe/frontend/executors/policies.py +++ b/reframe/frontend/executors/policies.py @@ -63,7 +63,7 @@ def runcase(self, case): # Execute cleanup of dependencies if all dependent cases have been # executed for dep in self.dependency_tree[case]: - self.dependency_count[dep] = -1 + self.dependency_count[dep] -= 1 if self.dependency_count[dep] == 0: # Check if dep has failed before cleaning for t in self.stats.tasks(): From 4a9cb19a1f80f34341ae68efc5ea11a406778969 Mon Sep 17 00:00:00 2001 From: bignamic Date: Wed, 18 Sep 2019 17:11:12 +0200 Subject: [PATCH 05/16] Coding style fixes --- unittests/resources/checks/frontend_checks.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/unittests/resources/checks/frontend_checks.py b/unittests/resources/checks/frontend_checks.py index 143d31d796..86312bc6d5 100644 --- a/unittests/resources/checks/frontend_checks.py +++ b/unittests/resources/checks/frontend_checks.py @@ -192,6 +192,7 @@ def __init__(self): self.valid_prog_environs = ['*'] self.depends_on('DependencyT1') + @rfm.simple_test class DependencyT1(rfm.RunOnlyRegressionTest): def __init__(self): @@ -202,6 +203,7 @@ def __init__(self): self.valid_prog_environs = ['*'] self.depends_on('DependencyT2') + @rfm.simple_test class DependencyT2(rfm.RunOnlyRegressionTest): def __init__(self): @@ -212,6 +214,7 @@ def __init__(self): self.valid_prog_environs = ['*'] self.depends_on('DependencyT3') + @rfm.simple_test class DependencyT3(rfm.RunOnlyRegressionTest): def __init__(self): @@ -221,6 +224,7 @@ def __init__(self): self.valid_systems = ['*'] self.valid_prog_environs = ['*'] + @rfm.simple_test class MultiDependencyT0(rfm.RunOnlyRegressionTest): def __init__(self): @@ -232,6 +236,7 @@ def __init__(self): self.depends_on('MultiDependencyT1') self.depends_on('MultiDependencyT2') + @rfm.simple_test class MultiDependencyT1(rfm.RunOnlyRegressionTest): def __init__(self): @@ -242,6 +247,7 @@ def __init__(self): self.valid_prog_environs = ['*'] self.depends_on('MultiDependencyT6') + @rfm.simple_test class MultiDependencyT2(rfm.RunOnlyRegressionTest): def __init__(self): @@ -253,6 +259,7 @@ def __init__(self): self.depends_on('MultiDependencyT3') self.depends_on('MultiDependencyT4') + @rfm.simple_test class MultiDependencyT3(rfm.RunOnlyRegressionTest): def __init__(self): @@ -264,6 +271,7 @@ def __init__(self): self.depends_on('MultiDependencyT6') self.depends_on('MultiDependencyT5') + @rfm.simple_test class MultiDependencyT4(rfm.RunOnlyRegressionTest): def __init__(self): @@ -274,6 +282,7 @@ def __init__(self): self.valid_prog_environs = ['*'] self.depends_on('MultiDependencyT5') + @rfm.simple_test class MultiDependencyT5(rfm.RunOnlyRegressionTest): def __init__(self): @@ -283,6 +292,7 @@ def __init__(self): self.valid_systems = ['*'] self.valid_prog_environs = ['*'] + @rfm.simple_test class MultiDependencyT6(rfm.RunOnlyRegressionTest): def __init__(self): From ba6b693f2d0b6021fd46cbb5bdd4abea662c5527 Mon Sep 17 00:00:00 2001 From: bignamic Date: Thu, 19 Sep 2019 17:14:30 +0200 Subject: [PATCH 06/16] Updated number of loaded checks in unit tests and fixed dependency graph type initialization --- reframe/frontend/executors/__init__.py | 3 ++- unittests/test_loader.py | 4 ++-- unittests/test_policies.py | 12 ++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/reframe/frontend/executors/__init__.py b/reframe/frontend/executors/__init__.py index 9d26b453ce..5cebc8155c 100644 --- a/reframe/frontend/executors/__init__.py +++ b/reframe/frontend/executors/__init__.py @@ -1,5 +1,6 @@ import abc import copy +import collections import sys import weakref @@ -355,7 +356,7 @@ def __init__(self): self.stats = None # Check dependencies data - self.dependency_tree = [] + self.dependency_tree = collections.OrderedDict() self.dependency_count = [] def __repr__(self): diff --git a/unittests/test_loader.py b/unittests/test_loader.py index 700e4c4968..ff6df20740 100644 --- a/unittests/test_loader.py +++ b/unittests/test_loader.py @@ -32,11 +32,11 @@ def test_load_file_absolute(self): def test_load_recursive(self): checks = self.loader.load_from_dir('unittests/resources/checks', recurse=True) - self.assertEqual(11, len(checks)) + self.assertEqual(22, len(checks)) def test_load_all(self): checks = self.loader_with_path.load_all() - self.assertEqual(10, len(checks)) + self.assertEqual(21, len(checks)) def test_load_all_with_prefix(self): checks = self.loader_with_prefix.load_all() diff --git a/unittests/test_policies.py b/unittests/test_policies.py index 0da4acde96..5cba0f478b 100644 --- a/unittests/test_policies.py +++ b/unittests/test_policies.py @@ -68,7 +68,7 @@ def test_runall(self): self.runall(self.checks) stats = self.runner.stats - self.assertEqual(7, stats.num_cases()) + self.assertEqual(18, stats.num_cases()) self.assertEqual(4, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) @@ -78,7 +78,7 @@ def test_runall_skip_system_check(self): self.runall(self.checks, skip_system_check=True) stats = self.runner.stats - self.assertEqual(8, stats.num_cases()) + self.assertEqual(19, stats.num_cases()) self.assertEqual(4, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) @@ -88,7 +88,7 @@ def test_runall_skip_prgenv_check(self): self.runall(self.checks, skip_environ_check=True) stats = self.runner.stats - self.assertEqual(8, stats.num_cases()) + self.assertEqual(19, stats.num_cases()) self.assertEqual(4, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) @@ -99,7 +99,7 @@ def test_runall_skip_sanity_check(self): self.runall(self.checks) stats = self.runner.stats - self.assertEqual(7, stats.num_cases()) + self.assertEqual(18, stats.num_cases()) self.assertEqual(3, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(0, self._num_failures_stage('sanity')) @@ -110,7 +110,7 @@ def test_runall_skip_performance_check(self): self.runall(self.checks) stats = self.runner.stats - self.assertEqual(7, stats.num_cases()) + self.assertEqual(18, stats.num_cases()) self.assertEqual(3, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) @@ -121,7 +121,7 @@ def test_strict_performance_check(self): self.runall(self.checks) stats = self.runner.stats - self.assertEqual(7, stats.num_cases()) + self.assertEqual(18, stats.num_cases()) self.assertEqual(5, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) From ef9acf6ebf8575621287bbc9b01f7c081dc46d09 Mon Sep 17 00:00:00 2001 From: bignamic Date: Thu, 19 Sep 2019 17:35:12 +0200 Subject: [PATCH 07/16] Dependency graph building moved into Runner class --- reframe/frontend/cli.py | 10 ---------- reframe/frontend/executors/__init__.py | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 57fb3c5b61..543e46fbcb 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -11,7 +11,6 @@ import reframe.core.runtime as runtime import reframe.frontend.argparse as argparse import reframe.frontend.check_filters as filters -import reframe.frontend.dependency as dependency import reframe.utility.os_ext as os_ext from reframe.core.exceptions import (EnvironError, ConfigError, ReframeError, ReframeFatalError, format_exception, @@ -488,12 +487,6 @@ def main(): # Act on checks - # Build dependency graph and reorder test case accordingly - dependency_graph = dependency.build_deps(testcases) - dependency.validate_deps(dependency_graph) - dependency.print_deps(dependency_graph) - testcases = dependency.toposort(dependency_graph) - # Unload regression's module and load user-specified modules if settings.reframe_module: rt.modules_system.unload_module(settings.reframe_module) @@ -564,9 +557,6 @@ def main(): exec_policy.sched_nodelist = options.nodelist exec_policy.sched_exclude_nodelist = options.exclude_nodes exec_policy.sched_options = options.job_options - exec_policy.dependency_tree = dependency_graph - exec_policy.dependency_count = dependency.create_deps_count( - dependency_graph) try: max_retries = int(options.max_retries) diff --git a/reframe/frontend/executors/__init__.py b/reframe/frontend/executors/__init__.py index 5cebc8155c..5cf10b1b75 100644 --- a/reframe/frontend/executors/__init__.py +++ b/reframe/frontend/executors/__init__.py @@ -259,6 +259,16 @@ def stats(self): return self._stats def runall(self, testcases): + + # Build dependency graph and reorder test case accordingly + dependency_graph = dependency.build_deps(testcases) + dependency.validate_deps(dependency_graph) + dependency.print_deps(dependency_graph) + testcases = dependency.toposort(dependency_graph) + self._policy.dependency_tree = dependency_graph + self._policy.dependency_count = dependency.create_deps_count( + dependency_graph) + num_checks = len({tc.check.name for tc in testcases}) self._printer.separator('short double line', 'Running %d check(s)' % num_checks) From db06b1652123b894d4b41dae6f5915d90f6d6ccd Mon Sep 17 00:00:00 2001 From: bignamic Date: Wed, 2 Oct 2019 16:26:29 +0200 Subject: [PATCH 08/16] Code cleaning --- reframe/frontend/cli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/reframe/frontend/cli.py b/reframe/frontend/cli.py index 543e46fbcb..e145218fe1 100644 --- a/reframe/frontend/cli.py +++ b/reframe/frontend/cli.py @@ -557,7 +557,6 @@ def main(): exec_policy.sched_nodelist = options.nodelist exec_policy.sched_exclude_nodelist = options.exclude_nodes exec_policy.sched_options = options.job_options - try: max_retries = int(options.max_retries) except ValueError: From 268f9e669a203f104b9e70095ac1aa001373e36e Mon Sep 17 00:00:00 2001 From: bignamic Date: Fri, 4 Oct 2019 12:26:49 +0200 Subject: [PATCH 09/16] Cleanup with dependency tests moved --- .../checks_unlisted/cleanup_checks.py | 127 ++++++++++++++++++ .../resources/checks_unlisted/test_cleanup.py | 20 +++ unittests/test_cli.py | 16 --- unittests/test_loader.py | 4 +- unittests/test_policies.py | 12 +- 5 files changed, 155 insertions(+), 24 deletions(-) create mode 100644 unittests/resources/checks_unlisted/cleanup_checks.py create mode 100644 unittests/resources/checks_unlisted/test_cleanup.py diff --git a/unittests/resources/checks_unlisted/cleanup_checks.py b/unittests/resources/checks_unlisted/cleanup_checks.py new file mode 100644 index 0000000000..b6e897ed40 --- /dev/null +++ b/unittests/resources/checks_unlisted/cleanup_checks.py @@ -0,0 +1,127 @@ +# +# Checks for testing the cleanup procedure with dependencies +# + +import reframe as rfm +import reframe.utility.sanity as sn + + +@rfm.simple_test +class DependencyT0(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo DependencyT0' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('DependencyT1') + + +@rfm.simple_test +class DependencyT1(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo DependencyT1' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('DependencyT2') + + +@rfm.simple_test +class DependencyT2(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo DependencyT2' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('DependencyT3') + + +@rfm.simple_test +class DependencyT3(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo DependencyT3' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + + +@rfm.simple_test +class MultiDependencyT0(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT0' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT1') + self.depends_on('MultiDependencyT2') + + +@rfm.simple_test +class MultiDependencyT1(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT1' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT6') + + +@rfm.simple_test +class MultiDependencyT2(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT2' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT3') + self.depends_on('MultiDependencyT4') + + +@rfm.simple_test +class MultiDependencyT3(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT3' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT6') + self.depends_on('MultiDependencyT5') + + +@rfm.simple_test +class MultiDependencyT4(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT4' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + self.depends_on('MultiDependencyT5') + + +@rfm.simple_test +class MultiDependencyT5(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT5' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] + + +@rfm.simple_test +class MultiDependencyT6(rfm.RunOnlyRegressionTest): + def __init__(self): + self.local = True + self.executable = 'echo MultiDependencyT6' + self.sanity_patterns = sn.assert_found('Dependency', self.stdout) + self.valid_systems = ['*'] + self.valid_prog_environs = ['*'] diff --git a/unittests/resources/checks_unlisted/test_cleanup.py b/unittests/resources/checks_unlisted/test_cleanup.py new file mode 100644 index 0000000000..2d3a3a6fc6 --- /dev/null +++ b/unittests/resources/checks_unlisted/test_cleanup.py @@ -0,0 +1,20 @@ +import unittest +from unittests.test_cli import TestFrontend + + +class TestCleanup(TestFrontend): + def test_dependency_cli(self): + self.checkpath = ['unittests/resources/checks_unlisted/cleanup_checks.py'] + self.action = 'run' + self.more_options = ['-n', 'Dependency'] + returncode, stdout, _ = self._run_reframe() + self.assertIn('Running 4 check(s)', stdout) + self.assertEqual(0, returncode) + + def test_multi_dependency_cli(self): + self.checkpath = ['unittests/resources/checks_unlisted/cleanup_checks.py'] + self.action = 'run' + self.more_options = ['-n', 'MultiDependency'] + returncode, stdout, _ = self._run_reframe() + self.assertIn('Running 7 check(s)', stdout) + self.assertEqual(0, returncode) diff --git a/unittests/test_cli.py b/unittests/test_cli.py index 9fff0dfed7..69ffb3c3f1 100644 --- a/unittests/test_cli.py +++ b/unittests/test_cli.py @@ -408,19 +408,3 @@ def test_verbosity(self): self.assertNotIn('Traceback', stdout) self.assertNotIn('Traceback', stderr) self.assertEqual(0, returncode) - - def test_dependency_cli(self): - self.checkpath = ['unittests/resources/checks/frontend_checks.py'] - self.action = 'run' - self.more_options = ['-n', 'Dependency'] - returncode, stdout, _ = self._run_reframe() - self.assertIn('Running 4 check(s)', stdout) - self.assertEqual(0, returncode) - - def test_multi_dependency_cli(self): - self.checkpath = ['unittests/resources/checks/frontend_checks.py'] - self.action = 'run' - self.more_options = ['-n', 'MultiDependency'] - returncode, stdout, _ = self._run_reframe() - self.assertIn('Running 7 check(s)', stdout) - self.assertEqual(0, returncode) diff --git a/unittests/test_loader.py b/unittests/test_loader.py index ff6df20740..700e4c4968 100644 --- a/unittests/test_loader.py +++ b/unittests/test_loader.py @@ -32,11 +32,11 @@ def test_load_file_absolute(self): def test_load_recursive(self): checks = self.loader.load_from_dir('unittests/resources/checks', recurse=True) - self.assertEqual(22, len(checks)) + self.assertEqual(11, len(checks)) def test_load_all(self): checks = self.loader_with_path.load_all() - self.assertEqual(21, len(checks)) + self.assertEqual(10, len(checks)) def test_load_all_with_prefix(self): checks = self.loader_with_prefix.load_all() diff --git a/unittests/test_policies.py b/unittests/test_policies.py index 5cba0f478b..0da4acde96 100644 --- a/unittests/test_policies.py +++ b/unittests/test_policies.py @@ -68,7 +68,7 @@ def test_runall(self): self.runall(self.checks) stats = self.runner.stats - self.assertEqual(18, stats.num_cases()) + self.assertEqual(7, stats.num_cases()) self.assertEqual(4, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) @@ -78,7 +78,7 @@ def test_runall_skip_system_check(self): self.runall(self.checks, skip_system_check=True) stats = self.runner.stats - self.assertEqual(19, stats.num_cases()) + self.assertEqual(8, stats.num_cases()) self.assertEqual(4, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) @@ -88,7 +88,7 @@ def test_runall_skip_prgenv_check(self): self.runall(self.checks, skip_environ_check=True) stats = self.runner.stats - self.assertEqual(19, stats.num_cases()) + self.assertEqual(8, stats.num_cases()) self.assertEqual(4, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) @@ -99,7 +99,7 @@ def test_runall_skip_sanity_check(self): self.runall(self.checks) stats = self.runner.stats - self.assertEqual(18, stats.num_cases()) + self.assertEqual(7, stats.num_cases()) self.assertEqual(3, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(0, self._num_failures_stage('sanity')) @@ -110,7 +110,7 @@ def test_runall_skip_performance_check(self): self.runall(self.checks) stats = self.runner.stats - self.assertEqual(18, stats.num_cases()) + self.assertEqual(7, stats.num_cases()) self.assertEqual(3, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) @@ -121,7 +121,7 @@ def test_strict_performance_check(self): self.runall(self.checks) stats = self.runner.stats - self.assertEqual(18, stats.num_cases()) + self.assertEqual(7, stats.num_cases()) self.assertEqual(5, len(stats.failures())) self.assertEqual(2, self._num_failures_stage('setup')) self.assertEqual(1, self._num_failures_stage('sanity')) From 023b283c56a7fb34576f212935ec76ec4253b51e Mon Sep 17 00:00:00 2001 From: bignamic Date: Fri, 4 Oct 2019 14:56:46 +0200 Subject: [PATCH 10/16] Code cleaning --- reframe/frontend/dependency.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/reframe/frontend/dependency.py b/reframe/frontend/dependency.py index 68a5e36abf..94f6e7e0d2 100644 --- a/reframe/frontend/dependency.py +++ b/reframe/frontend/dependency.py @@ -169,19 +169,16 @@ def visit(node, path): return list(itertools.chain(*(cases_by_name[n] for n in visited))) -def create_deps_count(graph): +def create_ref_count(graph): # TODO: create unit test - deps_count = {} - for test, deps in graph.items(): - try: - deps_count[test] += 1 - except KeyError: - deps_count[test] = 0 - for dep in deps: + ref_count = {} + for node, deps in graph.items(): + ref_count.setdefault(node,0) + for adj in deps: try: - deps_count[dep] += 1 + ref_count[adj] += 1 except KeyError: - deps_count[dep] = 0 + ref_count[adj] = 0 - return deps_count + return ref_count From 75ae31d751b456edd24b4bb17ba91cc95c20e798 Mon Sep 17 00:00:00 2001 From: bignamic Date: Fri, 4 Oct 2019 14:59:06 +0200 Subject: [PATCH 11/16] Dependecies cleanup tests moved to new location --- unittests/resources/checks/frontend_checks.py | 121 ------------------ 1 file changed, 121 deletions(-) diff --git a/unittests/resources/checks/frontend_checks.py b/unittests/resources/checks/frontend_checks.py index 86312bc6d5..b144f97668 100644 --- a/unittests/resources/checks/frontend_checks.py +++ b/unittests/resources/checks/frontend_checks.py @@ -180,124 +180,3 @@ def __init__(self, run_to_pass, filename): self.post_run = ['((current_run++))', 'echo $current_run > %s' % filename] self.sanity_patterns = sn.assert_found('%d' % run_to_pass, self.stdout) - - -@rfm.simple_test -class DependencyT0(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo DependencyT0' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - self.depends_on('DependencyT1') - - -@rfm.simple_test -class DependencyT1(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo DependencyT1' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - self.depends_on('DependencyT2') - - -@rfm.simple_test -class DependencyT2(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo DependencyT2' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - self.depends_on('DependencyT3') - - -@rfm.simple_test -class DependencyT3(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo DependencyT3' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - - -@rfm.simple_test -class MultiDependencyT0(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo MultiDependencyT0' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - self.depends_on('MultiDependencyT1') - self.depends_on('MultiDependencyT2') - - -@rfm.simple_test -class MultiDependencyT1(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo MultiDependencyT1' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - self.depends_on('MultiDependencyT6') - - -@rfm.simple_test -class MultiDependencyT2(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo MultiDependencyT2' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - self.depends_on('MultiDependencyT3') - self.depends_on('MultiDependencyT4') - - -@rfm.simple_test -class MultiDependencyT3(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo MultiDependencyT3' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - self.depends_on('MultiDependencyT6') - self.depends_on('MultiDependencyT5') - - -@rfm.simple_test -class MultiDependencyT4(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo MultiDependencyT4' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - self.depends_on('MultiDependencyT5') - - -@rfm.simple_test -class MultiDependencyT5(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo MultiDependencyT5' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] - - -@rfm.simple_test -class MultiDependencyT6(rfm.RunOnlyRegressionTest): - def __init__(self): - self.local = True - self.executable = 'echo MultiDependencyT6' - self.sanity_patterns = sn.assert_found('Dependency', self.stdout) - self.valid_systems = ['*'] - self.valid_prog_environs = ['*'] From 279757a68a003d705159ef453184688c3ab048ed Mon Sep 17 00:00:00 2001 From: bignamic Date: Fri, 4 Oct 2019 15:08:35 +0200 Subject: [PATCH 12/16] Code cleaning --- reframe/frontend/executors/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/reframe/frontend/executors/__init__.py b/reframe/frontend/executors/__init__.py index 5cf10b1b75..a2f79cf592 100644 --- a/reframe/frontend/executors/__init__.py +++ b/reframe/frontend/executors/__init__.py @@ -28,8 +28,6 @@ def __init__(self, check, partition, environ): self.__partition = copy.deepcopy(partition) self.__environ = copy.deepcopy(environ) self.__check._case = weakref.ref(self) - - # TODO: this member is not used self.__deps = [] def __iter__(self): @@ -263,10 +261,9 @@ def runall(self, testcases): # Build dependency graph and reorder test case accordingly dependency_graph = dependency.build_deps(testcases) dependency.validate_deps(dependency_graph) - dependency.print_deps(dependency_graph) testcases = dependency.toposort(dependency_graph) self._policy.dependency_tree = dependency_graph - self._policy.dependency_count = dependency.create_deps_count( + self._policy.ref_count = dependency.create_ref_count( dependency_graph) num_checks = len({tc.check.name for tc in testcases}) @@ -367,7 +364,10 @@ def __init__(self): # Check dependencies data self.dependency_tree = collections.OrderedDict() - self.dependency_count = [] + # For each check to be executed in a refame run + # ref_count[c] stores the number of checks depending + # on check c + self.ref_count = [] def __repr__(self): return debug.repr(self) From b3f726be91fc8aafc99ecc3bfdf7f9d961fdeaa1 Mon Sep 17 00:00:00 2001 From: bignamic Date: Fri, 4 Oct 2019 15:11:38 +0200 Subject: [PATCH 13/16] Code cleaning --- reframe/frontend/executors/policies.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/reframe/frontend/executors/policies.py b/reframe/frontend/executors/policies.py index f59fc8d027..fd3360b72e 100644 --- a/reframe/frontend/executors/policies.py +++ b/reframe/frontend/executors/policies.py @@ -22,7 +22,6 @@ def runcase(self, case): 'RUN', '%s on %s using %s' % (check.name, partition.fullname, environ.name) ) - task = RegressionTask(case) self._tasks.append(task) self.stats.add_task(task) @@ -48,7 +47,7 @@ def runcase(self, case): # Execute cleanup of current case if all dependent cases have been # executed - if self.dependency_count[case] == 0: + if self.ref_count[case] == 0: task.cleanup(not self.keep_stage_files, False) except TaskExit: @@ -63,8 +62,8 @@ def runcase(self, case): # Execute cleanup of dependencies if all dependent cases have been # executed for dep in self.dependency_tree[case]: - self.dependency_count[dep] -= 1 - if self.dependency_count[dep] == 0: + self.ref_count[dep] -= 1 + if self.ref_count[dep] == 0: # Check if dep has failed before cleaning for t in self.stats.tasks(): if t.testcase == dep and t.failed is False: From 4346353d02f8ce716ab62eca1b355fe8296275d3 Mon Sep 17 00:00:00 2001 From: bignamic Date: Tue, 15 Oct 2019 16:05:16 +0200 Subject: [PATCH 14/16] Coding style fix --- reframe/frontend/dependency.py | 2 +- unittests/resources/checks_unlisted/test_cleanup.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/reframe/frontend/dependency.py b/reframe/frontend/dependency.py index b0cb8ffd26..1f203cbdd3 100644 --- a/reframe/frontend/dependency.py +++ b/reframe/frontend/dependency.py @@ -174,7 +174,7 @@ def create_ref_count(graph): # TODO: create unit test ref_count = {} for node, deps in graph.items(): - ref_count.setdefault(node,0) + ref_count.setdefault(node, 0) for adj in deps: try: ref_count[adj] += 1 diff --git a/unittests/resources/checks_unlisted/test_cleanup.py b/unittests/resources/checks_unlisted/test_cleanup.py index 2d3a3a6fc6..6abf5d4211 100644 --- a/unittests/resources/checks_unlisted/test_cleanup.py +++ b/unittests/resources/checks_unlisted/test_cleanup.py @@ -4,7 +4,8 @@ class TestCleanup(TestFrontend): def test_dependency_cli(self): - self.checkpath = ['unittests/resources/checks_unlisted/cleanup_checks.py'] + self.checkpath = + ['unittests/resources/checks_unlisted/cleanup_checks.py'] self.action = 'run' self.more_options = ['-n', 'Dependency'] returncode, stdout, _ = self._run_reframe() @@ -12,7 +13,8 @@ def test_dependency_cli(self): self.assertEqual(0, returncode) def test_multi_dependency_cli(self): - self.checkpath = ['unittests/resources/checks_unlisted/cleanup_checks.py'] + self.checkpath = + ['unittests/resources/checks_unlisted/cleanup_checks.py'] self.action = 'run' self.more_options = ['-n', 'MultiDependency'] returncode, stdout, _ = self._run_reframe() From 9ee4fb886d6aab1281a6355da75b697e9f455bfe Mon Sep 17 00:00:00 2001 From: bignamic Date: Thu, 24 Oct 2019 15:00:16 +0200 Subject: [PATCH 15/16] Coding style fixes --- reframe/frontend/executors/__init__.py | 3 +-- reframe/frontend/executors/policies.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/reframe/frontend/executors/__init__.py b/reframe/frontend/executors/__init__.py index 068224ae2e..5827342480 100644 --- a/reframe/frontend/executors/__init__.py +++ b/reframe/frontend/executors/__init__.py @@ -258,7 +258,6 @@ def stats(self): def runall(self, testcases): - num_checks = len({tc.check.name for tc in testcases}) self._printer.separator('short double line', 'Running %d check(s)' % num_checks) @@ -329,7 +328,7 @@ class ExecutionPolicy(abc.ABC): An execution policy implements the regression check pipeline.''' - def __init__(self, dependency_graph = None): + def __init__(self, dependency_graph=None): # Options controlling the check execution self.skip_system_check = False self.force_local = False diff --git a/reframe/frontend/executors/policies.py b/reframe/frontend/executors/policies.py index eaa60d5f7c..b1dc3ea21a 100644 --- a/reframe/frontend/executors/policies.py +++ b/reframe/frontend/executors/policies.py @@ -10,7 +10,7 @@ class SerialExecutionPolicy(ExecutionPolicy): - def __init__(self, dependency_graph = None): + def __init__(self, dependency_graph=None): super().__init__(dependency_graph) self._tasks = [] @@ -110,7 +110,7 @@ def __call__(self, x, init_rate): class AsynchronousExecutionPolicy(ExecutionPolicy, TaskEventListener): - def __init__(self, dependency_graph = None): + def __init__(self, dependency_graph=None): super().__init__(dependency_graph) From f181c8b805914b8a2dd37d30c78e1fe9f9de1acb Mon Sep 17 00:00:00 2001 From: bignamic Date: Fri, 25 Oct 2019 16:37:03 +0200 Subject: [PATCH 16/16] Exception handling fix in cleanup procedure. --- reframe/frontend/executors/policies.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/reframe/frontend/executors/policies.py b/reframe/frontend/executors/policies.py index b1dc3ea21a..6f9d6572eb 100644 --- a/reframe/frontend/executors/policies.py +++ b/reframe/frontend/executors/policies.py @@ -50,15 +50,6 @@ def runcase(self, case): if self.ref_count is None or self.ref_count[case] == 0: task.cleanup(not self.keep_stage_files) - except TaskExit: - return - except ABORT_REASONS as e: - task.abort(e) - raise - except BaseException: - task.fail(sys.exc_info()) - finally: - # Execute cleanup of dependencies if all dependent cases have been # executed if self.dependency_graph is not None: @@ -68,11 +59,17 @@ def runcase(self, case): # Check if dep has failed before cleaning for t in self.stats.tasks(): if t.testcase == dep and t.failed is False: - dependency_clean_up_task = RegressionTask(dep) - dependency_clean_up_task.cleanup( - not self.keep_stage_files) + t.cleanup(not self.keep_stage_files) break + except TaskExit: + return + except ABORT_REASONS as e: + task.abort(e) + raise + except BaseException: + task.fail(sys.exc_info()) + finally: self.printer.status('FAIL' if task.failed else 'OK', task.check.info(), just='right')