From 661241c836c608e51d41542579a9ec7dcf769b14 Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauldmccarthy@gmail.com> Date: Mon, 30 Nov 2020 17:35:21 +0000 Subject: [PATCH] CI: Basic unit tests for wrapper creation/removal --- .ci/test_create_remove_wrapper.py | 178 ++++++++++++++++++++++++++++++ .gitlab-ci.yml | 18 +++ 2 files changed, 196 insertions(+) create mode 100755 .ci/test_create_remove_wrapper.py create mode 100644 .gitlab-ci.yml diff --git a/.ci/test_create_remove_wrapper.py b/.ci/test_create_remove_wrapper.py new file mode 100755 index 0000000..42ef5c6 --- /dev/null +++ b/.ci/test_create_remove_wrapper.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python +# +# test_create_remove_wrapper.py - Test the createFSLWrapper.sh and +# removeFSLWrapper.sh scripts. Requires Python 3.7. +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + + +import os.path as op +import subprocess as sp +import textwrap as tw +import os +import shlex +import shutil +import tempfile +import contextlib +from unittest import mock + + +BASE_DIR = op.abspath(op.join(op.dirname(__file__), '..')) +CREATE_WRAPPER = op.join(BASE_DIR, 'etc', 'fslconf', 'createFSLWrapper.sh') +REMOVE_WRAPPER = op.join(BASE_DIR, 'etc', 'fslconf', 'removeFSLWrapper.sh') + + +def run(cmd, **kwargs): + return sp.run(shlex.split(cmd), check=True, **kwargs) + + +@contextlib.contextmanager +def temp_fsldir(): + + testdir = tempfile.mkdtemp() + prevdir = os.getcwd() + fsldir = op.join(testdir, 'fsl') + wrapperdir = op.join(testdir, 'fsl', 'share', 'fsl', 'bin') + try: + + os.chdir(testdir) + os.mkdir(fsldir) + + with mock.patch.dict(os.environ, { + 'FSLDIR' : fsldir, + 'PREFIX' : fsldir, + 'FSL_CREATE_WRAPPER_SCRIPTS' : '1'}): + yield fsldir, wrapperdir + + finally: + os.chdir(prevdir) + shutil.rmtree(testdir) + + +def touch(path): + dirname = op.dirname(path) + if not op.exists(dirname): + os.makedirs(dirname) + with open(path, 'wt') as f: + f.write('.') + + +def test_env_vars_not_set(): + """Test that wrapper scripts are not created if the + FSL_CREATE_WRAPPER_SCRIPTS, FSLDIR, or PREFIX environment variables + are not set. + """ + with temp_fsldir() as (fsldir, wrapperdir): + touch(op.join(fsldir, 'bin', 'test_script')) + + env = os.environ.copy() + env.pop('FSL_CREATE_WRAPPER_SCRIPTS') + run(f'{CREATE_WRAPPER} test_script', env=env) + assert not op.exists(op.join(wrapperdir, 'test_script1')) + + env = os.environ.copy() + env.pop('FSLDIR') + run(f'{CREATE_WRAPPER} test_script', env=env) + assert not op.exists(op.join(wrapperdir, 'test_script1')) + + env = os.environ.copy() + env.pop('PREFIX') + run(f'{CREATE_WRAPPER} test_script', env=env) + assert not op.exists(op.join(wrapperdir, 'test_script1')) + + # FSLDIR invalid + env = os.environ.copy() + env['FSLDIR'] = '/some/non-existent/path' + run(f'{CREATE_WRAPPER} test_script', env=env) + assert not op.exists(op.join(wrapperdir, 'test_script1')) + + # FSLDIR != PREFIX + env = os.environ.copy() + env['FSLDIR'] = op.join(env['PREFIX'], 'other_fsl') + run(f'{CREATE_WRAPPER} test_script', env=env) + assert not op.exists(op.join(wrapperdir, 'test_script1')) + + +def test_create_python_wrapper(): + """Test creation of a wrapper script for a python executable""" + with temp_fsldir() as (fsldir, wrapperdir): + + script_path = op.join(fsldir, 'bin', 'test_script') + wrapper_path = op.join(wrapperdir, 'test_script') + + touch(script_path) + with open(script_path, 'wt') as f: + f.write('#!/usr/bin/env python\n') + f.write('print("hello")\n') + + expect = tw.dedent(f""" + #!/usr/bin/env bash + {fsldir}/bin/python -I {script_path} "$@" + """).strip() + + run(f'{CREATE_WRAPPER} test_script') + + assert op.exists(wrapper_path) + with open(wrapper_path, 'rt') as f: + got = f.read().strip() + + assert got == expect + + +def test_create_other_wrapper(): + """Test creation of a wrapper script for a non-python executable.""" + with temp_fsldir() as (fsldir, wrapperdir): + script_path = op.join(fsldir, 'bin', 'test_script') + wrapper_path = op.join(wrapperdir, 'test_script') + + touch(script_path) + with open(op.join(fsldir, 'bin', 'test_script'), 'wt') as f: + f.write('#!/usr/bin/env bash\n') + f.write('echo "hello"\n') + + expect = tw.dedent(f""" + #!/usr/bin/env bash + {script_path} "$@" + """).strip() + + run(f'{CREATE_WRAPPER} test_script') + + assert op.exists(wrapper_path) + with open(wrapper_path, 'rt') as f: + got = f.read().strip() + + assert got == expect + + +def test_permissions_preserved(): + """Test that wrapper script has same permissions as wrapped script.""" + with temp_fsldir() as (fsldir, wrapperdir): + perms = [0o777, 0o755, 0o644, 0o600, 0o755, 0o700] + script_path = op.join(fsldir, 'bin', 'test_script') + wrapper_path = op.join(wrapperdir, 'test_script') + touch(script_path) + + for perm in perms: + os.chmod(script_path, perm) + run(f'{CREATE_WRAPPER} test_script') + + stat = os.stat(wrapper_path) + assert (stat.st_mode & 0o777) == perm + + +def test_create_remove_wrappers(): + """Tests normal usage. """ + with temp_fsldir() as (fsldir, wrapperdir): + touch(op.join(fsldir, 'bin', 'test_script1')) + touch(op.join(fsldir, 'bin', 'test_script2')) + + run(f'{CREATE_WRAPPER} test_script1 test_script2') + + assert op.exists(op.join(wrapperdir, 'test_script1')) + assert op.exists(op.join(wrapperdir, 'test_script2')) + + run(f'{REMOVE_WRAPPER} test_script1 test_script2') + + assert not op.exists(op.join(wrapperdir, 'test_script1')) + assert not op.exists(op.join(wrapperdir, 'test_script2')) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..53c22aa --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,18 @@ +include: + - project: fsl/fsl-ci-rules + file: .gitlab-ci.yml + +stages: + - test + - fsl-ci-pre + - fsl-ci-build + - fsl-ci-deploy + +test: + stage: test + image: python:3.7 + tags: + - docker + script: + - pip install pytest + - pytest -v .ci \ No newline at end of file -- GitLab