Mercurial > repos > guerler > springsuite
diff planemo/lib/python3.7/site-packages/cwltool/tests/test_examples.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:18:57 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/planemo/lib/python3.7/site-packages/cwltool/tests/test_examples.py Fri Jul 31 00:18:57 2020 -0400 @@ -0,0 +1,1048 @@ +import json +import logging +import os +import stat +import sys +from io import BytesIO, StringIO +import pytest +from typing_extensions import Text + +import schema_salad.validate + +import cwltool.checker +import cwltool.expression as expr +import cwltool.factory +import cwltool.pathmapper +import cwltool.process +import cwltool.workflow +from cwltool.context import RuntimeContext +from cwltool.errors import WorkflowException +from cwltool.main import main +from cwltool.utils import onWindows +from cwltool.resolver import Path +from cwltool.process import CWL_IANA +from cwltool.sandboxjs import JavascriptException +from .util import (get_data, get_main_output, get_windows_safe_factory, subprocess, + needs_docker, working_directory, needs_singularity, temp_dir, windows_needs_docker) + +import six + +try: + reload +except: # pylint: disable=bare-except + try: + from imp import reload + except: + from importlib import reload + +sys.argv = [''] + +expression_match = [ + ("(foo)", True), + ("(foo.bar)", True), + ("(foo['bar'])", True), + ("(foo[\"bar\"])", True), + ("(foo.bar.baz)", True), + ("(foo['bar'].baz)", True), + ("(foo['bar']['baz'])", True), + ("(foo['b\\'ar']['baz'])", True), + ("(foo['b ar']['baz'])", True), + ("(foo_bar)", True), + + ("(foo.[\"bar\"])", False), + ("(.foo[\"bar\"])", False), + ("(foo [\"bar\"])", False), + ("( foo[\"bar\"])", False), + ("(foo[bar].baz)", False), + ("(foo['bar\"].baz)", False), + ("(foo['bar].baz)", False), + ("{foo}", False), + ("(foo.bar", False), + ("foo.bar)", False), + ("foo.b ar)", False), + ("foo.b\'ar)", False), + ("(foo+bar", False), + ("(foo bar", False) +] + + +@pytest.mark.parametrize('expression,expected', expression_match) +def test_expression_match(expression, expected): + match = expr.param_re.match(expression) + assert (match is not None) == expected + + +interpolate_input = { + "foo": { + "bar": { + "baz": "zab1" + }, + "b ar": { + "baz": 2 + }, + "b'ar": { + "baz": True + }, + 'b"ar': { + "baz": None + } + }, + "lst": ["A", "B"] +} + +interpolate_parameters = [ + ("$(foo)", interpolate_input["foo"]), + + ("$(foo.bar)", interpolate_input["foo"]["bar"]), + ("$(foo['bar'])", interpolate_input["foo"]["bar"]), + ("$(foo[\"bar\"])", interpolate_input["foo"]["bar"]), + + ("$(foo.bar.baz)", interpolate_input['foo']['bar']['baz']), + ("$(foo['bar'].baz)", interpolate_input['foo']['bar']['baz']), + ("$(foo['bar'][\"baz\"])", interpolate_input['foo']['bar']['baz']), + ("$(foo.bar['baz'])", interpolate_input['foo']['bar']['baz']), + + ("$(foo['b\\'ar'].baz)", True), + ("$(foo[\"b'ar\"].baz)", True), + ("$(foo['b\\\"ar'].baz)", None), + + ("$(lst[0])", "A"), + ("$(lst[1])", "B"), + ("$(lst.length)", 2), + ("$(lst['length'])", 2), + + ("-$(foo.bar)", """-{"baz": "zab1"}"""), + ("-$(foo['bar'])", """-{"baz": "zab1"}"""), + ("-$(foo[\"bar\"])", """-{"baz": "zab1"}"""), + + ("-$(foo.bar.baz)", "-zab1"), + ("-$(foo['bar'].baz)", "-zab1"), + ("-$(foo['bar'][\"baz\"])", "-zab1"), + ("-$(foo.bar['baz'])", "-zab1"), + + ("-$(foo['b ar'].baz)", "-2"), + ("-$(foo['b\\'ar'].baz)", "-true"), + ("-$(foo[\"b\\'ar\"].baz)", "-true"), + ("-$(foo['b\\\"ar'].baz)", "-null"), + + ("$(foo.bar) $(foo.bar)", """{"baz": "zab1"} {"baz": "zab1"}"""), + ("$(foo['bar']) $(foo['bar'])", """{"baz": "zab1"} {"baz": "zab1"}"""), + ("$(foo[\"bar\"]) $(foo[\"bar\"])", """{"baz": "zab1"} {"baz": "zab1"}"""), + + ("$(foo.bar.baz) $(foo.bar.baz)", "zab1 zab1"), + ("$(foo['bar'].baz) $(foo['bar'].baz)", "zab1 zab1"), + ("$(foo['bar'][\"baz\"]) $(foo['bar'][\"baz\"])", "zab1 zab1"), + ("$(foo.bar['baz']) $(foo.bar['baz'])", "zab1 zab1"), + + ("$(foo['b ar'].baz) $(foo['b ar'].baz)", "2 2"), + ("$(foo['b\\'ar'].baz) $(foo['b\\'ar'].baz)", "true true"), + ("$(foo[\"b\\'ar\"].baz) $(foo[\"b\\'ar\"].baz)", "true true"), + ("$(foo['b\\\"ar'].baz) $(foo['b\\\"ar'].baz)", "null null") +] + + +@pytest.mark.parametrize('pattern,expected', interpolate_parameters) +def test_expression_interpolate(pattern, expected): + assert expr.interpolate(pattern, interpolate_input) == expected + +interpolate_bad_parameters = [ + ("$(fooz)"), + ("$(foo.barz)"), + ("$(foo['barz'])"), + ("$(foo[\"barz\"])"), + + ("$(foo.bar.bazz)"), + ("$(foo['bar'].bazz)"), + ("$(foo['bar'][\"bazz\"])"), + ("$(foo.bar['bazz'])"), + + ("$(foo['b\\'ar'].bazz)"), + ("$(foo[\"b'ar\"].bazz)"), + ("$(foo['b\\\"ar'].bazz)"), + + ("$(lst[O])"), # not "0" the number, but the letter O + ("$(lst[2])"), + ("$(lst.lengthz)"), + ("$(lst['lengthz'])"), + + ("-$(foo.barz)"), + ("-$(foo['barz'])"), + ("-$(foo[\"barz\"])"), + + ("-$(foo.bar.bazz)"), + ("-$(foo['bar'].bazz)"), + ("-$(foo['bar'][\"bazz\"])"), + ("-$(foo.bar['bazz'])"), + + ("-$(foo['b ar'].bazz)"), + ("-$(foo['b\\'ar'].bazz)"), + ("-$(foo[\"b\\'ar\"].bazz)"), + ("-$(foo['b\\\"ar'].bazz)"), +] + +@pytest.mark.parametrize('pattern', interpolate_bad_parameters) +def test_expression_interpolate_failures(pattern): + result = None + try: + result = expr.interpolate(pattern, interpolate_input) + except JavascriptException: + return + assert false, 'Should have produced a JavascriptException, got "{}".'.format(result) + + +@windows_needs_docker +def test_factory(): + factory = get_windows_safe_factory() + echo = factory.make(get_data("tests/echo.cwl")) + + assert echo(inp="foo") == {"out": "foo\n"} + + +def test_factory_bad_outputs(): + factory = cwltool.factory.Factory() + + with pytest.raises(schema_salad.validate.ValidationException): + factory.make(get_data("tests/echo_broken_outputs.cwl")) + + +def test_factory_default_args(): + factory = cwltool.factory.Factory() + + assert factory.runtime_context.use_container is True + assert factory.runtime_context.on_error == "stop" + + +def test_factory_redefined_args(): + runtime_context = RuntimeContext() + runtime_context.use_container = False + runtime_context.on_error = "continue" + factory = cwltool.factory.Factory(runtime_context=runtime_context) + + assert factory.runtime_context.use_container is False + assert factory.runtime_context.on_error == "continue" + + +def test_factory_partial_scatter(): + runtime_context = RuntimeContext() + runtime_context.on_error = "continue" + factory = cwltool.factory.Factory(runtime_context=runtime_context) + + with pytest.raises(cwltool.factory.WorkflowStatus) as err_info: + factory.make(get_data("tests/wf/scatterfail.cwl"))() + + err = err_info.value + assert err.out["out"][0]["checksum"] == 'sha1$e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e' + assert err.out["out"][1] is None + assert err.out["out"][2]["checksum"] == 'sha1$a3db5c13ff90a36963278c6a39e4ee3c22e2a436' + + +def test_factory_partial_output(): + runtime_context = RuntimeContext() + runtime_context.on_error = "continue" + factory = cwltool.factory.Factory(runtime_context=runtime_context) + + with pytest.raises(cwltool.factory.WorkflowStatus) as err_info: + factory.make(get_data("tests/wf/wffail.cwl"))() + + err = err_info.value + assert err.out["out1"]["checksum"] == 'sha1$e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e' + assert err.out["out2"] is None + + +def test_scandeps(): + obj = { + "id": "file:///example/foo.cwl", + "steps": [ + { + "id": "file:///example/foo.cwl#step1", + "inputs": [{ + "id": "file:///example/foo.cwl#input1", + "default": { + "class": "File", + "location": "file:///example/data.txt" + } + }], + "run": { + "id": "file:///example/bar.cwl", + "inputs": [{ + "id": "file:///example/bar.cwl#input2", + "default": { + "class": "Directory", + "location": "file:///example/data2", + "listing": [{ + "class": "File", + "location": "file:///example/data3.txt", + "secondaryFiles": [{ + "class": "File", + "location": "file:///example/data5.txt" + }] + }] + }, + }, { + "id": "file:///example/bar.cwl#input3", + "default": { + "class": "Directory", + "listing": [{ + "class": "File", + "location": "file:///example/data4.txt" + }] + } + }, { + "id": "file:///example/bar.cwl#input4", + "default": { + "class": "File", + "contents": "file literal" + } + }] + } + } + ] + } + + def loadref(base, p): + if isinstance(p, dict): + return p + raise Exception("test case can't load things") + + scanned_deps = cwltool.process.scandeps( + obj["id"], obj, + {"$import", "run"}, + {"$include", "$schemas", "location"}, + loadref) + + scanned_deps.sort(key=lambda k: k["basename"]) + + expected_deps = [ + {"basename": "bar.cwl", + "nameroot": "bar", + "class": "File", + "format": CWL_IANA, + "nameext": ".cwl", + "location": "file:///example/bar.cwl"}, + {"basename": "data.txt", + "nameroot": "data", + "class": "File", + "nameext": ".txt", + "location": "file:///example/data.txt"}, + {"basename": "data2", + "class": "Directory", + "location": "file:///example/data2", + "listing": [ + {"basename": "data3.txt", + "nameroot": "data3", + "class": "File", + "nameext": ".txt", + "location": "file:///example/data3.txt", + "secondaryFiles": [ + {"class": "File", + "basename": "data5.txt", + "location": "file:///example/data5.txt", + "nameext": ".txt", + "nameroot": "data5" + }] + }] + }, { + "basename": "data4.txt", + "nameroot": "data4", + "class": "File", + "nameext": ".txt", + "location": "file:///example/data4.txt" + }] + + assert scanned_deps == expected_deps + + scanned_deps = cwltool.process.scandeps( + obj["id"], obj, + set(("run"), ), + set(), loadref) + + scanned_deps.sort(key=lambda k: k["basename"]) + + expected_deps = [{ + "basename": "bar.cwl", + "nameroot": "bar", + "format": CWL_IANA, + "class": "File", + "nameext": ".cwl", + "location": "file:///example/bar.cwl" + }] + + assert scanned_deps == expected_deps + +def test_trick_scandeps(): + if sys.version_info[0] < 3: + stream = BytesIO() + else: + stream = StringIO() + + main(["--print-deps", "--debug", get_data("tests/wf/trick_defaults.cwl")], stdout=stream) + assert json.loads(stream.getvalue())["secondaryFiles"][0]["location"][:2] != "_:" + + +def test_input_deps(): + if sys.version_info[0] < 3: + stream = BytesIO() + else: + stream = StringIO() + + main(["--print-input-deps", get_data("tests/wf/count-lines1-wf.cwl"), + get_data("tests/wf/wc-job.json")], stdout=stream) + + expected = {"class": "File", + "location": "wc-job.json", + "format": CWL_IANA, + "secondaryFiles": [{"class": "File", + "location": "whale.txt", + "basename": "whale.txt", + "nameroot": "whale", + "nameext": ".txt"}]} + assert json.loads(stream.getvalue()) == expected + + +def test_input_deps_cmdline_opts(): + if sys.version_info[0] < 3: + stream = BytesIO() + else: + stream = StringIO() + + main(["--print-input-deps", + get_data("tests/wf/count-lines1-wf.cwl"), + "--file1", get_data("tests/wf/whale.txt")], stdout=stream) + expected = {"class": "File", + "location": "", + "format": CWL_IANA, + "secondaryFiles": [{"class": "File", + "location": "whale.txt", + "basename": "whale.txt", + "nameroot": "whale", + "nameext": ".txt"}]} + assert json.loads(stream.getvalue()) == expected + + +def test_input_deps_cmdline_opts_relative_deps_cwd(): + if sys.version_info[0] < 3: + stream = BytesIO() + else: + stream = StringIO() + + data_path = get_data("tests/wf/whale.txt") + main(["--print-input-deps", "--relative-deps", "cwd", + get_data("tests/wf/count-lines1-wf.cwl"), + "--file1", data_path], stdout=stream) + + goal = {"class": "File", + "location": "", + "format": CWL_IANA, + "secondaryFiles": [{"class": "File", + "location": str( + Path(os.path.relpath( + data_path, os.path.curdir))), + "basename": "whale.txt", + "nameroot": "whale", + "nameext": ".txt"}]} + assert json.loads(stream.getvalue()) == goal + + +def test_dedupe(): + not_deduped = [ + {"class": "File", + "location": "file:///example/a"}, + {"class": "File", + "location": "file:///example/a"}, + {"class": "File", + "location": "file:///example/d"}, + {"class": "Directory", + "location": "file:///example/c", + "listing": [ + {"class": "File", + "location": "file:///example/d"} + ]} + ] + + expected = [ + {"class": "File", + "location": "file:///example/a"}, + {"class": "Directory", + "location": "file:///example/c", + "listing": [ + {"class": "File", + "location": "file:///example/d"} + ]} + ] + + assert cwltool.pathmapper.dedup(not_deduped) == expected + + +record = { + 'fields': [ + {'type': {'items': 'string', 'type': 'array'}, + 'name': u'file:///home/chapmanb/drive/work/cwl/test_bcbio_cwl/run_info-cwl-workflow/wf-variantcall.cwl#vc_rec/vc_rec/description' + }, + {'type': {'items': 'File', 'type': 'array'}, + 'name': u'file:///home/chapmanb/drive/work/cwl/test_bcbio_cwl/run_info-cwl-workflow/wf-variantcall.cwl#vc_rec/vc_rec/vrn_file' + }], + 'type': 'record', + 'name': u'file:///home/chapmanb/drive/work/cwl/test_bcbio_cwl/run_info-cwl-workflow/wf-variantcall.cwl#vc_rec/vc_rec' +} + +source_to_sink = [ + ('0', + {'items': ['string', 'null'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + True + ), + ('1', + {'items': ['string'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + True + ), + ('2', + {'items': ['string', 'null'], 'type': 'array'}, + {'items': ['string'], 'type': 'array'}, + True + ), + ('3', + {'items': ['string'], 'type': 'array'}, + {'items': ['int'], 'type': 'array'}, + False + ), + ('record 0', + record, record, + True + ), + ('record 1', + record, {'items': 'string', 'type': 'array'}, + False + ) +] + + +@pytest.mark.parametrize('name, source, sink, expected', source_to_sink) +def test_compare_types(name, source, sink, expected): + assert cwltool.workflow.can_assign_src_to_sink(source, sink) == expected, name + + +source_to_sink_strict = [ + ('0', + ['string', 'null'], ['string', 'null'], + True + ), + ('1', + ['string'], ['string', 'null'], + True + ), + ('2', + ['string', 'int'], ['string', 'null'], + False + ), + ('3', + {'items': ['string'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + True + ), + ('4', + {'items': ['string', 'int'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + False + ) +] + + +@pytest.mark.parametrize('name, source, sink, expected', source_to_sink_strict) +def test_compare_types_strict(name, source, sink, expected): + assert cwltool.workflow.can_assign_src_to_sink(source, sink, strict=True) == expected, name + + +typechecks = [ + (['string', 'int'], ['string', 'int', 'null'], + None, None, + "pass" + ), + (['string', 'int'], ['string', 'null'], + None, None, + "warning" + ), + (['File', 'int'], ['string', 'null'], + None, None, + "exception" + ), + ({'items': ['string', 'int'], 'type': 'array'}, + {'items': ['string', 'int', 'null'], 'type': 'array'}, + None, None, + "pass" + ), + ({'items': ['string', 'int'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + None, None, + "warning" + ), + ({'items': ['File', 'int'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + None, None, + "exception" + ), + # check linkMerge when sinktype is not an array + (['string', 'int'], ['string', 'int', 'null'], + "merge_nested", None, + "exception" + ), + # check linkMerge: merge_nested + (['string', 'int'], + {'items': ['string', 'int', 'null'], 'type': 'array'}, + "merge_nested", None, + "pass" + ), + (['string', 'int'], + {'items': ['string', 'null'], 'type': 'array'}, + "merge_nested", None, + "warning" + ), + (['File', 'int'], + {'items': ['string', 'null'], 'type': 'array'}, + "merge_nested", None, + "exception" + ), + # check linkMerge: merge_nested and sinktype is "Any" + (['string', 'int'], "Any", + "merge_nested", None, + "pass" + ), + # check linkMerge: merge_flattened + (['string', 'int'], + {'items': ['string', 'int', 'null'], 'type': 'array'}, + "merge_flattened", None, + "pass" + ), + (['string', 'int'], + {'items': ['string', 'null'], 'type': 'array'}, + "merge_flattened", None, + "warning" + ), + (['File', 'int'], + {'items': ['string', 'null'], 'type': 'array'}, + "merge_flattened", None, + "exception" + ), + ({'items': ['string', 'int'], 'type': 'array'}, + {'items': ['string', 'int', 'null'], 'type': 'array'}, + "merge_flattened", None, + "pass" + ), + ({'items': ['string', 'int'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + "merge_flattened", None, + "warning" + ), + ({'items': ['File', 'int'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + "merge_flattened", None, + "exception"), + # check linkMerge: merge_flattened and sinktype is "Any" + (['string', 'int'], "Any", + "merge_flattened", None, + "pass" + ), + ({'items': ['string', 'int'], 'type': 'array'}, "Any", + "merge_flattened", None, + "pass" + ), + # check linkMerge: merge_flattened when srctype is a list + ([{'items': 'string', 'type': 'array'}], + {'items': 'string', 'type': 'array'}, + "merge_flattened", None, + "pass" + ), + # check valueFrom + ({'items': ['File', 'int'], 'type': 'array'}, + {'items': ['string', 'null'], 'type': 'array'}, + "merge_flattened", "special value", + "pass" + ) +] + + +@pytest.mark.parametrize('src_type,sink_type,link_merge,value_from,expected_type', typechecks) +def test_typechecking(src_type, sink_type, link_merge, value_from, expected_type): + assert cwltool.checker.check_types( + src_type, sink_type, linkMerge=link_merge, valueFrom=value_from + ) == expected_type + + +def test_lifting(): + # check that lifting the types of the process outputs to the workflow step + # fails if the step 'out' doesn't match. + factory = cwltool.factory.Factory() + with pytest.raises(schema_salad.validate.ValidationException): + echo = factory.make(get_data("tests/test_bad_outputs_wf.cwl")) + assert echo(inp="foo") == {"out": "foo\n"} + + +def test_malformed_outputs(): + # check that tool validation fails if one of the outputs is not a valid CWL type + factory = cwltool.factory.Factory() + with pytest.raises(schema_salad.validate.ValidationException): + factory.make(get_data("tests/wf/malformed_outputs.cwl"))() + + +def test_separate_without_prefix(): + # check that setting 'separate = false' on an inputBinding without prefix fails the workflow + factory = cwltool.factory.Factory() + with pytest.raises(WorkflowException): + factory.make(get_data("tests/wf/separate_without_prefix.cwl"))() + + +def test_static_checker(): + # check that the static checker raises exception when a source type + # mismatches its sink type. + factory = cwltool.factory.Factory() + + with pytest.raises(schema_salad.validate.ValidationException): + factory.make(get_data("tests/checker_wf/broken-wf.cwl")) + + with pytest.raises(schema_salad.validate.ValidationException): + factory.make(get_data("tests/checker_wf/broken-wf2.cwl")) + + with pytest.raises(schema_salad.validate.ValidationException): + factory.make(get_data("tests/checker_wf/broken-wf3.cwl")) + + +def test_var_spool_cwl_checker1(): + """Confirm that references to /var/spool/cwl are caught.""" + stream = StringIO() + streamhandler = logging.StreamHandler(stream) + _logger = logging.getLogger("cwltool") + _logger.addHandler(streamhandler) + + factory = cwltool.factory.Factory() + try: + factory.make(get_data("tests/non_portable.cwl")) + assert "non_portable.cwl:18:4: Non-portable reference to /var/spool/cwl detected" in stream.getvalue() + finally: + _logger.removeHandler(streamhandler) + + +def test_var_spool_cwl_checker2(): + """Confirm that references to /var/spool/cwl are caught.""" + stream = StringIO() + streamhandler = logging.StreamHandler(stream) + _logger = logging.getLogger("cwltool") + _logger.addHandler(streamhandler) + + factory = cwltool.factory.Factory() + try: + factory.make(get_data("tests/non_portable2.cwl")) + assert "non_portable2.cwl:19:4: Non-portable reference to /var/spool/cwl detected" in stream.getvalue() + finally: + _logger.removeHandler(streamhandler) + + +def test_var_spool_cwl_checker3(): + """Confirm that references to /var/spool/cwl are caught.""" + stream = StringIO() + streamhandler = logging.StreamHandler(stream) + _logger = logging.getLogger("cwltool") + _logger.addHandler(streamhandler) + + factory = cwltool.factory.Factory() + try: + factory.make(get_data("tests/portable.cwl")) + assert "Non-portable reference to /var/spool/cwl detected" not in stream.getvalue() + finally: + _logger.removeHandler(streamhandler) + + +def test_print_dot(): + assert main(["--print-dot", get_data('tests/wf/revsort.cwl')]) == 0 + +test_factors = [(""), ("--parallel"), ("--debug"), ("--parallel --debug")] + +@pytest.mark.parametrize("factor", test_factors) +def test_js_console_cmd_line_tool(factor): + for test_file in ("js_output.cwl", "js_output_workflow.cwl"): + commands = factor.split() + commands.extend(["--js-console", "--no-container", get_data("tests/wf/" + test_file)]) + error_code, _, stderr = get_main_output(commands) + + assert "[log] Log message" in stderr + assert "[err] Error message" in stderr + + assert error_code == 0, stderr + +@pytest.mark.parametrize("factor", test_factors) +def test_no_js_console(factor): + for test_file in ("js_output.cwl", "js_output_workflow.cwl"): + commands = factor.split() + commands.extend(["--no-container", get_data("tests/wf/" + test_file)]) + _, _, stderr = get_main_output(commands) + + assert "[log] Log message" not in stderr + assert "[err] Error message" not in stderr + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_cid_file_dir(tmpdir, factor): + test_file = "cache_test_workflow.cwl" + cwd = tmpdir.chdir() + commands = factor.split() + commands.extend(["--cidfile-dir", str(tmpdir), get_data("tests/wf/" + test_file)]) + error_code, stdout, stderr = get_main_output(commands) + assert "completed success" in stderr + assert error_code == 0 + cidfiles_count = sum(1 for _ in tmpdir.visit(fil="*")) + assert cidfiles_count == 2 + cwd.chdir() + tmpdir.remove(ignore_errors=True) + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_cid_file_dir_arg_is_file_instead_of_dir(tmpdir, factor): + test_file = "cache_test_workflow.cwl" + bad_cidfile_dir = Text(tmpdir.ensure("cidfile-dir-actually-a-file")) + commands = factor.split() + commands.extend(["--cidfile-dir", bad_cidfile_dir, + get_data("tests/wf/" + test_file)]) + error_code, _, stderr = get_main_output(commands) + assert "is not a directory, please check it first" in stderr, stderr + assert error_code == 2 or error_code == 1, stderr + tmpdir.remove(ignore_errors=True) + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_cid_file_non_existing_dir(tmpdir, factor): + test_file = "cache_test_workflow.cwl" + bad_cidfile_dir = Text(tmpdir.join("cidfile-dir-badpath")) + commands = factor.split() + commands.extend(['--record-container-id',"--cidfile-dir", bad_cidfile_dir, + get_data("tests/wf/" + test_file)]) + error_code, _, stderr = get_main_output(commands) + assert "directory doesn't exist, please create it first" in stderr, stderr + assert error_code == 2 or error_code == 1, stderr + tmpdir.remove(ignore_errors=True) + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_cid_file_w_prefix(tmpdir, factor): + test_file = "cache_test_workflow.cwl" + cwd = tmpdir.chdir() + try: + commands = factor.split() + commands.extend(['--record-container-id', '--cidfile-prefix=pytestcid', + get_data("tests/wf/" + test_file)]) + error_code, stdout, stderr = get_main_output(commands) + finally: + listing = tmpdir.listdir() + cwd.chdir() + cidfiles_count = sum(1 for _ in tmpdir.visit(fil="pytestcid*")) + tmpdir.remove(ignore_errors=True) + assert "completed success" in stderr + assert error_code == 0 + assert cidfiles_count == 2, '{}/n{}'.format(listing, stderr) + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_secondary_files_v1_1(factor): + test_file = "secondary-files.cwl" + test_job_file = "secondary-files-job.yml" + try: + old_umask = os.umask(stat.S_IWOTH) # test run with umask 002 + commands = factor.split() + commands.extend(["--enable-dev", + get_data(os.path.join("tests", test_file)), + get_data(os.path.join("tests", test_job_file))]) + error_code, _, stderr = get_main_output(commands) + finally: + assert stat.S_IMODE(os.stat('lsout').st_mode) == 436 # 664 in octal, '-rw-rw-r--' + os.umask(old_umask) # revert back to original umask + assert "completed success" in stderr + assert error_code == 0 + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_secondary_files_v1_0(factor): + test_file = "secondary-files-string-v1.cwl" + test_job_file = "secondary-files-job.yml" + try: + old_umask = os.umask(stat.S_IWOTH) # test run with umask 002 + commands = factor.split() + commands.extend([ + get_data(os.path.join("tests", test_file)), + get_data(os.path.join("tests", test_job_file)) + ]) + error_code, _, stderr = get_main_output(commands) + finally: + assert stat.S_IMODE(os.stat('lsout').st_mode) == 436 # 664 in octal, '-rw-rw-r--' + os.umask(old_umask) # revert back to original umask + assert "completed success" in stderr + assert error_code == 0 + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_wf_without_container(tmpdir, factor): + test_file = "hello-workflow.cwl" + with temp_dir("cwltool_cache") as cache_dir: + commands = factor.split() + commands.extend(["--cachedir", cache_dir, "--outdir", str(tmpdir), + get_data("tests/wf/" + test_file), + "--usermessage", + "hello"]) + error_code, _, stderr = get_main_output(commands) + + assert "completed success" in stderr + assert error_code == 0 + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_issue_740_fixed(factor): + test_file = "cache_test_workflow.cwl" + with temp_dir("cwltool_cache") as cache_dir: + commands = factor.split() + commands.extend(["--cachedir", cache_dir, get_data("tests/wf/" + test_file)]) + error_code, _, stderr = get_main_output(commands) + + assert "completed success" in stderr + assert error_code == 0 + + commands = factor.split() + commands.extend(["--cachedir", cache_dir, get_data("tests/wf/" + test_file)]) + error_code, _, stderr = get_main_output(commands) + + assert "Output of job will be cached in" not in stderr + assert error_code == 0, stderr + + +@needs_docker +def test_compute_checksum(): + runtime_context = RuntimeContext() + runtime_context.compute_checksum = True + runtime_context.use_container = onWindows() + factory = cwltool.factory.Factory(runtime_context=runtime_context) + echo = factory.make(get_data("tests/wf/cat-tool.cwl")) + output = echo( + file1={"class": "File", + "location": get_data("tests/wf/whale.txt")}, + reverse=False) + assert output['output']["checksum"] == "sha1$327fc7aedf4f6b69a42a7c8b808dc5a7aff61376" + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_no_compute_chcksum(tmpdir, factor): + test_file = "tests/wf/wc-tool.cwl" + job_file = "tests/wf/wc-job.json" + commands = factor.split() + commands.extend(["--no-compute-checksum", "--outdir", str(tmpdir), + get_data(test_file), get_data(job_file)]) + error_code, stdout, stderr = get_main_output(commands) + assert "completed success" in stderr + assert error_code == 0 + assert "checksum" not in stdout + + +@pytest.mark.parametrize("factor", test_factors) +def test_bad_userspace_runtime(factor): + test_file = "tests/wf/wc-tool.cwl" + job_file = "tests/wf/wc-job.json" + commands = factor.split() + commands.extend([ + "--user-space-docker-cmd=quaquioN", "--default-container=debian", + get_data(test_file), get_data(job_file)]) + error_code, stdout, stderr = get_main_output(commands) + assert "or quaquioN is missing or broken" in stderr, stderr + assert error_code == 1 + +@windows_needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_bad_basecommand(factor): + test_file = "tests/wf/missing-tool.cwl" + commands = factor.split() + commands.extend([get_data(test_file)]) + error_code, stdout, stderr = get_main_output(commands) + assert "'neenooGo' not found" in stderr, stderr + assert error_code == 1 + + +@needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_bad_basecommand_docker(factor): + test_file = "tests/wf/missing-tool.cwl" + commands = factor.split() + commands.extend( + ["--debug", "--default-container", "debian", get_data(test_file)]) + error_code, stdout, stderr = get_main_output(commands) + assert "permanentFail" in stderr, stderr + assert error_code == 1 + +@pytest.mark.parametrize("factor", test_factors) +def test_v1_0_position_expression(factor): + test_file = "tests/echo-position-expr.cwl" + test_job = "tests/echo-position-expr-job.yml" + commands = factor.split() + commands.extend( + ['--debug', get_data(test_file), get_data(test_job)]) + error_code, stdout, stderr = get_main_output(commands) + assert "is not int" in stderr, stderr + assert error_code == 1 + + +@windows_needs_docker +@pytest.mark.parametrize("factor", test_factors) +def test_optional_numeric_output_0(factor): + test_file = "tests/wf/optional-numerical-output-0.cwl" + commands = factor.split() + commands.extend([get_data(test_file)]) + error_code, stdout, stderr = get_main_output(commands) + + assert "completed success" in stderr + assert error_code == 0 + assert json.loads(stdout)['out'] == 0 + +@pytest.mark.parametrize("factor", test_factors) +@windows_needs_docker +def test_env_filtering(factor): + test_file = "tests/env.cwl" + commands = factor.split() + commands.extend([get_data(test_file)]) + error_code, stdout, stderr = get_main_output(commands) + + process = subprocess.Popen(["sh", "-c", r"""getTrueShellExeName() { + local trueExe nextTarget 2>/dev/null + trueExe=$(ps -o comm= $$) || return 1 + [ "${trueExe#-}" = "$trueExe" ] || trueExe=${trueExe#-} + [ "${trueExe#/}" != "$trueExe" ] || trueExe=$([ -n "$ZSH_VERSION" ] && which -p "$trueExe" || which "$trueExe") + while nextTarget=$(readlink "$trueExe"); do trueExe=$nextTarget; done + printf '%s\n' "$(basename "$trueExe")" +} ; getTrueShellExeName"""], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=None) + sh_name, sh_name_err = process.communicate() + sh_name = sh_name.decode('utf-8').strip() + + assert "completed success" in stderr, (error_code, stdout, stderr) + assert error_code == 0, (error_code, stdout, stderr) + if onWindows(): + target = 5 + elif sh_name == "dash": + target = 4 + else: # bash adds "SHLVL" and "_" environment variables + target = 6 + result = json.loads(stdout)['env_count'] + details = '' + if result != target: + _, details, _ = get_main_output(["--quiet", get_data("tests/env2.cwl")]) + print(sh_name) + print(sh_name_err) + print(details) + assert result == target, (error_code, sh_name, sh_name_err, details, stdout, stderr) + +@windows_needs_docker +def test_v1_0_arg_empty_prefix_separate_false(): + test_file = "tests/arg-empty-prefix-separate-false.cwl" + error_code, stdout, stderr = get_main_output( + ['--debug', get_data(test_file), "--echo"]) + assert "completed success" in stderr + assert error_code == 0