diff --git a/easybuild/base/testing.py b/easybuild/base/testing.py index 41ec3b899f..33d40e497b 100644 --- a/easybuild/base/testing.py +++ b/easybuild/base/testing.py @@ -206,30 +206,30 @@ def get_stderr(self): return sys.stderr.getvalue() @contextmanager - def mocked_stdout(self): + def mocked_stdout(self, force_tty=False): """Context manager to mock stdout""" self.mock_stdout(True) try: yield sys.stdout finally: - self.mock_stdout(False) + self.mock_stdout(False, force_tty=force_tty) @contextmanager - def mocked_stderr(self): + def mocked_stderr(self, force_tty=False): """Context manager to mock stdout""" self.mock_stderr(True) try: yield sys.stderr finally: - self.mock_stderr(False) + self.mock_stderr(False, force_tty=force_tty) @contextmanager - def mocked_stdout_stderr(self, mock_stdout=True, mock_stderr=True): + def mocked_stdout_stderr(self, mock_stdout=True, mock_stderr=True, force_tty=False): """Context manager to mock stdout and stderr""" if mock_stdout: - self.mock_stdout(True) + self.mock_stdout(True, force_tty=force_tty) if mock_stderr: - self.mock_stderr(True) + self.mock_stderr(True, force_tty=force_tty) try: if mock_stdout and mock_stderr: yield sys.stdout, sys.stderr diff --git a/test/framework/build_log.py b/test/framework/build_log.py index 3ff8d6801a..47687426c1 100644 --- a/test/framework/build_log.py +++ b/test/framework/build_log.py @@ -111,19 +111,18 @@ def test_easybuildlog(self): # test basic log methods logToFile(tmplog, enable=True) log = getLogger('test_easybuildlog') - self.mock_stderr(True) - log.setLevelName('DEBUG') - log.debug("123 debug") - log.info("foobar info") - log.warning("justawarning") - log.deprecated("anotherwarning", newer_ver) - log.deprecated("onemorewarning", '1.0', '2.0') - log.deprecated("lastwarning", '1.0', max_ver='2.0') - log.deprecated("thisisnotprinted", '1.0', max_ver='2.0', silent=True) - log.error("kaput") - log.error("err: %s", 'msg: %s') - stderr = self.get_stderr() - self.mock_stderr(False) + with self.mocked_stderr(): + log.setLevelName('DEBUG') + log.debug("123 debug") + log.info("foobar info") + log.warning("justawarning") + log.deprecated("anotherwarning", newer_ver) + log.deprecated("onemorewarning", '1.0', '2.0') + log.deprecated("lastwarning", '1.0', max_ver='2.0') + log.deprecated("thisisnotprinted", '1.0', max_ver='2.0', silent=True) + log.error("kaput") + log.error("err: %s", 'msg: %s') + stderr = self.get_stderr() more_info = "see https://docs.easybuild.io/deprecated-functionality/ for more information" common_warning = "\nWARNING: Deprecated functionality, will no longer work in" @@ -188,9 +187,8 @@ def test_easybuildlog(self): logToFile(tmplog, enable=True) # also test use of 'more_info' named argument for log.deprecated - self.mock_stderr(True) - log.deprecated("\nthis is just a test\n", newer_ver, more_info="(see URLGOESHERE for more information)") - self.mock_stderr(False) + with self.mocked_stderr(): + log.deprecated("\nthis is just a test\n", newer_ver, more_info="(see URLGOESHERE for more information)") logtxt = read_file(tmplog) expected_logtxt = '\n'.join([ "[WARNING] :: Deprecated functionality, will no longer work in EasyBuild v10000001: ", @@ -211,18 +209,17 @@ def test_log_levels(self): logToFile(tmplog, enable=True) log = getLogger('test_easybuildlog') - self.mock_stderr(True) # avoid that some log statement spit out stuff to stderr while tests are running - for level in ['ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEVEL']: - log.setLevelName(level) - log.raiseError = False - log.error('kaput') - log.deprecated('almost kaput', '10000000000000') - log.raiseError = True - log.warning('this is a warning') - log.info('fyi') - log.debug('gdb') - log.devel('tmi') - self.mock_stderr(False) + with self.mocked_stderr(): # avoid that some log statement spit out stuff to stderr while tests are running + for level in ['ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEVEL']: + log.setLevelName(level) + log.raiseError = False + log.error('kaput') + log.deprecated('almost kaput', '10000000000000') + log.raiseError = True + log.warning('this is a warning') + log.info('fyi') + log.debug('gdb') + log.devel('tmi') logToFile(tmplog, enable=False) logtxt = read_file(tmplog) @@ -249,13 +246,10 @@ def test_print_warning(self): """Test print_warning""" def run_check(args, silent=False, expected_stderr='', **kwargs): """Helper function to check stdout/stderr produced via print_warning.""" - self.mock_stderr(True) - self.mock_stdout(True) - print_warning(*args, silent=silent, **kwargs) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + print_warning(*args, silent=silent, **kwargs) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertEqual(stdout, '') self.assertEqual(stderr, expected_stderr) @@ -308,13 +302,10 @@ def test_print_msg(self): """Test print_msg""" def run_check(msg, args, expected_stdout='', expected_stderr='', **kwargs): """Helper function to check stdout/stderr produced via print_msg.""" - self.mock_stdout(True) - self.mock_stderr(True) - print_msg(msg, *args, **kwargs) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + print_msg(msg, *args, **kwargs) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(stdout, expected_stdout) self.assertEqual(stderr, expected_stderr) @@ -347,13 +338,10 @@ def test_print_msg_rich(self): def run_check(msg, args, expected_stdout='', expected_stderr='', **kwargs): """Helper function to check stdout/stderr produced via print_msg.""" - self.mock_stdout(True, force_tty=True) - self.mock_stderr(True, force_tty=True) - print_msg(msg, *args, **kwargs) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(force_tty=True): + print_msg(msg, *args, **kwargs) + stdout = self.get_stdout() + stderr = self.get_stderr() # Check that the expected output stdout/stderr is being colorized # In order to allow using more styles/schemes (or even to account to changes in the rich default) # We only check for \x1b[0m which is the ANSI reset code that should be present in the output to undo @@ -386,13 +374,10 @@ def test_dry_run_msg(self): """Test dry_run_msg""" def run_check(msg, args, expected_stdout='', **kwargs): """Helper function to check stdout/stderr produced via dry_run_msg.""" - self.mock_stdout(True) - self.mock_stderr(True) - dry_run_msg(msg, *args, **kwargs) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + dry_run_msg(msg, *args, **kwargs) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(stdout, expected_stdout) self.assertEqual(stderr, '') @@ -407,13 +392,10 @@ def test_dry_run_warning(self): """Test dry_run_warningmsg""" def run_check(msg, args, expected_stdout='', **kwargs): """Helper function to check stdout/stderr produced via dry_run_warningmsg.""" - self.mock_stdout(True) - self.mock_stderr(True) - dry_run_warning(msg, *args, **kwargs) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + dry_run_warning(msg, *args, **kwargs) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(stdout, expected_stdout) self.assertEqual(stderr, '') @@ -458,10 +440,9 @@ def test_init_logging(self): stop_logging(logfile) # by default, path to tmp log file is printed - self.mock_stdout(True) - log, logfile = init_logging(None) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + log, logfile = init_logging(None) + stdout = self.get_stdout() self.assertExists(logfile) self.assertEqual(os.path.dirname(logfile), tmpdir) self.assertIsInstance(log, EasyBuildLog) @@ -470,9 +451,8 @@ def test_init_logging(self): stop_logging(logfile) # logging to stdout implies no log file - self.mock_stdout(True) - log, logfile = init_logging(None, logtostdout=True) - self.mock_stdout(False) + with self.mocked_stdout(): + log, logfile = init_logging(None, logtostdout=True) self.assertEqual(logfile, None) self.assertIsInstance(log, EasyBuildLog) diff --git a/test/framework/containers.py b/test/framework/containers.py index 5684b55717..93fc04548c 100644 --- a/test/framework/containers.py +++ b/test/framework/containers.py @@ -74,13 +74,10 @@ class ContainersTest(EnhancedTestCase): def run_main(self, args, raise_error=True): """Helper function to run main with arguments specified in 'args' and return stdout/stderr.""" - self.mock_stdout(True) - self.mock_stderr(True) - self.eb_main(args, raise_error=raise_error, verbose=True, do_build=True) - stdout = self.get_stdout().strip() - stderr = self.get_stderr().strip() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + self.eb_main(args, raise_error=raise_error, verbose=True, do_build=True) + stdout = self.get_stdout().strip() + stderr = self.get_stderr().strip() return stdout, stderr @@ -337,9 +334,8 @@ def test_end2end_singularity_image(self): # test again with container image already existing error_pattern = "Container image already exists at %s, not overwriting it without --force" % cont_img - self.mock_stdout(True) - self.assertErrorRegex(EasyBuildError, error_pattern, self.run_main, args, raise_error=True) - self.mock_stdout(False) + with self.mocked_stdout(): + self.assertErrorRegex(EasyBuildError, error_pattern, self.run_main, args, raise_error=True) args.append('--force') stdout, stderr = self.run_main(args) @@ -397,11 +393,12 @@ def test_end2end_dockerfile(self): error_pattern = "Container recipe at %s/containers/Dockerfile.toy-0.0 already exists, " \ "not overwriting it without --force" % self.test_prefix - self.assertErrorRegex(EasyBuildError, - error_pattern, - self.run_main, - base_args + ['--container-config=centos:7'], - raise_error=True) + with self.mocked_stdout(): + self.assertErrorRegex(EasyBuildError, + error_pattern, + self.run_main, + base_args + ['--container-config=centos:7'], + raise_error=True) remove_file(os.path.join(self.test_prefix, 'containers', 'Dockerfile.toy-0.0')) diff --git a/test/framework/docs.py b/test/framework/docs.py index ac72860515..b24138074e 100644 --- a/test/framework/docs.py +++ b/test/framework/docs.py @@ -1349,13 +1349,10 @@ def test_help(self): Test output produced by --help, with various output formats """ def get_eb_help_output(arg=''): - self.mock_stderr(True) - self.mock_stdout(True) - self.eb_main(['--help', arg]) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.eb_main(['--help', arg]) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertFalse(stderr) return stdout diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index 84a4db9722..744621d183 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -193,12 +193,9 @@ def test_load_module(self): # $TMPDIR is not touched yet at this point self.assertEqual(os.environ.get('TMPDIR'), orig_tmpdir) - self.mock_stderr(True) - self.mock_stdout(True) - eb.prepare_step(start_dir=False) - stderr = self.get_stderr() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + eb.prepare_step(start_dir=False) + stderr = self.get_stderr() self.assertTrue(stderr.strip().startswith("WARNING: Long $TMPDIR path may cause problems with OpenMPI 2.x")) # we expect $TMPDIR to be tweaked by the prepare step (OpenMPI 2.x doesn't like long $TMPDIR values) @@ -1223,10 +1220,10 @@ def test_handle_iterate_opts(self): expected_iter_opts['configopts'] = ["--opt1 --anotheropt", "--opt2", "--opt3 --optbis"] # once iteration mode is set, we're still in iteration #0 - self.mock_stdout(True) - eb.handle_iterate_opts() - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + eb.handle_iterate_opts() + stdout = self.get_stdout() + self.assertEqual(eb.iter_idx, 0) self.assertEqual(stdout, "== starting iteration 1/3 ...\n") self.assertEqual(eb.cfg.iterating, True) @@ -1237,10 +1234,10 @@ def test_handle_iterate_opts(self): self.assertEqual(eb.iter_opts, expected_iter_opts) # when next iteration is start, iteration index gets bumped - self.mock_stdout(True) - eb.handle_iterate_opts() - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + eb.handle_iterate_opts() + stdout = self.get_stdout() + self.assertEqual(eb.iter_idx, 1) self.assertEqual(stdout, "== starting iteration 2/3 ...\n") self.assertEqual(eb.cfg.iterating, True) @@ -1250,10 +1247,10 @@ def test_handle_iterate_opts(self): self.assertEqual(eb.cfg['configopts'], "--opt2") self.assertEqual(eb.iter_opts, expected_iter_opts) - self.mock_stdout(True) - eb.handle_iterate_opts() - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + eb.handle_iterate_opts() + stdout = self.get_stdout() + self.assertEqual(eb.iter_idx, 2) self.assertEqual(stdout, "== starting iteration 3/3 ...\n") self.assertEqual(eb.cfg.iterating, True) @@ -1566,10 +1563,9 @@ def test_extension_fake_modules(self): eb.installdir = config.install_path() update_build_option('trace', True) - self.mock_stdout(True) - eb.extensions_step(fetch=True) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + eb.extensions_step(fetch=True) + stdout = self.get_stdout() pattern = r">> running shell command:\n\s+bar.sh(\n\s+\[.*\]){3}\n\s+>> command completed: exit 0" self.assertRegex(stdout, re.compile(pattern, re.M)) @@ -2042,11 +2038,9 @@ def test_download_instructions(self): eb = EasyBlock(EasyConfig(self.eb_file)) error_pattern = common_error_pattern + ", please follow the download instructions above" - self.mock_stderr(True) - self.mock_stdout(True) - self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) - stderr = self.get_stderr().strip() - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) + stderr = self.get_stderr().strip() self.assertIn("Download instructions:\n\n Manual download from example.com required", stderr) self.assertIn("Make the files available in the active source path", stderr) @@ -2056,12 +2050,10 @@ def test_download_instructions(self): # now downloading of sources for extension should fail # top-level download instructions are printed (because there's nothing else) error_pattern = "^Couldn't find file ext_with_missing_sources-0.0.tar.gz anywhere" - self.mock_stderr(True) - self.mock_stdout(True) - self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) - stderr = self.get_stderr().strip() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) + stderr = self.get_stderr().strip() + self.assertIn("Download instructions:\n\n Manual download from example.com required", stderr) self.assertIn("Make the files available in the active source path", stderr) @@ -2071,12 +2063,9 @@ def test_download_instructions(self): eb = EasyBlock(EasyConfig(self.eb_file)) # no download instructions printed anymore now - self.mock_stderr(True) - self.mock_stdout(True) - self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) - stderr = self.get_stderr().strip() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) + stderr = self.get_stderr().strip() # inject download instructions for extension download_instructions = ' ' * 8 + "'download_instructions': " @@ -2086,12 +2075,10 @@ def test_download_instructions(self): self.writeEC() eb = EasyBlock(EasyConfig(self.eb_file)) - self.mock_stderr(True) - self.mock_stdout(True) - self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) - stderr = self.get_stderr().strip() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) + stderr = self.get_stderr().strip() + self.assertIn("Download instructions:\n\n Extension sources must be downloaded via example.com", stderr) self.assertIn("Make the files available in the active source path", stderr) @@ -2100,12 +2087,10 @@ def test_download_instructions(self): self.writeEC() eb = EasyBlock(EasyConfig(self.eb_file)) - self.mock_stderr(True) - self.mock_stdout(True) - self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) - stderr = self.get_stderr().strip() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step) + stderr = self.get_stderr().strip() + self.assertIn("Download instructions:\n\n Extension sources must be downloaded via example.com", stderr) self.assertIn("Make the files available in the active source path", stderr) @@ -2113,12 +2098,10 @@ def test_download_instructions(self): write_file(os.path.join(os.path.dirname(self.eb_file), 'ext_with_missing_sources-0.0.tar.gz'), '') # no more errors, all source files found (so no download instructions printed either) - self.mock_stderr(True) - self.mock_stdout(True) - eb.fetch_step() - stderr = self.get_stderr().strip() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + eb.fetch_step() + stderr = self.get_stderr().strip() + self.assertEqual(stderr, '') def test_fetch_patches(self): @@ -2242,12 +2225,10 @@ def test_obtain_file(self): remove_file(os.path.join(tmpdir, 'a', 'alt_toy', toy_tarball)) # enabling force_download results in re-downloading, even if file is already in sourcepath - self.mock_stderr(True) - self.mock_stdout(True) - res = eb.obtain_file(toy_tarball, urls=['file://%s' % tmpdir_subdir], force_download=True) - stderr = self.get_stderr() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + res = eb.obtain_file(toy_tarball, urls=['file://%s' % tmpdir_subdir], force_download=True) + stderr = self.get_stderr() + msg = "WARNING: Found file toy-0.0.tar.gz at %s, but re-downloading it anyway..." % toy_tarball_path self.assertEqual(stderr.strip(), msg) @@ -3281,23 +3262,19 @@ def test_checksum_step(self): } init_config(build_options=build_options) - self.mock_stderr(True) - self.mock_stdout(True) - eb.checksum_step() - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + eb.checksum_step() + stderr = self.get_stderr() + stdout = self.get_stdout() + self.assertEqual(stdout, '') self.assertEqual(stderr.strip(), "WARNING: Ignoring failing checksum verification for toy-0.0.tar.gz") - self.mock_stderr(True) - self.mock_stdout(True) - eb.collect_exts_file_info() - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + eb.collect_exts_file_info() + stderr = self.get_stderr() + stdout = self.get_stdout() + self.assertEqual(stdout, '') self.assertEqual(stderr.strip(), "WARNING: Ignoring failing checksum verification for bar-0.0.tar.gz\n\n\n" "WARNING: Ignoring failing checksum verification for toy-0.0.tar.gz") @@ -3554,14 +3531,12 @@ def test_sanity_check_paths_verification(self): def run_sanity_check_step(sanity_check_paths, enhance_sanity_check): """Helper function to run sanity check step, and do trivial check on generated output.""" - self.mock_stderr(True) - self.mock_stdout(True) - eb.cfg['sanity_check_paths'] = sanity_check_paths - eb.cfg['enhance_sanity_check'] = enhance_sanity_check - eb.sanity_check_step() - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + eb.cfg['sanity_check_paths'] = sanity_check_paths + eb.cfg['enhance_sanity_check'] = enhance_sanity_check + eb.sanity_check_step() + stderr, stdout = self.get_stderr(), self.get_stdout() + self.assertFalse(stderr) self.assertTrue(stdout.startswith("Sanity check paths")) diff --git a/test/framework/easyconfig.py b/test/framework/easyconfig.py index b3e7ed0982..69627b9390 100644 --- a/test/framework/easyconfig.py +++ b/test/framework/easyconfig.py @@ -1667,7 +1667,7 @@ def test_template_deprecation_and_alternative(self): with self.mocked_stdout_stderr() as (_, stderr): res = resolve_template(tmpl_str, tmpl_dict) - stderr = stderr.getvalue() + stderr = stderr.getvalue() for tmpl in [*template_test_deprecations.keys(), *template_test_alternatives.keys()]: self.assertNotIn("%(" + tmpl + ")s", res) @@ -4111,11 +4111,9 @@ def test_get_paths_for(self): symlink(test_ecs, os.path.join(self.test_prefix, 'easybuild', 'easyconfigs')) # temporarily mock stderr to avoid printed warning (because 'eb' is not available via $PATH) - self.mock_stderr(True) - - # locations listed in 'robot_path' named argument are taken into account - res = get_paths_for(subdir='easyconfigs', robot_path=[self.test_prefix]) - self.mock_stderr(False) + with self.mocked_stderr(): + # locations listed in 'robot_path' named argument are taken into account + res = get_paths_for(subdir='easyconfigs', robot_path=[self.test_prefix]) self.assertTrue(os.path.samefile(test_ecs, res[0])) # Can't have EB_SCRIPT_PATH set (for some of) these tests @@ -4593,12 +4591,10 @@ def test_fix_deprecated_easyconfigs(self): write_file(test_ec, test_ectxt) self.assertErrorRegex(EasyBuildError, unknown_params_error_pattern, EasyConfig, test_ec) - self.mock_stderr(True) - self.mock_stdout(True) - fix_deprecated_easyconfigs([test_ec]) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + fix_deprecated_easyconfigs([test_ec]) + stderr, stdout = self.get_stderr(), self.get_stdout() + self.assertFalse(stderr) self.assertIn("test.eb... FIXED!", stdout) @@ -5363,10 +5359,9 @@ def test_easyconfigs_caches(self): # also check whether easyconfigs cache works with end-to-end test args = [libtoy_ec, '--trace'] - self.mock_stdout(True) - self.eb_main(args, do_build=True, testing=False, raise_error=True, clear_caches=False) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + self.eb_main(args, do_build=True, testing=False, raise_error=True, clear_caches=False) + stdout = self.get_stdout() regex = re.compile(r"generating module file @ .*/modules/all/libtoy/0.0", re.M) self.assertTrue(regex.search(stdout), "Pattern '%s' should be found in: %s" % (regex.pattern, stdout)) @@ -5375,10 +5370,9 @@ def test_easyconfigs_caches(self): write_file(libtoy_ec, '') # retrying installation of libtoy easyconfig should not fail, thanks to easyconfigs cache - self.mock_stdout(True) - self.eb_main(args, do_build=True, testing=False, raise_error=True, clear_caches=False) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + self.eb_main(args, do_build=True, testing=False, raise_error=True, clear_caches=False) + stdout = self.get_stdout() regex = re.compile(r"libtoy/0\.0 is already installed", re.M) self.assertTrue(regex.search(stdout), "Pattern '%s' should be found in: %s" % (regex.pattern, stdout)) @@ -5416,9 +5410,9 @@ def test_templates(self): with self.mocked_stdout_stderr() as (stdout, stderr): self.assertEqual(ec['description'], "name: %(name)s, version: %(version)s, pyshortver: %(pyshortver)s") - self.assertFalse(stdout.getvalue()) - regex = re.compile(r"WARNING: Failed to resolve all templates.* %\(pyshortver\)s", re.M) - self.assertRegex(stderr.getvalue(), regex) + self.assertFalse(stdout.getvalue()) + regex = re.compile(r"WARNING: Failed to resolve all templates.* %\(pyshortver\)s", re.M) + self.assertRegex(stderr.getvalue(), regex) def suite(loader=None): diff --git a/test/framework/easystack.py b/test/framework/easystack.py index 5aa4d58d58..923c3f1fb4 100644 --- a/test/framework/easystack.py +++ b/test/framework/easystack.py @@ -155,10 +155,9 @@ def test_easystack_restore_env_after_each_build(self): '--easystack', test_es_path ] - self.mock_stdout(True) - stdout = self.eb_main(args, do_build=True, raise_error=True) - stdout = self.eb_main(args, do_build=True, raise_error=True, reset_env=False, redo_init_config=False) - self.mock_stdout(False) + with self.mocked_stdout(): + stdout = self.eb_main(args, do_build=True, raise_error=True) + stdout = self.eb_main(args, do_build=True, raise_error=True, reset_env=False, redo_init_config=False) regex = re.compile(r"WARNING Loaded modules detected: \[.*gompi/2018.*\]\n") self.assertFalse(regex.search(stdout), "Pattern '%s' should not be found in: %s" % (regex.pattern, stdout)) diff --git a/test/framework/environment.py b/test/framework/environment.py index 64467a9d3b..f015b61657 100644 --- a/test/framework/environment.py +++ b/test/framework/environment.py @@ -40,10 +40,9 @@ class EnvironmentTest(EnhancedTestCase): def test_setvar(self): """Test setvar function.""" - self.mock_stdout(True) - env.setvar('FOO', 'bar') - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + env.setvar('FOO', 'bar') + txt = self.get_stdout() self.assertEqual(os.getenv('FOO'), 'bar') self.assertEqual(os.environ['FOO'], 'bar') # no printing if dry run is not enabled @@ -54,19 +53,17 @@ def test_setvar(self): 'silent': False, } init_config(build_options=build_options) - self.mock_stdout(True) - env.setvar('FOO', 'foobaz') - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + env.setvar('FOO', 'foobaz') + txt = self.get_stdout() self.assertEqual(os.getenv('FOO'), 'foobaz') self.assertEqual(os.environ['FOO'], 'foobaz') self.assertEqual(txt, " export FOO='foobaz'\n") # disabling verbose - self.mock_stdout(True) - env.setvar('FOO', 'barfoo', verbose=False) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + env.setvar('FOO', 'barfoo', verbose=False) + txt = self.get_stdout() self.assertEqual(os.getenv('FOO'), 'barfoo') self.assertEqual(os.environ['FOO'], 'barfoo') self.assertEqual(txt, '') diff --git a/test/framework/filetools.py b/test/framework/filetools.py index 5da4f55cc9..2e4e326fa9 100644 --- a/test/framework/filetools.py +++ b/test/framework/filetools.py @@ -642,10 +642,9 @@ def test_download_file(self): if os.path.exists(target_location): shutil.rmtree(target_location) - self.mock_stdout(True) - path = ft.download_file(fn, source_url, target_location) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + path = ft.download_file(fn, source_url, target_location) + txt = self.get_stdout() self.assertEqual(path, target_location) self.assertNotExists(target_location) @@ -729,12 +728,9 @@ def fake_urllib_open(url, *args, **kwargs): self.assertEqual(res, None) update_build_option('insecure_download', True) - self.mock_stdout(True) - self.mock_stderr(True) - res = ft.download_file(fn, url, target_path) - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + res = ft.download_file(fn, url, target_path) + stderr = self.get_stderr() self.assertIn("WARNING: Not checking server certificates while downloading toy-0.0.eb", stderr) self.assertExists(res) @@ -770,12 +766,9 @@ def fake_requests_get(url, *args, **kwargs): self.assertEqual(res, None) update_build_option('insecure_download', True) - self.mock_stderr(True) - self.mock_stdout(True) - res = ft.download_file(fn, url, target_path) - stderr = self.get_stderr() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + res = ft.download_file(fn, url, target_path) + stderr = self.get_stderr() self.assertIn("WARNING: Not checking server certificates while downloading README.rst", stderr) self.assertExists(res) @@ -975,10 +968,9 @@ def test_read_write_file(self): self.assertEqual(ft.read_file(backup2), 'foo') # tese use of 'verbose' to make write_file print location of backed up file - self.mock_stdout(True) - ft.write_file(fp, 'foo', backup=True, verbose=True) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.write_file(fp, 'foo', backup=True, verbose=True) + stdout = self.get_stdout() regex = re.compile("^== Backup of .*/test.txt created at .*/test.txt.bak_[0-9]*") self.assertTrue(regex.search(stdout), "Pattern '%s' found in: %s" % (regex.pattern, stdout)) @@ -1011,10 +1003,9 @@ def test_read_write_file(self): foo = os.path.join(self.test_prefix, 'foo.txt') - self.mock_stdout(True) - ft.write_file(foo, 'bar') - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.write_file(foo, 'bar') + txt = self.get_stdout() self.assertNotExists(foo) self.assertTrue(re.match("^file written: .*/foo.txt$", txt)) @@ -2038,19 +2029,17 @@ def test_copy_file(self): # make sure target file is not there, it shouldn't get copied under dry run self.assertNotExists(target_path) - self.mock_stdout(True) - ft.copy_file(toy_ec, target_path) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.copy_file(toy_ec, target_path) + txt = self.get_stdout() self.assertNotExists(target_path) self.assertTrue(re.search("^copied file .*/toy-0.0.eb to .*/toy.eb", txt)) # forced copy, even in dry run mode - self.mock_stdout(True) - ft.copy_file(toy_ec, target_path, force_in_dry_run=True) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.copy_file(toy_ec, target_path, force_in_dry_run=True) + txt = self.get_stdout() self.assertExists(target_path) self.assertTrue(ft.read_file(toy_ec) == ft.read_file(target_path)) @@ -2062,10 +2051,9 @@ def test_copy_file(self): self.assertErrorRegex(EasyBuildError, "Could not copy *", ft.copy_file, src, target) # Test that copying a non-existing file in 'dry_run' mode does noting update_build_option('extended_dry_run', True) - self.mock_stdout(True) - ft.copy_file(src, target, force_in_dry_run=False) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.copy_file(src, target, force_in_dry_run=False) + txt = self.get_stdout() self.assertTrue(re.search("^copied file %s to %s" % (src, target), txt)) # However, if we add 'force_in_dry_run=True' it should throw an exception self.assertErrorRegex(EasyBuildError, "Could not copy *", ft.copy_file, src, target, force_in_dry_run=True) @@ -2187,24 +2175,18 @@ def test_copy_files(self): ft.remove_dir(target) # test enabling verbose mode - self.mock_stderr(True) - self.mock_stdout(True) - ft.copy_files([toy_ec], target, verbose=True) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + ft.copy_files([toy_ec], target, verbose=True) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') regex = re.compile(r"^1 file\(s\) copied to .*/target") self.assertTrue(regex.match(stdout), "Pattern '%s' should be found in: %s" % (regex.pattern, stdout)) ft.remove_dir(target) - self.mock_stderr(True) - self.mock_stdout(True) - ft.copy_files([toy_ec], target, target_single_file=True, verbose=True) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + ft.copy_files([toy_ec], target, target_single_file=True, verbose=True) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') regex = re.compile(r"/.*/toy-0\.0\.eb copied to .*/target") self.assertTrue(regex.match(stdout), "Pattern '%s' should be found in: %s" % (regex.pattern, stdout)) @@ -2215,12 +2197,9 @@ def test_copy_files(self): init_config(build_options={'extended_dry_run': True}) self.assertNotExists(os.path.join(target, 'test.eb')) - self.mock_stderr(True) - self.mock_stdout(True) - ft.copy_files(['test.eb'], target) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + ft.copy_files(['test.eb'], target) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertNotExists(os.path.join(target, 'test.eb')) self.assertEqual(stderr, '') @@ -2228,12 +2207,9 @@ def test_copy_files(self): regex = re.compile("^copied test.eb to .*/target") self.assertTrue(regex.match(stdout), "Pattern '%s' should be found in: %s" % (regex.pattern, stdout)) - self.mock_stderr(True) - self.mock_stdout(True) - ft.copy_files(['bar.eb', 'foo.eb'], target) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + ft.copy_files(['bar.eb', 'foo.eb'], target) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertNotExists(os.path.join(target, 'bar.eb')) self.assertNotExists(os.path.join(target, 'foo.eb')) @@ -2373,19 +2349,17 @@ def ignore_func(_, names): self.assertNotExists(target_dir) # no actual copying in dry run mode, unless forced - self.mock_stdout(True) - ft.copy_dir(to_copy, target_dir) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.copy_dir(to_copy, target_dir) + txt = self.get_stdout() self.assertNotExists(target_dir) self.assertTrue(re.search("^copied directory .*/GCC to .*/%s" % os.path.basename(target_dir), txt)) # forced copy, even in dry run mode - self.mock_stdout(True) - ft.copy_dir(to_copy, target_dir, force_in_dry_run=True) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.copy_dir(to_copy, target_dir, force_in_dry_run=True) + txt = self.get_stdout() self.assertExists(target_dir) self.assertTrue(sorted(os.listdir(to_copy)) == sorted(os.listdir(target_dir))) @@ -2418,11 +2392,10 @@ def test_copy(self): init_config(build_options=build_options) # no actual copying in dry run mode, unless forced - self.mock_stdout(True) - to_copy = [os.path.dirname(toy_file), os.path.join(gcc_dir, 'GCC-4.6.3.eb')] - ft.copy(to_copy, self.test_prefix) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + to_copy = [os.path.dirname(toy_file), os.path.join(gcc_dir, 'GCC-4.6.3.eb')] + ft.copy(to_copy, self.test_prefix) + txt = self.get_stdout() self.assertNotExists(os.path.join(self.test_prefix, 'toy')) self.assertNotExists(os.path.join(self.test_prefix, 'GCC-4.6.3.eb')) @@ -2430,10 +2403,9 @@ def test_copy(self): self.assertTrue(re.search("^copied file .*/GCC-4.6.3.eb to .*/GCC-4.6.3.eb", txt, re.M)) # forced copy, even in dry run mode - self.mock_stdout(True) - ft.copy(to_copy, self.test_prefix, force_in_dry_run=True) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.copy(to_copy, self.test_prefix, force_in_dry_run=True) + txt = self.get_stdout() self.assertTrue(os.path.isdir(os.path.join(self.test_prefix, 'toy'))) self.assertTrue(os.path.isfile(os.path.join(self.test_prefix, 'toy', 'toy-0.0.eb'))) @@ -2512,10 +2484,10 @@ def test_extract_file(self): } init_config(build_options=build_options) - self.mock_stdout(True) - path = ft.extract_file(toy_tarball, self.test_prefix, change_into_dir=False) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + path = ft.extract_file(toy_tarball, self.test_prefix, change_into_dir=False) + txt = self.get_stdout() + self.assertTrue(os.path.samefile(os.getcwd(), cwd)) self.assertTrue(os.path.samefile(path, self.test_prefix)) @@ -2580,11 +2552,10 @@ def test_empty_dir(self): } init_config(build_options=build_options) - self.mock_stdout(True) - ft.mkdir(test_dir) - ft.empty_dir(test_dir) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ft.mkdir(test_dir) + ft.empty_dir(test_dir) + txt = self.get_stdout() regex = re.compile("^directory [^ ]* emptied$") self.assertTrue(regex.match(txt), f"Pattern '{regex.pattern}' found in: {txt}") @@ -2646,19 +2617,17 @@ def test_remove(self): init_config(build_options=build_options) for remove_file_function in (ft.remove_file, ft.remove): - self.mock_stdout(True) - remove_file_function(testfile) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + remove_file_function(testfile) + txt = self.get_stdout() regex = re.compile("^file [^ ]* removed$") self.assertTrue(regex.match(txt), "Pattern '%s' found in: %s" % (regex.pattern, txt)) for remove_dir_function in (ft.remove_dir, ft.remove): - self.mock_stdout(True) - remove_dir_function(test_dir) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + remove_dir_function(test_dir) + txt = self.get_stdout() regex = re.compile("^directory [^ ]* removed$") self.assertTrue(regex.match(txt), "Pattern '%s' found in: %s" % (regex.pattern, txt)) @@ -2743,13 +2712,10 @@ def test_index_functions(self): self.assertTrue(regex.search(index_txt), "Pattern '%s' found in: %s" % (regex.pattern, index_txt)) # test load_index function - self.mock_stderr(True) - self.mock_stdout(True) - index = ft.load_index(ecs_dir) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + index = ft.load_index(ecs_dir) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertFalse(stderr) regex = re.compile(r"^== found valid index for %s, so using it\.\.\.$" % ecs_dir) @@ -2773,13 +2739,10 @@ def test_index_functions(self): regex = re.compile('^%s$' % fn, re.M) self.assertTrue(regex.search(index_txt), "Pattern '%s' found in: %s" % (regex.pattern, index_txt)) - self.mock_stderr(True) - self.mock_stdout(True) - index = ft.load_index(ecs_dir) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + index = ft.load_index(ecs_dir) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertFalse(stderr) regex = re.compile(r"^== found valid index for %s, so using it\.\.\.$" % ecs_dir) @@ -2794,13 +2757,10 @@ def test_index_functions(self): # test creating index file that's only valid for a (very) short amount of time index_fp = ft.dump_index(ecs_dir, max_age_sec=1) time.sleep(3) - self.mock_stderr(True) - self.mock_stdout(True) - index = ft.load_index(ecs_dir) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + index = ft.load_index(ecs_dir) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertIsNone(index) self.assertFalse(stdout) regex = re.compile(r"WARNING: Index for %s is no longer valid \(too old\), so ignoring it" % ecs_dir) @@ -2989,13 +2949,10 @@ def test_move_file(self): } init_config(build_options=build_options) - self.mock_stdout(True) - self.mock_stderr(True) - ft.move_file(test_file, new_test_file) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + ft.move_file(test_file, new_test_file) + stdout = self.get_stdout() + stderr = self.get_stderr() # informative message printed, but file was not actually moved regex = re.compile(r"^moved file .*/test\.txt to .*/new_test\.txt$") @@ -3418,12 +3375,9 @@ def test_make_archive(self): os.remove(unreprod_tar) # custom .tar.gz - self.mock_stdout(True) - self.mock_stderr(True) - custom_tgz = ft.make_archive(tardir, archive_file="custom_name.tar.gz", reproducible=True) - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + custom_tgz = ft.make_archive(tardir, archive_file="custom_name.tar.gz", reproducible=True) + stderr = self.get_stderr() warning_msg = "WARNING: Can not create reproducible archive due to unsupported file compression (gz)" self.assertIn(warning_msg, stderr) @@ -3432,12 +3386,9 @@ def test_make_archive(self): self.assertEqual(custom_tgz, "custom_name.tar.gz") self.assertExists(custom_tgz) os.remove(custom_tgz) - self.mock_stdout(True) - self.mock_stderr(True) - custom_tgz = ft.make_archive(tardir, archive_file="custom_name.tar.gz", reproducible=False) - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + custom_tgz = ft.make_archive(tardir, archive_file="custom_name.tar.gz", reproducible=False) + stderr = self.get_stderr() self.assertNotIn(warning_msg, stderr) @@ -3483,18 +3434,15 @@ def test_fake_vsc(self): ft.install_fake_vsc() - self.mock_stderr(True) - self.mock_stdout(True) - try: - import vsc # noqa - self.fail("'import vsc' results in an error") - except SystemExit: - pass + with self.mocked_stdout_stderr(): + try: + import vsc # noqa + self.fail("'import vsc' results in an error") + except SystemExit: + pass - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertEqual(stdout, '') @@ -3509,17 +3457,14 @@ def test_fake_vsc(self): sys.path.insert(0, self.test_prefix) - self.mock_stderr(True) - self.mock_stdout(True) - try: - from test_fake_vsc import import_vsc # noqa - self.fail("'import vsc' results in an error") - except SystemExit: - pass - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + try: + from test_fake_vsc import import_vsc # noqa + self.fail("'import vsc' results in an error") + except SystemExit: + pass + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertEqual(stdout, '') error_pattern = r"Detected import from 'vsc' namespace in .*/test_fake_vsc/import_vsc.py \(line 1\)" diff --git a/test/framework/github.py b/test/framework/github.py index 3c0337a73a..a338010471 100644 --- a/test/framework/github.py +++ b/test/framework/github.py @@ -253,28 +253,21 @@ def test_github_add_pr_labels(self): } init_config(build_options=build_options) - self.mock_stdout(True) - error_pattern = "Adding labels to PRs for repositories other than easyconfigs hasn't been implemented yet" - self.assertErrorRegex(EasyBuildError, error_pattern, gh.add_pr_labels, 1) - self.mock_stdout(False) + with self.mocked_stdout(): + error_pattern = "Adding labels to PRs for repositories other than easyconfigs hasn't been implemented yet" + self.assertErrorRegex(EasyBuildError, error_pattern, gh.add_pr_labels, 1) build_options['pr_target_repo'] = GITHUB_EASYCONFIGS_REPO init_config(build_options=build_options) - self.mock_stdout(True) - self.mock_stderr(True) - gh.add_pr_labels(21465) - stdout = self.get_stdout() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + gh.add_pr_labels(21465) + stdout = self.get_stdout() self.assertIn("Could not determine any missing labels for PR #21465", stdout) - self.mock_stdout(True) - self.mock_stderr(True) - gh.add_pr_labels(22088) # closed, unmerged, unlabeled PR - stdout = self.get_stdout() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + gh.add_pr_labels(22088) # closed, unmerged, unlabeled PR + stdout = self.get_stdout() self.assertIn("Could not determine any missing labels for PR #22088", stdout) def test_github_fetch_pr_data(self): @@ -312,10 +305,9 @@ def test_github_list_prs(self): expected = "PR #1: a pr" - self.mock_stdout(True) - output = gh.list_prs(parameters, per_page=1, github_user=GITHUB_TEST_ACCOUNT) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + output = gh.list_prs(parameters, per_page=1, github_user=GITHUB_TEST_ACCOUNT) + stdout = self.get_stdout() self.assertTrue(stdout.startswith("== Listing PRs with parameters: ")) @@ -341,14 +333,11 @@ def test_github_reasons_for_closing(self): pr_data, _ = gh.fetch_pr_data(16080, repo_owner, repo_name, GITHUB_TEST_ACCOUNT, full=True) - self.mock_stdout(True) - self.mock_stderr(True) - # can't easily check return value, since auto-detected reasons may change over time if PR is touched - res = gh.reasons_for_closing(pr_data) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + # can't easily check return value, since auto-detected reasons may change over time if PR is touched + res = gh.reasons_for_closing(pr_data) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertIsInstance(res, list) self.assertEqual(stderr.strip(), "WARNING: Using easyconfigs from closed PR #16080") @@ -374,10 +363,9 @@ def test_github_close_pr(self): } init_config(build_options=build_options) - self.mock_stdout(True) - gh.close_pr(2, motivation_msg='just a test') - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + gh.close_pr(2, motivation_msg='just a test') + stdout = self.get_stdout() patterns = [ "easybuilders/testrepository PR #2 was submitted by migueldiascosta", @@ -390,10 +378,9 @@ def test_github_close_pr(self): retest_msg = VALID_CLOSE_PR_REASONS['retest'] - self.mock_stdout(True) - gh.close_pr(2, motivation_msg=retest_msg) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + gh.close_pr(2, motivation_msg=retest_msg) + stdout = self.get_stdout() patterns = [ "easybuilders/testrepository PR #2 was submitted by migueldiascosta", @@ -607,10 +594,9 @@ def test_github_download_repo(self): return cwd = os.getcwd() - self.mock_stdout(True) - - # default: download tarball for master branch of easybuilders/easybuild-easyconfigs repo - path = gh.download_repo(path=self.test_prefix, github_user=GITHUB_TEST_ACCOUNT) + with self.mocked_stdout(): + # default: download tarball for master branch of easybuilders/easybuild-easyconfigs repo + path = gh.download_repo(path=self.test_prefix, github_user=GITHUB_TEST_ACCOUNT) repodir = os.path.join(self.test_prefix, 'easybuilders', 'easybuild-easyconfigs-main') self.assertTrue(os.path.samefile(path, repodir)) self.assertExists(repodir) @@ -642,7 +628,7 @@ def test_github_download_repo(self): self.assertIn('easybuild', os.listdir(repodir)) self.assertTrue(re.match('^[0-9a-f]{40}$', read_file(shafile))) self.assertExists(os.path.join(repodir, 'easybuild', 'easyblocks', '__init__.py')) - self.mock_stdout(False) + # stdout capture released by context manager above def test_github_download_repo_commit(self): """Test downloading repo at specific commit (which does not require any GitHub token)""" @@ -759,26 +745,23 @@ def test_github_find_patches(self): 'valid_module_classes': module_classes(), 'validate': False, }) - self.mock_stdout(True) - ec = gh.find_software_name_for_patch('toy-0.0_fix-silly-typo-in-printf-statement.patch', [ec_path]) - txt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + ec = gh.find_software_name_for_patch('toy-0.0_fix-silly-typo-in-printf-statement.patch', [ec_path]) + txt = self.get_stdout() self.assertEqual(ec, 'toy') reg = re.compile(r'[1-9]+ of [1-9]+ easyconfigs checked') self.assertTrue(re.search(reg, txt)) - self.mock_stdout(True) - self.assertEqual(gh.find_software_name_for_patch('test.patch', []), None) - self.mock_stdout(False) + with self.mocked_stdout(): + self.assertEqual(gh.find_software_name_for_patch('test.patch', []), None) non_utf8_patch = os.path.join(self.test_prefix, 'problem.patch') with open(non_utf8_patch, 'wb') as fp: fp.write(bytes("+ ximage->byte_order=T1_byte_order; /* Set t1lib\xb4s byteorder */\n", 'iso_8859_1')) - self.mock_stdout(True) - self.assertEqual(gh.find_software_name_for_patch('test.patch', [self.test_prefix]), None) - self.mock_stdout(False) + with self.mocked_stdout(): + self.assertEqual(gh.find_software_name_for_patch('test.patch', [self.test_prefix]), None) def test_github_det_commit_status(self): """Test det_commit_status function.""" @@ -835,13 +818,10 @@ def test_github_check_pr_eligible_to_merge(self): """Test check_pr_eligible_to_merge function""" def run_check(expected_result=False): """Helper function to check result of check_pr_eligible_to_merge""" - self.mock_stdout(True) - self.mock_stderr(True) - res = gh.check_pr_eligible_to_merge(pr_data) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + res = gh.check_pr_eligible_to_merge(pr_data) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(res, expected_result) self.assertEqual(stdout, expected_stdout) self.assertIn(expected_warning, stderr) @@ -1143,9 +1123,8 @@ def test_github_det_account_repo_branch_for_pr(self): }) # see https://github.com/easybuilders/easybuild-easyconfigs/pull/9149 - self.mock_stdout(True) - account, repo, branch = gh.det_account_repo_branch_for_pr(9149, github_user=GITHUB_TEST_ACCOUNT) - self.mock_stdout(False) + with self.mocked_stdout(): + account, repo, branch = gh.det_account_repo_branch_for_pr(9149, github_user=GITHUB_TEST_ACCOUNT) self.assertEqual(account, 'boegel') self.assertEqual(repo, 'easybuild-easyconfigs') self.assertEqual(branch, '20191017070734_new_pr_EasyBuild401') @@ -1156,9 +1135,8 @@ def test_github_det_account_repo_branch_for_pr(self): }) # see https://github.com/easybuilders/easybuild-framework/pull/3069 - self.mock_stdout(True) - account, repo, branch = gh.det_account_repo_branch_for_pr(3069, github_user=GITHUB_TEST_ACCOUNT) - self.mock_stdout(False) + with self.mocked_stdout(): + account, repo, branch = gh.det_account_repo_branch_for_pr(3069, github_user=GITHUB_TEST_ACCOUNT) self.assertEqual(account, 'migueldiascosta') self.assertEqual(repo, 'easybuild-framework') self.assertEqual(branch, 'fix_inject_checksums') @@ -1231,15 +1209,12 @@ def test_push_branch_to_github(self): git_repo = gh.init_repo(self.test_prefix, GITHUB_REPO) branch = 'test123' - self.mock_stderr(True) - self.mock_stdout(True) - gh.setup_repo(git_repo, GITHUB_USER, GITHUB_REPO, 'main') - git_repo.create_head(branch, force=True) - gh.push_branch_to_github(git_repo, GITHUB_USER, GITHUB_REPO, branch) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(True) - self.mock_stdout(True) + with self.mocked_stdout_stderr(): + gh.setup_repo(git_repo, GITHUB_USER, GITHUB_REPO, 'main') + git_repo.create_head(branch, force=True) + gh.push_branch_to_github(git_repo, GITHUB_USER, GITHUB_REPO, branch) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertEqual(stderr, '') @@ -1266,12 +1241,9 @@ def test_github_pr_test_report(self): init_session_state = session_state() - self.mock_stderr(True) - self.mock_stdout(True) - post_pr_test_report('1234', gh.GITHUB_EASYCONFIGS_REPO, test_report, "OK!", init_session_state, True) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + post_pr_test_report('1234', gh.GITHUB_EASYCONFIGS_REPO, test_report, "OK!", init_session_state, True) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') @@ -1283,12 +1255,9 @@ def test_github_pr_test_report(self): regex = re.compile(pattern, re.M) self.assertTrue(regex.search(stdout), "Pattern '%s' should be found in: %s" % (regex.pattern, stdout)) - self.mock_stderr(True) - self.mock_stdout(True) - post_pr_test_report('1234', gh.GITHUB_EASYBLOCKS_REPO, test_report, "OK!", init_session_state, True) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + post_pr_test_report('1234', gh.GITHUB_EASYBLOCKS_REPO, test_report, "OK!", init_session_state, True) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') @@ -1303,12 +1272,9 @@ def test_github_pr_test_report(self): # also test combination of --from-pr and --include-easyblocks-from-pr update_build_option('include_easyblocks_from_pr', ['6789']) - self.mock_stderr(True) - self.mock_stdout(True) - post_pr_test_report('1234', gh.GITHUB_EASYCONFIGS_REPO, test_report, "OK!", init_session_state, True) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + post_pr_test_report('1234', gh.GITHUB_EASYCONFIGS_REPO, test_report, "OK!", init_session_state, True) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') diff --git a/test/framework/hooks.py b/test/framework/hooks.py index 67ba87e4a1..20c03d6ebb 100644 --- a/test/framework/hooks.py +++ b/test/framework/hooks.py @@ -211,34 +211,32 @@ def __init__(self, *args, **kwargs): self.version = '1.2.3' def run_hooks(): - self.mock_stdout(True) - self.mock_stderr(True) - run_hook('start', hooks) - run_hook('parse', hooks, args=[''], msg="Running parse hook for example.eb...") - run_hook('build_and_install_loop', hooks, args=[['ec1', 'ec2']], pre_step_hook=True) - run_hook('easyblock', hooks, args=[FakeEasyBlock()], pre_step_hook=True) - run_hook('configure', hooks, pre_step_hook=True, args=[None]) - run_hook('run_shell_cmd', hooks, pre_step_hook=True, args=["configure.sh"], kwargs={'interactive': True}) - run_hook('configure', hooks, post_step_hook=True, args=[None]) - run_hook('build', hooks, pre_step_hook=True, args=[None]) - run_hook('run_shell_cmd', hooks, pre_step_hook=True, args=["make -j 3"]) - run_hook('build', hooks, post_step_hook=True, args=[None]) - run_hook('install', hooks, pre_step_hook=True, args=[None]) - res = run_hook('run_shell_cmd', hooks, pre_step_hook=True, args=["make install"], kwargs={}) - self.assertEqual(res, "sudo make install") - run_hook('install', hooks, post_step_hook=True, args=[None]) - run_hook('extensions', hooks, pre_step_hook=True, args=[None]) - for _ in range(3): - run_hook('single_extension', hooks, pre_step_hook=True, args=[None]) - run_hook('single_extension', hooks, post_step_hook=True, args=[None]) - run_hook('extensions', hooks, post_step_hook=True, args=[None]) - run_hook('fail', hooks, args=[EasyBuildError('oops')]) - run_hook('crash', hooks, args=[RuntimeError('boom!')]) - run_hook('easyblock', hooks, args=[FakeEasyBlock()], post_step_hook=True) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + run_hook('start', hooks) + run_hook('parse', hooks, args=[''], msg="Running parse hook for example.eb...") + run_hook('build_and_install_loop', hooks, args=[['ec1', 'ec2']], pre_step_hook=True) + run_hook('easyblock', hooks, args=[FakeEasyBlock()], pre_step_hook=True) + run_hook('configure', hooks, pre_step_hook=True, args=[None]) + run_hook('run_shell_cmd', hooks, pre_step_hook=True, args=["configure.sh"], + kwargs={'interactive': True}) + run_hook('configure', hooks, post_step_hook=True, args=[None]) + run_hook('build', hooks, pre_step_hook=True, args=[None]) + run_hook('run_shell_cmd', hooks, pre_step_hook=True, args=["make -j 3"]) + run_hook('build', hooks, post_step_hook=True, args=[None]) + run_hook('install', hooks, pre_step_hook=True, args=[None]) + res = run_hook('run_shell_cmd', hooks, pre_step_hook=True, args=["make install"], kwargs={}) + self.assertEqual(res, "sudo make install") + run_hook('install', hooks, post_step_hook=True, args=[None]) + run_hook('extensions', hooks, pre_step_hook=True, args=[None]) + for _ in range(3): + run_hook('single_extension', hooks, pre_step_hook=True, args=[None]) + run_hook('single_extension', hooks, post_step_hook=True, args=[None]) + run_hook('extensions', hooks, post_step_hook=True, args=[None]) + run_hook('fail', hooks, args=[EasyBuildError('oops')]) + run_hook('crash', hooks, args=[RuntimeError('boom!')]) + run_hook('easyblock', hooks, args=[FakeEasyBlock()], post_step_hook=True) + stdout = self.get_stdout() + stderr = self.get_stderr() return stdout, stderr diff --git a/test/framework/lib.py b/test/framework/lib.py index a0654bef65..176c14221f 100644 --- a/test/framework/lib.py +++ b/test/framework/lib.py @@ -95,11 +95,10 @@ def test_run_shell_cmd(self): self.configure() # runworks fine if set_up_configuration was called first - self.mock_stdout(True) - res = run_shell_cmd("echo hello") - self.mock_stdout(False) - self.assertEqual(res.exit_code, 0) - self.assertEqual(res.output, 'hello\n') + with self.mocked_stdout(): + res = run_shell_cmd("echo hello") + self.assertEqual(res.exit_code, 0) + self.assertEqual(res.output, 'hello\n') def test_mkdir(self): """Test use of mkdir function in the context of using EasyBuild framework as a library.""" diff --git a/test/framework/modules.py b/test/framework/modules.py index f3272cfa09..9e87dd45a7 100644 --- a/test/framework/modules.py +++ b/test/framework/modules.py @@ -1449,12 +1449,9 @@ def test_check_loaded_modules(self): def check_loaded_modules(): "Helper function to run check_loaded_modules and check on stdout/stderr." # there should be no errors/warnings by default if no (EasyBuild-generated) modules are loaded - self.mock_stdout(True) - self.mock_stderr(True) - self.modtool.check_loaded_modules() - stdout, stderr = self.get_stdout(), self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + self.modtool.check_loaded_modules() + stdout, stderr = self.get_stdout(), self.get_stderr() self.assertEqual(stdout, '') return stderr.strip() diff --git a/test/framework/output.py b/test/framework/output.py index ab87ca9cf2..0ee257ad44 100644 --- a/test/framework/output.py +++ b/test/framework/output.py @@ -161,13 +161,11 @@ def test_print_error(self): """ update_build_option('output_style', 'basic') msg = "This is yellow: " + colorize("a banana", color='yellow') - self.mock_stderr(True) - self.mock_stdout(True) - print_error(msg) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + print_error(msg) + stderr = self.get_stderr() + stdout = self.get_stdout() + self.assertEqual(stdout, '') expected = '\n\nThis is yellow: \x1b[1;33ma banana\x1b[0m\n\n' self.assertEqual(stderr, expected) @@ -182,13 +180,11 @@ def test_print_error_rich(self): self.skipTest("rich not available") update_build_option('output_style', 'rich') msg = "This is yellow: " + colorize("a banana", color='yellow') - self.mock_stderr(True) - self.mock_stdout(True) - print_error(msg) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + print_error(msg) + stderr = self.get_stderr() + stdout = self.get_stdout() + self.assertEqual(stdout, '') expected = '\n\nThis is yellow: a banana\n\n' self.assertEqual(stderr, expected) diff --git a/test/framework/parallelbuild.py b/test/framework/parallelbuild.py index cd1041beff..6971f93e2b 100644 --- a/test/framework/parallelbuild.py +++ b/test/framework/parallelbuild.py @@ -366,9 +366,8 @@ def test_build_easyconfigs_in_parallel_slurm(self): easyconfigs = process_easyconfig(test_ec) + process_easyconfig(foss_ec) ordered_ecs = resolve_dependencies(easyconfigs, self.modtool) - self.mock_stdout(True) - jobs = build_easyconfigs_in_parallel("echo '%(spec)s'", ordered_ecs, prepare_first=False) - self.mock_stdout(False) + with self.mocked_stdout(): + jobs = build_easyconfigs_in_parallel("echo '%(spec)s'", ordered_ecs, prepare_first=False) # jobs are submitted for foss & gzip (listed easyconfigs) self.assertEqual(len(jobs), 2) diff --git a/test/framework/robot.py b/test/framework/robot.py index 9f3815a468..2421ff44fc 100644 --- a/test/framework/robot.py +++ b/test/framework/robot.py @@ -703,10 +703,9 @@ def test_search_paths(self): '--search', 'toy', ] - self.mock_stdout(True) - self.eb_main(args, logfile=dummylogfn, raise_error=True) - outtxt = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + self.eb_main(args, logfile=dummylogfn, raise_error=True) + outtxt = self.get_stdout() # Make sure we found the copied file regex = re.compile(r"^ \* %s$" % os.path.join(self.test_prefix, test_ec), re.M) @@ -733,10 +732,9 @@ def test_github_det_easyconfig_paths_from_commit(self): '--tmpdir=%s' % self.test_prefix, ] - self.mock_stderr(True) - outtxt = self.eb_main(args, raise_error=True) - stderr = self.get_stderr() - self.mock_stderr(False) + with self.mocked_stderr(): + outtxt = self.eb_main(args, raise_error=True) + stderr = self.get_stderr() self.assertFalse(stderr) @@ -795,11 +793,8 @@ def test_github_det_easyconfig_paths_from_pr(self): '--tmpdir=%s' % self.test_prefix, ] - self.mock_stderr(True) - self.mock_stdout(True) - outtxt = self.eb_main(args, logfile=dummylogfn, raise_error=True) - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout(): + outtxt = self.eb_main(args, logfile=dummylogfn, raise_error=True) # full path doesn't matter (helps to avoid failing tests due to resolved symlinks) test_ecs_path = os.path.join('.*', 'test', 'framework', 'easyconfigs', 'test_ecs') @@ -1418,10 +1413,10 @@ def test_check_conflicts(self): non_conflict_ecs, _ = parse_easyconfigs([(gzip_ec, False), (gompi_ec, False)]) # no conflicts found, no output to stderr - self.mock_stderr(True) - conflicts = check_conflicts(non_conflict_ecs, self.modtool) - stderr = self.get_stderr() - self.mock_stderr(False) + with self.mocked_stderr(): + conflicts = check_conflicts(non_conflict_ecs, self.modtool) + stderr = self.get_stderr() + self.assertFalse(conflicts) self.assertEqual(stderr, '') @@ -1433,10 +1428,9 @@ def test_check_conflicts(self): ecs, _ = parse_easyconfigs([(new_gompi_ec, False), (gzip_ec, False)]) # conflicts are found and reported to stderr - self.mock_stderr(True) - conflicts = check_conflicts(ecs, self.modtool) - stderr = self.get_stderr() - self.mock_stderr(False) + with self.mocked_stderr(): + conflicts = check_conflicts(ecs, self.modtool) + stderr = self.get_stderr() self.assertTrue(conflicts) self.assertIn("Conflict found for dependencies of foss-2018a: GCC-4.6.4 vs GCC-6.4.0-2.28", stderr) @@ -1455,10 +1449,9 @@ def test_check_conflicts(self): (os.path.join(test_easyconfigs, 'g', 'GCC', 'GCC-6.4.0-2.28.eb'), False), (os.path.join(test_easyconfigs, 'g', 'GCC', 'GCC-4.9.3-2.25.eb'), False), ]) - self.mock_stderr(True) - conflicts = check_conflicts(ecs, self.modtool) - stderr = self.get_stderr() - self.mock_stderr(False) + with self.mocked_stderr(): + conflicts = check_conflicts(ecs, self.modtool) + stderr = self.get_stderr() self.assertTrue(conflicts) self.assertIn("Conflict between (dependencies of) easyconfigs: GCC-4.9.3-2.25 vs GCC-6.4.0-2.28", stderr) @@ -1468,10 +1461,9 @@ def test_check_conflicts(self): (os.path.join(test_easyconfigs, 'b', 'bzip2', 'bzip2-1.0.6-GCC-4.9.2.eb'), False), (os.path.join(test_easyconfigs, 'h', 'hwloc', 'hwloc-1.11.8-GCC-6.4.0-2.28.eb'), False), ]) - self.mock_stderr(True) - conflicts = check_conflicts(ecs, self.modtool) - stderr = self.get_stderr() - self.mock_stderr(False) + with self.mocked_stderr(): + conflicts = check_conflicts(ecs, self.modtool) + stderr = self.get_stderr() self.assertTrue(conflicts) self.assertIn("Conflict between (dependencies of) easyconfigs: GCC-4.9.2 vs GCC-6.4.0-2.28", stderr) @@ -1519,10 +1511,10 @@ def test_check_conflicts_wrapper_deps(self): write_file(wrapper_ec, wrapper_ec_txt) ecs, _ = parse_easyconfigs([(toy_ec, False), (wrapper_ec, False)]) - self.mock_stderr(True) - res = check_conflicts(ecs, self.modtool) - stderr = self.get_stderr() - self.mock_stderr(False) + with self.mocked_stderr(): + res = check_conflicts(ecs, self.modtool) + stderr = self.get_stderr() + self.assertEqual(stderr, '') self.assertFalse(res) @@ -1625,15 +1617,12 @@ def test_search_easyconfigs(self): # test use of print_result (enabled by default) for filename_only in [None, False, True]: - self.mock_stderr(True) - self.mock_stdout(True) - kwargs = {'consider_extra_paths': False} - if filename_only is not None: - kwargs['filename_only'] = filename_only - search_easyconfigs('binutils-.*-GCCcore-4.9.3', **kwargs) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + kwargs = {'consider_extra_paths': False} + if filename_only is not None: + kwargs['filename_only'] = filename_only + search_easyconfigs('binutils-.*-GCCcore-4.9.3', **kwargs) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertFalse(stderr) self.assertEqual(len(stdout.splitlines()), 2) diff --git a/test/framework/run.py b/test/framework/run.py index 5536570a77..d7e6f91a21 100644 --- a/test/framework/run.py +++ b/test/framework/run.py @@ -602,7 +602,7 @@ def handler(signum, _): try: run_shell_cmd(cmd) - self.assertFalse("This should never be reached, RunShellCmdError should occur!") + self.fail("This should never be reached, RunShellCmdError should occur!") except RunShellCmdError as err: self.assertEqual(str(err), "Shell command 'kill' failed!") self.assertEqual(err.cmd, "kill -9 $$") @@ -639,7 +639,7 @@ def handler(signum, _): # check error reporting output when stdout/stderr are collected separately try: run_shell_cmd(cmd, split_stderr=True) - self.assertFalse("This should never be reached, RunShellCmdError should occur!") + self.fail("This should never be reached, RunShellCmdError should occur!") except RunShellCmdError as err: self.assertEqual(str(err), "Shell command 'kill' failed!") self.assertEqual(err.cmd, "kill -9 $$") @@ -869,13 +869,10 @@ def test_run_cmd_trace(self): ] # trace output is enabled by default (since EasyBuild v5.0) - self.mock_stdout(True) - self.mock_stderr(True) - (out, ec) = run_cmd("echo hello") - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + (out, ec) = run_cmd("echo hello") + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(out, 'hello\n') self.assertEqual(ec, 0) self.assertTrue(stderr.strip().startswith("WARNING: Deprecated functionality")) @@ -883,13 +880,10 @@ def test_run_cmd_trace(self): self.assertTrue(regex.search(stdout), "Pattern '%s' found in: %s" % (regex.pattern, stdout)) update_build_option('trace', False) - self.mock_stdout(True) - self.mock_stderr(True) - (out, ec) = run_cmd("echo hello") - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + (out, ec) = run_cmd("echo hello") + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(out, 'hello\n') self.assertEqual(ec, 0) self.assertTrue(stderr.strip().startswith("WARNING: Deprecated functionality")) @@ -897,13 +891,10 @@ def test_run_cmd_trace(self): # also test with command that is fed input via stdin update_build_option('trace', True) - self.mock_stdout(True) - self.mock_stderr(True) - (out, ec) = run_cmd('cat', inp='hello') - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + (out, ec) = run_cmd('cat', inp='hello') + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(out, 'hello') self.assertEqual(ec, 0) self.assertTrue(stderr.strip().startswith("WARNING: Deprecated functionality")) @@ -913,13 +904,10 @@ def test_run_cmd_trace(self): self.assertTrue(regex.search(stdout), "Pattern '%s' found in: %s" % (regex.pattern, stdout)) update_build_option('trace', False) - self.mock_stdout(True) - self.mock_stderr(True) - (out, ec) = run_cmd('cat', inp='hello') - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + (out, ec) = run_cmd('cat', inp='hello') + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(out, 'hello') self.assertEqual(ec, 0) self.assertTrue(stderr.strip().startswith("WARNING: Deprecated functionality")) @@ -929,13 +917,10 @@ def test_run_cmd_trace(self): for trace in (True, False): init_config(build_options={'trace': trace}) - self.mock_stdout(True) - self.mock_stderr(True) - (out, ec) = run_cmd("echo hello", trace=False) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + (out, ec) = run_cmd("echo hello", trace=False) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(out, 'hello\n') self.assertEqual(ec, 0) self.assertEqual(stdout, '') @@ -955,13 +940,10 @@ def test_run_shell_cmd_trace(self): r" >> command completed: exit 0, ran in .*", ] - self.mock_stdout(True) - self.mock_stderr(True) - res = run_shell_cmd("echo hello") - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + res = run_shell_cmd("echo hello") + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(res.output, 'hello\n') self.assertEqual(res.exit_code, 0) self.assertEqual(stderr, '') @@ -969,13 +951,10 @@ def test_run_shell_cmd_trace(self): self.assertTrue(regex.search(stdout), "Pattern '%s' found in: %s" % (regex.pattern, stdout)) init_config(build_options={'trace': False}) - self.mock_stdout(True) - self.mock_stderr(True) - res = run_shell_cmd("echo hello") - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + res = run_shell_cmd("echo hello") + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(res.output, 'hello\n') self.assertEqual(res.exit_code, 0) self.assertEqual(stderr, '') @@ -985,13 +964,10 @@ def test_run_shell_cmd_trace(self): for trace in (True, False): init_config(build_options={'trace': trace}) - self.mock_stdout(True) - self.mock_stderr(True) - res = run_shell_cmd("echo hello", hidden=True) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + res = run_shell_cmd("echo hello", hidden=True) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(res.output, 'hello\n') self.assertEqual(res.exit_code, 0) self.assertEqual(stdout, '') @@ -1011,13 +987,10 @@ def test_run_shell_cmd_trace_stdin(self): r" >> command completed: exit 0, ran in .*", ] - self.mock_stdout(True) - self.mock_stderr(True) - res = run_shell_cmd("echo hello") - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + res = run_shell_cmd("echo hello") + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(res.output, 'hello\n') self.assertEqual(res.exit_code, 0) self.assertEqual(stderr, '') @@ -1025,13 +998,10 @@ def test_run_shell_cmd_trace_stdin(self): self.assertTrue(regex.search(stdout), "Pattern '%s' found in: %s" % (regex.pattern, stdout)) # also test with command that is fed input via stdin - self.mock_stdout(True) - self.mock_stderr(True) - res = run_shell_cmd('cat', stdin='hello') - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + res = run_shell_cmd('cat', stdin='hello') + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(res.output, 'hello') self.assertEqual(res.exit_code, 0) self.assertEqual(stderr, '') @@ -1041,13 +1011,10 @@ def test_run_shell_cmd_trace_stdin(self): self.assertTrue(regex.search(stdout), "Pattern '%s' found in: %s" % (regex.pattern, stdout)) # trace output can be disabled on a per-command basis by enabling 'hidden' - self.mock_stdout(True) - self.mock_stderr(True) - res = run_shell_cmd("echo hello", hidden=True) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + res = run_shell_cmd("echo hello", hidden=True) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(res.output, 'hello\n') self.assertEqual(res.exit_code, 0) self.assertEqual(stdout, '') @@ -1343,13 +1310,10 @@ def test_run_cmd_qa_trace(self): self.allow_deprecated_behaviour() # --trace is enabled by default - self.mock_stdout(True) - self.mock_stderr(True) - (out, ec) = run_cmd_qa("echo 'n: '; read n; seq 1 $n", {'n: ': '5'}) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + (out, ec) = run_cmd_qa("echo 'n: '; read n; seq 1 $n", {'n: ': '5'}) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertTrue(stderr.strip().startswith("WARNING: Deprecated functionality")) pattern = r"^ >> running interactive command:\n" pattern += r"\t\[started at: .*\]\n" @@ -1360,13 +1324,10 @@ def test_run_cmd_qa_trace(self): self.assertTrue(re.search(pattern, stdout), "Pattern '%s' found in: %s" % (pattern, stdout)) # trace output can be disabled on a per-command basis - self.mock_stdout(True) - self.mock_stderr(True) - (out, ec) = run_cmd("echo hello", trace=False) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + (out, ec) = run_cmd("echo hello", trace=False) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(stdout, '') self.assertTrue(stderr.strip().startswith("WARNING: Deprecated functionality")) @@ -1374,13 +1335,10 @@ def test_run_shell_cmd_qa_trace(self): """Test run_shell_cmd with qa_patterns under --trace""" update_build_option('trace', True) - self.mock_stdout(True) - self.mock_stderr(True) - run_shell_cmd("echo 'n: '; read n; seq 1 $n", qa_patterns=[('n: ', '5')]) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + run_shell_cmd("echo 'n: '; read n; seq 1 $n", qa_patterns=[('n: ', '5')]) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(stderr, '') pattern = r"^ >> running interactive shell command:\n" pattern += r"\techo \'n: \'; read n; seq 1 \$n\n" @@ -1391,13 +1349,10 @@ def test_run_shell_cmd_qa_trace(self): self.assertTrue(re.search(pattern, stdout), "Pattern '%s' found in: %s" % (pattern, stdout)) # trace output can be disabled on a per-command basis - self.mock_stdout(True) - self.mock_stderr(True) - run_shell_cmd("echo 'n: '; read n; seq 1 $n", qa_patterns=[('n: ', '5')], hidden=True) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + run_shell_cmd("echo 'n: '; read n; seq 1 $n", qa_patterns=[('n: ', '5')], hidden=True) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(stdout, '') self.assertEqual(stderr, '') @@ -1619,10 +1574,9 @@ def test_run_shell_cmd_dry_run(self): cmd = "somecommand foo 123 bar" - self.mock_stdout(True) - res = run_shell_cmd(cmd) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + res = run_shell_cmd(cmd) + stdout = self.get_stdout() # fake output/exit code is returned for commands not actually run in dry run mode self.assertEqual(res.exit_code, 0) self.assertEqual(res.output, '') @@ -1632,10 +1586,9 @@ def test_run_shell_cmd_dry_run(self): self.assertIn(expected, stdout) # check enabling 'hidden' - self.mock_stdout(True) - res = run_shell_cmd(cmd, hidden=True) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + res = run_shell_cmd(cmd, hidden=True) + stdout = self.get_stdout() # fake output/exit code is returned for commands not actually run in dry run mode self.assertEqual(res.exit_code, 0) self.assertEqual(res.output, '') @@ -1646,11 +1599,10 @@ def test_run_shell_cmd_dry_run(self): # check forced run_cmd outfile = os.path.join(self.test_prefix, 'cmd.out') self.assertNotExists(outfile) - self.mock_stdout(True) - res = run_shell_cmd("echo 'This is always echoed' > %s; echo done; false" % outfile, - fail_on_error=False, in_dry_run=True) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + res = run_shell_cmd("echo 'This is always echoed' > %s; echo done; false" % outfile, + fail_on_error=False, in_dry_run=True) + stdout = self.get_stdout() self.assertNotIn('running shell command "', stdout) self.assertNotEqual(res.exit_code, 0) self.assertEqual(res.output, 'done\n') @@ -1738,13 +1690,10 @@ def test_run_cmd_stream(self): # use of run_cmd is deprecated, so we need to allow it here self.allow_deprecated_behaviour() - self.mock_stdout(True) - self.mock_stderr(True) - (out, ec) = run_cmd("echo hello", stream_output=True) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + (out, ec) = run_cmd("echo hello", stream_output=True) + stdout = self.get_stdout() + stderr = self.get_stderr() self.assertEqual(ec, 0) self.assertEqual(out, "hello\n") @@ -1761,22 +1710,19 @@ def test_run_cmd_stream(self): def test_run_shell_cmd_stream(self): """Test use of run_shell_cmd with streaming output.""" init_config(build_options={'trace': True}) - self.mock_stdout(True) - self.mock_stderr(True) - cmd = '; '.join([ - "echo hello there", - "sleep 1", - "echo testing command that produces a fair amount of output", - "sleep 1", - "echo more than 128 bytes which means a whole bunch of characters...", - "sleep 1", - "echo more than 128 characters in fact, which is quite a bit when you think of it", - ]) - res = run_shell_cmd(cmd, stream_output=True) - stdout = self.get_stdout() - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + cmd = '; '.join([ + "echo hello there", + "sleep 1", + "echo testing command that produces a fair amount of output", + "sleep 1", + "echo more than 128 bytes which means a whole bunch of characters...", + "sleep 1", + "echo more than 128 characters in fact, which is quite a bit when you think of it", + ]) + res = run_shell_cmd(cmd, stream_output=True) + stdout = self.get_stdout() + stderr = self.get_stderr() expected_output = '\n'.join([ "hello there", @@ -1903,8 +1849,6 @@ def test_run_cmd_async(self): time.sleep(1) output += get_output_from_process(proc) ec = proc.poll() - - with self.mocked_stdout_stderr(): out, ec = complete_cmd(*cmd_info, simple=False, output=output) self.assertEqual(ec, 0) self.assertTrue(out.startswith('start\n')) diff --git a/test/framework/systemtools.py b/test/framework/systemtools.py index 50d7c58d18..3782d7c922 100644 --- a/test/framework/systemtools.py +++ b/test/framework/systemtools.py @@ -1185,10 +1185,10 @@ def mock_python_ver(py_maj_ver, py_min_ver): self.assertEqual(check_python_version(), pyver) # shouldn't raise any errors, since Python version used to run tests should be supported; - self.mock_stderr(True) - (py_maj_ver, py_min_ver) = check_python_version() - stderr = self.get_stderr() - self.mock_stderr(False) + with self.mocked_stderr(): + (py_maj_ver, py_min_ver) = check_python_version() + stderr = self.get_stderr() + self.assertFalse(stderr) self.assertIn(py_maj_ver, [2, 3]) @@ -1394,13 +1394,10 @@ def test_check_linked_shared_libs(self): warning_regex = re.compile(r"WARNING: Determining linked libraries.* via 'ldd .*/test.txt' failed!", re.M) - self.mock_stderr(True) - self.mock_stdout(True) - res = check_linked_shared_libs(test_file, banned_patterns=['/lib']) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + res = check_linked_shared_libs(test_file, banned_patterns=['/lib']) + stderr = self.get_stderr() + stdout = self.get_stdout() fail_msg = "Pattern '%s' should be found in: %s" % (warning_regex.pattern, stderr) self.assertTrue(warning_regex.search(stderr), fail_msg) diff --git a/test/framework/toolchain.py b/test/framework/toolchain.py index 16255d1826..e1206e08a4 100644 --- a/test/framework/toolchain.py +++ b/test/framework/toolchain.py @@ -227,12 +227,9 @@ def test_toolchain_compiler_env_vars(self): tc.set_options({}) # no warning about redefining if $CC/$CXX are not defined - self.mock_stderr(True) - self.mock_stdout(True) - tc.prepare() - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + tc.prepare() + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') self.assertEqual(stdout, '') @@ -258,12 +255,9 @@ def test_toolchain_compiler_env_vars(self): os.environ['CC'] = 'foo' os.environ['CXX'] = 'bar' - self.mock_stderr(True) - self.mock_stdout(True) - tc.prepare() - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + tc.prepare() + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stdout, '') @@ -276,12 +270,9 @@ def test_toolchain_compiler_env_vars(self): self.assertEqual(os.getenv('CXX'), 'g++') # no warning if the values are identical to the ones used in the minimal build environment - self.mock_stderr(True) - self.mock_stdout(True) - tc.prepare() - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + tc.prepare() + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') self.assertEqual(stdout, '') @@ -302,12 +293,9 @@ def test_toolchain_compiler_env_vars(self): # check whether a warning is printed when a value specified for $CC or $CXX is not found init_config(build_options={'minimal_build_env': 'CC:nosuchcommand,CXX:gcc'}) - self.mock_stderr(True) - self.mock_stdout(True) - tc.prepare() - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + tc.prepare() + stderr, stdout = self.get_stderr(), self.get_stdout() warning_msg = "WARNING: 'nosuchcommand' command not found in $PATH, " warning_msg += "not setting $CC in minimal build environment" @@ -324,12 +312,9 @@ def test_toolchain_compiler_env_vars(self): for key in ['CFLAGS', 'CXXFLAGS', 'FC']: os.environ.pop(key, None) - self.mock_stderr(True) - self.mock_stdout(True) - tc.prepare() - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + tc.prepare() + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(os.getenv('CC'), 'gcc') self.assertEqual(os.getenv('CXX'), 'g++') @@ -3317,13 +3302,10 @@ def prep(): """Helper function: create & prepare toolchain""" self.modtool.unload(['gompi', 'OpenMPI', 'hwloc', 'GCC']) tc = self.get_toolchain('gompi', version='2018a') - self.mock_stderr(True) - self.mock_stdout(True) - tc.prepare() - stderr = self.get_stderr().strip() - stdout = self.get_stdout().strip() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + tc.prepare() + stderr = self.get_stderr().strip() + stdout = self.get_stdout().strip() return tc, stdout, stderr diff --git a/test/framework/toy_build.py b/test/framework/toy_build.py index cfc78f8ba1..35a1673f4d 100644 --- a/test/framework/toy_build.py +++ b/test/framework/toy_build.py @@ -233,21 +233,17 @@ def _test_toy_build(self, extra_args=None, ec_file=None, tmpdir=None, verify=Tru def run_test_toy_build_with_output(self, *args, **kwargs): """Run test_toy_build with specified arguments, catch stdout/stderr and return it.""" - self.mock_stderr(True) - self.mock_stdout(True) - self._test_toy_build(*args, **kwargs) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self._test_toy_build(*args, **kwargs) + stderr = self.get_stderr() + stdout = self.get_stdout() return stdout, stderr def run_eb_main_capture_output(self, *args, **kwargs): """Run eb_main with specified arguments, capture stdout, and return output from eb_main""" - self.mock_stdout(True) - outtxt = self.eb_main(*args, **kwargs) - self.mock_stdout(False) + with self.mocked_stdout(): + outtxt = self.eb_main(*args, **kwargs) return outtxt def test_toy_build(self): @@ -845,9 +841,8 @@ def test_toy_group_check(self): else: write_file(test_ec, read_file(toy_ec) + "\ngroup = %s\n" % str(group)) - self.mock_stdout(True) - outtxt = self.eb_main(args, logfile=dummylogfn, do_build=True, raise_error=True, raise_systemexit=True) - self.mock_stdout(False) + with self.mocked_stdout(): + outtxt = self.eb_main(args, logfile=dummylogfn, do_build=True, raise_error=True, raise_systemexit=True) if get_module_syntax() == 'Tcl': module_version = LooseVersion(self.modtool.version) @@ -2122,14 +2117,12 @@ def test_backup_modules(self): toy_mod_backups = glob.glob(os.path.join(toy_mod_dir, '.' + toy_mod_fn + '.bak_*')) self.assertEqual(len(toy_mod_backups), 0) - self.mock_stderr(True) - self.mock_stdout(True) - # note: no need to specificy --backup-modules, enabled automatically under --module-only - self.eb_main(args + ['--module-only'], do_build=True, raise_error=True) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + # note: no need to specificy --backup-modules, enabled automatically under --module-only + self.eb_main(args + ['--module-only'], do_build=True, raise_error=True) + stderr = self.get_stderr() + stdout = self.get_stdout() + self.assertExists(toy_mod) toy_mod_backups = glob.glob(os.path.join(toy_mod_dir, '.' + toy_mod_fn + '.bak_*')) self.assertEqual(len(toy_mod_backups), 1) @@ -2154,13 +2147,10 @@ def test_backup_modules(self): # inject additional lines in module file to generate diff write_file(toy_mod, "some difference\n", append=True) - self.mock_stderr(True) - self.mock_stdout(True) - self.eb_main(args + ['--module-only'], do_build=True, raise_error=True, verbose=True) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.eb_main(args + ['--module-only'], do_build=True, raise_error=True, verbose=True) + stderr = self.get_stderr() + stdout = self.get_stdout() toy_mod_backups = glob.glob(os.path.join(toy_mod_dir, '.' + toy_mod_fn + '.bak_*')) self.assertEqual(len(toy_mod_backups), 2) @@ -2195,13 +2185,10 @@ def test_backup_modules(self): self.assertEqual(len(hidden_toy_mod_backups), 0) # 2nd installation: backup module is created - self.mock_stderr(True) - self.mock_stdout(True) - self.eb_main(args, do_build=True, raise_error=True, verbose=True) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.eb_main(args, do_build=True, raise_error=True, verbose=True) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertExists(toy_mod) lua_toy_mods = glob.glob(os.path.join(toy_mod_dir, '*.lua*')) @@ -2235,13 +2222,10 @@ def test_backup_modules(self): # tweak existing module file so we can verify diff of installed module with backup in stdout write_file(toy_mod, "some difference\n", append=True) - self.mock_stderr(True) - self.mock_stdout(True) - self.eb_main(args, do_build=True, raise_error=True, verbose=True) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.eb_main(args, do_build=True, raise_error=True, verbose=True) + stderr = self.get_stderr() + stdout = self.get_stdout() if LooseVersion(lmod_version) < LooseVersion('7.0.0'): backups_hidden += 1 @@ -2292,9 +2276,8 @@ def test_package_skip(self): self._test_toy_build(['--packagepath=%s' % pkgpath]) self.assertNotExists(pkgpath, "%s is not created without use of --package" % pkgpath) - self.mock_stdout(True) - self._test_toy_build(extra_args=['--package', '--skip'], verify=False) - self.mock_stdout(False) + with self.mocked_stdout(): + self._test_toy_build(extra_args=['--package', '--skip'], verify=False) toypkg = os.path.join(pkgpath, 'toy-0.0-eb-%s.1.rpm' % EASYBUILD_VERSION) self.assertExists(toypkg) @@ -2335,9 +2318,9 @@ def test_reproducibility(self): write_file(hooks_file, hooks_file_txt) # also use the easyblock with inheritance to fully test - self.mock_stdout(True) - self._test_toy_build(extra_args=['--minimal-toolchains', '--easyblock=EB_toytoy', '--hooks=%s' % hooks_file]) - self.mock_stdout(False) + with self.mocked_stdout(): + self._test_toy_build(extra_args=['--minimal-toolchains', '--easyblock=EB_toytoy', + '--hooks=%s' % hooks_file]) # Check whether easyconfig is dumped to reprod/ subdir reprod_dir = os.path.join(self.test_installpath, 'software', 'toy', '0.0', 'easybuild', 'reprod') @@ -2680,10 +2663,9 @@ def test_toy_build_enhanced_sanity_check(self): ] # by default, sanity check commands & paths specified by easyblock are used - self.mock_stdout(True) - self._test_toy_build(ec_file=test_ec, extra_args=eb_args, verify=False, testing=False, raise_error=True) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + self._test_toy_build(ec_file=test_ec, extra_args=eb_args, verify=False, testing=False, raise_error=True) + stdout = self.get_stdout() pattern_lines = [ r"Sanity check paths - file.*", @@ -2713,10 +2695,9 @@ def test_toy_build_enhanced_sanity_check(self): ]) write_file(test_ec, test_ec_txt) - self.mock_stdout(True) - self._test_toy_build(ec_file=test_ec, extra_args=eb_args, verify=False, testing=False, raise_error=True) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + self._test_toy_build(ec_file=test_ec, extra_args=eb_args, verify=False, testing=False, raise_error=True) + stdout = self.get_stdout() pattern_lines = [ r"Sanity check paths - file.*", @@ -2737,10 +2718,9 @@ def test_toy_build_enhanced_sanity_check(self): test_ec_txt = test_ec_txt + '\nenhance_sanity_check = True' write_file(test_ec, test_ec_txt) - self.mock_stdout(True) - self._test_toy_build(ec_file=test_ec, extra_args=eb_args, verify=False, testing=False, raise_error=True) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + self._test_toy_build(ec_file=test_ec, extra_args=eb_args, verify=False, testing=False, raise_error=True) + stdout = self.get_stdout() # now 'bin/toy' file and 'toy' command should also be part of sanity check pattern_lines = [ @@ -2770,10 +2750,9 @@ def test_toy_build_enhanced_sanity_check(self): '--trace', ] - self.mock_stdout(True) - self._test_toy_build(ec_file=test_ec, extra_args=eb_args, verify=False, testing=False, raise_error=True) - stdout = self.get_stdout() - self.mock_stdout(False) + with self.mocked_stdout(): + self._test_toy_build(ec_file=test_ec, extra_args=eb_args, verify=False, testing=False, raise_error=True) + stdout = self.get_stdout() pattern_lines = [ r"^== sanity checking\.\.\.", @@ -3335,7 +3314,7 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None, # It should not matter for the result, but triggers slightly different code paths in easyblock.py # This should succeed (since the default for --cuda-sanity-check-error-on-failed-checks is False) # as to not break backwards compatibility - write_file(cuobjdump_file, cuobjdump_txt_shebang), + write_file(cuobjdump_file, cuobjdump_txt_shebang) write_file(cuobjdump_file, cuobjdump_txt_sm90, append=True) write_file(cuobjdump_file, cuobjdump_txt_sm80_ptx, append=True) write_file(cuobjdump_file, cuobjdump_txt_sm70, append=True) @@ -3603,13 +3582,10 @@ def test_toy_build_trace(self): test_ec = os.path.join(self.test_prefix, 'test.eb') write_file(test_ec, read_file(toy_ec_file) + '\nsanity_check_commands = ["toy"]') - self.mock_stderr(True) - self.mock_stdout(True) - self._test_toy_build(ec_file=test_ec, extra_args=['--trace'], verify=False, testing=False) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self._test_toy_build(ec_file=test_ec, extra_args=['--trace'], verify=False, testing=False) + stderr = self.get_stderr() + stdout = self.get_stdout() self.assertEqual(stderr, '') @@ -3736,13 +3712,10 @@ def post_build_and_install_loop_hook(ecs): '--disable-trace', ] - self.mock_stderr(True) - self.mock_stdout(True) - self._test_toy_build(ec_file=test_ec, extra_args=extra_args, raise_error=True, debug=False) - stderr = self.get_stderr() - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self._test_toy_build(ec_file=test_ec, extra_args=extra_args, raise_error=True, debug=False) + stderr = self.get_stderr() + stdout = self.get_stdout() test_mod_path = os.path.join(self.test_installpath, 'modules', 'all') toy_mod_file = os.path.join(test_mod_path, 'toy', '0.0') @@ -4340,12 +4313,9 @@ def __exit__(self, type, value, traceback): # use context manager to remove lock after 3 seconds with RemoveLockAfter(3, toy_lock_path): - self.mock_stderr(True) - self.mock_stdout(True) - self._test_toy_build(extra_args=all_args, verify=False, raise_error=True, testing=False) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self._test_toy_build(extra_args=all_args, verify=False, raise_error=True, testing=False) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') @@ -4358,14 +4328,11 @@ def __exit__(self, type, value, traceback): # check use of --wait-on-lock-limit: if lock is never removed, we should give up when limit is reached mkdir(toy_lock_path) all_args = extra_args + ['--wait-on-lock-limit=3', '--wait-on-lock-interval=1'] - self.mock_stderr(True) - self.mock_stdout(True) - error_pattern = r"Maximum wait time for lock /.*toy_0.0.lock to be released reached: [0-9]+ sec >= 3 sec" - self.assertErrorRegex(EasyBuildError, error_pattern, self._test_toy_build, extra_args=all_args, - verify=False, raise_error=True, testing=False) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + error_pattern = r"Maximum wait time for lock /.*toy_0.0.lock to be released reached: [0-9]+ sec >= 3 sec" + self.assertErrorRegex(EasyBuildError, error_pattern, self._test_toy_build, extra_args=all_args, + verify=False, raise_error=True, testing=False) + stderr, stdout = self.get_stderr(), self.get_stdout() wait_matches = wait_regex.findall(stdout) self.assertIn(len(wait_matches), range(2, 5)) @@ -4375,12 +4342,9 @@ def __exit__(self, type, value, traceback): for opt in ['--wait-on-lock-limit=3', '--wait-on-lock-interval=1']: all_args = extra_args + [opt] self.assertNotExists(toy_lock_path) - self.mock_stderr(True) - self.mock_stdout(True) - self._test_toy_build(extra_args=all_args, verify=False, raise_error=True, testing=False) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self._test_toy_build(extra_args=all_args, verify=False, raise_error=True, testing=False) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertEqual(stderr, '') self.assertTrue(ok_regex.search(stdout), "Pattern '%s' found in: %s" % (ok_regex.pattern, stdout)) @@ -4447,14 +4411,11 @@ def __exit__(self, type, value, traceback): # change back to original working directory before each test change_dir(orig_wd) - self.mock_stderr(True) - self.mock_stdout(True) - self.assertErrorRegex(exc, '.*', self._test_toy_build, ec_file=test_ec, verify=False, - extra_args=extra_args, raise_error=True, testing=False, raise_systemexit=True) + with self.mocked_stdout_stderr(): + self.assertErrorRegex(exc, '.*', self._test_toy_build, ec_file=test_ec, verify=False, + extra_args=extra_args, raise_error=True, testing=False, raise_systemexit=True) - stderr = self.get_stderr().strip() - self.mock_stderr(False) - self.mock_stdout(False) + stderr = self.get_stderr().strip() pattern = r"^WARNING: signal received \(%s\), " % int(signum) pattern += r"cleaning up locks \(.*software_toy_0.0\)\.\.\." @@ -4671,12 +4632,10 @@ def test_toy_mod_files(self): self._test_toy_build(ec_file=test_ec) args = ['--try-toolchain=GCCcore,6.2.0', '--disable-map-toolchains'] - self.mock_stdout(True) - self.mock_stderr(True) - self._test_toy_build(ec_file=test_ec, extra_args=args) - stderr = self.get_stderr() - self.mock_stdout(False) - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + self._test_toy_build(ec_file=test_ec, extra_args=args) + stderr = self.get_stderr() + pattern = r"WARNING: One or more \.mod files found in .*/software/toy/0.0-GCCcore-6.2.0: .*/lib64/file.mod" self.assertRegex(stderr.strip(), pattern) @@ -4735,14 +4694,11 @@ def test_toy_unavailable_os_dep(self): test_report_fp = os.path.join(self.test_buildpath, 'full_test_report.md') - self.mock_stderr(True) - self.mock_stdout(True) - self._test_toy_build(ec_file=test_ec, force=False, raise_error=False, verify=False, - test_report_regexs=[r"One or more OS dependencies were not found"], - test_report=test_report_fp) - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self._test_toy_build(ec_file=test_ec, force=False, raise_error=False, verify=False, + test_report_regexs=[r"One or more OS dependencies were not found"], + test_report=test_report_fp) + stdout = self.get_stdout() patterns = [ r"Failed to process easyconfig", @@ -4766,12 +4722,9 @@ def test_toy_post_install_messages(self): test_report_fp = os.path.join(self.test_buildpath, 'full_test_report.md') - self.mock_stderr(True) - self.mock_stdout(True) - self._test_toy_build(ec_file=test_ec, test_report=test_report_fp) - stdout = self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self._test_toy_build(ec_file=test_ec, test_report=test_report_fp) + stdout = self.get_stdout() patterns = [ r"== This is post install message 1", diff --git a/test/framework/tweak.py b/test/framework/tweak.py index 48e6f48935..86a4faaf6c 100644 --- a/test/framework/tweak.py +++ b/test/framework/tweak.py @@ -398,12 +398,11 @@ def test_find_potential_version_mappings(self): 'version': '0.2.8' } - self.mock_stderr(True) - potential_versions = find_potential_version_mappings(openblas_dep, tc_mapping) - errtxt = self.get_stderr() - warning_stub = "\nWARNING: There may be newer version(s) of dep 'OpenBLAS' available with a different " \ - "versionsuffix to '-LAPACK-3.4.2'" - self.mock_stderr(False) + with self.mocked_stdout_stderr(): + potential_versions = find_potential_version_mappings(openblas_dep, tc_mapping) + errtxt = self.get_stderr() + warning_stub = "\nWARNING: There may be newer version(s) of dep 'OpenBLAS' available with a different " \ + "versionsuffix to '-LAPACK-3.4.2'" self.assertTrue(errtxt.startswith(warning_stub)) self.assertEqual(len(potential_versions), 0) potential_versions = find_potential_version_mappings(openblas_dep, tc_mapping, ignore_versionsuffixes=True)