Skip to content

Commit

Permalink
fix tests that got broken by enabling use of depends_on (instead of l…
Browse files Browse the repository at this point in the history
…oad) statement in generated environment modules by default
  • Loading branch information
boegel authored and Micket committed Sep 18, 2024
1 parent 9361e6e commit 9e5cba4
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 77 deletions.
17 changes: 9 additions & 8 deletions test/framework/easyblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ def test_make_module_dep(self):
" ('FFTW', '3.3.7'),",
" ('OpenBLAS', '0.2.20', '', ('GCC', '6.4.0-2.28')),",
']',
'module_depends_on = False',
])
self.writeEC()
eb = EasyBlock(EasyConfig(self.eb_file))
Expand Down Expand Up @@ -873,10 +874,10 @@ def test_make_module_dep_hmns(self):
with self.mocked_stdout_stderr():
mod_dep_txt = eb.make_module_dep()
for mod in ['GCC/6.4.0-2.28', 'OpenMPI/2.1.2']:
regex = re.compile('load.*%s' % mod)
regex = re.compile('(load|depends[-_]on).*%s' % mod)
self.assertFalse(regex.search(mod_dep_txt), "Pattern '%s' found in: %s" % (regex.pattern, mod_dep_txt))

regex = re.compile('load.*FFTW/3.3.7')
regex = re.compile('(load|depends[-_]on).*FFTW/3.3.7')
self.assertTrue(regex.search(mod_dep_txt), "Pattern '%s' found in: %s" % (regex.pattern, mod_dep_txt))

def test_make_module_dep_of_dep_hmns(self):
Expand Down Expand Up @@ -1361,27 +1362,27 @@ def test_make_module_step(self):

for (name, ver) in [('GCC', '6.4.0-2.28')]:
if get_module_syntax() == 'Tcl':
regex = re.compile(r'^\s*module load %s\s*$' % os.path.join(name, ver), re.M)
regex = re.compile(r'^\s*(module load|depends-on) %s\s*$' % os.path.join(name, ver), re.M)
elif get_module_syntax() == 'Lua':
regex = re.compile(r'^\s*load\("%s"\)$' % os.path.join(name, ver), re.M)
regex = re.compile(r'^\s*(load|depends_on)\("%s"\)$' % os.path.join(name, ver), re.M)
else:
self.fail("Unknown module syntax: %s" % get_module_syntax())
self.assertTrue(regex.search(txt), "Pattern %s found in %s" % (regex.pattern, txt))

for (name, ver) in [('test', '1.2.3')]:
if get_module_syntax() == 'Tcl':
regex = re.compile(r'^\s*module load %s/.%s\s*$' % (name, ver), re.M)
regex = re.compile(r'^\s*(module load|depends-on) %s/.%s\s*$' % (name, ver), re.M)
elif get_module_syntax() == 'Lua':
regex = re.compile(r'^\s*load\("%s/.%s"\)$' % (name, ver), re.M)
regex = re.compile(r'^\s*(load|depends_on)\("%s/.%s"\)$' % (name, ver), re.M)
else:
self.fail("Unknown module syntax: %s" % get_module_syntax())
self.assertTrue(regex.search(txt), "Pattern %s found in %s" % (regex.pattern, txt))

for (name, ver) in [('OpenMPI', '2.1.2-GCC-6.4.0-2.28')]:
if get_module_syntax() == 'Tcl':
regex = re.compile(r'^\s*module load %s/.?%s\s*$' % (name, ver), re.M)
regex = re.compile(r'^\s*(module load|depends-on) %s/.?%s\s*$' % (name, ver), re.M)
elif get_module_syntax() == 'Lua':
regex = re.compile(r'^\s*load\("%s/.?%s"\)$' % (name, ver), re.M)
regex = re.compile(r'^\s*(load|depends_on)\("%s/.?%s"\)$' % (name, ver), re.M)
else:
self.fail("Unknown module syntax: %s" % get_module_syntax())
self.assertFalse(regex.search(txt), "Pattern '%s' *not* found in %s" % (regex.pattern, txt))
Expand Down
6 changes: 6 additions & 0 deletions test/framework/easyconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -4785,6 +4785,8 @@ def test_recursive_module_unload(self):
toy_ec = os.path.join(test_ecs_dir, 'f', 'foss', 'foss-2018a.eb')
test_ec = os.path.join(self.test_prefix, 'test.eb')
test_ec_txt = read_file(toy_ec)
# this test only makes sense if depends_on is not used
test_ec_txt += '\nmodule_depends_on = False'
write_file(test_ec, test_ec_txt)

test_module = os.path.join(self.test_installpath, 'modules', 'all', 'foss', '2018a')
Expand Down Expand Up @@ -4827,6 +4829,8 @@ def test_recursive_module_unload(self):
# recursive_module_unload easyconfig parameter is honored
test_ec_bis = os.path.join(self.test_prefix, 'test_bis.eb')
test_ec_bis_txt = read_file(toy_ec) + '\nrecursive_module_unload = True'
# this test only makes sense if depends_on is not used
test_ec_bis_txt += '\nmodule_depends_on = False'
write_file(test_ec_bis, test_ec_bis_txt)

ec_bis = EasyConfig(test_ec_bis)
Expand Down Expand Up @@ -4871,6 +4875,8 @@ def test_recursive_module_unload(self):
self.assertTrue(build_option('recursive_mod_unload'))
test_ec_bis = os.path.join(self.test_prefix, 'test_bis.eb')
test_ec_bis_txt = read_file(toy_ec) + '\nrecursive_module_unload = False'
# this test only makes sense if depends_on is not used
test_ec_bis_txt += '\nmodule_depends_on = False'
write_file(test_ec_bis, test_ec_bis_txt)
ec_bis = EasyConfig(test_ec_bis)
self.assertEqual(ec_bis['recursive_module_unload'], False)
Expand Down
106 changes: 37 additions & 69 deletions test/framework/toy_build.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##
# Copyright 2013-2024 Ghent University
# Copyright 2013-2023 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
Expand Down Expand Up @@ -57,7 +57,7 @@
from easybuild.tools.filetools import adjust_permissions, change_dir, copy_file, mkdir, move_file
from easybuild.tools.filetools import read_file, remove_dir, remove_file, which, write_file
from easybuild.tools.module_generator import ModuleGeneratorTcl
from easybuild.tools.modules import EnvironmentModules, Lmod
from easybuild.tools.modules import Lmod
from easybuild.tools.run import run_shell_cmd
from easybuild.tools.utilities import nub
from easybuild.tools.systemtools import get_shared_lib_ext
Expand Down Expand Up @@ -262,7 +262,7 @@ def test_toy_broken(self):
broken_toy_ec = os.path.join(tmpdir, "toy-broken.eb")
toy_ec_file = os.path.join(os.path.dirname(__file__), 'easyconfigs', 'test_ecs', 't', 'toy', 'toy-0.0.eb')
broken_toy_ec_txt = read_file(toy_ec_file)
broken_toy_ec_txt += "checksums = ['clearywrongSHA256checksumoflength64-0123456789012345678901234567']"
broken_toy_ec_txt += "checksums = ['clearywrongMD5checksumoflength32']"
write_file(broken_toy_ec, broken_toy_ec_txt)
error_regex = "Checksum verification .* failed"
self.assertErrorRegex(EasyBuildError, error_regex, self.run_test_toy_build_with_output, ec_file=broken_toy_ec,
Expand Down Expand Up @@ -366,7 +366,8 @@ def test_toy_tweaked(self):
expected += "oh hai!"

# setting $LMOD_QUIET results in suppression of printed message with Lmod & module files in Tcl syntax
os.environ.pop('LMOD_QUIET', None)
if 'LMOD_QUIET' in os.environ:
del os.environ['LMOD_QUIET']

self.modtool.use(os.path.join(self.test_installpath, 'modules', 'all'))
out = self.modtool.run_module('load', 'toy/0.0-tweaked', return_output=True)
Expand Down Expand Up @@ -774,9 +775,14 @@ def test_toy_group_check(self):
self.mock_stdout(False)

if get_module_syntax() == 'Tcl':
module_version = LooseVersion(self.modtool.version)
if isinstance(self.modtool, EnvironmentModules) and module_version >= LooseVersion('4.6.0'):
toy_mod = os.path.join(self.test_installpath, 'modules', 'all', 'toy', '0.0')
pattern = "Can't generate robust check in TCL modules for users belonging to group %s." % group_name
regex = re.compile(pattern, re.M)
self.assertTrue(regex.search(outtxt), "Pattern '%s' found in: %s" % (regex.pattern, outtxt))

elif get_module_syntax() == 'Lua':
lmod_version = os.getenv('LMOD_VERSION', 'NOT_FOUND')
if LooseVersion(lmod_version) >= LooseVersion('6.0.8'):
toy_mod = os.path.join(self.test_installpath, 'modules', 'all', 'toy', '0.0.lua')
toy_mod_txt = read_file(toy_mod)

if isinstance(group, tuple):
Expand All @@ -787,35 +793,17 @@ def test_toy_group_check(self):
error_msg_pattern = "You are not part of '%s' group of users" % group_name

pattern = '\n'.join([
r'^if \{ \!\[ module-info usergroups %s \] \} \{' % group_name,
r' error "%s[^"]*"' % error_msg_pattern,
r'\}$',
r'^if not \( userInGroup\("%s"\) \) then' % group_name,
r' LmodError\("%s[^"]*"\)' % error_msg_pattern,
r'end$',
])
regex = re.compile(pattern, re.M)
self.assertTrue(regex.search(outtxt), "Pattern '%s' found in: %s" % (regex.pattern, toy_mod_txt))
else:
pattern = "Can't generate robust check in Tcl modules for users belonging to group %s." % group_name
regex = re.compile(pattern, re.M)
pattern = r"Can't generate robust check in Lua modules for users belonging to group %s. "
pattern += r"Lmod version not recent enough \(%s\), should be >= 6.0.8" % lmod_version
regex = re.compile(pattern % group_name, re.M)
self.assertTrue(regex.search(outtxt), "Pattern '%s' found in: %s" % (regex.pattern, outtxt))

elif get_module_syntax() == 'Lua':
toy_mod = os.path.join(self.test_installpath, 'modules', 'all', 'toy', '0.0.lua')
toy_mod_txt = read_file(toy_mod)

if isinstance(group, tuple):
group_name = group[0]
error_msg_pattern = "Hey, you're not in the '%s' group!" % group_name
else:
group_name = group
error_msg_pattern = "You are not part of '%s' group of users" % group_name

pattern = '\n'.join([
r'^if not \( userInGroup\("%s"\) \) then' % group_name,
r' LmodError\("%s[^"]*"\)' % error_msg_pattern,
r'end$',
])
regex = re.compile(pattern, re.M)
self.assertTrue(regex.search(outtxt), "Pattern '%s' found in: %s" % (regex.pattern, toy_mod_txt))
else:
self.fail("Unknown module syntax: %s" % get_module_syntax())

Expand Down Expand Up @@ -2330,7 +2318,6 @@ def test_reproducibility_ext_easyblocks(self):

def test_toy_toy(self):
"""Test building two easyconfigs in a single go, with one depending on the other."""

topdir = os.path.dirname(os.path.abspath(__file__))
toy_ec_file = os.path.join(topdir, 'easyconfigs', 'test_ecs', 't', 'toy', 'toy-0.0.eb')
toy_ec_txt = read_file(toy_ec_file)
Expand All @@ -2342,17 +2329,9 @@ def test_toy_toy(self):
])
write_file(ec1, ec1_txt)

# adapt toy easyconfig for toy2 to produce a modulefile with a dedicated
# name ('toy2' instead of 'toy')
ec2 = os.path.join(self.test_prefix, 'toy2.eb')
ec2_txt = '\n'.join([
toy_ec_txt,
"name = 'toy2'",
"easyblock = 'EB_toy'",
"sources = ['toy/toy-0.0.tar.gz']",
"patches = []",
"sanity_check_paths = { 'files': ['bin/toy2'], 'dirs': ['bin']}",
"prebuildopts = 'mv toy.source toy2.c &&'",
"versionsuffix = '-two'",
"dependencies = [('toy', '0.0', '-one')]",
])
Expand All @@ -2362,7 +2341,7 @@ def test_toy_toy(self):
self._test_toy_build(ec_file=self.test_prefix, verify=False)

mod1 = os.path.join(self.test_installpath, 'modules', 'all', 'toy', '0.0-one')
mod2 = os.path.join(self.test_installpath, 'modules', 'all', 'toy2', '0.0-two')
mod2 = os.path.join(self.test_installpath, 'modules', 'all', 'toy', '0.0-two')
if get_module_syntax() == 'Lua':
mod1 += '.lua'
mod2 += '.lua'
Expand All @@ -2375,15 +2354,15 @@ def test_toy_toy(self):
self.assertTrue(load1_regex.search(mod2_txt), "Pattern '%s' found in: %s" % (load1_regex.pattern, mod2_txt))

# Check the contents of the dumped env in the reprod dir to ensure it contains the dependency load
reprod_dir = os.path.join(self.test_installpath, 'software', 'toy2', '0.0-two', 'easybuild', 'reprod')
dumpenv_script = os.path.join(reprod_dir, 'toy2-0.0-two.env')
reprod_dir = os.path.join(self.test_installpath, 'software', 'toy', '0.0-two', 'easybuild', 'reprod')
dumpenv_script = os.path.join(reprod_dir, 'toy-0.0-two.env')
reprod_dumpenv = os.path.join(reprod_dir, dumpenv_script)
self.assertExists(reprod_dumpenv)

# Check contents of the dumpenv script
patterns = [
"""#!/bin/bash""",
"""# usage: source toy2-0.0-two.env""",
"""# usage: source toy-0.0-two.env""",
# defining build env
"""module load toy/0.0-one""",
"""# (no build environment defined)""",
Expand Down Expand Up @@ -2842,8 +2821,8 @@ def grab_gcc_rpath_wrapper_args():

# test use of rpath toolchain option
test_ecs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs')
toy_ec_txt = read_file(os.path.join(test_ecs, 't', 'toy', 'toy-0.0-gompi-2018a.eb'))
toy_ec_txt += "\ntoolchainopts = {'rpath': False}\n" # overwrites existing toolchainopts
toy_ec_txt = read_file(os.path.join(test_ecs, 't', 'toy', 'toy-0.0.eb'))
toy_ec_txt += "\ntoolchainopts = {'rpath': False}\n"
toy_ec = os.path.join(self.test_prefix, 'toy.eb')
write_file(toy_ec, toy_ec_txt)
with self.mocked_stdout_stderr():
Expand Down Expand Up @@ -3007,7 +2986,7 @@ def test_toy_build_trace(self):
r"\tgcc toy.c -o toy\n"
r"\t\[started at: .*\]",
r"\t\[working dir: .*\]",
r"\t\[output and state saved to .*\]",
r"\t\[output saved to .*\]",
r'',
]),
r" >> command completed: exit 0, ran in .*",
Expand Down Expand Up @@ -3209,22 +3188,13 @@ def test_toy_multi_deps(self):
'end',
])
else:
if not self.modtool.supports_safe_auto_load:
expected = '\n'.join([
'if { ![ is-loaded GCC/4.6.3 ] && ![ is-loaded GCC/7.3.0-2.30 ] } {',
' module load GCC/4.6.3',
'}',
])
else:
expected = '\n'.join([
'',
"if { [ module-info mode remove ] || [ is-loaded GCC/7.3.0-2.30 ] } {",
" module load GCC",
'} else {',
" module load GCC/4.6.3",
'}',
'',
])
expected = '\n'.join([
'if { [ module-info mode remove ] || [ is-loaded GCC/7.3.0-2.30 ] } {',
' depends-on GCC',
'} else {',
' depends-on GCC/4.6.3',
'}',
])

self.assertIn(expected, toy_mod_txt)

Expand Down Expand Up @@ -3786,9 +3756,7 @@ def __exit__(self, type, value, traceback):
toy_ec_txt = read_file(os.path.join(test_ecs_dir, 't', 'toy', 'toy-0.0.eb'))

test_ec = os.path.join(self.test_prefix, 'test.eb')
write_file(test_ec, toy_ec_txt + '\npostinstallcmds = ["sleep 10"]')

extra_args = ['--locks-dir=%s' % locks_dir, '--wait-on-lock-limit=3', '--wait-on-lock-interval=3']
write_file(test_ec, toy_ec_txt + '\npostinstallcmds = ["sleep 5"]')

signums = [
(signal.SIGABRT, SystemExit),
Expand All @@ -3801,15 +3769,15 @@ def __exit__(self, type, value, traceback):
# avoid recycling stderr of previous test
stderr = ''

with WaitAndSignal(3, signum):
with WaitAndSignal(1, signum):

# 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)
raise_error=True, testing=False, raise_systemexit=True)

stderr = self.get_stderr().strip()
self.mock_stderr(False)
Expand Down Expand Up @@ -3989,7 +3957,7 @@ def test_toy_build_sanity_check_linked_libs(self):
self.assertErrorRegex(EasyBuildError, error_msg, self._test_toy_build, force=False,
ec_file=test_ec, extra_args=['--module-only'], raise_error=True, verbose=False)

# check behaviour when alternative subdirectories are specified
# check behaviour when alternate subdirectories are specified
test_ec_txt = read_file(libtoy_ec)
test_ec_txt += "\nbin_lib_subdirs = ['', 'lib', 'lib64']"
write_file(test_ec, test_ec_txt)
Expand Down

0 comments on commit 9e5cba4

Please sign in to comment.