Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,22 +240,29 @@ jobs:
# create file owned by root but writable by anyone (used by test_copy_file)
sudo touch /tmp/file_to_overwrite_for_easybuild_test_copy_file.txt
sudo chmod o+w /tmp/file_to_overwrite_for_easybuild_test_copy_file.txt

if [ "$GITHUB_REPOSITORY_OWNER" == 'easybuilders' ] || [ '${{github.event.pull_request.head.repo.owner}}' == 'easybuilders' ]; then
FORCE_EB_GITHUB_TESTS=1
else
echo "Not force-enabling Github tests"
echo "\$GITHUB_EVENT_NAME=GITHUB_EVENT_NAME"
echo "\$GITHUB_REPOSITORY_OWNER=$GITHUB_REPOSITORY_OWNER"
echo "PR HEAD repo owner=${{github.event.pull_request.head.repo.owner}}"
fi

# run test suite
python -O -m test.framework.suite 2>&1 | tee test_framework_suite.log
# try and make sure output of running tests is clean (no printed messages/warnings)
IGNORE_PATTERNS="no GitHub token available"
IGNORE_PATTERNS+="|skipping SvnRepository test"
IGNORE_PATTERNS+="|requires Lmod as modules tool"
IGNORE_PATTERNS="^[s.]*$" # Only PASS (.) and SKIP (s) status on line
IGNORE_PATTERNS+="|stty: 'standard input': Inappropriate ioctl for device"
IGNORE_PATTERNS+="|CryptographyDeprecationWarning: Python 3.7"
IGNORE_PATTERNS+="|from cryptography.* import "
IGNORE_PATTERNS+="|Blowfish"
IGNORE_PATTERNS+="|GC3Pie not available, skipping test"
IGNORE_PATTERNS+="|CryptographyDeprecationWarning: TripleDES has been moved"
IGNORE_PATTERNS+="|algorithms.TripleDES"
# ignore lines with only successful ('.') and skipped ('s') tests
IGNORE_PATTERNS+="|^[\.s]+$"

TEST_OUTPUT=$(sed -n '/------------------------------/q;p' test_framework_suite.log) # Everything up to the result divider
# '|| true' is needed to avoid that GitHub Actions stops the job on non-zero exit of grep (i.e. when there are no matches)
PRINTED_MSG=$(egrep -v "${IGNORE_PATTERNS}" test_framework_suite.log | grep '\.\n*[A-Za-z]' || true)
test "x$PRINTED_MSG" = "x" || (echo "ERROR: Found printed messages in output of test suite" && echo "${PRINTED_MSG}" && exit 1)
PRINTED_MSG=$(echo "$TEST_OUTPUT" | egrep -v "${IGNORE_PATTERNS}" || true)
[[ -z $PRINTED_MSG ]] || (echo "ERROR: Found printed messages in output of test suite" && echo "${PRINTED_MSG}" && exit 1)
done
111 changes: 41 additions & 70 deletions test/framework/easyconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@

import easybuild.tools.build_log
import easybuild.framework.easyconfig as easyconfig
import easybuild.tools.github as gh
import easybuild.tools.systemtools as st
from easybuild.framework.easyblock import EasyBlock
from easybuild.framework.easyconfig.constants import EXTERNAL_MODULE_MARKER
Expand Down Expand Up @@ -79,13 +78,9 @@

from easybuild.tools.toolchain.utilities import search_toolchain
from easybuild.tools.utilities import quote_str, quote_py_str
from test.framework.github import GITHUB_TEST_ACCOUNT
from test.framework.utilities import find_full_path
from test.framework.github import requires_github_token
from test.framework.utilities import find_full_path, requires_autopep8, requires_pycodestyle, requires_pygraph

try:
import pycodestyle # noqa # pylint:disable=unused-import
except ImportError:
pass

EXPECTED_DOTTXT_TOY_DEPS = """digraph graphname {
toy;
Expand All @@ -112,9 +107,6 @@ def setUp(self):
if os.path.exists(self.eb_file):
os.remove(self.eb_file)

github_token = gh.fetch_github_token(GITHUB_TEST_ACCOUNT)
self.skip_github_tests = github_token is None and os.getenv('FORCE_EB_GITHUB_TESTS') is None

self.orig_easyconfig_DEPRECATED_EASYCONFIG_PARAMETERS = easyconfig.easyconfig.DEPRECATED_EASYCONFIG_PARAMETERS
self.orig_easyconfig_DEPRECATED_EASYCONFIG_TEMPLATES = easyconfig.easyconfig.DEPRECATED_EASYCONFIG_TEMPLATES
self.orig_easyconfig_ALTERNATIVE_EASYCONFIG_PARAMETERS = easyconfig.easyconfig.ALTERNATIVE_EASYCONFIG_PARAMETERS
Expand Down Expand Up @@ -2779,25 +2771,18 @@ def test_dump_order(self):
'foo_extra1', '', 'moduleclass', '']
self.assertEqual(param_regex.findall(ectxt), expected)

@requires_autopep8()
def test_dump_autopep8(self):
"""Test dump() with autopep8 usage enabled (only if autopep8 is available)."""
try:
import autopep8 # noqa # pylint:disable=unused-import
except ImportError:
print("Skipping test_dump_autopep8, since autopep8 is not available")
return
os.environ['EASYBUILD_DUMP_AUTOPEP8'] = '1'
init_config()
self.test_dump()
del os.environ['EASYBUILD_DUMP_AUTOPEP8']

@requires_pycodestyle()
def test_dump_extra(self):
"""Test EasyConfig's dump() method for files containing extra values"""

if 'pycodestyle' not in sys.modules:
print("Skipping test_dump_extra pycodestyle is not available")
return

rawtxt = '\n'.join([
"easyblock = 'EB_foo'",
'',
Expand Down Expand Up @@ -2834,13 +2819,10 @@ def test_dump_extra(self):

check_easyconfigs_style([testec])

@requires_pycodestyle()
def test_dump_template(self):
""" Test EasyConfig's dump() method for files containing templates"""

if 'pycodestyle' not in sys.modules:
print("Skipping test_dump_template pycodestyle is not available")
return

rawtxt = '\n'.join([
"easyblock = 'EB_foo'",
'',
Expand Down Expand Up @@ -2923,13 +2905,10 @@ def test_dump_template(self):

check_easyconfigs_style([testec])

@requires_pycodestyle()
def test_dump_comments(self):
""" Test dump() method for files containing comments """

if 'pycodestyle' not in sys.modules:
print("Skipping test_dump_comments pycodestyle is not available")
return

rawtxt = '\n'.join([
"# #",
"# some header comment",
Expand Down Expand Up @@ -3278,13 +3257,9 @@ def test_to_template_str(self):
res = "sanity_check_paths = {\n 'files': [],\n 'dirs': ['lib/python%(pyshortver)s/site-packages'],\n}"
self.assertEqual(to_template_str('sanity_check_paths', test_input, templ_const, templ_val), res)

@requires_pygraph()
def test_dep_graph(self):
"""Test for dep_graph."""
try:
import pygraph # noqa # pylint:disable=unused-import
except ImportError:
print("Skipping test_dep_graph, since pygraph is not available")
return

test_easyconfigs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs')
build_options = {
Expand Down Expand Up @@ -3315,52 +3290,47 @@ def test_dep_graph(self):
ordered_expected = '\n'.join(sorted(EXPECTED_DOTTXT_TOY_DEPS.split('\n')))
self.assertEqual(ordered_dottxt, ordered_expected)

@requires_pygraph()
def test_dep_graph_multi_deps(self):
"""
Test for dep_graph using easyconfig that uses multi_deps.
"""
try:
import pygraph # noqa # pylint:disable=unused-import

test_easyconfigs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs')
build_options = {
'external_modules_metadata': ConfigObj(),
'valid_module_classes': module_classes(),
'robot_path': [test_easyconfigs],
'silent': True,
}
init_config(build_options=build_options)

toy_ec = os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0.eb')
toy_ec_txt = read_file(toy_ec)
test_easyconfigs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs')
build_options = {
'external_modules_metadata': ConfigObj(),
'valid_module_classes': module_classes(),
'robot_path': [test_easyconfigs],
'silent': True,
}
init_config(build_options=build_options)

test_ec = os.path.join(self.test_prefix, 'test.eb')
test_ec_txt = toy_ec_txt + "\nmulti_deps = {'GCC': ['4.6.3', '4.8.3', '7.3.0-2.30']}"
write_file(test_ec, test_ec_txt)
toy_ec = os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0.eb')
toy_ec_txt = read_file(toy_ec)

ec_files = [(test_ec, False)]
ecs, _ = parse_easyconfigs(ec_files)
test_ec = os.path.join(self.test_prefix, 'test.eb')
test_ec_txt = toy_ec_txt + "\nmulti_deps = {'GCC': ['4.6.3', '4.8.3', '7.3.0-2.30']}"
write_file(test_ec, test_ec_txt)

dot_file = os.path.join(self.test_prefix, 'test.dot')
ordered_ecs = resolve_dependencies(ecs, self.modtool, retain_all_deps=True)
dep_graph(dot_file, ordered_ecs)
ec_files = [(test_ec, False)]
ecs, _ = parse_easyconfigs(ec_files)

# hard check for expect .dot file contents
# 3 nodes should be there: 'GCC/6.4.0-2.28 (EXT)', 'toy', and 'intel/2018a'
# and 2 edges: 'toy -> intel' and 'toy -> "GCC/6.4.0-2.28 (EXT)"'
dottxt = read_file(dot_file)
dot_file = os.path.join(self.test_prefix, 'test.dot')
ordered_ecs = resolve_dependencies(ecs, self.modtool, retain_all_deps=True)
dep_graph(dot_file, ordered_ecs)

self.assertTrue(dottxt.startswith('digraph graphname {'))
# hard check for expect .dot file contents
# 3 nodes should be there: 'GCC/6.4.0-2.28 (EXT)', 'toy', and 'intel/2018a'
# and 2 edges: 'toy -> intel' and 'toy -> "GCC/6.4.0-2.28 (EXT)"'
dottxt = read_file(dot_file)

# just check for toy -> GCC deps
# don't bother doing full output check
# (different order for fields depending on Python version makes that tricky)
for gccver in ['4.6.3', '4.8.3', '7.3.0-2.30']:
self.assertTrue('"GCC/%s";' % gccver in dottxt)
self.assertTrue('"toy/0.0" -> "GCC/%s"' % gccver in dottxt)
self.assertTrue(dottxt.startswith('digraph graphname {'))

except ImportError:
print("Skipping test_dep_graph, since pygraph is not available")
# just check for toy -> GCC deps
# don't bother doing full output check
# (different order for fields depending on Python version makes that tricky)
for gccver in ['4.6.3', '4.8.3', '7.3.0-2.30']:
self.assertTrue('"GCC/%s";' % gccver in dottxt)
self.assertTrue('"toy/0.0" -> "GCC/%s"' % gccver in dottxt)

def test_ActiveMNS_singleton(self):
"""Make sure ActiveMNS is a singleton class."""
Expand Down Expand Up @@ -4911,10 +4881,11 @@ def test_det_copy_ec_specs(self):
self.assertEqual(paths, args[:-1])
self.assertEqual(target_path, args[-1])

if self.skip_github_tests:
print("Skipping test_det_copy_ec_specs using --from-pr, no GitHub token available?")
return
@requires_github_token()
def test_det_copy_ec_specs_from_pr(self):
"""Test det_copy_ec_specs function with --from-pr."""

cwd = os.getcwd()
# use fixed PR (speeds up the test due to caching in fetch_files_from_pr;
# see https://github.com/easybuilders/easybuild-easyconfigs/pull/22345
from_pr = 22345
Expand Down
Loading