diff --git a/cwltool/builder.py b/cwltool/builder.py index 4fb91efdc..9a89e903c 100644 --- a/cwltool/builder.py +++ b/cwltool/builder.py @@ -217,6 +217,9 @@ def generate_arg(self, binding): # type: (Dict[Text,Any]) -> List[Text] prefix = binding.get("prefix") sep = binding.get("separate", True) + if prefix is None and not sep: + with SourceLine(binding, "separate", WorkflowException, _logger.isEnabledFor(logging.DEBUG)): + raise WorkflowException("'separate' option can not be specified without prefix") l = [] # type: List[Dict[Text,Text]] if isinstance(value, list): diff --git a/cwltool/load_tool.py b/cwltool/load_tool.py index a1c6dc53c..e48c19ad6 100644 --- a/cwltool/load_tool.py +++ b/cwltool/load_tool.py @@ -20,7 +20,7 @@ from avro.schema import Names from ruamel.yaml.comments import CommentedMap, CommentedSeq from schema_salad.ref_resolver import ContextType, Fetcher, Loader, file_uri -from schema_salad.sourceline import cmap +from schema_salad.sourceline import cmap, SourceLine from schema_salad.validate import ValidationException from . import process, update @@ -124,6 +124,9 @@ def _convert_stdstreams_to_files(workflowobj): if isinstance(workflowobj, dict): if workflowobj.get('class') == 'CommandLineTool': for out in workflowobj.get('outputs', []): + if type(out) is not CommentedMap: + with SourceLine(workflowobj, "outputs", ValidationException, _logger.isEnabledFor(logging.DEBUG)): + raise ValidationException("Output '%s' is not a valid OutputParameter." % out) for streamtype in ['stdout', 'stderr']: if out.get('type') == streamtype: if 'outputBinding' in out: diff --git a/tests/test_examples.py b/tests/test_examples.py index b63e19f92..36da186b8 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -7,6 +7,7 @@ from io import StringIO +from cwltool.errors import WorkflowException from cwltool.utils import onWindows try: @@ -525,6 +526,20 @@ def test_lifting(self): echo = f.make(get_data("tests/test_bad_outputs_wf.cwl")) self.assertEqual(echo(inp="foo"), {"out": "foo\n"}) + def test_malformed_outputs(self): + # check that tool validation fails if one of the outputs is not a valid CWL type + f = cwltool.factory.Factory() + with self.assertRaises(schema_salad.validate.ValidationException): + echo = f.make(get_data("tests/wf/malformed_outputs.cwl")) + echo() + + def test_separate_without_prefix(self): + # check that setting 'separate = false' on an inputBinding without prefix fails the workflow + with self.assertRaises(WorkflowException): + f = cwltool.factory.Factory() + echo = f.make(get_data("tests/wf/separate_without_prefix.cwl")) + echo() + def test_checker(self): # check that the static checker raises exception when a source type diff --git a/tests/wf/malformed_outputs.cwl b/tests/wf/malformed_outputs.cwl new file mode 100644 index 000000000..0fea9fb21 --- /dev/null +++ b/tests/wf/malformed_outputs.cwl @@ -0,0 +1,8 @@ +cwlVersion: v1.0 +class: CommandLineTool +baseCommand: echo + +inputs: + [] +outputs: + - diff --git a/tests/wf/separate_without_prefix.cwl b/tests/wf/separate_without_prefix.cwl new file mode 100644 index 000000000..78163ddd6 --- /dev/null +++ b/tests/wf/separate_without_prefix.cwl @@ -0,0 +1,22 @@ +cwlVersion: v1.0 +class: CommandLineTool +baseCommand: echo + +inputs: + src: + type: string + default: + string + inputBinding: + position: 1 + separate: false + +stdout: output.txt + +outputs: + output: + type: string + outputBinding: + glob: output.txt + loadContents: true + outputEval: $(self[0].contents)