diff --git a/tests/test_imglob.py b/tests/test_imglob.py index 333fbd104c8599dda439543ee9d0d339df126cfd..9a8e838d1321fd45c91c1d94188700067423097f 100644 --- a/tests/test_imglob.py +++ b/tests/test_imglob.py @@ -5,14 +5,11 @@ # Author: Paul McCarthy <pauldmccarthy@gmail.com> # -import mock import pytest import fsl.scripts.imglob as imglob -from tests import testdir -from tests import CaptureStdout - +from . import testdir def test_imglob_shouldPass(): @@ -88,60 +85,3 @@ def test_imglob_shouldFail(): with pytest.raises(ValueError): imglob.imglob([], 'bag') - - -def test_imglob_script_shouldPass(): - - # (files to create, args, expected) - tests = [ - ('file.hdr file.img', 'file', 'file'), - ('file.hdr file.img', '-extension file', 'file.hdr'), - ('file.hdr file.img', '-extensions file', 'file.hdr file.img'), - ('file.hdr file.img', 'file.hdr', 'file'), - ('file.hdr file.img', ' -extension file.hdr', 'file.hdr'), - ('file.hdr file.img', '-extensions file.hdr', 'file.hdr file.img'), - ('file.hdr file.img', 'file.img', 'file'), - ('file.hdr file.img', '-extension file.img', 'file.hdr'), - ('file.hdr file.img', '-extensions file.img', 'file.hdr file.img'), - ('file.hdr file.img', 'file.hdr file.img', 'file'), - ('file.hdr file.img', '-extension file.hdr file.img', 'file.hdr'), - ('file.hdr file.img', '-extensions file.hdr file.img', 'file.hdr file.img'), - ('file.hdr file.img', 'file file.img', 'file'), - ('file.hdr file.img', '-extension file file.img', 'file.hdr'), - ('file.hdr file.img', '-extensions file file.img', 'file.hdr file.img'), - - # no file or incomplete prefix - ('file.hdr file.img', 'bag', ''), - ('file.hdr file.img', '-extension bag', ''), - ('file.hdr file.img', '-extensions bag', ''), - ('file.hdr file.img', 'fi', ''), - ('file.hdr file.img', '-extension fi', ''), - ('file.hdr file.img', '-extensions fi', ''), - ] - - capture = CaptureStdout() - - for to_create, args, expected in tests: - with testdir(to_create.split()) as td: - - capture.reset() - - with capture: - assert imglob.main(args.split()) == 0 - - assert capture.stdout.strip().split() == expected.split() - - -def test_imglob_script_shouldFail(): - - capture = CaptureStdout() - - with capture: - assert imglob.main([]) != 0 - - assert capture.stdout.strip().lower().startswith('usage:') - - with capture, mock.patch('sys.argv', ['imglob']): - assert imglob.main() != 0 - - assert capture.stdout.strip().lower().startswith('usage:') diff --git a/tests/test_immv_imcp.py b/tests/test_immv_imcp.py index 215b4dc4062245786d4b37af190d626928cefc1c..dd1273d78e162a3ee96638cfba4b12850d1b080f 100644 --- a/tests/test_immv_imcp.py +++ b/tests/test_immv_imcp.py @@ -10,26 +10,18 @@ from __future__ import print_function import os.path as op -import itertools as it -import subprocess as sp import os import shutil import tempfile -import pytest - import nibabel as nib -from fsl.utils.tempdir import tempdir import fsl.utils.imcp as imcp -import fsl.scripts.imcp as imcp_script -import fsl.scripts.immv as immv_script import fsl.data.image as fslimage from . import make_random_image from . import make_dummy_file from . import looks_like_image -from . import cleardir real_print = print @@ -111,415 +103,6 @@ def checkFilesToExpect(files, outdir, outputType, datahashes): checkImageHash(f, h) -def test_imcp_script_shouldPass(move=False): - - - # The imcp/immv scripts should honour the - # FSLOUTPUTTYPE env var. If it is unset - # or invalid - '' in this case), they - # should produce .nii.gz - outputTypes = ['NIFTI', 'NIFTI_PAIR', 'NIFTI_GZ', ''] - reldirs = ['neutral', 'samedir', 'indir', 'outdir'] - - # Test tuples have the following structure (each - # item is a string which will be split on spaces): - # - # (files_to_create, imcp_args, files_to_expect) - # - # The files_to_expect is a list of - # prefixes - the suffix(es) is(are) - # determined by the current outputType - # - # If multiple files are being copied, the - # files_to_create and files_to_expect lists - # have to be in the same order. - tests = [ - - ('a.nii', 'a b', 'b'), - ('a.nii', 'a.nii b', 'b'), - ('a.nii', 'a b.nii', 'b'), - ('a.nii', 'a.nii b.nii', 'b'), - ('a.nii', 'a .', 'a'), - ('a.nii', 'a.nii .', 'a'), - ('a.nii', 'a b.hdr', 'b'), - ('a.nii', 'a b.img', 'b'), - ('a.nii', 'a b.nii.gz', 'b'), - ('a.nii', 'a.nii b.hdr', 'b'), - ('a.nii', 'a.nii b.img', 'b'), - ('a.nii', 'a.nii b.nii.gz', 'b'), - - ('a.nii.gz', 'a b', 'b'), - ('a.nii.gz', 'a.nii.gz b', 'b'), - ('a.nii.gz', 'a b.nii.gz', 'b'), - ('a.nii.gz', 'a.nii.gz b.nii.gz', 'b'), - ('a.nii.gz', 'a .', 'a'), - ('a.nii.gz', 'a.nii.gz .', 'a'), - ('a.nii.gz', 'a b.hdr', 'b'), - ('a.nii.gz', 'a b.img', 'b'), - ('a.nii.gz', 'a b.nii', 'b'), - ('a.nii.gz', 'a.nii.gz b.hdr', 'b'), - ('a.nii.gz', 'a.nii.gz b.img', 'b'), - ('a.nii.gz', 'a.nii.gz b.nii', 'b'), - - ('a.img', 'a b', 'b'), - ('a.img', 'a b.img', 'b'), - ('a.img', 'a b.hdr', 'b'), - ('a.img', 'a .', 'a'), - ('a.img', 'a.img b', 'b'), - ('a.img', 'a.img b.img', 'b'), - ('a.img', 'a.img b.hdr', 'b'), - ('a.img', 'a.img .', 'a'), - ('a.img', 'a.hdr b', 'b'), - ('a.img', 'a.hdr b.img', 'b'), - ('a.img', 'a.hdr b.hdr', 'b'), - ('a.img', 'a.hdr .', 'a'), - - ('a.img', 'a b.nii', 'b'), - ('a.img', 'a b.nii.gz', 'b'), - ('a.img', 'a .', 'a'), - ('a.img', 'a.hdr b.nii', 'b'), - ('a.img', 'a.hdr b.nii.gz', 'b'), - ('a.img', 'a.hdr .', 'a'), - ('a.img', 'a.img b.nii', 'b'), - ('a.img', 'a.img b.nii.gz', 'b'), - ('a.img', 'a.img .', 'a'), - - ('a.nii b.nii', 'a b .', 'a b'), - ('a.nii b.nii', 'a b.nii .', 'a b'), - ('a.nii b.nii', 'a.nii b .', 'a b'), - ('a.nii b.nii', 'a.nii b.nii .', 'a b'), - - ('a.img b.img', 'a b .', 'a b'), - ('a.img b.img', 'a b.img .', 'a b'), - ('a.img b.img', 'a b.hdr .', 'a b'), - ('a.img b.img', 'a.img b .', 'a b'), - ('a.img b.img', 'a.img b.img .', 'a b'), - ('a.img b.img', 'a.img b.hdr .', 'a b'), - ('a.img b.img', 'a.hdr b .', 'a b'), - ('a.img b.img', 'a.hdr b.img .', 'a b'), - ('a.img b.img', 'a.hdr b.hdr .', 'a b'), - - ('a.nii.gz b.nii.gz', 'a b .', 'a b'), - ('a.nii.gz b.nii.gz', 'a b.nii.gz .', 'a b'), - ('a.nii.gz b.nii.gz', 'a.nii.gz b .', 'a b'), - ('a.nii.gz b.nii.gz', 'a.nii.gz b.nii.gz .', 'a b'), - - # Heterogenous inputs - ('a.nii b.nii.gz', 'a b .', 'a b'), - ('a.nii b.nii.gz', 'a b.nii.gz .', 'a b'), - ('a.nii b.nii.gz', 'a.nii b .', 'a b'), - ('a.nii b.nii.gz', 'a.nii b.nii.gz .', 'a b'), - ('a.nii b.img', 'a b .', 'a b'), - ('a.nii b.img', 'a b.img .', 'a b'), - ('a.nii b.img', 'a b.hdr .', 'a b'), - ('a.nii b.img', 'a.nii b .', 'a b'), - ('a.nii b.img', 'a.nii b.img .', 'a b'), - ('a.nii b.img', 'a.nii b.hdr .', 'a b'), - ('a.img b.nii', 'a b .', 'a b'), - ('a.img b.nii', 'a b.nii .', 'a b'), - ('a.img b.nii', 'a.img b .', 'a b'), - ('a.img b.nii', 'a.img b.nii .', 'a b'), - ('a.img b.nii', 'a.hdr b .', 'a b'), - ('a.img b.nii', 'a.hdr b.nii .', 'a b'), - - # Duplicate inputs - ('a.img', 'a a .', 'a'), - ('a.img', 'a a.img .', 'a'), - ('a.img', 'a a.hdr .', 'a'), - ('a.img', 'a.img a .', 'a'), - ('a.img', 'a.img a.img .', 'a'), - ('a.img', 'a.img a.hdr .', 'a'), - ('a.img', 'a.hdr a .', 'a'), - ('a.img', 'a.hdr a.img .', 'a'), - ('a.img', 'a.hdr a.hdr .', 'a'), - - ('a.img b.img', 'a a b b .', 'a b'), - ('a.img b.img', 'a a b b.img .', 'a b'), - ('a.img b.img', 'a a b b.hdr .', 'a b'), - ('a.img b.img', 'a a b.img b .', 'a b'), - ('a.img b.img', 'a a b.img b.img .', 'a b'), - ('a.img b.img', 'a a b.img b.hdr .', 'a b'), - ('a.img b.img', 'a a.img b b .', 'a b'), - ('a.img b.img', 'a a.img b b.img .', 'a b'), - ('a.img b.img', 'a a.img b b.hdr .', 'a b'), - ('a.img b.img', 'a a.img b.img b .', 'a b'), - ('a.img b.img', 'a a.img b.img b.img .', 'a b'), - ('a.img b.img', 'a a.img b.img b.hdr .', 'a b'), - ('a.img b.img', 'a a.hdr b b .', 'a b'), - ('a.img b.img', 'a a.hdr b b.img .', 'a b'), - ('a.img b.img', 'a a.hdr b b.hdr .', 'a b'), - ('a.img b.img', 'a a.hdr b.img b .', 'a b'), - ('a.img b.img', 'a a.hdr b.img b.img .', 'a b'), - ('a.img b.img', 'a a.hdr b.img b.hdr .', 'a b'), - ('a.img b.img', 'a.img a b b .', 'a b'), - ('a.img b.img', 'a.img a b b.img .', 'a b'), - ('a.img b.img', 'a.img a b b.hdr .', 'a b'), - ('a.img b.img', 'a.img a b.img b .', 'a b'), - ('a.img b.img', 'a.img a b.img b.img .', 'a b'), - ('a.img b.img', 'a.img a b.img b.hdr .', 'a b'), - ('a.img b.img', 'a.img a.img b b .', 'a b'), - ('a.img b.img', 'a.img a.img b b.img .', 'a b'), - ('a.img b.img', 'a.img a.img b b.hdr .', 'a b'), - ('a.img b.img', 'a.img a.img b.img b .', 'a b'), - ('a.img b.img', 'a.img a.img b.img b.img .', 'a b'), - ('a.img b.img', 'a.img a.img b.img b.hdr .', 'a b'), - ('a.img b.img', 'a.img a.hdr b b .', 'a b'), - ('a.img b.img', 'a.img a.hdr b b.img .', 'a b'), - ('a.img b.img', 'a.img a.hdr b b.hdr .', 'a b'), - ('a.img b.img', 'a.img a.hdr b.img b .', 'a b'), - ('a.img b.img', 'a.img a.hdr b.img b.img .', 'a b'), - ('a.img b.img', 'a.img a.hdr b.img b.hdr .', 'a b'), - ('a.img b.img', 'a.hdr a b b .', 'a b'), - ('a.img b.img', 'a.hdr a b b.img .', 'a b'), - ('a.img b.img', 'a.hdr a b b.hdr .', 'a b'), - ('a.img b.img', 'a.hdr a b.img b .', 'a b'), - ('a.img b.img', 'a.hdr a b.img b.img .', 'a b'), - ('a.img b.img', 'a.hdr a b.img b.hdr .', 'a b'), - ('a.img b.img', 'a.hdr a.img b b .', 'a b'), - ('a.img b.img', 'a.hdr a.img b b.img .', 'a b'), - ('a.img b.img', 'a.hdr a.img b b.hdr .', 'a b'), - ('a.img b.img', 'a.hdr a.img b.img b .', 'a b'), - ('a.img b.img', 'a.hdr a.img b.img b.img .', 'a b'), - ('a.img b.img', 'a.hdr a.img b.img b.hdr .', 'a b'), - ('a.img b.img', 'a.hdr a.hdr b b .', 'a b'), - ('a.img b.img', 'a.hdr a.hdr b b.img .', 'a b'), - ('a.img b.img', 'a.hdr a.hdr b b.hdr .', 'a b'), - ('a.img b.img', 'a.hdr a.hdr b.img b .', 'a b'), - ('a.img b.img', 'a.hdr a.hdr b.img b.img .', 'a b'), - ('a.img b.img', 'a.hdr a.hdr b.img b.hdr .', 'a b'), - - # Inputs which cause the destination - # to be overwritten - this should be - # ok, the destination should be the - # last specified input. The order of - # files_to_create has to match the - # imcp_args order, otherwise my bodgy - # checkFilesToExpect function will - # break. - ('a.nii a.img', 'a.nii a.img .', 'a'), - ('a.img a.nii', 'a.img a.nii .', 'a'), - ('a.nii a.img a.nii.gz', 'a.nii a.img a.nii.gz .', 'a'), - ('a.nii a.nii.gz a.img ', 'a.nii a.nii.gz a.img .', 'a'), - ('a.img a.nii.gz a.nii ', 'a.img a.nii.gz a.nii .', 'a'), - ('a.img a.nii a.nii.gz', 'a.img a.nii a.nii.gz .', 'a'), - ('a.nii.gz a.img a.nii ', 'a.nii.gz a.img a.nii .', 'a'), - ('a.nii.gz a.nii a.img ', 'a.nii.gz a.nii a.img .', 'a'), - ] - - indir = tempfile.mkdtemp() - outdir = tempfile.mkdtemp() - startdir = os.getcwd() - - try: - - for outputType, reldir in it.product(outputTypes, reldirs): - - os.environ['FSLOUTPUTTYPE'] = outputType - - for files_to_create, imcp_args, files_to_expect in tests: - - imageHashes = [] - - print() - print('files_to_create: ', files_to_create) - print('imcp_args: ', imcp_args) - print('files_to_expect: ', files_to_expect) - - for i, fname in enumerate(files_to_create.split()): - imageHashes.append(makeImage(op.join(indir, fname))) - - imcp_args = imcp_args.split() - - tindir = indir - toutdir = outdir - - if reldir == 'neutral': reldir = startdir - elif reldir == 'indir': reldir = tindir - elif reldir == 'outdir': reldir = toutdir - elif reldir == 'samedir': - reldir = tindir - toutdir = tindir - - if not move: - - infiles = os.listdir(tindir) - - files_to_expect = files_to_expect + ' ' + \ - ' '.join(infiles) - - for inf in infiles: - img = nib.load(op.join(tindir, inf), - mmap=False) - imghash = hash(img.get_data().tobytes()) - img = None - imageHashes.append(imghash) - - print('adj files_to_expect: ', files_to_expect) - - os.chdir(reldir) - - imcp_args[:-1] = [op.join(tindir, a) for a in imcp_args[:-1]] - imcp_args[ -1] = op.join(toutdir, imcp_args[-1]) - - for i, a in enumerate(imcp_args): - if op.splitdrive(a)[0] == op.splitdrive(reldir)[0]: - imcp_args[i] = op.relpath(a, reldir) - - print('indir before: ', os.listdir(tindir)) - print('outdir before: ', os.listdir(toutdir)) - - if move: result = immv_script.main(imcp_args) - else: result = imcp_script.main(imcp_args) - - print('indir after: ', os.listdir(tindir)) - print('outdir after: ', os.listdir(toutdir)) - - assert result == 0 - - checkFilesToExpect( - files_to_expect, toutdir, outputType, imageHashes) - - # too hard if indir == outdir - if move and tindir != toutdir: - infiles = os.listdir(tindir) - infiles = [f for f in infiles if op.isfile(f)] - infiles = [f for f in infiles if op.isfile(f)] - assert len(infiles) == 0 - - cleardir(indir) - cleardir(outdir) - - finally: - os.chdir(startdir) - shutil.rmtree(indir) - shutil.rmtree(outdir) - - -@pytest.mark.noroottest -def test_imcp_script_shouldFail(move=False): - - # - len(srcs) > 1 and dest is not dir - # - input not readable - # - move=True and input not deleteable - # - ambiguous inputs - # - input is incomplete pair (e.g. .hdr - # without corresponding .img) - - # a.img - # a.hdr - # a.nii - # - # FAIL: imcp a dest - - # (files_to_create, imcp_args[, preproc]) - tests = [ - - # non-existent input - ('', 'a b'), - ('a.img', 'b.img a'), - - # dest is non-existent dir - ('a.img', 'a.img non_existent_dir/'), - - # len(srcs) > 1, but dest is not dir - ('a.img b.img', 'a b c.img'), - - # destination not writeable - ('a.img b.img', 'a b ./readonly_dir', 'mkdir outdir/readonly_dir; chmod a-wx outdir/readonly_dir'), - ('a.img', 'a b', 'mkdir outdir/b.nii.gz; chmod a-wx outdir/b.nii.gz'), - - # input not readable - ('a.img', 'a b', 'chmod a-rwx indir/a.img'), - - # ambiguous input - ('a.img a.nii', 'a b'), - - # input is part of incomplete pair - ('a.img', 'a b', 'rm indir/a.hdr'), - ('a.img', 'a.img b', 'rm indir/a.hdr'), - ('a.img', 'a.hdr b', 'rm indir/a.hdr'), - ('a.img', 'a b', 'rm indir/a.img'), - ('a.img', 'a.img b', 'rm indir/a.img'), - ('a.img', 'a.hdr b', 'rm indir/a.img'), - ] - - if move: - tests = tests + [ - # Input not deletable - ('a.img', 'a b', 'chmod a-wx indir'), - ('a.img', 'a b', 'chmod a-wx indir'), - ('a.nii', 'a b', 'chmod a-wx indir') - ] - - indir = tempfile.mkdtemp() - outdir = tempfile.mkdtemp() - - try: - for test in tests: - - files_to_create = test[0] - imcp_args = test[1] - - if len(test) == 3: preproc = test[2] - else: preproc = None - - files_to_create = files_to_create.split() - imcp_args = imcp_args .split() - - for fname in files_to_create: - makeImage(op.join(indir, fname)) - - imcp_args[:-1] = [op.join(indir, a) for a in imcp_args[:-1]] - imcp_args[ -1] = op.join(outdir, imcp_args[-1]) - - if preproc is not None: - for cmd in preproc.split(';'): - cmd = cmd.replace('indir', indir).replace('outdir', outdir) - sp.call(cmd.split()) - - print('calling {} {}'.format('immv' if move else 'imcp', - ' '.join(imcp_args))) - - print('indir before: {}'.format(os.listdir(indir))) - print('out dir before: {}'.format(os.listdir(outdir))) - - if move: result = immv_script.main(imcp_args) - else: result = imcp_script.main(imcp_args) - - print('indir after: {}'.format(os.listdir(indir))) - print('out dir after: {}'.format(os.listdir(outdir))) - - assert result != 0 - - sp.call('chmod u+rwx {}'.format(indir) .split()) - sp.call('chmod u+rwx {}'.format(outdir).split()) - - cleardir(indir) - cleardir(outdir) - - finally: - shutil.rmtree(indir) - shutil.rmtree(outdir) - - # Other failure cases - if move: assert immv_script.main() != 0 - else: assert imcp_script.main() != 0 - if move: assert immv_script.main([]) != 0 - else: assert imcp_script.main([]) != 0 - if move: assert immv_script.main(['wa']) != 0 - else: assert imcp_script.main(['wa']) != 0 - - - -def test_immv_script_shouldPass(): - test_imcp_script_shouldPass(move=True) - - -@pytest.mark.noroottest -def test_immv_script_shouldFail(): - test_imcp_script_shouldFail(move=True) - - def test_imcp_shouldPass(move=False): @@ -731,27 +314,3 @@ def test_imcp_shouldPass(move=False): def test_immv_shouldPass(): test_imcp_shouldPass(move=True) - -def test_imcp_badExt(): - with tempdir(): - - with open('file.nii.gz', 'wt') as f: - f.write('1') - - result = imcp_script.main(['file.nii', 'dest']) - - assert result == 0 - assert op.exists('dest.nii.gz') - - - -def test_immv_badExt(): - with tempdir(): - - with open('file.nii.gz', 'wt') as f: - f.write('1') - - result = immv_script.main(['file.nii', 'dest']) - - assert result == 0 - assert op.exists('dest.nii.gz') diff --git a/tests/test_scripts/__init__.py b/tests/test_scripts/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/test_atlasq_list_summary.py b/tests/test_scripts/test_atlasq_list_summary.py similarity index 100% rename from tests/test_atlasq_list_summary.py rename to tests/test_scripts/test_atlasq_list_summary.py diff --git a/tests/test_atlasq_ohi.py b/tests/test_scripts/test_atlasq_ohi.py similarity index 100% rename from tests/test_atlasq_ohi.py rename to tests/test_scripts/test_atlasq_ohi.py diff --git a/tests/test_atlasq_query.py b/tests/test_scripts/test_atlasq_query.py similarity index 100% rename from tests/test_atlasq_query.py rename to tests/test_scripts/test_atlasq_query.py diff --git a/tests/test_fsl_ents.py b/tests/test_scripts/test_fsl_ents.py similarity index 100% rename from tests/test_fsl_ents.py rename to tests/test_scripts/test_fsl_ents.py diff --git a/tests/test_scripts/test_imglob.py b/tests/test_scripts/test_imglob.py new file mode 100644 index 0000000000000000000000000000000000000000..0f8e934509ce68359d17a8a8794bbaaa47f1a691 --- /dev/null +++ b/tests/test_scripts/test_imglob.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +import mock + +import fsl.scripts.imglob as imglob + +from .. import testdir +from .. import CaptureStdout + + +def test_imglob_script_shouldPass(): + + # (files to create, args, expected) + tests = [ + ('file.hdr file.img', 'file', 'file'), + ('file.hdr file.img', '-extension file', 'file.hdr'), + ('file.hdr file.img', '-extensions file', 'file.hdr file.img'), + ('file.hdr file.img', 'file.hdr', 'file'), + ('file.hdr file.img', ' -extension file.hdr', 'file.hdr'), + ('file.hdr file.img', '-extensions file.hdr', 'file.hdr file.img'), + ('file.hdr file.img', 'file.img', 'file'), + ('file.hdr file.img', '-extension file.img', 'file.hdr'), + ('file.hdr file.img', '-extensions file.img', 'file.hdr file.img'), + ('file.hdr file.img', 'file.hdr file.img', 'file'), + ('file.hdr file.img', '-extension file.hdr file.img', 'file.hdr'), + ('file.hdr file.img', '-extensions file.hdr file.img', 'file.hdr file.img'), + ('file.hdr file.img', 'file file.img', 'file'), + ('file.hdr file.img', '-extension file file.img', 'file.hdr'), + ('file.hdr file.img', '-extensions file file.img', 'file.hdr file.img'), + + # no file or incomplete prefix + ('file.hdr file.img', 'bag', ''), + ('file.hdr file.img', '-extension bag', ''), + ('file.hdr file.img', '-extensions bag', ''), + ('file.hdr file.img', 'fi', ''), + ('file.hdr file.img', '-extension fi', ''), + ('file.hdr file.img', '-extensions fi', ''), + ] + + capture = CaptureStdout() + + for to_create, args, expected in tests: + with testdir(to_create.split()) as td: + + capture.reset() + + with capture: + assert imglob.main(args.split()) == 0 + + assert capture.stdout.strip().split() == expected.split() + + +def test_imglob_script_shouldFail(): + + capture = CaptureStdout() + + with capture: + assert imglob.main([]) != 0 + + assert capture.stdout.strip().lower().startswith('usage:') + + with capture, mock.patch('sys.argv', ['imglob']): + assert imglob.main() != 0 + + assert capture.stdout.strip().lower().startswith('usage:') diff --git a/tests/test_scripts/test_immv_imcp.py b/tests/test_scripts/test_immv_imcp.py new file mode 100644 index 0000000000000000000000000000000000000000..607a7da5d761d69c824f5d85f27751b8bf5a395d --- /dev/null +++ b/tests/test_scripts/test_immv_imcp.py @@ -0,0 +1,465 @@ +#!/usr/bin/env python + + + +import os.path as op +import itertools as it +import subprocess as sp +import os +import shutil +import tempfile + +import pytest + +import nibabel as nib + +from fsl.utils.tempdir import tempdir +import fsl.scripts.imcp as imcp_script +import fsl.scripts.immv as immv_script + +from .. import cleardir +from ..test_immv_imcp import makeImage, checkImageHash, checkFilesToExpect + + +real_print = print + +def print(*args, **kwargs): + pass + + + + + +def test_imcp_script_shouldPass(move=False): + + + # The imcp/immv scripts should honour the + # FSLOUTPUTTYPE env var. If it is unset + # or invalid - '' in this case), they + # should produce .nii.gz + outputTypes = ['NIFTI', 'NIFTI_PAIR', 'NIFTI_GZ', ''] + reldirs = ['neutral', 'samedir', 'indir', 'outdir'] + + # Test tuples have the following structure (each + # item is a string which will be split on spaces): + # + # (files_to_create, imcp_args, files_to_expect) + # + # The files_to_expect is a list of + # prefixes - the suffix(es) is(are) + # determined by the current outputType + # + # If multiple files are being copied, the + # files_to_create and files_to_expect lists + # have to be in the same order. + tests = [ + + ('a.nii', 'a b', 'b'), + ('a.nii', 'a.nii b', 'b'), + ('a.nii', 'a b.nii', 'b'), + ('a.nii', 'a.nii b.nii', 'b'), + ('a.nii', 'a .', 'a'), + ('a.nii', 'a.nii .', 'a'), + ('a.nii', 'a b.hdr', 'b'), + ('a.nii', 'a b.img', 'b'), + ('a.nii', 'a b.nii.gz', 'b'), + ('a.nii', 'a.nii b.hdr', 'b'), + ('a.nii', 'a.nii b.img', 'b'), + ('a.nii', 'a.nii b.nii.gz', 'b'), + + ('a.nii.gz', 'a b', 'b'), + ('a.nii.gz', 'a.nii.gz b', 'b'), + ('a.nii.gz', 'a b.nii.gz', 'b'), + ('a.nii.gz', 'a.nii.gz b.nii.gz', 'b'), + ('a.nii.gz', 'a .', 'a'), + ('a.nii.gz', 'a.nii.gz .', 'a'), + ('a.nii.gz', 'a b.hdr', 'b'), + ('a.nii.gz', 'a b.img', 'b'), + ('a.nii.gz', 'a b.nii', 'b'), + ('a.nii.gz', 'a.nii.gz b.hdr', 'b'), + ('a.nii.gz', 'a.nii.gz b.img', 'b'), + ('a.nii.gz', 'a.nii.gz b.nii', 'b'), + + ('a.img', 'a b', 'b'), + ('a.img', 'a b.img', 'b'), + ('a.img', 'a b.hdr', 'b'), + ('a.img', 'a .', 'a'), + ('a.img', 'a.img b', 'b'), + ('a.img', 'a.img b.img', 'b'), + ('a.img', 'a.img b.hdr', 'b'), + ('a.img', 'a.img .', 'a'), + ('a.img', 'a.hdr b', 'b'), + ('a.img', 'a.hdr b.img', 'b'), + ('a.img', 'a.hdr b.hdr', 'b'), + ('a.img', 'a.hdr .', 'a'), + + ('a.img', 'a b.nii', 'b'), + ('a.img', 'a b.nii.gz', 'b'), + ('a.img', 'a .', 'a'), + ('a.img', 'a.hdr b.nii', 'b'), + ('a.img', 'a.hdr b.nii.gz', 'b'), + ('a.img', 'a.hdr .', 'a'), + ('a.img', 'a.img b.nii', 'b'), + ('a.img', 'a.img b.nii.gz', 'b'), + ('a.img', 'a.img .', 'a'), + + ('a.nii b.nii', 'a b .', 'a b'), + ('a.nii b.nii', 'a b.nii .', 'a b'), + ('a.nii b.nii', 'a.nii b .', 'a b'), + ('a.nii b.nii', 'a.nii b.nii .', 'a b'), + + ('a.img b.img', 'a b .', 'a b'), + ('a.img b.img', 'a b.img .', 'a b'), + ('a.img b.img', 'a b.hdr .', 'a b'), + ('a.img b.img', 'a.img b .', 'a b'), + ('a.img b.img', 'a.img b.img .', 'a b'), + ('a.img b.img', 'a.img b.hdr .', 'a b'), + ('a.img b.img', 'a.hdr b .', 'a b'), + ('a.img b.img', 'a.hdr b.img .', 'a b'), + ('a.img b.img', 'a.hdr b.hdr .', 'a b'), + + ('a.nii.gz b.nii.gz', 'a b .', 'a b'), + ('a.nii.gz b.nii.gz', 'a b.nii.gz .', 'a b'), + ('a.nii.gz b.nii.gz', 'a.nii.gz b .', 'a b'), + ('a.nii.gz b.nii.gz', 'a.nii.gz b.nii.gz .', 'a b'), + + # Heterogenous inputs + ('a.nii b.nii.gz', 'a b .', 'a b'), + ('a.nii b.nii.gz', 'a b.nii.gz .', 'a b'), + ('a.nii b.nii.gz', 'a.nii b .', 'a b'), + ('a.nii b.nii.gz', 'a.nii b.nii.gz .', 'a b'), + ('a.nii b.img', 'a b .', 'a b'), + ('a.nii b.img', 'a b.img .', 'a b'), + ('a.nii b.img', 'a b.hdr .', 'a b'), + ('a.nii b.img', 'a.nii b .', 'a b'), + ('a.nii b.img', 'a.nii b.img .', 'a b'), + ('a.nii b.img', 'a.nii b.hdr .', 'a b'), + ('a.img b.nii', 'a b .', 'a b'), + ('a.img b.nii', 'a b.nii .', 'a b'), + ('a.img b.nii', 'a.img b .', 'a b'), + ('a.img b.nii', 'a.img b.nii .', 'a b'), + ('a.img b.nii', 'a.hdr b .', 'a b'), + ('a.img b.nii', 'a.hdr b.nii .', 'a b'), + + # Duplicate inputs + ('a.img', 'a a .', 'a'), + ('a.img', 'a a.img .', 'a'), + ('a.img', 'a a.hdr .', 'a'), + ('a.img', 'a.img a .', 'a'), + ('a.img', 'a.img a.img .', 'a'), + ('a.img', 'a.img a.hdr .', 'a'), + ('a.img', 'a.hdr a .', 'a'), + ('a.img', 'a.hdr a.img .', 'a'), + ('a.img', 'a.hdr a.hdr .', 'a'), + + ('a.img b.img', 'a a b b .', 'a b'), + ('a.img b.img', 'a a b b.img .', 'a b'), + ('a.img b.img', 'a a b b.hdr .', 'a b'), + ('a.img b.img', 'a a b.img b .', 'a b'), + ('a.img b.img', 'a a b.img b.img .', 'a b'), + ('a.img b.img', 'a a b.img b.hdr .', 'a b'), + ('a.img b.img', 'a a.img b b .', 'a b'), + ('a.img b.img', 'a a.img b b.img .', 'a b'), + ('a.img b.img', 'a a.img b b.hdr .', 'a b'), + ('a.img b.img', 'a a.img b.img b .', 'a b'), + ('a.img b.img', 'a a.img b.img b.img .', 'a b'), + ('a.img b.img', 'a a.img b.img b.hdr .', 'a b'), + ('a.img b.img', 'a a.hdr b b .', 'a b'), + ('a.img b.img', 'a a.hdr b b.img .', 'a b'), + ('a.img b.img', 'a a.hdr b b.hdr .', 'a b'), + ('a.img b.img', 'a a.hdr b.img b .', 'a b'), + ('a.img b.img', 'a a.hdr b.img b.img .', 'a b'), + ('a.img b.img', 'a a.hdr b.img b.hdr .', 'a b'), + ('a.img b.img', 'a.img a b b .', 'a b'), + ('a.img b.img', 'a.img a b b.img .', 'a b'), + ('a.img b.img', 'a.img a b b.hdr .', 'a b'), + ('a.img b.img', 'a.img a b.img b .', 'a b'), + ('a.img b.img', 'a.img a b.img b.img .', 'a b'), + ('a.img b.img', 'a.img a b.img b.hdr .', 'a b'), + ('a.img b.img', 'a.img a.img b b .', 'a b'), + ('a.img b.img', 'a.img a.img b b.img .', 'a b'), + ('a.img b.img', 'a.img a.img b b.hdr .', 'a b'), + ('a.img b.img', 'a.img a.img b.img b .', 'a b'), + ('a.img b.img', 'a.img a.img b.img b.img .', 'a b'), + ('a.img b.img', 'a.img a.img b.img b.hdr .', 'a b'), + ('a.img b.img', 'a.img a.hdr b b .', 'a b'), + ('a.img b.img', 'a.img a.hdr b b.img .', 'a b'), + ('a.img b.img', 'a.img a.hdr b b.hdr .', 'a b'), + ('a.img b.img', 'a.img a.hdr b.img b .', 'a b'), + ('a.img b.img', 'a.img a.hdr b.img b.img .', 'a b'), + ('a.img b.img', 'a.img a.hdr b.img b.hdr .', 'a b'), + ('a.img b.img', 'a.hdr a b b .', 'a b'), + ('a.img b.img', 'a.hdr a b b.img .', 'a b'), + ('a.img b.img', 'a.hdr a b b.hdr .', 'a b'), + ('a.img b.img', 'a.hdr a b.img b .', 'a b'), + ('a.img b.img', 'a.hdr a b.img b.img .', 'a b'), + ('a.img b.img', 'a.hdr a b.img b.hdr .', 'a b'), + ('a.img b.img', 'a.hdr a.img b b .', 'a b'), + ('a.img b.img', 'a.hdr a.img b b.img .', 'a b'), + ('a.img b.img', 'a.hdr a.img b b.hdr .', 'a b'), + ('a.img b.img', 'a.hdr a.img b.img b .', 'a b'), + ('a.img b.img', 'a.hdr a.img b.img b.img .', 'a b'), + ('a.img b.img', 'a.hdr a.img b.img b.hdr .', 'a b'), + ('a.img b.img', 'a.hdr a.hdr b b .', 'a b'), + ('a.img b.img', 'a.hdr a.hdr b b.img .', 'a b'), + ('a.img b.img', 'a.hdr a.hdr b b.hdr .', 'a b'), + ('a.img b.img', 'a.hdr a.hdr b.img b .', 'a b'), + ('a.img b.img', 'a.hdr a.hdr b.img b.img .', 'a b'), + ('a.img b.img', 'a.hdr a.hdr b.img b.hdr .', 'a b'), + + # Inputs which cause the destination + # to be overwritten - this should be + # ok, the destination should be the + # last specified input. The order of + # files_to_create has to match the + # imcp_args order, otherwise my bodgy + # checkFilesToExpect function will + # break. + ('a.nii a.img', 'a.nii a.img .', 'a'), + ('a.img a.nii', 'a.img a.nii .', 'a'), + ('a.nii a.img a.nii.gz', 'a.nii a.img a.nii.gz .', 'a'), + ('a.nii a.nii.gz a.img ', 'a.nii a.nii.gz a.img .', 'a'), + ('a.img a.nii.gz a.nii ', 'a.img a.nii.gz a.nii .', 'a'), + ('a.img a.nii a.nii.gz', 'a.img a.nii a.nii.gz .', 'a'), + ('a.nii.gz a.img a.nii ', 'a.nii.gz a.img a.nii .', 'a'), + ('a.nii.gz a.nii a.img ', 'a.nii.gz a.nii a.img .', 'a'), + ] + + indir = tempfile.mkdtemp() + outdir = tempfile.mkdtemp() + startdir = os.getcwd() + + try: + + for outputType, reldir in it.product(outputTypes, reldirs): + + os.environ['FSLOUTPUTTYPE'] = outputType + + for files_to_create, imcp_args, files_to_expect in tests: + + imageHashes = [] + + print() + print('files_to_create: ', files_to_create) + print('imcp_args: ', imcp_args) + print('files_to_expect: ', files_to_expect) + + for i, fname in enumerate(files_to_create.split()): + imageHashes.append(makeImage(op.join(indir, fname))) + + imcp_args = imcp_args.split() + + tindir = indir + toutdir = outdir + + if reldir == 'neutral': reldir = startdir + elif reldir == 'indir': reldir = tindir + elif reldir == 'outdir': reldir = toutdir + elif reldir == 'samedir': + reldir = tindir + toutdir = tindir + + if not move: + + infiles = os.listdir(tindir) + + files_to_expect = files_to_expect + ' ' + \ + ' '.join(infiles) + + for inf in infiles: + img = nib.load(op.join(tindir, inf), + mmap=False) + imghash = hash(img.get_data().tobytes()) + img = None + imageHashes.append(imghash) + + print('adj files_to_expect: ', files_to_expect) + + os.chdir(reldir) + + imcp_args[:-1] = [op.join(tindir, a) for a in imcp_args[:-1]] + imcp_args[ -1] = op.join(toutdir, imcp_args[-1]) + + for i, a in enumerate(imcp_args): + if op.splitdrive(a)[0] == op.splitdrive(reldir)[0]: + imcp_args[i] = op.relpath(a, reldir) + + print('indir before: ', os.listdir(tindir)) + print('outdir before: ', os.listdir(toutdir)) + + if move: result = immv_script.main(imcp_args) + else: result = imcp_script.main(imcp_args) + + print('indir after: ', os.listdir(tindir)) + print('outdir after: ', os.listdir(toutdir)) + + assert result == 0 + + checkFilesToExpect( + files_to_expect, toutdir, outputType, imageHashes) + + # too hard if indir == outdir + if move and tindir != toutdir: + infiles = os.listdir(tindir) + infiles = [f for f in infiles if op.isfile(f)] + infiles = [f for f in infiles if op.isfile(f)] + assert len(infiles) == 0 + + cleardir(indir) + cleardir(outdir) + + finally: + os.chdir(startdir) + shutil.rmtree(indir) + shutil.rmtree(outdir) + + +@pytest.mark.noroottest +def test_imcp_script_shouldFail(move=False): + + # - len(srcs) > 1 and dest is not dir + # - input not readable + # - move=True and input not deleteable + # - ambiguous inputs + # - input is incomplete pair (e.g. .hdr + # without corresponding .img) + + # a.img + # a.hdr + # a.nii + # + # FAIL: imcp a dest + + # (files_to_create, imcp_args[, preproc]) + tests = [ + + # non-existent input + ('', 'a b'), + ('a.img', 'b.img a'), + + # dest is non-existent dir + ('a.img', 'a.img non_existent_dir/'), + + # len(srcs) > 1, but dest is not dir + ('a.img b.img', 'a b c.img'), + + # destination not writeable + ('a.img b.img', 'a b ./readonly_dir', 'mkdir outdir/readonly_dir; chmod a-wx outdir/readonly_dir'), + ('a.img', 'a b', 'mkdir outdir/b.nii.gz; chmod a-wx outdir/b.nii.gz'), + + # input not readable + ('a.img', 'a b', 'chmod a-rwx indir/a.img'), + + # ambiguous input + ('a.img a.nii', 'a b'), + + # input is part of incomplete pair + ('a.img', 'a b', 'rm indir/a.hdr'), + ('a.img', 'a.img b', 'rm indir/a.hdr'), + ('a.img', 'a.hdr b', 'rm indir/a.hdr'), + ('a.img', 'a b', 'rm indir/a.img'), + ('a.img', 'a.img b', 'rm indir/a.img'), + ('a.img', 'a.hdr b', 'rm indir/a.img'), + ] + + if move: + tests = tests + [ + # Input not deletable + ('a.img', 'a b', 'chmod a-wx indir'), + ('a.img', 'a b', 'chmod a-wx indir'), + ('a.nii', 'a b', 'chmod a-wx indir') + ] + + indir = tempfile.mkdtemp() + outdir = tempfile.mkdtemp() + + try: + for test in tests: + + files_to_create = test[0] + imcp_args = test[1] + + if len(test) == 3: preproc = test[2] + else: preproc = None + + files_to_create = files_to_create.split() + imcp_args = imcp_args .split() + + for fname in files_to_create: + makeImage(op.join(indir, fname)) + + imcp_args[:-1] = [op.join(indir, a) for a in imcp_args[:-1]] + imcp_args[ -1] = op.join(outdir, imcp_args[-1]) + + if preproc is not None: + for cmd in preproc.split(';'): + cmd = cmd.replace('indir', indir).replace('outdir', outdir) + sp.call(cmd.split()) + + print('calling {} {}'.format('immv' if move else 'imcp', + ' '.join(imcp_args))) + + print('indir before: {}'.format(os.listdir(indir))) + print('out dir before: {}'.format(os.listdir(outdir))) + + if move: result = immv_script.main(imcp_args) + else: result = imcp_script.main(imcp_args) + + print('indir after: {}'.format(os.listdir(indir))) + print('out dir after: {}'.format(os.listdir(outdir))) + + assert result != 0 + + sp.call('chmod u+rwx {}'.format(indir) .split()) + sp.call('chmod u+rwx {}'.format(outdir).split()) + + cleardir(indir) + cleardir(outdir) + + finally: + shutil.rmtree(indir) + shutil.rmtree(outdir) + + # Other failure cases + if move: assert immv_script.main() != 0 + else: assert imcp_script.main() != 0 + if move: assert immv_script.main([]) != 0 + else: assert imcp_script.main([]) != 0 + if move: assert immv_script.main(['wa']) != 0 + else: assert imcp_script.main(['wa']) != 0 + + + +def test_immv_script_shouldPass(): + test_imcp_script_shouldPass(move=True) + + +@pytest.mark.noroottest +def test_immv_script_shouldFail(): + test_imcp_script_shouldFail(move=True) + + + +def test_imcp_badExt(): + with tempdir(): + + with open('file.nii.gz', 'wt') as f: + f.write('1') + + result = imcp_script.main(['file.nii', 'dest']) + + assert result == 0 + assert op.exists('dest.nii.gz') + + + +def test_immv_badExt(): + with tempdir(): + + with open('file.nii.gz', 'wt') as f: + f.write('1') + + result = immv_script.main(['file.nii', 'dest']) + + assert result == 0 + assert op.exists('dest.nii.gz')