diff --git a/cwltool/command_line_tool.py b/cwltool/command_line_tool.py index 54913b47f..a9d5e57e2 100644 --- a/cwltool/command_line_tool.py +++ b/cwltool/command_line_tool.py @@ -26,7 +26,7 @@ from mypy_extensions import mypyc_attr from ruamel.yaml.comments import CommentedMap, CommentedSeq -from schema_salad.avro.schema import Schema +from schema_salad.avro.schema import RecordSchema from schema_salad.exceptions import ValidationException from schema_salad.ref_resolver import file_uri, uri_file_path from schema_salad.sourceline import SourceLine @@ -1216,6 +1216,7 @@ def collect_output_ports( if cwl_version != "v1.0": builder.resources["exitCode"] = rcode try: + expected_schema = cast(RecordSchema, self.names.get_name("outputs_record_schema", None)) fs_access = builder.make_fs_access(outdir) custom_output = fs_access.join(outdir, "cwl.output.json") if fs_access.exists(custom_output): @@ -1227,6 +1228,20 @@ def collect_output_ports( custom_output, json_dumps(ret, indent=4), ) + if ORDERED_VERSIONS.index(cast(str, cwl_version)) >= ORDERED_VERSIONS.index( + "v1.3.0-dev1" + ): + for k in list(ret): + found = False + for field in expected_schema.fields: + if k == field.name: + found = True + break + if not found: + _logger.warning( + f"Discarded undeclared output named {k!r} from {custom_output}." + ) + ret.pop(k) else: for i, port in enumerate(ports): with SourceLine( @@ -1257,7 +1272,6 @@ def collect_output_ports( if compute_checksum: adjustFileObjs(ret, partial(compute_checksums, fs_access)) - expected_schema = cast(Schema, self.names.get_name("outputs_record_schema", None)) validate_ex( expected_schema, ret, diff --git a/tests/test-cwl-out-v1.0.cwl b/tests/test-cwl-out-v1.0.cwl new file mode 100644 index 000000000..f3a2c5f51 --- /dev/null +++ b/tests/test-cwl-out-v1.0.cwl @@ -0,0 +1,15 @@ +class: CommandLineTool +cwlVersion: v1.0 + +inputs: [] + +baseCommand: sh + +arguments: + - -c + - | + echo '{"foo": 5 }' + +stdout: cwl.output.json + +outputs: {} \ No newline at end of file diff --git a/tests/test-cwl-out-v1.1.cwl b/tests/test-cwl-out-v1.1.cwl new file mode 100644 index 000000000..20447ed0e --- /dev/null +++ b/tests/test-cwl-out-v1.1.cwl @@ -0,0 +1,15 @@ +class: CommandLineTool +cwlVersion: v1.1 + +inputs: [] + +baseCommand: sh + +arguments: + - -c + - | + echo '{"foo": 5 }' + +stdout: cwl.output.json + +outputs: {} \ No newline at end of file diff --git a/tests/test-cwl-out-v1.2.cwl b/tests/test-cwl-out-v1.2.cwl new file mode 100644 index 000000000..95acf4940 --- /dev/null +++ b/tests/test-cwl-out-v1.2.cwl @@ -0,0 +1,15 @@ +class: CommandLineTool +cwlVersion: v1.2 + +inputs: [] + +baseCommand: sh + +arguments: + - -c + - | + echo '{"foo": 5 }' + +stdout: cwl.output.json + +outputs: {} \ No newline at end of file diff --git a/tests/test-cwl-out-v1.3.cwl b/tests/test-cwl-out-v1.3.cwl new file mode 100644 index 000000000..b67ea780c --- /dev/null +++ b/tests/test-cwl-out-v1.3.cwl @@ -0,0 +1,15 @@ +class: CommandLineTool +cwlVersion: v1.3.0-dev1 + +inputs: [] + +baseCommand: sh + +arguments: + - -c + - | + echo '{"foo": 5 }' + +stdout: cwl.output.json + +outputs: {} diff --git a/tests/test_cwl_output_json.py b/tests/test_cwl_output_json.py new file mode 100644 index 000000000..ce2787aa8 --- /dev/null +++ b/tests/test_cwl_output_json.py @@ -0,0 +1,34 @@ +import json + +from .util import get_data, get_main_output + + +def test_cwl_output_json_missing_field_v1_0() -> None: + """Confirm that unknown outputs are propagated from cwl.output.json in CWL v1.0.""" + err_code, stdout, _ = get_main_output([get_data("tests/test-cwl-out-v1.0.cwl")]) + assert err_code == 0 + assert "foo" in json.loads(stdout) + + +def test_cwl_output_json_missing_field_v1_1() -> None: + """Confirm that unknown outputs are propagated from cwl.output.json in CWL v1.1.""" + err_code, stdout, _ = get_main_output([get_data("tests/test-cwl-out-v1.1.cwl")]) + assert err_code == 0 + assert "foo" in json.loads(stdout) + + +def test_cwl_output_json_missing_field_v1_2() -> None: + """Confirm that unknown outputs are propagated from cwl.output.json in CWL v1.2.""" + err_code, stdout, _ = get_main_output([get_data("tests/test-cwl-out-v1.2.cwl")]) + assert err_code == 0 + assert "foo" in json.loads(stdout) + + +def test_cwl_output_json_missing_field_v1_3() -> None: + """Confirm that unknown outputs are propagated from cwl.output.json in CWL v1.3.""" + err_code, stdout, stderr = get_main_output( + ["--enable-dev", get_data("tests/test-cwl-out-v1.3.cwl")] + ) + assert err_code == 0 + assert "foo" not in json.loads(stdout) + assert "Discarded undeclared output named 'foo' from" in stderr